github.com/aristanetworks/goarista@v0.0.0-20240514173732-cca2755bbd44/key/stringify_test.go (about) 1 // Copyright (c) 2015 Arista Networks, Inc. 2 // Use of this source code is governed by the Apache License 2.0 3 // that can be found in the COPYING file. 4 5 package key 6 7 import ( 8 "fmt" 9 "math" 10 "testing" 11 ) 12 13 func TestStringify(t *testing.T) { 14 testcases := []struct { 15 name string 16 input interface{} 17 output string // or expected panic error message. 18 }{{ 19 name: "nil", 20 input: nil, 21 output: "<nil>", 22 }, { 23 name: "struct{}", 24 input: struct{}{}, 25 output: "Unable to stringify type struct {}: struct {}{}", 26 }, { 27 name: "string", 28 input: "foobar", 29 output: "foobar", 30 }, { 31 name: "valid non-ASCII UTF-8 string", 32 input: "日本語", 33 output: "日本語", 34 }, { 35 name: "invalid UTF-8 string 1", 36 input: string([]byte{0xef, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe}), 37 output: "77++vr6+vg==", 38 }, { 39 name: "invalid UTF-8 string 2", 40 input: string([]byte{0xef, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x23}), 41 output: "77++vr6+viM=", 42 }, { 43 name: "invalid UTF-8 string 3", 44 input: string([]byte{0xef, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x23, 0x24}), 45 output: "77++vr6+viMk", 46 }, { 47 name: "uint8", 48 input: uint8(43), 49 output: "43", 50 }, { 51 name: "uint16", 52 input: uint16(43), 53 output: "43", 54 }, { 55 name: "uint32", 56 input: uint32(43), 57 output: "43", 58 }, { 59 name: "uint64", 60 input: uint64(43), 61 output: "43", 62 }, { 63 name: "max uint64", 64 input: uint64(math.MaxUint64), 65 output: "18446744073709551615", 66 }, { 67 name: "int8", 68 input: int8(-32), 69 output: "-32", 70 }, { 71 name: "int16", 72 input: int16(-32), 73 output: "-32", 74 }, { 75 name: "int32", 76 input: int32(-32), 77 output: "-32", 78 }, { 79 name: "int64", 80 input: int64(-32), 81 output: "-32", 82 }, { 83 name: "true", 84 input: true, 85 output: "true", 86 }, { 87 name: "false", 88 input: false, 89 output: "false", 90 }, { 91 name: "float32", 92 input: float32(2.345), 93 output: "f1075188859", 94 }, { 95 name: "float64", 96 input: float64(-34.6543), 97 output: "f-4593298060402564373", 98 }, { 99 name: "map[string]interface{}", 100 input: map[string]interface{}{ 101 "b": uint32(43), 102 "a": "foobar", 103 "ex": map[string]interface{}{ 104 "d": "barfoo", 105 "c": uint32(45), 106 }, 107 }, 108 output: "foobar_43_45_barfoo", 109 }, { 110 name: "nil inside map[string]interface{}", 111 input: map[string]interface{}{ 112 "n": nil, 113 }, 114 output: "<nil>", 115 }, { 116 name: "[]interface{}", 117 input: []interface{}{ 118 uint32(42), 119 true, 120 "foo", NewMap( 121 New("a"), "b", 122 New("b"), "c"), 123 }, 124 output: "42,true,foo,a=b_b=c", 125 }, { 126 name: "pointer", 127 input: NewPointer(Path{New("foo"), New("bar")}), 128 output: "{/foo/bar}", 129 }, { 130 name: "[]byte", 131 input: []byte{0x1}, 132 output: "AQ==", 133 }, { 134 name: "map with []byte", 135 input: map[string]interface{}{"key1": []byte{0x1}, "key2": uint32(42)}, 136 output: "AQ==_42", 137 }} 138 139 for _, tcase := range testcases { 140 // Pardon the contraption used to catch panic's in error cases. 141 func() { 142 defer func() { 143 if e := recover(); e != nil { 144 if tcase.output != e.(error).Error() { 145 t.Errorf("Test %s: Error returned: %q but wanted %q", 146 tcase.name, e, tcase.output) 147 } 148 } 149 }() 150 151 result := stringify(tcase.input) 152 if tcase.output != result { 153 t.Errorf("Test %s: Result is different\nReceived: %s\nExpected: %s", 154 tcase.name, result, tcase.output) 155 } 156 keyString := StringKey(New(tcase.input)) 157 if tcase.output != keyString { 158 t.Errorf("Test %s: KeyString result is different\nReceived: %s\nExpected: %s", 159 tcase.name, keyString, tcase.output) 160 } 161 }() 162 } 163 } 164 165 var benchcases = []Key{ 166 New(nil), 167 New("foobar"), 168 New(string([]byte{0xef, 0xbf, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe})), 169 New(uint64(123456)), 170 New(int8(-32)), 171 New(true), 172 New(float32(2.345)), 173 New(float64(-34.6543)), 174 New(map[string]interface{}{ 175 "b": uint32(43), 176 "a": "foobar", 177 "ex": map[string]interface{}{ 178 "d": "barfoo", 179 "c": uint32(45), 180 }, 181 }), 182 New([]interface{}{ 183 uint32(42), 184 true, 185 "foo", NewMap( 186 New("a"), "b", 187 New("b"), "c"), 188 }), 189 New(NewPointer(Path{New("foo"), New("bar")})), 190 } 191 192 var str string 193 194 func BenchmarkStringification(b *testing.B) { 195 for _, k := range benchcases { 196 b.Run(fmt.Sprintf("SI_%T", k.Key()), func(b *testing.B) { 197 b.ReportAllocs() 198 for i := 0; i < b.N; i++ { 199 str, _ = StringifyInterface(k.Key()) 200 } 201 }) 202 b.Run(fmt.Sprintf("SK_%T", k.Key()), func(b *testing.B) { 203 b.ReportAllocs() 204 for i := 0; i < b.N; i++ { 205 str = StringKey(k) 206 } 207 }) 208 } 209 }