github.com/cosmos/cosmos-proto@v1.0.0-beta.3/testpb/get_test.go (about) 1 package testpb 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/require" 7 "google.golang.org/protobuf/reflect/protoreflect" 8 ) 9 10 func TestGet_NoMap_NoList_NoOneof(t *testing.T) { 11 msg := &A{ 12 Enum: Enumeration_Two, 13 SomeBoolean: true, 14 INT32: 1, 15 SINT32: 2, 16 UINT32: 3, 17 INT64: 4, 18 SING64: 5, 19 UINT64: 6, 20 SFIXED32: 7, 21 FIXED32: 8, 22 FLOAT: 9, 23 SFIXED64: 10, 24 FIXED64: 11, 25 DOUBLE: 12, 26 STRING: "a string", 27 BYTES: []byte("test bytes"), 28 MESSAGE: &B{ 29 X: "something else", 30 }, 31 MAP: map[string]*B{"item": {X: "inside_map_item"}}, 32 LIST: []*B{{X: "part of list"}}, 33 ONEOF: nil, 34 LIST_ENUM: nil, 35 } 36 37 cases := map[string]struct { 38 fieldName protoreflect.Name 39 expected interface{} 40 }{ 41 "enum": { 42 fieldName: "enum", 43 expected: msg.Enum, 44 }, 45 46 "bool": { 47 fieldName: "some_boolean", 48 expected: msg.SomeBoolean, 49 }, 50 51 "int32": { 52 fieldName: "INT32", 53 expected: msg.INT32, 54 }, 55 56 "sint32": { 57 fieldName: "SINT32", 58 expected: msg.SINT32, 59 }, 60 61 "uint32": { 62 fieldName: "UINT32", 63 expected: msg.UINT32, 64 }, 65 66 "int64": { 67 fieldName: "INT64", 68 expected: msg.INT64, 69 }, 70 71 "sint64": { 72 fieldName: "SING64", 73 expected: msg.SING64, 74 }, 75 76 "uint64": { 77 fieldName: "UINT64", 78 expected: msg.UINT64, 79 }, 80 81 "sfixed32": { 82 fieldName: "SFIXED32", 83 expected: msg.SFIXED32, 84 }, 85 86 "float": { 87 fieldName: "FLOAT", 88 expected: msg.FLOAT, 89 }, 90 91 "double": { 92 fieldName: "DOUBLE", 93 expected: msg.DOUBLE, 94 }, 95 96 "bytes": { 97 fieldName: "BYTES", 98 expected: msg.BYTES, 99 }, 100 101 "string": { 102 fieldName: "STRING", 103 expected: msg.STRING, 104 }, 105 106 "sfixed64": { 107 fieldName: "SFIXED64", 108 expected: msg.SFIXED64, 109 }, 110 111 "fixed32": { 112 fieldName: "FIXED32", 113 expected: msg.FIXED32, 114 }, 115 116 "message": { 117 fieldName: "MESSAGE", 118 expected: msg.MESSAGE, 119 }, 120 } 121 122 for name, tc := range cases { 123 tc := tc 124 t.Run(name, func(t *testing.T) { 125 fd := msg.ProtoReflect().Descriptor().Fields().ByName(tc.fieldName) 126 127 v := msg.ProtoReflect().Get(fd) 128 129 // validity 130 require.True(t, v.IsValid(), "field must be valid") 131 132 // value casting 133 require.NotPanics(t, func() { 134 switch fd.Kind() { 135 case protoreflect.BoolKind: 136 v.Bool() 137 case protoreflect.EnumKind: 138 v.Enum() 139 case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: 140 v.Int() 141 case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind: 142 v.Uint() 143 case protoreflect.FloatKind, protoreflect.DoubleKind: 144 v.Float() 145 case protoreflect.StringKind: 146 _ = v.String() 147 case protoreflect.BytesKind: 148 v.Bytes() 149 case protoreflect.MessageKind, protoreflect.GroupKind: 150 v.Message() 151 } 152 }) 153 154 // assignment and equality 155 var concreteValue interface{} 156 157 switch fd.Kind() { 158 case protoreflect.BoolKind: 159 concreteValue = v.Bool() 160 case protoreflect.EnumKind: 161 concreteValue = (Enumeration)(v.Enum()) 162 case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: 163 concreteValue = (int32)(v.Int()) 164 case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: 165 concreteValue = (uint32)(v.Uint()) 166 case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: 167 concreteValue = (int64)(v.Int()) 168 case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: 169 concreteValue = (uint64)(v.Uint()) 170 case protoreflect.FloatKind: 171 concreteValue = (float32)(v.Float()) 172 case protoreflect.DoubleKind: 173 concreteValue = (float64)(v.Float()) 174 case protoreflect.StringKind: 175 concreteValue = v.String() 176 case protoreflect.BytesKind: 177 concreteValue = v.Bytes() 178 case protoreflect.MessageKind, protoreflect.GroupKind: 179 concreteValue = v.Message().Interface().(*B) 180 } 181 182 require.Equal(t, tc.expected, concreteValue) 183 }) 184 } 185 } 186 187 func TestGetPanics(t *testing.T) { 188 msg := &A{} 189 190 t.Run("unknown field", func(t *testing.T) { 191 fd := (&B{}).ProtoReflect().Descriptor().Fields().ByName("X") 192 require.Panics(t, func() { 193 msg.ProtoReflect().Get(fd) 194 }) 195 }) 196 } 197 198 func TestGetList(t *testing.T) { 199 fd := (&A{}).ProtoReflect().Descriptor().Fields().ByName("LIST") 200 201 t.Run("mutability", func(t *testing.T) { 202 msg := &A{LIST: []*B{ 203 { 204 X: "1", 205 }, 206 }} 207 208 v := msg.ProtoReflect().Get(fd).List() 209 210 require.True(t, v.IsValid()) 211 212 // we append a variable 213 toAppend := &B{ 214 X: "2", 215 } 216 v.Append(protoreflect.ValueOfMessage(toAppend.ProtoReflect())) 217 218 // assert that we find it inside A 219 require.Len(t, msg.LIST, 2) 220 221 require.Equal(t, toAppend, msg.LIST[1]) 222 }) 223 224 t.Run("invalidity", func(t *testing.T) { 225 t.Run("nil", func(t *testing.T) { 226 msg := &A{} 227 228 v := msg.ProtoReflect().Get(fd).List() 229 230 require.False(t, v.IsValid()) 231 232 }) 233 234 t.Run("empty", func(t *testing.T) { 235 msg := &A{LIST: []*B{}} 236 237 v := msg.ProtoReflect().Get(fd).List() 238 239 require.False(t, v.IsValid()) 240 }) 241 242 t.Run("invalidity panics", func(t *testing.T) { 243 msg := &A{} 244 245 v := msg.ProtoReflect().Get(fd).List() 246 247 require.Panics(t, func() { 248 v.Set(0, protoreflect.ValueOfMessage((&B{}).ProtoReflect())) 249 }) 250 251 require.Panics(t, func() { 252 v.Append(protoreflect.ValueOfMessage((&B{}).ProtoReflect())) 253 }) 254 255 require.Panics(t, func() { 256 v.AppendMutable() 257 }) 258 259 require.Panics(t, func() { 260 v.Truncate(1) 261 }) 262 263 require.Panics(t, func() { 264 v.Get(0) 265 }) 266 }) 267 268 t.Run("invalidty no panics", func(t *testing.T) { 269 msg := &A{} 270 271 v := msg.ProtoReflect().Get(fd).List() 272 273 require.NotPanics(t, func() { 274 v.NewElement() 275 }) 276 277 require.NotPanics(t, func() { 278 v.Len() 279 }) 280 }) 281 }) 282 } 283 284 func TestGetMap(t *testing.T) { 285 fd := (&A{}).ProtoReflect().Descriptor().Fields().ByName("MAP") 286 287 t.Run("mutability", func(t *testing.T) { 288 msg := &A{MAP: map[string]*B{ 289 "1": &B{X: "a"}, 290 }} 291 292 mv := msg.ProtoReflect().Get(fd).Map() 293 294 key := "2" 295 value := &B{X: "b"} 296 297 mv.Set(protoreflect.MapKey(protoreflect.ValueOfString(key)), protoreflect.ValueOfMessage(value.ProtoReflect())) 298 299 require.Len(t, msg.MAP, 2) 300 301 require.Equal(t, value, msg.MAP[key]) 302 }) 303 304 t.Run("invalidity", func(t *testing.T) { 305 t.Run("nil", func(t *testing.T) { 306 msg := new(A) 307 require.False(t, msg.ProtoReflect().Get(fd).Map().IsValid()) 308 }) 309 310 t.Run("empty", func(t *testing.T) { 311 msg := &A{MAP: map[string]*B{}} 312 require.False(t, msg.ProtoReflect().Get(fd).Map().IsValid()) 313 }) 314 315 t.Run("invalidity panics", func(t *testing.T) { 316 msg := &A{MAP: map[string]*B{}} 317 318 mv := msg.ProtoReflect().Get(fd).Map() 319 320 require.Panics(t, func() { 321 mv.Mutable(protoreflect.MapKey(protoreflect.ValueOfString("something"))) 322 }) 323 324 require.Panics(t, func() { 325 mv.Set(protoreflect.MapKey(protoreflect.ValueOfString("something")), protoreflect.ValueOfMessage((&B{}).ProtoReflect())) 326 }) 327 }) 328 329 t.Run("invalidty no panics", func(t *testing.T) { 330 msg := &A{MAP: map[string]*B{}} 331 332 mv := msg.ProtoReflect().Get(fd).Map() 333 334 require.NotPanics(t, func() { 335 v := mv.Get(protoreflect.MapKey(protoreflect.ValueOfString("idk"))) 336 require.False(t, v.IsValid()) 337 }) 338 339 require.NotPanics(t, func() { 340 mv.Len() 341 }) 342 343 require.NotPanics(t, func() { 344 mv.NewValue() 345 }) 346 347 require.NotPanics(t, func() { 348 mv.Clear(protoreflect.MapKey(protoreflect.ValueOfString("xd"))) 349 }) 350 351 require.NotPanics(t, func() { 352 require.False(t, mv.Has(protoreflect.MapKey(protoreflect.ValueOfString("xd")))) 353 }) 354 355 require.NotPanics(t, func() { 356 ex := false 357 mv.Range(func(key protoreflect.MapKey, value protoreflect.Value) bool { 358 ex = true 359 return true 360 }) 361 362 require.False(t, ex) 363 }) 364 365 }) 366 }) 367 } 368 369 func TestGetMessage(t *testing.T) { 370 fd := (&A{}).ProtoReflect().Descriptor().Fields().ByName("MESSAGE") 371 t.Run("valid", func(t *testing.T) { 372 msg := &A{MESSAGE: &B{}} 373 require.True(t, msg.ProtoReflect().Get(fd).Message().IsValid()) 374 }) 375 376 t.Run("invalid", func(t *testing.T) { 377 msg := new(A) 378 require.False(t, msg.ProtoReflect().Get(fd).Message().IsValid()) 379 }) 380 } 381 382 func TestGetOneof(t *testing.T) { 383 fdMsg := (&A{}).ProtoReflect().Descriptor().Fields().ByName("ONEOF_B") 384 fdString := (&A{}).ProtoReflect().Descriptor().Fields().ByName("ONEOF_STRING") 385 t.Run("nil message", func(t *testing.T) { 386 msg := &A{} 387 value := msg.ProtoReflect().Get(fdMsg) 388 389 require.True(t, value.IsValid()) 390 require.False(t, value.Message().IsValid()) 391 }) 392 393 t.Run("empty string", func(t *testing.T) { 394 msg := &A{} 395 value := msg.ProtoReflect().Get(fdString) 396 397 require.True(t, value.IsValid()) 398 require.Equal(t, "", value.String()) 399 }) 400 401 t.Run("existing message", func(t *testing.T) { 402 msg := &A{ONEOF: &A_ONEOF_B{ONEOF_B: &B{}}} 403 mv := msg.ProtoReflect().Get(fdMsg).Message() 404 sv := msg.ProtoReflect().Get(fdString).String() 405 406 require.True(t, mv.IsValid()) 407 require.Empty(t, sv) 408 409 require.Equal(t, msg.GetONEOF_B(), mv.Interface()) 410 }) 411 } 412 413 func TestGetoneof(t *testing.T) { 414 x := &A{} 415 oneOf1 := x.ProtoReflect().Descriptor().Fields().ByName("ONEOF_STRING") 416 oneOf2 := x.ProtoReflect().Descriptor().Fields().ByName("ONEOF_B") 417 t.Logf("%s", oneOf1) 418 419 v := x.ProtoReflect().Get(oneOf1) 420 t.Logf("%s", v.Interface()) // empty string 421 422 v = x.ProtoReflect().Get(oneOf2) 423 t.Logf("%v", v.Message().IsValid()) // nil object, is valid 424 }