@@ -44,82 +44,88 @@ void capture_returnsNull_withoutProfilingContext() {
4444 }
4545
4646 @ Test
47- void capture_returnsNull_withoutActiveSpan () {
47+ void capture_recordsEntryTimingWithoutActiveSpan () {
4848 ProfilingContextIntegration profiling = mock (ProfilingContextIntegration .class );
49+ when (profiling .getCurrentTicks ()).thenReturn (START_TICKS );
50+
51+ long before = System .nanoTime ();
52+ TaskBlockHelper .State state = TaskBlockHelper .capture (BLOCKER , profiling , null );
53+ long after = System .nanoTime ();
4954
50- assertNull (TaskBlockHelper .capture (BLOCKER , profiling , null ));
55+ assertNotNull (state );
56+ assertEquals (profiling , state .profiling );
57+ assertEquals (START_TICKS , state .startTicks );
58+ assertTrue (state .startNanos >= before , "startNanos should be captured after `before`" );
59+ assertTrue (state .startNanos <= after , "startNanos should be captured before `after`" );
60+ assertEquals (BLOCKER , state .blocker );
61+ assertEquals (0L , state .spanId );
62+ assertEquals (0L , state .rootSpanId );
5163 }
5264
5365 @ Test
5466 void capture_returnsNull_whenSpanContextIsNotProfilerContext () {
5567 ProfilingContextIntegration profiling = mock (ProfilingContextIntegration .class );
5668 AgentSpan nonProfilerSpan = mock (AgentSpan .class );
5769 AgentSpanContext nonProfilerCtx = mock (AgentSpanContext .class );
58- when (nonProfilerSpan .context ()).thenReturn (nonProfilerCtx );
70+ when (nonProfilerSpan .spanContext ()).thenReturn (nonProfilerCtx );
5971
6072 assertNull (TaskBlockHelper .capture (BLOCKER , profiling , nonProfilerSpan ));
6173 }
6274
6375 @ Test
64- void capture_recordsEntryTimingWithoutSpanIds () {
65- // Span identity is captured natively at the recordTaskBlock JNI boundary; the Java-side
66- // State only retains the fields the native side cannot recompute (start tick, start nanos,
67- // blocker). The presence of an active span on the thread is still gated by capture() so we
68- // skip the JNI hop for span-less intervals.
76+ void capture_returnsNullWithActiveSpan () {
6977 ProfilingContextIntegration profiling = mock (ProfilingContextIntegration .class );
7078 AgentSpan span = mock (AgentSpan .class );
7179 ProfilerSpanContext ctx = mock (ProfilerSpanContext .class );
72- when (span .context ()).thenReturn (ctx );
73- when (profiling . getCurrentTicks ()).thenReturn (START_TICKS );
80+ when (span .spanContext ()).thenReturn (ctx );
81+ when (ctx . getSpanId ()).thenReturn (SPAN_ID );
7482
75- long before = System .nanoTime ();
7683 TaskBlockHelper .State state = TaskBlockHelper .capture (BLOCKER , profiling , span );
77- long after = System .nanoTime ();
7884
79- assertNotNull (state );
80- assertEquals (profiling , state .profiling );
81- assertEquals (START_TICKS , state .startTicks );
82- assertTrue (state .startNanos >= before , "startNanos should be captured after `before`" );
83- assertTrue (state .startNanos <= after , "startNanos should be captured before `after`" );
84- assertEquals (BLOCKER , state .blocker );
85- assertEquals (0L , state .spanId );
86- assertEquals (0L , state .rootSpanId );
85+ assertNull (state );
86+ verify (profiling , never ()).getCurrentTicks ();
8787 }
8888
8989 @ Test
90- void capture_deferredRecordsEntryTimingAndSpanIds () {
90+ void capture_deferredReturnsNullWithActiveSpan () {
9191 ProfilingContextIntegration profiling = mock (ProfilingContextIntegration .class );
9292 AgentSpan span = mock (AgentSpan .class );
9393 ProfilerSpanContext ctx = mock (ProfilerSpanContext .class );
94- when (span .context ()).thenReturn (ctx );
94+ when (span .spanContext ()).thenReturn (ctx );
9595 when (ctx .getSpanId ()).thenReturn (SPAN_ID );
9696 when (ctx .getRootSpanId ()).thenReturn (ROOT_SPAN_ID );
97+
98+ TaskBlockHelper .State state = TaskBlockHelper .capture (BLOCKER , profiling , span , true );
99+
100+ assertNull (state );
101+ verify (profiling , never ()).getCurrentTicks ();
102+ verify (profiling , never ()).blockEnter (anyInt ());
103+ }
104+
105+ @ Test
106+ void capture_deferredRecordsEntryTimingWithZeroContext () {
107+ ProfilingContextIntegration profiling = mock (ProfilingContextIntegration .class );
97108 when (profiling .getCurrentTicks ()).thenReturn (START_TICKS );
98109 when (profiling .blockEnter (ProfilingContextIntegration .BLOCKING_STATE_SLEEPING ))
99110 .thenReturn (BLOCK_TOKEN );
100111
101- TaskBlockHelper .State state = TaskBlockHelper .capture (BLOCKER , profiling , span , true );
112+ TaskBlockHelper .State state = TaskBlockHelper .capture (BLOCKER , profiling , null , true );
102113
103114 assertNotNull (state );
104115 assertEquals (START_TICKS , state .startTicks );
105116 assertEquals (BLOCKER , state .blocker );
106117 assertTrue (state .deferred );
107118 assertFalse (state .isVirtual );
108119 assertEquals (BLOCK_TOKEN , state .blockToken );
109- assertEquals (SPAN_ID , state .spanId );
110- assertEquals (ROOT_SPAN_ID , state .rootSpanId );
120+ assertEquals (0L , state .spanId );
121+ assertEquals (0L , state .rootSpanId );
111122 verify (profiling ).blockEnter (ProfilingContextIntegration .BLOCKING_STATE_SLEEPING );
112123 }
113124
114125 @ Test
115- void capture_deferredSleepOnVirtualThreadUsesVirtualState () throws Exception {
126+ void capture_deferredSleepOnVirtualThreadUsesZeroContextVirtualState () throws Exception {
116127 assumeTrue (hasVirtualThreads (), "virtual threads are not available on this JVM" );
117128 ProfilingContextIntegration profiling = mock (ProfilingContextIntegration .class );
118- AgentSpan span = mock (AgentSpan .class );
119- ProfilerSpanContext ctx = mock (ProfilerSpanContext .class );
120- when (span .context ()).thenReturn (ctx );
121- when (ctx .getSpanId ()).thenReturn (SPAN_ID );
122- when (ctx .getRootSpanId ()).thenReturn (ROOT_SPAN_ID );
123129 when (profiling .getCurrentTicks ()).thenReturn (START_TICKS );
124130
125131 AtomicReference <TaskBlockHelper .State > stateRef = new AtomicReference <>();
@@ -128,7 +134,7 @@ void capture_deferredSleepOnVirtualThreadUsesVirtualState() throws Exception {
128134 startVirtualThread (
129135 () -> {
130136 try {
131- stateRef .set (TaskBlockHelper .capture (BLOCKER , profiling , span , true ));
137+ stateRef .set (TaskBlockHelper .capture (BLOCKER , profiling , null , true ));
132138 } catch (Throwable error ) {
133139 errorRef .set (error );
134140 }
@@ -142,13 +148,13 @@ void capture_deferredSleepOnVirtualThreadUsesVirtualState() throws Exception {
142148 assertNotNull (state );
143149 assertTrue (state .isVirtual );
144150 assertFalse (state .deferred );
145- assertEquals (SPAN_ID , state .spanId );
146- assertEquals (ROOT_SPAN_ID , state .rootSpanId );
151+ assertEquals (0L , state .spanId );
152+ assertEquals (0L , state .rootSpanId );
147153
148154 waitUntilEligible (state );
149155 TaskBlockHelper .finish (state );
150156
151- verify (profiling ).recordTaskBlockWithContext (START_TICKS , BLOCKER , 0L , SPAN_ID , ROOT_SPAN_ID );
157+ verify (profiling ).recordTaskBlockWithContext (START_TICKS , BLOCKER , 0L , 0L , 0L );
152158 verify (profiling , never ())
153159 .enqueueTaskBlock (
154160 anyLong (), anyLong (), anyLong (), anyLong (), anyLong (), anyLong (), anyLong (), anyInt ());
@@ -160,7 +166,7 @@ void captureSafely_returnsNullWhenEntryCaptureThrows() {
160166 ProfilingContextIntegration profiling = mock (ProfilingContextIntegration .class );
161167 AgentSpan span = mock (AgentSpan .class );
162168 ProfilerSpanContext ctx = mock (ProfilerSpanContext .class );
163- when (span .context ()).thenReturn (ctx );
169+ when (span .spanContext ()).thenReturn (ctx );
164170 when (profiling .getCurrentTicks ()).thenThrow (new RuntimeException ("boom" ));
165171
166172 assertNull (TaskBlockHelper .captureSafely (BLOCKER , profiling , span ));
@@ -198,8 +204,8 @@ void finish_exitsNativeBlockEvenWhenTooShort() {
198204 System .nanoTime () + 60_000_000_000L ,
199205 BLOCKER ,
200206 true ,
201- SPAN_ID ,
202- ROOT_SPAN_ID ,
207+ 0L ,
208+ 0L ,
203209 BLOCK_TOKEN );
204210
205211 TaskBlockHelper .finish (state );
@@ -227,7 +233,24 @@ void finish_emitsTaskBlockForEligibleInterval() {
227233 }
228234
229235 @ Test
230- void finish_emitsVirtualTaskBlockWithSpanRootOnlyContext () {
236+ void finish_emitsVirtualTaskBlockWithZeroContext () {
237+ ProfilingContextIntegration profiling = mock (ProfilingContextIntegration .class );
238+ TaskBlockHelper .State state =
239+ new TaskBlockHelper .State (
240+ profiling ,
241+ START_TICKS ,
242+ System .nanoTime () - 2 * TaskBlockHelper .MIN_TASK_BLOCK_NANOS ,
243+ BLOCKER ,
244+ 0L ,
245+ 0L );
246+
247+ TaskBlockHelper .finish (state );
248+
249+ verify (profiling ).recordTaskBlockWithContext (START_TICKS , BLOCKER , 0L , 0L , 0L );
250+ }
251+
252+ @ Test
253+ void finish_skipsVirtualTaskBlockWithActiveSpanContext () {
231254 ProfilingContextIntegration profiling = mock (ProfilingContextIntegration .class );
232255 TaskBlockHelper .State state =
233256 new TaskBlockHelper .State (
@@ -240,11 +263,11 @@ void finish_emitsVirtualTaskBlockWithSpanRootOnlyContext() {
240263
241264 TaskBlockHelper .finish (state );
242265
243- verify (profiling ). recordTaskBlockWithContext ( START_TICKS , BLOCKER , 0L , SPAN_ID , ROOT_SPAN_ID );
266+ verifyNoInteractions (profiling );
244267 }
245268
246269 @ Test
247- void finish_enqueuesDeferredTaskBlockWithEntrySpanRootOnlyContext () {
270+ void finish_enqueuesDeferredTaskBlockWithZeroContext () {
248271 long anchorSampleId = 101L ;
249272 long suppressedSampleCount = 3L ;
250273 ProfilingContextIntegration profiling = mock (ProfilingContextIntegration .class );
@@ -268,8 +291,8 @@ void finish_enqueuesDeferredTaskBlockWithEntrySpanRootOnlyContext() {
268291 System .nanoTime () - 2 * TaskBlockHelper .MIN_TASK_BLOCK_NANOS ,
269292 BLOCKER ,
270293 true ,
271- SPAN_ID ,
272- ROOT_SPAN_ID ,
294+ 0L ,
295+ 0L ,
273296 BLOCK_TOKEN );
274297
275298 TaskBlockHelper .finish (state );
@@ -279,8 +302,8 @@ void finish_enqueuesDeferredTaskBlockWithEntrySpanRootOnlyContext() {
279302 eq (START_TICKS ),
280303 anyLong (),
281304 eq (BLOCKER ),
282- eq (SPAN_ID ),
283- eq (ROOT_SPAN_ID ),
305+ eq (0L ),
306+ eq (0L ),
284307 eq (anchorSampleId ),
285308 eq (suppressedSampleCount ),
286309 eq (ProfilingContextIntegration .BLOCKING_STATE_SLEEPING ));
0 commit comments