diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt index 69afb1c943a..f76a372aaa3 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt @@ -1,2 +1,24 @@ Comparing source compatibility of opentelemetry-sdk-testing-1.68.0-SNAPSHOT.jar against opentelemetry-sdk-testing-1.67.0.jar -No changes. \ No newline at end of file +*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.testing.assertj.MetricAssert (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasDoubleGaugePointsSatisfying(java.util.function.Consumer[]) + +++ NEW ANNOTATION: java.lang.SafeVarargs + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasDoubleGaugePointsSatisfying(java.lang.Iterable>) + +++ NEW METHOD: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasDoubleSumPointsSatisfying(java.util.function.Consumer[]) + +++ NEW ANNOTATION: java.lang.SafeVarargs + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasDoubleSumPointsSatisfying(java.lang.Iterable>) + +++ NEW METHOD: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasExponentialHistogramPointsSatisfying(java.util.function.Consumer[]) + +++ NEW ANNOTATION: java.lang.SafeVarargs + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasExponentialHistogramPointsSatisfying(java.lang.Iterable>) + +++ NEW METHOD: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasHistogramPointsSatisfying(java.util.function.Consumer[]) + +++ NEW ANNOTATION: java.lang.SafeVarargs + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasHistogramPointsSatisfying(java.lang.Iterable>) + +++ NEW METHOD: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasLongGaugePointsSatisfying(java.util.function.Consumer[]) + +++ NEW ANNOTATION: java.lang.SafeVarargs + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasLongGaugePointsSatisfying(java.lang.Iterable>) + +++ NEW METHOD: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasLongSumPointsSatisfying(java.util.function.Consumer[]) + +++ NEW ANNOTATION: java.lang.SafeVarargs + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasLongSumPointsSatisfying(java.lang.Iterable>) + +++ NEW METHOD: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasSummaryPointsSatisfying(java.util.function.Consumer[]) + +++ NEW ANNOTATION: java.lang.SafeVarargs + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.MetricAssert hasSummaryPointsSatisfying(java.lang.Iterable>) diff --git a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/MetricAssert.java b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/MetricAssert.java index 5df6a7bf92a..9b4e3cc9dbc 100644 --- a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/MetricAssert.java +++ b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/MetricAssert.java @@ -122,6 +122,26 @@ public MetricAssert hasDoubleGaugeSatisfying(Consumer asserti return this; } + /** + * Asserts this {@link MetricData} is a double gauge with points matching all of the given + * assertions and no more, in any order. + */ + @SafeVarargs + @SuppressWarnings("varargs") + public final MetricAssert hasDoubleGaugePointsSatisfying( + Consumer... assertions) { + return hasDoubleGaugeSatisfying(gauge -> gauge.hasPointsSatisfying(assertions)); + } + + /** + * Asserts this {@link MetricData} is a double gauge with points matching all of the given + * assertions and no more, in any order. + */ + public MetricAssert hasDoubleGaugePointsSatisfying( + Iterable> assertions) { + return hasDoubleGaugeSatisfying(gauge -> gauge.hasPointsSatisfying(assertions)); + } + /** * Asserts this {@link MetricData} is a {@code LongGauge} that satisfies the provided assertion. */ @@ -139,6 +159,25 @@ public MetricAssert hasLongGaugeSatisfying(Consumer assertion) return this; } + /** + * Asserts this {@link MetricData} is a long gauge with points matching all of the given + * assertions and no more, in any order. + */ + @SafeVarargs + @SuppressWarnings("varargs") + public final MetricAssert hasLongGaugePointsSatisfying(Consumer... assertions) { + return hasLongGaugeSatisfying(gauge -> gauge.hasPointsSatisfying(assertions)); + } + + /** + * Asserts this {@link MetricData} is a long gauge with points matching all of the given + * assertions and no more, in any order. + */ + public MetricAssert hasLongGaugePointsSatisfying( + Iterable> assertions) { + return hasLongGaugeSatisfying(gauge -> gauge.hasPointsSatisfying(assertions)); + } + /** Asserts this {@link MetricData} is a double sum that satisfies the provided assertion. */ public MetricAssert hasDoubleSumSatisfying(Consumer assertion) { isNotNull(); @@ -154,6 +193,26 @@ public MetricAssert hasDoubleSumSatisfying(Consumer assertion) return this; } + /** + * Asserts this {@link MetricData} is a double sum with points matching all of the given + * assertions and no more, in any order. + */ + @SafeVarargs + @SuppressWarnings("varargs") + public final MetricAssert hasDoubleSumPointsSatisfying( + Consumer... assertions) { + return hasDoubleSumSatisfying(sum -> sum.hasPointsSatisfying(assertions)); + } + + /** + * Asserts this {@link MetricData} is a double sum with points matching all of the given + * assertions and no more, in any order. + */ + public MetricAssert hasDoubleSumPointsSatisfying( + Iterable> assertions) { + return hasDoubleSumSatisfying(sum -> sum.hasPointsSatisfying(assertions)); + } + /** Asserts this {@link MetricData} is a long sum that satisfies the provided assertion. */ public MetricAssert hasLongSumSatisfying(Consumer assertion) { isNotNull(); @@ -169,6 +228,25 @@ public MetricAssert hasLongSumSatisfying(Consumer assertion) { return this; } + /** + * Asserts this {@link MetricData} is a long sum with points matching all of the given assertions + * and no more, in any order. + */ + @SafeVarargs + @SuppressWarnings("varargs") + public final MetricAssert hasLongSumPointsSatisfying(Consumer... assertions) { + return hasLongSumSatisfying(sum -> sum.hasPointsSatisfying(assertions)); + } + + /** + * Asserts this {@link MetricData} is a long sum with points matching all of the given assertions + * and no more, in any order. + */ + public MetricAssert hasLongSumPointsSatisfying( + Iterable> assertions) { + return hasLongSumSatisfying(sum -> sum.hasPointsSatisfying(assertions)); + } + /** Asserts this {@link MetricData} is a histogram that satisfies the provided assertion. */ public MetricAssert hasHistogramSatisfying(Consumer assertion) { isNotNull(); @@ -184,6 +262,26 @@ public MetricAssert hasHistogramSatisfying(Consumer assertion) return this; } + /** + * Asserts this {@link MetricData} is a histogram with points matching all of the given assertions + * and no more, in any order. + */ + @SafeVarargs + @SuppressWarnings("varargs") + public final MetricAssert hasHistogramPointsSatisfying( + Consumer... assertions) { + return hasHistogramSatisfying(histogram -> histogram.hasPointsSatisfying(assertions)); + } + + /** + * Asserts this {@link MetricData} is a histogram with points matching all of the given assertions + * and no more, in any order. + */ + public MetricAssert hasHistogramPointsSatisfying( + Iterable> assertions) { + return hasHistogramSatisfying(histogram -> histogram.hasPointsSatisfying(assertions)); + } + /** * Asserts this {@link MetricData} is an exponential histogram that satisfies the provided * assertion. @@ -205,6 +303,28 @@ public MetricAssert hasExponentialHistogramSatisfying( return this; } + /** + * Asserts this {@link MetricData} is an exponential histogram with points matching all of the + * given assertions and no more, in any order. + */ + @SafeVarargs + @SuppressWarnings("varargs") + public final MetricAssert hasExponentialHistogramPointsSatisfying( + Consumer... assertions) { + return hasExponentialHistogramSatisfying( + histogram -> histogram.hasPointsSatisfying(assertions)); + } + + /** + * Asserts this {@link MetricData} is an exponential histogram with points matching all of the + * given assertions and no more, in any order. + */ + public MetricAssert hasExponentialHistogramPointsSatisfying( + Iterable> assertions) { + return hasExponentialHistogramSatisfying( + histogram -> histogram.hasPointsSatisfying(assertions)); + } + /** Asserts this {@link MetricData} is a summary that satisfies the provided assertion. */ public MetricAssert hasSummarySatisfying(Consumer assertion) { isNotNull(); @@ -219,4 +339,23 @@ public MetricAssert hasSummarySatisfying(Consumer assertion) { assertion.accept(new SummaryAssert(actual.getSummaryData())); return this; } + + /** + * Asserts this {@link MetricData} is a summary with points matching all of the given assertions + * and no more, in any order. + */ + @SafeVarargs + @SuppressWarnings("varargs") + public final MetricAssert hasSummaryPointsSatisfying(Consumer... assertions) { + return hasSummarySatisfying(summary -> summary.hasPointsSatisfying(assertions)); + } + + /** + * Asserts this {@link MetricData} is a summary with points matching all of the given assertions + * and no more, in any order. + */ + public MetricAssert hasSummaryPointsSatisfying( + Iterable> assertions) { + return hasSummarySatisfying(summary -> summary.hasPointsSatisfying(assertions)); + } } diff --git a/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/MetricAssertionsTest.java b/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/MetricAssertionsTest.java index b0a1ac3e240..09fb4b2409f 100644 --- a/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/MetricAssertionsTest.java +++ b/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/MetricAssertionsTest.java @@ -30,6 +30,7 @@ import io.opentelemetry.sdk.metrics.data.LongExemplarData; import io.opentelemetry.sdk.metrics.data.LongPointData; import io.opentelemetry.sdk.metrics.data.MetricData; +import io.opentelemetry.sdk.metrics.data.MetricDataType; import io.opentelemetry.sdk.metrics.data.SummaryPointData; import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoubleExemplarData; import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoublePointData; @@ -50,7 +51,12 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; // We always assert the contents of lists out of order to verify that assertions behave that way. class MetricAssertionsTest { @@ -304,6 +310,239 @@ class MetricAssertionsTest { // Points Collections.singletonList(SUMMARY_POINT_DATA))); + @Test + void doubleGaugePointsSatisfying() { + assertThat(DOUBLE_GAUGE_METRIC) + .hasName("gauge") + .hasDoubleGaugePointsSatisfying( + point -> point.hasValue(3.0).hasStartEpochNanos(3), + point -> point.hasValue(3.0).hasStartEpochNanos(1)) + .hasDoubleGaugePointsSatisfying( + Arrays.asList( + point -> point.hasValue(3.0).hasStartEpochNanos(3), + point -> point.hasValue(3.0).hasStartEpochNanos(1))) + .hasUnit("1"); + } + + @Test + void longGaugePointsSatisfying() { + assertThat(LONG_GAUGE_METRIC) + .hasName("gauge") + .hasLongGaugePointsSatisfying( + point -> point.hasValue(Long.MAX_VALUE), point -> point.hasValue(1)) + .hasLongGaugePointsSatisfying( + Arrays.asList(point -> point.hasValue(Long.MAX_VALUE), point -> point.hasValue(1))) + .hasUnit("1"); + } + + @Test + void doubleSumPointsSatisfying() { + assertThat(DOUBLE_SUM_METRIC) + .hasName("sum") + .hasDoubleSumPointsSatisfying( + point -> point.hasValue(3.0).hasStartEpochNanos(3), + point -> point.hasValue(3.0).hasStartEpochNanos(1)) + .hasDoubleSumPointsSatisfying( + Arrays.asList( + point -> point.hasValue(3.0).hasStartEpochNanos(3), + point -> point.hasValue(3.0).hasStartEpochNanos(1))) + .hasDoubleSumSatisfying(sum -> sum.isMonotonic().isCumulative()); + } + + @Test + void longSumPointsSatisfying() { + assertThat(LONG_SUM_METRIC) + .hasName("sum") + .hasLongSumPointsSatisfying( + point -> point.hasValue(Long.MAX_VALUE), point -> point.hasValue(1)) + .hasLongSumPointsSatisfying( + Arrays.asList(point -> point.hasValue(Long.MAX_VALUE), point -> point.hasValue(1))) + .hasLongSumSatisfying(sum -> sum.isMonotonic().isCumulative()); + } + + @Test + void histogramPointsSatisfying() { + MetricAssert assertion = assertThat(HISTOGRAM_METRIC).hasName("histogram"); + assertThat( + assertion + .hasHistogramPointsSatisfying(point -> point.hasCount(3).hasSum(15)) + .hasHistogramSatisfying(HistogramAssert::isCumulative)) + .isSameAs(assertion); + assertThat( + assertion + .hasHistogramPointsSatisfying( + Collections.singletonList(point -> point.hasCount(3).hasSum(15))) + .hasUnit("1")) + .isSameAs(assertion); + } + + @Test + void exponentialHistogramPointsSatisfying() { + assertThat(EXPONENTIAL_HISTOGRAM_METRIC) + .hasName("exponential_histogram") + .hasExponentialHistogramPointsSatisfying(point -> point.hasCount(4).hasSum(10).hasScale(1)) + .hasExponentialHistogramPointsSatisfying( + Collections.singletonList(point -> point.hasCount(4).hasSum(10).hasScale(1))) + .hasExponentialHistogramSatisfying(ExponentialHistogramAssert::isCumulative); + } + + @Test + void summaryPointsSatisfying() { + assertThat(SUMMARY_METRIC) + .hasName("summary") + .hasSummaryPointsSatisfying(point -> point.hasCount(1).hasSum(2)) + .hasSummaryPointsSatisfying(Collections.singletonList(point -> point.hasCount(1).hasSum(2))) + .hasUnit("1"); + } + + @ParameterizedTest + @MethodSource("pointShortcuts") + void pointShortcutsFailure(MetricData metric, Consumer assertion) { + assertThatThrownBy(() -> assertion.accept(assertThat((MetricData) null))) + .isInstanceOf(AssertionError.class) + .hasMessageContaining("not to be null"); + + MetricData wrongType = + metric.getType() == MetricDataType.HISTOGRAM ? SUMMARY_METRIC : HISTOGRAM_METRIC; + assertThatThrownBy(() -> assertion.accept(assertThat(wrongType))) + .isInstanceOf(AssertionError.class) + .hasMessage( + "Expected MetricData to have type <%s> but found <%s>", + metric.getType(), wrongType.getType()); + + assertThatThrownBy(() -> assertion.accept(assertThat(metric))) + .isInstanceOf(AssertionError.class); + } + + static Stream pointShortcuts() { + return Stream.of( + Arguments.argumentSet( + "double gauge varargs", + DOUBLE_GAUGE_METRIC, + (Consumer) MetricAssert::hasDoubleGaugePointsSatisfying), + Arguments.argumentSet( + "double gauge iterable", + DOUBLE_GAUGE_METRIC, + (Consumer) + metric -> metric.hasDoubleGaugePointsSatisfying(Collections.emptyList())), + Arguments.argumentSet( + "long gauge varargs", + LONG_GAUGE_METRIC, + (Consumer) MetricAssert::hasLongGaugePointsSatisfying), + Arguments.argumentSet( + "long gauge iterable", + LONG_GAUGE_METRIC, + (Consumer) + metric -> metric.hasLongGaugePointsSatisfying(Collections.emptyList())), + Arguments.argumentSet( + "double sum varargs", + DOUBLE_SUM_METRIC, + (Consumer) MetricAssert::hasDoubleSumPointsSatisfying), + Arguments.argumentSet( + "double sum iterable", + DOUBLE_SUM_METRIC, + (Consumer) + metric -> metric.hasDoubleSumPointsSatisfying(Collections.emptyList())), + Arguments.argumentSet( + "long sum varargs", + LONG_SUM_METRIC, + (Consumer) MetricAssert::hasLongSumPointsSatisfying), + Arguments.argumentSet( + "long sum iterable", + LONG_SUM_METRIC, + (Consumer) + metric -> metric.hasLongSumPointsSatisfying(Collections.emptyList())), + Arguments.argumentSet( + "histogram varargs", + HISTOGRAM_METRIC, + (Consumer) MetricAssert::hasHistogramPointsSatisfying), + Arguments.argumentSet( + "histogram iterable", + HISTOGRAM_METRIC, + (Consumer) + metric -> metric.hasHistogramPointsSatisfying(Collections.emptyList())), + Arguments.argumentSet( + "exponential histogram varargs", + EXPONENTIAL_HISTOGRAM_METRIC, + (Consumer) MetricAssert::hasExponentialHistogramPointsSatisfying), + Arguments.argumentSet( + "exponential histogram iterable", + EXPONENTIAL_HISTOGRAM_METRIC, + (Consumer) + metric -> metric.hasExponentialHistogramPointsSatisfying(Collections.emptyList())), + Arguments.argumentSet( + "summary varargs", + SUMMARY_METRIC, + (Consumer) MetricAssert::hasSummaryPointsSatisfying), + Arguments.argumentSet( + "summary iterable", + SUMMARY_METRIC, + (Consumer) + metric -> metric.hasSummaryPointsSatisfying(Collections.emptyList()))); + } + + @Test + void pointShortcutsRejectMismatchedPoints() { + assertThatThrownBy( + () -> + assertThat(HISTOGRAM_METRIC) + .hasHistogramPointsSatisfying(point -> point.hasCount(42))) + .isInstanceOf(AssertionError.class); + } + + @Test + void pointShortcutsRequireExactMatching() { + assertThatThrownBy( + () -> + assertThat(LONG_GAUGE_METRIC) + .hasLongGaugePointsSatisfying(point -> point.hasValue(1))) + .isInstanceOf(AssertionError.class); + assertThatThrownBy( + () -> + assertThat(LONG_GAUGE_METRIC) + .hasLongGaugePointsSatisfying( + point -> point.hasValue(Long.MAX_VALUE), + point -> point.hasValue(1), + point -> point.hasValue(1))) + .isInstanceOf(AssertionError.class); + assertThatThrownBy( + () -> + assertThat(LONG_GAUGE_METRIC) + .hasLongGaugePointsSatisfying( + point -> point.hasValue(1), point -> point.hasValue(1))) + .isInstanceOf(AssertionError.class); + } + + @Test + @SuppressWarnings("NullAway") + void pointShortcutsNullAssertions() { + assertThatThrownBy( + () -> + assertThat(HISTOGRAM_METRIC) + .hasHistogramPointsSatisfying((Consumer[]) null)) + .isInstanceOf(NullPointerException.class); + assertThatThrownBy( + () -> + assertThat(HISTOGRAM_METRIC) + .hasHistogramPointsSatisfying((Iterable>) null)) + .isInstanceOf(NullPointerException.class); + assertThatThrownBy( + () -> + assertThat(HISTOGRAM_METRIC) + .hasHistogramPointsSatisfying((Consumer) null)) + .isInstanceOf(NullPointerException.class); + assertThatThrownBy( + () -> + assertThat(SUMMARY_METRIC) + .hasHistogramPointsSatisfying((Consumer[]) null)) + .isInstanceOf(AssertionError.class); + assertThatThrownBy( + () -> + assertThat((MetricData) null) + .hasHistogramPointsSatisfying((Consumer[]) null)) + .isInstanceOf(AssertionError.class); + } + @Test @SuppressWarnings("Convert2MethodRef") void doubleGauge() {