github.com/instana/go-sensor@v1.62.2-0.20240520081010-4919868049e1/propagation_test.go (about)

     1  // (c) Copyright IBM Corp. 2021
     2  // (c) Copyright Instana Inc. 2016
     3  
     4  package instana_test
     5  
     6  import (
     7  	"net/http"
     8  	"testing"
     9  
    10  	instana "github.com/instana/go-sensor"
    11  	"github.com/instana/go-sensor/w3ctrace"
    12  	ot "github.com/opentracing/opentracing-go"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func TestTracer_Inject_HTTPHeaders(t *testing.T) {
    18  	examples := map[string]struct {
    19  		SpanContext instana.SpanContext
    20  		Headers     http.Header
    21  		Expected    http.Header
    22  	}{
    23  		"no trace context": {
    24  			SpanContext: instana.SpanContext{
    25  				TraceIDHi: 0x1,
    26  				TraceID:   0x2435,
    27  				SpanID:    0x3546,
    28  				Baggage: map[string]string{
    29  					"foo": "bar",
    30  				},
    31  			},
    32  			Headers: http.Header{
    33  				"Authorization": {"Basic 123"},
    34  			},
    35  			Expected: http.Header{
    36  				"Authorization":   {"Basic 123"},
    37  				"X-Instana-T":     {"0000000000002435"},
    38  				"X-Instana-S":     {"0000000000003546"},
    39  				"X-Instana-L":     {"1"},
    40  				"X-Instana-B-Foo": {"bar"},
    41  				"Traceparent":     {"00-00000000000000010000000000002435-0000000000003546-01"},
    42  				"Tracestate":      {"in=0000000000002435;0000000000003546"},
    43  				"Server-Timing":   {"intid;desc=0000000000002435"},
    44  			},
    45  		},
    46  		"with instana trace": {
    47  			SpanContext: instana.SpanContext{
    48  				TraceIDHi: 0x1,
    49  				TraceID:   0x2435,
    50  				SpanID:    0x3546,
    51  				Baggage: map[string]string{
    52  					"foo": "bar",
    53  				},
    54  			},
    55  			Headers: http.Header{
    56  				"Authorization":   {"Basic 123"},
    57  				"x-instana-t":     {"0000000000001314"},
    58  				"X-INSTANA-S":     {"0000000000001314"},
    59  				"X-Instana-L":     {"1"},
    60  				"X-Instana-B-foo": {"hello"},
    61  			},
    62  			Expected: http.Header{
    63  				"Authorization":   {"Basic 123"},
    64  				"X-Instana-T":     {"0000000000002435"},
    65  				"X-Instana-S":     {"0000000000003546"},
    66  				"X-Instana-L":     {"1"},
    67  				"X-Instana-B-Foo": {"bar"},
    68  				"Traceparent":     {"00-00000000000000010000000000002435-0000000000003546-01"},
    69  				"Tracestate":      {"in=0000000000002435;0000000000003546"},
    70  				"Server-Timing":   {"intid;desc=0000000000002435"},
    71  			},
    72  		},
    73  		"with instana trace suppressed": {
    74  			SpanContext: instana.SpanContext{
    75  				TraceIDHi:  0x1,
    76  				TraceID:    0x2435,
    77  				SpanID:     0x3546,
    78  				Suppressed: true,
    79  			},
    80  			Headers: http.Header{
    81  				"Authorization": {"Basic 123"},
    82  			},
    83  			Expected: http.Header{
    84  				"Authorization": {"Basic 123"},
    85  				"X-Instana-L":   {"0"},
    86  				"Traceparent":   {"00-00000000000000010000000000002435-0000000000003546-00"},
    87  				"Server-Timing": {"intid;desc=0000000000002435"},
    88  			},
    89  		},
    90  	}
    91  
    92  	for name, example := range examples {
    93  		t.Run(name, func(t *testing.T) {
    94  			recorder := instana.NewTestRecorder()
    95  			tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
    96  			defer instana.ShutdownSensor()
    97  
    98  			require.NoError(t, tracer.Inject(example.SpanContext, ot.HTTPHeaders, ot.HTTPHeadersCarrier(example.Headers)))
    99  			assert.Equal(t, example.Expected, example.Headers)
   100  		})
   101  	}
   102  }
   103  
   104  func TestTracer_Inject_HTTPHeaders_W3CTraceContext(t *testing.T) {
   105  	examples := map[string]struct {
   106  		SpanContext instana.SpanContext
   107  		Expected    http.Header
   108  	}{
   109  		"instana trace suppressed, no w3c trace": {
   110  			SpanContext: instana.SpanContext{
   111  				TraceIDHi:  0x01,
   112  				TraceID:    0x2435,
   113  				SpanID:     0x3546,
   114  				Suppressed: true,
   115  			},
   116  			Expected: http.Header{
   117  				"X-Instana-L":   {"0"},
   118  				"Traceparent":   {"00-00000000000000010000000000002435-0000000000003546-00"},
   119  				"Server-Timing": {"intid;desc=0000000000002435"},
   120  			},
   121  		},
   122  		"instana trace suppressed, w3c trace not sampled": {
   123  			SpanContext: instana.SpanContext{
   124  				TraceIDHi: 0x01,
   125  				TraceID:   0x2435,
   126  				SpanID:    0x3546,
   127  				W3CContext: w3ctrace.Context{
   128  					RawParent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00",
   129  					RawState:  "rojo=00f067aa0ba902b7",
   130  				},
   131  				Suppressed: true,
   132  			},
   133  			Expected: http.Header{
   134  				"X-Instana-L":   {"0"},
   135  				"Traceparent":   {"00-4bf92f3577b34da6a3ce929d0e0e4736-0000000000003546-00"},
   136  				"Tracestate":    {"rojo=00f067aa0ba902b7"},
   137  				"Server-Timing": {"intid;desc=0000000000002435"},
   138  			},
   139  		},
   140  		"instana trace suppressed, w3c trace sampled": {
   141  			SpanContext: instana.SpanContext{
   142  				TraceIDHi: 0x01,
   143  				TraceID:   0x2435,
   144  				SpanID:    0x3546,
   145  				W3CContext: w3ctrace.Context{
   146  					RawParent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
   147  					RawState:  "rojo=00f067aa0ba902b7",
   148  				},
   149  				Suppressed: true,
   150  			},
   151  			Expected: http.Header{
   152  				"X-Instana-L":   {"0"},
   153  				"Traceparent":   {"00-4bf92f3577b34da6a3ce929d0e0e4736-0000000000003546-00"},
   154  				"Tracestate":    {"rojo=00f067aa0ba902b7"},
   155  				"Server-Timing": {"intid;desc=0000000000002435"},
   156  			},
   157  		},
   158  		"instana trace, no w3c trace": {
   159  			SpanContext: instana.SpanContext{
   160  				TraceIDHi: 0x01,
   161  				TraceID:   0x2435,
   162  				SpanID:    0x3546,
   163  			},
   164  			Expected: http.Header{
   165  				"X-Instana-T":   {"0000000000002435"},
   166  				"X-Instana-S":   {"0000000000003546"},
   167  				"X-Instana-L":   {"1"},
   168  				"Traceparent":   {"00-00000000000000010000000000002435-0000000000003546-01"},
   169  				"Tracestate":    {"in=0000000000002435;0000000000003546"},
   170  				"Server-Timing": {"intid;desc=0000000000002435"},
   171  			},
   172  		},
   173  		"instana trace, w3c trace not sampled": {
   174  			SpanContext: instana.SpanContext{
   175  				TraceIDHi: 0x01,
   176  				TraceID:   0x2435,
   177  				SpanID:    0x3546,
   178  				W3CContext: w3ctrace.Context{
   179  					RawParent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00",
   180  					RawState:  "rojo=00f067aa0ba902b7",
   181  				},
   182  			},
   183  			Expected: http.Header{
   184  				"X-Instana-T":   {"0000000000002435"},
   185  				"X-Instana-S":   {"0000000000003546"},
   186  				"X-Instana-L":   {"1"},
   187  				"Traceparent":   {"00-4bf92f3577b34da6a3ce929d0e0e4736-0000000000003546-01"},
   188  				"Tracestate":    {"in=0000000000002435;0000000000003546,rojo=00f067aa0ba902b7"},
   189  				"Server-Timing": {"intid;desc=0000000000002435"},
   190  			},
   191  		},
   192  		"instana trace, w3c trace": {
   193  			SpanContext: instana.SpanContext{
   194  				TraceIDHi: 0x01,
   195  				TraceID:   0x2435,
   196  				SpanID:    0x3546,
   197  				W3CContext: w3ctrace.Context{
   198  					RawParent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
   199  					RawState:  "rojo=00f067aa0ba902b7",
   200  				},
   201  			},
   202  			Expected: http.Header{
   203  				"X-Instana-T":   {"0000000000002435"},
   204  				"X-Instana-S":   {"0000000000003546"},
   205  				"X-Instana-L":   {"1"},
   206  				"Traceparent":   {"00-4bf92f3577b34da6a3ce929d0e0e4736-0000000000003546-01"},
   207  				"Tracestate":    {"in=0000000000002435;0000000000003546,rojo=00f067aa0ba902b7"},
   208  				"Server-Timing": {"intid;desc=0000000000002435"},
   209  			},
   210  		},
   211  	}
   212  
   213  	for name, example := range examples {
   214  		t.Run(name, func(t *testing.T) {
   215  			recorder := instana.NewTestRecorder()
   216  			tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   217  			defer instana.ShutdownSensor()
   218  			headers := http.Header{}
   219  
   220  			require.NoError(t, tracer.Inject(example.SpanContext, ot.HTTPHeaders, ot.HTTPHeadersCarrier(headers)))
   221  			assert.Equal(t, example.Expected, headers)
   222  		})
   223  	}
   224  }
   225  
   226  func TestTracer_Inject_HTTPHeaders_SuppressedTracing(t *testing.T) {
   227  	recorder := instana.NewTestRecorder()
   228  	tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   229  	defer instana.ShutdownSensor()
   230  
   231  	headers := http.Header{
   232  		"Authorization": {"Basic 123"},
   233  		"x-instana-t":   {"0000000000001314"},
   234  		"X-INSTANA-S":   {"0000000000001314"},
   235  		"X-Instana-L":   {"1"},
   236  	}
   237  
   238  	sc := instana.SpanContext{
   239  		TraceIDHi:  0x1,
   240  		TraceID:    0x2435,
   241  		SpanID:     0x3546,
   242  		Suppressed: true,
   243  	}
   244  
   245  	require.NoError(t, tracer.Inject(sc, ot.HTTPHeaders, ot.HTTPHeadersCarrier(headers)))
   246  
   247  	assert.Empty(t, headers.Get("X-Instana-T"))
   248  	assert.Empty(t, headers.Get("X-Instana-S"))
   249  	assert.Equal(t, "0", headers.Get("X-Instana-L"))
   250  	assert.Equal(t, "Basic 123", headers.Get("Authorization"))
   251  	assert.Equal(t, "intid;desc=0000000000002435", headers.Get("Server-Timing"))
   252  }
   253  
   254  func TestTracer_Inject_HTTPHeaders_WithExistingServerTiming(t *testing.T) {
   255  	recorder := instana.NewTestRecorder()
   256  	tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   257  	defer instana.ShutdownSensor()
   258  
   259  	headers := http.Header{
   260  		"x-instana-t":   {"0000000000001314"},
   261  		"X-INSTANA-S":   {"0000000000001314"},
   262  		"X-Instana-L":   {"1"},
   263  		"Server-Timing": {"db;dur=53, app;dur=47.2", `cache;desc="Cache Read";dur=23.2`},
   264  	}
   265  
   266  	sc := instana.SpanContext{
   267  		TraceID:    0x2435,
   268  		SpanID:     0x3546,
   269  		Suppressed: true,
   270  	}
   271  
   272  	require.NoError(t, tracer.Inject(sc, ot.HTTPHeaders, ot.HTTPHeadersCarrier(headers)))
   273  	assert.Equal(t, `db;dur=53, app;dur=47.2, cache;desc="Cache Read";dur=23.2, intid;desc=0000000000002435`, headers.Get("Server-Timing"))
   274  }
   275  
   276  func TestTracer_Extract_HTTPHeaders(t *testing.T) {
   277  	examples := map[string]struct {
   278  		Headers  map[string]string
   279  		Expected instana.SpanContext
   280  	}{
   281  		"tracing enabled": {
   282  			Headers: map[string]string{
   283  				"Authorization":   "Basic 123",
   284  				"x-instana-t":     "0000000000000000000000010000000000001314",
   285  				"X-INSTANA-S":     "0000000000002435",
   286  				"X-Instana-L":     "1",
   287  				"X-Instana-B-Foo": "bar",
   288  			},
   289  			Expected: instana.SpanContext{
   290  				TraceIDHi: 0x1,
   291  				TraceID:   0x1314,
   292  				SpanID:    0x2435,
   293  				Baggage: map[string]string{
   294  					"Foo": "bar",
   295  				},
   296  			},
   297  		},
   298  		"tracing disabled": {
   299  			Headers: map[string]string{
   300  				"Authorization": "Basic 123",
   301  				"x-instana-t":   "0000000000000000000000010000000000001314",
   302  				"X-INSTANA-S":   "0000000000002435",
   303  				"X-Instana-L":   "0",
   304  			},
   305  			Expected: instana.SpanContext{
   306  				TraceIDHi:  0x1,
   307  				TraceID:    0x1314,
   308  				SpanID:     0x2435,
   309  				Suppressed: true,
   310  				Baggage:    map[string]string{},
   311  			},
   312  		},
   313  		"tracing disabled, with correlation data": {
   314  			Headers: map[string]string{
   315  				"Authorization": "Basic 123",
   316  				"x-instana-t":   "10000000000001314",
   317  				"X-INSTANA-S":   "2435",
   318  				"X-Instana-L":   "0,correlationType=web;correlationId=1234",
   319  			},
   320  			Expected: instana.SpanContext{
   321  				TraceIDHi:  0x1,
   322  				TraceID:    0x1314,
   323  				SpanID:     0x2435,
   324  				Suppressed: true,
   325  				Baggage:    map[string]string{},
   326  			},
   327  		},
   328  		"tracing disabled, no trace context": {
   329  			Headers: map[string]string{
   330  				"Authorization": "Basic 123",
   331  				"X-Instana-L":   "0",
   332  			},
   333  			Expected: instana.SpanContext{
   334  				Suppressed: true,
   335  				Baggage:    map[string]string{},
   336  			},
   337  		},
   338  		"w3c trace context, with instana headers": {
   339  			Headers: map[string]string{
   340  				"x-instana-t": "10000000000001314",
   341  				"X-INSTANA-S": "2435",
   342  				"X-Instana-L": "1",
   343  				"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
   344  				"tracestate":  "rojo=00f067aa0ba902b7",
   345  			},
   346  			Expected: instana.SpanContext{
   347  				TraceIDHi: 0x1,
   348  				TraceID:   0x1314,
   349  				SpanID:    0x2435,
   350  				Baggage:   map[string]string{},
   351  				W3CContext: w3ctrace.Context{
   352  					RawParent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
   353  					RawState:  "rojo=00f067aa0ba902b7",
   354  				},
   355  			},
   356  		},
   357  		"w3c trace context, no instana headers": {
   358  			Headers: map[string]string{
   359  				"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
   360  				"tracestate":  "in=10000000000001314;2435,rojo=00f067aa0ba902b7",
   361  			},
   362  			Expected: instana.SpanContext{
   363  				Baggage: map[string]string{},
   364  				W3CContext: w3ctrace.Context{
   365  					RawParent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
   366  					RawState:  "in=10000000000001314;2435,rojo=00f067aa0ba902b7",
   367  				},
   368  			},
   369  		},
   370  	}
   371  
   372  	for name, example := range examples {
   373  		t.Run(name, func(t *testing.T) {
   374  			recorder := instana.NewTestRecorder()
   375  			tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   376  			defer instana.ShutdownSensor()
   377  
   378  			headers := http.Header{}
   379  			for k, v := range example.Headers {
   380  				headers.Set(k, v)
   381  			}
   382  
   383  			sc, err := tracer.Extract(ot.HTTPHeaders, ot.HTTPHeadersCarrier(headers))
   384  			require.NoError(t, err)
   385  
   386  			assert.Equal(t, example.Expected, sc)
   387  		})
   388  	}
   389  }
   390  
   391  func TestTracer_Extract_HTTPHeaders_WithEUMCorrelation(t *testing.T) {
   392  	examples := map[string]struct {
   393  		Headers  map[string]string
   394  		Expected instana.SpanContext
   395  	}{
   396  		"tracing enabled, no instana headers": {
   397  			Headers: map[string]string{
   398  				"X-Instana-L": "1,correlationType=web;correlationId=1234",
   399  			},
   400  		},
   401  		"tracing enabled, with instana headers": {
   402  			Headers: map[string]string{
   403  				"X-Instana-T": "0000000000002435",
   404  				"X-Instana-S": "0000000000003546",
   405  				"X-Instana-L": "1,correlationType=web;correlationId=1234",
   406  			},
   407  		},
   408  	}
   409  
   410  	for name, example := range examples {
   411  		t.Run(name, func(t *testing.T) {
   412  			recorder := instana.NewTestRecorder()
   413  			tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   414  			defer instana.ShutdownSensor()
   415  
   416  			headers := http.Header{}
   417  			for k, v := range example.Headers {
   418  				headers.Set(k, v)
   419  			}
   420  
   421  			sc, err := tracer.Extract(ot.HTTPHeaders, ot.HTTPHeadersCarrier(headers))
   422  			require.NoError(t, err)
   423  
   424  			spanContext := sc.(instana.SpanContext)
   425  
   426  			assert.EqualValues(t, 0, spanContext.TraceID)
   427  			assert.EqualValues(t, 0, spanContext.SpanID)
   428  			assert.Empty(t, spanContext.ParentID)
   429  			assert.Equal(t, instana.EUMCorrelationData{ID: "1234", Type: "web"}, spanContext.Correlation)
   430  		})
   431  	}
   432  }
   433  
   434  func TestTracer_Extract_HTTPHeaders_NoContext(t *testing.T) {
   435  	recorder := instana.NewTestRecorder()
   436  	tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   437  	defer instana.ShutdownSensor()
   438  
   439  	headers := http.Header{
   440  		"Authorization": {"Basic 123"},
   441  	}
   442  
   443  	_, err := tracer.Extract(ot.HTTPHeaders, ot.HTTPHeadersCarrier(headers))
   444  	assert.Equal(t, ot.ErrSpanContextNotFound, err)
   445  }
   446  
   447  func TestTracer_Extract_HTTPHeaders_CorruptedContext(t *testing.T) {
   448  	examples := map[string]http.Header{
   449  		"missing trace id": {
   450  			"X-INSTANA-S": {"1314"},
   451  			"X-Instana-L": {"1"},
   452  		},
   453  		"missing span id": {
   454  			"x-instana-t": {"1314"},
   455  			"X-Instana-L": {"1"},
   456  		},
   457  		"malformed trace id": {
   458  			"x-instana-t": {"wrong"},
   459  			"X-INSTANA-S": {"1314"},
   460  			"X-Instana-L": {"1"},
   461  		},
   462  		"malformed span id": {
   463  			"x-instana-t": {"1314"},
   464  			"X-INSTANA-S": {"wrong"},
   465  			"X-Instana-L": {"1"},
   466  		},
   467  	}
   468  
   469  	for name, headers := range examples {
   470  		t.Run(name, func(t *testing.T) {
   471  			recorder := instana.NewTestRecorder()
   472  			tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   473  			defer instana.ShutdownSensor()
   474  
   475  			_, err := tracer.Extract(ot.HTTPHeaders, ot.HTTPHeadersCarrier(headers))
   476  			assert.Equal(t, ot.ErrSpanContextCorrupted, err)
   477  		})
   478  	}
   479  }
   480  
   481  func TestTracer_Inject_TextMap_AddValues(t *testing.T) {
   482  	recorder := instana.NewTestRecorder()
   483  	tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   484  	defer instana.ShutdownSensor()
   485  
   486  	sc := instana.SpanContext{
   487  		TraceIDHi: 0x1,
   488  		TraceID:   0x2435,
   489  		SpanID:    0x3546,
   490  		Baggage: map[string]string{
   491  			"foo": "bar",
   492  		},
   493  	}
   494  
   495  	carrier := map[string]string{
   496  		"key1": "value1",
   497  	}
   498  
   499  	require.NoError(t, tracer.Inject(sc, ot.TextMap, ot.TextMapCarrier(carrier)))
   500  
   501  	assert.Equal(t, map[string]string{
   502  		"x-instana-t":     "0000000000002435",
   503  		"x-instana-s":     "0000000000003546",
   504  		"x-instana-l":     "1",
   505  		"x-instana-b-foo": "bar",
   506  		"key1":            "value1",
   507  	}, carrier)
   508  }
   509  
   510  func TestTracer_Inject_TextMap_UpdateValues(t *testing.T) {
   511  	recorder := instana.NewTestRecorder()
   512  	tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   513  	defer instana.ShutdownSensor()
   514  
   515  	sc := instana.SpanContext{
   516  		TraceIDHi: 0x1,
   517  		TraceID:   0x2435,
   518  		SpanID:    0x3546,
   519  		Baggage: map[string]string{
   520  			"foo": "bar",
   521  		},
   522  	}
   523  
   524  	carrier := map[string]string{
   525  		"key1":            "value1",
   526  		"x-instana-t":     "0000000000001314",
   527  		"X-INSTANA-S":     "0000000000001314",
   528  		"X-Instana-L":     "1",
   529  		"X-INSTANA-b-foo": "hello",
   530  	}
   531  
   532  	require.NoError(t, tracer.Inject(sc, ot.TextMap, ot.TextMapCarrier(carrier)))
   533  
   534  	assert.Equal(t, map[string]string{
   535  		"x-instana-t":     "0000000000002435",
   536  		"X-INSTANA-S":     "0000000000003546",
   537  		"X-Instana-L":     "1",
   538  		"X-INSTANA-b-foo": "bar",
   539  		"key1":            "value1",
   540  	}, carrier)
   541  }
   542  
   543  func TestTracer_Inject_TextMap_SuppressedTracing(t *testing.T) {
   544  	recorder := instana.NewTestRecorder()
   545  	tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   546  	defer instana.ShutdownSensor()
   547  
   548  	sc := instana.SpanContext{
   549  		TraceIDHi:  0x1,
   550  		TraceID:    0x2435,
   551  		SpanID:     0x3546,
   552  		Suppressed: true,
   553  	}
   554  
   555  	carrier := map[string]string{
   556  		"key1":        "value1",
   557  		"x-instana-t": "0000000000001314",
   558  		"X-INSTANA-S": "0000000000001314",
   559  		"X-Instana-L": "1",
   560  	}
   561  
   562  	require.NoError(t, tracer.Inject(sc, ot.TextMap, ot.TextMapCarrier(carrier)))
   563  
   564  	assert.Equal(t, map[string]string{
   565  		"X-Instana-L": "0",
   566  		"key1":        "value1",
   567  	}, carrier)
   568  }
   569  
   570  func TestTracer_Extract_TextMap(t *testing.T) {
   571  	examples := map[string]struct {
   572  		Carrier  map[string]string
   573  		Expected instana.SpanContext
   574  	}{
   575  		"tracing enabled": {
   576  			Carrier: map[string]string{
   577  				"Authorization":   "Basic 123",
   578  				"x-instana-t":     "10000000000001314",
   579  				"X-INSTANA-S":     "2435",
   580  				"X-Instana-L":     "1",
   581  				"X-Instana-B-Foo": "bar",
   582  			},
   583  			Expected: instana.SpanContext{
   584  				TraceIDHi: 0x1,
   585  				TraceID:   0x1314,
   586  				SpanID:    0x2435,
   587  				Baggage: map[string]string{
   588  					"Foo": "bar",
   589  				},
   590  			},
   591  		},
   592  		"tracing disabled": {
   593  			Carrier: map[string]string{
   594  				"Authorization": "Basic 123",
   595  				"x-instana-t":   "10000000000001314",
   596  				"X-INSTANA-S":   "2435",
   597  				"X-Instana-L":   "0",
   598  			},
   599  			Expected: instana.SpanContext{
   600  				TraceIDHi:  0x1,
   601  				TraceID:    0x1314,
   602  				SpanID:     0x2435,
   603  				Suppressed: true,
   604  				Baggage:    map[string]string{},
   605  			},
   606  		},
   607  		"tracing disabled, no instana context": {
   608  			Carrier: map[string]string{
   609  				"Authorization": "Basic 123",
   610  				"X-Instana-L":   "0",
   611  			},
   612  			Expected: instana.SpanContext{
   613  				Suppressed: true,
   614  				Baggage:    map[string]string{},
   615  			},
   616  		},
   617  	}
   618  
   619  	for name, example := range examples {
   620  		t.Run(name, func(t *testing.T) {
   621  			recorder := instana.NewTestRecorder()
   622  			tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   623  			defer instana.ShutdownSensor()
   624  
   625  			sc, err := tracer.Extract(ot.TextMap, ot.TextMapCarrier(example.Carrier))
   626  			require.NoError(t, err)
   627  
   628  			assert.Equal(t, example.Expected, sc)
   629  		})
   630  	}
   631  }
   632  
   633  func TestTracer_Extract_TextMap_NoContext(t *testing.T) {
   634  	recorder := instana.NewTestRecorder()
   635  	tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   636  	defer instana.ShutdownSensor()
   637  
   638  	carrier := map[string]string{
   639  		"key": "value",
   640  	}
   641  
   642  	_, err := tracer.Extract(ot.TextMap, ot.TextMapCarrier(carrier))
   643  	assert.Equal(t, ot.ErrSpanContextNotFound, err)
   644  }
   645  
   646  func TestTracer_Extract_TextMap_CorruptedContext(t *testing.T) {
   647  	examples := map[string]map[string]string{
   648  		"missing trace id": {
   649  			"x-instana-s": "1314",
   650  			"x-instana-l": "1",
   651  		},
   652  		"missing span id": {
   653  			"x-instana-t": "1314",
   654  			"x-instana-l": "1",
   655  		},
   656  		"malformed trace id": {
   657  			"x-instana-t": "wrong",
   658  			"x-instana-s": "1314",
   659  			"x-instana-l": "1",
   660  		},
   661  		"malformed span id": {
   662  			"x-instana-t": "1314",
   663  			"x-instana-s": "wrong",
   664  			"x-instana-l": "1",
   665  		},
   666  	}
   667  
   668  	for name, carrier := range examples {
   669  		t.Run(name, func(t *testing.T) {
   670  			recorder := instana.NewTestRecorder()
   671  			tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   672  			defer instana.ShutdownSensor()
   673  
   674  			_, err := tracer.Extract(ot.TextMap, ot.TextMapCarrier(carrier))
   675  			assert.Equal(t, ot.ErrSpanContextCorrupted, err)
   676  		})
   677  	}
   678  }
   679  
   680  type textMapWithRemoveAll struct {
   681  	ot.TextMapCarrier
   682  }
   683  
   684  func (c *textMapWithRemoveAll) RemoveAll() {
   685  	for k := range c.TextMapCarrier {
   686  		delete(c.TextMapCarrier, k)
   687  	}
   688  }
   689  
   690  func TestTracer_Inject_CarrierWithRemoveAll_SuppressedTrace(t *testing.T) {
   691  	recorder := instana.NewTestRecorder()
   692  	tracer := instana.NewTracerWithEverything(&instana.Options{AgentClient: alwaysReadyClient{}}, recorder)
   693  	defer instana.ShutdownSensor()
   694  
   695  	sc := instana.SpanContext{
   696  		TraceIDHi:  0x1,
   697  		TraceID:    0x2435,
   698  		SpanID:     0x3546,
   699  		Suppressed: true,
   700  	}
   701  
   702  	carrier := map[string]string{
   703  		"x-instana-t": "0000000000001314",
   704  		"X-INSTANA-S": "0000000000001314",
   705  		"X-Instana-L": "1",
   706  	}
   707  
   708  	require.NoError(t, tracer.Inject(sc, ot.TextMap, &textMapWithRemoveAll{carrier}))
   709  
   710  	assert.Equal(t, map[string]string{
   711  		"X-Instana-L": "0",
   712  	}, carrier)
   713  }