@@ -69,4 +69,89 @@ class InstrumentationDefaultMethodsTest extends Specification {
6969 then :
7070 events == [" dispatched" , " completed" ]
7171 }
72+
73+ def " chained field fetching does not allocate a chained context when all entries are no-op" () {
74+ given :
75+ def instrumentation = new ChainedInstrumentation (new Instrumentation () {}, SimplePerformantInstrumentation . INSTANCE )
76+ def state = instrumentation. createStateAsync(null ). join()
77+
78+ when :
79+ def context = instrumentation. beginFieldFetching(null , state)
80+
81+ then :
82+ context. is(FieldFetchingInstrumentationContext . NOOP )
83+ }
84+
85+ def " chained field fetching returns the only real context directly" () {
86+ given :
87+ def realContext = Mock (FieldFetchingInstrumentationContext )
88+ def instrumentation = new ChainedInstrumentation (
89+ new Instrumentation () {},
90+ instrumentationReturning(realContext),
91+ SimplePerformantInstrumentation . INSTANCE
92+ )
93+ def state = instrumentation. createStateAsync(null ). join()
94+
95+ when :
96+ def context = instrumentation. beginFieldFetching(null , state)
97+
98+ then :
99+ context. is(realContext)
100+ }
101+
102+ def " chained field fetching keeps multiple real contexts and skips canonical no-ops" () {
103+ given :
104+ def events = []
105+ def instrumentation = new ChainedInstrumentation (
106+ new Instrumentation () {},
107+ instrumentationReturning(recordingContext(" first" , events)),
108+ SimplePerformantInstrumentation . INSTANCE ,
109+ instrumentationReturning(recordingContext(" second" , events))
110+ )
111+ def state = instrumentation. createStateAsync(null ). join()
112+
113+ when :
114+ def context = instrumentation. beginFieldFetching(null , state)
115+ context. onDispatched()
116+ context. onFetchedValue(" value" )
117+ context. onCompleted(" complete" , null )
118+
119+ then :
120+ events == [
121+ " first-dispatched" ,
122+ " second-dispatched" ,
123+ " first-fetched-value" ,
124+ " second-fetched-value" ,
125+ " first-completed-complete" ,
126+ " second-completed-complete" ,
127+ ]
128+ }
129+
130+ private static Instrumentation instrumentationReturning (FieldFetchingInstrumentationContext context ) {
131+ return new Instrumentation () {
132+ @Override
133+ FieldFetchingInstrumentationContext beginFieldFetching (InstrumentationFieldFetchParameters parameters , InstrumentationState state ) {
134+ return context
135+ }
136+ }
137+ }
138+
139+ private static FieldFetchingInstrumentationContext recordingContext (String name , List<String > events ) {
140+ return new FieldFetchingInstrumentationContext () {
141+ @Override
142+ void onDispatched () {
143+ events. add(name + " -dispatched" )
144+ }
145+
146+ @Override
147+ void onFetchedValue (Object fetchedValue ) {
148+ events. add(name + " -fetched-" + fetchedValue)
149+ }
150+
151+ @Override
152+ void onCompleted (Object result , Throwable t ) {
153+ events. add(name + " -completed-" + result)
154+ }
155+ }
156+ }
72157}
0 commit comments