3333import static com .google .common .truth .Truth .assertThat ;
3434import static org .mockito .ArgumentMatchers .any ;
3535import static org .mockito .ArgumentMatchers .anyString ;
36+ import static org .mockito .ArgumentMatchers .nullable ;
3637import static org .mockito .Mockito .atLeastOnce ;
3738import static org .mockito .Mockito .mock ;
3839import static org .mockito .Mockito .verify ;
4142import com .google .api .gax .rpc .LibraryMetadata ;
4243import com .google .api .gax .tracing .ApiTracerContext .Transport ;
4344import com .google .api .gax .tracing .ApiTracerFactory .OperationType ;
45+ import io .opentelemetry .api .OpenTelemetry ;
4446import io .opentelemetry .api .common .AttributeKey ;
4547import io .opentelemetry .api .common .Attributes ;
4648import io .opentelemetry .api .trace .Span ;
5456import org .mockito .ArgumentCaptor ;
5557
5658class SpanTracerFactoryTest {
59+ private OpenTelemetry openTelemetry ;
5760 private Tracer tracer ;
5861 private SpanBuilder spanBuilder ;
5962 private Span span ;
6063
64+ private LibraryMetadata validMetadata ;
65+
6166 @ BeforeEach
6267 void setUp () {
68+ openTelemetry = mock (OpenTelemetry .class );
6369 tracer = mock (Tracer .class );
6470 spanBuilder = mock (SpanBuilder .class );
6571 span = mock (Span .class );
72+ when (openTelemetry .getTracer (nullable (String .class ), nullable (String .class )))
73+ .thenReturn (tracer );
6674 when (tracer .spanBuilder (anyString ())).thenReturn (spanBuilder );
6775 when (spanBuilder .setSpanKind (any ())).thenReturn (spanBuilder );
6876 when (spanBuilder .setAllAttributes (any (Attributes .class ))).thenReturn (spanBuilder );
6977 when (spanBuilder .startSpan ()).thenReturn (span );
78+
79+ validMetadata = mock (LibraryMetadata .class );
80+ when (validMetadata .artifactName ()).thenReturn ("gax-java" );
81+ when (validMetadata .version ()).thenReturn ("2.1.0" );
7082 }
7183
7284 @ ParameterizedTest
7385 @ ValueSource (booleans = {false , true })
7486 void testNewTracer_createsSpanTracer (boolean useContext ) {
75- SpanTracerFactory factory = new SpanTracerFactory (tracer , ApiTracerContext .empty ());
87+ SpanTracerFactory factory =
88+ new SpanTracerFactory (openTelemetry , tracer , ApiTracerContext .empty ());
7689 ApiTracer tracerInstance ;
7790 if (useContext ) {
7891 ApiTracerContext context =
@@ -92,11 +105,12 @@ void testNewTracer_createsSpanTracer(boolean useContext) {
92105 @ ParameterizedTest
93106 @ ValueSource (booleans = {false , true })
94107 void testNewTracer_addsAttributes (boolean useContext ) {
95- ApiTracerFactory factory = new SpanTracerFactory (tracer , ApiTracerContext .empty ());
108+ ApiTracerFactory factory =
109+ new SpanTracerFactory (openTelemetry , tracer , ApiTracerContext .empty ());
96110 factory =
97111 factory .withContext (
98112 ApiTracerContext .newBuilder ()
99- .setLibraryMetadata (LibraryMetadata . empty () )
113+ .setLibraryMetadata (validMetadata )
100114 .setServerAddress ("test-address" )
101115 .build ());
102116 ApiTracer tracerInstance ;
@@ -105,7 +119,7 @@ void testNewTracer_addsAttributes(boolean useContext) {
105119 ApiTracerContext .newBuilder ()
106120 .setFullMethodName ("service/method" )
107121 .setTransport (Transport .GRPC )
108- .setLibraryMetadata (LibraryMetadata . empty () )
122+ .setLibraryMetadata (validMetadata )
109123 .build ();
110124 tracerInstance = factory .newTracer (null , context );
111125 } else {
@@ -128,11 +142,12 @@ void testNewTracer_addsAttributes(boolean useContext) {
128142 void testWithContext_addsInferredAttributes (boolean useContext ) {
129143 ApiTracerContext context =
130144 ApiTracerContext .newBuilder ()
131- .setLibraryMetadata (LibraryMetadata . empty () )
145+ .setLibraryMetadata (validMetadata )
132146 .setServerAddress ("example.com" )
133147 .build ();
134148
135- SpanTracerFactory factory = new SpanTracerFactory (tracer , ApiTracerContext .empty ());
149+ SpanTracerFactory factory =
150+ new SpanTracerFactory (openTelemetry , tracer , ApiTracerContext .empty ());
136151 ApiTracerFactory factoryWithContext = factory .withContext (context );
137152
138153 ApiTracer tracerInstance ;
@@ -141,7 +156,7 @@ void testWithContext_addsInferredAttributes(boolean useContext) {
141156 ApiTracerContext .newBuilder ()
142157 .setFullMethodName ("service/method" )
143158 .setTransport (Transport .GRPC )
144- .setLibraryMetadata (LibraryMetadata . empty () )
159+ .setLibraryMetadata (validMetadata )
145160 .build ();
146161 tracerInstance = factoryWithContext .newTracer (null , callContext );
147162 } else {
@@ -164,9 +179,11 @@ void testWithContext_addsInferredAttributes(boolean useContext) {
164179 @ ParameterizedTest
165180 @ ValueSource (booleans = {false , true })
166181 void testWithContext_noEndpointContext_doesNotAddServerAddressAttribute (boolean useContext ) {
167- ApiTracerContext context = ApiTracerContext .empty ();
182+ ApiTracerContext context =
183+ ApiTracerContext .newBuilder ().setLibraryMetadata (validMetadata ).build ();
168184
169- SpanTracerFactory factory = new SpanTracerFactory (tracer , ApiTracerContext .empty ());
185+ SpanTracerFactory factory =
186+ new SpanTracerFactory (openTelemetry , tracer , ApiTracerContext .empty ());
170187 ApiTracerFactory factoryWithContext = factory .withContext (context );
171188
172189 ApiTracer tracerInstance ;
@@ -175,7 +192,7 @@ void testWithContext_noEndpointContext_doesNotAddServerAddressAttribute(boolean
175192 ApiTracerContext .newBuilder ()
176193 .setFullMethodName ("service/method" )
177194 .setTransport (Transport .GRPC )
178- .setLibraryMetadata (LibraryMetadata . empty () )
195+ .setLibraryMetadata (validMetadata )
179196 .build ();
180197 tracerInstance = factoryWithContext .newTracer (null , callContext );
181198 } else {
@@ -203,7 +220,8 @@ void testNewTracer_withContext_grpc_usesFullMethodName() {
203220 .setLibraryMetadata (LibraryMetadata .empty ())
204221 .build ();
205222
206- SpanTracerFactory factory = new SpanTracerFactory (tracer , ApiTracerContext .empty ());
223+ SpanTracerFactory factory =
224+ new SpanTracerFactory (openTelemetry , tracer , ApiTracerContext .empty ());
207225 ApiTracer tracerInstance = factory .newTracer (null , context );
208226
209227 tracerInstance .attemptStarted (null , 1 );
@@ -229,7 +247,8 @@ void testNewTracer_withContext_http_usesHttpMethodAndPathTemplate(
229247 .setLibraryMetadata (LibraryMetadata .empty ())
230248 .build ();
231249
232- SpanTracerFactory factory = new SpanTracerFactory (tracer , ApiTracerContext .empty ());
250+ SpanTracerFactory factory =
251+ new SpanTracerFactory (openTelemetry , tracer , ApiTracerContext .empty ());
233252 ApiTracer tracerInstance = factory .newTracer (null , context );
234253
235254 tracerInstance .attemptStarted (null , 1 );
@@ -246,7 +265,8 @@ void testNewTracer_withContext_http_noHttpMethodOrPathTemplate_usesFullMethodNam
246265 .setLibraryMetadata (LibraryMetadata .empty ())
247266 .build ();
248267
249- SpanTracerFactory factory = new SpanTracerFactory (tracer , ApiTracerContext .empty ());
268+ SpanTracerFactory factory =
269+ new SpanTracerFactory (openTelemetry , tracer , ApiTracerContext .empty ());
250270 ApiTracer tracerInstance = factory .newTracer (null , context );
251271
252272 tracerInstance .attemptStarted (null , 1 );
@@ -256,7 +276,8 @@ void testNewTracer_withContext_http_noHttpMethodOrPathTemplate_usesFullMethodNam
256276
257277 @ Test
258278 void testNewTracer_withSpanName_usesPlaceholder () {
259- SpanTracerFactory factory = new SpanTracerFactory (tracer , ApiTracerContext .empty ());
279+ SpanTracerFactory factory =
280+ new SpanTracerFactory (openTelemetry , tracer , ApiTracerContext .empty ());
260281 ApiTracer tracerInstance =
261282 factory .newTracer (null , SpanName .of ("Service" , "Method" ), OperationType .Unary );
262283
@@ -272,7 +293,7 @@ void testNewTracer_mergesFactoryContext() {
272293 .setServerAddress ("factory-address" )
273294 .setLibraryMetadata (LibraryMetadata .empty ())
274295 .build ();
275- SpanTracerFactory factory = new SpanTracerFactory (tracer , apiTracerContext );
296+ SpanTracerFactory factory = new SpanTracerFactory (openTelemetry , tracer , apiTracerContext );
276297
277298 ApiTracerContext callContext =
278299 ApiTracerContext .newBuilder ()
@@ -293,4 +314,51 @@ void testNewTracer_mergesFactoryContext() {
293314 assertThat (attributes .asMap ())
294315 .containsEntry (AttributeKey .stringKey ("rpc.method" ), "Service/Method" );
295316 }
317+
318+ @ Test
319+ void testNoOpWhenTracerNull () {
320+ SpanTracerFactory factory =
321+ new SpanTracerFactory (openTelemetry , null , ApiTracerContext .empty ());
322+
323+ ApiTracer tracerInstance =
324+ factory .newTracer (null , SpanName .of ("Service" , "Method" ), OperationType .Unary );
325+
326+ assertThat (tracerInstance ).isInstanceOf (BaseApiTracer .class );
327+
328+ ApiTracer tracerInstance2 = factory .newTracer (null , ApiTracerContext .empty ());
329+
330+ assertThat (tracerInstance2 ).isInstanceOf (BaseApiTracer .class );
331+ }
332+
333+ @ Test
334+ void testWithContext_nullContext_returnsBaseApiTracerFactory () {
335+ SpanTracerFactory factory =
336+ new SpanTracerFactory (openTelemetry , tracer , ApiTracerContext .empty ());
337+ ApiTracerFactory factoryWithContext = factory .withContext (null );
338+ assertThat (factoryWithContext ).isInstanceOf (BaseApiTracerFactory .class );
339+ }
340+
341+ @ Test
342+ void testWithContext_nullMetadata_returnsBaseApiTracerFactory () {
343+ SpanTracerFactory factory =
344+ new SpanTracerFactory (openTelemetry , tracer , ApiTracerContext .empty ());
345+ // Assuming ApiTracerContext.empty() has null libraryMetadata
346+ ApiTracerFactory factoryWithContext = factory .withContext (ApiTracerContext .empty ());
347+ assertThat (factoryWithContext ).isInstanceOf (BaseApiTracerFactory .class );
348+ }
349+
350+ @ Test
351+ void testWithContext_nullTracer_returnsBaseApiTracerFactory () {
352+ OpenTelemetry mockOpenTelemetry = mock (OpenTelemetry .class );
353+ when (mockOpenTelemetry .getTracer (nullable (String .class ), nullable (String .class )))
354+ .thenReturn (null );
355+
356+ SpanTracerFactory factory =
357+ new SpanTracerFactory (mockOpenTelemetry , tracer , ApiTracerContext .empty ());
358+ ApiTracerContext context =
359+ ApiTracerContext .newBuilder ().setLibraryMetadata (LibraryMetadata .empty ()).build ();
360+
361+ ApiTracerFactory factoryWithContext = factory .withContext (context );
362+ assertThat (factoryWithContext ).isInstanceOf (BaseApiTracerFactory .class );
363+ }
296364}
0 commit comments