@@ -18,6 +18,7 @@ import (
18
18
19
19
"github.com/stretchr/testify/assert"
20
20
"github.com/stretchr/testify/require"
21
+ "go.opentelemetry.io/otel/trace"
21
22
22
23
"go.opentelemetry.io/collector/component"
23
24
"go.opentelemetry.io/collector/component/componenttest"
@@ -1205,3 +1206,181 @@ func requireCurrentlyDispatchedItemsEqual(t *testing.T, pq *persistentQueue[uint
1205
1206
defer pq .mu .Unlock ()
1206
1207
assert .ElementsMatch (t , compare , pq .currentlyDispatchedItems )
1207
1208
}
1209
+
1210
+ func TestSpanContextFromWrapper (t * testing.T ) {
1211
+ testCases := []struct {
1212
+ name string
1213
+ wrapper spanContextConfigWrapper
1214
+ expectErr bool
1215
+ errContains string
1216
+ expectNil bool
1217
+ expectValid bool
1218
+ expectTraceID string
1219
+ expectSpanID string
1220
+ expectFlags string
1221
+ expectState string
1222
+ expectRemote bool
1223
+ }{
1224
+ {
1225
+ name : "invalid trace id" ,
1226
+ wrapper : spanContextConfigWrapper {
1227
+ TraceID : "invalidtraceid" ,
1228
+ SpanID : "0102030405060708" ,
1229
+ TraceFlags : "01" ,
1230
+ TraceState : "" ,
1231
+ Remote : false ,
1232
+ },
1233
+ expectErr : true ,
1234
+ expectNil : true ,
1235
+ },
1236
+ {
1237
+ name : "invalid span id" ,
1238
+ wrapper : spanContextConfigWrapper {
1239
+ TraceID : "0102030405060708090a0b0c0d0e0f10" ,
1240
+ SpanID : "invalidspanid" ,
1241
+ TraceFlags : "01" ,
1242
+ TraceState : "" ,
1243
+ Remote : false ,
1244
+ },
1245
+ expectErr : true ,
1246
+ expectNil : true ,
1247
+ },
1248
+ {
1249
+ name : "invalid trace flags hex" ,
1250
+ wrapper : spanContextConfigWrapper {
1251
+ TraceID : "0102030405060708090a0b0c0d0e0f10" ,
1252
+ SpanID : "0102030405060708" ,
1253
+ TraceFlags : "zz" ,
1254
+ TraceState : "" ,
1255
+ Remote : false ,
1256
+ },
1257
+ expectErr : true ,
1258
+ expectNil : true ,
1259
+ },
1260
+ {
1261
+ name : "invalid trace flags length" ,
1262
+ wrapper : spanContextConfigWrapper {
1263
+ TraceID : "0102030405060708090a0b0c0d0e0f10" ,
1264
+ SpanID : "0102030405060708" ,
1265
+ TraceFlags : "0102" ,
1266
+ TraceState : "" ,
1267
+ Remote : false ,
1268
+ },
1269
+ expectErr : true ,
1270
+ expectNil : true ,
1271
+ errContains : errInvalidTraceFlagsLength ,
1272
+ },
1273
+ {
1274
+ name : "invalid trace state" ,
1275
+ wrapper : spanContextConfigWrapper {
1276
+ TraceID : "0102030405060708090a0b0c0d0e0f10" ,
1277
+ SpanID : "0102030405060708" ,
1278
+ TraceFlags : "01" ,
1279
+ TraceState : "invalid=tracestate,=bad" ,
1280
+ Remote : false ,
1281
+ },
1282
+ expectErr : true ,
1283
+ expectNil : true ,
1284
+ },
1285
+ {
1286
+ name : "valid span context" ,
1287
+ wrapper : spanContextConfigWrapper {
1288
+ TraceID : "0102030405060708090a0b0c0d0e0f10" ,
1289
+ SpanID : "0102030405060708" ,
1290
+ TraceFlags : "01" ,
1291
+ TraceState : "vendor=value" ,
1292
+ Remote : true ,
1293
+ },
1294
+ expectErr : false ,
1295
+ expectNil : false ,
1296
+ expectValid : true ,
1297
+ expectTraceID : "0102030405060708090a0b0c0d0e0f10" ,
1298
+ expectSpanID : "0102030405060708" ,
1299
+ expectFlags : "01" ,
1300
+ expectState : "vendor=value" ,
1301
+ expectRemote : true ,
1302
+ },
1303
+ }
1304
+
1305
+ for _ , tc := range testCases {
1306
+ t .Run (tc .name , func (t * testing.T ) {
1307
+ scc , err := SpanContextFromWrapper (tc .wrapper )
1308
+ if tc .expectErr {
1309
+ require .Error (t , err )
1310
+ if tc .errContains != "" {
1311
+ assert .Contains (t , err .Error (), tc .errContains )
1312
+ }
1313
+ } else {
1314
+ require .NoError (t , err )
1315
+ }
1316
+ if tc .expectNil {
1317
+ assert .Nil (t , scc )
1318
+ } else {
1319
+ assert .NotNil (t , scc )
1320
+ if tc .expectValid {
1321
+ assert .True (t , scc .IsValid ())
1322
+ assert .Equal (t , tc .expectTraceID , scc .TraceID ().String ())
1323
+ assert .Equal (t , tc .expectSpanID , scc .SpanID ().String ())
1324
+ assert .Equal (t , tc .expectFlags , scc .TraceFlags ().String ())
1325
+ assert .Equal (t , tc .expectState , scc .TraceState ().String ())
1326
+ assert .Equal (t , tc .expectRemote , scc .IsRemote ())
1327
+ }
1328
+ }
1329
+ })
1330
+ }
1331
+ }
1332
+
1333
+ func TestPersistentQueue_SpanContextRoundTrip (t * testing.T ) {
1334
+ // Setup a minimal persistent queue using uint64Encoding and uint64
1335
+ pq := newPersistentQueue [uint64 ](persistentQueueSettings [uint64 ]{
1336
+ sizer : request.RequestsSizer [uint64 ]{},
1337
+ capacity : 10 ,
1338
+ signal : pipeline .SignalTraces ,
1339
+ storageID : component.ID {},
1340
+ encoding : uint64Encoding {},
1341
+ id : component .NewID (exportertest .NopType ),
1342
+ telemetry : componenttest .NewNopTelemetrySettings (),
1343
+ }).(* persistentQueue [uint64 ])
1344
+
1345
+ ext := storagetest .NewMockStorageExtension (nil )
1346
+ client , err := ext .GetClient (context .Background (), component .KindExporter , pq .set .id , pq .set .signal .String ())
1347
+ require .NoError (t , err )
1348
+ pq .initClient (context .Background (), client )
1349
+
1350
+ // Create a valid SpanContext
1351
+ traceID , _ := trace .TraceIDFromHex ("0102030405060708090a0b0c0d0e0f10" )
1352
+ spanID , _ := trace .SpanIDFromHex ("0102030405060708" )
1353
+ sc := trace .NewSpanContext (trace.SpanContextConfig {
1354
+ TraceID : traceID ,
1355
+ SpanID : spanID ,
1356
+ TraceFlags : 0x01 ,
1357
+ TraceState : trace.TraceState {},
1358
+ Remote : true ,
1359
+ })
1360
+ ctxWithSC := trace .ContextWithSpanContext (context .Background (), sc )
1361
+
1362
+ // Offer a request with this context
1363
+ req := uint64 (42 )
1364
+ require .NoError (t , pq .Offer (ctxWithSC , req ))
1365
+
1366
+ // Read the request and restored context
1367
+ restoredCtx , gotReq , _ , ok := pq .Read (context .Background ())
1368
+ require .True (t , ok )
1369
+ assert .Equal (t , req , gotReq )
1370
+ restoredSC := trace .SpanContextFromContext (restoredCtx )
1371
+ assert .True (t , restoredSC .IsValid ())
1372
+ assert .Equal (t , sc .TraceID (), restoredSC .TraceID ())
1373
+ assert .Equal (t , sc .SpanID (), restoredSC .SpanID ())
1374
+ assert .Equal (t , sc .TraceFlags (), restoredSC .TraceFlags ())
1375
+ assert .Equal (t , sc .TraceState ().String (), restoredSC .TraceState ().String ())
1376
+ assert .Equal (t , sc .IsRemote (), restoredSC .IsRemote ())
1377
+
1378
+ // Also test with a context with no SpanContext
1379
+ req2 := uint64 (99 )
1380
+ require .NoError (t , pq .Offer (context .Background (), req2 ))
1381
+ restoredCtx2 , gotReq2 , _ , ok2 := pq .Read (context .Background ())
1382
+ require .True (t , ok2 )
1383
+ assert .Equal (t , req2 , gotReq2 )
1384
+ restoredSC2 := trace .SpanContextFromContext (restoredCtx2 )
1385
+ assert .False (t , restoredSC2 .IsValid ())
1386
+ }
0 commit comments