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