blob: 1e9bd98b4e9446b2f8bc60630044409e79944508 [file] [log] [blame]
Herbie Ongc96a79d2019-03-08 10:49:17 -08001// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package jsonpb_test
6
7import (
8 "math"
9 "testing"
10
11 protoV1 "github.com/golang/protobuf/proto"
12 "github.com/golang/protobuf/v2/encoding/jsonpb"
13 "github.com/golang/protobuf/v2/encoding/testprotos/pb2"
14 "github.com/golang/protobuf/v2/encoding/testprotos/pb3"
15 "github.com/golang/protobuf/v2/internal/scalar"
16 "github.com/golang/protobuf/v2/proto"
Herbie Onge52379a2019-03-15 18:00:19 -070017 preg "github.com/golang/protobuf/v2/reflect/protoregistry"
Joe Tsai4fddeba2019-03-20 18:29:32 -070018 "github.com/golang/protobuf/v2/runtime/protoiface"
Herbie Onge63c4c42019-03-22 22:20:22 -070019
20 knownpb "github.com/golang/protobuf/v2/types/known"
Herbie Ongc96a79d2019-03-08 10:49:17 -080021)
22
Herbie Onge52379a2019-03-15 18:00:19 -070023func init() {
24 // TODO: remove these registerExtension calls when generated code registers
25 // to V2 global registry.
26 registerExtension(pb2.E_OptExtBool)
27 registerExtension(pb2.E_OptExtString)
28 registerExtension(pb2.E_OptExtEnum)
29 registerExtension(pb2.E_OptExtNested)
30 registerExtension(pb2.E_RptExtFixed32)
31 registerExtension(pb2.E_RptExtEnum)
32 registerExtension(pb2.E_RptExtNested)
33 registerExtension(pb2.E_ExtensionsContainer_OptExtBool)
34 registerExtension(pb2.E_ExtensionsContainer_OptExtString)
35 registerExtension(pb2.E_ExtensionsContainer_OptExtEnum)
36 registerExtension(pb2.E_ExtensionsContainer_OptExtNested)
37 registerExtension(pb2.E_ExtensionsContainer_RptExtString)
38 registerExtension(pb2.E_ExtensionsContainer_RptExtEnum)
39 registerExtension(pb2.E_ExtensionsContainer_RptExtNested)
40 registerExtension(pb2.E_MessageSetExtension)
41 registerExtension(pb2.E_MessageSetExtension_MessageSetExtension)
42 registerExtension(pb2.E_MessageSetExtension_NotMessageSetExtension)
43 registerExtension(pb2.E_MessageSetExtension_ExtNested)
44 registerExtension(pb2.E_FakeMessageSetExtension_MessageSetExtension)
45}
46
Joe Tsai4fddeba2019-03-20 18:29:32 -070047func registerExtension(xd *protoiface.ExtensionDescV1) {
Herbie Onge52379a2019-03-15 18:00:19 -070048 preg.GlobalTypes.Register(xd.Type)
49}
50
Herbie Ongc96a79d2019-03-08 10:49:17 -080051func TestUnmarshal(t *testing.T) {
52 tests := []struct {
53 desc string
54 umo jsonpb.UnmarshalOptions
55 inputMessage proto.Message
56 inputText string
57 wantMessage proto.Message
58 // TODO: verify expected error message substring.
59 wantErr bool
60 }{{
61 desc: "proto2 empty message",
62 inputMessage: &pb2.Scalars{},
63 inputText: "{}",
64 wantMessage: &pb2.Scalars{},
65 }, {
66 desc: "unexpected value instead of EOF",
67 inputMessage: &pb2.Scalars{},
68 inputText: "{} {}",
69 wantErr: true,
70 }, {
71 desc: "proto2 optional scalars set to zero values",
72 inputMessage: &pb2.Scalars{},
73 inputText: `{
74 "optBool": false,
75 "optInt32": 0,
76 "optInt64": 0,
77 "optUint32": 0,
78 "optUint64": 0,
79 "optSint32": 0,
80 "optSint64": 0,
81 "optFixed32": 0,
82 "optFixed64": 0,
83 "optSfixed32": 0,
84 "optSfixed64": 0,
85 "optFloat": 0,
86 "optDouble": 0,
87 "optBytes": "",
88 "optString": ""
89}`,
90 wantMessage: &pb2.Scalars{
91 OptBool: scalar.Bool(false),
92 OptInt32: scalar.Int32(0),
93 OptInt64: scalar.Int64(0),
94 OptUint32: scalar.Uint32(0),
95 OptUint64: scalar.Uint64(0),
96 OptSint32: scalar.Int32(0),
97 OptSint64: scalar.Int64(0),
98 OptFixed32: scalar.Uint32(0),
99 OptFixed64: scalar.Uint64(0),
100 OptSfixed32: scalar.Int32(0),
101 OptSfixed64: scalar.Int64(0),
102 OptFloat: scalar.Float32(0),
103 OptDouble: scalar.Float64(0),
104 OptBytes: []byte{},
105 OptString: scalar.String(""),
106 },
107 }, {
108 desc: "proto3 scalars set to zero values",
109 inputMessage: &pb3.Scalars{},
110 inputText: `{
111 "sBool": false,
112 "sInt32": 0,
113 "sInt64": 0,
114 "sUint32": 0,
115 "sUint64": 0,
116 "sSint32": 0,
117 "sSint64": 0,
118 "sFixed32": 0,
119 "sFixed64": 0,
120 "sSfixed32": 0,
121 "sSfixed64": 0,
122 "sFloat": 0,
123 "sDouble": 0,
124 "sBytes": "",
125 "sString": ""
126}`,
127 wantMessage: &pb3.Scalars{},
128 }, {
129 desc: "proto2 optional scalars set to null",
130 inputMessage: &pb2.Scalars{},
131 inputText: `{
132 "optBool": null,
133 "optInt32": null,
134 "optInt64": null,
135 "optUint32": null,
136 "optUint64": null,
137 "optSint32": null,
138 "optSint64": null,
139 "optFixed32": null,
140 "optFixed64": null,
141 "optSfixed32": null,
142 "optSfixed64": null,
143 "optFloat": null,
144 "optDouble": null,
145 "optBytes": null,
146 "optString": null
147}`,
148 wantMessage: &pb2.Scalars{},
149 }, {
150 desc: "proto3 scalars set to null",
151 inputMessage: &pb3.Scalars{},
152 inputText: `{
153 "sBool": null,
154 "sInt32": null,
155 "sInt64": null,
156 "sUint32": null,
157 "sUint64": null,
158 "sSint32": null,
159 "sSint64": null,
160 "sFixed32": null,
161 "sFixed64": null,
162 "sSfixed32": null,
163 "sSfixed64": null,
164 "sFloat": null,
165 "sDouble": null,
166 "sBytes": null,
167 "sString": null
168}`,
169 wantMessage: &pb3.Scalars{},
170 }, {
171 desc: "boolean",
172 inputMessage: &pb3.Scalars{},
173 inputText: `{"sBool": true}`,
174 wantMessage: &pb3.Scalars{
175 SBool: true,
176 },
177 }, {
178 desc: "not boolean",
179 inputMessage: &pb3.Scalars{},
180 inputText: `{"sBool": "true"}`,
181 wantErr: true,
182 }, {
183 desc: "float and double",
184 inputMessage: &pb3.Scalars{},
185 inputText: `{
186 "sFloat": 1.234,
187 "sDouble": 5.678
188}`,
189 wantMessage: &pb3.Scalars{
190 SFloat: 1.234,
191 SDouble: 5.678,
192 },
193 }, {
194 desc: "float and double in string",
195 inputMessage: &pb3.Scalars{},
196 inputText: `{
197 "sFloat": "1.234",
198 "sDouble": "5.678"
199}`,
200 wantMessage: &pb3.Scalars{
201 SFloat: 1.234,
202 SDouble: 5.678,
203 },
204 }, {
205 desc: "float and double in E notation",
206 inputMessage: &pb3.Scalars{},
207 inputText: `{
208 "sFloat": 12.34E-1,
209 "sDouble": 5.678e4
210}`,
211 wantMessage: &pb3.Scalars{
212 SFloat: 1.234,
213 SDouble: 56780,
214 },
215 }, {
216 desc: "float and double in string E notation",
217 inputMessage: &pb3.Scalars{},
218 inputText: `{
219 "sFloat": "12.34E-1",
220 "sDouble": "5.678e4"
221}`,
222 wantMessage: &pb3.Scalars{
223 SFloat: 1.234,
224 SDouble: 56780,
225 },
226 }, {
227 desc: "float exceeds limit",
228 inputMessage: &pb3.Scalars{},
229 inputText: `{"sFloat": 3.4e39}`,
230 wantErr: true,
231 }, {
232 desc: "float in string exceeds limit",
233 inputMessage: &pb3.Scalars{},
234 inputText: `{"sFloat": "-3.4e39"}`,
235 wantErr: true,
236 }, {
237 desc: "double exceeds limit",
238 inputMessage: &pb3.Scalars{},
239 inputText: `{"sFloat": -1.79e+309}`,
240 wantErr: true,
241 }, {
242 desc: "double in string exceeds limit",
243 inputMessage: &pb3.Scalars{},
244 inputText: `{"sFloat": "1.79e+309"}`,
245 wantErr: true,
246 }, {
247 desc: "infinites",
248 inputMessage: &pb3.Scalars{},
249 inputText: `{"sFloat": "Infinity", "sDouble": "-Infinity"}`,
250 wantMessage: &pb3.Scalars{
251 SFloat: float32(math.Inf(+1)),
252 SDouble: math.Inf(-1),
253 },
254 }, {
255 desc: "not float",
256 inputMessage: &pb3.Scalars{},
257 inputText: `{"sFloat": true}`,
258 wantErr: true,
259 }, {
260 desc: "not double",
261 inputMessage: &pb3.Scalars{},
262 inputText: `{"sDouble": "not a number"}`,
263 wantErr: true,
264 }, {
265 desc: "integers",
266 inputMessage: &pb3.Scalars{},
267 inputText: `{
268 "sInt32": 1234,
269 "sInt64": -1234,
270 "sUint32": 1e2,
271 "sUint64": 100E-2,
272 "sSint32": 1.0,
273 "sSint64": -1.0,
274 "sFixed32": 1.234e+5,
275 "sFixed64": 1200E-2,
276 "sSfixed32": -1.234e05,
277 "sSfixed64": -1200e-02
278}`,
279 wantMessage: &pb3.Scalars{
280 SInt32: 1234,
281 SInt64: -1234,
282 SUint32: 100,
283 SUint64: 1,
284 SSint32: 1,
285 SSint64: -1,
286 SFixed32: 123400,
287 SFixed64: 12,
288 SSfixed32: -123400,
289 SSfixed64: -12,
290 },
291 }, {
292 desc: "integers in string",
293 inputMessage: &pb3.Scalars{},
294 inputText: `{
295 "sInt32": "1234",
296 "sInt64": "-1234",
297 "sUint32": "1e2",
298 "sUint64": "100E-2",
299 "sSint32": "1.0",
300 "sSint64": "-1.0",
301 "sFixed32": "1.234e+5",
302 "sFixed64": "1200E-2",
303 "sSfixed32": "-1.234e05",
304 "sSfixed64": "-1200e-02"
305}`,
306 wantMessage: &pb3.Scalars{
307 SInt32: 1234,
308 SInt64: -1234,
309 SUint32: 100,
310 SUint64: 1,
311 SSint32: 1,
312 SSint64: -1,
313 SFixed32: 123400,
314 SFixed64: 12,
315 SSfixed32: -123400,
316 SSfixed64: -12,
317 },
318 }, {
319 desc: "integers in escaped string",
320 inputMessage: &pb3.Scalars{},
321 inputText: `{"sInt32": "\u0031\u0032"}`,
322 wantMessage: &pb3.Scalars{
323 SInt32: 12,
324 },
325 }, {
326 desc: "number is not an integer",
327 inputMessage: &pb3.Scalars{},
328 inputText: `{"sInt32": 1.001}`,
329 wantErr: true,
330 }, {
331 desc: "32-bit int exceeds limit",
332 inputMessage: &pb3.Scalars{},
333 inputText: `{"sInt32": 2e10}`,
334 wantErr: true,
335 }, {
336 desc: "64-bit int exceeds limit",
337 inputMessage: &pb3.Scalars{},
338 inputText: `{"sSfixed64": -9e19}`,
339 wantErr: true,
340 }, {
341 desc: "not integer",
342 inputMessage: &pb3.Scalars{},
343 inputText: `{"sInt32": "not a number"}`,
344 wantErr: true,
345 }, {
346 desc: "not unsigned integer",
347 inputMessage: &pb3.Scalars{},
348 inputText: `{"sUint32": "not a number"}`,
349 wantErr: true,
350 }, {
351 desc: "number is not an unsigned integer",
352 inputMessage: &pb3.Scalars{},
353 inputText: `{"sUint32": -1}`,
354 wantErr: true,
355 }, {
356 desc: "string",
357 inputMessage: &pb2.Scalars{},
358 inputText: `{"optString": "谷歌"}`,
359 wantMessage: &pb2.Scalars{
360 OptString: scalar.String("谷歌"),
361 },
362 }, {
363 desc: "string with invalid UTF-8",
364 inputMessage: &pb3.Scalars{},
365 inputText: "{\"sString\": \"\xff\"}",
366 wantMessage: &pb3.Scalars{
367 SString: "\xff",
368 },
369 wantErr: true,
370 }, {
371 desc: "not string",
372 inputMessage: &pb2.Scalars{},
373 inputText: `{"optString": 42}`,
374 wantErr: true,
375 }, {
376 desc: "bytes",
377 inputMessage: &pb3.Scalars{},
378 inputText: `{"sBytes": "aGVsbG8gd29ybGQ"}`,
379 wantMessage: &pb3.Scalars{
380 SBytes: []byte("hello world"),
381 },
382 }, {
383 desc: "bytes padded",
384 inputMessage: &pb3.Scalars{},
385 inputText: `{"sBytes": "aGVsbG8gd29ybGQ="}`,
386 wantMessage: &pb3.Scalars{
387 SBytes: []byte("hello world"),
388 },
389 }, {
390 desc: "not bytes",
391 inputMessage: &pb3.Scalars{},
392 inputText: `{"sBytes": true}`,
393 wantErr: true,
394 }, {
395 desc: "proto2 enum",
396 inputMessage: &pb2.Enums{},
397 inputText: `{
398 "optEnum": "ONE",
399 "optNestedEnum": "UNO"
400}`,
401 wantMessage: &pb2.Enums{
402 OptEnum: pb2.Enum_ONE.Enum(),
403 OptNestedEnum: pb2.Enums_UNO.Enum(),
404 },
405 }, {
406 desc: "proto3 enum",
407 inputMessage: &pb3.Enums{},
408 inputText: `{
409 "sEnum": "ONE",
410 "sNestedEnum": "DIEZ"
411}`,
412 wantMessage: &pb3.Enums{
413 SEnum: pb3.Enum_ONE,
414 SNestedEnum: pb3.Enums_DIEZ,
415 },
416 }, {
417 desc: "enum numeric value",
418 inputMessage: &pb3.Enums{},
419 inputText: `{
420 "sEnum": 2,
421 "sNestedEnum": 2
422}`,
423 wantMessage: &pb3.Enums{
424 SEnum: pb3.Enum_TWO,
425 SNestedEnum: pb3.Enums_DOS,
426 },
427 }, {
428 desc: "enum unnamed numeric value",
429 inputMessage: &pb3.Enums{},
430 inputText: `{
431 "sEnum": 101,
432 "sNestedEnum": -101
433}`,
434 wantMessage: &pb3.Enums{
435 SEnum: 101,
436 SNestedEnum: -101,
437 },
438 }, {
439 desc: "enum set to number string",
440 inputMessage: &pb3.Enums{},
441 inputText: `{
442 "sEnum": "1",
443}`,
444 wantErr: true,
445 }, {
446 desc: "enum set to invalid named",
447 inputMessage: &pb3.Enums{},
448 inputText: `{
449 "sEnum": "UNNAMED",
450}`,
451 wantErr: true,
452 }, {
453 desc: "enum set to not enum",
454 inputMessage: &pb3.Enums{},
455 inputText: `{
456 "sEnum": true,
457}`,
458 wantErr: true,
459 }, {
460 desc: "proto name",
461 inputMessage: &pb3.JSONNames{},
462 inputText: `{
463 "s_string": "proto name used"
464}`,
465 wantMessage: &pb3.JSONNames{
466 SString: "proto name used",
467 },
468 }, {
469 desc: "json_name",
470 inputMessage: &pb3.JSONNames{},
471 inputText: `{
472 "foo_bar": "json_name used"
473}`,
474 wantMessage: &pb3.JSONNames{
475 SString: "json_name used",
476 },
477 }, {
478 desc: "camelCase name",
479 inputMessage: &pb3.JSONNames{},
480 inputText: `{
481 "sString": "camelcase used"
482}`,
483 wantErr: true,
484 }, {
485 desc: "proto name and json_name",
486 inputMessage: &pb3.JSONNames{},
487 inputText: `{
488 "foo_bar": "json_name used",
489 "s_string": "proto name used"
490}`,
491 wantErr: true,
492 }, {
493 desc: "duplicate field names",
494 inputMessage: &pb3.JSONNames{},
495 inputText: `{
496 "foo_bar": "one",
497 "foo_bar": "two",
498}`,
499 wantErr: true,
500 }, {
501 desc: "null message",
502 inputMessage: &pb2.Nests{},
503 inputText: "null",
504 wantErr: true,
505 }, {
506 desc: "proto2 nested message not set",
507 inputMessage: &pb2.Nests{},
508 inputText: "{}",
509 wantMessage: &pb2.Nests{},
510 }, {
511 desc: "proto2 nested message set to null",
512 inputMessage: &pb2.Nests{},
513 inputText: `{
514 "optNested": null,
515 "optgroup": null
516}`,
517 wantMessage: &pb2.Nests{},
518 }, {
519 desc: "proto2 nested message set to empty",
520 inputMessage: &pb2.Nests{},
521 inputText: `{
522 "optNested": {},
523 "optgroup": {}
524}`,
525 wantMessage: &pb2.Nests{
526 OptNested: &pb2.Nested{},
527 Optgroup: &pb2.Nests_OptGroup{},
528 },
529 }, {
530 desc: "proto2 nested messages",
531 inputMessage: &pb2.Nests{},
532 inputText: `{
533 "optNested": {
534 "optString": "nested message",
535 "optNested": {
536 "optString": "another nested message"
537 }
538 }
539}`,
540 wantMessage: &pb2.Nests{
541 OptNested: &pb2.Nested{
542 OptString: scalar.String("nested message"),
543 OptNested: &pb2.Nested{
544 OptString: scalar.String("another nested message"),
545 },
546 },
547 },
548 }, {
549 desc: "proto2 groups",
550 inputMessage: &pb2.Nests{},
551 inputText: `{
552 "optgroup": {
553 "optString": "inside a group",
554 "optNested": {
555 "optString": "nested message inside a group"
556 },
557 "optnestedgroup": {
558 "optFixed32": 47
559 }
560 }
561}`,
562 wantMessage: &pb2.Nests{
563 Optgroup: &pb2.Nests_OptGroup{
564 OptString: scalar.String("inside a group"),
565 OptNested: &pb2.Nested{
566 OptString: scalar.String("nested message inside a group"),
567 },
568 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
569 OptFixed32: scalar.Uint32(47),
570 },
571 },
572 },
573 }, {
574 desc: "proto3 nested message not set",
575 inputMessage: &pb3.Nests{},
576 inputText: "{}",
577 wantMessage: &pb3.Nests{},
578 }, {
579 desc: "proto3 nested message set to null",
580 inputMessage: &pb3.Nests{},
581 inputText: `{"sNested": null}`,
582 wantMessage: &pb3.Nests{},
583 }, {
584 desc: "proto3 nested message set to empty",
585 inputMessage: &pb3.Nests{},
586 inputText: `{"sNested": {}}`,
587 wantMessage: &pb3.Nests{
588 SNested: &pb3.Nested{},
589 },
590 }, {
591 desc: "proto3 nested message",
592 inputMessage: &pb3.Nests{},
593 inputText: `{
594 "sNested": {
595 "sString": "nested message",
596 "sNested": {
597 "sString": "another nested message"
598 }
599 }
600}`,
601 wantMessage: &pb3.Nests{
602 SNested: &pb3.Nested{
603 SString: "nested message",
604 SNested: &pb3.Nested{
605 SString: "another nested message",
606 },
607 },
608 },
609 }, {
610 desc: "message set to non-message",
611 inputMessage: &pb3.Nests{},
612 inputText: `"not valid"`,
613 wantErr: true,
614 }, {
615 desc: "nested message set to non-message",
616 inputMessage: &pb3.Nests{},
617 inputText: `{"sNested": true}`,
618 wantErr: true,
619 }, {
620 desc: "oneof not set",
621 inputMessage: &pb3.Oneofs{},
622 inputText: "{}",
623 wantMessage: &pb3.Oneofs{},
624 }, {
625 desc: "oneof set to empty string",
626 inputMessage: &pb3.Oneofs{},
627 inputText: `{"oneofString": ""}`,
628 wantMessage: &pb3.Oneofs{
629 Union: &pb3.Oneofs_OneofString{},
630 },
631 }, {
632 desc: "oneof set to string",
633 inputMessage: &pb3.Oneofs{},
634 inputText: `{"oneofString": "hello"}`,
635 wantMessage: &pb3.Oneofs{
636 Union: &pb3.Oneofs_OneofString{
637 OneofString: "hello",
638 },
639 },
640 }, {
641 desc: "oneof set to enum",
642 inputMessage: &pb3.Oneofs{},
643 inputText: `{"oneofEnum": "ZERO"}`,
644 wantMessage: &pb3.Oneofs{
645 Union: &pb3.Oneofs_OneofEnum{
646 OneofEnum: pb3.Enum_ZERO,
647 },
648 },
649 }, {
650 desc: "oneof set to empty message",
651 inputMessage: &pb3.Oneofs{},
652 inputText: `{"oneofNested": {}}`,
653 wantMessage: &pb3.Oneofs{
654 Union: &pb3.Oneofs_OneofNested{
655 OneofNested: &pb3.Nested{},
656 },
657 },
658 }, {
659 desc: "oneof set to message",
660 inputMessage: &pb3.Oneofs{},
661 inputText: `{
662 "oneofNested": {
663 "sString": "nested message"
664 }
665}`,
666 wantMessage: &pb3.Oneofs{
667 Union: &pb3.Oneofs_OneofNested{
668 OneofNested: &pb3.Nested{
669 SString: "nested message",
670 },
671 },
672 },
673 }, {
674 desc: "repeated null fields",
675 inputMessage: &pb2.Repeats{},
676 inputText: `{
677 "rptString": null,
678 "rptInt32" : null,
679 "rptFloat" : null,
680 "rptBytes" : null
681}`,
682 wantMessage: &pb2.Repeats{},
683 }, {
684 desc: "repeated scalars",
685 inputMessage: &pb2.Repeats{},
686 inputText: `{
687 "rptString": ["hello", "world"],
688 "rptInt32" : [-1, 0, 1],
689 "rptBool" : [false, true]
690}`,
691 wantMessage: &pb2.Repeats{
692 RptString: []string{"hello", "world"},
693 RptInt32: []int32{-1, 0, 1},
694 RptBool: []bool{false, true},
695 },
696 }, {
697 desc: "repeated enums",
698 inputMessage: &pb2.Enums{},
699 inputText: `{
700 "rptEnum" : ["TEN", 1, 42],
701 "rptNestedEnum": ["DOS", 2, -47]
702}`,
703 wantMessage: &pb2.Enums{
704 RptEnum: []pb2.Enum{pb2.Enum_TEN, pb2.Enum_ONE, 42},
705 RptNestedEnum: []pb2.Enums_NestedEnum{pb2.Enums_DOS, pb2.Enums_DOS, -47},
706 },
707 }, {
708 desc: "repeated messages",
709 inputMessage: &pb2.Nests{},
710 inputText: `{
711 "rptNested": [
712 {
713 "optString": "repeat nested one"
714 },
715 {
716 "optString": "repeat nested two",
717 "optNested": {
718 "optString": "inside repeat nested two"
719 }
720 },
721 {}
722 ]
723}`,
724 wantMessage: &pb2.Nests{
725 RptNested: []*pb2.Nested{
726 {
727 OptString: scalar.String("repeat nested one"),
728 },
729 {
730 OptString: scalar.String("repeat nested two"),
731 OptNested: &pb2.Nested{
732 OptString: scalar.String("inside repeat nested two"),
733 },
734 },
735 {},
736 },
737 },
738 }, {
739 desc: "repeated groups",
740 inputMessage: &pb2.Nests{},
741 inputText: `{
742 "rptgroup": [
743 {
744 "rptString": ["hello", "world"]
745 },
746 {}
747 ]
748}
749`,
750 wantMessage: &pb2.Nests{
751 Rptgroup: []*pb2.Nests_RptGroup{
752 {
753 RptString: []string{"hello", "world"},
754 },
755 {},
756 },
757 },
758 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -0700759 desc: "repeated string contains invalid UTF8",
760 inputMessage: &pb2.Repeats{},
761 inputText: `{"rptString": ["` + "abc\xff" + `"]}`,
762 wantMessage: &pb2.Repeats{
763 RptString: []string{"abc\xff"},
764 },
765 wantErr: true,
766 }, {
767 desc: "repeated messages contain invalid UTF8",
768 inputMessage: &pb2.Nests{},
769 inputText: `{"rptNested": [{"optString": "` + "abc\xff" + `"}]}`,
770 wantMessage: &pb2.Nests{
771 RptNested: []*pb2.Nested{{OptString: scalar.String("abc\xff")}},
772 },
773 wantErr: true,
774 }, {
775 desc: "repeated scalars contain invalid type",
Herbie Ongc96a79d2019-03-08 10:49:17 -0800776 inputMessage: &pb2.Repeats{},
777 inputText: `{"rptString": ["hello", null, "world"]}`,
778 wantErr: true,
779 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -0700780 desc: "repeated messages contain invalid type",
Herbie Ongc96a79d2019-03-08 10:49:17 -0800781 inputMessage: &pb2.Nests{},
782 inputText: `{"rptNested": [{}, null]}`,
783 wantErr: true,
784 }, {
785 desc: "map fields 1",
786 inputMessage: &pb3.Maps{},
787 inputText: `{
788 "int32ToStr": {
789 "-101": "-101",
790 "0" : "zero",
791 "255" : "0xff"
792 },
793 "boolToUint32": {
794 "false": 101,
795 "true" : "42"
796 }
797}`,
798 wantMessage: &pb3.Maps{
799 Int32ToStr: map[int32]string{
800 -101: "-101",
801 0xff: "0xff",
802 0: "zero",
803 },
804 BoolToUint32: map[bool]uint32{
805 true: 42,
806 false: 101,
807 },
808 },
809 }, {
810 desc: "map fields 2",
811 inputMessage: &pb3.Maps{},
812 inputText: `{
813 "uint64ToEnum": {
814 "1" : "ONE",
815 "2" : 2,
816 "10": 101
817 }
818}`,
819 wantMessage: &pb3.Maps{
820 Uint64ToEnum: map[uint64]pb3.Enum{
821 1: pb3.Enum_ONE,
822 2: pb3.Enum_TWO,
823 10: 101,
824 },
825 },
826 }, {
827 desc: "map fields 3",
828 inputMessage: &pb3.Maps{},
829 inputText: `{
830 "strToNested": {
831 "nested_one": {
832 "sString": "nested in a map"
833 },
834 "nested_two": {}
835 }
836}`,
837 wantMessage: &pb3.Maps{
838 StrToNested: map[string]*pb3.Nested{
839 "nested_one": {
840 SString: "nested in a map",
841 },
842 "nested_two": {},
843 },
844 },
845 }, {
846 desc: "map fields 4",
847 inputMessage: &pb3.Maps{},
848 inputText: `{
849 "strToOneofs": {
850 "nested": {
851 "oneofNested": {
852 "sString": "nested oneof in map field value"
853 }
854 },
855 "string": {
856 "oneofString": "hello"
857 }
858 }
859}`,
860 wantMessage: &pb3.Maps{
861 StrToOneofs: map[string]*pb3.Oneofs{
862 "string": {
863 Union: &pb3.Oneofs_OneofString{
864 OneofString: "hello",
865 },
866 },
867 "nested": {
868 Union: &pb3.Oneofs_OneofNested{
869 OneofNested: &pb3.Nested{
870 SString: "nested oneof in map field value",
871 },
872 },
873 },
874 },
875 },
876 }, {
877 desc: "map contains duplicate keys",
878 inputMessage: &pb3.Maps{},
879 inputText: `{
880 "int32ToStr": {
881 "0": "cero",
882 "0": "zero"
883 }
884}
885`,
886 wantErr: true,
887 }, {
888 desc: "map key empty string",
889 inputMessage: &pb3.Maps{},
890 inputText: `{
891 "strToNested": {
892 "": {}
893 }
894}`,
895 wantMessage: &pb3.Maps{
896 StrToNested: map[string]*pb3.Nested{
897 "": {},
898 },
899 },
900 }, {
901 desc: "map contains invalid key 1",
902 inputMessage: &pb3.Maps{},
903 inputText: `{
904 "int32ToStr": {
905 "invalid": "cero"
906}`,
907 wantErr: true,
908 }, {
909 desc: "map contains invalid key 2",
910 inputMessage: &pb3.Maps{},
911 inputText: `{
912 "int32ToStr": {
913 "1.02": "float"
914}`,
915 wantErr: true,
916 }, {
917 desc: "map contains invalid key 3",
918 inputMessage: &pb3.Maps{},
919 inputText: `{
920 "int32ToStr": {
921 "2147483648": "exceeds 32-bit integer max limit"
922}`,
923 wantErr: true,
924 }, {
925 desc: "map contains invalid key 4",
926 inputMessage: &pb3.Maps{},
927 inputText: `{
928 "uint64ToEnum": {
929 "-1": 0
930 }
931}`,
932 wantErr: true,
933 }, {
934 desc: "map contains invalid value",
935 inputMessage: &pb3.Maps{},
936 inputText: `{
937 "int32ToStr": {
938 "101": true
939}`,
940 wantErr: true,
941 }, {
942 desc: "map contains null for scalar value",
943 inputMessage: &pb3.Maps{},
944 inputText: `{
945 "int32ToStr": {
946 "101": null
947}`,
948 wantErr: true,
949 }, {
950 desc: "map contains null for message value",
951 inputMessage: &pb3.Maps{},
952 inputText: `{
953 "strToNested": {
954 "hello": null
955 }
956}`,
957 wantErr: true,
Herbie Onge52379a2019-03-15 18:00:19 -0700958 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -0700959 desc: "map contains contains message value with invalid UTF8",
960 inputMessage: &pb3.Maps{},
961 inputText: `{
962 "strToNested": {
963 "hello": {
964 "sString": "` + "abc\xff" + `"
965 }
966 }
967}`,
968 wantMessage: &pb3.Maps{
969 StrToNested: map[string]*pb3.Nested{
970 "hello": {SString: "abc\xff"},
971 },
972 },
973 wantErr: true,
974 }, {
975 desc: "map key contains invalid UTF8",
976 inputMessage: &pb3.Maps{},
977 inputText: `{
978 "strToNested": {
979 "` + "abc\xff" + `": {}
980 }
981}`,
982 wantMessage: &pb3.Maps{
983 StrToNested: map[string]*pb3.Nested{
984 "abc\xff": {},
985 },
986 },
987 wantErr: true,
988 }, {
Herbie Ong329be5b2019-03-27 14:47:59 -0700989 desc: "required fields not set",
990 inputMessage: &pb2.Requireds{},
991 wantErr: true,
992 }, {
993 desc: "required field set",
994 inputMessage: &pb2.PartialRequired{},
995 inputText: `{
996 "reqString": "this is required"
997}`,
998 wantMessage: &pb2.PartialRequired{
999 ReqString: scalar.String("this is required"),
1000 },
1001 }, {
1002 desc: "required fields partially set",
1003 inputMessage: &pb2.Requireds{},
1004 inputText: `{
1005 "reqBool": false,
1006 "reqSfixed64": 42,
1007 "reqString": "hello",
1008 "reqEnum": "ONE"
1009}`,
1010 wantMessage: &pb2.Requireds{
1011 ReqBool: scalar.Bool(false),
1012 ReqSfixed64: scalar.Int64(42),
1013 ReqString: scalar.String("hello"),
1014 ReqEnum: pb2.Enum_ONE.Enum(),
1015 },
1016 wantErr: true,
1017 }, {
1018 desc: "required fields partially set with AllowPartial",
1019 umo: jsonpb.UnmarshalOptions{AllowPartial: true},
1020 inputMessage: &pb2.Requireds{},
1021 inputText: `{
1022 "reqBool": false,
1023 "reqSfixed64": 42,
1024 "reqString": "hello",
1025 "reqEnum": "ONE"
1026}`,
1027 wantMessage: &pb2.Requireds{
1028 ReqBool: scalar.Bool(false),
1029 ReqSfixed64: scalar.Int64(42),
1030 ReqString: scalar.String("hello"),
1031 ReqEnum: pb2.Enum_ONE.Enum(),
1032 },
1033 }, {
1034 desc: "required fields all set",
1035 inputMessage: &pb2.Requireds{},
1036 inputText: `{
1037 "reqBool": false,
1038 "reqSfixed64": 42,
1039 "reqDouble": 1.23,
1040 "reqString": "hello",
1041 "reqEnum": "ONE",
1042 "reqNested": {}
1043}`,
1044 wantMessage: &pb2.Requireds{
1045 ReqBool: scalar.Bool(false),
1046 ReqSfixed64: scalar.Int64(42),
1047 ReqDouble: scalar.Float64(1.23),
1048 ReqString: scalar.String("hello"),
1049 ReqEnum: pb2.Enum_ONE.Enum(),
1050 ReqNested: &pb2.Nested{},
1051 },
1052 }, {
1053 desc: "indirect required field",
1054 inputMessage: &pb2.IndirectRequired{},
1055 inputText: `{
1056 "optNested": {}
1057}`,
1058 wantMessage: &pb2.IndirectRequired{
1059 OptNested: &pb2.NestedWithRequired{},
1060 },
1061 wantErr: true,
1062 }, {
1063 desc: "indirect required field with AllowPartial",
1064 umo: jsonpb.UnmarshalOptions{AllowPartial: true},
1065 inputMessage: &pb2.IndirectRequired{},
1066 inputText: `{
1067 "optNested": {}
1068}`,
1069 wantMessage: &pb2.IndirectRequired{
1070 OptNested: &pb2.NestedWithRequired{},
1071 },
1072 }, {
1073 desc: "indirect required field in repeated",
1074 inputMessage: &pb2.IndirectRequired{},
1075 inputText: `{
1076 "rptNested": [
1077 {"reqString": "one"},
1078 {}
1079 ]
1080}`,
1081 wantMessage: &pb2.IndirectRequired{
1082 RptNested: []*pb2.NestedWithRequired{
1083 {
1084 ReqString: scalar.String("one"),
1085 },
1086 {},
1087 },
1088 },
1089 wantErr: true,
1090 }, {
1091 desc: "indirect required field in repeated with AllowPartial",
1092 umo: jsonpb.UnmarshalOptions{AllowPartial: true},
1093 inputMessage: &pb2.IndirectRequired{},
1094 inputText: `{
1095 "rptNested": [
1096 {"reqString": "one"},
1097 {}
1098 ]
1099}`,
1100 wantMessage: &pb2.IndirectRequired{
1101 RptNested: []*pb2.NestedWithRequired{
1102 {
1103 ReqString: scalar.String("one"),
1104 },
1105 {},
1106 },
1107 },
1108 }, {
1109 desc: "indirect required field in map",
1110 inputMessage: &pb2.IndirectRequired{},
1111 inputText: `{
1112 "strToNested": {
1113 "missing": {},
1114 "contains": {
1115 "reqString": "here"
1116 }
1117 }
1118}`,
1119 wantMessage: &pb2.IndirectRequired{
1120 StrToNested: map[string]*pb2.NestedWithRequired{
1121 "missing": &pb2.NestedWithRequired{},
1122 "contains": &pb2.NestedWithRequired{
1123 ReqString: scalar.String("here"),
1124 },
1125 },
1126 },
1127 wantErr: true,
1128 }, {
1129 desc: "indirect required field in map with AllowPartial",
1130 umo: jsonpb.UnmarshalOptions{AllowPartial: true},
1131 inputMessage: &pb2.IndirectRequired{},
1132 inputText: `{
1133 "strToNested": {
1134 "missing": {},
1135 "contains": {
1136 "reqString": "here"
1137 }
1138 }
1139}`,
1140 wantMessage: &pb2.IndirectRequired{
1141 StrToNested: map[string]*pb2.NestedWithRequired{
1142 "missing": &pb2.NestedWithRequired{},
1143 "contains": &pb2.NestedWithRequired{
1144 ReqString: scalar.String("here"),
1145 },
1146 },
1147 },
1148 }, {
1149 desc: "indirect required field in oneof",
1150 inputMessage: &pb2.IndirectRequired{},
1151 inputText: `{
1152 "oneofNested": {}
1153}`,
1154 wantMessage: &pb2.IndirectRequired{
1155 Union: &pb2.IndirectRequired_OneofNested{
1156 OneofNested: &pb2.NestedWithRequired{},
1157 },
1158 },
1159 wantErr: true,
1160 }, {
1161 desc: "indirect required field in oneof with AllowPartial",
1162 umo: jsonpb.UnmarshalOptions{AllowPartial: true},
1163 inputMessage: &pb2.IndirectRequired{},
1164 inputText: `{
1165 "oneofNested": {}
1166}`,
1167 wantMessage: &pb2.IndirectRequired{
1168 Union: &pb2.IndirectRequired_OneofNested{
1169 OneofNested: &pb2.NestedWithRequired{},
1170 },
1171 },
1172 }, {
Herbie Onge52379a2019-03-15 18:00:19 -07001173 desc: "extensions of non-repeated fields",
1174 inputMessage: &pb2.Extensions{},
1175 inputText: `{
1176 "optString": "non-extension field",
1177 "optBool": true,
1178 "optInt32": 42,
1179 "[pb2.opt_ext_bool]": true,
1180 "[pb2.opt_ext_nested]": {
1181 "optString": "nested in an extension",
Herbie Onge63c4c42019-03-22 22:20:22 -07001182 "optNested": {
1183 "optString": "another nested in an extension"
Herbie Onge52379a2019-03-15 18:00:19 -07001184 }
1185 },
1186 "[pb2.opt_ext_string]": "extension field",
1187 "[pb2.opt_ext_enum]": "TEN"
1188}`,
1189 wantMessage: func() proto.Message {
1190 m := &pb2.Extensions{
1191 OptString: scalar.String("non-extension field"),
1192 OptBool: scalar.Bool(true),
1193 OptInt32: scalar.Int32(42),
1194 }
1195 setExtension(m, pb2.E_OptExtBool, true)
1196 setExtension(m, pb2.E_OptExtString, "extension field")
1197 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
1198 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
1199 OptString: scalar.String("nested in an extension"),
1200 OptNested: &pb2.Nested{
1201 OptString: scalar.String("another nested in an extension"),
1202 },
1203 })
1204 return m
1205 }(),
1206 }, {
1207 desc: "extensions of repeated fields",
1208 inputMessage: &pb2.Extensions{},
1209 inputText: `{
1210 "[pb2.rpt_ext_enum]": ["TEN", 101, "ONE"],
1211 "[pb2.rpt_ext_fixed32]": [42, 47],
1212 "[pb2.rpt_ext_nested]": [
1213 {"optString": "one"},
1214 {"optString": "two"},
1215 {"optString": "three"}
1216 ]
1217}`,
1218 wantMessage: func() proto.Message {
1219 m := &pb2.Extensions{}
1220 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
1221 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
1222 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
1223 &pb2.Nested{OptString: scalar.String("one")},
1224 &pb2.Nested{OptString: scalar.String("two")},
1225 &pb2.Nested{OptString: scalar.String("three")},
1226 })
1227 return m
1228 }(),
1229 }, {
1230 desc: "extensions of non-repeated fields in another message",
1231 inputMessage: &pb2.Extensions{},
1232 inputText: `{
1233 "[pb2.ExtensionsContainer.opt_ext_bool]": true,
1234 "[pb2.ExtensionsContainer.opt_ext_enum]": "TEN",
1235 "[pb2.ExtensionsContainer.opt_ext_nested]": {
1236 "optString": "nested in an extension",
1237 "optNested": {
1238 "optString": "another nested in an extension"
1239 }
1240 },
1241 "[pb2.ExtensionsContainer.opt_ext_string]": "extension field"
1242}`,
1243 wantMessage: func() proto.Message {
1244 m := &pb2.Extensions{}
1245 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1246 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
1247 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
1248 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
1249 OptString: scalar.String("nested in an extension"),
1250 OptNested: &pb2.Nested{
1251 OptString: scalar.String("another nested in an extension"),
1252 },
1253 })
1254 return m
1255 }(),
1256 }, {
1257 desc: "extensions of repeated fields in another message",
1258 inputMessage: &pb2.Extensions{},
1259 inputText: `{
1260 "optString": "non-extension field",
1261 "optBool": true,
1262 "optInt32": 42,
1263 "[pb2.ExtensionsContainer.rpt_ext_nested]": [
1264 {"optString": "one"},
1265 {"optString": "two"},
1266 {"optString": "three"}
1267 ],
1268 "[pb2.ExtensionsContainer.rpt_ext_enum]": ["TEN", 101, "ONE"],
1269 "[pb2.ExtensionsContainer.rpt_ext_string]": ["hello", "world"]
1270}`,
1271 wantMessage: func() proto.Message {
1272 m := &pb2.Extensions{
1273 OptString: scalar.String("non-extension field"),
1274 OptBool: scalar.Bool(true),
1275 OptInt32: scalar.Int32(42),
1276 }
1277 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
1278 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1279 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
1280 &pb2.Nested{OptString: scalar.String("one")},
1281 &pb2.Nested{OptString: scalar.String("two")},
1282 &pb2.Nested{OptString: scalar.String("three")},
1283 })
1284 return m
1285 }(),
1286 }, {
1287 desc: "invalid extension field name",
1288 inputMessage: &pb2.Extensions{},
1289 inputText: `{ "[pb2.invalid_message_field]": true }`,
1290 wantErr: true,
1291 }, {
1292 desc: "MessageSet",
1293 inputMessage: &pb2.MessageSet{},
1294 inputText: `{
1295 "[pb2.MessageSetExtension]": {
1296 "optString": "a messageset extension"
1297 },
1298 "[pb2.MessageSetExtension.ext_nested]": {
1299 "optString": "just a regular extension"
1300 },
1301 "[pb2.MessageSetExtension.not_message_set_extension]": {
1302 "optString": "not a messageset extension"
1303 }
1304}`,
1305 wantMessage: func() proto.Message {
1306 m := &pb2.MessageSet{}
1307 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1308 OptString: scalar.String("a messageset extension"),
1309 })
1310 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1311 OptString: scalar.String("not a messageset extension"),
1312 })
1313 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1314 OptString: scalar.String("just a regular extension"),
1315 })
1316 return m
1317 }(),
1318 }, {
1319 desc: "extension field set to null",
1320 inputMessage: &pb2.Extensions{},
1321 inputText: `{
1322 "[pb2.ExtensionsContainer.opt_ext_bool]": null,
1323 "[pb2.ExtensionsContainer.opt_ext_nested]": null
1324}`,
1325 wantMessage: func() proto.Message {
1326 m := &pb2.Extensions{}
1327 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, nil)
1328 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, nil)
1329 return m
1330 }(),
1331 }, {
1332 desc: "extensions of repeated field contains null",
1333 inputMessage: &pb2.Extensions{},
1334 inputText: `{
1335 "[pb2.ExtensionsContainer.rpt_ext_nested]": [
1336 {"optString": "one"},
1337 null,
1338 {"optString": "three"}
1339 ],
1340}`,
1341 wantErr: true,
1342 }, {
1343 desc: "not real MessageSet 1",
1344 inputMessage: &pb2.FakeMessageSet{},
1345 inputText: `{
1346 "[pb2.FakeMessageSetExtension.message_set_extension]": {
1347 "optString": "not a messageset extension"
1348 }
1349}`,
1350 wantMessage: func() proto.Message {
1351 m := &pb2.FakeMessageSet{}
1352 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1353 OptString: scalar.String("not a messageset extension"),
1354 })
1355 return m
1356 }(),
1357 }, {
1358 desc: "not real MessageSet 2",
1359 inputMessage: &pb2.FakeMessageSet{},
1360 inputText: `{
1361 "[pb2.FakeMessageSetExtension]": {
1362 "optString": "not a messageset extension"
1363 }
1364}`,
1365 wantErr: true,
1366 }, {
1367 desc: "not real MessageSet 3",
1368 inputMessage: &pb2.MessageSet{},
1369 inputText: `{
1370 "[pb2.message_set_extension]": {
1371 "optString": "another not a messageset extension"
1372 }
1373}`,
1374 wantMessage: func() proto.Message {
1375 m := &pb2.MessageSet{}
1376 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1377 OptString: scalar.String("another not a messageset extension"),
1378 })
1379 return m
1380 }(),
Herbie Onge63c4c42019-03-22 22:20:22 -07001381 }, {
1382 desc: "Empty",
1383 inputMessage: &knownpb.Empty{},
1384 inputText: `{}`,
1385 wantMessage: &knownpb.Empty{},
1386 }, {
1387 desc: "Empty contains unknown",
1388 inputMessage: &knownpb.Empty{},
1389 inputText: `{"unknown": null}`,
1390 wantErr: true,
1391 }, {
1392 desc: "BoolValue false",
1393 inputMessage: &knownpb.BoolValue{},
1394 inputText: `false`,
1395 wantMessage: &knownpb.BoolValue{},
1396 }, {
1397 desc: "BoolValue true",
1398 inputMessage: &knownpb.BoolValue{},
1399 inputText: `true`,
1400 wantMessage: &knownpb.BoolValue{Value: true},
1401 }, {
1402 desc: "BoolValue invalid value",
1403 inputMessage: &knownpb.BoolValue{},
1404 inputText: `{}`,
1405 wantErr: true,
1406 }, {
1407 desc: "Int32Value",
1408 inputMessage: &knownpb.Int32Value{},
1409 inputText: `42`,
1410 wantMessage: &knownpb.Int32Value{Value: 42},
1411 }, {
1412 desc: "Int32Value in JSON string",
1413 inputMessage: &knownpb.Int32Value{},
1414 inputText: `"1.23e3"`,
1415 wantMessage: &knownpb.Int32Value{Value: 1230},
1416 }, {
1417 desc: "Int64Value",
1418 inputMessage: &knownpb.Int64Value{},
1419 inputText: `"42"`,
1420 wantMessage: &knownpb.Int64Value{Value: 42},
1421 }, {
1422 desc: "UInt32Value",
1423 inputMessage: &knownpb.UInt32Value{},
1424 inputText: `42`,
1425 wantMessage: &knownpb.UInt32Value{Value: 42},
1426 }, {
1427 desc: "UInt64Value",
1428 inputMessage: &knownpb.UInt64Value{},
1429 inputText: `"42"`,
1430 wantMessage: &knownpb.UInt64Value{Value: 42},
1431 }, {
1432 desc: "FloatValue",
1433 inputMessage: &knownpb.FloatValue{},
1434 inputText: `1.02`,
1435 wantMessage: &knownpb.FloatValue{Value: 1.02},
1436 }, {
1437 desc: "FloatValue exceeds max limit",
1438 inputMessage: &knownpb.FloatValue{},
1439 inputText: `1.23+40`,
1440 wantErr: true,
1441 }, {
1442 desc: "FloatValue Infinity",
1443 inputMessage: &knownpb.FloatValue{},
1444 inputText: `"-Infinity"`,
1445 wantMessage: &knownpb.FloatValue{Value: float32(math.Inf(-1))},
1446 }, {
1447 desc: "DoubleValue",
1448 inputMessage: &knownpb.DoubleValue{},
1449 inputText: `1.02`,
1450 wantMessage: &knownpb.DoubleValue{Value: 1.02},
1451 }, {
1452 desc: "DoubleValue Infinity",
1453 inputMessage: &knownpb.DoubleValue{},
1454 inputText: `"Infinity"`,
1455 wantMessage: &knownpb.DoubleValue{Value: math.Inf(+1)},
1456 }, {
1457 desc: "StringValue empty",
1458 inputMessage: &knownpb.StringValue{},
1459 inputText: `""`,
1460 wantMessage: &knownpb.StringValue{},
1461 }, {
1462 desc: "StringValue",
1463 inputMessage: &knownpb.StringValue{},
1464 inputText: `"谷歌"`,
1465 wantMessage: &knownpb.StringValue{Value: "谷歌"},
1466 }, {
1467 desc: "StringValue with invalid UTF8 error",
1468 inputMessage: &knownpb.StringValue{},
1469 inputText: "\"abc\xff\"",
1470 wantMessage: &knownpb.StringValue{Value: "abc\xff"},
1471 wantErr: true,
1472 }, {
1473 desc: "StringValue field with invalid UTF8 error",
1474 inputMessage: &pb2.KnownTypes{},
1475 inputText: "{\n \"optString\": \"abc\xff\"\n}",
1476 wantMessage: &pb2.KnownTypes{
1477 OptString: &knownpb.StringValue{Value: "abc\xff"},
1478 },
1479 wantErr: true,
1480 }, {
1481 desc: "BytesValue",
1482 inputMessage: &knownpb.BytesValue{},
1483 inputText: `"aGVsbG8="`,
1484 wantMessage: &knownpb.BytesValue{Value: []byte("hello")},
1485 }, {
1486 desc: "Value null",
1487 inputMessage: &knownpb.Value{},
1488 inputText: `null`,
1489 wantMessage: &knownpb.Value{Kind: &knownpb.Value_NullValue{}},
1490 }, {
1491 desc: "Value field null",
1492 inputMessage: &pb2.KnownTypes{},
1493 inputText: `{
1494 "optValue": null
1495}`,
1496 wantMessage: &pb2.KnownTypes{
1497 OptValue: &knownpb.Value{Kind: &knownpb.Value_NullValue{}},
1498 },
1499 }, {
1500 desc: "Value bool",
1501 inputMessage: &knownpb.Value{},
1502 inputText: `false`,
1503 wantMessage: &knownpb.Value{Kind: &knownpb.Value_BoolValue{}},
1504 }, {
1505 desc: "Value field bool",
1506 inputMessage: &pb2.KnownTypes{},
1507 inputText: `{
1508 "optValue": true
1509}`,
1510 wantMessage: &pb2.KnownTypes{
1511 OptValue: &knownpb.Value{Kind: &knownpb.Value_BoolValue{true}},
1512 },
1513 }, {
1514 desc: "Value number",
1515 inputMessage: &knownpb.Value{},
1516 inputText: `1.02`,
1517 wantMessage: &knownpb.Value{Kind: &knownpb.Value_NumberValue{1.02}},
1518 }, {
1519 desc: "Value field number",
1520 inputMessage: &pb2.KnownTypes{},
1521 inputText: `{
1522 "optValue": 1.02
1523}`,
1524 wantMessage: &pb2.KnownTypes{
1525 OptValue: &knownpb.Value{Kind: &knownpb.Value_NumberValue{1.02}},
1526 },
1527 }, {
1528 desc: "Value string",
1529 inputMessage: &knownpb.Value{},
1530 inputText: `"hello"`,
1531 wantMessage: &knownpb.Value{Kind: &knownpb.Value_StringValue{"hello"}},
1532 }, {
1533 desc: "Value string with invalid UTF8",
1534 inputMessage: &knownpb.Value{},
1535 inputText: "\"\xff\"",
1536 wantMessage: &knownpb.Value{Kind: &knownpb.Value_StringValue{"\xff"}},
1537 wantErr: true,
1538 }, {
1539 desc: "Value field string",
1540 inputMessage: &pb2.KnownTypes{},
1541 inputText: `{
1542 "optValue": "NaN"
1543}`,
1544 wantMessage: &pb2.KnownTypes{
1545 OptValue: &knownpb.Value{Kind: &knownpb.Value_StringValue{"NaN"}},
1546 },
1547 }, {
1548 desc: "Value field string with invalid UTF8",
1549 inputMessage: &pb2.KnownTypes{},
1550 inputText: `{
1551 "optValue": "` + "\xff" + `"
1552}`,
1553 wantMessage: &pb2.KnownTypes{
1554 OptValue: &knownpb.Value{Kind: &knownpb.Value_StringValue{"\xff"}},
1555 },
1556 wantErr: true,
1557 }, {
1558 desc: "Value empty struct",
1559 inputMessage: &knownpb.Value{},
1560 inputText: `{}`,
1561 wantMessage: &knownpb.Value{
1562 Kind: &knownpb.Value_StructValue{
1563 &knownpb.Struct{Fields: map[string]*knownpb.Value{}},
1564 },
1565 },
1566 }, {
1567 desc: "Value struct",
1568 inputMessage: &knownpb.Value{},
1569 inputText: `{
1570 "string": "hello",
1571 "number": 123,
1572 "null": null,
1573 "bool": false,
1574 "struct": {
1575 "string": "world"
1576 },
1577 "list": []
1578}`,
1579 wantMessage: &knownpb.Value{
1580 Kind: &knownpb.Value_StructValue{
1581 &knownpb.Struct{
1582 Fields: map[string]*knownpb.Value{
1583 "string": {Kind: &knownpb.Value_StringValue{"hello"}},
1584 "number": {Kind: &knownpb.Value_NumberValue{123}},
1585 "null": {Kind: &knownpb.Value_NullValue{}},
1586 "bool": {Kind: &knownpb.Value_BoolValue{false}},
1587 "struct": {
1588 Kind: &knownpb.Value_StructValue{
1589 &knownpb.Struct{
1590 Fields: map[string]*knownpb.Value{
1591 "string": {Kind: &knownpb.Value_StringValue{"world"}},
1592 },
1593 },
1594 },
1595 },
1596 "list": {
1597 Kind: &knownpb.Value_ListValue{&knownpb.ListValue{}},
1598 },
1599 },
1600 },
1601 },
1602 },
1603 }, {
1604 desc: "Value struct with invalid UTF8 string",
1605 inputMessage: &knownpb.Value{},
1606 inputText: "{\"string\": \"abc\xff\"}",
1607 wantMessage: &knownpb.Value{
1608 Kind: &knownpb.Value_StructValue{
1609 &knownpb.Struct{
1610 Fields: map[string]*knownpb.Value{
1611 "string": {Kind: &knownpb.Value_StringValue{"abc\xff"}},
1612 },
1613 },
1614 },
1615 },
1616 wantErr: true,
1617 }, {
1618 desc: "Value field struct",
1619 inputMessage: &pb2.KnownTypes{},
1620 inputText: `{
1621 "optValue": {
1622 "string": "hello"
1623 }
1624}`,
1625 wantMessage: &pb2.KnownTypes{
1626 OptValue: &knownpb.Value{
1627 Kind: &knownpb.Value_StructValue{
1628 &knownpb.Struct{
1629 Fields: map[string]*knownpb.Value{
1630 "string": {Kind: &knownpb.Value_StringValue{"hello"}},
1631 },
1632 },
1633 },
1634 },
1635 },
1636 }, {
1637 desc: "Value empty list",
1638 inputMessage: &knownpb.Value{},
1639 inputText: `[]`,
1640 wantMessage: &knownpb.Value{
1641 Kind: &knownpb.Value_ListValue{
1642 &knownpb.ListValue{Values: []*knownpb.Value{}},
1643 },
1644 },
1645 }, {
1646 desc: "Value list",
1647 inputMessage: &knownpb.Value{},
1648 inputText: `[
1649 "string",
1650 123,
1651 null,
1652 true,
1653 {},
1654 [
1655 "string",
1656 1.23,
1657 null,
1658 false
1659 ]
1660]`,
1661 wantMessage: &knownpb.Value{
1662 Kind: &knownpb.Value_ListValue{
1663 &knownpb.ListValue{
1664 Values: []*knownpb.Value{
1665 {Kind: &knownpb.Value_StringValue{"string"}},
1666 {Kind: &knownpb.Value_NumberValue{123}},
1667 {Kind: &knownpb.Value_NullValue{}},
1668 {Kind: &knownpb.Value_BoolValue{true}},
1669 {Kind: &knownpb.Value_StructValue{&knownpb.Struct{}}},
1670 {
1671 Kind: &knownpb.Value_ListValue{
1672 &knownpb.ListValue{
1673 Values: []*knownpb.Value{
1674 {Kind: &knownpb.Value_StringValue{"string"}},
1675 {Kind: &knownpb.Value_NumberValue{1.23}},
1676 {Kind: &knownpb.Value_NullValue{}},
1677 {Kind: &knownpb.Value_BoolValue{false}},
1678 },
1679 },
1680 },
1681 },
1682 },
1683 },
1684 },
1685 },
1686 }, {
1687 desc: "Value list with invalid UTF8 string",
1688 inputMessage: &knownpb.Value{},
1689 inputText: "[\"abc\xff\"]",
1690 wantMessage: &knownpb.Value{
1691 Kind: &knownpb.Value_ListValue{
1692 &knownpb.ListValue{
1693 Values: []*knownpb.Value{
1694 {Kind: &knownpb.Value_StringValue{"abc\xff"}},
1695 },
1696 },
1697 },
1698 },
1699 wantErr: true,
1700 }, {
1701 desc: "Value field list with invalid UTF8 string",
1702 inputMessage: &pb2.KnownTypes{},
1703 inputText: `{
1704 "optValue": [ "` + "abc\xff" + `"]
1705}`,
1706 wantMessage: &pb2.KnownTypes{
1707 OptValue: &knownpb.Value{
1708 Kind: &knownpb.Value_ListValue{
1709 &knownpb.ListValue{
1710 Values: []*knownpb.Value{
1711 {Kind: &knownpb.Value_StringValue{"abc\xff"}},
1712 },
1713 },
1714 },
1715 },
1716 },
1717 wantErr: true,
1718 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001719 desc: "Duration empty string",
1720 inputMessage: &knownpb.Duration{},
1721 inputText: `""`,
1722 wantErr: true,
1723 }, {
1724 desc: "Duration with secs",
1725 inputMessage: &knownpb.Duration{},
1726 inputText: `"3s"`,
1727 wantMessage: &knownpb.Duration{Seconds: 3},
1728 }, {
1729 desc: "Duration with escaped unicode",
1730 inputMessage: &knownpb.Duration{},
1731 inputText: `"\u0033s"`,
1732 wantMessage: &knownpb.Duration{Seconds: 3},
1733 }, {
1734 desc: "Duration with -secs",
1735 inputMessage: &knownpb.Duration{},
1736 inputText: `"-3s"`,
1737 wantMessage: &knownpb.Duration{Seconds: -3},
1738 }, {
1739 desc: "Duration with nanos",
1740 inputMessage: &knownpb.Duration{},
1741 inputText: `"0.001s"`,
1742 wantMessage: &knownpb.Duration{Nanos: 1e6},
1743 }, {
1744 desc: "Duration with -nanos",
1745 inputMessage: &knownpb.Duration{},
1746 inputText: `"-0.001s"`,
1747 wantMessage: &knownpb.Duration{Nanos: -1e6},
1748 }, {
1749 desc: "Duration with -secs -nanos",
1750 inputMessage: &knownpb.Duration{},
1751 inputText: `"-123.000000450s"`,
1752 wantMessage: &knownpb.Duration{Seconds: -123, Nanos: -450},
1753 }, {
1754 desc: "Duration with large secs",
1755 inputMessage: &knownpb.Duration{},
1756 inputText: `"10000000000.000000001s"`,
1757 wantMessage: &knownpb.Duration{Seconds: 1e10, Nanos: 1},
1758 }, {
1759 desc: "Duration with decimal without fractional",
1760 inputMessage: &knownpb.Duration{},
1761 inputText: `"3.s"`,
1762 wantMessage: &knownpb.Duration{Seconds: 3},
1763 }, {
1764 desc: "Duration with decimal without integer",
1765 inputMessage: &knownpb.Duration{},
1766 inputText: `"0.5s"`,
1767 wantMessage: &knownpb.Duration{Nanos: 5e8},
1768 }, {
1769 desc: "Duration with +secs out of range",
1770 inputMessage: &knownpb.Duration{},
1771 inputText: `"315576000001s"`,
1772 wantErr: true,
1773 }, {
1774 desc: "Duration with -secs out of range",
1775 inputMessage: &knownpb.Duration{},
1776 inputText: `"-315576000001s"`,
1777 wantErr: true,
1778 }, {
1779 desc: "Duration with nanos beyond 9 digits",
1780 inputMessage: &knownpb.Duration{},
1781 inputText: `"0.9999999990s"`,
1782 wantErr: true,
1783 }, {
1784 desc: "Duration without suffix s",
1785 inputMessage: &knownpb.Duration{},
1786 inputText: `"123"`,
1787 wantErr: true,
1788 }, {
1789 desc: "Timestamp zero",
1790 inputMessage: &knownpb.Timestamp{},
1791 inputText: `"1970-01-01T00:00:00Z"`,
1792 wantMessage: &knownpb.Timestamp{},
1793 }, {
1794 desc: "Timestamp with tz adjustment",
1795 inputMessage: &knownpb.Timestamp{},
1796 inputText: `"1970-01-01T00:00:00+01:00"`,
1797 wantMessage: &knownpb.Timestamp{Seconds: -3600},
1798 }, {
1799 desc: "Timestamp UTC",
1800 inputMessage: &knownpb.Timestamp{},
1801 inputText: `"2019-03-19T23:03:21Z"`,
1802 wantMessage: &knownpb.Timestamp{Seconds: 1553036601},
1803 }, {
1804 desc: "Timestamp with escaped unicode",
1805 inputMessage: &knownpb.Timestamp{},
1806 inputText: `"2019-0\u0033-19T23:03:21Z"`,
1807 wantMessage: &knownpb.Timestamp{Seconds: 1553036601},
1808 }, {
1809 desc: "Timestamp with nanos",
1810 inputMessage: &knownpb.Timestamp{},
1811 inputText: `"2019-03-19T23:03:21.000000001Z"`,
1812 wantMessage: &knownpb.Timestamp{Seconds: 1553036601, Nanos: 1},
1813 }, {
1814 desc: "Timestamp upper limit",
1815 inputMessage: &knownpb.Timestamp{},
1816 inputText: `"9999-12-31T23:59:59.999999999Z"`,
1817 wantMessage: &knownpb.Timestamp{Seconds: 253402300799, Nanos: 999999999},
1818 }, {
1819 desc: "Timestamp above upper limit",
1820 inputMessage: &knownpb.Timestamp{},
1821 inputText: `"9999-12-31T23:59:59-01:00"`,
1822 wantErr: true,
1823 }, {
1824 desc: "Timestamp lower limit",
1825 inputMessage: &knownpb.Timestamp{},
1826 inputText: `"0001-01-01T00:00:00Z"`,
1827 wantMessage: &knownpb.Timestamp{Seconds: -62135596800},
1828 }, {
1829 desc: "Timestamp below lower limit",
1830 inputMessage: &knownpb.Timestamp{},
1831 inputText: `"0001-01-01T00:00:00+01:00"`,
1832 wantErr: true,
1833 }, {
1834 desc: "Timestamp with nanos beyond 9 digits",
1835 inputMessage: &knownpb.Timestamp{},
1836 inputText: `"1970-01-01T00:00:00.0000000001Z"`,
1837 wantErr: true,
1838 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -07001839 desc: "FieldMask empty",
1840 inputMessage: &knownpb.FieldMask{},
1841 inputText: `""`,
1842 wantMessage: &knownpb.FieldMask{Paths: []string{}},
1843 }, {
1844 desc: "FieldMask",
1845 inputMessage: &knownpb.FieldMask{},
1846 inputText: `"foo,fooBar , foo.barQux ,Foo"`,
1847 wantMessage: &knownpb.FieldMask{
1848 Paths: []string{
1849 "foo",
1850 "foo_bar",
1851 "foo.bar_qux",
1852 "_foo",
1853 },
1854 },
1855 }, {
1856 desc: "FieldMask field",
1857 inputMessage: &pb2.KnownTypes{},
1858 inputText: `{
1859 "optFieldmask": "foo, qux.fooBar"
1860}`,
1861 wantMessage: &pb2.KnownTypes{
1862 OptFieldmask: &knownpb.FieldMask{
1863 Paths: []string{
1864 "foo",
1865 "qux.foo_bar",
1866 },
1867 },
1868 },
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001869 }, {
1870 desc: "Any empty",
1871 inputMessage: &knownpb.Any{},
1872 inputText: `{}`,
1873 wantMessage: &knownpb.Any{},
1874 }, {
1875 desc: "Any with non-custom message",
1876 umo: jsonpb.UnmarshalOptions{
1877 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
1878 },
1879 inputMessage: &knownpb.Any{},
1880 inputText: `{
1881 "@type": "foo/pb2.Nested",
1882 "optString": "embedded inside Any",
1883 "optNested": {
1884 "optString": "inception"
1885 }
1886}`,
1887 wantMessage: func() proto.Message {
1888 m := &pb2.Nested{
1889 OptString: scalar.String("embedded inside Any"),
1890 OptNested: &pb2.Nested{
1891 OptString: scalar.String("inception"),
1892 },
1893 }
1894 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1895 if err != nil {
1896 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1897 }
1898 return &knownpb.Any{
1899 TypeUrl: "foo/pb2.Nested",
1900 Value: b,
1901 }
1902 }(),
1903 }, {
1904 desc: "Any with empty embedded message",
1905 umo: jsonpb.UnmarshalOptions{
1906 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
1907 },
1908 inputMessage: &knownpb.Any{},
1909 inputText: `{
1910 "@type": "foo/pb2.Nested"
1911}`,
1912 wantMessage: &knownpb.Any{TypeUrl: "foo/pb2.Nested"},
1913 }, {
1914 desc: "Any without registered type",
1915 umo: jsonpb.UnmarshalOptions{Resolver: preg.NewTypes()},
1916 inputMessage: &knownpb.Any{},
1917 inputText: `{
1918 "@type": "foo/pb2.Nested"
1919}`,
1920 wantErr: true,
1921 }, {
1922 desc: "Any with missing required error",
1923 umo: jsonpb.UnmarshalOptions{
1924 Resolver: preg.NewTypes((&pb2.PartialRequired{}).ProtoReflect().Type()),
1925 },
1926 inputMessage: &knownpb.Any{},
1927 inputText: `{
1928 "@type": "pb2.PartialRequired",
1929 "optString": "embedded inside Any"
1930}`,
1931 wantMessage: func() proto.Message {
1932 m := &pb2.PartialRequired{
1933 OptString: scalar.String("embedded inside Any"),
1934 }
1935 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1936 // TODO: Marshal may fail due to required field not set at some
1937 // point. Need to ignore required not set error here.
1938 if err != nil {
1939 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1940 }
1941 return &knownpb.Any{
1942 TypeUrl: string(m.ProtoReflect().Type().FullName()),
1943 Value: b,
1944 }
1945 }(),
1946 wantErr: true,
1947 }, {
1948 desc: "Any with partial required and AllowPartial",
1949 umo: jsonpb.UnmarshalOptions{
1950 AllowPartial: true,
1951 Resolver: preg.NewTypes((&pb2.PartialRequired{}).ProtoReflect().Type()),
1952 },
1953 inputMessage: &knownpb.Any{},
1954 inputText: `{
1955 "@type": "pb2.PartialRequired",
1956 "optString": "embedded inside Any"
1957}`,
1958 wantMessage: func() proto.Message {
1959 m := &pb2.PartialRequired{
1960 OptString: scalar.String("embedded inside Any"),
1961 }
1962 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1963 // TODO: Marshal may fail due to required field not set at some
1964 // point. Need to ignore required not set error here.
1965 if err != nil {
1966 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1967 }
1968 return &knownpb.Any{
1969 TypeUrl: string(m.ProtoReflect().Type().FullName()),
1970 Value: b,
1971 }
1972 }(),
1973 }, {
1974 desc: "Any with invalid UTF8",
1975 umo: jsonpb.UnmarshalOptions{
1976 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
1977 },
1978 inputMessage: &knownpb.Any{},
1979 inputText: `{
1980 "optString": "` + "abc\xff" + `",
1981 "@type": "foo/pb2.Nested"
1982}`,
1983 wantMessage: func() proto.Message {
1984 m := &pb2.Nested{
1985 OptString: scalar.String("abc\xff"),
1986 }
1987 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1988 if err != nil {
1989 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1990 }
1991 return &knownpb.Any{
1992 TypeUrl: "foo/pb2.Nested",
1993 Value: b,
1994 }
1995 }(),
1996 wantErr: true,
1997 }, {
1998 desc: "Any with BoolValue",
1999 umo: jsonpb.UnmarshalOptions{
2000 Resolver: preg.NewTypes((&knownpb.BoolValue{}).ProtoReflect().Type()),
2001 },
2002 inputMessage: &knownpb.Any{},
2003 inputText: `{
2004 "@type": "type.googleapis.com/google.protobuf.BoolValue",
2005 "value": true
2006}`,
2007 wantMessage: func() proto.Message {
2008 m := &knownpb.BoolValue{Value: true}
2009 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2010 if err != nil {
2011 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2012 }
2013 return &knownpb.Any{
2014 TypeUrl: "type.googleapis.com/google.protobuf.BoolValue",
2015 Value: b,
2016 }
2017 }(),
2018 }, {
2019 desc: "Any with Empty",
2020 umo: jsonpb.UnmarshalOptions{
2021 Resolver: preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
2022 },
2023 inputMessage: &knownpb.Any{},
2024 inputText: `{
2025 "value": {},
2026 "@type": "type.googleapis.com/google.protobuf.Empty"
2027}`,
2028 wantMessage: func() proto.Message {
2029 m := &knownpb.Empty{}
2030 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2031 if err != nil {
2032 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2033 }
2034 return &knownpb.Any{
2035 TypeUrl: "type.googleapis.com/google.protobuf.Empty",
2036 Value: b,
2037 }
2038 }(),
2039 }, {
2040 desc: "Any with missing Empty",
2041 umo: jsonpb.UnmarshalOptions{
2042 Resolver: preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
2043 },
2044 inputMessage: &knownpb.Any{},
2045 inputText: `{
2046 "@type": "type.googleapis.com/google.protobuf.Empty"
2047}`,
2048 wantErr: true,
2049 }, {
2050 desc: "Any with StringValue containing invalid UTF8",
2051 umo: jsonpb.UnmarshalOptions{
2052 Resolver: preg.NewTypes((&knownpb.StringValue{}).ProtoReflect().Type()),
2053 },
2054 inputMessage: &knownpb.Any{},
2055 inputText: `{
2056 "@type": "google.protobuf.StringValue",
2057 "value": "` + "abc\xff" + `"
2058}`,
2059 wantMessage: func() proto.Message {
2060 m := &knownpb.StringValue{Value: "abc\xff"}
2061 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2062 if err != nil {
2063 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2064 }
2065 return &knownpb.Any{
2066 TypeUrl: "google.protobuf.StringValue",
2067 Value: b,
2068 }
2069 }(),
2070 wantErr: true,
2071 }, {
2072 desc: "Any with Int64Value",
2073 umo: jsonpb.UnmarshalOptions{
2074 Resolver: preg.NewTypes((&knownpb.Int64Value{}).ProtoReflect().Type()),
2075 },
2076 inputMessage: &knownpb.Any{},
2077 inputText: `{
2078 "@type": "google.protobuf.Int64Value",
2079 "value": "42"
2080}`,
2081 wantMessage: func() proto.Message {
2082 m := &knownpb.Int64Value{Value: 42}
2083 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2084 if err != nil {
2085 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2086 }
2087 return &knownpb.Any{
2088 TypeUrl: "google.protobuf.Int64Value",
2089 Value: b,
2090 }
2091 }(),
2092 }, {
2093 desc: "Any with invalid Int64Value",
2094 umo: jsonpb.UnmarshalOptions{
2095 Resolver: preg.NewTypes((&knownpb.Int64Value{}).ProtoReflect().Type()),
2096 },
2097 inputMessage: &knownpb.Any{},
2098 inputText: `{
2099 "@type": "google.protobuf.Int64Value",
2100 "value": "forty-two"
2101}`,
2102 wantErr: true,
2103 }, {
2104 desc: "Any with invalid UInt64Value",
2105 umo: jsonpb.UnmarshalOptions{
2106 Resolver: preg.NewTypes((&knownpb.UInt64Value{}).ProtoReflect().Type()),
2107 },
2108 inputMessage: &knownpb.Any{},
2109 inputText: `{
2110 "@type": "google.protobuf.UInt64Value",
2111 "value": -42
2112}`,
2113 wantErr: true,
2114 }, {
2115 desc: "Any with Duration",
2116 umo: jsonpb.UnmarshalOptions{
2117 Resolver: preg.NewTypes((&knownpb.Duration{}).ProtoReflect().Type()),
2118 },
2119 inputMessage: &knownpb.Any{},
2120 inputText: `{
2121 "@type": "type.googleapis.com/google.protobuf.Duration",
2122 "value": "0s"
2123}`,
2124 wantMessage: func() proto.Message {
2125 m := &knownpb.Duration{}
2126 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2127 if err != nil {
2128 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2129 }
2130 return &knownpb.Any{
2131 TypeUrl: "type.googleapis.com/google.protobuf.Duration",
2132 Value: b,
2133 }
2134 }(),
2135 }, {
2136 desc: "Any with Value of StringValue",
2137 umo: jsonpb.UnmarshalOptions{
2138 Resolver: preg.NewTypes((&knownpb.Value{}).ProtoReflect().Type()),
2139 },
2140 inputMessage: &knownpb.Any{},
2141 inputText: `{
2142 "@type": "google.protobuf.Value",
2143 "value": "` + "abc\xff" + `"
2144}`,
2145 wantMessage: func() proto.Message {
2146 m := &knownpb.Value{Kind: &knownpb.Value_StringValue{"abc\xff"}}
2147 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2148 if err != nil {
2149 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2150 }
2151 return &knownpb.Any{
2152 TypeUrl: "google.protobuf.Value",
2153 Value: b,
2154 }
2155 }(),
2156 wantErr: true,
2157 }, {
2158 desc: "Any with Value of NullValue",
2159 umo: jsonpb.UnmarshalOptions{
2160 Resolver: preg.NewTypes((&knownpb.Value{}).ProtoReflect().Type()),
2161 },
2162 inputMessage: &knownpb.Any{},
2163 inputText: `{
2164 "@type": "google.protobuf.Value",
2165 "value": null
2166}`,
2167 wantMessage: func() proto.Message {
2168 m := &knownpb.Value{Kind: &knownpb.Value_NullValue{}}
2169 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2170 if err != nil {
2171 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2172 }
2173 return &knownpb.Any{
2174 TypeUrl: "google.protobuf.Value",
2175 Value: b,
2176 }
2177 }(),
2178 }, {
2179 desc: "Any with Struct",
2180 umo: jsonpb.UnmarshalOptions{
2181 Resolver: preg.NewTypes(
2182 (&knownpb.Struct{}).ProtoReflect().Type(),
2183 (&knownpb.Value{}).ProtoReflect().Type(),
2184 (&knownpb.BoolValue{}).ProtoReflect().Type(),
2185 knownpb.NullValue_NULL_VALUE.Type(),
2186 (&knownpb.StringValue{}).ProtoReflect().Type(),
2187 ),
2188 },
2189 inputMessage: &knownpb.Any{},
2190 inputText: `{
2191 "@type": "google.protobuf.Struct",
2192 "value": {
2193 "bool": true,
2194 "null": null,
2195 "string": "hello",
2196 "struct": {
2197 "string": "world"
2198 }
2199 }
2200}`,
2201 wantMessage: func() proto.Message {
2202 m := &knownpb.Struct{
2203 Fields: map[string]*knownpb.Value{
2204 "bool": {Kind: &knownpb.Value_BoolValue{true}},
2205 "null": {Kind: &knownpb.Value_NullValue{}},
2206 "string": {Kind: &knownpb.Value_StringValue{"hello"}},
2207 "struct": {
2208 Kind: &knownpb.Value_StructValue{
2209 &knownpb.Struct{
2210 Fields: map[string]*knownpb.Value{
2211 "string": {Kind: &knownpb.Value_StringValue{"world"}},
2212 },
2213 },
2214 },
2215 },
2216 },
2217 }
2218 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2219 if err != nil {
2220 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2221 }
2222 return &knownpb.Any{
2223 TypeUrl: "google.protobuf.Struct",
2224 Value: b,
2225 }
2226 }(),
2227 }, {
2228 desc: "Any with missing @type",
2229 umo: jsonpb.UnmarshalOptions{},
2230 inputMessage: &knownpb.Any{},
2231 inputText: `{
2232 "value": {}
2233}`,
2234 wantErr: true,
2235 }, {
2236 desc: "Any with empty @type",
2237 inputMessage: &knownpb.Any{},
2238 inputText: `{
2239 "@type": ""
2240}`,
2241 wantErr: true,
2242 }, {
2243 desc: "Any with duplicate @type",
2244 umo: jsonpb.UnmarshalOptions{
2245 Resolver: preg.NewTypes(
2246 (&pb2.Nested{}).ProtoReflect().Type(),
2247 (&knownpb.StringValue{}).ProtoReflect().Type(),
2248 ),
2249 },
2250 inputMessage: &knownpb.Any{},
2251 inputText: `{
2252 "@type": "google.protobuf.StringValue",
2253 "value": "hello",
2254 "@type": "pb2.Nested"
2255}`,
2256 wantErr: true,
2257 }, {
2258 desc: "Any with duplicate value",
2259 umo: jsonpb.UnmarshalOptions{
2260 Resolver: preg.NewTypes((&knownpb.StringValue{}).ProtoReflect().Type()),
2261 },
2262 inputMessage: &knownpb.Any{},
2263 inputText: `{
2264 "@type": "google.protobuf.StringValue",
2265 "value": "hello",
2266 "value": "world"
2267}`,
2268 wantErr: true,
2269 }, {
2270 desc: "Any with unknown field",
2271 umo: jsonpb.UnmarshalOptions{
2272 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
2273 },
2274 inputMessage: &knownpb.Any{},
2275 inputText: `{
2276 "@type": "pb2.Nested",
2277 "optString": "hello",
2278 "unknown": "world"
2279}`,
2280 wantErr: true,
2281 }, {
2282 desc: "Any with embedded type containing Any",
2283 umo: jsonpb.UnmarshalOptions{
2284 Resolver: preg.NewTypes(
2285 (&pb2.KnownTypes{}).ProtoReflect().Type(),
2286 (&knownpb.Any{}).ProtoReflect().Type(),
2287 (&knownpb.StringValue{}).ProtoReflect().Type(),
2288 ),
2289 },
2290 inputMessage: &knownpb.Any{},
2291 inputText: `{
2292 "@type": "pb2.KnownTypes",
2293 "optAny": {
2294 "@type": "google.protobuf.StringValue",
2295 "value": "` + "abc\xff" + `"
2296 }
2297}`,
2298 wantMessage: func() proto.Message {
2299 m1 := &knownpb.StringValue{Value: "abc\xff"}
2300 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
2301 if err != nil {
2302 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2303 }
2304 m2 := &knownpb.Any{
2305 TypeUrl: "google.protobuf.StringValue",
2306 Value: b,
2307 }
2308 m3 := &pb2.KnownTypes{OptAny: m2}
2309 b, err = proto.MarshalOptions{Deterministic: true}.Marshal(m3)
2310 if err != nil {
2311 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2312 }
2313 return &knownpb.Any{
2314 TypeUrl: "pb2.KnownTypes",
2315 Value: b,
2316 }
2317 }(),
2318 wantErr: true,
2319 }, {
2320 desc: "well known types as field values",
2321 umo: jsonpb.UnmarshalOptions{
2322 Resolver: preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
2323 },
2324 inputMessage: &pb2.KnownTypes{},
2325 inputText: `{
2326 "optBool": false,
2327 "optInt32": 42,
2328 "optInt64": "42",
2329 "optUint32": 42,
2330 "optUint64": "42",
2331 "optFloat": 1.23,
2332 "optDouble": 3.1415,
2333 "optString": "hello",
2334 "optBytes": "aGVsbG8=",
2335 "optDuration": "123s",
2336 "optTimestamp": "2019-03-19T23:03:21Z",
2337 "optStruct": {
2338 "string": "hello"
2339 },
2340 "optList": [
2341 null,
2342 "",
2343 {},
2344 []
2345 ],
2346 "optValue": "world",
2347 "optEmpty": {},
2348 "optAny": {
2349 "@type": "google.protobuf.Empty",
2350 "value": {}
2351 },
2352 "optFieldmask": "fooBar,barFoo"
2353}`,
2354 wantMessage: &pb2.KnownTypes{
2355 OptBool: &knownpb.BoolValue{Value: false},
2356 OptInt32: &knownpb.Int32Value{Value: 42},
2357 OptInt64: &knownpb.Int64Value{Value: 42},
2358 OptUint32: &knownpb.UInt32Value{Value: 42},
2359 OptUint64: &knownpb.UInt64Value{Value: 42},
2360 OptFloat: &knownpb.FloatValue{Value: 1.23},
2361 OptDouble: &knownpb.DoubleValue{Value: 3.1415},
2362 OptString: &knownpb.StringValue{Value: "hello"},
2363 OptBytes: &knownpb.BytesValue{Value: []byte("hello")},
2364 OptDuration: &knownpb.Duration{Seconds: 123},
2365 OptTimestamp: &knownpb.Timestamp{Seconds: 1553036601},
2366 OptStruct: &knownpb.Struct{
2367 Fields: map[string]*knownpb.Value{
2368 "string": {Kind: &knownpb.Value_StringValue{"hello"}},
2369 },
2370 },
2371 OptList: &knownpb.ListValue{
2372 Values: []*knownpb.Value{
2373 {Kind: &knownpb.Value_NullValue{}},
2374 {Kind: &knownpb.Value_StringValue{}},
2375 {
2376 Kind: &knownpb.Value_StructValue{
2377 &knownpb.Struct{Fields: map[string]*knownpb.Value{}},
2378 },
2379 },
2380 {
2381 Kind: &knownpb.Value_ListValue{
2382 &knownpb.ListValue{Values: []*knownpb.Value{}},
2383 },
2384 },
2385 },
2386 },
2387 OptValue: &knownpb.Value{
2388 Kind: &knownpb.Value_StringValue{"world"},
2389 },
2390 OptEmpty: &knownpb.Empty{},
2391 OptAny: &knownpb.Any{
2392 TypeUrl: "google.protobuf.Empty",
2393 },
2394 OptFieldmask: &knownpb.FieldMask{
2395 Paths: []string{"foo_bar", "bar_foo"},
2396 },
2397 },
Herbie Ongc96a79d2019-03-08 10:49:17 -08002398 }}
2399
2400 for _, tt := range tests {
2401 tt := tt
2402 t.Run(tt.desc, func(t *testing.T) {
2403 err := tt.umo.Unmarshal(tt.inputMessage, []byte(tt.inputText))
2404 if err != nil && !tt.wantErr {
2405 t.Errorf("Unmarshal() returned error: %v\n\n", err)
2406 }
2407 if err == nil && tt.wantErr {
2408 t.Error("Unmarshal() got nil error, want error\n\n")
2409 }
2410 if tt.wantMessage != nil && !protoV1.Equal(tt.inputMessage.(protoV1.Message), tt.wantMessage.(protoV1.Message)) {
2411 t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", tt.inputMessage, tt.wantMessage)
2412 }
2413 })
2414 }
2415}