Skip to content
This repository was archived by the owner on Nov 7, 2022. It is now read-only.

Commit 68cae62

Browse files
author
Bogdan Drutu
authored
Add tests for [trace|span]_id conversion from ints, and change code t… (#468)
* Add tests for [trace|span]_id conversion from ints, and change code to use this. * Add tests for the returned errors. * Fix comments for public functions in big_endian_convertor. * Fix typo.
1 parent 36103bb commit 68cae62

File tree

11 files changed

+247
-123
lines changed

11 files changed

+247
-123
lines changed

exporter/zipkinexporter/zipkin.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ package zipkinexporter
1616

1717
import (
1818
"context"
19-
"encoding/binary"
2019
"fmt"
2120
"net"
2221
"strconv"
2322
"sync"
2423
"time"
2524

25+
tracetranslator "github.com/census-instrumentation/opencensus-service/translator/trace"
26+
2627
zipkinmodel "github.com/openzipkin/zipkin-go/model"
2728
zipkinreporter "github.com/openzipkin/zipkin-go/reporter"
2829
zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http"
@@ -276,14 +277,13 @@ func canonicalCodeString(code int32) string {
276277
}
277278

278279
func convertTraceID(t trace.TraceID) zipkinmodel.TraceID {
279-
return zipkinmodel.TraceID{
280-
High: binary.BigEndian.Uint64(t[:8]),
281-
Low: binary.BigEndian.Uint64(t[8:]),
282-
}
280+
h, l, _ := tracetranslator.BytesToUInt64TraceID(t[:])
281+
return zipkinmodel.TraceID{High: h, Low: l}
283282
}
284283

285284
func convertSpanID(s trace.SpanID) zipkinmodel.ID {
286-
return zipkinmodel.ID(binary.BigEndian.Uint64(s[:]))
285+
id, _ := tracetranslator.BytesToUInt64SpanID(s[:])
286+
return zipkinmodel.ID(id)
287287
}
288288

289289
func spanKind(s *trace.SpanData) zipkinmodel.Kind {

internal/collector/processor/idbatcher/id_batcher_test.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
package idbatcher
1616

1717
import (
18-
"encoding/binary"
1918
"runtime"
2019
"sync"
2120
"sync/atomic"
2221
"testing"
2322
"time"
23+
24+
tracetranslator "github.com/census-instrumentation/opencensus-service/translator/trace"
2425
)
2526

2627
func TestBatcherNew(t *testing.T) {
@@ -155,9 +156,7 @@ func concurrencyTest(t *testing.T, numBatches, newBatchesInitialCapacity, batchC
155156
func generateSequentialIds(numIds uint64) [][]byte {
156157
ids := make([][]byte, numIds, numIds)
157158
for i := uint64(0); i < numIds; i++ {
158-
dst := make([]byte, 16, 16)
159-
binary.BigEndian.PutUint64(dst, i)
160-
ids[i] = dst
159+
ids[i] = tracetranslator.UInt64ToByteTraceID(0, i)
161160
}
162161
return ids
163162
}

internal/collector/processor/tailsampling/processor_test.go

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,18 @@
1515
package tailsampling
1616

1717
import (
18-
"encoding/binary"
1918
"sync"
2019
"testing"
2120
"time"
2221

2322
"github.com/census-instrumentation/opencensus-service/data"
2423
"github.com/census-instrumentation/opencensus-service/internal/collector/processor"
2524
"github.com/census-instrumentation/opencensus-service/internal/collector/processor/idbatcher"
25+
"github.com/census-instrumentation/opencensus-service/internal/collector/sampling"
26+
tracetranslator "github.com/census-instrumentation/opencensus-service/translator/trace"
2627

2728
tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1"
2829
"go.uber.org/zap"
29-
30-
"github.com/census-instrumentation/opencensus-service/internal/collector/sampling"
3130
)
3231

3332
const (
@@ -171,7 +170,7 @@ func TestSamplingPolicyTypicalPath(t *testing.T) {
171170
func generateIdsAndBatches(numIds int) ([][]byte, []data.TraceData) {
172171
traceIds := make([][]byte, numIds, numIds)
173172
for i := 0; i < numIds; i++ {
174-
traceIds[i] = indexToTraceID(i + 1)
173+
traceIds[i] = tracetranslator.UInt64ToByteTraceID(1, uint64(i+1))
175174
}
176175

177176
tds := []data.TraceData{}
@@ -180,7 +179,7 @@ func generateIdsAndBatches(numIds int) ([][]byte, []data.TraceData) {
180179
for j := range spans {
181180
spans[j] = &tracepb.Span{
182181
TraceId: traceIds[i],
183-
SpanId: indexToSpanID(i + 1),
182+
SpanId: tracetranslator.UInt64ToByteSpanID(uint64(i + 1)),
184183
}
185184
}
186185

@@ -287,16 +286,3 @@ func (p *mockSpanProcessor) ProcessSpans(td data.TraceData, spanFormat string) e
287286
p.TotalSpans += batchSize
288287
return nil
289288
}
290-
291-
func indexToTraceID(low int) []byte {
292-
traceID := make([]byte, 16)
293-
binary.BigEndian.PutUint64(traceID[:8], 1)
294-
binary.BigEndian.PutUint64(traceID[8:], uint64(low))
295-
return traceID
296-
}
297-
298-
func indexToSpanID(id int) []byte {
299-
spanID := make([]byte, 8)
300-
binary.BigEndian.PutUint64(spanID, uint64(id))
301-
return spanID
302-
}

receiver/zipkinreceiver/trace_receiver.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"compress/gzip"
1919
"compress/zlib"
2020
"context"
21-
"encoding/binary"
2221
"encoding/json"
2322
"errors"
2423
"fmt"
@@ -43,6 +42,7 @@ import (
4342
"github.com/census-instrumentation/opencensus-service/observability"
4443
"github.com/census-instrumentation/opencensus-service/processor"
4544
"github.com/census-instrumentation/opencensus-service/receiver"
45+
tracetranslator "github.com/census-instrumentation/opencensus-service/translator/trace"
4646
zipkintranslator "github.com/census-instrumentation/opencensus-service/translator/trace/zipkin"
4747
)
4848

@@ -344,19 +344,14 @@ func zTraceIDToOCProtoTraceID(zTraceID zipkinmodel.TraceID) ([]byte, error) {
344344
if zTraceID.High == 0 && zTraceID.Low == 0 {
345345
return nil, errZeroTraceID
346346
}
347-
traceID := make([]byte, 16)
348-
binary.BigEndian.PutUint64(traceID[:8], uint64(zTraceID.High))
349-
binary.BigEndian.PutUint64(traceID[8:], uint64(zTraceID.Low))
350-
return traceID, nil
347+
return tracetranslator.UInt64ToByteTraceID(zTraceID.High, zTraceID.Low), nil
351348
}
352349

353350
func zSpanIDToOCProtoSpanID(id zipkinmodel.ID) ([]byte, error) {
354351
if id == 0 {
355352
return nil, errZeroID
356353
}
357-
spanID := make([]byte, 8)
358-
binary.BigEndian.PutUint64(spanID, uint64(id))
359-
return spanID, nil
354+
return tracetranslator.UInt64ToByteSpanID(uint64(id)), nil
360355
}
361356

362357
func zipkinSpanToTraceSpan(zs *zipkinmodel.SpanModel) (*tracepb.Span, *commonpb.Node, error) {

translator/trace/big_endian_converter.go

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,89 @@ package tracetranslator
1616

1717
import (
1818
"encoding/binary"
19+
"errors"
1920
)
2021

21-
// Int64TraceIDToByteTraceID takes a long representaition of a trace id
22-
// and converts it to a []byte representation.
23-
func Int64TraceIDToByteTraceID(high, low int64) []byte {
22+
var (
23+
// ErrNilTraceID error returned when the TraceID is nil
24+
ErrNilTraceID = errors.New("TraceID is nil")
25+
// ErrWrongLenTraceID error returned when the TraceID does not have 16 bytes.
26+
ErrWrongLenTraceID = errors.New("TraceID does not have 16 bytes")
27+
// ErrNilSpanID error returned when the SpanID is nil
28+
ErrNilSpanID = errors.New("SpanID is nil")
29+
// ErrWrongLenSpanID error returned when the SpanID does not have 8 bytes.
30+
ErrWrongLenSpanID = errors.New("SpanID does not have 8 bytes")
31+
)
32+
33+
// UInt64ToByteTraceID takes a two uint64 representation of a TraceID and
34+
// converts it to a []byte representation.
35+
func UInt64ToByteTraceID(high, low uint64) []byte {
2436
if high == 0 && low == 0 {
2537
return nil
2638
}
2739
traceID := make([]byte, 16)
28-
binary.BigEndian.PutUint64(traceID[:8], uint64(high))
29-
binary.BigEndian.PutUint64(traceID[8:], uint64(low))
40+
binary.BigEndian.PutUint64(traceID[:8], high)
41+
binary.BigEndian.PutUint64(traceID[8:], low)
3042
return traceID
3143
}
3244

33-
// Int64SpanIDToByteSpanID takes a long representation of a span id and
45+
// Int64ToByteTraceID takes a two int64 representation of a TraceID and
3446
// converts it to a []byte representation.
35-
func Int64SpanIDToByteSpanID(id int64) []byte {
47+
func Int64ToByteTraceID(high, low int64) []byte {
48+
return UInt64ToByteTraceID(uint64(high), uint64(low))
49+
}
50+
51+
// BytesToUInt64TraceID takes a []byte representation of a TraceID and
52+
// converts it to a two uint64 representation.
53+
func BytesToUInt64TraceID(traceID []byte) (uint64, uint64, error) {
54+
if traceID == nil {
55+
return 0, 0, ErrNilTraceID
56+
}
57+
if len(traceID) != 16 {
58+
return 0, 0, ErrWrongLenTraceID
59+
}
60+
return binary.BigEndian.Uint64(traceID[:8]), binary.BigEndian.Uint64(traceID[8:]), nil
61+
}
62+
63+
// BytesToInt64TraceID takes a []byte representation of a TraceID and
64+
// converts it to a two int64 representation.
65+
func BytesToInt64TraceID(traceID []byte) (int64, int64, error) {
66+
traceIDHigh, traceIDLow, err := BytesToUInt64TraceID(traceID)
67+
return int64(traceIDHigh), int64(traceIDLow), err
68+
}
69+
70+
// UInt64ToByteSpanID takes a uint64 representation of a SpanID and
71+
// converts it to a []byte representation.
72+
func UInt64ToByteSpanID(id uint64) []byte {
3673
if id == 0 {
3774
return nil
3875
}
3976
spanID := make([]byte, 8)
40-
binary.BigEndian.PutUint64(spanID, uint64(id))
77+
binary.BigEndian.PutUint64(spanID, id)
4178
return spanID
4279
}
80+
81+
// Int64ToByteSpanID takes a int64 representation of a SpanID and
82+
// converts it to a []byte representation.
83+
func Int64ToByteSpanID(id int64) []byte {
84+
return UInt64ToByteSpanID(uint64(id))
85+
}
86+
87+
// BytesToUInt64SpanID takes a []byte representation of a SpanID and
88+
// converts it to a uint64 representation.
89+
func BytesToUInt64SpanID(b []byte) (uint64, error) {
90+
if b == nil {
91+
return 0, ErrNilSpanID
92+
}
93+
if len(b) != 8 {
94+
return 0, ErrWrongLenSpanID
95+
}
96+
return binary.BigEndian.Uint64(b), nil
97+
}
98+
99+
// BytesToInt64SpanID takes a []byte representation of a SpanID and
100+
// converts it to a int64 representation.
101+
func BytesToInt64SpanID(b []byte) (int64, error) {
102+
id, err := BytesToUInt64SpanID(b)
103+
return int64(id), err
104+
}

translator/trace/big_endian_converter_test.go

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,140 @@
1313
// limitations under the License.
1414

1515
package tracetranslator
16+
17+
import (
18+
"math"
19+
"reflect"
20+
"testing"
21+
)
22+
23+
func TestUInt64ToBytesTraceIDConversion(t *testing.T) {
24+
if nil != UInt64ToByteTraceID(0, 0) {
25+
t.Errorf("Failed to convert 0 TraceID:\n\tGot: %v\nWant: nil", UInt64ToByteTraceID(0, 0))
26+
}
27+
assertEqual(t, UInt64ToByteTraceID(256*256+256+1, 256+1),
28+
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01},
29+
"Failed simple conversion:")
30+
assertEqual(t, UInt64ToByteTraceID(0, 5),
31+
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05},
32+
"Failed to convert 0 high:")
33+
assertEqual(t, UInt64ToByteTraceID(5, 0),
34+
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
35+
"Failed to convert 0 low:")
36+
assertEqual(t, UInt64ToByteTraceID(math.MaxUint64, 5),
37+
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05},
38+
"Failed to convert MaxUint64:")
39+
}
40+
41+
func TestInt64ToBytesTraceIDConversion(t *testing.T) {
42+
if nil != Int64ToByteTraceID(0, 0) {
43+
t.Errorf("Failed to convert 0 TraceID:\n\tGot: %v\nWant: nil", Int64ToByteTraceID(0, 0))
44+
}
45+
assertEqual(t, Int64ToByteTraceID(0, -1),
46+
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
47+
"Failed to convert negative low:")
48+
assertEqual(t, Int64ToByteTraceID(-2, 5),
49+
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05},
50+
"Failed to convert negative high:")
51+
assertEqual(t, Int64ToByteTraceID(5, math.MinInt64),
52+
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
53+
"Failed to convert MinInt64:")
54+
}
55+
56+
func TestBytesToUInt64TraceIDErrors(t *testing.T) {
57+
if _, _, err := BytesToUInt64TraceID(nil); err != ErrNilTraceID {
58+
t.Errorf("Got: %v\nWant: %v", err, ErrNilTraceID)
59+
}
60+
longTraceID := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00}
61+
if _, _, err := BytesToUInt64TraceID(longTraceID); err != ErrWrongLenTraceID {
62+
t.Errorf("Got: %v\nWant: %v", err, ErrWrongLenTraceID)
63+
}
64+
}
65+
66+
func TestUInt64ToBytesSpanIDConversion(t *testing.T) {
67+
if nil != UInt64ToByteSpanID(0) {
68+
t.Errorf("Failed to convert 0 SpanID:\n\tGot: %v\nWant: nil", UInt64ToByteSpanID(0))
69+
}
70+
assertEqual(t, UInt64ToByteSpanID(256*256+256+1),
71+
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01},
72+
"Failed simple conversion:")
73+
assertEqual(t, UInt64ToByteSpanID(math.MaxUint64),
74+
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
75+
"Failed to convert MaxUint64:")
76+
}
77+
78+
func TestInt64ToBytesSpanIDConversion(t *testing.T) {
79+
if nil != Int64ToByteSpanID(0) {
80+
t.Errorf("Failed to convert 0 SpanID:\n\tGot: %v\nWant: nil", Int64ToByteSpanID(0))
81+
}
82+
assertEqual(t, Int64ToByteSpanID(5),
83+
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05},
84+
"Failed to convert positive id:")
85+
assertEqual(t, Int64ToByteSpanID(-1),
86+
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
87+
"Failed to convert negative id:")
88+
assertEqual(t, Int64ToByteSpanID(math.MinInt64),
89+
[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
90+
"Failed to convert MinInt64:")
91+
}
92+
93+
func TestBytesToUInt64SpanIDErrors(t *testing.T) {
94+
if _, err := BytesToUInt64SpanID(nil); err != ErrNilSpanID {
95+
t.Errorf("Got: %v\nWant: %v", err, ErrNilSpanID)
96+
}
97+
if _, err := BytesToUInt64SpanID([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}); err != ErrWrongLenSpanID {
98+
t.Errorf("Got: %v\nWant: %v", err, ErrWrongLenSpanID)
99+
}
100+
}
101+
102+
func TestTraceIDInt64RoundTrip(t *testing.T) {
103+
wh := int64(0x70605040302010FF)
104+
wl := int64(0x0001020304050607)
105+
gh, gl, err := BytesToInt64TraceID(Int64ToByteTraceID(wh, wl))
106+
if err != nil {
107+
t.Errorf("Error converting from bytes TraceID: %v", err)
108+
}
109+
if gh != wh || gl != wl {
110+
t.Errorf("Round trip of TraceID failed:\n\tGot: (0x%0x, 0x%0x)\n\tWant: (0x%0x, 0x%0x)", gl, gh, wl, wh)
111+
}
112+
}
113+
114+
func TestTraceIDUInt64RoundTrip(t *testing.T) {
115+
wh := uint64(0x70605040302010FF)
116+
wl := uint64(0x0001020304050607)
117+
gh, gl, err := BytesToUInt64TraceID(UInt64ToByteTraceID(wh, wl))
118+
if err != nil {
119+
t.Errorf("Error converting from bytes TraceID: %v", err)
120+
}
121+
if gl != wl || gh != wh {
122+
t.Errorf("Round trip of TraceID failed:\n\tGot: (0x%0x, 0x%0x)\n\tWant: (0x%0x, 0x%0x)", gl, gh, wl, wh)
123+
}
124+
}
125+
126+
func TestSpanIdInt64RoundTrip(t *testing.T) {
127+
w := int64(0x0001020304050607)
128+
g, err := BytesToInt64SpanID(Int64ToByteSpanID(w))
129+
if err != nil {
130+
t.Errorf("Error converting from OC span id: %v", err)
131+
}
132+
if g != w {
133+
t.Errorf("Round trip of SpanId failed:\n\tGot: 0x%0x\n\tWant: 0x%0x", g, w)
134+
}
135+
}
136+
137+
func TestSpanIdUInt64RoundTrip(t *testing.T) {
138+
w := uint64(0x0001020304050607)
139+
g, err := BytesToUInt64SpanID(UInt64ToByteSpanID(w))
140+
if err != nil {
141+
t.Errorf("Error converting from OC span id: %v", err)
142+
}
143+
if g != w {
144+
t.Errorf("Round trip of SpanId failed:\n\tGot: 0x%0x\n\tWant: 0x%0x", g, w)
145+
}
146+
}
147+
148+
func assertEqual(t *testing.T, got []byte, want []byte, em string) {
149+
if !reflect.DeepEqual(got, want) {
150+
t.Errorf("%s\n\tGot: %v\n\tWant: %v\n", em, got, want)
151+
}
152+
}

0 commit comments

Comments
 (0)