github.com/grpc-ecosystem/grpc-gateway/v2@v2.19.1/runtime/query_test.go (about) 1 package runtime_test 2 3 import ( 4 "errors" 5 "net/url" 6 "strconv" 7 "testing" 8 "time" 9 10 "github.com/google/go-cmp/cmp" 11 "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 12 "github.com/grpc-ecosystem/grpc-gateway/v2/runtime/internal/examplepb" 13 "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" 14 "google.golang.org/protobuf/proto" 15 "google.golang.org/protobuf/testing/protocmp" 16 "google.golang.org/protobuf/types/known/durationpb" 17 field_mask "google.golang.org/protobuf/types/known/fieldmaskpb" 18 "google.golang.org/protobuf/types/known/structpb" 19 "google.golang.org/protobuf/types/known/timestamppb" 20 "google.golang.org/protobuf/types/known/wrapperspb" 21 ) 22 23 func BenchmarkPopulateQueryParameters(b *testing.B) { 24 timeT := time.Date(2016, time.December, 15, 12, 23, 32, 49, time.UTC) 25 timeStr := timeT.Format(time.RFC3339Nano) 26 27 durationT := 13 * time.Hour 28 durationStr := durationT.String() 29 30 fieldmaskStr := "float_value,double_value" 31 32 msg := &examplepb.Proto3Message{} 33 values := url.Values{ 34 "float_value": {"1.5"}, 35 "double_value": {"2.5"}, 36 "int64_value": {"-1"}, 37 "int32_value": {"-2"}, 38 "uint64_value": {"3"}, 39 "uint32_value": {"4"}, 40 "bool_value": {"true"}, 41 "string_value": {"str"}, 42 "bytes_value": {"Ynl0ZXM="}, 43 "repeated_value": {"a", "b", "c"}, 44 "enum_value": {"1"}, 45 "repeated_enum": {"1", "2", "0"}, 46 "timestamp_value": {timeStr}, 47 "duration_value": {durationStr}, 48 "fieldmask_value": {fieldmaskStr}, 49 "optional_string_value": {"optional-str"}, 50 "wrapper_float_value": {"1.5"}, 51 "wrapper_double_value": {"2.5"}, 52 "wrapper_int64_value": {"-1"}, 53 "wrapper_int32_value": {"-2"}, 54 "wrapper_u_int64_value": {"3"}, 55 "wrapper_u_int32_value": {"4"}, 56 "wrapper_bool_value": {"true"}, 57 "wrapper_string_value": {"str"}, 58 "wrapper_bytes_value": {"Ynl0ZXM="}, 59 "map_value[key]": {"value"}, 60 "map_value[second]": {"bar"}, 61 "map_value[third]": {"zzz"}, 62 "map_value[fourth]": {""}, 63 `map_value[~!@#$%^&*()]`: {"value"}, 64 "map_value2[key]": {"-2"}, 65 "map_value3[-2]": {"value"}, 66 "map_value4[key]": {"-1"}, 67 "map_value5[-1]": {"value"}, 68 "map_value6[key]": {"3"}, 69 "map_value7[3]": {"value"}, 70 "map_value8[key]": {"4"}, 71 "map_value9[4]": {"value"}, 72 "map_value10[key]": {"1.5"}, 73 "map_value11[1.5]": {"value"}, 74 "map_value12[key]": {"2.5"}, 75 "map_value13[2.5]": {"value"}, 76 "map_value14[key]": {"true"}, 77 "map_value15[true]": {"value"}, 78 } 79 filter := utilities.NewDoubleArray([][]string{ 80 {"bool_value"}, {"repeated_value"}, 81 }) 82 83 for i := 0; i < b.N; i++ { 84 _ = runtime.PopulateQueryParameters(msg, values, filter) 85 } 86 } 87 88 func TestPopulateParameters(t *testing.T) { 89 timeT := time.Date(2016, time.December, 15, 12, 23, 32, 49, time.UTC) 90 timeStr := timeT.Format(time.RFC3339Nano) 91 timePb := timestamppb.New(timeT) 92 93 durationT := 13 * time.Hour 94 durationStr := durationT.String() 95 durationPb := durationpb.New(durationT) 96 97 fieldmaskStr := "float_value,double_value" 98 fieldmaskPb := &field_mask.FieldMask{Paths: []string{"float_value", "double_value"}} 99 100 structValueJsonStrings := []string{`{"a":{"b":1}}`, `""`, "{}", "[]", "true", "0"} 101 structValueValues := make([]*structpb.Value, len(structValueJsonStrings)) 102 for i := range structValueValues { 103 structValueValues[i] = &structpb.Value{} 104 err := structValueValues[i].UnmarshalJSON([]byte(structValueJsonStrings[i])) 105 if err != nil { 106 t.Errorf("build struct.Value value failed: %s", err.Error()) 107 } 108 } 109 structJsonStrings := []string{`{"a":{"b":1}}`, "{}", `{"c":[1,2],"d":[{"e":1,"f":{}}]}`} 110 structValues := make([]*structpb.Struct, len(structJsonStrings)) 111 for i := range structValues { 112 structValues[i] = &structpb.Struct{} 113 err := structValues[i].UnmarshalJSON([]byte(structJsonStrings[i])) 114 if err != nil { 115 t.Errorf("build struct.Struct value failed: %s", err.Error()) 116 } 117 } 118 119 for i, spec := range []struct { 120 values url.Values 121 filter *utilities.DoubleArray 122 want proto.Message 123 wanterr error 124 }{ 125 { 126 values: url.Values{ 127 "float_value": {"1.5"}, 128 "double_value": {"2.5"}, 129 "int64_value": {"-1"}, 130 "int32_value": {"-2"}, 131 "uint64_value": {"3"}, 132 "uint32_value": {"4"}, 133 "bool_value": {"true"}, 134 "string_value": {"str"}, 135 "bytes_value": {"YWJjMTIzIT8kKiYoKSctPUB-"}, 136 "repeated_value": {"a", "b", "c"}, 137 "repeated_message": {"1", "2", "3"}, 138 "enum_value": {"1"}, 139 "repeated_enum": {"1", "2", "0"}, 140 "timestamp_value": {timeStr}, 141 "duration_value": {durationStr}, 142 "fieldmask_value": {fieldmaskStr}, 143 "wrapper_float_value": {"1.5"}, 144 "wrapper_double_value": {"2.5"}, 145 "wrapper_int64_value": {"-1"}, 146 "wrapper_int32_value": {"-2"}, 147 "wrapper_u_int64_value": {"3"}, 148 "wrapper_u_int32_value": {"4"}, 149 "wrapper_bool_value": {"true"}, 150 "wrapper_string_value": {"str"}, 151 "wrapper_bytes_value": {"YWJjMTIzIT8kKiYoKSctPUB-"}, 152 "map_value[key]": {"value"}, 153 "map_value[second]": {"bar"}, 154 "map_value[third]": {"zzz"}, 155 "map_value[fourth]": {""}, 156 `map_value[~!@#$%^&*()]`: {"value"}, 157 "map_value2[key]": {"-2"}, 158 "map_value3[-2]": {"value"}, 159 "map_value4[key]": {"-1"}, 160 "map_value5[-1]": {"value"}, 161 "map_value6[key]": {"3"}, 162 "map_value7[3]": {"value"}, 163 "map_value8[key]": {"4"}, 164 "map_value9[4]": {"value"}, 165 "map_value10[key]": {"1.5"}, 166 "map_value11[1.5]": {"value"}, 167 "map_value12[key]": {"2.5"}, 168 "map_value13[2.5]": {"value"}, 169 "map_value14[key]": {"true"}, 170 "map_value15[true]": {"value"}, 171 "map_value16[key]": {"2"}, 172 "struct_value_value": {structValueJsonStrings[0]}, 173 "struct_value": {structJsonStrings[0]}, 174 }, 175 filter: utilities.NewDoubleArray(nil), 176 want: &examplepb.Proto3Message{ 177 FloatValue: 1.5, 178 DoubleValue: 2.5, 179 Int64Value: -1, 180 Int32Value: -2, 181 Uint64Value: 3, 182 Uint32Value: 4, 183 BoolValue: true, 184 StringValue: "str", 185 BytesValue: []byte("abc123!?$*&()'-=@~"), 186 RepeatedValue: []string{"a", "b", "c"}, 187 RepeatedMessage: []*wrapperspb.UInt64Value{{Value: 1}, {Value: 2}, {Value: 3}}, 188 EnumValue: examplepb.EnumValue_Y, 189 RepeatedEnum: []examplepb.EnumValue{examplepb.EnumValue_Y, examplepb.EnumValue_Z, examplepb.EnumValue_X}, 190 TimestampValue: timePb, 191 DurationValue: durationPb, 192 FieldmaskValue: fieldmaskPb, 193 WrapperFloatValue: wrapperspb.Float(1.5), 194 WrapperDoubleValue: wrapperspb.Double(2.5), 195 WrapperInt64Value: wrapperspb.Int64(-1), 196 WrapperInt32Value: wrapperspb.Int32(-2), 197 WrapperUInt64Value: wrapperspb.UInt64(3), 198 WrapperUInt32Value: wrapperspb.UInt32(4), 199 WrapperBoolValue: wrapperspb.Bool(true), 200 WrapperStringValue: wrapperspb.String("str"), 201 WrapperBytesValue: wrapperspb.Bytes([]byte("abc123!?$*&()'-=@~")), 202 MapValue: map[string]string{ 203 "key": "value", 204 "second": "bar", 205 "third": "zzz", 206 "fourth": "", 207 `~!@#$%^&*()`: "value", 208 }, 209 MapValue2: map[string]int32{"key": -2}, 210 MapValue3: map[int32]string{-2: "value"}, 211 MapValue4: map[string]int64{"key": -1}, 212 MapValue5: map[int64]string{-1: "value"}, 213 MapValue6: map[string]uint32{"key": 3}, 214 MapValue7: map[uint32]string{3: "value"}, 215 MapValue8: map[string]uint64{"key": 4}, 216 MapValue9: map[uint64]string{4: "value"}, 217 MapValue10: map[string]float32{"key": 1.5}, 218 MapValue12: map[string]float64{"key": 2.5}, 219 MapValue14: map[string]bool{"key": true}, 220 MapValue15: map[bool]string{true: "value"}, 221 MapValue16: map[string]*wrapperspb.UInt64Value{"key": {Value: 2}}, 222 StructValueValue: structValueValues[0], 223 StructValue: structValues[0], 224 }, 225 }, 226 { 227 values: url.Values{ 228 "floatValue": {"1.5"}, 229 "doubleValue": {"2.5"}, 230 "int64Value": {"-1"}, 231 "int32Value": {"-2"}, 232 "uint64Value": {"3"}, 233 "uint32Value": {"4"}, 234 "boolValue": {"true"}, 235 "stringValue": {"str"}, 236 "bytesValue": {"Ynl0ZXM="}, 237 "repeatedValue": {"a", "b", "c"}, 238 "enumValue": {"1"}, 239 "repeatedEnum": {"1", "2", "0"}, 240 "timestampValue": {timeStr}, 241 "durationValue": {durationStr}, 242 "fieldmaskValue": {fieldmaskStr}, 243 "wrapperFloatValue": {"1.5"}, 244 "wrapperDoubleValue": {"2.5"}, 245 "wrapperInt64Value": {"-1"}, 246 "wrapperInt32Value": {"-2"}, 247 "wrapperUInt64Value": {"3"}, 248 "wrapperUInt32Value": {"4"}, 249 "wrapperBoolValue": {"true"}, 250 "wrapperStringValue": {"str"}, 251 "wrapperBytesValue": {"Ynl0ZXM="}, 252 "struct_value_value": {structValueJsonStrings[1]}, 253 "struct_value": {structJsonStrings[1]}, 254 }, 255 filter: utilities.NewDoubleArray(nil), 256 want: &examplepb.Proto3Message{ 257 FloatValue: 1.5, 258 DoubleValue: 2.5, 259 Int64Value: -1, 260 Int32Value: -2, 261 Uint64Value: 3, 262 Uint32Value: 4, 263 BoolValue: true, 264 StringValue: "str", 265 BytesValue: []byte("bytes"), 266 RepeatedValue: []string{"a", "b", "c"}, 267 EnumValue: examplepb.EnumValue_Y, 268 RepeatedEnum: []examplepb.EnumValue{examplepb.EnumValue_Y, examplepb.EnumValue_Z, examplepb.EnumValue_X}, 269 TimestampValue: timePb, 270 DurationValue: durationPb, 271 FieldmaskValue: fieldmaskPb, 272 WrapperFloatValue: wrapperspb.Float(1.5), 273 WrapperDoubleValue: wrapperspb.Double(2.5), 274 WrapperInt64Value: wrapperspb.Int64(-1), 275 WrapperInt32Value: wrapperspb.Int32(-2), 276 WrapperUInt64Value: wrapperspb.UInt64(3), 277 WrapperUInt32Value: wrapperspb.UInt32(4), 278 WrapperBoolValue: wrapperspb.Bool(true), 279 WrapperStringValue: wrapperspb.String("str"), 280 WrapperBytesValue: wrapperspb.Bytes([]byte("bytes")), 281 StructValueValue: structValueValues[1], 282 StructValue: structValues[1], 283 }, 284 }, 285 { 286 values: url.Values{ 287 "enum_value": {"Z"}, 288 "repeated_enum": {"X", "2", "0"}, 289 "struct_value_value": {structValueJsonStrings[2]}, 290 "struct_value": {structJsonStrings[2]}, 291 }, 292 filter: utilities.NewDoubleArray(nil), 293 want: &examplepb.Proto3Message{ 294 EnumValue: examplepb.EnumValue_Z, 295 RepeatedEnum: []examplepb.EnumValue{examplepb.EnumValue_X, examplepb.EnumValue_Z, examplepb.EnumValue_X}, 296 StructValueValue: structValueValues[2], 297 StructValue: structValues[2], 298 }, 299 }, 300 { 301 values: url.Values{ 302 "struct_value_value": {structValueJsonStrings[3]}, 303 }, 304 filter: utilities.NewDoubleArray(nil), 305 want: &examplepb.Proto3Message{ 306 StructValueValue: structValueValues[3], 307 }, 308 }, 309 { 310 values: url.Values{ 311 "struct_value_value": {structValueJsonStrings[4]}, 312 }, 313 filter: utilities.NewDoubleArray(nil), 314 want: &examplepb.Proto3Message{ 315 StructValueValue: structValueValues[4], 316 }, 317 }, 318 { 319 values: url.Values{ 320 "struct_value_value": {structValueJsonStrings[5]}, 321 }, 322 filter: utilities.NewDoubleArray(nil), 323 want: &examplepb.Proto3Message{ 324 StructValueValue: structValueValues[5], 325 }, 326 }, 327 { 328 values: url.Values{ 329 "float_value": {"1.5"}, 330 "double_value": {"2.5"}, 331 "int64_value": {"-1"}, 332 "int32_value": {"-2"}, 333 "uint64_value": {"3"}, 334 "uint32_value": {"4"}, 335 "bool_value": {"true"}, 336 "string_value": {"str"}, 337 "repeated_value": {"a", "b", "c"}, 338 }, 339 filter: utilities.NewDoubleArray(nil), 340 want: &examplepb.Proto2Message{ 341 FloatValue: proto.Float32(1.5), 342 DoubleValue: proto.Float64(2.5), 343 Int64Value: proto.Int64(-1), 344 Int32Value: proto.Int32(-2), 345 Uint64Value: proto.Uint64(3), 346 Uint32Value: proto.Uint32(4), 347 BoolValue: proto.Bool(true), 348 StringValue: proto.String("str"), 349 RepeatedValue: []string{"a", "b", "c"}, 350 }, 351 }, 352 { 353 values: url.Values{ 354 "floatValue": {"1.5"}, 355 "doubleValue": {"2.5"}, 356 "int64Value": {"-1"}, 357 "int32Value": {"-2"}, 358 "uint64Value": {"3"}, 359 "uint32Value": {"4"}, 360 "boolValue": {"true"}, 361 "stringValue": {"str"}, 362 "repeatedValue": {"a", "b", "c"}, 363 }, 364 filter: utilities.NewDoubleArray(nil), 365 want: &examplepb.Proto2Message{ 366 FloatValue: proto.Float32(1.5), 367 DoubleValue: proto.Float64(2.5), 368 Int64Value: proto.Int64(-1), 369 Int32Value: proto.Int32(-2), 370 Uint64Value: proto.Uint64(3), 371 Uint32Value: proto.Uint32(4), 372 BoolValue: proto.Bool(true), 373 StringValue: proto.String("str"), 374 RepeatedValue: []string{"a", "b", "c"}, 375 }, 376 }, 377 { 378 values: url.Values{ 379 "nested.nested.nested.repeated_value": {"a", "b", "c"}, 380 "nested.nested.nested.string_value": {"s"}, 381 "nested.nested.string_value": {"t"}, 382 "nested.string_value": {"u"}, 383 "nested.nested.map_value[first]": {"foo"}, 384 "nested.nested.map_value[second]": {"bar"}, 385 }, 386 filter: utilities.NewDoubleArray(nil), 387 want: &examplepb.Proto3Message{ 388 Nested: &examplepb.Proto3Message{ 389 Nested: &examplepb.Proto3Message{ 390 MapValue: map[string]string{ 391 "first": "foo", 392 "second": "bar", 393 }, 394 Nested: &examplepb.Proto3Message{ 395 RepeatedValue: []string{"a", "b", "c"}, 396 StringValue: "s", 397 }, 398 StringValue: "t", 399 }, 400 StringValue: "u", 401 }, 402 }, 403 }, 404 { 405 values: url.Values{ 406 "oneof_string_value": {"foobar"}, 407 }, 408 filter: utilities.NewDoubleArray(nil), 409 want: &examplepb.Proto3Message{ 410 OneofValue: &examplepb.Proto3Message_OneofStringValue{ 411 OneofStringValue: "foobar", 412 }, 413 }, 414 }, 415 { 416 values: url.Values{ 417 "oneofStringValue": {"foobar"}, 418 }, 419 filter: utilities.NewDoubleArray(nil), 420 want: &examplepb.Proto3Message{ 421 OneofValue: &examplepb.Proto3Message_OneofStringValue{ 422 OneofStringValue: "foobar", 423 }, 424 }, 425 }, 426 { 427 values: url.Values{ 428 "oneof_bool_value": {"true"}, 429 }, 430 filter: utilities.NewDoubleArray(nil), 431 want: &examplepb.Proto3Message{ 432 OneofValue: &examplepb.Proto3Message_OneofBoolValue{ 433 OneofBoolValue: true, 434 }, 435 }, 436 }, 437 { 438 values: url.Values{ 439 "nested_oneof_value_one.int64Value": {"-1"}, 440 "nested_oneof_value_one.string_value": {"foo"}, 441 }, 442 filter: utilities.NewDoubleArray(nil), 443 want: &examplepb.Proto3Message{ 444 NestedOneofValue: &examplepb.Proto3Message_NestedOneofValueOne{ 445 NestedOneofValueOne: &examplepb.Proto3Message{ 446 Int64Value: -1, 447 StringValue: "foo", 448 }, 449 }, 450 }, 451 }, 452 { 453 // Error on "null" 454 values: url.Values{ 455 "timestampValue": {"null"}, 456 }, 457 filter: utilities.NewDoubleArray(nil), 458 want: &examplepb.Proto3Message{}, 459 wanterr: errors.New(`parsing field "timestamp_value": parsing time "null" as "2006-01-02T15:04:05.999999999Z07:00": cannot parse "null" as "2006"`), 460 }, 461 { 462 // Error on "null" 463 values: url.Values{ 464 "durationValue": {"null"}, 465 }, 466 filter: utilities.NewDoubleArray(nil), 467 want: &examplepb.Proto3Message{}, 468 wanterr: errors.New(`parsing field "duration_value": time: invalid duration "null"`), 469 }, 470 { 471 // Don't allow setting a oneof more than once 472 values: url.Values{ 473 "oneof_bool_value": {"true"}, 474 "oneof_string_value": {"foobar"}, 475 }, 476 filter: utilities.NewDoubleArray(nil), 477 want: &examplepb.Proto3Message{}, 478 wanterr: errors.New("field already set for oneof \"oneof_value\""), 479 }, 480 { 481 // Error when there are too many values 482 values: url.Values{ 483 "uint64_value": {"1", "2"}, 484 }, 485 filter: utilities.NewDoubleArray(nil), 486 want: &examplepb.Proto3Message{}, 487 wanterr: errors.New("too many values for field \"uint64_value\": 1, 2"), 488 }, 489 { 490 // Error when dereferencing a list of messages 491 values: url.Values{ 492 "repeated_message.value": {"1"}, 493 }, 494 filter: utilities.NewDoubleArray(nil), 495 want: &examplepb.Proto3Message{}, 496 wanterr: errors.New("invalid path: \"repeated_message\" is not a message"), 497 }, 498 } { 499 t.Run(strconv.Itoa(i), func(t *testing.T) { 500 msg := spec.want.ProtoReflect().New().Interface() 501 err := runtime.PopulateQueryParameters(msg, spec.values, spec.filter) 502 if spec.wanterr != nil { 503 if err == nil || err.Error() != spec.wanterr.Error() { 504 t.Errorf("runtime.PopulateQueryParameters(msg, %v, %v) failed with %q; want error %q", spec.values, spec.filter, err, spec.wanterr) 505 } 506 return 507 } 508 509 if err != nil { 510 t.Errorf("runtime.PopulateQueryParameters(msg, %v, %v) failed with %v; want success", spec.values, spec.filter, err) 511 return 512 } 513 if diff := cmp.Diff(spec.want, msg, protocmp.Transform()); diff != "" { 514 t.Errorf("runtime.PopulateQueryParameters(msg, %v, %v): %s", spec.values, spec.filter, diff) 515 } 516 }) 517 } 518 } 519 520 func TestPopulateParametersWithFilters(t *testing.T) { 521 for _, spec := range []struct { 522 values url.Values 523 filter *utilities.DoubleArray 524 want proto.Message 525 }{ 526 { 527 values: url.Values{ 528 "bool_value": {"true"}, 529 "string_value": {"str"}, 530 "repeated_value": {"a", "b", "c"}, 531 }, 532 filter: utilities.NewDoubleArray([][]string{ 533 {"bool_value"}, {"repeated_value"}, 534 }), 535 want: &examplepb.Proto3Message{ 536 StringValue: "str", 537 }, 538 }, 539 { 540 values: url.Values{ 541 "nested.nested.bool_value": {"true"}, 542 "nested.nested.string_value": {"str"}, 543 "nested.string_value": {"str"}, 544 "string_value": {"str"}, 545 }, 546 filter: utilities.NewDoubleArray([][]string{ 547 {"nested"}, 548 }), 549 want: &examplepb.Proto3Message{ 550 StringValue: "str", 551 }, 552 }, 553 { 554 values: url.Values{ 555 "nested.nested.bool_value": {"true"}, 556 "nested.nested.string_value": {"str"}, 557 "nested.string_value": {"str"}, 558 "string_value": {"str"}, 559 }, 560 filter: utilities.NewDoubleArray([][]string{ 561 {"nested", "nested"}, 562 }), 563 want: &examplepb.Proto3Message{ 564 Nested: &examplepb.Proto3Message{ 565 StringValue: "str", 566 }, 567 StringValue: "str", 568 }, 569 }, 570 { 571 values: url.Values{ 572 "nested.nested.bool_value": {"true"}, 573 "nested.nested.string_value": {"str"}, 574 "nested.string_value": {"str"}, 575 "string_value": {"str"}, 576 }, 577 filter: utilities.NewDoubleArray([][]string{ 578 {"nested", "nested", "string_value"}, 579 }), 580 want: &examplepb.Proto3Message{ 581 Nested: &examplepb.Proto3Message{ 582 StringValue: "str", 583 Nested: &examplepb.Proto3Message{ 584 BoolValue: true, 585 }, 586 }, 587 StringValue: "str", 588 }, 589 }, 590 } { 591 msg := spec.want.ProtoReflect().New().Interface() 592 err := runtime.PopulateQueryParameters(msg, spec.values, spec.filter) 593 if err != nil { 594 t.Errorf("runtime.PoplateQueryParameters(msg, %v, %v) failed with %v; want success", spec.values, spec.filter, err) 595 continue 596 } 597 if got, want := msg, spec.want; !proto.Equal(got, want) { 598 t.Errorf("runtime.PopulateQueryParameters(msg, %v, %v = %v; want %v", spec.values, spec.filter, got, want) 599 } 600 } 601 } 602 603 func TestPopulateQueryParametersWithInvalidNestedParameters(t *testing.T) { 604 for _, spec := range []struct { 605 msg proto.Message 606 values url.Values 607 filter *utilities.DoubleArray 608 }{ 609 { 610 msg: &examplepb.Proto3Message{}, 611 values: url.Values{ 612 "float_value.nested": {"test"}, 613 }, 614 filter: utilities.NewDoubleArray(nil), 615 }, 616 { 617 msg: &examplepb.Proto3Message{}, 618 values: url.Values{ 619 "double_value.nested": {"test"}, 620 }, 621 filter: utilities.NewDoubleArray(nil), 622 }, 623 { 624 msg: &examplepb.Proto3Message{}, 625 values: url.Values{ 626 "int64_value.nested": {"test"}, 627 }, 628 filter: utilities.NewDoubleArray(nil), 629 }, 630 { 631 msg: &examplepb.Proto3Message{}, 632 values: url.Values{ 633 "int32_value.nested": {"test"}, 634 }, 635 filter: utilities.NewDoubleArray(nil), 636 }, 637 { 638 msg: &examplepb.Proto3Message{}, 639 values: url.Values{ 640 "uint64_value.nested": {"test"}, 641 }, 642 filter: utilities.NewDoubleArray(nil), 643 }, 644 { 645 msg: &examplepb.Proto3Message{}, 646 values: url.Values{ 647 "uint32_value.nested": {"test"}, 648 }, 649 filter: utilities.NewDoubleArray(nil), 650 }, 651 { 652 msg: &examplepb.Proto3Message{}, 653 values: url.Values{ 654 "bool_value.nested": {"test"}, 655 }, 656 filter: utilities.NewDoubleArray(nil), 657 }, 658 { 659 msg: &examplepb.Proto3Message{}, 660 values: url.Values{ 661 "string_value.nested": {"test"}, 662 }, 663 filter: utilities.NewDoubleArray(nil), 664 }, 665 { 666 msg: &examplepb.Proto3Message{}, 667 values: url.Values{ 668 "repeated_value.nested": {"test"}, 669 }, 670 filter: utilities.NewDoubleArray(nil), 671 }, 672 { 673 msg: &examplepb.Proto3Message{}, 674 values: url.Values{ 675 "enum_value.nested": {"test"}, 676 }, 677 filter: utilities.NewDoubleArray(nil), 678 }, 679 { 680 msg: &examplepb.Proto3Message{}, 681 values: url.Values{ 682 "enum_value.nested": {"test"}, 683 }, 684 filter: utilities.NewDoubleArray(nil), 685 }, 686 { 687 msg: &examplepb.Proto3Message{}, 688 values: url.Values{ 689 "repeated_enum.nested": {"test"}, 690 }, 691 filter: utilities.NewDoubleArray(nil), 692 }, 693 } { 694 spec.msg = spec.msg.ProtoReflect().New().Interface() 695 err := runtime.PopulateQueryParameters(spec.msg, spec.values, spec.filter) 696 if err == nil { 697 t.Errorf("runtime.PopulateQueryParameters(msg, %v, %v) did not fail; want error", spec.values, spec.filter) 698 } 699 } 700 }