@@ -6,6 +6,7 @@ package queuebatch
66import (
77 "context"
88 "encoding/binary"
9+ "encoding/json"
910 "errors"
1011 "fmt"
1112 "math"
@@ -1304,7 +1305,7 @@ func TestSpanContextFromWrapper(t *testing.T) {
13041305
13051306 for _ , tc := range testCases {
13061307 t .Run (tc .name , func (t * testing.T ) {
1307- scc , err := SpanContextFromWrapper (tc .wrapper )
1308+ scc , err := spanContextFromWrapper (tc .wrapper )
13081309 if tc .expectErr {
13091310 require .Error (t , err )
13101311 if tc .errContains != "" {
@@ -1384,3 +1385,101 @@ func TestPersistentQueue_SpanContextRoundTrip(t *testing.T) {
13841385 restoredSC2 := trace .SpanContextFromContext (restoredCtx2 )
13851386 assert .False (t , restoredSC2 .IsValid ())
13861387}
1388+
1389+ func TestMarshalUnmarshalRequestWithSpanContext (t * testing.T ) {
1390+ t .Run ("valid SpanContext round-trip" , func (t * testing.T ) {
1391+ traceID , _ := trace .TraceIDFromHex ("0102030405060708090a0b0c0d0e0f10" )
1392+ spanID , _ := trace .SpanIDFromHex ("0102030405060708" )
1393+ sc := trace .NewSpanContext (trace.SpanContextConfig {
1394+ TraceID : traceID ,
1395+ SpanID : spanID ,
1396+ TraceFlags : 0x01 ,
1397+ TraceState : trace.TraceState {},
1398+ Remote : true ,
1399+ })
1400+ ctxWithSC := trace .ContextWithSpanContext (context .Background (), sc )
1401+ request := uint64 (42 )
1402+ data , err := marshalRequestWithSpanContext (ctxWithSC , uint64Encoding {}, request )
1403+ require .NoError (t , err )
1404+ gotReq , gotCtx , err := unmarshalRequestWithSpanContext (uint64Encoding {}, data )
1405+ require .NoError (t , err )
1406+ assert .Equal (t , request , gotReq )
1407+ restoredSC := trace .SpanContextFromContext (gotCtx )
1408+ assert .True (t , restoredSC .IsValid ())
1409+ assert .Equal (t , sc .TraceID (), restoredSC .TraceID ())
1410+ assert .Equal (t , sc .SpanID (), restoredSC .SpanID ())
1411+ assert .Equal (t , sc .TraceFlags (), restoredSC .TraceFlags ())
1412+ assert .Equal (t , sc .TraceState ().String (), restoredSC .TraceState ().String ())
1413+ assert .Equal (t , sc .IsRemote (), restoredSC .IsRemote ())
1414+ })
1415+
1416+ t .Run ("invalid SpanContext is omitted" , func (t * testing.T ) {
1417+ // An invalid SpanContext (zero value)
1418+ ctxWithInvalidSC := trace .ContextWithSpanContext (context .Background (), trace.SpanContext {})
1419+ request := uint64 (99 )
1420+ data , err := marshalRequestWithSpanContext (ctxWithInvalidSC , uint64Encoding {}, request )
1421+ require .NoError (t , err )
1422+ // Should not contain span_context field
1423+ assert .NotContains (t , string (data ), "span_context" )
1424+ gotReq , gotCtx , err := unmarshalRequestWithSpanContext (uint64Encoding {}, data )
1425+ require .NoError (t , err )
1426+ assert .Equal (t , request , gotReq )
1427+ restoredSC := trace .SpanContextFromContext (gotCtx )
1428+ assert .False (t , restoredSC .IsValid ())
1429+ })
1430+
1431+ t .Run ("no SpanContext in context is omitted" , func (t * testing.T ) {
1432+ request := uint64 (123 )
1433+ data , err := marshalRequestWithSpanContext (context .Background (), uint64Encoding {}, request )
1434+ require .NoError (t , err )
1435+ assert .NotContains (t , string (data ), "span_context" )
1436+ gotReq , gotCtx , err := unmarshalRequestWithSpanContext (uint64Encoding {}, data )
1437+ require .NoError (t , err )
1438+ assert .Equal (t , request , gotReq )
1439+ restoredSC := trace .SpanContextFromContext (gotCtx )
1440+ assert .False (t , restoredSC .IsValid ())
1441+ })
1442+
1443+ t .Run ("corrupted span_context field" , func (t * testing.T ) {
1444+ // Manually create a bad envelope
1445+ envelope := marshaledRequestWithSpanContext {
1446+ RequestBytes : []byte {0x2a , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 },
1447+ SpanContextJSON : []byte (`{"TraceID":123}` ), // invalid TraceID
1448+ }
1449+ data , err := json .Marshal (envelope )
1450+ require .NoError (t , err )
1451+ _ , gotCtx , err := unmarshalRequestWithSpanContext (uint64Encoding {}, data )
1452+ require .NoError (t , err )
1453+ // Should not panic, should return background context
1454+ restoredSC := trace .SpanContextFromContext (gotCtx )
1455+ assert .False (t , restoredSC .IsValid ())
1456+ })
1457+
1458+ t .Run ("valid JSON, invalid RequestBytes returns error" , func (t * testing.T ) {
1459+ envelope := marshaledRequestWithSpanContext {
1460+ RequestBytes : []byte {0x01 , 0x02 }, // too short for uint64Encoding.Unmarshal
1461+ SpanContextJSON : nil ,
1462+ }
1463+ data , err := json .Marshal (envelope )
1464+ require .NoError (t , err )
1465+ _ , _ , err = unmarshalRequestWithSpanContext (uint64Encoding {}, data )
1466+ require .Error (t , err )
1467+ })
1468+ }
1469+
1470+ type errorEncoding struct {}
1471+
1472+ func (errorEncoding ) Marshal (_ uint64 ) ([]byte , error ) {
1473+ return nil , errors .New ("marshal error" )
1474+ }
1475+
1476+ func (errorEncoding ) Unmarshal (_ []byte ) (uint64 , error ) {
1477+ return 0 , nil
1478+ }
1479+
1480+ func TestMarshalRequestWithSpanContext_MarshalError (t * testing.T ) {
1481+ ctx := context .Background ()
1482+ _ , err := marshalRequestWithSpanContext (ctx , errorEncoding {}, uint64 (123 ))
1483+ require .Error (t , err )
1484+ assert .Contains (t , err .Error (), "marshal error" )
1485+ }
0 commit comments