From 3f2317fdac1f0bb704f26b468b5894ac64474cc0 Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Tue, 3 May 2022 11:25:47 +0300 Subject: [PATCH] Add hasSpansSatisfyingExactlyInAnyOrder (#4427) * Add hasSpansSatisfyingExactlyInAnyOrder * address review comment * address review comment --- .../opentelemetry-sdk-testing.txt | 5 ++ .../sdk/testing/assertj/TraceAssert.java | 25 ++++++++ .../testing/assertj/TraceAssertionsTest.java | 62 +++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt index a7b62271d3..66257c80ea 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt @@ -111,6 +111,11 @@ Comparing source compatibility of against +++ NEW METHOD: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.SummaryPointAssert hasValuesSatisfying(java.util.function.Consumer[]) +++ NEW ANNOTATION: java.lang.SafeVarargs +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.SummaryPointAssert hasValuesSatisfying(java.lang.Iterable) +*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.testing.assertj.TraceAssert (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.TraceAssert hasSpansSatisfyingExactlyInAnyOrder(java.util.function.Consumer[]) + +++ NEW ANNOTATION: java.lang.SafeVarargs + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.TraceAssert hasSpansSatisfyingExactlyInAnyOrder(java.lang.Iterable) +++ NEW CLASS: PUBLIC(+) FINAL(+) io.opentelemetry.sdk.testing.assertj.ValueAtQuantileAssert (not serializable) +++ CLASS FILE FORMAT VERSION: 52.0 <- n.a. +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.testing.assertj.ValueAtQuantileAssert hasQuantile(double) diff --git a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/TraceAssert.java b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/TraceAssert.java index 4e63a95f01..5f3da9db7f 100644 --- a/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/TraceAssert.java +++ b/sdk/testing/src/main/java/io/opentelemetry/sdk/testing/assertj/TraceAssert.java @@ -66,6 +66,31 @@ public final class TraceAssert return this; } + /** + * Asserts that the trace under assertion has the same number of spans as provided {@code + * assertions} and verifies that there is a combination of spans that satisfies specified {@link + * SpanDataAssert} {@code assertions} in the given order. This is a variation of {@link + * #hasSpansSatisfyingExactly(Consumer...)} where order does not matter. + */ + @SafeVarargs + @SuppressWarnings("varargs") + public final TraceAssert hasSpansSatisfyingExactlyInAnyOrder( + Consumer... assertions) { + return hasSpansSatisfyingExactlyInAnyOrder(Arrays.asList(assertions)); + } + + /** + * Asserts that the trace under assertion has the same number of spans as provided {@code + * assertions} and verifies that there is a combination of spans that satisfies specified {@link + * SpanDataAssert} {@code assertions} in the given order. This is a variation of {@link + * #hasSpansSatisfyingExactly(Iterable)} where order does not matter. + */ + public TraceAssert hasSpansSatisfyingExactlyInAnyOrder( + Iterable> assertions) { + Consumer[] spanDataAsserts = AssertUtil.toConsumers(assertions, SpanDataAssert::new); + return satisfiesExactlyInAnyOrder(spanDataAsserts); + } + /** * Returns the {@linkplain SpanData span} at the {@code index} within the trace. This can be * useful for asserting the parent of a span. diff --git a/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/TraceAssertionsTest.java b/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/TraceAssertionsTest.java index 95151e35f9..820d0d5896 100644 --- a/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/TraceAssertionsTest.java +++ b/sdk/testing/src/test/java/io/opentelemetry/sdk/testing/assertj/TraceAssertionsTest.java @@ -24,10 +24,13 @@ import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.testing.trace.TestSpanData; import io.opentelemetry.sdk.trace.data.EventData; import io.opentelemetry.sdk.trace.data.LinkData; +import io.opentelemetry.sdk.trace.data.SpanData; import io.opentelemetry.sdk.trace.data.StatusData; import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import java.time.Instant; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; @@ -496,4 +499,63 @@ class TraceAssertionsTest { satisfies(COINS, val -> val.containsExactly(0.01, 0.05, 0.1)))) .isInstanceOf(AssertionError.class); } + + private static TestSpanData buildTestSpan(String spanId, String spanName) { + return TestSpanData.builder() + .setResource(RESOURCE) + .setInstrumentationScopeInfo(INSTRUMENTATION_SCOPE_INFO) + .setName(spanName) + .setKind(SpanKind.CLIENT) + .setStartEpochNanos(100) + .setStatus(StatusData.ok()) + .setEndEpochNanos(200) + .setHasEnded(true) + .setSpanContext(SpanContext.create(TRACE_ID, spanId, TraceFlags.getSampled(), TRACE_STATE)) + .build(); + } + + @Test + void hasSpansSatisfyingExactly() { + Collection> traces = new ArrayList<>(); + traces.add(Arrays.asList(buildTestSpan(SPAN_ID1, "span1"), buildTestSpan(SPAN_ID2, "span2"))); + + // test asserting spans in exact oder + TracesAssert.assertThat(traces) + .hasTracesSatisfyingExactly( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasSpanId(SPAN_ID1), span -> span.hasSpanId(SPAN_ID2))); + // test asserting spans in wrong oder + assertThatThrownBy( + () -> + TracesAssert.assertThat(traces) + .hasTracesSatisfyingExactly( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasSpanId(SPAN_ID2), + span -> span.hasSpanId(SPAN_ID1)))) + .isInstanceOf(AssertionError.class); + + // test asserting spans in any order + TracesAssert.assertThat(traces) + .hasTracesSatisfyingExactly( + trace -> + trace.hasSpansSatisfyingExactlyInAnyOrder( + span -> span.hasSpanId(SPAN_ID1), span -> span.hasSpanId(SPAN_ID2))); + TracesAssert.assertThat(traces) + .hasTracesSatisfyingExactly( + trace -> + trace.hasSpansSatisfyingExactlyInAnyOrder( + span -> span.hasSpanId(SPAN_ID2), span -> span.hasSpanId(SPAN_ID1))); + // test not asserting all spans + assertThatThrownBy( + () -> + TracesAssert.assertThat(traces) + .hasTracesSatisfyingExactly( + trace -> + trace.hasSpansSatisfyingExactlyInAnyOrder( + span -> span.hasSpanId(SPAN_ID1), + span -> span.hasSpanId(SPAN_ID1)))) + .isInstanceOf(AssertionError.class); + } }