1 package mocktracer
2
3 import (
4 "net/http"
5 "reflect"
6 "sync"
7 "testing"
8 "time"
9
10 "github.com/stretchr/testify/assert"
11 "github.com/stretchr/testify/require"
12
13 "github.com/opentracing/opentracing-go"
14 "github.com/opentracing/opentracing-go/ext"
15 "github.com/opentracing/opentracing-go/log"
16 )
17
18 func TestMockTracer_StartSpan(t *testing.T) {
19 tracer := New()
20 span1 := tracer.StartSpan(
21 "a",
22 opentracing.Tags(map[string]interface{}{"x": "y"}))
23
24 span2 := span1.Tracer().StartSpan(
25 "", opentracing.ChildOf(span1.Context()))
26 span2.Finish()
27 span1.Finish()
28 finishedSpans := tracer.FinishedSpans()
29 unfinishedSpans := tracer.UnfinishedSpans()
30 assert.Equal(t, 2, len(finishedSpans))
31 assert.Equal(t, 0, len(unfinishedSpans))
32
33 parent := finishedSpans[1]
34 child := finishedSpans[0]
35 assert.Equal(t, map[string]interface{}{"x": "y"}, parent.Tags())
36 assert.Equal(t, child.ParentID, parent.Context().(MockSpanContext).SpanID)
37 }
38
39 func TestMockSpan_SetOperationName(t *testing.T) {
40 tracer := New()
41 span := tracer.StartSpan("")
42 span.SetOperationName("x")
43 assert.Equal(t, "x", span.(*MockSpan).OperationName)
44 }
45
46 func TestMockSpanContext_Baggage(t *testing.T) {
47 tracer := New()
48 span := tracer.StartSpan("x")
49 span.SetBaggageItem("x", "y")
50 assert.Equal(t, "y", span.BaggageItem("x"))
51 assert.Equal(t, map[string]string{"x": "y"}, span.Context().(MockSpanContext).Baggage)
52
53 baggage := make(map[string]string)
54 span.Context().ForeachBaggageItem(func(k, v string) bool {
55 baggage[k] = v
56 return true
57 })
58 assert.Equal(t, map[string]string{"x": "y"}, baggage)
59
60 span.SetBaggageItem("a", "b")
61 baggage = make(map[string]string)
62 span.Context().ForeachBaggageItem(func(k, v string) bool {
63 baggage[k] = v
64 return false
65 })
66 assert.Equal(t, 2, len(span.Context().(MockSpanContext).Baggage))
67 assert.Equal(t, 1, len(baggage))
68 }
69
70 func TestMockSpan_Tag(t *testing.T) {
71 tracer := New()
72 span := tracer.StartSpan("x")
73 span.SetTag("x", "y")
74 assert.Equal(t, "y", span.(*MockSpan).Tag("x"))
75 }
76
77 func TestMockSpan_Tags(t *testing.T) {
78 tracer := New()
79 span := tracer.StartSpan("x")
80 span.SetTag("x", "y")
81 assert.Equal(t, map[string]interface{}{"x": "y"}, span.(*MockSpan).Tags())
82 }
83
84 func TestMockTracer_FinishedSpans_and_Reset(t *testing.T) {
85 tracer := New()
86 span := tracer.StartSpan("x")
87 span.SetTag("x", "y")
88 assert.Len(t, tracer.UnfinishedSpans(), 1)
89 span.Finish()
90 spans := tracer.FinishedSpans()
91 assert.Len(t, spans, 1)
92 assert.Len(t, tracer.UnfinishedSpans(), 0)
93 assert.Equal(t, map[string]interface{}{"x": "y"}, spans[0].Tags())
94
95 tracer.StartSpan("z")
96 tracer.Reset()
97 spans = tracer.FinishedSpans()
98 assert.Len(t, spans, 0)
99 assert.Len(t, tracer.UnfinishedSpans(), 0)
100 }
101
102 func zeroOutTimestamps(recs []MockLogRecord) {
103 for i := range recs {
104 recs[i].Timestamp = time.Time{}
105 }
106 }
107
108 func TestMockSpan_LogKV(t *testing.T) {
109 tracer := New()
110 span := tracer.StartSpan("s")
111 span.LogKV("key0", "string0")
112 span.LogKV("key1", "string1", "key2", uint32(42))
113 span.Finish()
114 spans := tracer.FinishedSpans()
115 assert.Equal(t, 1, len(spans))
116 actual := spans[0].Logs()
117 zeroOutTimestamps(actual)
118 assert.Equal(t, []MockLogRecord{
119 MockLogRecord{
120 Fields: []MockKeyValue{
121 MockKeyValue{Key: "key0", ValueKind: reflect.String, ValueString: "string0"},
122 },
123 },
124 MockLogRecord{
125 Fields: []MockKeyValue{
126 MockKeyValue{Key: "key1", ValueKind: reflect.String, ValueString: "string1"},
127 MockKeyValue{Key: "key2", ValueKind: reflect.Uint32, ValueString: "42"},
128 },
129 },
130 }, actual)
131 }
132
133 func TestMockSpan_LogFields(t *testing.T) {
134 tracer := New()
135 span := tracer.StartSpan("s")
136 span.LogFields(log.String("key0", "string0"))
137 span.LogFields(log.String("key1", "string1"), log.Uint32("key2", uint32(42)))
138 span.LogFields(log.Lazy(func(fv log.Encoder) {
139 fv.EmitInt("key_lazy", 12)
140 }))
141 span.FinishWithOptions(opentracing.FinishOptions{
142 LogRecords: []opentracing.LogRecord{
143 {Timestamp: time.Now(), Fields: []log.Field{log.String("key9", "finish")}},
144 }})
145 spans := tracer.FinishedSpans()
146 assert.Equal(t, 1, len(spans))
147 actual := spans[0].Logs()
148 zeroOutTimestamps(actual)
149 assert.Equal(t, []MockLogRecord{
150 MockLogRecord{
151 Fields: []MockKeyValue{
152 MockKeyValue{Key: "key0", ValueKind: reflect.String, ValueString: "string0"},
153 },
154 },
155 MockLogRecord{
156 Fields: []MockKeyValue{
157 MockKeyValue{Key: "key1", ValueKind: reflect.String, ValueString: "string1"},
158 MockKeyValue{Key: "key2", ValueKind: reflect.Uint32, ValueString: "42"},
159 },
160 },
161 MockLogRecord{
162 Fields: []MockKeyValue{
163
164 MockKeyValue{Key: "key_lazy", ValueKind: reflect.Int, ValueString: "12"},
165 },
166 },
167 MockLogRecord{
168 Fields: []MockKeyValue{
169 MockKeyValue{Key: "key9", ValueKind: reflect.String, ValueString: "finish"},
170 },
171 },
172 }, actual)
173 }
174
175 func TestMockSpan_DeprecatedLogs(t *testing.T) {
176 tracer := New()
177 span := tracer.StartSpan("x")
178 span.LogEvent("x")
179 span.LogEventWithPayload("y", "z")
180 span.LogEvent("a")
181 span.FinishWithOptions(opentracing.FinishOptions{
182 BulkLogData: []opentracing.LogData{{Event: "f"}}})
183 spans := tracer.FinishedSpans()
184 assert.Equal(t, 1, len(spans))
185 actual := spans[0].Logs()
186 zeroOutTimestamps(actual)
187 assert.Equal(t, []MockLogRecord{
188 MockLogRecord{
189 Fields: []MockKeyValue{
190 MockKeyValue{Key: "event", ValueKind: reflect.String, ValueString: "x"},
191 },
192 },
193 MockLogRecord{
194 Fields: []MockKeyValue{
195 MockKeyValue{Key: "event", ValueKind: reflect.String, ValueString: "y"},
196 MockKeyValue{Key: "payload", ValueKind: reflect.String, ValueString: "z"},
197 },
198 },
199 MockLogRecord{
200 Fields: []MockKeyValue{
201 MockKeyValue{Key: "event", ValueKind: reflect.String, ValueString: "a"},
202 },
203 },
204 MockLogRecord{
205 Fields: []MockKeyValue{
206 MockKeyValue{Key: "event", ValueKind: reflect.String, ValueString: "f"},
207 },
208 },
209 }, actual)
210 }
211
212 func TestMockTracer_Propagation(t *testing.T) {
213 textCarrier := func() interface{} {
214 return opentracing.TextMapCarrier(make(map[string]string))
215 }
216 textLen := func(c interface{}) int {
217 return len(c.(opentracing.TextMapCarrier))
218 }
219
220 httpCarrier := func() interface{} {
221 httpHeaders := http.Header(make(map[string][]string))
222 return opentracing.HTTPHeadersCarrier(httpHeaders)
223 }
224 httpLen := func(c interface{}) int {
225 return len(c.(opentracing.HTTPHeadersCarrier))
226 }
227
228 tests := []struct {
229 sampled bool
230 format opentracing.BuiltinFormat
231 carrier func() interface{}
232 len func(interface{}) int
233 }{
234 {sampled: true, format: opentracing.TextMap, carrier: textCarrier, len: textLen},
235 {sampled: false, format: opentracing.TextMap, carrier: textCarrier, len: textLen},
236 {sampled: true, format: opentracing.HTTPHeaders, carrier: httpCarrier, len: httpLen},
237 {sampled: false, format: opentracing.HTTPHeaders, carrier: httpCarrier, len: httpLen},
238 }
239 for _, test := range tests {
240 tracer := New()
241 span := tracer.StartSpan("x")
242 span.SetBaggageItem("x", "y:z")
243 if !test.sampled {
244 ext.SamplingPriority.Set(span, 0)
245 }
246 mSpan := span.(*MockSpan)
247
248 assert.Equal(t, opentracing.ErrUnsupportedFormat,
249 tracer.Inject(span.Context(), opentracing.Binary, nil))
250 assert.Equal(t, opentracing.ErrInvalidCarrier,
251 tracer.Inject(span.Context(), opentracing.TextMap, span))
252
253 carrier := test.carrier()
254
255 err := tracer.Inject(span.Context(), test.format, carrier)
256 require.NoError(t, err)
257 assert.Equal(t, 4, test.len(carrier), "expect baggage + 2 ids + sampled")
258 if test.format == opentracing.HTTPHeaders {
259 c := carrier.(opentracing.HTTPHeadersCarrier)
260 assert.Equal(t, "y%3Az", c["Mockpfx-Baggage-X"][0])
261 }
262
263 _, err = tracer.Extract(opentracing.Binary, nil)
264 assert.Equal(t, opentracing.ErrUnsupportedFormat, err)
265 _, err = tracer.Extract(opentracing.TextMap, tracer)
266 assert.Equal(t, opentracing.ErrInvalidCarrier, err)
267
268 extractedContext, err := tracer.Extract(test.format, carrier)
269 require.NoError(t, err)
270 assert.Equal(t, mSpan.SpanContext.TraceID, extractedContext.(MockSpanContext).TraceID)
271 assert.Equal(t, mSpan.SpanContext.SpanID, extractedContext.(MockSpanContext).SpanID)
272 assert.Equal(t, test.sampled, extractedContext.(MockSpanContext).Sampled)
273 assert.Equal(t, "y:z", extractedContext.(MockSpanContext).Baggage["x"])
274 }
275 }
276
277 func TestMockSpan_Races(t *testing.T) {
278 span := New().StartSpan("x")
279 var wg sync.WaitGroup
280 wg.Add(2)
281 go func() {
282 defer wg.Done()
283 span.SetBaggageItem("test_key", "test_value")
284 }()
285 go func() {
286 defer wg.Done()
287 span.Context()
288 }()
289 wg.Wait()
290 }
291
View as plain text