github.com/waldiirawan/apm-agent-go/v2@v2.2.2/tracecontext_test.go (about) 1 // Licensed to Elasticsearch B.V. under one or more contributor 2 // license agreements. See the NOTICE file distributed with 3 // this work for additional information regarding copyright 4 // ownership. Elasticsearch B.V. licenses this file to you under 5 // the Apache License, Version 2.0 (the "License"); you may 6 // not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 package apm_test 19 20 import ( 21 "fmt" 22 "strings" 23 "testing" 24 25 "github.com/stretchr/testify/assert" 26 27 "github.com/waldiirawan/apm-agent-go/v2" 28 ) 29 30 func TestTraceID(t *testing.T) { 31 var id apm.TraceID 32 assert.EqualError(t, id.Validate(), "zero trace-id is invalid") 33 34 id[0] = 1 35 assert.NoError(t, id.Validate()) 36 } 37 38 func TestSpanID(t *testing.T) { 39 var id apm.SpanID 40 assert.EqualError(t, id.Validate(), "zero span-id is invalid") 41 42 id[0] = 1 43 assert.NoError(t, id.Validate()) 44 } 45 46 func TestTraceOptions(t *testing.T) { 47 opts := apm.TraceOptions(0xFE) 48 assert.False(t, opts.Recorded()) 49 50 opts = opts.WithRecorded(true) 51 assert.True(t, opts.Recorded()) 52 assert.Equal(t, apm.TraceOptions(0xFF), opts) 53 54 opts = opts.WithRecorded(false) 55 assert.False(t, opts.Recorded()) 56 assert.Equal(t, apm.TraceOptions(0xFE), opts) 57 } 58 59 func TestTraceStateInvalidLength(t *testing.T) { 60 const maxEntries = 32 61 62 entries := make([]apm.TraceStateEntry, 0, maxEntries) 63 for i := 0; i < cap(entries); i++ { 64 entries = append(entries, apm.TraceStateEntry{Key: fmt.Sprintf("k%d", i), Value: "value"}) 65 ts := apm.NewTraceState(entries...) 66 assert.NoError(t, ts.Validate()) 67 } 68 69 entries = append(entries, apm.TraceStateEntry{Key: "straw", Value: "camel's back"}) 70 ts := apm.NewTraceState(entries...) 71 assert.EqualError(t, ts.Validate(), "tracestate contains more than the maximum allowed number of entries, 32") 72 } 73 74 func TestTraceStateDuplicateKey(t *testing.T) { 75 // This test asserts: 76 // 1. Accept a tracestate with duplicate keys. 77 // 2. Use the last reference. 78 // 3. Discard any duplicate 'es' entries. 79 // 4. Keep any duplicate 3rd party system keys as is. 80 ts := apm.NewTraceState( 81 apm.TraceStateEntry{Key: "x", Value: "b"}, 82 apm.TraceStateEntry{Key: "a", Value: "b"}, 83 apm.TraceStateEntry{Key: "y", Value: "b"}, 84 apm.TraceStateEntry{Key: "a", Value: "c"}, 85 apm.TraceStateEntry{Key: "es", Value: "s:1;a:b"}, 86 apm.TraceStateEntry{Key: "z", Value: "w"}, 87 apm.TraceStateEntry{Key: "a", Value: "d"}, 88 apm.TraceStateEntry{Key: "es", Value: "s:0.5;k:v"}, 89 apm.TraceStateEntry{Key: "c", Value: "first"}, 90 apm.TraceStateEntry{Key: "r", Value: "first"}, 91 apm.TraceStateEntry{Key: "es", Value: "s:0.1;k:v"}, 92 apm.TraceStateEntry{Key: "c", Value: "second"}, 93 ) 94 assert.NoError(t, ts.Validate()) 95 assert.Equal(t, "es=s:0.1;k:v,x=b,a=b,y=b,a=c,z=w,a=d,c=first,r=first,c=second", ts.String()) 96 } 97 98 func TestTraceStateElasticEntryFirst(t *testing.T) { 99 ts := apm.NewTraceState( 100 apm.TraceStateEntry{Key: "es", Value: "s:1;a:b"}, 101 apm.TraceStateEntry{Key: "z", Value: "w"}, 102 apm.TraceStateEntry{Key: "a", Value: "d"}, 103 ) 104 assert.NoError(t, ts.Validate()) 105 assert.Equal(t, "es=s:1;a:b,z=w,a=d", ts.String()) 106 } 107 108 func TestTraceStateInvalidKey(t *testing.T) { 109 ts := apm.NewTraceState(apm.TraceStateEntry{Key: "~"}) 110 assert.EqualError(t, ts.Validate(), `invalid tracestate entry at position 0: invalid key "~"`) 111 } 112 113 func TestTraceStateInvalidValueLength(t *testing.T) { 114 ts := apm.NewTraceState(apm.TraceStateEntry{Key: "oy"}) 115 assert.EqualError(t, ts.Validate(), `invalid tracestate entry at position 0: invalid value for key "oy": value is empty`) 116 117 ts = apm.NewTraceState(apm.TraceStateEntry{Key: "oy", Value: strings.Repeat("*", 257)}) 118 assert.EqualError(t, ts.Validate(), 119 `invalid tracestate entry at position 0: invalid value for key "oy": value contains 257 characters, maximum allowed is 256`) 120 } 121 122 func TestTraceStateInvalidValueCharacter(t *testing.T) { 123 for _, value := range []string{ 124 string(rune(0)), 125 "header" + string(rune(0)) + "trailer", 126 } { 127 ts := apm.NewTraceState(apm.TraceStateEntry{Key: "oy", Value: value}) 128 assert.EqualError(t, ts.Validate(), 129 `invalid tracestate entry at position 0: invalid value for key "oy": value contains invalid character '\x00'`) 130 } 131 } 132 133 func TestTraceStateInvalidElasticEntry(t *testing.T) { 134 ts := apm.NewTraceState(apm.TraceStateEntry{Key: "es", Value: "foo"}) 135 assert.EqualError(t, ts.Validate(), `invalid tracestate entry at position 0: malformed 'es' tracestate entry`) 136 137 ts = apm.NewTraceState(apm.TraceStateEntry{Key: "es", Value: "s:foo"}) 138 assert.EqualError(t, ts.Validate(), `invalid tracestate entry at position 0: strconv.ParseFloat: parsing "foo": invalid syntax`) 139 140 ts = apm.NewTraceState(apm.TraceStateEntry{Key: "es", Value: "s:1.5"}) 141 assert.EqualError(t, ts.Validate(), `invalid tracestate entry at position 0: sample rate "1.5" out of range`) 142 }