Skip to content

Commit 63ae45b

Browse files
committed
add more test cases for traceContext extraction.
1 parent 6fb763f commit 63ae45b

File tree

2 files changed

+129
-12
lines changed

2 files changed

+129
-12
lines changed

propagation/http_trace_context_propagator.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"context"
1919
"encoding/hex"
2020
"fmt"
21+
"regexp"
2122
"strconv"
2223
"strings"
2324

@@ -36,6 +37,7 @@ const (
3637
type httpTraceContextPropagator struct{}
3738

3839
var _ apipropagation.TextFormatPropagator = httpTraceContextPropagator{}
40+
var traceCtxRegExp = regexp.MustCompile("^[0-9a-f]{2}-[a-f0-9]{32}-[a-f0-9]{16}-[a-f0-9]{2}")
3941

4042
func (hp httpTraceContextPropagator) Inject(ctx context.Context, supplier apipropagation.Supplier) {
4143
sc := trace.CurrentSpan(ctx).SpanContext()
@@ -56,6 +58,11 @@ func (hp httpTraceContextPropagator) Extract(ctx context.Context, supplier apipr
5658
return core.EmptySpanContext()
5759
}
5860

61+
if !traceCtxRegExp.MatchString(h) {
62+
fmt.Printf("header does not match regex %s\n", h)
63+
return core.EmptySpanContext()
64+
}
65+
5966
sections := strings.Split(h, "-")
6067
if len(sections) < 4 {
6168
return core.EmptySpanContext()
@@ -104,11 +111,14 @@ func (hp httpTraceContextPropagator) Extract(ctx context.Context, supplier apipr
104111
}
105112
sc.SpanID = result
106113

114+
if len(sections[3]) != 2 {
115+
return core.EmptySpanContext()
116+
}
107117
opts, err := hex.DecodeString(sections[3])
108-
if err != nil || len(opts) < 1 {
118+
if err != nil || len(opts) < 1 || (version == 0 && opts[0] > 2) {
109119
return core.EmptySpanContext()
110120
}
111-
sc.TraceOptions = opts[0]
121+
sc.TraceOptions = opts[0] &^ core.TraceOptionUnused
112122

113123
if !sc.IsValid() {
114124
return core.EmptySpanContext()

propagation/http_trace_context_propagator_test.go

Lines changed: 117 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,31 @@ var (
3333
spanID = uint64(0x00f067aa0ba902b7)
3434
)
3535

36-
func TestExtractTraceContextFromHTTPReq(t *testing.T) {
36+
func TestExtractValidTraceContextFromHTTPReq(t *testing.T) {
3737
trace.SetGlobalTracer(&mocktrace.MockTracer{})
3838
propagator := propagation.HttpTraceContextPropagator()
3939
tests := []struct {
4040
name string
4141
header string
4242
wantSc core.SpanContext
4343
}{
44+
{
45+
name: "valid header",
46+
header: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00",
47+
wantSc: core.SpanContext{
48+
TraceID: traceID,
49+
SpanID: spanID,
50+
},
51+
},
52+
{
53+
name: "valid header and sampled",
54+
header: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
55+
wantSc: core.SpanContext{
56+
TraceID: traceID,
57+
SpanID: spanID,
58+
TraceOptions: core.TraceOptionSampled,
59+
},
60+
},
4461
{
4562
name: "future version",
4663
header: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
@@ -51,28 +68,118 @@ func TestExtractTraceContextFromHTTPReq(t *testing.T) {
5168
},
5269
},
5370
{
54-
name: "zero trace ID and span ID",
55-
header: "00-00000000000000000000000000000000-0000000000000000-01",
56-
wantSc: core.EmptySpanContext(),
71+
name: "future options with sampled bit set",
72+
header: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-09",
73+
wantSc: core.SpanContext{
74+
TraceID: traceID,
75+
SpanID: spanID,
76+
TraceOptions: core.TraceOptionSampled,
77+
},
5778
},
5879
{
59-
name: "valid header",
60-
header: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
80+
name: "future options with sampled bit cleared",
81+
header: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-08",
82+
wantSc: core.SpanContext{
83+
TraceID: traceID,
84+
SpanID: spanID,
85+
},
86+
},
87+
{
88+
name: "future additional data",
89+
header: "02-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-09-XYZxsf09",
6190
wantSc: core.SpanContext{
6291
TraceID: traceID,
6392
SpanID: spanID,
6493
TraceOptions: core.TraceOptionSampled,
6594
},
6695
},
96+
}
97+
98+
for _, tt := range tests {
99+
t.Run(tt.name, func(t *testing.T) {
100+
req, _ := http.NewRequest("GET", "http://example.com", nil)
101+
req.Header.Set("traceparent", tt.header)
102+
103+
ctx := context.Background()
104+
gotSc := propagator.Extract(ctx, req.Header)
105+
if diff := cmp.Diff(gotSc, tt.wantSc); diff != "" {
106+
t.Errorf("Extract Tracecontext: %s: -got +want %s", tt.name, diff)
107+
}
108+
})
109+
}
110+
}
111+
112+
func TestExtractInvalidTraceContextFromHTTPReq(t *testing.T) {
113+
trace.SetGlobalTracer(&mocktrace.MockTracer{})
114+
propagator := propagation.HttpTraceContextPropagator()
115+
wantSc := core.EmptySpanContext()
116+
tests := []struct {
117+
name string
118+
header string
119+
}{
120+
{
121+
name: "wrong version length",
122+
header: "0000-00000000000000000000000000000000-0000000000000000-01",
123+
},
124+
{
125+
name: "wrong trace ID length",
126+
header: "00-ab00000000000000000000000000000000-cd00000000000000-01",
127+
},
128+
{
129+
name: "wrong span ID length",
130+
header: "00-ab000000000000000000000000000000-cd0000000000000000-01",
131+
},
132+
{
133+
name: "wrong trace flag length",
134+
header: "00-ab000000000000000000000000000000-cd00000000000000-0100",
135+
},
136+
{
137+
name: "bogus version length",
138+
header: "qw-00000000000000000000000000000000-0000000000000000-01",
139+
},
140+
{
141+
name: "bogus trace ID length",
142+
header: "00-qw000000000000000000000000000000-cd00000000000000-01",
143+
},
144+
{
145+
name: "bogus span ID length",
146+
header: "00-ab000000000000000000000000000000-qw00000000000000-01",
147+
},
148+
{
149+
name: "bogus trace flag length",
150+
header: "00-ab000000000000000000000000000000-cd00000000000000-qw",
151+
},
152+
{
153+
name: "upper case version length",
154+
header: "A0-00000000000000000000000000000000-0000000000000000-01",
155+
},
156+
{
157+
name: "upper case trace ID length",
158+
header: "00-AB000000000000000000000000000000-cd00000000000000-01",
159+
},
160+
{
161+
name: "upper case span ID length",
162+
header: "00-ab000000000000000000000000000000-CD00000000000000-01",
163+
},
164+
{
165+
name: "upper case trace flag length",
166+
header: "00-ab000000000000000000000000000000-cd00000000000000-A1",
167+
},
168+
{
169+
name: "zero trace ID and span ID",
170+
header: "00-00000000000000000000000000000000-0000000000000000-01",
171+
},
172+
{
173+
name: "trace-flag unused bits set",
174+
header: "00-ab000000000000000000000000000000-cd00000000000000-09",
175+
},
67176
{
68177
name: "missing options",
69178
header: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7",
70-
wantSc: core.EmptySpanContext(),
71179
},
72180
{
73181
name: "empty options",
74182
header: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-",
75-
wantSc: core.EmptySpanContext(),
76183
},
77184
}
78185

@@ -83,7 +190,7 @@ func TestExtractTraceContextFromHTTPReq(t *testing.T) {
83190

84191
ctx := context.Background()
85192
gotSc := propagator.Extract(ctx, req.Header)
86-
if diff := cmp.Diff(gotSc, tt.wantSc); diff != "" {
193+
if diff := cmp.Diff(gotSc, wantSc); diff != "" {
87194
t.Errorf("Extract Tracecontext: %s: -got +want %s", tt.name, diff)
88195
}
89196
})
@@ -149,4 +256,4 @@ func TestHttpTraceContextPropagator_GetAllKeys(t *testing.T) {
149256
if diff := cmp.Diff(got, want); diff != "" {
150257
t.Errorf("GetAllKeys: -got +want %s", diff)
151258
}
152-
}
259+
}

0 commit comments

Comments
 (0)