File: testtracer_test.go

package info (click to toggle)
golang-github-opentracing-opentracing-go 1.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, bullseye-backports, experimental
  • size: 268 kB
  • sloc: makefile: 18
file content (138 lines) | stat: -rw-r--r-- 3,889 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package opentracing

import (
	"strconv"
	"strings"
	"time"

	"github.com/opentracing/opentracing-go/log"
)

const testHTTPHeaderPrefix = "testprefix-"

// testTracer is a most-noop Tracer implementation that makes it possible for
// unittests to verify whether certain methods were / were not called.
type testTracer struct{}

var fakeIDSource = 1

func nextFakeID() int {
	fakeIDSource++
	return fakeIDSource
}

type testSpanContext struct {
	HasParent bool
	FakeID    int
}

func (n testSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {}

type testSpan struct {
	spanContext   testSpanContext
	OperationName string
	StartTime     time.Time
	Tags          map[string]interface{}
}

func (n testSpan) Equal(os Span) bool {
	other, ok := os.(testSpan)
	if !ok {
		return false
	}
	if n.spanContext != other.spanContext {
		return false
	}
	if n.OperationName != other.OperationName {
		return false
	}
	if !n.StartTime.Equal(other.StartTime) {
		return false
	}
	if len(n.Tags) != len(other.Tags) {
		return false
	}

	for k, v := range n.Tags {
		if ov, ok := other.Tags[k]; !ok || ov != v {
			return false
		}
	}

	return true
}

// testSpan:
func (n testSpan) Context() SpanContext                                  { return n.spanContext }
func (n testSpan) SetTag(key string, value interface{}) Span             { return n }
func (n testSpan) Finish()                                               {}
func (n testSpan) FinishWithOptions(opts FinishOptions)                  {}
func (n testSpan) LogFields(fields ...log.Field)                         {}
func (n testSpan) LogKV(kvs ...interface{})                              {}
func (n testSpan) SetOperationName(operationName string) Span            { return n }
func (n testSpan) Tracer() Tracer                                        { return testTracer{} }
func (n testSpan) SetBaggageItem(key, val string) Span                   { return n }
func (n testSpan) BaggageItem(key string) string                         { return "" }
func (n testSpan) LogEvent(event string)                                 {}
func (n testSpan) LogEventWithPayload(event string, payload interface{}) {}
func (n testSpan) Log(data LogData)                                      {}

// StartSpan belongs to the Tracer interface.
func (n testTracer) StartSpan(operationName string, opts ...StartSpanOption) Span {
	sso := StartSpanOptions{}
	for _, o := range opts {
		o.Apply(&sso)
	}
	return n.startSpanWithOptions(operationName, sso)
}

func (n testTracer) startSpanWithOptions(name string, opts StartSpanOptions) Span {
	fakeID := nextFakeID()
	if len(opts.References) > 0 {
		fakeID = opts.References[0].ReferencedContext.(testSpanContext).FakeID
	}

	return testSpan{
		OperationName: name,
		StartTime:     opts.StartTime,
		Tags:          opts.Tags,
		spanContext: testSpanContext{
			HasParent: len(opts.References) > 0,
			FakeID:    fakeID,
		},
	}
}

// Inject belongs to the Tracer interface.
func (n testTracer) Inject(sp SpanContext, format interface{}, carrier interface{}) error {
	spanContext := sp.(testSpanContext)
	switch format {
	case HTTPHeaders, TextMap:
		carrier.(TextMapWriter).Set(testHTTPHeaderPrefix+"fakeid", strconv.Itoa(spanContext.FakeID))
		return nil
	}
	return ErrUnsupportedFormat
}

// Extract belongs to the Tracer interface.
func (n testTracer) Extract(format interface{}, carrier interface{}) (SpanContext, error) {
	switch format {
	case HTTPHeaders, TextMap:
		// Just for testing purposes... generally not a worthwhile thing to
		// propagate.
		sm := testSpanContext{}
		err := carrier.(TextMapReader).ForeachKey(func(key, val string) error {
			switch strings.ToLower(key) {
			case testHTTPHeaderPrefix + "fakeid":
				i, err := strconv.Atoi(val)
				if err != nil {
					return err
				}
				sm.FakeID = i
			}
			return nil
		})
		return sm, err
	}
	return nil, ErrSpanContextNotFound
}