Skip to content

Commit ff38437

Browse files
authored
improve assertions by showing the last result on a timeout (#13119)
1 parent da9aa6c commit ff38437

File tree

2 files changed

+60
-48
lines changed

2 files changed

+60
-48
lines changed

testing-common/src/main/java/io/opentelemetry/instrumentation/testing/InstrumentationTestRunner.java

+59-39
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.opentelemetry.sdk.testing.assertj.TraceAssert;
1919
import io.opentelemetry.sdk.testing.assertj.TracesAssert;
2020
import io.opentelemetry.sdk.trace.data.SpanData;
21+
import java.time.Duration;
2122
import java.util.ArrayList;
2223
import java.util.Arrays;
2324
import java.util.Collection;
@@ -29,6 +30,7 @@
2930
import java.util.stream.Collectors;
3031
import javax.annotation.Nullable;
3132
import org.assertj.core.api.ListAssert;
33+
import org.awaitility.core.ConditionFactory;
3234
import org.awaitility.core.ConditionTimeoutException;
3335

3436
/**
@@ -118,25 +120,7 @@ private <T extends Consumer<TraceAssert>> void waitAndAssertTraces(
118120
List<T> assertionsList = new ArrayList<>();
119121
assertions.forEach(assertionsList::add);
120122

121-
try {
122-
await()
123-
.untilAsserted(() -> doAssertTraces(traceComparator, assertionsList, verifyScopeVersion));
124-
} catch (Throwable t) {
125-
// awaitility is doing a jmx call that is not implemented in GraalVM:
126-
// call:
127-
// https://github.com/awaitility/awaitility/blob/fbe16add874b4260dd240108304d5c0be84eabc8/awaitility/src/main/java/org/awaitility/core/ConditionAwaiter.java#L157
128-
// see https://github.com/oracle/graal/issues/6101 (spring boot graal native image)
129-
if (t.getClass().getName().equals("com.oracle.svm.core.jdk.UnsupportedFeatureError")
130-
|| t instanceof ConditionTimeoutException) {
131-
// Don't throw this failure since the stack is the awaitility thread, causing confusion.
132-
// Instead, just assert one more time on the test thread, which will fail with a better
133-
// stack trace.
134-
// TODO: There is probably a better way to do this.
135-
doAssertTraces(traceComparator, assertionsList, verifyScopeVersion);
136-
} else {
137-
throw t;
138-
}
139-
}
123+
awaitUntilAsserted(() -> doAssertTraces(traceComparator, assertionsList, verifyScopeVersion));
140124
}
141125

142126
private <T extends Consumer<TraceAssert>> void doAssertTraces(
@@ -159,31 +143,42 @@ private <T extends Consumer<TraceAssert>> void doAssertTraces(
159143
*/
160144
public final void waitAndAssertMetrics(
161145
String instrumentationName, String metricName, Consumer<ListAssert<MetricData>> assertion) {
162-
await()
163-
.untilAsserted(
164-
() ->
165-
assertion.accept(
166-
assertThat(getExportedMetrics())
167-
.filteredOn(
168-
data ->
169-
data.getInstrumentationScopeInfo()
170-
.getName()
171-
.equals(instrumentationName)
172-
&& data.getName().equals(metricName))));
146+
147+
awaitUntilAsserted(
148+
() ->
149+
assertion.accept(
150+
assertThat(getExportedMetrics())
151+
.describedAs(
152+
"Metrics for instrumentation %s and metric name %s",
153+
instrumentationName, metricName)
154+
.filteredOn(
155+
data ->
156+
data.getInstrumentationScopeInfo().getName().equals(instrumentationName)
157+
&& data.getName().equals(metricName))));
173158
}
174159

175160
@SafeVarargs
176161
public final void waitAndAssertMetrics(
177162
String instrumentationName, Consumer<MetricAssert>... assertions) {
178-
await()
179-
.untilAsserted(
180-
() -> {
181-
Collection<MetricData> metrics = instrumentationMetrics(instrumentationName);
182-
assertThat(metrics).isNotEmpty();
183-
for (Consumer<MetricAssert> assertion : assertions) {
184-
assertThat(metrics).anySatisfy(metric -> assertion.accept(assertThat(metric)));
185-
}
186-
});
163+
awaitUntilAsserted(
164+
() -> {
165+
Collection<MetricData> metrics = instrumentationMetrics(instrumentationName);
166+
assertThat(metrics).isNotEmpty();
167+
for (int i = 0; i < assertions.length; i++) {
168+
int index = i;
169+
assertThat(metrics)
170+
.describedAs(
171+
"Metrics for instrumentation %s and assertion %d", instrumentationName, index)
172+
.anySatisfy(metric -> assertions[index].accept(assertThat(metric)));
173+
}
174+
});
175+
}
176+
177+
public final List<LogRecordData> waitForLogRecords(int numberOfLogRecords) {
178+
awaitUntilAsserted(
179+
() -> assertThat(getExportedLogRecords().size()).isEqualTo(numberOfLogRecords),
180+
await().timeout(Duration.ofSeconds(20)));
181+
return getExportedLogRecords();
187182
}
188183

189184
private List<MetricData> instrumentationMetrics(String instrumentationName) {
@@ -265,4 +260,29 @@ public final <T, E extends Throwable> T runWithNonRecordingSpan(ThrowingSupplier
265260
throws E {
266261
return testInstrumenters.runWithNonRecordingSpan(callback);
267262
}
263+
264+
private static void awaitUntilAsserted(Runnable runnable) {
265+
awaitUntilAsserted(runnable, await());
266+
}
267+
268+
private static void awaitUntilAsserted(Runnable runnable, ConditionFactory conditionFactory) {
269+
try {
270+
conditionFactory.untilAsserted(runnable::run);
271+
} catch (Throwable t) {
272+
// awaitility is doing a jmx call that is not implemented in GraalVM:
273+
// call:
274+
// https://github.com/awaitility/awaitility/blob/fbe16add874b4260dd240108304d5c0be84eabc8/awaitility/src/main/java/org/awaitility/core/ConditionAwaiter.java#L157
275+
// see https://github.com/oracle/graal/issues/6101 (spring boot graal native image)
276+
if (t.getClass().getName().equals("com.oracle.svm.core.jdk.UnsupportedFeatureError")
277+
|| t instanceof ConditionTimeoutException) {
278+
// Don't throw this failure since the stack is the awaitility thread, causing confusion.
279+
// Instead, just assert one more time on the test thread, which will fail with a better
280+
// stack trace - that is on the same thread as the test.
281+
// TODO: There is probably a better way to do this.
282+
runnable.run();
283+
} else {
284+
throw t;
285+
}
286+
}
287+
}
268288
}

testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/InstrumentationExtension.java

+1-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package io.opentelemetry.instrumentation.testing.junit;
77

88
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
9-
import static org.awaitility.Awaitility.await;
109

1110
import io.opentelemetry.api.OpenTelemetry;
1211
import io.opentelemetry.context.ContextStorage;
@@ -22,7 +21,6 @@
2221
import io.opentelemetry.sdk.testing.assertj.MetricAssert;
2322
import io.opentelemetry.sdk.testing.assertj.TraceAssert;
2423
import io.opentelemetry.sdk.trace.data.SpanData;
25-
import java.time.Duration;
2624
import java.util.ArrayList;
2725
import java.util.Arrays;
2826
import java.util.Comparator;
@@ -125,13 +123,7 @@ public List<List<SpanData>> waitForTraces(int numberOfTraces) {
125123
* This waits up to 20 seconds, then times out.
126124
*/
127125
public List<LogRecordData> waitForLogRecords(int numberOfLogRecords) {
128-
await()
129-
.timeout(Duration.ofSeconds(20))
130-
.untilAsserted(
131-
() ->
132-
assertThat(testRunner.getExportedLogRecords().size())
133-
.isEqualTo(numberOfLogRecords));
134-
return testRunner.getExportedLogRecords();
126+
return testRunner.waitForLogRecords(numberOfLogRecords);
135127
}
136128

137129
@SafeVarargs

0 commit comments

Comments
 (0)