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  }