blob: 9d50ac109e67bd38fd4dec5502c8be1f3bb0c18e [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: `{
Herbie Ong300b9fe2019-03-29 15:42:20 -0700442 "sEnum": "1"
Herbie Ongc96a79d2019-03-08 10:49:17 -0800443}`,
444 wantErr: true,
445 }, {
446 desc: "enum set to invalid named",
447 inputMessage: &pb3.Enums{},
448 inputText: `{
Herbie Ong300b9fe2019-03-29 15:42:20 -0700449 "sEnum": "UNNAMED"
Herbie Ongc96a79d2019-03-08 10:49:17 -0800450}`,
451 wantErr: true,
452 }, {
453 desc: "enum set to not enum",
454 inputMessage: &pb3.Enums{},
455 inputText: `{
Herbie Ong300b9fe2019-03-29 15:42:20 -0700456 "sEnum": true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800457}`,
458 wantErr: true,
459 }, {
Herbie Ong300b9fe2019-03-29 15:42:20 -0700460 desc: "enum set to JSON null",
461 inputMessage: &pb3.Enums{},
462 inputText: `{
463 "sEnum": null
464}`,
465 wantMessage: &pb3.Enums{},
466 }, {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800467 desc: "proto name",
468 inputMessage: &pb3.JSONNames{},
469 inputText: `{
470 "s_string": "proto name used"
471}`,
472 wantMessage: &pb3.JSONNames{
473 SString: "proto name used",
474 },
475 }, {
476 desc: "json_name",
477 inputMessage: &pb3.JSONNames{},
478 inputText: `{
479 "foo_bar": "json_name used"
480}`,
481 wantMessage: &pb3.JSONNames{
482 SString: "json_name used",
483 },
484 }, {
485 desc: "camelCase name",
486 inputMessage: &pb3.JSONNames{},
487 inputText: `{
488 "sString": "camelcase used"
489}`,
490 wantErr: true,
491 }, {
492 desc: "proto name and json_name",
493 inputMessage: &pb3.JSONNames{},
494 inputText: `{
495 "foo_bar": "json_name used",
496 "s_string": "proto name used"
497}`,
498 wantErr: true,
499 }, {
500 desc: "duplicate field names",
501 inputMessage: &pb3.JSONNames{},
502 inputText: `{
503 "foo_bar": "one",
504 "foo_bar": "two",
505}`,
506 wantErr: true,
507 }, {
508 desc: "null message",
509 inputMessage: &pb2.Nests{},
510 inputText: "null",
511 wantErr: true,
512 }, {
513 desc: "proto2 nested message not set",
514 inputMessage: &pb2.Nests{},
515 inputText: "{}",
516 wantMessage: &pb2.Nests{},
517 }, {
518 desc: "proto2 nested message set to null",
519 inputMessage: &pb2.Nests{},
520 inputText: `{
521 "optNested": null,
522 "optgroup": null
523}`,
524 wantMessage: &pb2.Nests{},
525 }, {
526 desc: "proto2 nested message set to empty",
527 inputMessage: &pb2.Nests{},
528 inputText: `{
529 "optNested": {},
530 "optgroup": {}
531}`,
532 wantMessage: &pb2.Nests{
533 OptNested: &pb2.Nested{},
534 Optgroup: &pb2.Nests_OptGroup{},
535 },
536 }, {
537 desc: "proto2 nested messages",
538 inputMessage: &pb2.Nests{},
539 inputText: `{
540 "optNested": {
541 "optString": "nested message",
542 "optNested": {
543 "optString": "another nested message"
544 }
545 }
546}`,
547 wantMessage: &pb2.Nests{
548 OptNested: &pb2.Nested{
549 OptString: scalar.String("nested message"),
550 OptNested: &pb2.Nested{
551 OptString: scalar.String("another nested message"),
552 },
553 },
554 },
555 }, {
556 desc: "proto2 groups",
557 inputMessage: &pb2.Nests{},
558 inputText: `{
559 "optgroup": {
560 "optString": "inside a group",
561 "optNested": {
562 "optString": "nested message inside a group"
563 },
564 "optnestedgroup": {
565 "optFixed32": 47
566 }
567 }
568}`,
569 wantMessage: &pb2.Nests{
570 Optgroup: &pb2.Nests_OptGroup{
571 OptString: scalar.String("inside a group"),
572 OptNested: &pb2.Nested{
573 OptString: scalar.String("nested message inside a group"),
574 },
575 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
576 OptFixed32: scalar.Uint32(47),
577 },
578 },
579 },
580 }, {
581 desc: "proto3 nested message not set",
582 inputMessage: &pb3.Nests{},
583 inputText: "{}",
584 wantMessage: &pb3.Nests{},
585 }, {
586 desc: "proto3 nested message set to null",
587 inputMessage: &pb3.Nests{},
588 inputText: `{"sNested": null}`,
589 wantMessage: &pb3.Nests{},
590 }, {
591 desc: "proto3 nested message set to empty",
592 inputMessage: &pb3.Nests{},
593 inputText: `{"sNested": {}}`,
594 wantMessage: &pb3.Nests{
595 SNested: &pb3.Nested{},
596 },
597 }, {
598 desc: "proto3 nested message",
599 inputMessage: &pb3.Nests{},
600 inputText: `{
601 "sNested": {
602 "sString": "nested message",
603 "sNested": {
604 "sString": "another nested message"
605 }
606 }
607}`,
608 wantMessage: &pb3.Nests{
609 SNested: &pb3.Nested{
610 SString: "nested message",
611 SNested: &pb3.Nested{
612 SString: "another nested message",
613 },
614 },
615 },
616 }, {
617 desc: "message set to non-message",
618 inputMessage: &pb3.Nests{},
619 inputText: `"not valid"`,
620 wantErr: true,
621 }, {
622 desc: "nested message set to non-message",
623 inputMessage: &pb3.Nests{},
624 inputText: `{"sNested": true}`,
625 wantErr: true,
626 }, {
627 desc: "oneof not set",
628 inputMessage: &pb3.Oneofs{},
629 inputText: "{}",
630 wantMessage: &pb3.Oneofs{},
631 }, {
632 desc: "oneof set to empty string",
633 inputMessage: &pb3.Oneofs{},
634 inputText: `{"oneofString": ""}`,
635 wantMessage: &pb3.Oneofs{
636 Union: &pb3.Oneofs_OneofString{},
637 },
638 }, {
639 desc: "oneof set to string",
640 inputMessage: &pb3.Oneofs{},
641 inputText: `{"oneofString": "hello"}`,
642 wantMessage: &pb3.Oneofs{
643 Union: &pb3.Oneofs_OneofString{
644 OneofString: "hello",
645 },
646 },
647 }, {
648 desc: "oneof set to enum",
649 inputMessage: &pb3.Oneofs{},
650 inputText: `{"oneofEnum": "ZERO"}`,
651 wantMessage: &pb3.Oneofs{
652 Union: &pb3.Oneofs_OneofEnum{
653 OneofEnum: pb3.Enum_ZERO,
654 },
655 },
656 }, {
657 desc: "oneof set to empty message",
658 inputMessage: &pb3.Oneofs{},
659 inputText: `{"oneofNested": {}}`,
660 wantMessage: &pb3.Oneofs{
661 Union: &pb3.Oneofs_OneofNested{
662 OneofNested: &pb3.Nested{},
663 },
664 },
665 }, {
666 desc: "oneof set to message",
667 inputMessage: &pb3.Oneofs{},
668 inputText: `{
669 "oneofNested": {
670 "sString": "nested message"
671 }
672}`,
673 wantMessage: &pb3.Oneofs{
674 Union: &pb3.Oneofs_OneofNested{
675 OneofNested: &pb3.Nested{
676 SString: "nested message",
677 },
678 },
679 },
680 }, {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700681 desc: "oneof set to more than one field",
682 inputMessage: &pb3.Oneofs{},
683 inputText: `{
684 "oneofEnum": "ZERO",
685 "oneofString": "hello"
686}`,
687 wantErr: true,
688 }, {
689 desc: "oneof set to null and value",
690 inputMessage: &pb3.Oneofs{},
691 inputText: `{
692 "oneofEnum": "ZERO",
693 "oneofString": null
694}`,
695 wantMessage: &pb3.Oneofs{
696 Union: &pb3.Oneofs_OneofEnum{
697 OneofEnum: pb3.Enum_ZERO,
698 },
699 },
700 }, {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800701 desc: "repeated null fields",
702 inputMessage: &pb2.Repeats{},
703 inputText: `{
704 "rptString": null,
705 "rptInt32" : null,
706 "rptFloat" : null,
707 "rptBytes" : null
708}`,
709 wantMessage: &pb2.Repeats{},
710 }, {
711 desc: "repeated scalars",
712 inputMessage: &pb2.Repeats{},
713 inputText: `{
714 "rptString": ["hello", "world"],
715 "rptInt32" : [-1, 0, 1],
716 "rptBool" : [false, true]
717}`,
718 wantMessage: &pb2.Repeats{
719 RptString: []string{"hello", "world"},
720 RptInt32: []int32{-1, 0, 1},
721 RptBool: []bool{false, true},
722 },
723 }, {
724 desc: "repeated enums",
725 inputMessage: &pb2.Enums{},
726 inputText: `{
727 "rptEnum" : ["TEN", 1, 42],
728 "rptNestedEnum": ["DOS", 2, -47]
729}`,
730 wantMessage: &pb2.Enums{
731 RptEnum: []pb2.Enum{pb2.Enum_TEN, pb2.Enum_ONE, 42},
732 RptNestedEnum: []pb2.Enums_NestedEnum{pb2.Enums_DOS, pb2.Enums_DOS, -47},
733 },
734 }, {
735 desc: "repeated messages",
736 inputMessage: &pb2.Nests{},
737 inputText: `{
738 "rptNested": [
739 {
740 "optString": "repeat nested one"
741 },
742 {
743 "optString": "repeat nested two",
744 "optNested": {
745 "optString": "inside repeat nested two"
746 }
747 },
748 {}
749 ]
750}`,
751 wantMessage: &pb2.Nests{
752 RptNested: []*pb2.Nested{
753 {
754 OptString: scalar.String("repeat nested one"),
755 },
756 {
757 OptString: scalar.String("repeat nested two"),
758 OptNested: &pb2.Nested{
759 OptString: scalar.String("inside repeat nested two"),
760 },
761 },
762 {},
763 },
764 },
765 }, {
766 desc: "repeated groups",
767 inputMessage: &pb2.Nests{},
768 inputText: `{
769 "rptgroup": [
770 {
771 "rptString": ["hello", "world"]
772 },
773 {}
774 ]
775}
776`,
777 wantMessage: &pb2.Nests{
778 Rptgroup: []*pb2.Nests_RptGroup{
779 {
780 RptString: []string{"hello", "world"},
781 },
782 {},
783 },
784 },
785 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -0700786 desc: "repeated string contains invalid UTF8",
787 inputMessage: &pb2.Repeats{},
788 inputText: `{"rptString": ["` + "abc\xff" + `"]}`,
789 wantMessage: &pb2.Repeats{
790 RptString: []string{"abc\xff"},
791 },
792 wantErr: true,
793 }, {
794 desc: "repeated messages contain invalid UTF8",
795 inputMessage: &pb2.Nests{},
796 inputText: `{"rptNested": [{"optString": "` + "abc\xff" + `"}]}`,
797 wantMessage: &pb2.Nests{
798 RptNested: []*pb2.Nested{{OptString: scalar.String("abc\xff")}},
799 },
800 wantErr: true,
801 }, {
802 desc: "repeated scalars contain invalid type",
Herbie Ongc96a79d2019-03-08 10:49:17 -0800803 inputMessage: &pb2.Repeats{},
804 inputText: `{"rptString": ["hello", null, "world"]}`,
805 wantErr: true,
806 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -0700807 desc: "repeated messages contain invalid type",
Herbie Ongc96a79d2019-03-08 10:49:17 -0800808 inputMessage: &pb2.Nests{},
809 inputText: `{"rptNested": [{}, null]}`,
810 wantErr: true,
811 }, {
812 desc: "map fields 1",
813 inputMessage: &pb3.Maps{},
814 inputText: `{
815 "int32ToStr": {
816 "-101": "-101",
817 "0" : "zero",
818 "255" : "0xff"
819 },
820 "boolToUint32": {
821 "false": 101,
822 "true" : "42"
823 }
824}`,
825 wantMessage: &pb3.Maps{
826 Int32ToStr: map[int32]string{
827 -101: "-101",
828 0xff: "0xff",
829 0: "zero",
830 },
831 BoolToUint32: map[bool]uint32{
832 true: 42,
833 false: 101,
834 },
835 },
836 }, {
837 desc: "map fields 2",
838 inputMessage: &pb3.Maps{},
839 inputText: `{
840 "uint64ToEnum": {
841 "1" : "ONE",
842 "2" : 2,
843 "10": 101
844 }
845}`,
846 wantMessage: &pb3.Maps{
847 Uint64ToEnum: map[uint64]pb3.Enum{
848 1: pb3.Enum_ONE,
849 2: pb3.Enum_TWO,
850 10: 101,
851 },
852 },
853 }, {
854 desc: "map fields 3",
855 inputMessage: &pb3.Maps{},
856 inputText: `{
857 "strToNested": {
858 "nested_one": {
859 "sString": "nested in a map"
860 },
861 "nested_two": {}
862 }
863}`,
864 wantMessage: &pb3.Maps{
865 StrToNested: map[string]*pb3.Nested{
866 "nested_one": {
867 SString: "nested in a map",
868 },
869 "nested_two": {},
870 },
871 },
872 }, {
873 desc: "map fields 4",
874 inputMessage: &pb3.Maps{},
875 inputText: `{
876 "strToOneofs": {
877 "nested": {
878 "oneofNested": {
879 "sString": "nested oneof in map field value"
880 }
881 },
882 "string": {
883 "oneofString": "hello"
884 }
885 }
886}`,
887 wantMessage: &pb3.Maps{
888 StrToOneofs: map[string]*pb3.Oneofs{
889 "string": {
890 Union: &pb3.Oneofs_OneofString{
891 OneofString: "hello",
892 },
893 },
894 "nested": {
895 Union: &pb3.Oneofs_OneofNested{
896 OneofNested: &pb3.Nested{
897 SString: "nested oneof in map field value",
898 },
899 },
900 },
901 },
902 },
903 }, {
904 desc: "map contains duplicate keys",
905 inputMessage: &pb3.Maps{},
906 inputText: `{
907 "int32ToStr": {
908 "0": "cero",
909 "0": "zero"
910 }
911}
912`,
913 wantErr: true,
914 }, {
915 desc: "map key empty string",
916 inputMessage: &pb3.Maps{},
917 inputText: `{
918 "strToNested": {
919 "": {}
920 }
921}`,
922 wantMessage: &pb3.Maps{
923 StrToNested: map[string]*pb3.Nested{
924 "": {},
925 },
926 },
927 }, {
928 desc: "map contains invalid key 1",
929 inputMessage: &pb3.Maps{},
930 inputText: `{
931 "int32ToStr": {
932 "invalid": "cero"
933}`,
934 wantErr: true,
935 }, {
936 desc: "map contains invalid key 2",
937 inputMessage: &pb3.Maps{},
938 inputText: `{
939 "int32ToStr": {
940 "1.02": "float"
941}`,
942 wantErr: true,
943 }, {
944 desc: "map contains invalid key 3",
945 inputMessage: &pb3.Maps{},
946 inputText: `{
947 "int32ToStr": {
948 "2147483648": "exceeds 32-bit integer max limit"
949}`,
950 wantErr: true,
951 }, {
952 desc: "map contains invalid key 4",
953 inputMessage: &pb3.Maps{},
954 inputText: `{
955 "uint64ToEnum": {
956 "-1": 0
957 }
958}`,
959 wantErr: true,
960 }, {
961 desc: "map contains invalid value",
962 inputMessage: &pb3.Maps{},
963 inputText: `{
964 "int32ToStr": {
965 "101": true
966}`,
967 wantErr: true,
968 }, {
969 desc: "map contains null for scalar value",
970 inputMessage: &pb3.Maps{},
971 inputText: `{
972 "int32ToStr": {
973 "101": null
974}`,
975 wantErr: true,
976 }, {
977 desc: "map contains null for message value",
978 inputMessage: &pb3.Maps{},
979 inputText: `{
980 "strToNested": {
981 "hello": null
982 }
983}`,
984 wantErr: true,
Herbie Onge52379a2019-03-15 18:00:19 -0700985 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -0700986 desc: "map contains contains message value with invalid UTF8",
987 inputMessage: &pb3.Maps{},
988 inputText: `{
989 "strToNested": {
990 "hello": {
991 "sString": "` + "abc\xff" + `"
992 }
993 }
994}`,
995 wantMessage: &pb3.Maps{
996 StrToNested: map[string]*pb3.Nested{
997 "hello": {SString: "abc\xff"},
998 },
999 },
1000 wantErr: true,
1001 }, {
1002 desc: "map key contains invalid UTF8",
1003 inputMessage: &pb3.Maps{},
1004 inputText: `{
1005 "strToNested": {
1006 "` + "abc\xff" + `": {}
1007 }
1008}`,
1009 wantMessage: &pb3.Maps{
1010 StrToNested: map[string]*pb3.Nested{
1011 "abc\xff": {},
1012 },
1013 },
1014 wantErr: true,
1015 }, {
Herbie Ong329be5b2019-03-27 14:47:59 -07001016 desc: "required fields not set",
1017 inputMessage: &pb2.Requireds{},
1018 wantErr: true,
1019 }, {
1020 desc: "required field set",
1021 inputMessage: &pb2.PartialRequired{},
1022 inputText: `{
1023 "reqString": "this is required"
1024}`,
1025 wantMessage: &pb2.PartialRequired{
1026 ReqString: scalar.String("this is required"),
1027 },
1028 }, {
1029 desc: "required fields partially set",
1030 inputMessage: &pb2.Requireds{},
1031 inputText: `{
1032 "reqBool": false,
1033 "reqSfixed64": 42,
1034 "reqString": "hello",
1035 "reqEnum": "ONE"
1036}`,
1037 wantMessage: &pb2.Requireds{
1038 ReqBool: scalar.Bool(false),
1039 ReqSfixed64: scalar.Int64(42),
1040 ReqString: scalar.String("hello"),
1041 ReqEnum: pb2.Enum_ONE.Enum(),
1042 },
1043 wantErr: true,
1044 }, {
1045 desc: "required fields partially set with AllowPartial",
1046 umo: jsonpb.UnmarshalOptions{AllowPartial: true},
1047 inputMessage: &pb2.Requireds{},
1048 inputText: `{
1049 "reqBool": false,
1050 "reqSfixed64": 42,
1051 "reqString": "hello",
1052 "reqEnum": "ONE"
1053}`,
1054 wantMessage: &pb2.Requireds{
1055 ReqBool: scalar.Bool(false),
1056 ReqSfixed64: scalar.Int64(42),
1057 ReqString: scalar.String("hello"),
1058 ReqEnum: pb2.Enum_ONE.Enum(),
1059 },
1060 }, {
1061 desc: "required fields all set",
1062 inputMessage: &pb2.Requireds{},
1063 inputText: `{
1064 "reqBool": false,
1065 "reqSfixed64": 42,
1066 "reqDouble": 1.23,
1067 "reqString": "hello",
1068 "reqEnum": "ONE",
1069 "reqNested": {}
1070}`,
1071 wantMessage: &pb2.Requireds{
1072 ReqBool: scalar.Bool(false),
1073 ReqSfixed64: scalar.Int64(42),
1074 ReqDouble: scalar.Float64(1.23),
1075 ReqString: scalar.String("hello"),
1076 ReqEnum: pb2.Enum_ONE.Enum(),
1077 ReqNested: &pb2.Nested{},
1078 },
1079 }, {
1080 desc: "indirect required field",
1081 inputMessage: &pb2.IndirectRequired{},
1082 inputText: `{
1083 "optNested": {}
1084}`,
1085 wantMessage: &pb2.IndirectRequired{
1086 OptNested: &pb2.NestedWithRequired{},
1087 },
1088 wantErr: true,
1089 }, {
1090 desc: "indirect required field with AllowPartial",
1091 umo: jsonpb.UnmarshalOptions{AllowPartial: true},
1092 inputMessage: &pb2.IndirectRequired{},
1093 inputText: `{
1094 "optNested": {}
1095}`,
1096 wantMessage: &pb2.IndirectRequired{
1097 OptNested: &pb2.NestedWithRequired{},
1098 },
1099 }, {
1100 desc: "indirect required field in repeated",
1101 inputMessage: &pb2.IndirectRequired{},
1102 inputText: `{
1103 "rptNested": [
1104 {"reqString": "one"},
1105 {}
1106 ]
1107}`,
1108 wantMessage: &pb2.IndirectRequired{
1109 RptNested: []*pb2.NestedWithRequired{
1110 {
1111 ReqString: scalar.String("one"),
1112 },
1113 {},
1114 },
1115 },
1116 wantErr: true,
1117 }, {
1118 desc: "indirect required field in repeated with AllowPartial",
1119 umo: jsonpb.UnmarshalOptions{AllowPartial: true},
1120 inputMessage: &pb2.IndirectRequired{},
1121 inputText: `{
1122 "rptNested": [
1123 {"reqString": "one"},
1124 {}
1125 ]
1126}`,
1127 wantMessage: &pb2.IndirectRequired{
1128 RptNested: []*pb2.NestedWithRequired{
1129 {
1130 ReqString: scalar.String("one"),
1131 },
1132 {},
1133 },
1134 },
1135 }, {
1136 desc: "indirect required field in map",
1137 inputMessage: &pb2.IndirectRequired{},
1138 inputText: `{
1139 "strToNested": {
1140 "missing": {},
1141 "contains": {
1142 "reqString": "here"
1143 }
1144 }
1145}`,
1146 wantMessage: &pb2.IndirectRequired{
1147 StrToNested: map[string]*pb2.NestedWithRequired{
1148 "missing": &pb2.NestedWithRequired{},
1149 "contains": &pb2.NestedWithRequired{
1150 ReqString: scalar.String("here"),
1151 },
1152 },
1153 },
1154 wantErr: true,
1155 }, {
1156 desc: "indirect required field in map with AllowPartial",
1157 umo: jsonpb.UnmarshalOptions{AllowPartial: true},
1158 inputMessage: &pb2.IndirectRequired{},
1159 inputText: `{
1160 "strToNested": {
1161 "missing": {},
1162 "contains": {
1163 "reqString": "here"
1164 }
1165 }
1166}`,
1167 wantMessage: &pb2.IndirectRequired{
1168 StrToNested: map[string]*pb2.NestedWithRequired{
1169 "missing": &pb2.NestedWithRequired{},
1170 "contains": &pb2.NestedWithRequired{
1171 ReqString: scalar.String("here"),
1172 },
1173 },
1174 },
1175 }, {
1176 desc: "indirect required field in oneof",
1177 inputMessage: &pb2.IndirectRequired{},
1178 inputText: `{
1179 "oneofNested": {}
1180}`,
1181 wantMessage: &pb2.IndirectRequired{
1182 Union: &pb2.IndirectRequired_OneofNested{
1183 OneofNested: &pb2.NestedWithRequired{},
1184 },
1185 },
1186 wantErr: true,
1187 }, {
1188 desc: "indirect required field in oneof with AllowPartial",
1189 umo: jsonpb.UnmarshalOptions{AllowPartial: true},
1190 inputMessage: &pb2.IndirectRequired{},
1191 inputText: `{
1192 "oneofNested": {}
1193}`,
1194 wantMessage: &pb2.IndirectRequired{
1195 Union: &pb2.IndirectRequired_OneofNested{
1196 OneofNested: &pb2.NestedWithRequired{},
1197 },
1198 },
1199 }, {
Herbie Onge52379a2019-03-15 18:00:19 -07001200 desc: "extensions of non-repeated fields",
1201 inputMessage: &pb2.Extensions{},
1202 inputText: `{
1203 "optString": "non-extension field",
1204 "optBool": true,
1205 "optInt32": 42,
1206 "[pb2.opt_ext_bool]": true,
1207 "[pb2.opt_ext_nested]": {
1208 "optString": "nested in an extension",
Herbie Onge63c4c42019-03-22 22:20:22 -07001209 "optNested": {
1210 "optString": "another nested in an extension"
Herbie Onge52379a2019-03-15 18:00:19 -07001211 }
1212 },
1213 "[pb2.opt_ext_string]": "extension field",
1214 "[pb2.opt_ext_enum]": "TEN"
1215}`,
1216 wantMessage: func() proto.Message {
1217 m := &pb2.Extensions{
1218 OptString: scalar.String("non-extension field"),
1219 OptBool: scalar.Bool(true),
1220 OptInt32: scalar.Int32(42),
1221 }
1222 setExtension(m, pb2.E_OptExtBool, true)
1223 setExtension(m, pb2.E_OptExtString, "extension field")
1224 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
1225 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
1226 OptString: scalar.String("nested in an extension"),
1227 OptNested: &pb2.Nested{
1228 OptString: scalar.String("another nested in an extension"),
1229 },
1230 })
1231 return m
1232 }(),
1233 }, {
1234 desc: "extensions of repeated fields",
1235 inputMessage: &pb2.Extensions{},
1236 inputText: `{
1237 "[pb2.rpt_ext_enum]": ["TEN", 101, "ONE"],
1238 "[pb2.rpt_ext_fixed32]": [42, 47],
1239 "[pb2.rpt_ext_nested]": [
1240 {"optString": "one"},
1241 {"optString": "two"},
1242 {"optString": "three"}
1243 ]
1244}`,
1245 wantMessage: func() proto.Message {
1246 m := &pb2.Extensions{}
1247 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
1248 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
1249 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
1250 &pb2.Nested{OptString: scalar.String("one")},
1251 &pb2.Nested{OptString: scalar.String("two")},
1252 &pb2.Nested{OptString: scalar.String("three")},
1253 })
1254 return m
1255 }(),
1256 }, {
1257 desc: "extensions of non-repeated fields in another message",
1258 inputMessage: &pb2.Extensions{},
1259 inputText: `{
1260 "[pb2.ExtensionsContainer.opt_ext_bool]": true,
1261 "[pb2.ExtensionsContainer.opt_ext_enum]": "TEN",
1262 "[pb2.ExtensionsContainer.opt_ext_nested]": {
1263 "optString": "nested in an extension",
1264 "optNested": {
1265 "optString": "another nested in an extension"
1266 }
1267 },
1268 "[pb2.ExtensionsContainer.opt_ext_string]": "extension field"
1269}`,
1270 wantMessage: func() proto.Message {
1271 m := &pb2.Extensions{}
1272 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1273 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
1274 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
1275 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
1276 OptString: scalar.String("nested in an extension"),
1277 OptNested: &pb2.Nested{
1278 OptString: scalar.String("another nested in an extension"),
1279 },
1280 })
1281 return m
1282 }(),
1283 }, {
1284 desc: "extensions of repeated fields in another message",
1285 inputMessage: &pb2.Extensions{},
1286 inputText: `{
1287 "optString": "non-extension field",
1288 "optBool": true,
1289 "optInt32": 42,
1290 "[pb2.ExtensionsContainer.rpt_ext_nested]": [
1291 {"optString": "one"},
1292 {"optString": "two"},
1293 {"optString": "three"}
1294 ],
1295 "[pb2.ExtensionsContainer.rpt_ext_enum]": ["TEN", 101, "ONE"],
1296 "[pb2.ExtensionsContainer.rpt_ext_string]": ["hello", "world"]
1297}`,
1298 wantMessage: func() proto.Message {
1299 m := &pb2.Extensions{
1300 OptString: scalar.String("non-extension field"),
1301 OptBool: scalar.Bool(true),
1302 OptInt32: scalar.Int32(42),
1303 }
1304 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
1305 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1306 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
1307 &pb2.Nested{OptString: scalar.String("one")},
1308 &pb2.Nested{OptString: scalar.String("two")},
1309 &pb2.Nested{OptString: scalar.String("three")},
1310 })
1311 return m
1312 }(),
1313 }, {
1314 desc: "invalid extension field name",
1315 inputMessage: &pb2.Extensions{},
1316 inputText: `{ "[pb2.invalid_message_field]": true }`,
1317 wantErr: true,
1318 }, {
1319 desc: "MessageSet",
1320 inputMessage: &pb2.MessageSet{},
1321 inputText: `{
1322 "[pb2.MessageSetExtension]": {
1323 "optString": "a messageset extension"
1324 },
1325 "[pb2.MessageSetExtension.ext_nested]": {
1326 "optString": "just a regular extension"
1327 },
1328 "[pb2.MessageSetExtension.not_message_set_extension]": {
1329 "optString": "not a messageset extension"
1330 }
1331}`,
1332 wantMessage: func() proto.Message {
1333 m := &pb2.MessageSet{}
1334 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1335 OptString: scalar.String("a messageset extension"),
1336 })
1337 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1338 OptString: scalar.String("not a messageset extension"),
1339 })
1340 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1341 OptString: scalar.String("just a regular extension"),
1342 })
1343 return m
1344 }(),
1345 }, {
1346 desc: "extension field set to null",
1347 inputMessage: &pb2.Extensions{},
1348 inputText: `{
1349 "[pb2.ExtensionsContainer.opt_ext_bool]": null,
1350 "[pb2.ExtensionsContainer.opt_ext_nested]": null
1351}`,
1352 wantMessage: func() proto.Message {
1353 m := &pb2.Extensions{}
1354 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, nil)
1355 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, nil)
1356 return m
1357 }(),
1358 }, {
1359 desc: "extensions of repeated field contains null",
1360 inputMessage: &pb2.Extensions{},
1361 inputText: `{
1362 "[pb2.ExtensionsContainer.rpt_ext_nested]": [
1363 {"optString": "one"},
1364 null,
1365 {"optString": "three"}
1366 ],
1367}`,
1368 wantErr: true,
1369 }, {
1370 desc: "not real MessageSet 1",
1371 inputMessage: &pb2.FakeMessageSet{},
1372 inputText: `{
1373 "[pb2.FakeMessageSetExtension.message_set_extension]": {
1374 "optString": "not a messageset extension"
1375 }
1376}`,
1377 wantMessage: func() proto.Message {
1378 m := &pb2.FakeMessageSet{}
1379 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1380 OptString: scalar.String("not a messageset extension"),
1381 })
1382 return m
1383 }(),
1384 }, {
1385 desc: "not real MessageSet 2",
1386 inputMessage: &pb2.FakeMessageSet{},
1387 inputText: `{
1388 "[pb2.FakeMessageSetExtension]": {
1389 "optString": "not a messageset extension"
1390 }
1391}`,
1392 wantErr: true,
1393 }, {
1394 desc: "not real MessageSet 3",
1395 inputMessage: &pb2.MessageSet{},
1396 inputText: `{
1397 "[pb2.message_set_extension]": {
1398 "optString": "another not a messageset extension"
1399 }
1400}`,
1401 wantMessage: func() proto.Message {
1402 m := &pb2.MessageSet{}
1403 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1404 OptString: scalar.String("another not a messageset extension"),
1405 })
1406 return m
1407 }(),
Herbie Onge63c4c42019-03-22 22:20:22 -07001408 }, {
1409 desc: "Empty",
1410 inputMessage: &knownpb.Empty{},
1411 inputText: `{}`,
1412 wantMessage: &knownpb.Empty{},
1413 }, {
1414 desc: "Empty contains unknown",
1415 inputMessage: &knownpb.Empty{},
1416 inputText: `{"unknown": null}`,
1417 wantErr: true,
1418 }, {
1419 desc: "BoolValue false",
1420 inputMessage: &knownpb.BoolValue{},
1421 inputText: `false`,
1422 wantMessage: &knownpb.BoolValue{},
1423 }, {
1424 desc: "BoolValue true",
1425 inputMessage: &knownpb.BoolValue{},
1426 inputText: `true`,
1427 wantMessage: &knownpb.BoolValue{Value: true},
1428 }, {
1429 desc: "BoolValue invalid value",
1430 inputMessage: &knownpb.BoolValue{},
1431 inputText: `{}`,
1432 wantErr: true,
1433 }, {
1434 desc: "Int32Value",
1435 inputMessage: &knownpb.Int32Value{},
1436 inputText: `42`,
1437 wantMessage: &knownpb.Int32Value{Value: 42},
1438 }, {
1439 desc: "Int32Value in JSON string",
1440 inputMessage: &knownpb.Int32Value{},
1441 inputText: `"1.23e3"`,
1442 wantMessage: &knownpb.Int32Value{Value: 1230},
1443 }, {
1444 desc: "Int64Value",
1445 inputMessage: &knownpb.Int64Value{},
1446 inputText: `"42"`,
1447 wantMessage: &knownpb.Int64Value{Value: 42},
1448 }, {
1449 desc: "UInt32Value",
1450 inputMessage: &knownpb.UInt32Value{},
1451 inputText: `42`,
1452 wantMessage: &knownpb.UInt32Value{Value: 42},
1453 }, {
1454 desc: "UInt64Value",
1455 inputMessage: &knownpb.UInt64Value{},
1456 inputText: `"42"`,
1457 wantMessage: &knownpb.UInt64Value{Value: 42},
1458 }, {
1459 desc: "FloatValue",
1460 inputMessage: &knownpb.FloatValue{},
1461 inputText: `1.02`,
1462 wantMessage: &knownpb.FloatValue{Value: 1.02},
1463 }, {
1464 desc: "FloatValue exceeds max limit",
1465 inputMessage: &knownpb.FloatValue{},
1466 inputText: `1.23+40`,
1467 wantErr: true,
1468 }, {
1469 desc: "FloatValue Infinity",
1470 inputMessage: &knownpb.FloatValue{},
1471 inputText: `"-Infinity"`,
1472 wantMessage: &knownpb.FloatValue{Value: float32(math.Inf(-1))},
1473 }, {
1474 desc: "DoubleValue",
1475 inputMessage: &knownpb.DoubleValue{},
1476 inputText: `1.02`,
1477 wantMessage: &knownpb.DoubleValue{Value: 1.02},
1478 }, {
1479 desc: "DoubleValue Infinity",
1480 inputMessage: &knownpb.DoubleValue{},
1481 inputText: `"Infinity"`,
1482 wantMessage: &knownpb.DoubleValue{Value: math.Inf(+1)},
1483 }, {
1484 desc: "StringValue empty",
1485 inputMessage: &knownpb.StringValue{},
1486 inputText: `""`,
1487 wantMessage: &knownpb.StringValue{},
1488 }, {
1489 desc: "StringValue",
1490 inputMessage: &knownpb.StringValue{},
1491 inputText: `"谷歌"`,
1492 wantMessage: &knownpb.StringValue{Value: "谷歌"},
1493 }, {
1494 desc: "StringValue with invalid UTF8 error",
1495 inputMessage: &knownpb.StringValue{},
1496 inputText: "\"abc\xff\"",
1497 wantMessage: &knownpb.StringValue{Value: "abc\xff"},
1498 wantErr: true,
1499 }, {
1500 desc: "StringValue field with invalid UTF8 error",
1501 inputMessage: &pb2.KnownTypes{},
1502 inputText: "{\n \"optString\": \"abc\xff\"\n}",
1503 wantMessage: &pb2.KnownTypes{
1504 OptString: &knownpb.StringValue{Value: "abc\xff"},
1505 },
1506 wantErr: true,
1507 }, {
Herbie Ong300b9fe2019-03-29 15:42:20 -07001508 desc: "NullValue field with JSON null",
1509 inputMessage: &pb2.KnownTypes{},
1510 inputText: `{
1511 "optNull": null
1512}`,
1513 wantMessage: &pb2.KnownTypes{OptNull: new(knownpb.NullValue)},
1514 }, {
1515 desc: "NullValue field with string",
1516 inputMessage: &pb2.KnownTypes{},
1517 inputText: `{
1518 "optNull": "NULL_VALUE"
1519}`,
1520 wantMessage: &pb2.KnownTypes{OptNull: new(knownpb.NullValue)},
1521 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -07001522 desc: "BytesValue",
1523 inputMessage: &knownpb.BytesValue{},
1524 inputText: `"aGVsbG8="`,
1525 wantMessage: &knownpb.BytesValue{Value: []byte("hello")},
1526 }, {
1527 desc: "Value null",
1528 inputMessage: &knownpb.Value{},
1529 inputText: `null`,
1530 wantMessage: &knownpb.Value{Kind: &knownpb.Value_NullValue{}},
1531 }, {
1532 desc: "Value field null",
1533 inputMessage: &pb2.KnownTypes{},
1534 inputText: `{
1535 "optValue": null
1536}`,
1537 wantMessage: &pb2.KnownTypes{
1538 OptValue: &knownpb.Value{Kind: &knownpb.Value_NullValue{}},
1539 },
1540 }, {
1541 desc: "Value bool",
1542 inputMessage: &knownpb.Value{},
1543 inputText: `false`,
1544 wantMessage: &knownpb.Value{Kind: &knownpb.Value_BoolValue{}},
1545 }, {
1546 desc: "Value field bool",
1547 inputMessage: &pb2.KnownTypes{},
1548 inputText: `{
1549 "optValue": true
1550}`,
1551 wantMessage: &pb2.KnownTypes{
1552 OptValue: &knownpb.Value{Kind: &knownpb.Value_BoolValue{true}},
1553 },
1554 }, {
1555 desc: "Value number",
1556 inputMessage: &knownpb.Value{},
1557 inputText: `1.02`,
1558 wantMessage: &knownpb.Value{Kind: &knownpb.Value_NumberValue{1.02}},
1559 }, {
1560 desc: "Value field number",
1561 inputMessage: &pb2.KnownTypes{},
1562 inputText: `{
1563 "optValue": 1.02
1564}`,
1565 wantMessage: &pb2.KnownTypes{
1566 OptValue: &knownpb.Value{Kind: &knownpb.Value_NumberValue{1.02}},
1567 },
1568 }, {
1569 desc: "Value string",
1570 inputMessage: &knownpb.Value{},
1571 inputText: `"hello"`,
1572 wantMessage: &knownpb.Value{Kind: &knownpb.Value_StringValue{"hello"}},
1573 }, {
1574 desc: "Value string with invalid UTF8",
1575 inputMessage: &knownpb.Value{},
1576 inputText: "\"\xff\"",
1577 wantMessage: &knownpb.Value{Kind: &knownpb.Value_StringValue{"\xff"}},
1578 wantErr: true,
1579 }, {
1580 desc: "Value field string",
1581 inputMessage: &pb2.KnownTypes{},
1582 inputText: `{
1583 "optValue": "NaN"
1584}`,
1585 wantMessage: &pb2.KnownTypes{
1586 OptValue: &knownpb.Value{Kind: &knownpb.Value_StringValue{"NaN"}},
1587 },
1588 }, {
1589 desc: "Value field string with invalid UTF8",
1590 inputMessage: &pb2.KnownTypes{},
1591 inputText: `{
1592 "optValue": "` + "\xff" + `"
1593}`,
1594 wantMessage: &pb2.KnownTypes{
1595 OptValue: &knownpb.Value{Kind: &knownpb.Value_StringValue{"\xff"}},
1596 },
1597 wantErr: true,
1598 }, {
1599 desc: "Value empty struct",
1600 inputMessage: &knownpb.Value{},
1601 inputText: `{}`,
1602 wantMessage: &knownpb.Value{
1603 Kind: &knownpb.Value_StructValue{
1604 &knownpb.Struct{Fields: map[string]*knownpb.Value{}},
1605 },
1606 },
1607 }, {
1608 desc: "Value struct",
1609 inputMessage: &knownpb.Value{},
1610 inputText: `{
1611 "string": "hello",
1612 "number": 123,
1613 "null": null,
1614 "bool": false,
1615 "struct": {
1616 "string": "world"
1617 },
1618 "list": []
1619}`,
1620 wantMessage: &knownpb.Value{
1621 Kind: &knownpb.Value_StructValue{
1622 &knownpb.Struct{
1623 Fields: map[string]*knownpb.Value{
1624 "string": {Kind: &knownpb.Value_StringValue{"hello"}},
1625 "number": {Kind: &knownpb.Value_NumberValue{123}},
1626 "null": {Kind: &knownpb.Value_NullValue{}},
1627 "bool": {Kind: &knownpb.Value_BoolValue{false}},
1628 "struct": {
1629 Kind: &knownpb.Value_StructValue{
1630 &knownpb.Struct{
1631 Fields: map[string]*knownpb.Value{
1632 "string": {Kind: &knownpb.Value_StringValue{"world"}},
1633 },
1634 },
1635 },
1636 },
1637 "list": {
1638 Kind: &knownpb.Value_ListValue{&knownpb.ListValue{}},
1639 },
1640 },
1641 },
1642 },
1643 },
1644 }, {
1645 desc: "Value struct with invalid UTF8 string",
1646 inputMessage: &knownpb.Value{},
1647 inputText: "{\"string\": \"abc\xff\"}",
1648 wantMessage: &knownpb.Value{
1649 Kind: &knownpb.Value_StructValue{
1650 &knownpb.Struct{
1651 Fields: map[string]*knownpb.Value{
1652 "string": {Kind: &knownpb.Value_StringValue{"abc\xff"}},
1653 },
1654 },
1655 },
1656 },
1657 wantErr: true,
1658 }, {
1659 desc: "Value field struct",
1660 inputMessage: &pb2.KnownTypes{},
1661 inputText: `{
1662 "optValue": {
1663 "string": "hello"
1664 }
1665}`,
1666 wantMessage: &pb2.KnownTypes{
1667 OptValue: &knownpb.Value{
1668 Kind: &knownpb.Value_StructValue{
1669 &knownpb.Struct{
1670 Fields: map[string]*knownpb.Value{
1671 "string": {Kind: &knownpb.Value_StringValue{"hello"}},
1672 },
1673 },
1674 },
1675 },
1676 },
1677 }, {
1678 desc: "Value empty list",
1679 inputMessage: &knownpb.Value{},
1680 inputText: `[]`,
1681 wantMessage: &knownpb.Value{
1682 Kind: &knownpb.Value_ListValue{
1683 &knownpb.ListValue{Values: []*knownpb.Value{}},
1684 },
1685 },
1686 }, {
1687 desc: "Value list",
1688 inputMessage: &knownpb.Value{},
1689 inputText: `[
1690 "string",
1691 123,
1692 null,
1693 true,
1694 {},
1695 [
1696 "string",
1697 1.23,
1698 null,
1699 false
1700 ]
1701]`,
1702 wantMessage: &knownpb.Value{
1703 Kind: &knownpb.Value_ListValue{
1704 &knownpb.ListValue{
1705 Values: []*knownpb.Value{
1706 {Kind: &knownpb.Value_StringValue{"string"}},
1707 {Kind: &knownpb.Value_NumberValue{123}},
1708 {Kind: &knownpb.Value_NullValue{}},
1709 {Kind: &knownpb.Value_BoolValue{true}},
1710 {Kind: &knownpb.Value_StructValue{&knownpb.Struct{}}},
1711 {
1712 Kind: &knownpb.Value_ListValue{
1713 &knownpb.ListValue{
1714 Values: []*knownpb.Value{
1715 {Kind: &knownpb.Value_StringValue{"string"}},
1716 {Kind: &knownpb.Value_NumberValue{1.23}},
1717 {Kind: &knownpb.Value_NullValue{}},
1718 {Kind: &knownpb.Value_BoolValue{false}},
1719 },
1720 },
1721 },
1722 },
1723 },
1724 },
1725 },
1726 },
1727 }, {
1728 desc: "Value list with invalid UTF8 string",
1729 inputMessage: &knownpb.Value{},
1730 inputText: "[\"abc\xff\"]",
1731 wantMessage: &knownpb.Value{
1732 Kind: &knownpb.Value_ListValue{
1733 &knownpb.ListValue{
1734 Values: []*knownpb.Value{
1735 {Kind: &knownpb.Value_StringValue{"abc\xff"}},
1736 },
1737 },
1738 },
1739 },
1740 wantErr: true,
1741 }, {
1742 desc: "Value field list with invalid UTF8 string",
1743 inputMessage: &pb2.KnownTypes{},
1744 inputText: `{
1745 "optValue": [ "` + "abc\xff" + `"]
1746}`,
1747 wantMessage: &pb2.KnownTypes{
1748 OptValue: &knownpb.Value{
1749 Kind: &knownpb.Value_ListValue{
1750 &knownpb.ListValue{
1751 Values: []*knownpb.Value{
1752 {Kind: &knownpb.Value_StringValue{"abc\xff"}},
1753 },
1754 },
1755 },
1756 },
1757 },
1758 wantErr: true,
1759 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001760 desc: "Duration empty string",
1761 inputMessage: &knownpb.Duration{},
1762 inputText: `""`,
1763 wantErr: true,
1764 }, {
1765 desc: "Duration with secs",
1766 inputMessage: &knownpb.Duration{},
1767 inputText: `"3s"`,
1768 wantMessage: &knownpb.Duration{Seconds: 3},
1769 }, {
1770 desc: "Duration with escaped unicode",
1771 inputMessage: &knownpb.Duration{},
1772 inputText: `"\u0033s"`,
1773 wantMessage: &knownpb.Duration{Seconds: 3},
1774 }, {
1775 desc: "Duration with -secs",
1776 inputMessage: &knownpb.Duration{},
1777 inputText: `"-3s"`,
1778 wantMessage: &knownpb.Duration{Seconds: -3},
1779 }, {
Herbie Ong17523eb2019-03-29 17:46:57 -07001780 desc: "Duration with plus sign",
1781 inputMessage: &knownpb.Duration{},
1782 inputText: `"+3s"`,
1783 wantMessage: &knownpb.Duration{Seconds: 3},
1784 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001785 desc: "Duration with nanos",
1786 inputMessage: &knownpb.Duration{},
1787 inputText: `"0.001s"`,
1788 wantMessage: &knownpb.Duration{Nanos: 1e6},
1789 }, {
1790 desc: "Duration with -nanos",
1791 inputMessage: &knownpb.Duration{},
1792 inputText: `"-0.001s"`,
1793 wantMessage: &knownpb.Duration{Nanos: -1e6},
1794 }, {
Herbie Ong17523eb2019-03-29 17:46:57 -07001795 desc: "Duration with -nanos",
1796 inputMessage: &knownpb.Duration{},
1797 inputText: `"-.001s"`,
1798 wantMessage: &knownpb.Duration{Nanos: -1e6},
1799 }, {
1800 desc: "Duration with +nanos",
1801 inputMessage: &knownpb.Duration{},
1802 inputText: `"+.001s"`,
1803 wantMessage: &knownpb.Duration{Nanos: 1e6},
1804 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001805 desc: "Duration with -secs -nanos",
1806 inputMessage: &knownpb.Duration{},
1807 inputText: `"-123.000000450s"`,
1808 wantMessage: &knownpb.Duration{Seconds: -123, Nanos: -450},
1809 }, {
1810 desc: "Duration with large secs",
1811 inputMessage: &knownpb.Duration{},
1812 inputText: `"10000000000.000000001s"`,
1813 wantMessage: &knownpb.Duration{Seconds: 1e10, Nanos: 1},
1814 }, {
1815 desc: "Duration with decimal without fractional",
1816 inputMessage: &knownpb.Duration{},
1817 inputText: `"3.s"`,
1818 wantMessage: &knownpb.Duration{Seconds: 3},
1819 }, {
1820 desc: "Duration with decimal without integer",
1821 inputMessage: &knownpb.Duration{},
1822 inputText: `"0.5s"`,
1823 wantMessage: &knownpb.Duration{Nanos: 5e8},
1824 }, {
1825 desc: "Duration with +secs out of range",
1826 inputMessage: &knownpb.Duration{},
1827 inputText: `"315576000001s"`,
1828 wantErr: true,
1829 }, {
1830 desc: "Duration with -secs out of range",
1831 inputMessage: &knownpb.Duration{},
1832 inputText: `"-315576000001s"`,
1833 wantErr: true,
1834 }, {
1835 desc: "Duration with nanos beyond 9 digits",
1836 inputMessage: &knownpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001837 inputText: `"0.1000000000s"`,
Herbie Ongc4450372019-03-27 09:59:51 -07001838 wantErr: true,
1839 }, {
1840 desc: "Duration without suffix s",
1841 inputMessage: &knownpb.Duration{},
1842 inputText: `"123"`,
1843 wantErr: true,
1844 }, {
Herbie Ong17523eb2019-03-29 17:46:57 -07001845 desc: "Duration invalid signed fraction",
1846 inputMessage: &knownpb.Duration{},
1847 inputText: `"123.+123s"`,
1848 wantErr: true,
1849 }, {
1850 desc: "Duration invalid multiple .",
1851 inputMessage: &knownpb.Duration{},
1852 inputText: `"123.123.s"`,
1853 wantErr: true,
1854 }, {
1855 desc: "Duration invalid integer",
1856 inputMessage: &knownpb.Duration{},
1857 inputText: `"01s"`,
1858 wantErr: true,
1859 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001860 desc: "Timestamp zero",
1861 inputMessage: &knownpb.Timestamp{},
1862 inputText: `"1970-01-01T00:00:00Z"`,
1863 wantMessage: &knownpb.Timestamp{},
1864 }, {
1865 desc: "Timestamp with tz adjustment",
1866 inputMessage: &knownpb.Timestamp{},
1867 inputText: `"1970-01-01T00:00:00+01:00"`,
1868 wantMessage: &knownpb.Timestamp{Seconds: -3600},
1869 }, {
1870 desc: "Timestamp UTC",
1871 inputMessage: &knownpb.Timestamp{},
1872 inputText: `"2019-03-19T23:03:21Z"`,
1873 wantMessage: &knownpb.Timestamp{Seconds: 1553036601},
1874 }, {
1875 desc: "Timestamp with escaped unicode",
1876 inputMessage: &knownpb.Timestamp{},
1877 inputText: `"2019-0\u0033-19T23:03:21Z"`,
1878 wantMessage: &knownpb.Timestamp{Seconds: 1553036601},
1879 }, {
1880 desc: "Timestamp with nanos",
1881 inputMessage: &knownpb.Timestamp{},
1882 inputText: `"2019-03-19T23:03:21.000000001Z"`,
1883 wantMessage: &knownpb.Timestamp{Seconds: 1553036601, Nanos: 1},
1884 }, {
1885 desc: "Timestamp upper limit",
1886 inputMessage: &knownpb.Timestamp{},
1887 inputText: `"9999-12-31T23:59:59.999999999Z"`,
1888 wantMessage: &knownpb.Timestamp{Seconds: 253402300799, Nanos: 999999999},
1889 }, {
1890 desc: "Timestamp above upper limit",
1891 inputMessage: &knownpb.Timestamp{},
1892 inputText: `"9999-12-31T23:59:59-01:00"`,
1893 wantErr: true,
1894 }, {
1895 desc: "Timestamp lower limit",
1896 inputMessage: &knownpb.Timestamp{},
1897 inputText: `"0001-01-01T00:00:00Z"`,
1898 wantMessage: &knownpb.Timestamp{Seconds: -62135596800},
1899 }, {
1900 desc: "Timestamp below lower limit",
1901 inputMessage: &knownpb.Timestamp{},
1902 inputText: `"0001-01-01T00:00:00+01:00"`,
1903 wantErr: true,
1904 }, {
1905 desc: "Timestamp with nanos beyond 9 digits",
1906 inputMessage: &knownpb.Timestamp{},
1907 inputText: `"1970-01-01T00:00:00.0000000001Z"`,
1908 wantErr: true,
1909 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -07001910 desc: "FieldMask empty",
1911 inputMessage: &knownpb.FieldMask{},
1912 inputText: `""`,
1913 wantMessage: &knownpb.FieldMask{Paths: []string{}},
1914 }, {
1915 desc: "FieldMask",
1916 inputMessage: &knownpb.FieldMask{},
1917 inputText: `"foo,fooBar , foo.barQux ,Foo"`,
1918 wantMessage: &knownpb.FieldMask{
1919 Paths: []string{
1920 "foo",
1921 "foo_bar",
1922 "foo.bar_qux",
1923 "_foo",
1924 },
1925 },
1926 }, {
1927 desc: "FieldMask field",
1928 inputMessage: &pb2.KnownTypes{},
1929 inputText: `{
1930 "optFieldmask": "foo, qux.fooBar"
1931}`,
1932 wantMessage: &pb2.KnownTypes{
1933 OptFieldmask: &knownpb.FieldMask{
1934 Paths: []string{
1935 "foo",
1936 "qux.foo_bar",
1937 },
1938 },
1939 },
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001940 }, {
1941 desc: "Any empty",
1942 inputMessage: &knownpb.Any{},
1943 inputText: `{}`,
1944 wantMessage: &knownpb.Any{},
1945 }, {
1946 desc: "Any with non-custom message",
1947 umo: jsonpb.UnmarshalOptions{
1948 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
1949 },
1950 inputMessage: &knownpb.Any{},
1951 inputText: `{
1952 "@type": "foo/pb2.Nested",
1953 "optString": "embedded inside Any",
1954 "optNested": {
1955 "optString": "inception"
1956 }
1957}`,
1958 wantMessage: func() proto.Message {
1959 m := &pb2.Nested{
1960 OptString: scalar.String("embedded inside Any"),
1961 OptNested: &pb2.Nested{
1962 OptString: scalar.String("inception"),
1963 },
1964 }
1965 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1966 if err != nil {
1967 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1968 }
1969 return &knownpb.Any{
1970 TypeUrl: "foo/pb2.Nested",
1971 Value: b,
1972 }
1973 }(),
1974 }, {
1975 desc: "Any with empty embedded message",
1976 umo: jsonpb.UnmarshalOptions{
1977 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
1978 },
1979 inputMessage: &knownpb.Any{},
1980 inputText: `{
1981 "@type": "foo/pb2.Nested"
1982}`,
1983 wantMessage: &knownpb.Any{TypeUrl: "foo/pb2.Nested"},
1984 }, {
1985 desc: "Any without registered type",
1986 umo: jsonpb.UnmarshalOptions{Resolver: preg.NewTypes()},
1987 inputMessage: &knownpb.Any{},
1988 inputText: `{
1989 "@type": "foo/pb2.Nested"
1990}`,
1991 wantErr: true,
1992 }, {
1993 desc: "Any with missing required error",
1994 umo: jsonpb.UnmarshalOptions{
1995 Resolver: preg.NewTypes((&pb2.PartialRequired{}).ProtoReflect().Type()),
1996 },
1997 inputMessage: &knownpb.Any{},
1998 inputText: `{
1999 "@type": "pb2.PartialRequired",
2000 "optString": "embedded inside Any"
2001}`,
2002 wantMessage: func() proto.Message {
2003 m := &pb2.PartialRequired{
2004 OptString: scalar.String("embedded inside Any"),
2005 }
2006 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2007 // TODO: Marshal may fail due to required field not set at some
2008 // point. Need to ignore required not set error here.
2009 if err != nil {
2010 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2011 }
2012 return &knownpb.Any{
2013 TypeUrl: string(m.ProtoReflect().Type().FullName()),
2014 Value: b,
2015 }
2016 }(),
2017 wantErr: true,
2018 }, {
2019 desc: "Any with partial required and AllowPartial",
2020 umo: jsonpb.UnmarshalOptions{
2021 AllowPartial: true,
2022 Resolver: preg.NewTypes((&pb2.PartialRequired{}).ProtoReflect().Type()),
2023 },
2024 inputMessage: &knownpb.Any{},
2025 inputText: `{
2026 "@type": "pb2.PartialRequired",
2027 "optString": "embedded inside Any"
2028}`,
2029 wantMessage: func() proto.Message {
2030 m := &pb2.PartialRequired{
2031 OptString: scalar.String("embedded inside Any"),
2032 }
2033 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2034 // TODO: Marshal may fail due to required field not set at some
2035 // point. Need to ignore required not set error here.
2036 if err != nil {
2037 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2038 }
2039 return &knownpb.Any{
2040 TypeUrl: string(m.ProtoReflect().Type().FullName()),
2041 Value: b,
2042 }
2043 }(),
2044 }, {
2045 desc: "Any with invalid UTF8",
2046 umo: jsonpb.UnmarshalOptions{
2047 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
2048 },
2049 inputMessage: &knownpb.Any{},
2050 inputText: `{
2051 "optString": "` + "abc\xff" + `",
2052 "@type": "foo/pb2.Nested"
2053}`,
2054 wantMessage: func() proto.Message {
2055 m := &pb2.Nested{
2056 OptString: scalar.String("abc\xff"),
2057 }
2058 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2059 if err != nil {
2060 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2061 }
2062 return &knownpb.Any{
2063 TypeUrl: "foo/pb2.Nested",
2064 Value: b,
2065 }
2066 }(),
2067 wantErr: true,
2068 }, {
2069 desc: "Any with BoolValue",
2070 umo: jsonpb.UnmarshalOptions{
2071 Resolver: preg.NewTypes((&knownpb.BoolValue{}).ProtoReflect().Type()),
2072 },
2073 inputMessage: &knownpb.Any{},
2074 inputText: `{
2075 "@type": "type.googleapis.com/google.protobuf.BoolValue",
2076 "value": true
2077}`,
2078 wantMessage: func() proto.Message {
2079 m := &knownpb.BoolValue{Value: true}
2080 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2081 if err != nil {
2082 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2083 }
2084 return &knownpb.Any{
2085 TypeUrl: "type.googleapis.com/google.protobuf.BoolValue",
2086 Value: b,
2087 }
2088 }(),
2089 }, {
2090 desc: "Any with Empty",
2091 umo: jsonpb.UnmarshalOptions{
2092 Resolver: preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
2093 },
2094 inputMessage: &knownpb.Any{},
2095 inputText: `{
2096 "value": {},
2097 "@type": "type.googleapis.com/google.protobuf.Empty"
2098}`,
2099 wantMessage: func() proto.Message {
2100 m := &knownpb.Empty{}
2101 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2102 if err != nil {
2103 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2104 }
2105 return &knownpb.Any{
2106 TypeUrl: "type.googleapis.com/google.protobuf.Empty",
2107 Value: b,
2108 }
2109 }(),
2110 }, {
2111 desc: "Any with missing Empty",
2112 umo: jsonpb.UnmarshalOptions{
2113 Resolver: preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
2114 },
2115 inputMessage: &knownpb.Any{},
2116 inputText: `{
2117 "@type": "type.googleapis.com/google.protobuf.Empty"
2118}`,
2119 wantErr: true,
2120 }, {
2121 desc: "Any with StringValue containing invalid UTF8",
2122 umo: jsonpb.UnmarshalOptions{
2123 Resolver: preg.NewTypes((&knownpb.StringValue{}).ProtoReflect().Type()),
2124 },
2125 inputMessage: &knownpb.Any{},
2126 inputText: `{
2127 "@type": "google.protobuf.StringValue",
2128 "value": "` + "abc\xff" + `"
2129}`,
2130 wantMessage: func() proto.Message {
2131 m := &knownpb.StringValue{Value: "abc\xff"}
2132 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2133 if err != nil {
2134 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2135 }
2136 return &knownpb.Any{
2137 TypeUrl: "google.protobuf.StringValue",
2138 Value: b,
2139 }
2140 }(),
2141 wantErr: true,
2142 }, {
2143 desc: "Any with Int64Value",
2144 umo: jsonpb.UnmarshalOptions{
2145 Resolver: preg.NewTypes((&knownpb.Int64Value{}).ProtoReflect().Type()),
2146 },
2147 inputMessage: &knownpb.Any{},
2148 inputText: `{
2149 "@type": "google.protobuf.Int64Value",
2150 "value": "42"
2151}`,
2152 wantMessage: func() proto.Message {
2153 m := &knownpb.Int64Value{Value: 42}
2154 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2155 if err != nil {
2156 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2157 }
2158 return &knownpb.Any{
2159 TypeUrl: "google.protobuf.Int64Value",
2160 Value: b,
2161 }
2162 }(),
2163 }, {
2164 desc: "Any with invalid Int64Value",
2165 umo: jsonpb.UnmarshalOptions{
2166 Resolver: preg.NewTypes((&knownpb.Int64Value{}).ProtoReflect().Type()),
2167 },
2168 inputMessage: &knownpb.Any{},
2169 inputText: `{
2170 "@type": "google.protobuf.Int64Value",
2171 "value": "forty-two"
2172}`,
2173 wantErr: true,
2174 }, {
2175 desc: "Any with invalid UInt64Value",
2176 umo: jsonpb.UnmarshalOptions{
2177 Resolver: preg.NewTypes((&knownpb.UInt64Value{}).ProtoReflect().Type()),
2178 },
2179 inputMessage: &knownpb.Any{},
2180 inputText: `{
2181 "@type": "google.protobuf.UInt64Value",
2182 "value": -42
2183}`,
2184 wantErr: true,
2185 }, {
2186 desc: "Any with Duration",
2187 umo: jsonpb.UnmarshalOptions{
2188 Resolver: preg.NewTypes((&knownpb.Duration{}).ProtoReflect().Type()),
2189 },
2190 inputMessage: &knownpb.Any{},
2191 inputText: `{
2192 "@type": "type.googleapis.com/google.protobuf.Duration",
2193 "value": "0s"
2194}`,
2195 wantMessage: func() proto.Message {
2196 m := &knownpb.Duration{}
2197 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2198 if err != nil {
2199 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2200 }
2201 return &knownpb.Any{
2202 TypeUrl: "type.googleapis.com/google.protobuf.Duration",
2203 Value: b,
2204 }
2205 }(),
2206 }, {
2207 desc: "Any with Value of StringValue",
2208 umo: jsonpb.UnmarshalOptions{
2209 Resolver: preg.NewTypes((&knownpb.Value{}).ProtoReflect().Type()),
2210 },
2211 inputMessage: &knownpb.Any{},
2212 inputText: `{
2213 "@type": "google.protobuf.Value",
2214 "value": "` + "abc\xff" + `"
2215}`,
2216 wantMessage: func() proto.Message {
2217 m := &knownpb.Value{Kind: &knownpb.Value_StringValue{"abc\xff"}}
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.Value",
2224 Value: b,
2225 }
2226 }(),
2227 wantErr: true,
2228 }, {
2229 desc: "Any with Value of NullValue",
2230 umo: jsonpb.UnmarshalOptions{
2231 Resolver: preg.NewTypes((&knownpb.Value{}).ProtoReflect().Type()),
2232 },
2233 inputMessage: &knownpb.Any{},
2234 inputText: `{
2235 "@type": "google.protobuf.Value",
2236 "value": null
2237}`,
2238 wantMessage: func() proto.Message {
2239 m := &knownpb.Value{Kind: &knownpb.Value_NullValue{}}
2240 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2241 if err != nil {
2242 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2243 }
2244 return &knownpb.Any{
2245 TypeUrl: "google.protobuf.Value",
2246 Value: b,
2247 }
2248 }(),
2249 }, {
2250 desc: "Any with Struct",
2251 umo: jsonpb.UnmarshalOptions{
2252 Resolver: preg.NewTypes(
2253 (&knownpb.Struct{}).ProtoReflect().Type(),
2254 (&knownpb.Value{}).ProtoReflect().Type(),
2255 (&knownpb.BoolValue{}).ProtoReflect().Type(),
2256 knownpb.NullValue_NULL_VALUE.Type(),
2257 (&knownpb.StringValue{}).ProtoReflect().Type(),
2258 ),
2259 },
2260 inputMessage: &knownpb.Any{},
2261 inputText: `{
2262 "@type": "google.protobuf.Struct",
2263 "value": {
2264 "bool": true,
2265 "null": null,
2266 "string": "hello",
2267 "struct": {
2268 "string": "world"
2269 }
2270 }
2271}`,
2272 wantMessage: func() proto.Message {
2273 m := &knownpb.Struct{
2274 Fields: map[string]*knownpb.Value{
2275 "bool": {Kind: &knownpb.Value_BoolValue{true}},
2276 "null": {Kind: &knownpb.Value_NullValue{}},
2277 "string": {Kind: &knownpb.Value_StringValue{"hello"}},
2278 "struct": {
2279 Kind: &knownpb.Value_StructValue{
2280 &knownpb.Struct{
2281 Fields: map[string]*knownpb.Value{
2282 "string": {Kind: &knownpb.Value_StringValue{"world"}},
2283 },
2284 },
2285 },
2286 },
2287 },
2288 }
2289 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2290 if err != nil {
2291 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2292 }
2293 return &knownpb.Any{
2294 TypeUrl: "google.protobuf.Struct",
2295 Value: b,
2296 }
2297 }(),
2298 }, {
2299 desc: "Any with missing @type",
2300 umo: jsonpb.UnmarshalOptions{},
2301 inputMessage: &knownpb.Any{},
2302 inputText: `{
2303 "value": {}
2304}`,
2305 wantErr: true,
2306 }, {
2307 desc: "Any with empty @type",
2308 inputMessage: &knownpb.Any{},
2309 inputText: `{
2310 "@type": ""
2311}`,
2312 wantErr: true,
2313 }, {
2314 desc: "Any with duplicate @type",
2315 umo: jsonpb.UnmarshalOptions{
2316 Resolver: preg.NewTypes(
2317 (&pb2.Nested{}).ProtoReflect().Type(),
2318 (&knownpb.StringValue{}).ProtoReflect().Type(),
2319 ),
2320 },
2321 inputMessage: &knownpb.Any{},
2322 inputText: `{
2323 "@type": "google.protobuf.StringValue",
2324 "value": "hello",
2325 "@type": "pb2.Nested"
2326}`,
2327 wantErr: true,
2328 }, {
2329 desc: "Any with duplicate value",
2330 umo: jsonpb.UnmarshalOptions{
2331 Resolver: preg.NewTypes((&knownpb.StringValue{}).ProtoReflect().Type()),
2332 },
2333 inputMessage: &knownpb.Any{},
2334 inputText: `{
2335 "@type": "google.protobuf.StringValue",
2336 "value": "hello",
2337 "value": "world"
2338}`,
2339 wantErr: true,
2340 }, {
2341 desc: "Any with unknown field",
2342 umo: jsonpb.UnmarshalOptions{
2343 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
2344 },
2345 inputMessage: &knownpb.Any{},
2346 inputText: `{
2347 "@type": "pb2.Nested",
2348 "optString": "hello",
2349 "unknown": "world"
2350}`,
2351 wantErr: true,
2352 }, {
2353 desc: "Any with embedded type containing Any",
2354 umo: jsonpb.UnmarshalOptions{
2355 Resolver: preg.NewTypes(
2356 (&pb2.KnownTypes{}).ProtoReflect().Type(),
2357 (&knownpb.Any{}).ProtoReflect().Type(),
2358 (&knownpb.StringValue{}).ProtoReflect().Type(),
2359 ),
2360 },
2361 inputMessage: &knownpb.Any{},
2362 inputText: `{
2363 "@type": "pb2.KnownTypes",
2364 "optAny": {
2365 "@type": "google.protobuf.StringValue",
2366 "value": "` + "abc\xff" + `"
2367 }
2368}`,
2369 wantMessage: func() proto.Message {
2370 m1 := &knownpb.StringValue{Value: "abc\xff"}
2371 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
2372 if err != nil {
2373 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2374 }
2375 m2 := &knownpb.Any{
2376 TypeUrl: "google.protobuf.StringValue",
2377 Value: b,
2378 }
2379 m3 := &pb2.KnownTypes{OptAny: m2}
2380 b, err = proto.MarshalOptions{Deterministic: true}.Marshal(m3)
2381 if err != nil {
2382 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2383 }
2384 return &knownpb.Any{
2385 TypeUrl: "pb2.KnownTypes",
2386 Value: b,
2387 }
2388 }(),
2389 wantErr: true,
2390 }, {
2391 desc: "well known types as field values",
2392 umo: jsonpb.UnmarshalOptions{
2393 Resolver: preg.NewTypes((&knownpb.Empty{}).ProtoReflect().Type()),
2394 },
2395 inputMessage: &pb2.KnownTypes{},
2396 inputText: `{
2397 "optBool": false,
2398 "optInt32": 42,
2399 "optInt64": "42",
2400 "optUint32": 42,
2401 "optUint64": "42",
2402 "optFloat": 1.23,
2403 "optDouble": 3.1415,
2404 "optString": "hello",
2405 "optBytes": "aGVsbG8=",
2406 "optDuration": "123s",
2407 "optTimestamp": "2019-03-19T23:03:21Z",
2408 "optStruct": {
2409 "string": "hello"
2410 },
2411 "optList": [
2412 null,
2413 "",
2414 {},
2415 []
2416 ],
2417 "optValue": "world",
2418 "optEmpty": {},
2419 "optAny": {
2420 "@type": "google.protobuf.Empty",
2421 "value": {}
2422 },
2423 "optFieldmask": "fooBar,barFoo"
2424}`,
2425 wantMessage: &pb2.KnownTypes{
2426 OptBool: &knownpb.BoolValue{Value: false},
2427 OptInt32: &knownpb.Int32Value{Value: 42},
2428 OptInt64: &knownpb.Int64Value{Value: 42},
2429 OptUint32: &knownpb.UInt32Value{Value: 42},
2430 OptUint64: &knownpb.UInt64Value{Value: 42},
2431 OptFloat: &knownpb.FloatValue{Value: 1.23},
2432 OptDouble: &knownpb.DoubleValue{Value: 3.1415},
2433 OptString: &knownpb.StringValue{Value: "hello"},
2434 OptBytes: &knownpb.BytesValue{Value: []byte("hello")},
2435 OptDuration: &knownpb.Duration{Seconds: 123},
2436 OptTimestamp: &knownpb.Timestamp{Seconds: 1553036601},
2437 OptStruct: &knownpb.Struct{
2438 Fields: map[string]*knownpb.Value{
2439 "string": {Kind: &knownpb.Value_StringValue{"hello"}},
2440 },
2441 },
2442 OptList: &knownpb.ListValue{
2443 Values: []*knownpb.Value{
2444 {Kind: &knownpb.Value_NullValue{}},
2445 {Kind: &knownpb.Value_StringValue{}},
2446 {
2447 Kind: &knownpb.Value_StructValue{
2448 &knownpb.Struct{Fields: map[string]*knownpb.Value{}},
2449 },
2450 },
2451 {
2452 Kind: &knownpb.Value_ListValue{
2453 &knownpb.ListValue{Values: []*knownpb.Value{}},
2454 },
2455 },
2456 },
2457 },
2458 OptValue: &knownpb.Value{
2459 Kind: &knownpb.Value_StringValue{"world"},
2460 },
2461 OptEmpty: &knownpb.Empty{},
2462 OptAny: &knownpb.Any{
2463 TypeUrl: "google.protobuf.Empty",
2464 },
2465 OptFieldmask: &knownpb.FieldMask{
2466 Paths: []string{"foo_bar", "bar_foo"},
2467 },
2468 },
Herbie Ongc96a79d2019-03-08 10:49:17 -08002469 }}
2470
2471 for _, tt := range tests {
2472 tt := tt
2473 t.Run(tt.desc, func(t *testing.T) {
2474 err := tt.umo.Unmarshal(tt.inputMessage, []byte(tt.inputText))
2475 if err != nil && !tt.wantErr {
2476 t.Errorf("Unmarshal() returned error: %v\n\n", err)
2477 }
2478 if err == nil && tt.wantErr {
2479 t.Error("Unmarshal() got nil error, want error\n\n")
2480 }
2481 if tt.wantMessage != nil && !protoV1.Equal(tt.inputMessage.(protoV1.Message), tt.wantMessage.(protoV1.Message)) {
2482 t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", tt.inputMessage, tt.wantMessage)
2483 }
2484 })
2485 }
2486}