trpc.group/trpc-go/trpc-go@v1.0.3/restful/serializer_test.go (about) 1 // 2 // 3 // Tencent is pleased to support the open source community by making tRPC available. 4 // 5 // Copyright (C) 2023 THL A29 Limited, a Tencent company. 6 // All rights reserved. 7 // 8 // If you have downloaded a copy of the tRPC source code from Tencent, 9 // please note that tRPC source code is licensed under the Apache 2.0 License, 10 // A copy of the Apache 2.0 License is included in this file. 11 // 12 // 13 14 package restful_test 15 16 import ( 17 "net/url" 18 "reflect" 19 "strings" 20 "testing" 21 22 "trpc.group/trpc-go/trpc-go/restful" 23 "trpc.group/trpc-go/trpc-go/testdata/restful/bookstore" 24 "trpc.group/trpc-go/trpc-go/testdata/restful/helloworld" 25 26 "github.com/google/go-cmp/cmp" 27 "github.com/stretchr/testify/require" 28 "google.golang.org/protobuf/encoding/protojson" 29 "google.golang.org/protobuf/proto" 30 "google.golang.org/protobuf/testing/protocmp" 31 "google.golang.org/protobuf/types/known/durationpb" 32 "google.golang.org/protobuf/types/known/emptypb" 33 "google.golang.org/protobuf/types/known/structpb" 34 "google.golang.org/protobuf/types/known/timestamppb" 35 "google.golang.org/protobuf/types/known/wrapperspb" 36 ) 37 38 var j = &restful.JSONPBSerializer{} 39 var f = &restful.FormSerializer{} 40 var p = &restful.ProtoSerializer{} 41 42 type anonymousSerializer struct { 43 restful.Serializer 44 } 45 46 func (anonymousSerializer) Name() string { return "" } 47 48 type mockSerializer struct { 49 restful.Serializer 50 } 51 52 func (mockSerializer) Name() string { return "mock" } 53 func (mockSerializer) ContentType() string { return "mock" } 54 55 func TestRegisterSerializer(t *testing.T) { 56 for _, test := range []struct { 57 serializer restful.Serializer 58 expectPanic bool 59 desc string 60 }{ 61 { 62 serializer: nil, 63 expectPanic: true, 64 desc: "register nil serializer test", 65 }, 66 { 67 serializer: anonymousSerializer{}, 68 expectPanic: true, 69 desc: "register anonymous serializer test", 70 }, 71 { 72 serializer: mockSerializer{}, 73 expectPanic: false, 74 desc: "register mock serializer test", 75 }, 76 } { 77 register := func() { restful.RegisterSerializer(test.serializer) } 78 if test.expectPanic { 79 require.Panics(t, register, test.desc) 80 } else { 81 require.NotPanics(t, register, test.desc) 82 } 83 var s restful.Serializer 84 if !test.expectPanic { 85 s = restful.GetSerializer(test.serializer.Name()) 86 require.True(t, reflect.DeepEqual(s, test.serializer), test.desc) 87 } 88 } 89 } 90 91 func TestSetDefaultSerializer(t *testing.T) { 92 for _, test := range []struct { 93 serializer restful.Serializer 94 expectPanic bool 95 desc string 96 }{ 97 { 98 serializer: nil, 99 expectPanic: true, 100 desc: "set nil serializer test", 101 }, 102 { 103 serializer: anonymousSerializer{}, 104 expectPanic: true, 105 desc: "set anonymous serializer test", 106 }, 107 { 108 serializer: mockSerializer{}, 109 expectPanic: false, 110 desc: "set mock serializer test", 111 }, 112 } { 113 register := func() { restful.SetDefaultSerializer(test.serializer) } 114 if test.expectPanic { 115 require.Panics(t, register, test.desc) 116 } else { 117 require.NotPanics(t, register, test.desc) 118 } 119 } 120 } 121 122 func TestContentType(t *testing.T) { 123 require.Equal(t, "application/json", j.ContentType()) 124 require.Equal(t, "application/json", f.ContentType()) 125 require.Equal(t, "application/octet-stream", p.ContentType()) 126 } 127 128 func TestProtoSerializer(t *testing.T) { 129 input := &helloworld.HelloRequest{ 130 Name: "nobody", 131 SingleNested: &helloworld.NestedOuter{ 132 Name: "anybody", 133 }, 134 PrimitiveDoubleValue: float64(1.23), 135 Time: ×tamppb.Timestamp{ 136 Seconds: int64(111111111), 137 }, 138 EnumValue: helloworld.NumericEnum_ONE, 139 OneofValue: &helloworld.HelloRequest_OneofString{ 140 OneofString: "oneof", 141 }, 142 MappedStringValue: map[string]string{ 143 "foo": "bar", 144 }, 145 } 146 147 // marshal 148 wrongMarshalObj := "foobar" 149 _, err := p.Marshal(wrongMarshalObj) 150 require.NotNil(t, err) 151 152 buf, err := p.Marshal(input) 153 require.Nil(t, err) 154 155 // unmarshal 156 wrongUnmarshalObj := 1 157 err = p.Unmarshal(buf, &wrongUnmarshalObj) 158 require.NotNil(t, err) 159 160 output := &helloworld.HelloRequest{} 161 err = p.Unmarshal(buf, output) 162 require.Nil(t, err) 163 require.True(t, proto.Equal(input, output)) 164 } 165 166 func TestJSONPBSerializer(t *testing.T) { 167 input := &helloworld.HelloRequest{ 168 Name: "nobody", 169 SingleNested: &helloworld.NestedOuter{ 170 Name: "anybody", 171 }, 172 PrimitiveDoubleValue: float64(1.23), 173 Time: ×tamppb.Timestamp{ 174 Seconds: int64(111111111), 175 }, 176 EnumValue: helloworld.NumericEnum_ONE, 177 OneofValue: &helloworld.HelloRequest_OneofString{ 178 OneofString: "oneof", 179 }, 180 MappedStringValue: map[string]string{ 181 "foo": "bar", 182 }, 183 } 184 // marshal 185 buf, err := j.Marshal(input) 186 require.Nil(t, err) 187 // unmarshal 188 output := &helloworld.HelloRequest{} 189 err = j.Unmarshal(buf, output) 190 require.Nil(t, err) 191 require.True(t, proto.Equal(input, output)) 192 } 193 194 func TestJSONPBSerializerMarshalField(t *testing.T) { 195 for _, test := range []struct { 196 input interface{} 197 want []byte 198 desc string 199 }{ 200 {input: int32(1), want: []byte("1"), desc: "jsonpb marshal field test 01"}, 201 {input: proto.Int32(1), want: []byte("1"), desc: "jsonpb marshal field test 02"}, 202 {input: int64(1), want: []byte("1"), desc: "jsonpb marshal field test 03"}, 203 {input: proto.Int64(1), want: []byte("1"), desc: "jsonpb marshal field test 04"}, 204 {input: uint32(1), want: []byte("1"), desc: "jsonpb marshal field test 05"}, 205 {input: proto.Uint32(1), want: []byte("1"), desc: "jsonpb marshal field test 06"}, 206 {input: uint64(1), want: []byte("1"), desc: "jsonpb marshal field test 07"}, 207 {input: proto.Uint64(1), want: []byte("1"), desc: "jsonpb marshal field test 08"}, 208 {input: "abc", want: []byte(`"abc"`), desc: "jsonpb marshal field test 09"}, 209 {input: proto.String("abc"), want: []byte(`"abc"`), desc: "jsonpb marshal field test 10"}, 210 {input: float32(1.5), want: []byte(`1.5`), desc: "jsonpb marshal field test 11"}, 211 {input: proto.Float32(1.5), want: []byte(`1.5`), desc: "jsonpb marshal field test 12"}, 212 {input: float64(1.5), want: []byte(`1.5`), desc: "jsonpb marshal field test 13"}, 213 {input: proto.Float64(1.5), want: []byte(`1.5`), desc: "jsonpb marshal field test 14"}, 214 {input: true, want: []byte("true"), desc: "jsonpb marshal field test 15"}, 215 {input: false, want: []byte("false"), desc: "jsonpb marshal field test 16"}, 216 {input: (*string)(nil), want: []byte("null"), desc: "jsonpb marshal field test 17"}, 217 { 218 input: helloworld.NumericEnum_ONE, 219 want: []byte(`"ONE"`), 220 desc: "jsonpb marshal field test 18", 221 }, 222 { 223 input: (*helloworld.NumericEnum)(proto.Int32(int32(helloworld.NumericEnum_ONE))), 224 want: []byte(`"ONE"`), 225 desc: "jsonpb marshal field test 19", 226 }, 227 { 228 input: map[string]int32{ 229 "foo": 1, 230 }, 231 want: []byte(`{"foo":1}`), 232 desc: "jsonpb marshal field test 20", 233 }, 234 { 235 input: map[string]*bookstore.Book{ 236 "foo": {Id: 123}, 237 }, 238 want: []byte(`{"foo":{"id":123}}`), 239 desc: "jsonpb marshal field test 21", 240 }, 241 { 242 input: map[int32]*bookstore.Book{ 243 1: {Id: 123}, 244 }, 245 want: []byte(`{"1":{"id":123}}`), 246 desc: "jsonpb marshal field test 22", 247 }, 248 { 249 input: map[bool]*bookstore.Book{ 250 true: {Id: 123}, 251 }, 252 want: []byte(`{"true":{"id":123}}`), 253 desc: "jsonpb marshal field test 23", 254 }, 255 { 256 input: &durationpb.Duration{ 257 Seconds: 123, 258 Nanos: 456000000, 259 }, 260 want: []byte(`"123.456s"`), 261 desc: "jsonpb marshal field test 24", 262 }, 263 { 264 input: ×tamppb.Timestamp{ 265 Seconds: 1462875553, 266 Nanos: 123000000, 267 }, 268 want: []byte(`"2016-05-10T10:19:13.123Z"`), 269 desc: "jsonpb marshal field test 25", 270 }, 271 { 272 input: new(emptypb.Empty), 273 want: []byte("{}"), 274 desc: "jsonpb marshal field test 26", 275 }, 276 { 277 input: &structpb.Value{ 278 Kind: new(structpb.Value_NullValue), 279 }, 280 want: []byte("null"), 281 desc: "jsonpb marshal field test 27", 282 }, 283 { 284 input: &structpb.Value{ 285 Kind: &structpb.Value_NumberValue{ 286 NumberValue: 123.4, 287 }, 288 }, 289 want: []byte("123.4"), 290 desc: "jsonpb marshal field test 28", 291 }, 292 { 293 input: &structpb.Value{ 294 Kind: &structpb.Value_StringValue{ 295 StringValue: "abc", 296 }, 297 }, 298 want: []byte(`"abc"`), 299 desc: "jsonpb marshal field test 29", 300 }, 301 { 302 input: &structpb.Value{ 303 Kind: &structpb.Value_BoolValue{ 304 BoolValue: true, 305 }, 306 }, 307 want: []byte("true"), 308 desc: "jsonpb marshal field test 30", 309 }, 310 { 311 input: &structpb.Struct{ 312 Fields: map[string]*structpb.Value{ 313 "foo_bar": { 314 Kind: &structpb.Value_BoolValue{ 315 BoolValue: true, 316 }, 317 }, 318 }, 319 }, 320 want: []byte(`{"foo_bar":true}`), 321 desc: "jsonpb marshal field test 31", 322 }, 323 324 { 325 input: &wrapperspb.BoolValue{Value: true}, 326 want: []byte("true"), 327 desc: "jsonpb marshal field test 32", 328 }, 329 { 330 input: &wrapperspb.DoubleValue{Value: 123.456}, 331 want: []byte("123.456"), 332 desc: "jsonpb marshal field test 33", 333 }, 334 { 335 input: &wrapperspb.FloatValue{Value: 123.456}, 336 want: []byte("123.456"), 337 desc: "jsonpb marshal field test 34", 338 }, 339 { 340 input: &wrapperspb.Int32Value{Value: -123}, 341 want: []byte("-123"), 342 desc: "jsonpb marshal field test 35", 343 }, 344 { 345 input: &wrapperspb.Int64Value{Value: -123}, 346 want: []byte(`"-123"`), 347 desc: "jsonpb marshal field test 36", 348 }, 349 { 350 input: &wrapperspb.UInt32Value{Value: 123}, 351 want: []byte("123"), 352 desc: "jsonpb marshal field test 37", 353 }, 354 { 355 input: &wrapperspb.UInt64Value{Value: 123}, 356 want: []byte(`"123"`), 357 desc: "jsonpb marshal field test 38", 358 }, 359 { 360 input: []**bookstore.Book{}, 361 want: []byte("[]"), 362 desc: "jsonpb marshal field test 39", 363 }, 364 { 365 input: []*bookstore.Book{{Id: 1}}, 366 want: []byte(`[{"id":"1","author":"","title":"","content":null}]`), 367 desc: "jsonpb marshal field test 40", 368 }, 369 { 370 input: nil, 371 want: []byte("null"), 372 desc: "jsonpb marshal field test 41", 373 }, 374 } { 375 got, err := j.Marshal(test.input) 376 require.Nil(t, err, test.desc) 377 s := strings.Replace(string(got), " ", "", -1) 378 s = strings.Replace(s, "\n", "", -1) 379 s = strings.Replace(s, "\t", "", -1) 380 require.Equal(t, test.want, []byte(s), test.desc) 381 } 382 } 383 384 func TestJSONPBSerializerUnmarshalField(t *testing.T) { 385 for _, test := range []struct { 386 input []byte 387 want interface{} 388 desc string 389 }{ 390 {input: []byte("1"), want: int32(1), desc: "jsonpb unmarshal field test 01"}, 391 {input: []byte("1"), want: proto.Int32(1), desc: "jsonpb unmarshal field test 02"}, 392 {input: []byte("1"), want: int64(1), desc: "jsonpb unmarshal field test 03"}, 393 {input: []byte("1"), want: proto.Int64(1), desc: "jsonpb unmarshal field test 04"}, 394 {input: []byte("1"), want: uint32(1), desc: "jsonpb unmarshal field test 05"}, 395 {input: []byte("1"), want: proto.Uint32(1), desc: "jsonpb unmarshal field test 06"}, 396 {input: []byte("1"), want: uint64(1), desc: "jsonpb unmarshal field test 07"}, 397 {input: []byte("1"), want: proto.Uint64(1), desc: "jsonpb unmarshal field test 08"}, 398 {input: []byte(`"abc"`), want: "abc", desc: "jsonpb unmarshal field test 09"}, 399 {input: []byte(`"abc"`), want: proto.String("abc"), desc: "jsonpb unmarshal field test 10"}, 400 {input: []byte(`1.5`), want: float32(1.5), desc: "jsonpb unmarshal field test 11"}, 401 {input: []byte(`1.5`), want: proto.Float32(1.5), desc: "jsonpb unmarshal field test 12"}, 402 {input: []byte(`1.5`), want: float64(1.5), desc: "jsonpb unmarshal field test 13"}, 403 {input: []byte(`1.5`), want: proto.Float64(1.5), desc: "jsonpb unmarshal field test 14"}, 404 {input: []byte("true"), want: true, desc: "jsonpb unmarshal field test 15"}, 405 {input: []byte("false"), want: false, desc: "jsonpb unmarshal field test 16"}, 406 {input: []byte("null"), want: (*string)(nil), desc: "jsonpb unmarshal field test 17"}, 407 { 408 input: []byte("1"), 409 want: helloworld.NumericEnum_ONE, 410 desc: "jsonpb unmarshal field test 18", 411 }, 412 { 413 input: []byte("1"), 414 want: (*helloworld.NumericEnum)(proto.Int32(int32(helloworld.NumericEnum_ONE))), 415 desc: "jsonpb unmarshal field test 19", 416 }, 417 { 418 input: []byte(`{"foo":1}`), 419 want: map[string]int32{ 420 "foo": 1, 421 }, 422 desc: "jsonpb unmarshal field test 20", 423 }, 424 { 425 input: []byte(`{"foo":{"id":123}}`), 426 want: map[string]*bookstore.Book{ 427 "foo": {Id: 123}, 428 }, 429 desc: "jsonpb unmarshal field test 21", 430 }, 431 { 432 input: []byte(`{"1":{"id":123}}`), 433 want: map[int32]*bookstore.Book{ 434 1: {Id: 123}, 435 }, 436 desc: "jsonpb unmarshal field test 22", 437 }, 438 { 439 input: []byte(`{"true":{"id":123}}`), 440 want: map[bool]*bookstore.Book{ 441 true: {Id: 123}, 442 }, 443 desc: "jsonpb unmarshal field test 23", 444 }, 445 { 446 input: []byte(`"123.456s"`), 447 want: &durationpb.Duration{ 448 Seconds: 123, 449 Nanos: 456000000, 450 }, 451 desc: "jsonpb unmarshal field test 24", 452 }, 453 { 454 input: []byte(`"2016-05-10T10:19:13.123Z"`), 455 want: ×tamppb.Timestamp{ 456 Seconds: 1462875553, 457 Nanos: 123000000, 458 }, 459 desc: "jsonpb unmarshal field test 25", 460 }, 461 { 462 input: []byte("{}"), 463 want: new(emptypb.Empty), 464 desc: "jsonpb unmarshal field test 26", 465 }, 466 { 467 input: []byte("null"), 468 want: &structpb.Value{ 469 Kind: new(structpb.Value_NullValue), 470 }, 471 desc: "jsonpb unmarshal field test 27", 472 }, 473 { 474 input: []byte("123.4"), 475 want: &structpb.Value{ 476 Kind: &structpb.Value_NumberValue{ 477 NumberValue: 123.4, 478 }, 479 }, 480 desc: "jsonpb unmarshal field test 28", 481 }, 482 { 483 input: []byte(`"abc"`), 484 want: &structpb.Value{ 485 Kind: &structpb.Value_StringValue{ 486 StringValue: "abc", 487 }, 488 }, 489 desc: "jsonpb unmarshal field test 29", 490 }, 491 { 492 input: []byte("true"), 493 want: &structpb.Value{ 494 Kind: &structpb.Value_BoolValue{ 495 BoolValue: true, 496 }, 497 }, 498 desc: "jsonpb unmarshal field test 30", 499 }, 500 { 501 input: []byte(`{"foo_bar":true}`), 502 want: &structpb.Struct{ 503 Fields: map[string]*structpb.Value{ 504 "foo_bar": { 505 Kind: &structpb.Value_BoolValue{ 506 BoolValue: true, 507 }, 508 }, 509 }, 510 }, 511 desc: "jsonpb unmarshal field test 31", 512 }, 513 { 514 input: []byte("true"), 515 want: &wrapperspb.BoolValue{Value: true}, 516 desc: "jsonpb unmarshal field test 32", 517 }, 518 { 519 input: []byte("123.456"), 520 want: &wrapperspb.DoubleValue{Value: 123.456}, 521 desc: "jsonpb unmarshal field test 33", 522 }, 523 { 524 input: []byte("123.456"), 525 want: &wrapperspb.FloatValue{Value: 123.456}, 526 desc: "jsonpb unmarshal field test 34", 527 }, 528 { 529 input: []byte("-123"), 530 want: &wrapperspb.Int32Value{Value: -123}, 531 desc: "jsonpb unmarshal field test 35", 532 }, 533 { 534 input: []byte(`"-123"`), 535 want: &wrapperspb.Int64Value{Value: -123}, 536 desc: "jsonpb unmarshal field test 36", 537 }, 538 { 539 input: []byte("123"), 540 want: &wrapperspb.UInt32Value{Value: 123}, 541 desc: "jsonpb unmarshal field test 37", 542 }, 543 { 544 input: []byte(`"123"`), 545 want: &wrapperspb.UInt64Value{Value: 123}, 546 desc: "jsonpb unmarshal field test 38", 547 }, 548 { 549 input: []byte(`{"1":"foo"}`), 550 want: map[uint32]string{ 551 1: "foo", 552 }, 553 desc: "jsonpb unmarshal field test 39", 554 }, 555 { 556 input: []byte(`{"1":"foo"}`), 557 want: map[int64]string{ 558 1: "foo", 559 }, 560 desc: "jsonpb unmarshal field test 40", 561 }, 562 { 563 input: []byte(`{"1":"foo"}`), 564 want: map[uint64]string{ 565 1: "foo", 566 }, 567 desc: "jsonpb unmarshal field test 41", 568 }, 569 { 570 input: []byte(`{"1":"foo"}`), 571 want: map[float32]string{ 572 1: "foo", 573 }, 574 desc: "jsonpb unmarshal field test 42", 575 }, 576 { 577 input: []byte(`{"1":"foo"}`), 578 want: map[float64]string{ 579 1: "foo", 580 }, 581 desc: "jsonpb unmarshal field test 43", 582 }, 583 { 584 input: []byte(`{"1":null}`), 585 want: map[float64]*string{ 586 1: nil, 587 }, 588 desc: "jsonpb unmarshal field test 44", 589 }, 590 { 591 input: []byte(`[{"id":"1"},{"id":"2"}]`), 592 want: []*bookstore.Book{ 593 {Id: 1}, {Id: 2}, 594 }, 595 desc: "jsonpb unmarshal field test 45", 596 }, 597 { 598 input: []byte(`[{"a":true},{"b":true}]`), 599 want: []helloworld.NestedInner{ 600 {A: true}, {B: true}, 601 }, 602 desc: "jsonpb unmarshal field test 46", 603 }, 604 } { 605 rflValue := reflect.New(reflect.TypeOf(test.want)) 606 err := j.Unmarshal(test.input, rflValue.Interface()) 607 require.Nil(t, err, test.desc) 608 require.Equal(t, "", cmp.Diff(rflValue.Elem().Interface(), test.want, protocmp.Transform()), test.desc) 609 } 610 } 611 612 func TestFormSerializerMarshal(t *testing.T) { 613 for _, test := range []struct { 614 input interface{} 615 emitUnpopupated bool 616 expect string 617 desc string 618 }{ 619 { 620 input: &helloworld.HelloRequest{ 621 Name: "nobody", 622 SingleNested: &helloworld.NestedOuter{ 623 Name: "anybody", 624 }, 625 PrimitiveDoubleValue: float64(1.23), 626 Time: ×tamppb.Timestamp{ 627 Seconds: int64(111111111), 628 }, 629 EnumValue: helloworld.NumericEnum_ONE, 630 OneofValue: &helloworld.HelloRequest_OneofString{ 631 OneofString: "oneof", 632 }, 633 MappedStringValue: map[string]string{ 634 "foo": "bar", 635 }, 636 }, 637 emitUnpopupated: false, 638 expect: `{ 639 "name":"nobody", 640 "singleNested":{"name":"anybody"}, 641 "primitiveDoubleValue":1.23, 642 "enumValue":"ONE", 643 "oneofString":"oneof", 644 "mappedStringValue":{"foo":"bar"}, 645 "time":"1973-07-10T00:11:51Z" 646 }`, 647 desc: "form serializer marshal proto message test ", 648 }, 649 { 650 input: helloworld.NumericEnum_ONE, 651 emitUnpopupated: true, 652 expect: `"ONE"`, 653 desc: "form serializer marshal non proto field test", 654 }, 655 } { 656 restful.Marshaller.EmitUnpopulated = test.emitUnpopupated 657 buf, err := f.Marshal(test.input) 658 require.Nil(t, err) 659 want := strings.Replace(test.expect, " ", "", -1) 660 want = strings.Replace(want, "\n", "", -1) 661 want = strings.Replace(want, "\t", "", -1) 662 got := strings.Replace(string(buf), " ", "", -1) 663 got = strings.Replace(got, "\n", "", -1) 664 got = strings.Replace(got, "\t", "", -1) 665 require.Equal(t, want, got, test.desc) 666 } 667 } 668 669 func TestFormSerializerUnmarshal(t *testing.T) { 670 for _, test := range []struct { 671 data []byte 672 unmarshalObj interface{} 673 want interface{} 674 wantErr bool 675 desc string 676 }{ 677 { 678 data: []byte(url.Values{ 679 "name": []string{"nobody"}, 680 "single_nested.name": []string{"anybody"}, 681 "primitive_bool_value": []string{"true"}, 682 "primitive_int32_value": []string{"1"}, 683 "primitive_uint32_value": []string{"1"}, 684 "primitive_int64_value": []string{"1"}, 685 "primitive_uint64_value": []string{"1"}, 686 "primitive_float_value": []string{"1"}, 687 "primitive_double_value": []string{"1.23"}, 688 "primitive_bytes_value": []string{""}, 689 "time": []string{"1970-01-01T00:00:01Z"}, 690 "duration": []string{"0"}, 691 "wrapped_bool_value": []string{"true"}, 692 "wrapped_int32_value": []string{"1"}, 693 "wrapped_uint32_value": []string{"1"}, 694 "wrapped_int64_value": []string{"1"}, 695 "wrapped_uint64_value": []string{"1"}, 696 "wrapped_float_value": []string{"1"}, 697 "wrapped_double_value": []string{"1"}, 698 "wrapped_str_value": []string{"foo"}, 699 "wrapped_bytes_value": []string{""}, 700 "enum_value": []string{"1"}, 701 "oneof_string": []string{"oneof"}, 702 "mapped_string_value": []string{"foo", "bar"}, 703 "repeated_string_value": []string{"foobar", "foo", "bar", "baz"}, 704 }.Encode()), 705 unmarshalObj: &helloworld.HelloRequest{}, 706 want: &helloworld.HelloRequest{ 707 Name: "nobody", 708 SingleNested: &helloworld.NestedOuter{ 709 Name: "anybody", 710 }, 711 PrimitiveBoolValue: true, 712 PrimitiveInt32Value: 1, 713 PrimitiveUint32Value: 1, 714 PrimitiveInt64Value: 1, 715 PrimitiveUint64Value: 1, 716 PrimitiveFloatValue: 1, 717 PrimitiveDoubleValue: float64(1.23), 718 PrimitiveBytesValue: []byte(""), 719 Time: ×tamppb.Timestamp{ 720 Seconds: int64(1), 721 }, 722 Duration: &durationpb.Duration{}, 723 WrappedBoolValue: &wrapperspb.BoolValue{Value: true}, 724 WrappedFloatValue: &wrapperspb.FloatValue{Value: 1}, 725 WrappedStrValue: &wrapperspb.StringValue{Value: "foo"}, 726 WrappedBytesValue: &wrapperspb.BytesValue{}, 727 WrappedInt32Value: &wrapperspb.Int32Value{Value: 1}, 728 WrappedUint32Value: &wrapperspb.UInt32Value{Value: 1}, 729 WrappedDoubleValue: &wrapperspb.DoubleValue{Value: 1}, 730 WrappedInt64Value: &wrapperspb.Int64Value{Value: 1}, 731 WrappedUint64Value: &wrapperspb.UInt64Value{Value: 1}, 732 EnumValue: helloworld.NumericEnum_ONE, 733 OneofValue: &helloworld.HelloRequest_OneofString{ 734 OneofString: "oneof", 735 }, 736 RepeatedStringValue: []string{ 737 "foobar", "foo", "bar", "baz", 738 }, 739 MappedStringValue: map[string]string{ 740 "foo": "bar", 741 }, 742 }, 743 wantErr: false, 744 desc: "form serializer unmarshal to proto message test", 745 }, 746 { 747 data: []byte("!@#$%^&"), 748 unmarshalObj: &helloworld.HelloRequest{}, 749 want: nil, 750 wantErr: true, 751 desc: "form serializer unmarshal invalid data test", 752 }, 753 { 754 data: []byte(url.Values{ 755 "primitive_string_value": []string{"foo", "bar"}, 756 }.Encode()), 757 unmarshalObj: &helloworld.HelloRequest{}, 758 want: nil, 759 wantErr: true, 760 desc: "form serializer unmarshal invalid len of values test", 761 }, 762 { 763 data: []byte(url.Values{ 764 "primitive_int32_value": []string{"foo"}, 765 }.Encode()), 766 unmarshalObj: &helloworld.HelloRequest{}, 767 want: nil, 768 wantErr: true, 769 desc: "form serializer unmarshal invalid field data test", 770 }, 771 { 772 data: []byte(url.Values{ 773 "mapped_string_value": []string{"foo", "bar", "baz"}, 774 }.Encode()), 775 unmarshalObj: &helloworld.HelloRequest{}, 776 want: nil, 777 wantErr: true, 778 desc: "form serializer unmarshal map invalid len of values test", 779 }, 780 { 781 data: []byte(url.Values{ 782 "mapped_enum_value": []string{"foo", "bar"}, 783 }.Encode()), 784 unmarshalObj: &helloworld.HelloRequest{}, 785 want: nil, 786 wantErr: true, 787 desc: "form serializer unmarshal map invalid value test", 788 }, 789 { 790 data: []byte(url.Values{ 791 "repeated_enum_value": []string{"foo", "bar"}, 792 }.Encode()), 793 unmarshalObj: &helloworld.HelloRequest{}, 794 want: nil, 795 wantErr: true, 796 desc: "form serializer unmarshal repeated test", 797 }, 798 { 799 data: []byte(url.Values{ 800 "wrapped_bool_value": []string{"foo"}, 801 }.Encode()), 802 unmarshalObj: &helloworld.HelloRequest{}, 803 want: nil, 804 wantErr: true, 805 desc: "form serializer unmarshal google.protobuf.bool field data test", 806 }, 807 { 808 data: []byte(url.Values{ 809 "wrapped_int32_value": []string{"foo"}, 810 }.Encode()), 811 unmarshalObj: &helloworld.HelloRequest{}, 812 want: nil, 813 wantErr: true, 814 desc: "form serializer unmarshal google.protobuf.int32 field data test", 815 }, 816 { 817 data: []byte(url.Values{ 818 "foo": []string{"bar"}, 819 }.Encode()), 820 unmarshalObj: 1, 821 want: nil, 822 wantErr: true, 823 desc: "form serializer unmarshal to wrong obj test", 824 }, 825 } { 826 err := f.Unmarshal(test.data, test.unmarshalObj) 827 if test.wantErr { 828 require.NotNil(t, err, test.desc) 829 } else { 830 require.Nil(t, err, test.desc) 831 require.Equal(t, "", cmp.Diff(test.unmarshalObj, test.want, protocmp.Transform()), test.desc) 832 } 833 } 834 } 835 836 func TestJSONPBSerializerMarshalOptions(t *testing.T) { 837 for _, test := range []struct { 838 input interface{} 839 option func(*protojson.MarshalOptions) 840 want []byte 841 wantErr bool 842 desc string 843 }{ 844 { 845 input: ([]*helloworld.HelloRequest)(nil), 846 option: func(o *protojson.MarshalOptions) { 847 o.EmitUnpopulated = true 848 }, 849 want: []byte("[]"), 850 wantErr: false, 851 desc: "jsonpb marshal options test 01", 852 }, 853 { 854 input: map[string]string{"foo": "bar"}, 855 option: func(o *protojson.MarshalOptions) { 856 o.Indent = " " 857 }, 858 want: []byte(`{ 859 "foo": "bar" 860 }`), 861 wantErr: false, 862 desc: "jsonpb marshal options test 02", 863 }, 864 } { 865 test.option(&restful.Marshaller) 866 got, err := j.Marshal(test.input) 867 if test.wantErr { 868 require.NotNil(t, err, test.desc) 869 } else { 870 require.Nil(t, err, test.desc) 871 require.Equal(t, got, test.want, test.desc) 872 } 873 } 874 } 875 876 func TestJSONPBAllowUnmarshalNil(t *testing.T) { 877 var req helloworld.HelloRequest 878 j.AllowUnmarshalNil = true 879 err := j.Unmarshal([]byte{}, &req) 880 require.Nil(t, err) 881 require.True(t, reflect.DeepEqual(&req, &helloworld.HelloRequest{})) 882 }