1// Copyright The OpenTelemetry Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package label_test 16 17import ( 18 "strings" 19 "testing" 20 21 "github.com/google/go-cmp/cmp" 22 23 "go.opentelemetry.io/otel/label" 24) 25 26func TestKeyValueConstructors(t *testing.T) { 27 tt := []struct { 28 name string 29 actual label.KeyValue 30 expected label.KeyValue 31 }{ 32 { 33 name: "Bool", 34 actual: label.Bool("k1", true), 35 expected: label.KeyValue{ 36 Key: "k1", 37 Value: label.BoolValue(true), 38 }, 39 }, 40 { 41 name: "Int64", 42 actual: label.Int64("k1", 123), 43 expected: label.KeyValue{ 44 Key: "k1", 45 Value: label.Int64Value(123), 46 }, 47 }, 48 { 49 name: "Uint64", 50 actual: label.Uint64("k1", 1), 51 expected: label.KeyValue{ 52 Key: "k1", 53 Value: label.Uint64Value(1), 54 }, 55 }, 56 { 57 name: "Float64", 58 actual: label.Float64("k1", 123.5), 59 expected: label.KeyValue{ 60 Key: "k1", 61 Value: label.Float64Value(123.5), 62 }, 63 }, 64 { 65 name: "Int32", 66 actual: label.Int32("k1", 123), 67 expected: label.KeyValue{ 68 Key: "k1", 69 Value: label.Int32Value(123), 70 }, 71 }, 72 { 73 name: "Uint32", 74 actual: label.Uint32("k1", 123), 75 expected: label.KeyValue{ 76 Key: "k1", 77 Value: label.Uint32Value(123), 78 }, 79 }, 80 { 81 name: "Float32", 82 actual: label.Float32("k1", 123.5), 83 expected: label.KeyValue{ 84 Key: "k1", 85 Value: label.Float32Value(123.5), 86 }, 87 }, 88 { 89 name: "String", 90 actual: label.String("k1", "123.5"), 91 expected: label.KeyValue{ 92 Key: "k1", 93 Value: label.StringValue("123.5"), 94 }, 95 }, 96 { 97 name: "Int", 98 actual: label.Int("k1", 123), 99 expected: label.KeyValue{ 100 Key: "k1", 101 Value: label.IntValue(123), 102 }, 103 }, 104 { 105 name: "Uint", 106 actual: label.Uint("k1", 123), 107 expected: label.KeyValue{ 108 Key: "k1", 109 Value: label.UintValue(123), 110 }, 111 }, 112 } 113 114 for _, test := range tt { 115 t.Run(test.name, func(t *testing.T) { 116 if diff := cmp.Diff(test.actual, test.expected, cmp.AllowUnexported(label.Value{})); diff != "" { 117 t.Fatal(diff) 118 } 119 }) 120 } 121} 122 123func TestAny(t *testing.T) { 124 builder := &strings.Builder{} 125 builder.WriteString("foo") 126 jsonifyStruct := struct { 127 Public string 128 private string 129 Tagged string `json:"tagName"` 130 Empty string 131 OmitEmpty string `json:",omitempty"` 132 Omit string `json:"-"` 133 }{"foo", "bar", "baz", "", "", "omitted"} 134 invalidStruct := struct { 135 N complex64 136 }{complex(0, 0)} 137 for _, testcase := range []struct { 138 key string 139 value interface{} 140 wantType label.Type 141 wantValue interface{} 142 }{ 143 { 144 key: "bool type inferred", 145 value: true, 146 wantType: label.BOOL, 147 wantValue: true, 148 }, 149 { 150 key: "int64 type inferred", 151 value: int64(42), 152 wantType: label.INT64, 153 wantValue: int64(42), 154 }, 155 { 156 key: "uint64 type inferred", 157 value: uint64(42), 158 wantType: label.UINT64, 159 wantValue: uint64(42), 160 }, 161 { 162 key: "float64 type inferred", 163 value: float64(42.1), 164 wantType: label.FLOAT64, 165 wantValue: 42.1, 166 }, 167 { 168 key: "int32 type inferred", 169 value: int32(42), 170 wantType: label.INT32, 171 wantValue: int32(42), 172 }, 173 { 174 key: "uint32 type inferred", 175 value: uint32(42), 176 wantType: label.UINT32, 177 wantValue: uint32(42), 178 }, 179 { 180 key: "float32 type inferred", 181 value: float32(42.1), 182 wantType: label.FLOAT32, 183 wantValue: float32(42.1), 184 }, 185 { 186 key: "string type inferred", 187 value: "foo", 188 wantType: label.STRING, 189 wantValue: "foo", 190 }, 191 { 192 key: "stringer type inferred", 193 value: builder, 194 wantType: label.STRING, 195 wantValue: "foo", 196 }, 197 { 198 key: "unknown value serialized as %v", 199 value: nil, 200 wantType: label.STRING, 201 wantValue: "<nil>", 202 }, 203 { 204 key: "JSON struct serialized correctly", 205 value: &jsonifyStruct, 206 wantType: label.STRING, 207 wantValue: `{"Public":"foo","tagName":"baz","Empty":""}`, 208 }, 209 { 210 key: "Invalid JSON struct falls back to string", 211 value: &invalidStruct, 212 wantType: label.STRING, 213 wantValue: "&{(0+0i)}", 214 }, 215 } { 216 t.Logf("Running test case %s", testcase.key) 217 keyValue := label.Any(testcase.key, testcase.value) 218 if keyValue.Value.Type() != testcase.wantType { 219 t.Errorf("wrong value type, got %#v, expected %#v", keyValue.Value.Type(), testcase.wantType) 220 } 221 got := keyValue.Value.AsInterface() 222 if diff := cmp.Diff(testcase.wantValue, got); diff != "" { 223 t.Errorf("+got, -want: %s", diff) 224 } 225 } 226} 227