66package io .opentelemetry .instrumentation .reactor .v3_1 ;
77
88import static java .util .concurrent .TimeUnit .MILLISECONDS ;
9+ import static java .util .concurrent .TimeUnit .SECONDS ;
910import static org .assertj .core .api .Assertions .assertThat ;
10-
11+ import static org .junit .jupiter .api .Assumptions .assumeTrue ;
12+
13+ import io .opentelemetry .api .trace .Span ;
14+ import io .opentelemetry .api .trace .SpanContext ;
15+ import io .opentelemetry .api .trace .TraceFlags ;
16+ import io .opentelemetry .api .trace .TraceState ;
17+ import io .opentelemetry .context .Context ;
18+ import io .opentelemetry .context .Scope ;
1119import java .util .concurrent .Callable ;
20+ import java .util .concurrent .CountDownLatch ;
21+ import java .util .concurrent .atomic .AtomicBoolean ;
1222import java .util .concurrent .atomic .AtomicReference ;
23+ import java .util .function .Function ;
24+ import org .junit .jupiter .api .AfterEach ;
1325import org .junit .jupiter .api .Test ;
1426import reactor .core .CoreSubscriber ;
1527import reactor .core .Disposable ;
28+ import reactor .core .publisher .Hooks ;
1629import reactor .core .publisher .Mono ;
1730import reactor .core .scheduler .Schedulers ;
1831
1932class HooksTest {
2033
34+ private static final Span PARENT_SPAN =
35+ Span .wrap (
36+ SpanContext .create (
37+ "11111111111111111111111111111111" ,
38+ "1111111111111111" ,
39+ TraceFlags .getSampled (),
40+ TraceState .getDefault ()));
41+
42+ @ AfterEach
43+ void resetHooks () throws ReflectiveOperationException {
44+ Hooks .resetOnEachOperator (TracingSubscriber .class .getName ());
45+ if (schedulerHooksSupported ()) {
46+ Schedulers .class
47+ .getMethod ("resetOnScheduleHook" , String .class )
48+ .invoke (null , ContextPropagationOperator .RunnableWrapper .class .getName ());
49+ }
50+ }
51+
2152 @ Test
2253 void canResetOurHooks () {
2354 ContextPropagationOperator operator = ContextPropagationOperator .create ();
@@ -35,17 +66,19 @@ void canResetOurHooks() {
3566 assertThat (subscriber .get ()).extracting ("actual" ).isNotInstanceOf (TracingSubscriber .class );
3667 }
3768
38- private static class CapturingMono extends Mono <Integer > {
39- private final AtomicReference <CoreSubscriber <? super Integer >> subscriber ;
69+ @ Test
70+ void canResetSchedulerHook () throws InterruptedException {
71+ assumeTrue (schedulerHooksSupported ());
4072
41- private CapturingMono (AtomicReference <CoreSubscriber <? super Integer >> subscriber ) {
42- this .subscriber = subscriber ;
43- }
73+ ContextPropagationOperator operator = ContextPropagationOperator .create ();
4474
45- @ Override
46- public void subscribe (CoreSubscriber <? super Integer > actual ) {
47- subscriber .set (actual );
48- }
75+ assertThat (schedulerPropagatesContext ()).isFalse ();
76+
77+ operator .registerOnEachOperator ();
78+ assertThat (schedulerPropagatesContext ()).isTrue ();
79+
80+ operator .resetOnEachOperator ();
81+ assertThat (schedulerPropagatesContext ()).isFalse ();
4982 }
5083
5184 @ Test
@@ -71,4 +104,42 @@ void testInvalidBlockUsage() throws InterruptedException {
71104 disposable .dispose ();
72105 operator .resetOnEachOperator ();
73106 }
107+
108+ private static boolean schedulerHooksSupported () {
109+ try {
110+ Schedulers .class .getMethod ("onScheduleHook" , String .class , Function .class );
111+ Schedulers .class .getMethod ("resetOnScheduleHook" , String .class );
112+ return true ;
113+ } catch (NoSuchMethodException e ) {
114+ return false ;
115+ }
116+ }
117+
118+ private static boolean schedulerPropagatesContext () throws InterruptedException {
119+ CountDownLatch latch = new CountDownLatch (1 );
120+ AtomicBoolean currentSpanValid = new AtomicBoolean (false );
121+ try (Scope ignored = Context .root ().with (PARENT_SPAN ).makeCurrent ()) {
122+ Schedulers .single ()
123+ .schedule (
124+ () -> {
125+ currentSpanValid .set (Span .current ().getSpanContext ().isValid ());
126+ latch .countDown ();
127+ });
128+ }
129+ assertThat (latch .await (5 , SECONDS )).isTrue ();
130+ return currentSpanValid .get ();
131+ }
132+
133+ private static class CapturingMono extends Mono <Integer > {
134+ private final AtomicReference <CoreSubscriber <? super Integer >> subscriber ;
135+
136+ private CapturingMono (AtomicReference <CoreSubscriber <? super Integer >> subscriber ) {
137+ this .subscriber = subscriber ;
138+ }
139+
140+ @ Override
141+ public void subscribe (CoreSubscriber <? super Integer > actual ) {
142+ subscriber .set (actual );
143+ }
144+ }
74145}
0 commit comments