github.com/instana/go-sensor@v1.62.2-0.20240520081010-4919868049e1/w3ctrace/state_test.go (about)

     1  // (c) Copyright IBM Corp. 2021
     2  // (c) Copyright Instana Inc. 2020
     3  
     4  package w3ctrace_test
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/instana/go-sensor/w3ctrace"
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  const maxKVPairs = 32
    17  
    18  func TestParseState(t *testing.T) {
    19  
    20  	examples := map[string]struct {
    21  		Header   string
    22  		Expected w3ctrace.State
    23  	}{
    24  		"empty": {
    25  			Expected: w3ctrace.NewState([]string{}, ""),
    26  		},
    27  		"single tracing system": {
    28  			Header:   "rojo=00f067aa0ba902b7",
    29  			Expected: w3ctrace.NewState([]string{"rojo=00f067aa0ba902b7"}, ""),
    30  		},
    31  		"multiple tracing systems": {
    32  			Header:   "rojo=00f067aa0ba902b7,congo=t61rcWkgMzE",
    33  			Expected: w3ctrace.NewState([]string{"rojo=00f067aa0ba902b7", "congo=t61rcWkgMzE"}, ""),
    34  		},
    35  		"only an Instana list member": {
    36  			Header:   "in=fa2375d711a4ca0f;02468acefdb97531",
    37  			Expected: w3ctrace.NewState([]string{}, "fa2375d711a4ca0f;02468acefdb97531"),
    38  		},
    39  		"one other and one Instana list member": {
    40  			Header:   "rojo=00f067aa0ba902b7,in=fa2375d711a4ca0f;02468acefdb97531",
    41  			Expected: w3ctrace.NewState([]string{"rojo=00f067aa0ba902b7"}, "fa2375d711a4ca0f;02468acefdb97531"),
    42  		},
    43  		"one Instana and one other list member": {
    44  			Header:   "in=fa2375d711a4ca0f;02468acefdb97531,rojo=00f067aa0ba902b7",
    45  			Expected: w3ctrace.NewState([]string{"rojo=00f067aa0ba902b7"}, "fa2375d711a4ca0f;02468acefdb97531"),
    46  		},
    47  		"one Instana list member between two others": {
    48  			Header:   "rojo=00f067aa0ba902b7,in=fa2375d711a4ca0f;02468acefdb97531,congo=t61rcWkgMzE",
    49  			Expected: w3ctrace.NewState([]string{"rojo=00f067aa0ba902b7", "congo=t61rcWkgMzE"}, "fa2375d711a4ca0f;02468acefdb97531"),
    50  		},
    51  		"with empty list items": {
    52  			Header:   "rojo=00f067aa0ba902b7,    ,,congo=t61rcWkgMzE",
    53  			Expected: w3ctrace.NewState([]string{"rojo=00f067aa0ba902b7", "    ", "congo=t61rcWkgMzE"}, ""),
    54  		},
    55  		"with whitespace around the Instana list member": {
    56  			Header:   "rojo=00f067aa0ba902b7,  in   =   fa2375d711a4ca0f;02468acefdb97531    ,congo=t61rcWkgMzE",
    57  			Expected: w3ctrace.NewState([]string{"rojo=00f067aa0ba902b7", "congo=t61rcWkgMzE"}, "fa2375d711a4ca0f;02468acefdb97531"),
    58  		},
    59  		"with 33 list items": {
    60  			Header:   strings.TrimRight(strings.Repeat("rojo=00f067aa0ba902b7,", maxKVPairs+1), ","),
    61  			Expected: w3ctrace.NewState(strings.Split(strings.TrimRight(strings.Repeat("rojo=00f067aa0ba902b7,", maxKVPairs), ","), ","), "")},
    62  		"with too many list members and an Instana list member at the end": {
    63  			Header:   strings.TrimRight(strings.Repeat("rojo=00f067aa0ba902b7,", maxKVPairs+1), ",") + ",in=fa2375d711a4ca0f;02468acefdb97531",
    64  			Expected: w3ctrace.NewState(strings.Split(strings.TrimRight(strings.Repeat("rojo=00f067aa0ba902b7,", maxKVPairs-1), ","), ","), "fa2375d711a4ca0f;02468acefdb97531"),
    65  		},
    66  		"with 34 list items, with long one at the beginning": {
    67  			Header: "rojo=" + strings.Repeat("a", 129) + "," + strings.TrimRight(strings.Repeat("rojo=00f067aa0ba902b7,", maxKVPairs+1), ","),
    68  			Expected: w3ctrace.NewState(
    69  				strings.Split(strings.TrimRight(strings.Repeat("rojo=00f067aa0ba902b7,", maxKVPairs), ","), ","),
    70  				"",
    71  			),
    72  		},
    73  		"with 33 list items, each is more then 128 char long": {
    74  			Header: strings.TrimRight(strings.Repeat("rojo="+strings.Repeat("a", 129)+",", maxKVPairs+1), ","),
    75  			Expected: w3ctrace.NewState(
    76  				strings.Split(strings.TrimRight(strings.Repeat("rojo="+strings.Repeat("a", 129)+",", maxKVPairs), ","), ","),
    77  				"",
    78  			),
    79  		},
    80  		"with 34 list items: one short and 33 long": {
    81  			Header: "rojo=00f067aa0ba902b7," + strings.TrimRight(strings.Repeat("rojo="+strings.Repeat("a", 129)+",", maxKVPairs+1), ","),
    82  			Expected: w3ctrace.NewState(
    83  				strings.Split("rojo=00f067aa0ba902b7,"+strings.TrimRight(strings.Repeat("rojo="+strings.Repeat("a", 129)+",", maxKVPairs-1), ","), ","),
    84  				"",
    85  			),
    86  		},
    87  		"with 64 list items, mixed long and short values": {
    88  			Header: strings.TrimRight(strings.Repeat("short="+strings.Repeat("b", 10)+","+"long="+strings.Repeat("a", 129)+",", maxKVPairs), ","),
    89  			Expected: w3ctrace.NewState(
    90  				strings.Split(strings.TrimRight(strings.Repeat("short="+strings.Repeat("b", 10)+",", maxKVPairs), ","), ","),
    91  				"",
    92  			),
    93  		},
    94  		"with empty header value": {
    95  			Header:   "",
    96  			Expected: w3ctrace.NewState([]string{}, ""),
    97  		},
    98  		"with a lot of comas": {
    99  			Header:   strings.Repeat(",", 1024),
   100  			Expected: w3ctrace.NewState([]string{}, ""),
   101  		},
   102  	}
   103  
   104  	for name, example := range examples {
   105  		t.Run(name, func(t *testing.T) {
   106  			st := w3ctrace.ParseState(example.Header)
   107  			assert.Equal(t, example.Expected, st)
   108  		})
   109  	}
   110  }
   111  
   112  func TestState_FormStateWithInstanaTraceStateValueIntoEmptyTraceState(t *testing.T) {
   113  	st := w3ctrace.NewState([]string{}, "")
   114  	st = w3ctrace.FormStateWithInstanaTraceStateValue(st, "fa2375d711a4ca0f;02468acefdb97531")
   115  	require.Equal(t, w3ctrace.NewState([]string{}, "fa2375d711a4ca0f;02468acefdb97531"), st)
   116  }
   117  
   118  func TestState_FormStateWithInstanaTraceStateValueIntoNonEmptyTraceState(t *testing.T) {
   119  	st := w3ctrace.NewState([]string{"key1=value1", "key2=value"}, "")
   120  	st = w3ctrace.FormStateWithInstanaTraceStateValue(st, "fa2375d711a4ca0f;02468acefdb97531")
   121  	require.Equal(t, w3ctrace.NewState([]string{"key1=value1", "key2=value"}, "fa2375d711a4ca0f;02468acefdb97531"), st)
   122  }
   123  
   124  func TestState_FormStateWithInstanaTraceStateValueOverwriteExistingValue(t *testing.T) {
   125  	st := w3ctrace.NewState([]string{}, "fa2375d711a4ca0f;02468acefdb97531")
   126  	st = w3ctrace.FormStateWithInstanaTraceStateValue(st, "aaabbccddeeff012;123456789abcdef0")
   127  	require.Equal(t, w3ctrace.NewState([]string{}, "aaabbccddeeff012;123456789abcdef0"), st)
   128  }
   129  
   130  func TestState_FormStateWithInstanaTraceStateValueResetExistingValue(t *testing.T) {
   131  	st := w3ctrace.NewState([]string{}, "fa2375d711a4ca0f;02468acefdb97531")
   132  	st = w3ctrace.FormStateWithInstanaTraceStateValue(st, "")
   133  	require.Equal(t, w3ctrace.NewState([]string{}, ""), st)
   134  }
   135  
   136  func TestState_FormStateWithInstanaTraceStateValueAddToTraceStateWithMaxNumberOfListMembers(t *testing.T) {
   137  	var listMembers []string
   138  	for i := 0; i < maxKVPairs; i++ {
   139  		listMembers = append(listMembers, fmt.Sprintf("key%d=value%d", i, i))
   140  	}
   141  
   142  	// initially, we are just under the allowed number of list members
   143  	st := w3ctrace.NewState(listMembers, "")
   144  	require.Equal(t, w3ctrace.NewState(listMembers, ""), st)
   145  	// now we also add an Instana list member, which brings us over the limit
   146  	st = w3ctrace.FormStateWithInstanaTraceStateValue(st, "fa2375d711a4ca0f;02468acefdb97531")
   147  	// so we expect the right-most list member to be dropped
   148  	require.Equal(t, w3ctrace.NewState(listMembers[:maxKVPairs-1], "fa2375d711a4ca0f;02468acefdb97531"), st)
   149  }
   150  
   151  func TestState_FetchInstanaTraceStateValueNotPresent(t *testing.T) {
   152  	st := w3ctrace.NewState([]string{}, "")
   153  	instanaTraceStateValue, ok := st.FetchInstanaTraceStateValue()
   154  	require.False(t, ok)
   155  	require.Equal(t, "", instanaTraceStateValue)
   156  }
   157  
   158  func TestState_FetchInstanaTraceStateValuePresent(t *testing.T) {
   159  	st := w3ctrace.NewState([]string{}, "fa2375d711a4ca0f;02468acefdb97531")
   160  	instanaTraceStateValue, ok := st.FetchInstanaTraceStateValue()
   161  	require.True(t, ok)
   162  	require.Equal(t, "fa2375d711a4ca0f;02468acefdb97531", instanaTraceStateValue)
   163  }
   164  
   165  func TestState_String(t *testing.T) {
   166  	examples := map[string]struct {
   167  		State    w3ctrace.State
   168  		Expected string
   169  	}{
   170  		"empty": {},
   171  		"single tracing system": {
   172  			State:    w3ctrace.NewState([]string{"rojo=00f067aa0ba902b7"}, ""),
   173  			Expected: "rojo=00f067aa0ba902b7",
   174  		},
   175  		"only an Instana list member": {
   176  			State:    w3ctrace.NewState([]string{}, "fa2375d711a4ca0f;02468acefdb97531"),
   177  			Expected: "in=fa2375d711a4ca0f;02468acefdb97531",
   178  		},
   179  		"multiple tracing systems, without Instana list member": {
   180  			State:    w3ctrace.NewState([]string{"rojo=00f067aa0ba902b7", "congo=t61rcWkgMzE"}, ""),
   181  			Expected: "rojo=00f067aa0ba902b7,congo=t61rcWkgMzE",
   182  		},
   183  		"multiple tracing systems plus an Instana list member": {
   184  			State:    w3ctrace.NewState([]string{"rojo=00f067aa0ba902b7", "congo=t61rcWkgMzE"}, "fa2375d711a4ca0f;02468acefdb97531"),
   185  			Expected: "in=fa2375d711a4ca0f;02468acefdb97531,rojo=00f067aa0ba902b7,congo=t61rcWkgMzE",
   186  		},
   187  	}
   188  
   189  	for name, example := range examples {
   190  		t.Run(name, func(t *testing.T) {
   191  			assert.Equal(t, example.Expected, example.State.String())
   192  		})
   193  	}
   194  }