From 8c868b33d5c96de3b90f827156e97a981db17518 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Thu, 16 Apr 2026 13:21:38 -0400 Subject: [PATCH] Proper handling of `Target of 'verifyAll' block must not be null` error. --- .../agent/test/base/HttpClientTest.groovy | 32 +++++----- .../agent/test/base/HttpServerTest.groovy | 58 +++++++++---------- .../RecordingDatastreamsPayloadWriter.groovy | 17 +++++- ...cordingDatastreamsPayloadWriterTest.groovy | 58 +++++++++++++++++++ 4 files changed, 119 insertions(+), 46 deletions(-) create mode 100644 dd-java-agent/instrumentation-testing/src/test/groovy/datadog/trace/agent/test/datastreams/RecordingDatastreamsPayloadWriterTest.groovy diff --git a/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy b/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy index e787feeda1f..149ee9303f0 100644 --- a/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy +++ b/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy @@ -203,7 +203,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { } and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -249,7 +249,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -300,7 +300,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -337,7 +337,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -376,7 +376,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -416,7 +416,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -451,7 +451,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -486,7 +486,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -534,7 +534,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -584,7 +584,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -624,7 +624,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -662,7 +662,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -726,7 +726,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -820,7 +820,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -850,7 +850,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { } and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -885,7 +885,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { } and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { diff --git a/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy b/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy index 0b2a28d954b..a8418af43b2 100644 --- a/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy +++ b/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy @@ -662,7 +662,7 @@ abstract class HttpServerTest extends WithHttpServer { } and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -707,7 +707,7 @@ abstract class HttpServerTest extends WithHttpServer { } and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -754,7 +754,7 @@ abstract class HttpServerTest extends WithHttpServer { } and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -799,7 +799,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -864,7 +864,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -914,7 +914,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -958,7 +958,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1014,7 +1014,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1063,7 +1063,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1095,7 +1095,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1140,7 +1140,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1188,7 +1188,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1230,7 +1230,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1275,7 +1275,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1318,7 +1318,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1361,7 +1361,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1403,7 +1403,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1463,7 +1463,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1511,7 +1511,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1545,7 +1545,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1579,7 +1579,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1614,7 +1614,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1671,7 +1671,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1723,7 +1723,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1770,7 +1770,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1810,7 +1810,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1848,7 +1848,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1910,7 +1910,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { @@ -1968,7 +1968,7 @@ abstract class HttpServerTest extends WithHttpServer { and: if (isDataStreamsEnabled()) { - StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { + StatsGroup first = TEST_DATA_STREAMS_WRITER.waitForGroup { it.parentHash == 0 } verifyAll(first) { diff --git a/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/datastreams/RecordingDatastreamsPayloadWriter.groovy b/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/datastreams/RecordingDatastreamsPayloadWriter.groovy index 9feb48f3a98..2b79aef9b6e 100644 --- a/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/datastreams/RecordingDatastreamsPayloadWriter.groovy +++ b/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/datastreams/RecordingDatastreamsPayloadWriter.groovy @@ -87,7 +87,22 @@ class RecordingDatastreamsPayloadWriter implements DatastreamsPayloadWriter { waitFor(count, timeout, this.@schemaRegistryUsages) } - private static void waitFor(int count, long timeout, Collection collection) { + StatsGroup waitForGroup(Closure predicate, long timeout = TimeUnit.SECONDS.toMillis(3)) { + long deadline = System.currentTimeMillis() + timeout + while (System.currentTimeMillis() < deadline) { + synchronized (this) { + StatsGroup group = this.@groups.find(predicate) + if (group != null) { + return group + } + } + Thread.sleep(100) + } + + assert false: "Expected a matching stats group within ${timeout}ms" + } + + private void waitFor(int count, long timeout, Collection collection) { long deadline = System.currentTimeMillis() + timeout while (System.currentTimeMillis() < deadline) { synchronized (this) { diff --git a/dd-java-agent/instrumentation-testing/src/test/groovy/datadog/trace/agent/test/datastreams/RecordingDatastreamsPayloadWriterTest.groovy b/dd-java-agent/instrumentation-testing/src/test/groovy/datadog/trace/agent/test/datastreams/RecordingDatastreamsPayloadWriterTest.groovy new file mode 100644 index 00000000000..e3706feb98f --- /dev/null +++ b/dd-java-agent/instrumentation-testing/src/test/groovy/datadog/trace/agent/test/datastreams/RecordingDatastreamsPayloadWriterTest.groovy @@ -0,0 +1,58 @@ +package datadog.trace.agent.test.datastreams + +import static datadog.trace.api.datastreams.DataStreamsTags.Direction.INBOUND +import static java.util.concurrent.TimeUnit.SECONDS + +import datadog.trace.api.datastreams.DataStreamsTags +import datadog.trace.api.datastreams.StatsPoint +import datadog.trace.core.datastreams.StatsBucket +import datadog.trace.core.datastreams.StatsGroup +import spock.lang.Specification + +class RecordingDatastreamsPayloadWriterTest extends Specification { + private static Thread startWorker(RecordingDatastreamsPayloadWriter writer, long delay) { + return Thread.startDaemon { + writer.writePayload([bucket(1L, 123L, DataStreamsTags.create("test1", INBOUND))], null) + Thread.sleep(delay) + writer.writePayload([bucket(2L, 0L, DataStreamsTags.create("test2", INBOUND))], null) + } + } + + + def "waitForGroup waits for a matching group"() { + setup: + def writer = new RecordingDatastreamsPayloadWriter() + def worker = startWorker(writer, 50L) + + when: + StatsGroup group = writer.waitForGroup({ it.parentHash == 0 }, SECONDS.toMillis(1)) + + then: + group.parentHash == 0 + + cleanup: + worker.join(SECONDS.toMillis(2)) + } + + def "waitForGroup fails by timeout"() { + setup: + def writer = new RecordingDatastreamsPayloadWriter() + def worker = startWorker(writer, SECONDS.toMillis(3)) + + when: + writer.waitForGroup({ it.parentHash == 0 }, SECONDS.toMillis(1)) + + then: + AssertionError error = thrown() + error.message.contains("Expected a matching stats group within 1000ms") + + cleanup: + worker.join(SECONDS.toMillis(5)) + } + + private static StatsBucket bucket(long hash, long parentHash, DataStreamsTags tags) { + StatsBucket bucket = new StatsBucket(0, SECONDS.toNanos(1L)) + bucket.addPoint(new StatsPoint(tags, hash, parentHash, hash, 0, 1, 1, 0, null)) + return bucket + } +}