github.com/jhump/protoreflect@v1.16.0/dynamic/dynamic_message_test.go (about) 1 package dynamic 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 8 "github.com/golang/protobuf/proto" 9 10 "github.com/jhump/protoreflect/desc" 11 "github.com/jhump/protoreflect/internal" 12 "github.com/jhump/protoreflect/internal/testprotos" 13 "github.com/jhump/protoreflect/internal/testutil" 14 ) 15 16 var typeOfGenericSlice = reflect.TypeOf([]interface{}(nil)) 17 var typeOfString = reflect.TypeOf("") 18 var typeOfGenericMap = reflect.TypeOf(map[interface{}]interface{}(nil)) 19 20 func canAssign(target, source reflect.Kind) bool { 21 if target == reflect.Int64 && (source == reflect.Int32 || source == reflect.Int) { 22 return true 23 } 24 if target == reflect.Uint64 && (source == reflect.Uint32 || source == reflect.Uint) { 25 return true 26 } 27 if target == reflect.Float64 && source == reflect.Float32 { 28 return true 29 } 30 return target == source 31 } 32 33 func TestGetSetClearScalarFields(t *testing.T) { 34 fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto") 35 testutil.Ok(t, err) 36 md := fd.FindSymbol("testprotos.UnaryFields").(*desc.MessageDescriptor) 37 dm := NewMessage(md) 38 39 inputs := map[reflect.Kind]struct { 40 input interface{} 41 zero interface{} 42 }{ 43 reflect.Bool: {input: true, zero: false}, 44 reflect.Int32: {input: int32(-12), zero: int32(0)}, 45 reflect.Int64: {input: int64(-1234), zero: int64(0)}, 46 reflect.Uint32: {input: uint32(45), zero: uint32(0)}, 47 reflect.Uint64: {input: uint64(4567), zero: uint64(0)}, 48 reflect.Float32: {input: float32(2.718), zero: float32(0)}, 49 reflect.Float64: {input: float64(3.14159), zero: float64(0)}, 50 reflect.String: {input: "foobar", zero: ""}, 51 reflect.Slice: {input: []byte("snafu"), zero: []byte(nil)}, 52 } 53 54 cases := []struct { 55 kind reflect.Kind 56 tagNumber int 57 fieldName string 58 }{ 59 {kind: reflect.Int32, tagNumber: 1, fieldName: "i"}, 60 {kind: reflect.Int64, tagNumber: 2, fieldName: "j"}, 61 {kind: reflect.Int32, tagNumber: 3, fieldName: "k"}, 62 {kind: reflect.Int64, tagNumber: 4, fieldName: "l"}, 63 {kind: reflect.Uint32, tagNumber: 5, fieldName: "m"}, 64 {kind: reflect.Uint64, tagNumber: 6, fieldName: "n"}, 65 {kind: reflect.Uint32, tagNumber: 7, fieldName: "o"}, 66 {kind: reflect.Uint64, tagNumber: 8, fieldName: "p"}, 67 {kind: reflect.Int32, tagNumber: 9, fieldName: "q"}, 68 {kind: reflect.Int64, tagNumber: 10, fieldName: "r"}, 69 {kind: reflect.Float32, tagNumber: 11, fieldName: "s"}, 70 {kind: reflect.Float64, tagNumber: 12, fieldName: "t"}, 71 {kind: reflect.Slice, tagNumber: 13, fieldName: "u"}, 72 {kind: reflect.String, tagNumber: 14, fieldName: "v"}, 73 {kind: reflect.Bool, tagNumber: 15, fieldName: "w"}, 74 } 75 76 for idx, c := range cases { 77 zero := inputs[c.kind].zero 78 79 for k, i := range inputs { 80 allowed := canAssign(c.kind, k) 81 82 // First run the case using Try* methods 83 84 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 85 86 v, err := dm.TryGetFieldByNumber(c.tagNumber) 87 testutil.Ok(t, err) 88 testutil.Eq(t, zero, v) 89 v, err = dm.TryGetFieldByName(c.fieldName) 90 testutil.Ok(t, err) 91 testutil.Eq(t, zero, v) 92 93 _, err = dm.TryGetRepeatedFieldByNumber(c.tagNumber, 0) 94 testutil.Eq(t, FieldIsNotRepeatedError, err) 95 _, err = dm.TryGetRepeatedFieldByName(c.fieldName, 0) 96 testutil.Eq(t, FieldIsNotRepeatedError, err) 97 98 err = dm.TrySetRepeatedFieldByNumber(c.tagNumber, 0, i.input) 99 testutil.Eq(t, FieldIsNotRepeatedError, err) 100 err = dm.TrySetRepeatedFieldByName(c.fieldName, 0, i.input) 101 testutil.Eq(t, FieldIsNotRepeatedError, err) 102 103 _, err = dm.TryGetMapFieldByNumber(c.tagNumber, "foo") 104 testutil.Eq(t, FieldIsNotMapError, err) 105 _, err = dm.TryGetMapFieldByName(c.fieldName, "foo") 106 testutil.Eq(t, FieldIsNotMapError, err) 107 108 err = dm.TryPutMapFieldByNumber(c.tagNumber, "foo", i.input) 109 testutil.Eq(t, FieldIsNotMapError, err) 110 err = dm.TryPutMapFieldByName(c.fieldName, "foo", i.input) 111 testutil.Eq(t, FieldIsNotMapError, err) 112 113 err = dm.TryRemoveMapFieldByNumber(c.tagNumber, "foo") 114 testutil.Eq(t, FieldIsNotMapError, err) 115 err = dm.TryRemoveMapFieldByName(c.fieldName, "foo") 116 testutil.Eq(t, FieldIsNotMapError, err) 117 118 err = dm.TrySetFieldByNumber(c.tagNumber, i.input) 119 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 120 // make sure value stuck 121 v, err = dm.TryGetFieldByNumber(c.tagNumber) 122 testutil.Ok(t, err) 123 testutil.Eq(t, coerce(i.input, c.kind), v) 124 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 125 } 126 err = dm.TrySetFieldByName(c.fieldName, i.input) 127 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 128 // make sure value stuck 129 v, err = dm.TryGetFieldByName(c.fieldName) 130 testutil.Ok(t, err) 131 testutil.Eq(t, coerce(i.input, c.kind), v) 132 testutil.Require(t, dm.HasFieldName(c.fieldName)) 133 } 134 135 err = dm.TryClearFieldByNumber(c.tagNumber) 136 testutil.Ok(t, err) 137 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 138 err = dm.TryClearFieldByName(c.fieldName) 139 testutil.Ok(t, err) 140 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 141 142 v, err = dm.TryGetFieldByNumber(c.tagNumber) 143 testutil.Ok(t, err) 144 testutil.Eq(t, zero, v) 145 v, err = dm.TryGetFieldByName(c.fieldName) 146 testutil.Ok(t, err) 147 testutil.Eq(t, zero, v) 148 149 // Now we do it again using the non-Try* methods (e.g. the ones that panic) 150 151 v = dm.GetFieldByNumber(c.tagNumber) 152 testutil.Eq(t, zero, v) 153 v = dm.GetFieldByName(c.fieldName) 154 testutil.Eq(t, zero, v) 155 156 err = catchPanic(func() { dm.GetRepeatedFieldByNumber(c.tagNumber, 0) }) 157 testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic) 158 err = catchPanic(func() { dm.GetRepeatedFieldByName(c.fieldName, 0) }) 159 testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic) 160 161 err = catchPanic(func() { dm.SetRepeatedFieldByNumber(c.tagNumber, 0, i.input) }) 162 testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic) 163 err = catchPanic(func() { dm.SetRepeatedFieldByName(c.fieldName, 0, i.input) }) 164 testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic) 165 166 err = catchPanic(func() { dm.GetMapFieldByNumber(c.tagNumber, "foo") }) 167 testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic) 168 err = catchPanic(func() { dm.GetMapFieldByName(c.fieldName, "foo") }) 169 testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic) 170 171 err = catchPanic(func() { dm.PutMapFieldByNumber(c.tagNumber, "foo", i.input) }) 172 testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic) 173 err = catchPanic(func() { dm.PutMapFieldByName(c.fieldName, "foo", i.input) }) 174 testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic) 175 176 err = catchPanic(func() { dm.RemoveMapFieldByNumber(c.tagNumber, "foo") }) 177 testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic) 178 err = catchPanic(func() { dm.RemoveMapFieldByName(c.fieldName, "foo") }) 179 testutil.Eq(t, FieldIsNotMapError.Error(), err.(panicError).panic) 180 181 err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, i.input) }) 182 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 183 // make sure value stuck 184 v = dm.GetFieldByNumber(c.tagNumber) 185 testutil.Eq(t, coerce(i.input, c.kind), v) 186 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 187 } 188 dm.ClearFieldByNumber(c.tagNumber) 189 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 190 191 err = catchPanic(func() { dm.SetFieldByName(c.fieldName, i.input) }) 192 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 193 // make sure value stuck 194 v = dm.GetFieldByName(c.fieldName) 195 testutil.Eq(t, coerce(i.input, c.kind), v) 196 testutil.Require(t, dm.HasFieldName(c.fieldName)) 197 } 198 dm.ClearFieldByName(c.fieldName) 199 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 200 201 v = dm.GetFieldByNumber(c.tagNumber) 202 testutil.Eq(t, zero, v) 203 v = dm.GetFieldByName(c.fieldName) 204 testutil.Eq(t, zero, v) 205 } 206 } 207 } 208 209 func TestGetSetClearRepeatedFields(t *testing.T) { 210 fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto") 211 testutil.Ok(t, err) 212 md := fd.FindSymbol("testprotos.RepeatedFields").(*desc.MessageDescriptor) 213 dm := NewMessage(md) 214 215 inputs := map[reflect.Kind]interface{}{ 216 reflect.Bool: true, 217 reflect.Int32: int32(-12), 218 reflect.Int64: int64(-1234), 219 reflect.Uint32: uint32(45), 220 reflect.Uint64: uint64(4567), 221 reflect.Float32: float32(2.718), 222 reflect.Float64: float64(3.14159), 223 reflect.String: "foobar", 224 reflect.Slice: []byte("snafu"), 225 } 226 227 sliceKinds := []func(interface{}) interface{}{ 228 // index 0 will not work since it doesn't return a slice 229 func(v interface{}) interface{} { 230 return v 231 }, 232 func(v interface{}) interface{} { 233 // generic slice 234 return []interface{}{v, v, v} 235 }, 236 func(v interface{}) interface{} { 237 // slice element type is the same as value type 238 sl := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(v)), 3, 3) 239 val := reflect.ValueOf(v) 240 sl.Index(0).Set(val) 241 sl.Index(1).Set(val) 242 sl.Index(2).Set(val) 243 return sl.Interface() 244 }, 245 } 246 247 cases := []struct { 248 kind reflect.Kind 249 tagNumber int 250 fieldName string 251 }{ 252 {kind: reflect.Int32, tagNumber: 1, fieldName: "i"}, 253 {kind: reflect.Int64, tagNumber: 2, fieldName: "j"}, 254 {kind: reflect.Int32, tagNumber: 3, fieldName: "k"}, 255 {kind: reflect.Int64, tagNumber: 4, fieldName: "l"}, 256 {kind: reflect.Uint32, tagNumber: 5, fieldName: "m"}, 257 {kind: reflect.Uint64, tagNumber: 6, fieldName: "n"}, 258 {kind: reflect.Uint32, tagNumber: 7, fieldName: "o"}, 259 {kind: reflect.Uint64, tagNumber: 8, fieldName: "p"}, 260 {kind: reflect.Int32, tagNumber: 9, fieldName: "q"}, 261 {kind: reflect.Int64, tagNumber: 10, fieldName: "r"}, 262 {kind: reflect.Float32, tagNumber: 11, fieldName: "s"}, 263 {kind: reflect.Float64, tagNumber: 12, fieldName: "t"}, 264 {kind: reflect.Slice, tagNumber: 13, fieldName: "u"}, 265 {kind: reflect.String, tagNumber: 14, fieldName: "v"}, 266 {kind: reflect.Bool, tagNumber: 15, fieldName: "w"}, 267 } 268 269 zero := reflect.Zero(typeOfGenericSlice).Interface() 270 271 for idx, c := range cases { 272 for k, i := range inputs { 273 allowed := canAssign(c.kind, k) 274 for j, sk := range sliceKinds { 275 276 // First run the case using Try* methods 277 278 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 279 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 280 281 v, err := dm.TryGetFieldByNumber(c.tagNumber) 282 testutil.Ok(t, err) 283 testutil.Eq(t, zero, v) 284 v, err = dm.TryGetFieldByName(c.fieldName) 285 testutil.Ok(t, err) 286 testutil.Eq(t, zero, v) 287 288 input := sk(i) 289 err = dm.TrySetFieldByNumber(c.tagNumber, input) 290 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 291 // make sure value stuck 292 v, err = dm.TryGetFieldByNumber(c.tagNumber) 293 testutil.Ok(t, err) 294 testutil.Eq(t, typeOfGenericSlice, reflect.TypeOf(v)) 295 testutil.Eq(t, coerceSlice(input, c.kind), v) 296 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 297 } 298 err = dm.TryClearFieldByNumber(c.tagNumber) 299 testutil.Ok(t, err) 300 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 301 302 err = dm.TrySetFieldByName(c.fieldName, input) 303 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 304 // make sure value stuck 305 v, err = dm.TryGetFieldByName(c.fieldName) 306 testutil.Ok(t, err) 307 testutil.Eq(t, typeOfGenericSlice, reflect.TypeOf(v)) 308 testutil.Eq(t, coerceSlice(input, c.kind), v) 309 testutil.Require(t, dm.HasFieldName(c.fieldName)) 310 } 311 err = dm.TryClearFieldByName(c.fieldName) 312 testutil.Ok(t, err) 313 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 314 315 v, err = dm.TryGetFieldByNumber(c.tagNumber) 316 testutil.Ok(t, err) 317 testutil.Eq(t, zero, v) 318 v, err = dm.TryGetFieldByName(c.fieldName) 319 testutil.Ok(t, err) 320 testutil.Eq(t, zero, v) 321 // Now we do it again using the non-Try* methods (e.g. the ones that panic) 322 323 v = dm.GetFieldByNumber(c.tagNumber) 324 testutil.Eq(t, zero, v) 325 v = dm.GetFieldByName(c.fieldName) 326 testutil.Eq(t, zero, v) 327 328 err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, input) }) 329 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 330 // make sure value stuck 331 v = dm.GetFieldByNumber(c.tagNumber) 332 testutil.Eq(t, typeOfGenericSlice, reflect.TypeOf(v)) 333 testutil.Eq(t, coerceSlice(input, c.kind), v) 334 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 335 } 336 dm.ClearFieldByNumber(c.tagNumber) 337 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 338 339 err = catchPanic(func() { dm.SetFieldByName(c.fieldName, input) }) 340 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 341 // make sure value stuck 342 v = dm.GetFieldByName(c.fieldName) 343 testutil.Eq(t, typeOfGenericSlice, reflect.TypeOf(v)) 344 testutil.Eq(t, coerceSlice(input, c.kind), v) 345 testutil.Require(t, dm.HasFieldName(c.fieldName)) 346 } 347 dm.ClearFieldByName(c.fieldName) 348 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 349 350 v = dm.GetFieldByNumber(c.tagNumber) 351 testutil.Eq(t, zero, v) 352 v = dm.GetFieldByName(c.fieldName) 353 testutil.Eq(t, zero, v) 354 } 355 } 356 } 357 } 358 359 func TestGetSetAtIndexAddRepeatedFields(t *testing.T) { 360 fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto") 361 testutil.Ok(t, err) 362 md := fd.FindSymbol("testprotos.RepeatedFields").(*desc.MessageDescriptor) 363 dm := NewMessage(md) 364 365 inputs := map[reflect.Kind]struct { 366 input1 interface{} 367 input2 interface{} 368 zero interface{} 369 }{ 370 reflect.Bool: {input1: true, input2: false, zero: false}, 371 reflect.Int32: {input1: int32(-12), input2: int32(42), zero: int32(0)}, 372 reflect.Int64: {input1: int64(-1234), input2: int64(424242), zero: int64(0)}, 373 reflect.Uint32: {input1: uint32(45), input2: uint32(42), zero: uint32(0)}, 374 reflect.Uint64: {input1: uint64(4567), input2: uint64(424242), zero: uint64(0)}, 375 reflect.Float32: {input1: float32(2.718), input2: float32(-3.14159), zero: float32(0)}, 376 reflect.Float64: {input1: float64(3.14159), input2: float64(-2.718), zero: float64(0)}, 377 reflect.String: {input1: "foobar", input2: "snafu", zero: ""}, 378 reflect.Slice: {input1: []byte("snafu"), input2: []byte("foobar"), zero: []byte(nil)}, 379 } 380 381 cases := []struct { 382 kind reflect.Kind 383 tagNumber int 384 fieldName string 385 }{ 386 {kind: reflect.Int32, tagNumber: 1, fieldName: "i"}, 387 {kind: reflect.Int64, tagNumber: 2, fieldName: "j"}, 388 {kind: reflect.Int32, tagNumber: 3, fieldName: "k"}, 389 {kind: reflect.Int64, tagNumber: 4, fieldName: "l"}, 390 {kind: reflect.Uint32, tagNumber: 5, fieldName: "m"}, 391 {kind: reflect.Uint64, tagNumber: 6, fieldName: "n"}, 392 {kind: reflect.Uint32, tagNumber: 7, fieldName: "o"}, 393 {kind: reflect.Uint64, tagNumber: 8, fieldName: "p"}, 394 {kind: reflect.Int32, tagNumber: 9, fieldName: "q"}, 395 {kind: reflect.Int64, tagNumber: 10, fieldName: "r"}, 396 {kind: reflect.Float32, tagNumber: 11, fieldName: "s"}, 397 {kind: reflect.Float64, tagNumber: 12, fieldName: "t"}, 398 {kind: reflect.Slice, tagNumber: 13, fieldName: "u"}, 399 {kind: reflect.String, tagNumber: 14, fieldName: "v"}, 400 {kind: reflect.Bool, tagNumber: 15, fieldName: "w"}, 401 } 402 403 for idx, c := range cases { 404 zero := inputs[c.kind].zero 405 406 for k, i := range inputs { 407 allowed := canAssign(c.kind, k) 408 409 // First run the case using Try* methods 410 411 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 412 413 _, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 0) 414 testutil.Eq(t, IndexOutOfRangeError, err) 415 _, err = dm.TryGetRepeatedFieldByName(c.fieldName, 0) 416 testutil.Eq(t, IndexOutOfRangeError, err) 417 418 err = dm.TryAddRepeatedFieldByNumber(c.tagNumber, i.input1) 419 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 420 // make sure value stuck 421 v, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 0) 422 testutil.Ok(t, err) 423 testutil.Eq(t, coerce(i.input1, c.kind), v) 424 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 425 } 426 427 err = dm.TryAddRepeatedFieldByNumber(c.tagNumber, i.input2) 428 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 429 // make sure value stuck 430 v, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 1) 431 testutil.Ok(t, err) 432 testutil.Eq(t, coerce(i.input2, c.kind), v) 433 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 434 } 435 436 var exp interface{} 437 if !allowed { 438 // adds above failed (because wrong kind), so go ahead and add 439 // correct values so we can test Set* methods 440 dm.AddRepeatedFieldByNumber(c.tagNumber, zero) 441 exp = zero 442 dm.AddRepeatedFieldByNumber(c.tagNumber, exp) 443 } else { 444 exp = coerce(i.input2, c.kind) 445 } 446 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len()) 447 448 err = dm.TrySetRepeatedFieldByNumber(c.tagNumber, 2, zero) 449 testutil.Eq(t, IndexOutOfRangeError, err) 450 err = dm.TrySetRepeatedFieldByNumber(c.tagNumber, 0, i.input2) 451 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 452 // make sure value stuck 453 v, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 0) 454 testutil.Ok(t, err) 455 testutil.Eq(t, coerce(i.input2, c.kind), v) 456 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 457 // and value at other index is unchanged 458 v, err = dm.TryGetRepeatedFieldByNumber(c.tagNumber, 1) 459 testutil.Ok(t, err) 460 testutil.Eq(t, exp, v) 461 } 462 463 err = dm.TrySetRepeatedFieldByNumber(c.tagNumber, 1, i.input1) 464 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 465 // make sure value stuck 466 v, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 1) 467 testutil.Ok(t, err) 468 testutil.Eq(t, coerce(i.input1, c.kind), v) 469 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 470 } 471 472 err = dm.TryClearFieldByNumber(c.tagNumber) 473 testutil.Ok(t, err) 474 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 475 476 // Now we do it again for the ByName methods 477 err = dm.TryAddRepeatedFieldByName(c.fieldName, i.input1) 478 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 479 // make sure value stuck 480 v, err := dm.TryGetRepeatedFieldByName(c.fieldName, 0) 481 testutil.Ok(t, err) 482 testutil.Eq(t, coerce(i.input1, c.kind), v) 483 testutil.Require(t, dm.HasFieldName(c.fieldName)) 484 } 485 err = dm.TryAddRepeatedFieldByName(c.fieldName, i.input2) 486 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 487 // make sure value stuck 488 v, err := dm.TryGetRepeatedFieldByName(c.fieldName, 1) 489 testutil.Ok(t, err) 490 testutil.Eq(t, coerce(i.input2, c.kind), v) 491 testutil.Require(t, dm.HasFieldName(c.fieldName)) 492 } 493 494 if !allowed { 495 // adds above failed (because wrong kind), so go ahead and add 496 // correct values so we can test Set* methods 497 dm.AddRepeatedFieldByName(c.fieldName, zero) 498 exp = zero 499 dm.AddRepeatedFieldByName(c.fieldName, exp) 500 } else { 501 exp = coerce(i.input2, c.kind) 502 } 503 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len()) 504 505 err = dm.TrySetRepeatedFieldByName(c.fieldName, 2, zero) 506 testutil.Eq(t, IndexOutOfRangeError, err) 507 err = dm.TrySetRepeatedFieldByName(c.fieldName, 0, i.input2) 508 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 509 // make sure value stuck 510 v, err := dm.TryGetRepeatedFieldByName(c.fieldName, 0) 511 testutil.Ok(t, err) 512 testutil.Eq(t, coerce(i.input2, c.kind), v) 513 testutil.Require(t, dm.HasFieldName(c.fieldName)) 514 // and value at other index is unchanged 515 v, err = dm.TryGetRepeatedFieldByName(c.fieldName, 1) 516 testutil.Ok(t, err) 517 testutil.Eq(t, exp, v) 518 } 519 520 err = dm.TrySetRepeatedFieldByName(c.fieldName, 1, i.input1) 521 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 522 // make sure value stuck 523 v, err := dm.TryGetRepeatedFieldByName(c.fieldName, 1) 524 testutil.Ok(t, err) 525 testutil.Eq(t, coerce(i.input1, c.kind), v) 526 testutil.Require(t, dm.HasFieldName(c.fieldName)) 527 } 528 529 err = dm.TryClearFieldByName(c.fieldName) 530 testutil.Ok(t, err) 531 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 532 533 // Now we do it again using the non-Try* methods (e.g. the ones that panic) 534 535 err = catchPanic(func() { dm.GetRepeatedFieldByNumber(c.tagNumber, 0) }) 536 testutil.Require(t, err != nil) 537 testutil.Eq(t, IndexOutOfRangeError.Error(), err.(panicError).panic) 538 539 err = catchPanic(func() { dm.AddRepeatedFieldByNumber(c.tagNumber, i.input1) }) 540 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 541 // make sure value stuck 542 v := dm.GetRepeatedFieldByNumber(c.tagNumber, 0) 543 testutil.Eq(t, coerce(i.input1, c.kind), v) 544 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 545 } 546 547 err = catchPanic(func() { dm.AddRepeatedFieldByNumber(c.tagNumber, i.input2) }) 548 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 549 // make sure value stuck 550 v := dm.GetRepeatedFieldByNumber(c.tagNumber, 1) 551 testutil.Eq(t, coerce(i.input2, c.kind), v) 552 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 553 } 554 555 if !allowed { 556 // adds above failed (because wrong kind), so go ahead and add 557 // correct values so we can test Set* methods 558 dm.AddRepeatedFieldByNumber(c.tagNumber, zero) 559 dm.AddRepeatedFieldByNumber(c.tagNumber, exp) 560 } 561 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len()) 562 563 err = catchPanic(func() { dm.SetRepeatedFieldByNumber(c.tagNumber, 2, zero) }) 564 testutil.Require(t, err != nil) 565 testutil.Eq(t, IndexOutOfRangeError.Error(), err.(panicError).panic) 566 err = catchPanic(func() { dm.SetRepeatedFieldByNumber(c.tagNumber, 0, i.input2) }) 567 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 568 // make sure value stuck 569 v := dm.GetRepeatedFieldByNumber(c.tagNumber, 0) 570 testutil.Eq(t, coerce(i.input2, c.kind), v) 571 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 572 // and value at other index is unchanged 573 v = dm.GetRepeatedFieldByNumber(c.tagNumber, 1) 574 testutil.Eq(t, exp, v) 575 } 576 577 err = catchPanic(func() { dm.SetRepeatedFieldByNumber(c.tagNumber, 1, i.input1) }) 578 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 579 // make sure value stuck 580 v := dm.GetRepeatedFieldByNumber(c.tagNumber, 1) 581 testutil.Eq(t, coerce(i.input1, c.kind), v) 582 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 583 } 584 585 dm.ClearFieldByNumber(c.tagNumber) 586 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 587 588 // Again - Non Try methds by Name 589 err = catchPanic(func() { dm.GetRepeatedFieldByName(c.fieldName, 0) }) 590 testutil.Require(t, err != nil) 591 testutil.Eq(t, IndexOutOfRangeError.Error(), err.(panicError).panic) 592 593 err = catchPanic(func() { dm.AddRepeatedFieldByName(c.fieldName, i.input1) }) 594 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 595 // make sure value stuck 596 v := dm.GetRepeatedFieldByName(c.fieldName, 0) 597 testutil.Eq(t, coerce(i.input1, c.kind), v) 598 testutil.Require(t, dm.HasFieldName(c.fieldName)) 599 } 600 601 err = catchPanic(func() { dm.AddRepeatedFieldByName(c.fieldName, i.input2) }) 602 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 603 // make sure value stuck 604 v := dm.GetRepeatedFieldByName(c.fieldName, 1) 605 testutil.Eq(t, coerce(i.input2, c.kind), v) 606 testutil.Require(t, dm.HasFieldName(c.fieldName)) 607 } 608 609 if !allowed { 610 // adds above failed (because wrong kind), so go ahead and add 611 // correct values so we can test Set* methods 612 dm.AddRepeatedFieldByName(c.fieldName, zero) 613 dm.AddRepeatedFieldByName(c.fieldName, exp) 614 } 615 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len()) 616 617 err = catchPanic(func() { dm.SetRepeatedFieldByName(c.fieldName, 2, zero) }) 618 testutil.Require(t, err != nil) 619 testutil.Eq(t, IndexOutOfRangeError.Error(), err.(panicError).panic) 620 err = catchPanic(func() { dm.SetRepeatedFieldByName(c.fieldName, 0, i.input2) }) 621 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 622 // make sure value stuck 623 v := dm.GetRepeatedFieldByName(c.fieldName, 0) 624 testutil.Eq(t, coerce(i.input2, c.kind), v) 625 testutil.Require(t, dm.HasFieldName(c.fieldName)) 626 // and value at other index is unchanged 627 v = dm.GetRepeatedFieldByName(c.fieldName, 1) 628 testutil.Eq(t, exp, v) 629 } 630 631 err = catchPanic(func() { dm.SetRepeatedFieldByName(c.fieldName, 1, i.input1) }) 632 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 633 // make sure value stuck 634 v := dm.GetRepeatedFieldByName(c.fieldName, 1) 635 testutil.Eq(t, coerce(i.input1, c.kind), v) 636 testutil.Require(t, dm.HasFieldName(c.fieldName)) 637 } 638 639 dm.ClearFieldByName(c.fieldName) 640 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 641 } 642 } 643 } 644 645 func TestGetSetClearMapFields_KeyTypes(t *testing.T) { 646 fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto") 647 testutil.Ok(t, err) 648 md := fd.FindSymbol("testprotos.MapKeyFields").(*desc.MessageDescriptor) 649 dm := NewMessage(md) 650 651 inputs := map[reflect.Kind]interface{}{ 652 reflect.Bool: true, 653 reflect.Int32: int32(-12), 654 reflect.Int64: int64(-1234), 655 reflect.Uint32: uint32(45), 656 reflect.Uint64: uint64(4567), 657 reflect.String: "foobar", 658 } 659 660 mapKinds := []func(interface{}) interface{}{ 661 // index 0 will not work since it doesn't return a map 662 func(v interface{}) interface{} { 663 return v 664 }, 665 func(v interface{}) interface{} { 666 // generic map 667 return map[interface{}]interface{}{v: "foo"} 668 }, 669 func(v interface{}) interface{} { 670 // specific key and value types 671 mp := reflect.MakeMap(reflect.MapOf(reflect.TypeOf(v), typeOfString)) 672 val := reflect.ValueOf(v) 673 mp.SetMapIndex(val, reflect.ValueOf("foo")) 674 return mp.Interface() 675 }, 676 } 677 678 cases := []struct { 679 kind reflect.Kind 680 tagNumber int 681 fieldName string 682 }{ 683 {kind: reflect.Int32, tagNumber: 1, fieldName: "i"}, 684 {kind: reflect.Int64, tagNumber: 2, fieldName: "j"}, 685 {kind: reflect.Int32, tagNumber: 3, fieldName: "k"}, 686 {kind: reflect.Int64, tagNumber: 4, fieldName: "l"}, 687 {kind: reflect.Uint32, tagNumber: 5, fieldName: "m"}, 688 {kind: reflect.Uint64, tagNumber: 6, fieldName: "n"}, 689 {kind: reflect.Uint32, tagNumber: 7, fieldName: "o"}, 690 {kind: reflect.Uint64, tagNumber: 8, fieldName: "p"}, 691 {kind: reflect.Int32, tagNumber: 9, fieldName: "q"}, 692 {kind: reflect.Int64, tagNumber: 10, fieldName: "r"}, 693 {kind: reflect.String, tagNumber: 11, fieldName: "s"}, 694 {kind: reflect.Bool, tagNumber: 12, fieldName: "t"}, 695 } 696 697 zero := reflect.Zero(typeOfGenericMap).Interface() 698 699 for idx, c := range cases { 700 for k, i := range inputs { 701 allowed := canAssign(c.kind, k) 702 for j, mk := range mapKinds { 703 // First run the case using Try* methods 704 705 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 706 707 v, err := dm.TryGetFieldByNumber(c.tagNumber) 708 testutil.Ok(t, err) 709 testutil.Eq(t, zero, v) 710 v, err = dm.TryGetFieldByName(c.fieldName) 711 testutil.Ok(t, err) 712 testutil.Eq(t, zero, v) 713 714 input := mk(i) 715 err = dm.TrySetFieldByNumber(c.tagNumber, input) 716 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 717 // make sure value stuck 718 v, err = dm.TryGetFieldByNumber(c.tagNumber) 719 testutil.Ok(t, err) 720 testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v)) 721 testutil.Eq(t, coerceMapKeys(input, c.kind), v) 722 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 723 } 724 err = dm.TryClearFieldByNumber(c.tagNumber) 725 testutil.Ok(t, err) 726 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 727 v, err = dm.TryGetFieldByNumber(c.tagNumber) 728 testutil.Ok(t, err) 729 testutil.Eq(t, zero, v) 730 731 err = dm.TrySetFieldByName(c.fieldName, input) 732 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 733 // make sure value stuck 734 v, err = dm.TryGetFieldByName(c.fieldName) 735 testutil.Ok(t, err) 736 testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v)) 737 testutil.Eq(t, coerceMapKeys(input, c.kind), v) 738 testutil.Require(t, dm.HasFieldName(c.fieldName)) 739 } 740 err = dm.TryClearFieldByName(c.fieldName) 741 testutil.Ok(t, err) 742 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 743 v, err = dm.TryGetFieldByName(c.fieldName) 744 testutil.Ok(t, err) 745 testutil.Eq(t, zero, v) 746 747 // Now we do it again using the non-Try* methods (e.g. the ones that panic) 748 749 v = dm.GetFieldByNumber(c.tagNumber) 750 testutil.Eq(t, zero, v) 751 v = dm.GetFieldByName(c.fieldName) 752 testutil.Eq(t, zero, v) 753 754 err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, input) }) 755 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 756 // make sure value stuck 757 v = dm.GetFieldByNumber(c.tagNumber) 758 testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v)) 759 testutil.Eq(t, coerceMapKeys(input, c.kind), v) 760 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 761 } 762 dm.ClearFieldByNumber(c.tagNumber) 763 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 764 v = dm.GetFieldByNumber(c.tagNumber) 765 testutil.Eq(t, zero, v) 766 767 err = catchPanic(func() { dm.SetFieldByName(c.fieldName, input) }) 768 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 769 // make sure value stuck 770 v = dm.GetFieldByNumber(c.tagNumber) 771 testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v)) 772 testutil.Eq(t, coerceMapKeys(input, c.kind), v) 773 testutil.Require(t, dm.HasFieldName(c.fieldName)) 774 } 775 dm.ClearFieldByName(c.fieldName) 776 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 777 v = dm.GetFieldByName(c.fieldName) 778 testutil.Eq(t, zero, v) 779 } 780 } 781 } 782 } 783 784 func TestGetSetClearMapFields_ValueTypes(t *testing.T) { 785 fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto") 786 testutil.Ok(t, err) 787 md := fd.FindSymbol("testprotos.MapValFields").(*desc.MessageDescriptor) 788 dm := NewMessage(md) 789 790 inputs := map[reflect.Kind]interface{}{ 791 reflect.Bool: true, 792 reflect.Int32: int32(-12), 793 reflect.Int64: int64(-1234), 794 reflect.Uint32: uint32(45), 795 reflect.Uint64: uint64(4567), 796 reflect.Float32: float32(2.718), 797 reflect.Float64: float64(3.14159), 798 reflect.String: "foobar", 799 reflect.Slice: []byte("snafu"), 800 } 801 802 mapKinds := []func(interface{}) interface{}{ 803 // index 0 will not work since it doesn't return a map 804 func(v interface{}) interface{} { 805 return v 806 }, 807 func(v interface{}) interface{} { 808 // generic slice 809 return map[interface{}]interface{}{"foo": v, "bar": v, "baz": v} 810 }, 811 func(v interface{}) interface{} { 812 // specific key and value types 813 mp := reflect.MakeMap(reflect.MapOf(typeOfString, reflect.TypeOf(v))) 814 val := reflect.ValueOf(v) 815 mp.SetMapIndex(reflect.ValueOf("foo"), val) 816 mp.SetMapIndex(reflect.ValueOf("bar"), val) 817 mp.SetMapIndex(reflect.ValueOf("baz"), val) 818 return mp.Interface() 819 }, 820 } 821 822 cases := []struct { 823 kind reflect.Kind 824 tagNumber int 825 fieldName string 826 }{ 827 {kind: reflect.Int32, tagNumber: 1, fieldName: "i"}, 828 {kind: reflect.Int64, tagNumber: 2, fieldName: "j"}, 829 {kind: reflect.Int32, tagNumber: 3, fieldName: "k"}, 830 {kind: reflect.Int64, tagNumber: 4, fieldName: "l"}, 831 {kind: reflect.Uint32, tagNumber: 5, fieldName: "m"}, 832 {kind: reflect.Uint64, tagNumber: 6, fieldName: "n"}, 833 {kind: reflect.Uint32, tagNumber: 7, fieldName: "o"}, 834 {kind: reflect.Uint64, tagNumber: 8, fieldName: "p"}, 835 {kind: reflect.Int32, tagNumber: 9, fieldName: "q"}, 836 {kind: reflect.Int64, tagNumber: 10, fieldName: "r"}, 837 {kind: reflect.Float32, tagNumber: 11, fieldName: "s"}, 838 {kind: reflect.Float64, tagNumber: 12, fieldName: "t"}, 839 {kind: reflect.Slice, tagNumber: 13, fieldName: "u"}, 840 {kind: reflect.String, tagNumber: 14, fieldName: "v"}, 841 {kind: reflect.Bool, tagNumber: 15, fieldName: "w"}, 842 } 843 844 zero := reflect.Zero(typeOfGenericMap).Interface() 845 846 for idx, c := range cases { 847 for k, i := range inputs { 848 allowed := canAssign(c.kind, k) 849 for j, mk := range mapKinds { 850 // First run the case using Try* methods 851 852 v, err := dm.TryGetFieldByNumber(c.tagNumber) 853 testutil.Ok(t, err) 854 testutil.Eq(t, zero, v) 855 v, err = dm.TryGetFieldByName(c.fieldName) 856 testutil.Ok(t, err) 857 testutil.Eq(t, zero, v) 858 859 input := mk(i) 860 err = dm.TrySetFieldByNumber(c.tagNumber, input) 861 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 862 // make sure value stuck 863 v, err = dm.TryGetFieldByNumber(c.tagNumber) 864 testutil.Ok(t, err) 865 testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v)) 866 testutil.Eq(t, coerceMapVals(input, c.kind), v) 867 } 868 869 err = dm.TryClearFieldByNumber(c.tagNumber) 870 testutil.Ok(t, err) 871 872 v, err = dm.TryGetFieldByNumber(c.tagNumber) 873 testutil.Ok(t, err) 874 testutil.Eq(t, zero, v) 875 876 err = dm.TrySetFieldByName(c.fieldName, input) 877 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 878 // make sure value stuck 879 v, err = dm.TryGetFieldByName(c.fieldName) 880 testutil.Ok(t, err) 881 testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v)) 882 testutil.Eq(t, coerceMapVals(input, c.kind), v) 883 } 884 885 err = dm.TryClearFieldByName(c.fieldName) 886 testutil.Ok(t, err) 887 888 v, err = dm.TryGetFieldByName(c.fieldName) 889 testutil.Ok(t, err) 890 testutil.Eq(t, zero, v) 891 // Now we do it again using the non-Try* methods (e.g. the ones that panic) 892 893 v = dm.GetFieldByNumber(c.tagNumber) 894 testutil.Eq(t, zero, v) 895 v = dm.GetFieldByName(c.fieldName) 896 testutil.Eq(t, zero, v) 897 898 err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, input) }) 899 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 900 // make sure value stuck 901 v = dm.GetFieldByNumber(c.tagNumber) 902 testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v)) 903 testutil.Eq(t, coerceMapVals(input, c.kind), v) 904 } 905 dm.ClearFieldByNumber(c.tagNumber) 906 v = dm.GetFieldByNumber(c.tagNumber) 907 testutil.Eq(t, zero, v) 908 909 err = catchPanic(func() { dm.SetFieldByName(c.fieldName, input) }) 910 if shouldTestValue(t, err, j != 0 && allowed, k, c.kind, idx) { 911 // make sure value stuck 912 v = dm.GetFieldByName(c.fieldName) 913 testutil.Eq(t, typeOfGenericMap, reflect.TypeOf(v)) 914 testutil.Eq(t, coerceMapVals(input, c.kind), v) 915 } 916 dm.ClearFieldByName(c.fieldName) 917 v = dm.GetFieldByName(c.fieldName) 918 testutil.Eq(t, zero, v) 919 } 920 } 921 } 922 } 923 924 func TestGetPutDeleteMapFields(t *testing.T) { 925 fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto") 926 testutil.Ok(t, err) 927 md := fd.FindSymbol("testprotos.MapValFields").(*desc.MessageDescriptor) 928 dm := NewMessage(md) 929 930 inputs := map[reflect.Kind]struct { 931 input1 interface{} 932 input2 interface{} 933 zero interface{} 934 }{ 935 reflect.Bool: {input1: true, input2: false, zero: false}, 936 reflect.Int32: {input1: int32(-12), input2: int32(42), zero: int32(0)}, 937 reflect.Int64: {input1: int64(-1234), input2: int64(424242), zero: int64(0)}, 938 reflect.Uint32: {input1: uint32(45), input2: uint32(42), zero: uint32(0)}, 939 reflect.Uint64: {input1: uint64(4567), input2: uint64(424242), zero: uint64(0)}, 940 reflect.Float32: {input1: float32(2.718), input2: float32(-3.14159), zero: float32(0)}, 941 reflect.Float64: {input1: float64(3.14159), input2: float64(-2.718), zero: float64(0)}, 942 reflect.String: {input1: "foobar", input2: "snafu", zero: ""}, 943 reflect.Slice: {input1: []byte("snafu"), input2: []byte("foobar"), zero: []byte(nil)}, 944 } 945 946 cases := []struct { 947 kind reflect.Kind 948 tagNumber int 949 fieldName string 950 }{ 951 {kind: reflect.Int32, tagNumber: 1, fieldName: "i"}, 952 {kind: reflect.Int64, tagNumber: 2, fieldName: "j"}, 953 {kind: reflect.Int32, tagNumber: 3, fieldName: "k"}, 954 {kind: reflect.Int64, tagNumber: 4, fieldName: "l"}, 955 {kind: reflect.Uint32, tagNumber: 5, fieldName: "m"}, 956 {kind: reflect.Uint64, tagNumber: 6, fieldName: "n"}, 957 {kind: reflect.Uint32, tagNumber: 7, fieldName: "o"}, 958 {kind: reflect.Uint64, tagNumber: 8, fieldName: "p"}, 959 {kind: reflect.Int32, tagNumber: 9, fieldName: "q"}, 960 {kind: reflect.Int64, tagNumber: 10, fieldName: "r"}, 961 {kind: reflect.Float32, tagNumber: 11, fieldName: "s"}, 962 {kind: reflect.Float64, tagNumber: 12, fieldName: "t"}, 963 {kind: reflect.Slice, tagNumber: 13, fieldName: "u"}, 964 {kind: reflect.String, tagNumber: 14, fieldName: "v"}, 965 {kind: reflect.Bool, tagNumber: 15, fieldName: "w"}, 966 } 967 968 for idx, c := range cases { 969 zero := inputs[c.kind].zero 970 971 for k, i := range inputs { 972 allowed := canAssign(c.kind, k) 973 974 // First run the case using Try* methods 975 976 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 977 978 v, err := dm.TryGetMapFieldByNumber(c.tagNumber, "foo") 979 testutil.Ok(t, err) 980 testutil.Require(t, v == nil) 981 982 err = dm.TryPutMapFieldByNumber(c.tagNumber, "foo", i.input1) 983 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 984 // make sure value stuck 985 v, err = dm.TryGetMapFieldByNumber(c.tagNumber, "foo") 986 testutil.Ok(t, err) 987 testutil.Eq(t, coerce(i.input1, c.kind), v) 988 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 989 } 990 991 err = dm.TryPutMapFieldByNumber(c.tagNumber, "bar", i.input2) 992 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 993 // make sure value stuck 994 v, err = dm.TryGetMapFieldByNumber(c.tagNumber, "bar") 995 testutil.Ok(t, err) 996 testutil.Eq(t, coerce(i.input2, c.kind), v) 997 } 998 999 var exp interface{} 1000 if !allowed { 1001 // adds above failed (because wrong kind), so go ahead and add 1002 // correct values so we can test Set* methods 1003 dm.PutMapFieldByNumber(c.tagNumber, "foo", zero) 1004 exp = zero 1005 dm.PutMapFieldByNumber(c.tagNumber, "bar", exp) 1006 } else { 1007 exp = coerce(i.input2, c.kind) 1008 } 1009 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len()) 1010 1011 // removing missing key is not an error 1012 err = dm.TryRemoveMapFieldByNumber(c.tagNumber, "baz") 1013 testutil.Ok(t, err) 1014 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len()) 1015 1016 err = dm.TryRemoveMapFieldByNumber(c.tagNumber, "foo") 1017 testutil.Ok(t, err) 1018 testutil.Eq(t, 1, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len()) 1019 // value has been deleted 1020 v, err = dm.TryGetMapFieldByNumber(c.tagNumber, "foo") 1021 testutil.Ok(t, err) 1022 testutil.Require(t, v == nil) 1023 // other key not affected 1024 v, err = dm.TryGetMapFieldByNumber(c.tagNumber, "bar") 1025 testutil.Ok(t, err) 1026 testutil.Eq(t, exp, v) 1027 1028 err = dm.TryRemoveMapFieldByNumber(c.tagNumber, "bar") 1029 testutil.Ok(t, err) 1030 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 1031 testutil.Eq(t, 0, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len()) 1032 1033 // Now run the try methods using ByName methods 1034 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 1035 1036 v, err = dm.TryGetMapFieldByName(c.fieldName, "foo") 1037 testutil.Ok(t, err) 1038 testutil.Require(t, v == nil) 1039 1040 err = dm.TryPutMapFieldByName(c.fieldName, "foo", i.input1) 1041 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1042 // make sure value stuck 1043 v, err = dm.TryGetMapFieldByName(c.fieldName, "foo") 1044 testutil.Ok(t, err) 1045 testutil.Eq(t, coerce(i.input1, c.kind), v) 1046 testutil.Require(t, dm.HasFieldName(c.fieldName)) 1047 } 1048 1049 err = dm.TryPutMapFieldByName(c.fieldName, "bar", i.input2) 1050 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1051 // make sure value stuck 1052 v, err = dm.TryGetMapFieldByName(c.fieldName, "bar") 1053 testutil.Ok(t, err) 1054 testutil.Eq(t, coerce(i.input2, c.kind), v) 1055 } 1056 1057 if !allowed { 1058 // adds above failed (because wrong kind), so go ahead and add 1059 // correct values so we can test Set* methods 1060 dm.PutMapFieldByName(c.fieldName, "foo", zero) 1061 exp = zero 1062 dm.PutMapFieldByName(c.fieldName, "bar", exp) 1063 } else { 1064 exp = coerce(i.input2, c.kind) 1065 } 1066 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len()) 1067 1068 // removing missing key is not an error 1069 err = dm.TryRemoveMapFieldByName(c.fieldName, "baz") 1070 testutil.Ok(t, err) 1071 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len()) 1072 1073 err = dm.TryRemoveMapFieldByName(c.fieldName, "foo") 1074 testutil.Ok(t, err) 1075 testutil.Eq(t, 1, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len()) 1076 // value has been deleted 1077 v, err = dm.TryGetMapFieldByName(c.fieldName, "foo") 1078 testutil.Ok(t, err) 1079 testutil.Require(t, v == nil) 1080 // other key not affected 1081 v, err = dm.TryGetMapFieldByName(c.fieldName, "bar") 1082 testutil.Ok(t, err) 1083 testutil.Eq(t, exp, v) 1084 1085 err = dm.TryRemoveMapFieldByName(c.fieldName, "bar") 1086 testutil.Ok(t, err) 1087 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 1088 testutil.Eq(t, 0, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len()) 1089 1090 // Now we do it again using the non-Try* methods (e.g. the ones that panic) 1091 1092 v = dm.GetMapFieldByNumber(c.tagNumber, "foo") 1093 testutil.Require(t, v == nil) 1094 1095 err = catchPanic(func() { dm.PutMapFieldByNumber(c.tagNumber, "foo", i.input1) }) 1096 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1097 // make sure value stuck 1098 v = dm.GetMapFieldByNumber(c.tagNumber, "foo") 1099 testutil.Eq(t, coerce(i.input1, c.kind), v) 1100 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 1101 } 1102 1103 err = catchPanic(func() { dm.PutMapFieldByNumber(c.tagNumber, "bar", i.input2) }) 1104 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1105 // make sure value stuck 1106 v = dm.GetMapFieldByNumber(c.tagNumber, "bar") 1107 testutil.Eq(t, coerce(i.input2, c.kind), v) 1108 } 1109 1110 if !allowed { 1111 // adds above failed (because wrong kind), so go ahead and add 1112 // correct values so we can test Set* methods 1113 dm.PutMapFieldByNumber(c.tagNumber, "foo", zero) 1114 dm.PutMapFieldByNumber(c.tagNumber, "bar", exp) 1115 } 1116 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len()) 1117 1118 // removing missing key does not panic 1119 err = catchPanic(func() { dm.RemoveMapFieldByNumber(c.tagNumber, "baz") }) 1120 testutil.Ok(t, err) 1121 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len()) 1122 1123 err = catchPanic(func() { dm.RemoveMapFieldByNumber(c.tagNumber, "foo") }) 1124 testutil.Ok(t, err) 1125 testutil.Eq(t, 1, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len()) 1126 // value has been deleted 1127 v = dm.GetMapFieldByNumber(c.tagNumber, "foo") 1128 testutil.Require(t, v == nil) 1129 // other key not affected 1130 v = dm.GetMapFieldByNumber(c.tagNumber, "bar") 1131 testutil.Eq(t, exp, v) 1132 1133 err = catchPanic(func() { dm.RemoveMapFieldByNumber(c.tagNumber, "bar") }) 1134 testutil.Ok(t, err) 1135 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 1136 testutil.Eq(t, 0, reflect.ValueOf(dm.GetFieldByNumber(c.tagNumber)).Len()) 1137 1138 // Now run the non-try methods using byName methods 1139 v = dm.GetMapFieldByName(c.fieldName, "foo") 1140 testutil.Require(t, v == nil) 1141 1142 err = catchPanic(func() { dm.PutMapFieldByName(c.fieldName, "foo", i.input1) }) 1143 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1144 // make sure value stuck 1145 v = dm.GetMapFieldByName(c.fieldName, "foo") 1146 testutil.Eq(t, coerce(i.input1, c.kind), v) 1147 testutil.Require(t, dm.HasFieldName(c.fieldName)) 1148 } 1149 1150 err = catchPanic(func() { dm.PutMapFieldByName(c.fieldName, "bar", i.input2) }) 1151 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1152 // make sure value stuck 1153 v = dm.GetMapFieldByName(c.fieldName, "bar") 1154 testutil.Eq(t, coerce(i.input2, c.kind), v) 1155 } 1156 1157 if !allowed { 1158 // adds above failed (because wrong kind), so go ahead and add 1159 // correct values so we can test Set* methods 1160 dm.PutMapFieldByName(c.fieldName, "foo", zero) 1161 dm.PutMapFieldByName(c.fieldName, "bar", exp) 1162 } 1163 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len()) 1164 1165 // removing missing key does not panic 1166 err = catchPanic(func() { dm.RemoveMapFieldByName(c.fieldName, "baz") }) 1167 testutil.Ok(t, err) 1168 testutil.Eq(t, 2, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len()) 1169 1170 err = catchPanic(func() { dm.RemoveMapFieldByName(c.fieldName, "foo") }) 1171 testutil.Ok(t, err) 1172 testutil.Eq(t, 1, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len()) 1173 // value has been deleted 1174 v = dm.GetMapFieldByName(c.fieldName, "foo") 1175 testutil.Require(t, v == nil) 1176 // other key not affected 1177 v = dm.GetMapFieldByName(c.fieldName, "bar") 1178 testutil.Eq(t, exp, v) 1179 1180 err = catchPanic(func() { dm.RemoveMapFieldByName(c.fieldName, "bar") }) 1181 testutil.Ok(t, err) 1182 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 1183 testutil.Eq(t, 0, reflect.ValueOf(dm.GetFieldByName(c.fieldName)).Len()) 1184 } 1185 } 1186 } 1187 1188 func TestMapFields_AsIfRepeatedFieldOfEntries(t *testing.T) { 1189 fd, err := desc.LoadFileDescriptor("desc_test_field_types.proto") 1190 testutil.Ok(t, err) 1191 md := fd.FindSymbol("testprotos.MapValFields").(*desc.MessageDescriptor) 1192 dm := NewMessage(md) 1193 1194 inputs := map[reflect.Kind]struct { 1195 input1 interface{} 1196 input2 interface{} 1197 }{ 1198 reflect.Bool: {input1: true, input2: false}, 1199 reflect.Int32: {input1: int32(-12), input2: int32(42)}, 1200 reflect.Int64: {input1: int64(-1234), input2: int64(424242)}, 1201 reflect.Uint32: {input1: uint32(45), input2: uint32(42)}, 1202 reflect.Uint64: {input1: uint64(4567), input2: uint64(424242)}, 1203 reflect.Float32: {input1: float32(2.718), input2: float32(-3.14159)}, 1204 reflect.Float64: {input1: float64(3.14159), input2: float64(-2.718)}, 1205 reflect.String: {input1: "foobar", input2: "snafu"}, 1206 reflect.Slice: {input1: []byte("snafu"), input2: []byte("foobar")}, 1207 } 1208 1209 cases := []struct { 1210 kind reflect.Kind 1211 tagNumber int 1212 fieldName string 1213 }{ 1214 {kind: reflect.Int32, tagNumber: 1, fieldName: "i"}, 1215 {kind: reflect.Int64, tagNumber: 2, fieldName: "j"}, 1216 {kind: reflect.Int32, tagNumber: 3, fieldName: "k"}, 1217 {kind: reflect.Int64, tagNumber: 4, fieldName: "l"}, 1218 {kind: reflect.Uint32, tagNumber: 5, fieldName: "m"}, 1219 {kind: reflect.Uint64, tagNumber: 6, fieldName: "n"}, 1220 {kind: reflect.Uint32, tagNumber: 7, fieldName: "o"}, 1221 {kind: reflect.Uint64, tagNumber: 8, fieldName: "p"}, 1222 {kind: reflect.Int32, tagNumber: 9, fieldName: "q"}, 1223 {kind: reflect.Int64, tagNumber: 10, fieldName: "r"}, 1224 {kind: reflect.Float32, tagNumber: 11, fieldName: "s"}, 1225 {kind: reflect.Float64, tagNumber: 12, fieldName: "t"}, 1226 {kind: reflect.Slice, tagNumber: 13, fieldName: "u"}, 1227 {kind: reflect.String, tagNumber: 14, fieldName: "v"}, 1228 {kind: reflect.Bool, tagNumber: 15, fieldName: "w"}, 1229 } 1230 1231 for idx, c := range cases { 1232 // instead of iterating through all of the possible input types, we 1233 // just grab a couple via index into cases (so we can easily use the 1234 // tagNumber to build an appropriate entry message) 1235 var i1, i2 int 1236 if idx == 0 { 1237 i1 = len(cases) - 1 1238 } else { 1239 i1 = idx - 1 1240 } 1241 if idx == len(cases)-1 { 1242 i2 = 0 1243 } else { 1244 i2 = idx + 1 1245 } 1246 1247 for _, jdx := range []int{i1, idx, i2} { 1248 k := cases[jdx].kind 1249 i := inputs[k] 1250 1251 mdEntry := md.FindFieldByNumber(int32(cases[jdx].tagNumber)).GetMessageType() 1252 input1 := NewMessage(mdEntry) 1253 input1.SetFieldByNumber(1, "foo") 1254 input1.SetFieldByNumber(2, i.input1) 1255 input2 := NewMessage(mdEntry) 1256 input2.SetFieldByNumber(1, "bar") 1257 input2.SetFieldByNumber(2, i.input2) 1258 1259 // we don't use canAssign because even though type of c.kind might be assignable to k, the 1260 // map entry types are messages which are not assignable 1261 allowed := c.kind == k //canAssign(c.kind, k) 1262 1263 // First run the case using Try* methods 1264 1265 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 1266 1267 _, err := dm.TryGetRepeatedFieldByNumber(c.tagNumber, 0) 1268 testutil.Eq(t, FieldIsNotRepeatedError, err) 1269 1270 err = dm.TryAddRepeatedFieldByNumber(c.tagNumber, input1) 1271 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1272 // make sure value stuck 1273 v, err := dm.TryGetMapFieldByNumber(c.tagNumber, "foo") 1274 testutil.Ok(t, err) 1275 testutil.Eq(t, coerce(i.input1, c.kind), v) 1276 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 1277 } 1278 1279 err = dm.TryAddRepeatedFieldByNumber(c.tagNumber, input2) 1280 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1281 // make sure value stuck 1282 v, err := dm.TryGetMapFieldByNumber(c.tagNumber, "bar") 1283 testutil.Ok(t, err) 1284 testutil.Eq(t, coerce(i.input2, c.kind), v) 1285 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 1286 } 1287 1288 err = dm.TrySetRepeatedFieldByNumber(c.tagNumber, 0, input2) 1289 testutil.Eq(t, FieldIsNotRepeatedError, err) 1290 1291 err = dm.TryClearFieldByNumber(c.tagNumber) 1292 testutil.Ok(t, err) 1293 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 1294 1295 err = dm.TrySetFieldByNumber(c.tagNumber, []interface{}{input1, input2}) 1296 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1297 // make sure values stuck 1298 v, err := dm.TryGetMapFieldByNumber(c.tagNumber, "foo") 1299 testutil.Ok(t, err) 1300 testutil.Eq(t, coerce(i.input1, c.kind), v) 1301 v, err = dm.TryGetMapFieldByNumber(c.tagNumber, "bar") 1302 testutil.Ok(t, err) 1303 testutil.Eq(t, coerce(i.input2, c.kind), v) 1304 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 1305 } 1306 1307 err = dm.TryClearFieldByNumber(c.tagNumber) 1308 testutil.Ok(t, err) 1309 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 1310 1311 // Now use the try ByName methods 1312 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 1313 1314 _, err = dm.TryGetRepeatedFieldByName(c.fieldName, 0) 1315 testutil.Eq(t, FieldIsNotRepeatedError, err) 1316 1317 err = dm.TryAddRepeatedFieldByName(c.fieldName, input1) 1318 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1319 // make sure value stuck 1320 v, err := dm.TryGetMapFieldByName(c.fieldName, "foo") 1321 testutil.Ok(t, err) 1322 testutil.Eq(t, coerce(i.input1, c.kind), v) 1323 testutil.Require(t, dm.HasFieldName(c.fieldName)) 1324 } 1325 1326 err = dm.TryAddRepeatedFieldByName(c.fieldName, input2) 1327 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1328 // make sure value stuck 1329 v, err := dm.TryGetMapFieldByName(c.fieldName, "bar") 1330 testutil.Ok(t, err) 1331 testutil.Eq(t, coerce(i.input2, c.kind), v) 1332 testutil.Require(t, dm.HasFieldName(c.fieldName)) 1333 } 1334 1335 err = dm.TrySetRepeatedFieldByName(c.fieldName, 0, input2) 1336 testutil.Eq(t, FieldIsNotRepeatedError, err) 1337 1338 err = dm.TryClearFieldByName(c.fieldName) 1339 testutil.Ok(t, err) 1340 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 1341 1342 err = dm.TrySetFieldByName(c.fieldName, []interface{}{input1, input2}) 1343 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1344 // make sure values stuck 1345 v, err := dm.TryGetMapFieldByName(c.fieldName, "foo") 1346 testutil.Ok(t, err) 1347 testutil.Eq(t, coerce(i.input1, c.kind), v) 1348 v, err = dm.TryGetMapFieldByName(c.fieldName, "bar") 1349 testutil.Ok(t, err) 1350 testutil.Eq(t, coerce(i.input2, c.kind), v) 1351 testutil.Require(t, dm.HasFieldName(c.fieldName)) 1352 } 1353 1354 err = dm.TryClearFieldByName(c.fieldName) 1355 testutil.Ok(t, err) 1356 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 1357 1358 // Now we do it again using the non-Try* methods (e.g. the ones that panic) 1359 1360 err = catchPanic(func() { dm.GetRepeatedFieldByNumber(c.tagNumber, 0) }) 1361 testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic) 1362 1363 err = catchPanic(func() { dm.AddRepeatedFieldByNumber(c.tagNumber, input1) }) 1364 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1365 // make sure value stuck 1366 v := dm.GetMapFieldByNumber(c.tagNumber, "foo") 1367 testutil.Eq(t, coerce(i.input1, c.kind), v) 1368 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 1369 } 1370 1371 err = catchPanic(func() { dm.AddRepeatedFieldByNumber(c.tagNumber, input2) }) 1372 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1373 // make sure value stuck 1374 v := dm.GetMapFieldByNumber(c.tagNumber, "bar") 1375 testutil.Eq(t, coerce(i.input2, c.kind), v) 1376 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 1377 } 1378 1379 err = catchPanic(func() { dm.SetRepeatedFieldByNumber(c.tagNumber, 0, input2) }) 1380 testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic) 1381 1382 dm.ClearFieldByNumber(c.tagNumber) 1383 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 1384 1385 err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, []interface{}{input1, input2}) }) 1386 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1387 // make sure values stuck 1388 v := dm.GetMapFieldByNumber(c.tagNumber, "foo") 1389 testutil.Eq(t, coerce(i.input1, c.kind), v) 1390 v = dm.GetMapFieldByNumber(c.tagNumber, "bar") 1391 testutil.Eq(t, coerce(i.input2, c.kind), v) 1392 testutil.Require(t, dm.HasFieldNumber(c.tagNumber)) 1393 } 1394 1395 dm.ClearFieldByNumber(c.tagNumber) 1396 testutil.Require(t, !dm.HasFieldNumber(c.tagNumber)) 1397 1398 // Now the non-try ByName methods 1399 err = catchPanic(func() { dm.GetRepeatedFieldByName(c.fieldName, 0) }) 1400 testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic) 1401 1402 err = catchPanic(func() { dm.AddRepeatedFieldByName(c.fieldName, input1) }) 1403 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1404 // make sure value stuck 1405 v := dm.GetMapFieldByName(c.fieldName, "foo") 1406 testutil.Eq(t, coerce(i.input1, c.kind), v) 1407 testutil.Require(t, dm.HasFieldName(c.fieldName)) 1408 } 1409 1410 err = catchPanic(func() { dm.AddRepeatedFieldByName(c.fieldName, input2) }) 1411 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1412 // make sure value stuck 1413 v := dm.GetMapFieldByName(c.fieldName, "bar") 1414 testutil.Eq(t, coerce(i.input2, c.kind), v) 1415 testutil.Require(t, dm.HasFieldName(c.fieldName)) 1416 } 1417 1418 err = catchPanic(func() { dm.SetRepeatedFieldByName(c.fieldName, 0, input2) }) 1419 testutil.Eq(t, FieldIsNotRepeatedError.Error(), err.(panicError).panic) 1420 1421 dm.ClearFieldByName(c.fieldName) 1422 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 1423 1424 err = catchPanic(func() { dm.SetFieldByName(c.fieldName, []interface{}{input1, input2}) }) 1425 if shouldTestValue(t, err, allowed, k, c.kind, idx) { 1426 // make sure values stuck 1427 v := dm.GetMapFieldByName(c.fieldName, "foo") 1428 testutil.Eq(t, coerce(i.input1, c.kind), v) 1429 v = dm.GetMapFieldByName(c.fieldName, "bar") 1430 testutil.Eq(t, coerce(i.input2, c.kind), v) 1431 testutil.Require(t, dm.HasFieldName(c.fieldName)) 1432 } 1433 1434 dm.ClearFieldByNumber(c.tagNumber) 1435 testutil.Require(t, !dm.HasFieldName(c.fieldName)) 1436 1437 } 1438 } 1439 } 1440 1441 func shouldTestValue(t *testing.T, err error, expectOk bool, sk, tk reflect.Kind, idx int) bool { 1442 if expectOk && err != nil { 1443 t.Errorf("Not expecting an error assigning a %v to a %v (case #%d): %s", sk, tk, idx, err.Error()) 1444 return false 1445 } else if !expectOk && err == nil { 1446 t.Errorf("Expecting an error assigning a %v to a %v (case #%d)", sk, tk, idx) 1447 return false 1448 } else { 1449 return expectOk 1450 } 1451 } 1452 1453 func coerce(v interface{}, k reflect.Kind) interface{} { 1454 switch k { 1455 case reflect.Int64: 1456 return reflect.ValueOf(v).Int() 1457 case reflect.Uint64: 1458 return reflect.ValueOf(v).Uint() 1459 case reflect.Float64: 1460 return reflect.ValueOf(v).Float() 1461 default: 1462 return v 1463 } 1464 } 1465 1466 func coerceSlice(v interface{}, k reflect.Kind) interface{} { 1467 switch k { 1468 case reflect.Int64: 1469 rv := reflect.ValueOf(v) 1470 sl := make([]int64, rv.Len()) 1471 for i := range sl { 1472 sl[i] = reflect.ValueOf(rv.Index(i).Interface()).Int() 1473 } 1474 return sl 1475 case reflect.Uint64: 1476 rv := reflect.ValueOf(v) 1477 sl := make([]uint64, rv.Len()) 1478 for i := range sl { 1479 sl[i] = reflect.ValueOf(rv.Index(i).Interface()).Uint() 1480 } 1481 return sl 1482 case reflect.Float64: 1483 rv := reflect.ValueOf(v) 1484 sl := make([]float64, rv.Len()) 1485 for i := range sl { 1486 sl[i] = reflect.ValueOf(rv.Index(i).Interface()).Float() 1487 } 1488 return sl 1489 default: 1490 return v 1491 } 1492 } 1493 1494 func coerceMapKeys(v interface{}, k reflect.Kind) interface{} { 1495 switch k { 1496 case reflect.Int64: 1497 rv := reflect.ValueOf(v) 1498 m := make(map[int64]interface{}, rv.Len()) 1499 for _, key := range rv.MapKeys() { 1500 val := rv.MapIndex(key) 1501 m[reflect.ValueOf(key.Interface()).Int()] = val.Interface() 1502 } 1503 return m 1504 case reflect.Uint64: 1505 rv := reflect.ValueOf(v) 1506 m := make(map[uint64]interface{}, rv.Len()) 1507 for _, key := range rv.MapKeys() { 1508 val := rv.MapIndex(key) 1509 m[reflect.ValueOf(key.Interface()).Uint()] = val.Interface() 1510 } 1511 return m 1512 // no case for Float64 because map keys can't be floats 1513 default: 1514 return v 1515 } 1516 } 1517 1518 func coerceMapVals(v interface{}, k reflect.Kind) interface{} { 1519 switch k { 1520 case reflect.Int64: 1521 rv := reflect.ValueOf(v) 1522 m := make(map[interface{}]int64, rv.Len()) 1523 for _, key := range rv.MapKeys() { 1524 val := rv.MapIndex(key) 1525 m[key.Interface()] = reflect.ValueOf(val.Interface()).Int() 1526 } 1527 return m 1528 case reflect.Uint64: 1529 rv := reflect.ValueOf(v) 1530 m := make(map[interface{}]uint64, rv.Len()) 1531 for _, key := range rv.MapKeys() { 1532 val := rv.MapIndex(key) 1533 m[key.Interface()] = reflect.ValueOf(val.Interface()).Uint() 1534 } 1535 return m 1536 case reflect.Float64: 1537 rv := reflect.ValueOf(v) 1538 m := make(map[interface{}]float64, rv.Len()) 1539 for _, key := range rv.MapKeys() { 1540 val := rv.MapIndex(key) 1541 m[key.Interface()] = reflect.ValueOf(val.Interface()).Float() 1542 } 1543 return m 1544 default: 1545 return v 1546 } 1547 } 1548 1549 func TestGetSetExtensionFields(t *testing.T) { 1550 fd, err := desc.LoadFileDescriptor("desc_test1.proto") 1551 testutil.Ok(t, err) 1552 md := fd.FindSymbol("testprotos.AnotherTestMessage").(*desc.MessageDescriptor) 1553 dm := NewMessage(md) 1554 1555 inputs := map[reflect.Kind]struct { 1556 input interface{} 1557 zero interface{} 1558 }{ 1559 reflect.Ptr: { 1560 input: &testprotos.TestMessage{Ne: []testprotos.TestMessage_NestedEnum{testprotos.TestMessage_VALUE1}}, 1561 zero: (*testprotos.TestMessage)(nil), 1562 }, 1563 reflect.Int32: {input: int32(-12), zero: int32(0)}, 1564 reflect.Uint64: {input: uint64(4567), zero: uint64(0)}, 1565 reflect.String: {input: "foobar", zero: ""}, 1566 reflect.Slice: {input: []bool{true, false, true, false, true}, zero: []bool(nil)}} 1567 1568 cases := []struct { 1569 kind reflect.Kind 1570 extfd *desc.FieldDescriptor 1571 }{ 1572 {kind: reflect.Ptr, extfd: loadExtension(t, testprotos.E_Xtm)}, 1573 {kind: reflect.Int32, extfd: loadExtension(t, testprotos.E_Xi)}, 1574 {kind: reflect.Uint64, extfd: loadExtension(t, testprotos.E_Xui)}, 1575 {kind: reflect.String, extfd: loadExtension(t, testprotos.E_Xs)}, 1576 {kind: reflect.Slice, extfd: loadExtension(t, testprotos.E_TestMessage_NestedMessage_AnotherNestedMessage_Flags)}, 1577 } 1578 1579 for _, c := range cases { 1580 zero := inputs[c.kind].zero 1581 1582 for k, i := range inputs { 1583 // First run the case using Try* methods 1584 1585 testutil.Require(t, !dm.HasField(c.extfd)) 1586 1587 v, err := dm.TryGetField(c.extfd) 1588 testutil.Ok(t, err) 1589 if c.kind == reflect.Ptr { 1590 testutil.Ceq(t, zero, v, eqm) 1591 } else { 1592 testutil.Eq(t, zero, v) 1593 } 1594 1595 err = dm.TrySetField(c.extfd, i.input) 1596 if k == c.kind && err != nil { 1597 t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error()) 1598 } else if k != c.kind && err == nil { 1599 t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind) 1600 } else if k == c.kind { 1601 // make sure value stuck 1602 v, err = dm.TryGetField(c.extfd) 1603 testutil.Ok(t, err) 1604 testutil.Eq(t, i.input, v) 1605 testutil.Require(t, dm.HasField(c.extfd)) 1606 } 1607 1608 err = dm.TryClearField(c.extfd) 1609 testutil.Ok(t, err) 1610 testutil.Require(t, !dm.HasField(c.extfd)) 1611 1612 v, err = dm.TryGetField(c.extfd) 1613 testutil.Ok(t, err) 1614 if c.kind == reflect.Ptr { 1615 testutil.Ceq(t, zero, v, eqm) 1616 } else { 1617 testutil.Eq(t, zero, v) 1618 } 1619 1620 // Now we do it again using the non-Try* methods (e.g. the ones that panic) 1621 1622 v = dm.GetField(c.extfd) 1623 if c.kind == reflect.Ptr { 1624 testutil.Ceq(t, zero, v, eqm) 1625 } else { 1626 testutil.Eq(t, zero, v) 1627 } 1628 1629 err = catchPanic(func() { dm.SetField(c.extfd, i.input) }) 1630 if k == c.kind && err != nil { 1631 t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error()) 1632 } else if k != c.kind && err == nil { 1633 t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind) 1634 } else if k == c.kind { 1635 // make sure value stuck 1636 v = dm.GetField(c.extfd) 1637 testutil.Eq(t, i.input, v) 1638 testutil.Require(t, dm.HasField(c.extfd)) 1639 } 1640 1641 dm.ClearField(c.extfd) 1642 testutil.Require(t, !dm.HasField(c.extfd)) 1643 1644 v = dm.GetField(c.extfd) 1645 if c.kind == reflect.Ptr { 1646 testutil.Ceq(t, zero, v, eqm) 1647 } else { 1648 testutil.Eq(t, zero, v) 1649 } 1650 } 1651 } 1652 } 1653 1654 func TestGetSetExtensionFields_ByTagNumber(t *testing.T) { 1655 fd, err := desc.LoadFileDescriptor("desc_test1.proto") 1656 testutil.Ok(t, err) 1657 md := fd.FindSymbol("testprotos.AnotherTestMessage").(*desc.MessageDescriptor) 1658 er := NewExtensionRegistryWithDefaults() 1659 dm := NewMessageFactoryWithExtensionRegistry(er).NewMessage(md).(*Message) 1660 1661 inputs := map[reflect.Kind]struct { 1662 input interface{} 1663 zero interface{} 1664 }{ 1665 reflect.Ptr: { 1666 input: &testprotos.TestMessage{Ne: []testprotos.TestMessage_NestedEnum{testprotos.TestMessage_VALUE1}}, 1667 zero: (*testprotos.TestMessage)(nil), 1668 }, 1669 reflect.Int32: {input: int32(-12), zero: int32(0)}, 1670 reflect.Uint64: {input: uint64(4567), zero: uint64(0)}, 1671 reflect.String: {input: "foobar", zero: ""}, 1672 reflect.Slice: {input: []bool{true, false, true, false, true}, zero: []bool(nil)}} 1673 1674 cases := []struct { 1675 kind reflect.Kind 1676 tagNumber int 1677 fieldName string 1678 }{ 1679 {kind: reflect.Ptr, tagNumber: int(testprotos.E_Xtm.Field), fieldName: testprotos.E_Xtm.Name}, 1680 {kind: reflect.Int32, tagNumber: int(testprotos.E_Xi.Field), fieldName: testprotos.E_Xi.Name}, 1681 {kind: reflect.Uint64, tagNumber: int(testprotos.E_Xui.Field), fieldName: testprotos.E_Xui.Name}, 1682 {kind: reflect.String, tagNumber: int(testprotos.E_Xs.Field), fieldName: testprotos.E_Xs.Name}, 1683 {kind: reflect.Slice, tagNumber: int(testprotos.E_TestMessage_NestedMessage_AnotherNestedMessage_Flags.Field), 1684 fieldName: testprotos.E_TestMessage_NestedMessage_AnotherNestedMessage_Flags.Name}, 1685 } 1686 1687 for _, c := range cases { 1688 zero := inputs[c.kind].zero 1689 1690 for k, i := range inputs { 1691 // First run the case using Try* methods 1692 1693 v, err := dm.TryGetFieldByNumber(c.tagNumber) 1694 testutil.Ok(t, err) 1695 if c.kind == reflect.Ptr { 1696 testutil.Ceq(t, zero, v, eqm) 1697 } else { 1698 testutil.Eq(t, zero, v) 1699 } 1700 1701 err = dm.TrySetFieldByNumber(c.tagNumber, i.input) 1702 if k == c.kind && err != nil { 1703 t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error()) 1704 } else if k != c.kind && err == nil { 1705 t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind) 1706 } else if k == c.kind { 1707 // make sure value stuck 1708 v, err = dm.TryGetFieldByNumber(c.tagNumber) 1709 testutil.Ok(t, err) 1710 testutil.Eq(t, i.input, v) 1711 } 1712 1713 err = dm.TryClearFieldByNumber(c.tagNumber) 1714 testutil.Ok(t, err) 1715 1716 v, err = dm.TryGetFieldByNumber(c.tagNumber) 1717 testutil.Ok(t, err) 1718 if c.kind == reflect.Ptr { 1719 testutil.Ceq(t, zero, v, eqm) 1720 } else { 1721 testutil.Eq(t, zero, v) 1722 } 1723 1724 // Now we do it again using the non-Try* methods (e.g. the ones that panic) 1725 1726 v = dm.GetFieldByNumber(c.tagNumber) 1727 if c.kind == reflect.Ptr { 1728 testutil.Ceq(t, zero, v, eqm) 1729 } else { 1730 testutil.Eq(t, zero, v) 1731 } 1732 1733 err = catchPanic(func() { dm.SetFieldByNumber(c.tagNumber, i.input) }) 1734 if k == c.kind && err != nil { 1735 t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error()) 1736 } else if k != c.kind && err == nil { 1737 t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind) 1738 } else if k == c.kind { 1739 // make sure value stuck 1740 v = dm.GetFieldByNumber(c.tagNumber) 1741 testutil.Eq(t, i.input, v) 1742 } 1743 1744 dm.ClearFieldByNumber(c.tagNumber) 1745 1746 v = dm.GetFieldByNumber(c.tagNumber) 1747 if c.kind == reflect.Ptr { 1748 testutil.Ceq(t, zero, v, eqm) 1749 } else { 1750 testutil.Eq(t, zero, v) 1751 } 1752 } 1753 } 1754 } 1755 1756 func TestGetSetExtensionFields_ByName(t *testing.T) { 1757 fd, err := desc.LoadFileDescriptor("desc_test1.proto") 1758 testutil.Ok(t, err) 1759 md := fd.FindSymbol("testprotos.AnotherTestMessage").(*desc.MessageDescriptor) 1760 er := NewExtensionRegistryWithDefaults() 1761 dm := NewMessageFactoryWithExtensionRegistry(er).NewMessage(md).(*Message) 1762 1763 inputs := map[reflect.Kind]struct { 1764 input interface{} 1765 zero interface{} 1766 }{ 1767 reflect.Ptr: { 1768 input: &testprotos.TestMessage{Ne: []testprotos.TestMessage_NestedEnum{testprotos.TestMessage_VALUE1}}, 1769 zero: (*testprotos.TestMessage)(nil), 1770 }, 1771 reflect.Int32: {input: int32(-12), zero: int32(0)}, 1772 reflect.Uint64: {input: uint64(4567), zero: uint64(0)}, 1773 reflect.String: {input: "foobar", zero: ""}, 1774 reflect.Slice: {input: []bool{true, false, true, false, true}, zero: []bool(nil)}} 1775 1776 cases := []struct { 1777 kind reflect.Kind 1778 tagNumber int 1779 fieldName string 1780 }{ 1781 {kind: reflect.Ptr, tagNumber: int(testprotos.E_Xtm.Field), fieldName: testprotos.E_Xtm.Name}, 1782 {kind: reflect.Int32, tagNumber: int(testprotos.E_Xi.Field), fieldName: testprotos.E_Xi.Name}, 1783 {kind: reflect.Uint64, tagNumber: int(testprotos.E_Xui.Field), fieldName: testprotos.E_Xui.Name}, 1784 {kind: reflect.String, tagNumber: int(testprotos.E_Xs.Field), fieldName: testprotos.E_Xs.Name}, 1785 {kind: reflect.Slice, tagNumber: int(testprotos.E_TestMessage_NestedMessage_AnotherNestedMessage_Flags.Field), 1786 fieldName: testprotos.E_TestMessage_NestedMessage_AnotherNestedMessage_Flags.Name}, 1787 } 1788 1789 for _, c := range cases { 1790 zero := inputs[c.kind].zero 1791 1792 for k, i := range inputs { 1793 // First run the case using Try* methods 1794 1795 v, err := dm.TryGetFieldByName(c.fieldName) 1796 testutil.Ok(t, err) 1797 if c.kind == reflect.Ptr { 1798 testutil.Ceq(t, zero, v, eqm) 1799 } else { 1800 testutil.Eq(t, zero, v) 1801 } 1802 1803 err = dm.TrySetFieldByName(c.fieldName, i.input) 1804 if k == c.kind && err != nil { 1805 t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error()) 1806 } else if k != c.kind && err == nil { 1807 t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind) 1808 } else if k == c.kind { 1809 // make sure value stuck 1810 v, err = dm.TryGetFieldByName(c.fieldName) 1811 testutil.Ok(t, err) 1812 testutil.Eq(t, i.input, v) 1813 } 1814 1815 err = dm.TryClearFieldByName(c.fieldName) 1816 testutil.Ok(t, err) 1817 1818 v, err = dm.TryGetFieldByName(c.fieldName) 1819 testutil.Ok(t, err) 1820 if c.kind == reflect.Ptr { 1821 testutil.Ceq(t, zero, v, eqm) 1822 } else { 1823 testutil.Eq(t, zero, v) 1824 } 1825 1826 // Now we do it again using the non-Try* methods (e.g. the ones that panic) 1827 1828 v = dm.GetFieldByName(c.fieldName) 1829 if c.kind == reflect.Ptr { 1830 testutil.Ceq(t, zero, v, eqm) 1831 } else { 1832 testutil.Eq(t, zero, v) 1833 } 1834 1835 err = catchPanic(func() { dm.SetFieldByName(c.fieldName, i.input) }) 1836 if k == c.kind && err != nil { 1837 t.Errorf("Not expecting an error assigning a %v to a %v (%v): %s", k, c.kind, c, err.Error()) 1838 } else if k != c.kind && err == nil { 1839 t.Errorf("Expecting an error assigning a %v to a %v", k, c.kind) 1840 } else if k == c.kind { 1841 // make sure value stuck 1842 v = dm.GetFieldByName(c.fieldName) 1843 testutil.Eq(t, i.input, v) 1844 } 1845 1846 dm.ClearFieldByName(c.fieldName) 1847 1848 v = dm.GetFieldByName(c.fieldName) 1849 if c.kind == reflect.Ptr { 1850 testutil.Ceq(t, zero, v, eqm) 1851 } else { 1852 testutil.Eq(t, zero, v) 1853 } 1854 } 1855 } 1856 } 1857 1858 func loadExtension(t *testing.T, ed *proto.ExtensionDesc) *desc.FieldDescriptor { 1859 fd, err := desc.LoadFieldDescriptorForExtension(ed) 1860 testutil.Ok(t, err, "failed to load descriptor for extension %s (%d)", ed.Name, ed.Field) 1861 return fd 1862 } 1863 1864 func TestGetSetOneOfFields(t *testing.T) { 1865 fd, err := desc.LoadFileDescriptor("desc_test2.proto") 1866 testutil.Ok(t, err) 1867 md := fd.FindSymbol("testprotos.Frobnitz").(*desc.MessageDescriptor) 1868 dm := NewMessage(md) 1869 1870 fdc1 := md.FindFieldByName("c1") 1871 fdc2 := md.FindFieldByName("c2") 1872 fdg1 := md.FindFieldByName("g1") 1873 fdg2 := md.FindFieldByName("g2") 1874 fdg3 := md.FindFieldByName("g3") 1875 1876 oodc := md.GetFile().FindSymbol("testprotos.Frobnitz.abc").(*desc.OneOfDescriptor) 1877 oodg := md.GetFile().FindSymbol("testprotos.Frobnitz.def").(*desc.OneOfDescriptor) 1878 1879 // nothing set 1880 fld, v := dm.GetOneOfField(oodc) 1881 testutil.Require(t, fld == nil && v == nil) 1882 fld, v = dm.GetOneOfField(oodg) 1883 testutil.Require(t, fld == nil && v == nil) 1884 1885 nm := &testprotos.TestMessage_NestedMessage{} 1886 dm.SetField(fdc1, nm) 1887 fld, v = dm.GetOneOfField(oodc) 1888 testutil.Eq(t, fdc1, fld) 1889 testutil.Eq(t, nm, v) 1890 fld, v = dm.GetOneOfField(oodg) // other one-of untouched 1891 testutil.Require(t, fld == nil && v == nil) 1892 1893 // setting c2 should unset field c1 1894 dm.SetField(fdc2, testprotos.TestMessage_VALUE1) 1895 fld, v = dm.GetOneOfField(oodc) 1896 testutil.Eq(t, fdc2, fld) 1897 testutil.Eq(t, int32(testprotos.TestMessage_VALUE1), v) 1898 testutil.Require(t, !dm.HasField(fdc1)) 1899 1900 // try other one-of, too 1901 dm.SetField(fdg1, int32(321)) 1902 fld, v = dm.GetOneOfField(oodg) 1903 testutil.Eq(t, fdg1, fld) 1904 testutil.Eq(t, int32(321), v) 1905 fld, v = dm.GetOneOfField(oodc) // other one-of untouched 1906 testutil.Eq(t, fdc2, fld) 1907 testutil.Eq(t, int32(testprotos.TestMessage_VALUE1), v) 1908 1909 // setting g2 should unset field g1 1910 dm.SetField(fdg2, int32(654)) 1911 fld, v = dm.GetOneOfField(oodg) 1912 testutil.Eq(t, fdg2, fld) 1913 testutil.Eq(t, int32(654), v) 1914 testutil.Require(t, !dm.HasField(fdg1)) 1915 1916 // similar for g3 1917 dm.SetField(fdg3, uint32(987)) 1918 fld, v = dm.GetOneOfField(oodg) 1919 testutil.Eq(t, fdg3, fld) 1920 testutil.Eq(t, uint32(987), v) 1921 testutil.Require(t, !dm.HasField(fdg1)) 1922 testutil.Require(t, !dm.HasField(fdg2)) 1923 1924 // ensure clearing fields behaves as expected 1925 dm.ClearField(fdc2) 1926 fld, v = dm.GetOneOfField(oodc) 1927 testutil.Require(t, fld == nil && v == nil) 1928 1929 dm.ClearField(fdg3) 1930 fld, v = dm.GetOneOfField(oodg) 1931 testutil.Require(t, fld == nil && v == nil) 1932 } 1933 1934 func TestSetGetOneOfDefaultValue(t *testing.T) { 1935 md, err := desc.LoadMessageDescriptorForMessage((*testprotos.OneOfMessage)(nil)) 1936 testutil.Ok(t, err) 1937 oneof := md.GetFile().FindSymbol("testprotos.OneOfMessage.value").(*desc.OneOfDescriptor) 1938 1939 var testCases = []struct { 1940 fieldName string 1941 fieldValue interface{} 1942 }{ 1943 {"binary_value", []byte{}}, 1944 {"string_value", ""}, 1945 {"boolean_value", false}, 1946 {"int_value", int32(0)}, 1947 {"int64_value", int64(0)}, 1948 {"double_value", float64(0)}, 1949 {"float_value", float32(0)}, 1950 {"msg_value", (*testprotos.OneOfMessage)(nil)}, 1951 } 1952 1953 for _, tc := range testCases { 1954 dm := NewMessage(md) 1955 field := md.FindFieldByName(tc.fieldName) 1956 dm.SetField(field, tc.fieldValue) 1957 1958 // Ensure that the zero-value is set correctly 1959 oneOfField, resultValue := dm.GetOneOfField(oneof) 1960 testutil.Eq(t, tc.fieldValue, resultValue) 1961 testutil.Eq(t, field, oneOfField) 1962 1963 // Ensure that clearing the field results in no field being set 1964 dm.ClearField(field) 1965 oneOfField, resultValue = dm.GetOneOfField(oneof) 1966 testutil.Eq(t, nil, resultValue) 1967 testutil.Eq(t, (*desc.FieldDescriptor)(nil), oneOfField) 1968 } 1969 } 1970 1971 func TestForEachMapFieldEntry(t *testing.T) { 1972 data := map[string]float64{ 1973 "pi": 3.14159, 1974 "e": 2.71828, 1975 "answer": 42, 1976 } 1977 msg := testprotos.MapValFields{ 1978 T: data, 1979 } 1980 dm, err := AsDynamicMessage(&msg) 1981 testutil.Ok(t, err) 1982 1983 count := 0 1984 entries := map[string]float64{} 1985 dm.ForEachMapFieldEntryByName("t", func(k, v interface{}) bool { 1986 count++ 1987 entries[k.(string)] = v.(float64) 1988 return true 1989 }) 1990 testutil.Eq(t, 3, count) 1991 testutil.Eq(t, data, entries) 1992 1993 count = 0 1994 dm.ForEachMapFieldEntryByName("t", func(k, v interface{}) bool { 1995 count++ 1996 // break immediately 1997 return false 1998 }) 1999 // only saw first entry 2000 testutil.Eq(t, 1, count) 2001 } 2002 2003 func TestSetIntroducesNewField(t *testing.T) { 2004 // TODO 2005 } 2006 2007 func TestGetEnablesParsingUnknownField(t *testing.T) { 2008 // TODO 2009 } 2010 2011 func TestSetClearsUnknownFields(t *testing.T) { 2012 // TODO 2013 } 2014 2015 func TestMergeInto(t *testing.T) { 2016 // TODO 2017 } 2018 2019 func TestMergeFrom(t *testing.T) { 2020 // TODO 2021 } 2022 2023 func TestGetDescriptor(t *testing.T) { 2024 type generatedMessage interface { 2025 proto.Message 2026 Descriptor() ([]byte, []int) 2027 } 2028 2029 testCases := []struct { 2030 name string 2031 genMsg generatedMessage 2032 }{ 2033 {name: "top-level message", genMsg: (*testprotos.TestMessage)(nil)}, 2034 {name: "nested message", genMsg: (*testprotos.TestMessage_NestedMessage)(nil)}, 2035 {name: "deeply nested message", genMsg: (*testprotos.TestMessage_NestedMessage_AnotherNestedMessage_YetAnotherNestedMessage)(nil)}, 2036 } 2037 for _, testCase := range testCases { 2038 md, err := desc.LoadMessageDescriptorForMessage(testCase.genMsg) 2039 testutil.Ok(t, err, "%s: failed to load descriptor", testCase.name) 2040 2041 dynMsg := NewMessage(md) 2042 actualBytes, actualPath := dynMsg.Descriptor() 2043 2044 expectedBytes, expectedPath := testCase.genMsg.Descriptor() 2045 testutil.Eq(t, expectedPath, actualPath, "%s: descriptor paths are not the same", testCase.name) 2046 2047 actualFd, err := internal.DecodeFileDescriptor("TestMessage", actualBytes) 2048 // desc.LoadMessageDescriptorForMessage above can incorporate source code info that will 2049 // not be present when directly calling generated messages's Descriptor method 2050 actualFd.SourceCodeInfo = nil 2051 testutil.Ok(t, err, "%s: failed to decode descriptor from bytes", testCase.name) 2052 expectedFd, err := internal.DecodeFileDescriptor("TestMessage", expectedBytes) 2053 testutil.Ok(t, err, "%s: failed to decode descriptor from bytes", testCase.name) 2054 2055 testutil.Ceq(t, expectedFd, actualFd, eqpm, "%s: descriptors do not match", testCase.name) 2056 } 2057 } 2058 2059 type panicError struct { 2060 panic interface{} 2061 } 2062 2063 func (e panicError) Error() string { 2064 return fmt.Sprintf("panic: %v", e.panic) 2065 } 2066 2067 func catchPanic(action func()) (err error) { 2068 defer func() { 2069 e := recover() 2070 if e != nil { 2071 err = panicError{e} 2072 } 2073 }() 2074 2075 action() 2076 return nil 2077 }