blob: ae58d6c5eb60064c2e507c24992d025e97fbd0fb [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
Damien Neil5c5b5312019-05-14 12:44:37 -07005package protojson_test
Herbie Ongc96a79d2019-03-08 10:49:17 -08006
7import (
8 "math"
9 "testing"
10
Damien Neil5c5b5312019-05-14 12:44:37 -070011 "google.golang.org/protobuf/encoding/protojson"
Damien Neile89e6242019-05-13 23:55:40 -070012 "google.golang.org/protobuf/encoding/testprotos/pb2"
13 "google.golang.org/protobuf/encoding/testprotos/pb3"
14 pimpl "google.golang.org/protobuf/internal/impl"
15 "google.golang.org/protobuf/internal/scalar"
16 "google.golang.org/protobuf/proto"
17 preg "google.golang.org/protobuf/reflect/protoregistry"
Herbie Onge63c4c42019-03-22 22:20:22 -070018
Joe Tsaia95b29f2019-05-16 12:47:20 -070019 "google.golang.org/protobuf/types/known/anypb"
20 "google.golang.org/protobuf/types/known/durationpb"
21 "google.golang.org/protobuf/types/known/emptypb"
22 "google.golang.org/protobuf/types/known/fieldmaskpb"
23 "google.golang.org/protobuf/types/known/structpb"
24 "google.golang.org/protobuf/types/known/timestamppb"
25 "google.golang.org/protobuf/types/known/wrapperspb"
Herbie Ongc96a79d2019-03-08 10:49:17 -080026)
27
28func TestUnmarshal(t *testing.T) {
29 tests := []struct {
30 desc string
Damien Neil5c5b5312019-05-14 12:44:37 -070031 umo protojson.UnmarshalOptions
Herbie Ongc96a79d2019-03-08 10:49:17 -080032 inputMessage proto.Message
33 inputText string
34 wantMessage proto.Message
35 // TODO: verify expected error message substring.
36 wantErr bool
37 }{{
38 desc: "proto2 empty message",
39 inputMessage: &pb2.Scalars{},
40 inputText: "{}",
41 wantMessage: &pb2.Scalars{},
42 }, {
43 desc: "unexpected value instead of EOF",
44 inputMessage: &pb2.Scalars{},
45 inputText: "{} {}",
46 wantErr: true,
47 }, {
48 desc: "proto2 optional scalars set to zero values",
49 inputMessage: &pb2.Scalars{},
50 inputText: `{
51 "optBool": false,
52 "optInt32": 0,
53 "optInt64": 0,
54 "optUint32": 0,
55 "optUint64": 0,
56 "optSint32": 0,
57 "optSint64": 0,
58 "optFixed32": 0,
59 "optFixed64": 0,
60 "optSfixed32": 0,
61 "optSfixed64": 0,
62 "optFloat": 0,
63 "optDouble": 0,
64 "optBytes": "",
65 "optString": ""
66}`,
67 wantMessage: &pb2.Scalars{
68 OptBool: scalar.Bool(false),
69 OptInt32: scalar.Int32(0),
70 OptInt64: scalar.Int64(0),
71 OptUint32: scalar.Uint32(0),
72 OptUint64: scalar.Uint64(0),
73 OptSint32: scalar.Int32(0),
74 OptSint64: scalar.Int64(0),
75 OptFixed32: scalar.Uint32(0),
76 OptFixed64: scalar.Uint64(0),
77 OptSfixed32: scalar.Int32(0),
78 OptSfixed64: scalar.Int64(0),
79 OptFloat: scalar.Float32(0),
80 OptDouble: scalar.Float64(0),
81 OptBytes: []byte{},
82 OptString: scalar.String(""),
83 },
84 }, {
85 desc: "proto3 scalars set to zero values",
86 inputMessage: &pb3.Scalars{},
87 inputText: `{
88 "sBool": false,
89 "sInt32": 0,
90 "sInt64": 0,
91 "sUint32": 0,
92 "sUint64": 0,
93 "sSint32": 0,
94 "sSint64": 0,
95 "sFixed32": 0,
96 "sFixed64": 0,
97 "sSfixed32": 0,
98 "sSfixed64": 0,
99 "sFloat": 0,
100 "sDouble": 0,
101 "sBytes": "",
102 "sString": ""
103}`,
104 wantMessage: &pb3.Scalars{},
105 }, {
106 desc: "proto2 optional scalars set to null",
107 inputMessage: &pb2.Scalars{},
108 inputText: `{
109 "optBool": null,
110 "optInt32": null,
111 "optInt64": null,
112 "optUint32": null,
113 "optUint64": null,
114 "optSint32": null,
115 "optSint64": null,
116 "optFixed32": null,
117 "optFixed64": null,
118 "optSfixed32": null,
119 "optSfixed64": null,
120 "optFloat": null,
121 "optDouble": null,
122 "optBytes": null,
123 "optString": null
124}`,
125 wantMessage: &pb2.Scalars{},
126 }, {
127 desc: "proto3 scalars set to null",
128 inputMessage: &pb3.Scalars{},
129 inputText: `{
130 "sBool": null,
131 "sInt32": null,
132 "sInt64": null,
133 "sUint32": null,
134 "sUint64": null,
135 "sSint32": null,
136 "sSint64": null,
137 "sFixed32": null,
138 "sFixed64": null,
139 "sSfixed32": null,
140 "sSfixed64": null,
141 "sFloat": null,
142 "sDouble": null,
143 "sBytes": null,
144 "sString": null
145}`,
146 wantMessage: &pb3.Scalars{},
147 }, {
148 desc: "boolean",
149 inputMessage: &pb3.Scalars{},
150 inputText: `{"sBool": true}`,
151 wantMessage: &pb3.Scalars{
152 SBool: true,
153 },
154 }, {
155 desc: "not boolean",
156 inputMessage: &pb3.Scalars{},
157 inputText: `{"sBool": "true"}`,
158 wantErr: true,
159 }, {
160 desc: "float and double",
161 inputMessage: &pb3.Scalars{},
162 inputText: `{
163 "sFloat": 1.234,
164 "sDouble": 5.678
165}`,
166 wantMessage: &pb3.Scalars{
167 SFloat: 1.234,
168 SDouble: 5.678,
169 },
170 }, {
171 desc: "float and double in string",
172 inputMessage: &pb3.Scalars{},
173 inputText: `{
174 "sFloat": "1.234",
175 "sDouble": "5.678"
176}`,
177 wantMessage: &pb3.Scalars{
178 SFloat: 1.234,
179 SDouble: 5.678,
180 },
181 }, {
182 desc: "float and double in E notation",
183 inputMessage: &pb3.Scalars{},
184 inputText: `{
185 "sFloat": 12.34E-1,
186 "sDouble": 5.678e4
187}`,
188 wantMessage: &pb3.Scalars{
189 SFloat: 1.234,
190 SDouble: 56780,
191 },
192 }, {
193 desc: "float and double in string E notation",
194 inputMessage: &pb3.Scalars{},
195 inputText: `{
196 "sFloat": "12.34E-1",
197 "sDouble": "5.678e4"
198}`,
199 wantMessage: &pb3.Scalars{
200 SFloat: 1.234,
201 SDouble: 56780,
202 },
203 }, {
204 desc: "float exceeds limit",
205 inputMessage: &pb3.Scalars{},
206 inputText: `{"sFloat": 3.4e39}`,
207 wantErr: true,
208 }, {
209 desc: "float in string exceeds limit",
210 inputMessage: &pb3.Scalars{},
211 inputText: `{"sFloat": "-3.4e39"}`,
212 wantErr: true,
213 }, {
214 desc: "double exceeds limit",
215 inputMessage: &pb3.Scalars{},
216 inputText: `{"sFloat": -1.79e+309}`,
217 wantErr: true,
218 }, {
219 desc: "double in string exceeds limit",
220 inputMessage: &pb3.Scalars{},
221 inputText: `{"sFloat": "1.79e+309"}`,
222 wantErr: true,
223 }, {
224 desc: "infinites",
225 inputMessage: &pb3.Scalars{},
226 inputText: `{"sFloat": "Infinity", "sDouble": "-Infinity"}`,
227 wantMessage: &pb3.Scalars{
228 SFloat: float32(math.Inf(+1)),
229 SDouble: math.Inf(-1),
230 },
231 }, {
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700232 desc: "float string with leading space",
233 inputMessage: &pb3.Scalars{},
234 inputText: `{"sFloat": " 1.234"}`,
235 wantErr: true,
236 }, {
237 desc: "double string with trailing space",
238 inputMessage: &pb3.Scalars{},
239 inputText: `{"sDouble": "5.678 "}`,
240 wantErr: true,
241 }, {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800242 desc: "not float",
243 inputMessage: &pb3.Scalars{},
244 inputText: `{"sFloat": true}`,
245 wantErr: true,
246 }, {
247 desc: "not double",
248 inputMessage: &pb3.Scalars{},
249 inputText: `{"sDouble": "not a number"}`,
250 wantErr: true,
251 }, {
252 desc: "integers",
253 inputMessage: &pb3.Scalars{},
254 inputText: `{
255 "sInt32": 1234,
256 "sInt64": -1234,
257 "sUint32": 1e2,
258 "sUint64": 100E-2,
259 "sSint32": 1.0,
260 "sSint64": -1.0,
261 "sFixed32": 1.234e+5,
262 "sFixed64": 1200E-2,
263 "sSfixed32": -1.234e05,
264 "sSfixed64": -1200e-02
265}`,
266 wantMessage: &pb3.Scalars{
267 SInt32: 1234,
268 SInt64: -1234,
269 SUint32: 100,
270 SUint64: 1,
271 SSint32: 1,
272 SSint64: -1,
273 SFixed32: 123400,
274 SFixed64: 12,
275 SSfixed32: -123400,
276 SSfixed64: -12,
277 },
278 }, {
279 desc: "integers in string",
280 inputMessage: &pb3.Scalars{},
281 inputText: `{
282 "sInt32": "1234",
283 "sInt64": "-1234",
284 "sUint32": "1e2",
285 "sUint64": "100E-2",
286 "sSint32": "1.0",
287 "sSint64": "-1.0",
288 "sFixed32": "1.234e+5",
289 "sFixed64": "1200E-2",
290 "sSfixed32": "-1.234e05",
291 "sSfixed64": "-1200e-02"
292}`,
293 wantMessage: &pb3.Scalars{
294 SInt32: 1234,
295 SInt64: -1234,
296 SUint32: 100,
297 SUint64: 1,
298 SSint32: 1,
299 SSint64: -1,
300 SFixed32: 123400,
301 SFixed64: 12,
302 SSfixed32: -123400,
303 SSfixed64: -12,
304 },
305 }, {
306 desc: "integers in escaped string",
307 inputMessage: &pb3.Scalars{},
308 inputText: `{"sInt32": "\u0031\u0032"}`,
309 wantMessage: &pb3.Scalars{
310 SInt32: 12,
311 },
312 }, {
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700313 desc: "integer string with leading space",
314 inputMessage: &pb3.Scalars{},
315 inputText: `{"sInt32": " 1234"}`,
316 wantErr: true,
317 }, {
318 desc: "integer string with trailing space",
319 inputMessage: &pb3.Scalars{},
320 inputText: `{"sUint32": "1e2 "}`,
321 wantErr: true,
322 }, {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800323 desc: "number is not an integer",
324 inputMessage: &pb3.Scalars{},
325 inputText: `{"sInt32": 1.001}`,
326 wantErr: true,
327 }, {
328 desc: "32-bit int exceeds limit",
329 inputMessage: &pb3.Scalars{},
330 inputText: `{"sInt32": 2e10}`,
331 wantErr: true,
332 }, {
333 desc: "64-bit int exceeds limit",
334 inputMessage: &pb3.Scalars{},
335 inputText: `{"sSfixed64": -9e19}`,
336 wantErr: true,
337 }, {
338 desc: "not integer",
339 inputMessage: &pb3.Scalars{},
340 inputText: `{"sInt32": "not a number"}`,
341 wantErr: true,
342 }, {
343 desc: "not unsigned integer",
344 inputMessage: &pb3.Scalars{},
345 inputText: `{"sUint32": "not a number"}`,
346 wantErr: true,
347 }, {
348 desc: "number is not an unsigned integer",
349 inputMessage: &pb3.Scalars{},
350 inputText: `{"sUint32": -1}`,
351 wantErr: true,
352 }, {
353 desc: "string",
354 inputMessage: &pb2.Scalars{},
355 inputText: `{"optString": "谷歌"}`,
356 wantMessage: &pb2.Scalars{
357 OptString: scalar.String("谷歌"),
358 },
359 }, {
360 desc: "string with invalid UTF-8",
361 inputMessage: &pb3.Scalars{},
362 inputText: "{\"sString\": \"\xff\"}",
Damien Neil8c86fc52019-06-19 09:28:29 -0700363 wantErr: true,
Herbie Ongc96a79d2019-03-08 10:49:17 -0800364 }, {
365 desc: "not string",
366 inputMessage: &pb2.Scalars{},
367 inputText: `{"optString": 42}`,
368 wantErr: true,
369 }, {
370 desc: "bytes",
371 inputMessage: &pb3.Scalars{},
372 inputText: `{"sBytes": "aGVsbG8gd29ybGQ"}`,
373 wantMessage: &pb3.Scalars{
374 SBytes: []byte("hello world"),
375 },
376 }, {
377 desc: "bytes padded",
378 inputMessage: &pb3.Scalars{},
379 inputText: `{"sBytes": "aGVsbG8gd29ybGQ="}`,
380 wantMessage: &pb3.Scalars{
381 SBytes: []byte("hello world"),
382 },
383 }, {
384 desc: "not bytes",
385 inputMessage: &pb3.Scalars{},
386 inputText: `{"sBytes": true}`,
387 wantErr: true,
388 }, {
389 desc: "proto2 enum",
390 inputMessage: &pb2.Enums{},
391 inputText: `{
392 "optEnum": "ONE",
393 "optNestedEnum": "UNO"
394}`,
395 wantMessage: &pb2.Enums{
396 OptEnum: pb2.Enum_ONE.Enum(),
397 OptNestedEnum: pb2.Enums_UNO.Enum(),
398 },
399 }, {
400 desc: "proto3 enum",
401 inputMessage: &pb3.Enums{},
402 inputText: `{
403 "sEnum": "ONE",
404 "sNestedEnum": "DIEZ"
405}`,
406 wantMessage: &pb3.Enums{
407 SEnum: pb3.Enum_ONE,
408 SNestedEnum: pb3.Enums_DIEZ,
409 },
410 }, {
411 desc: "enum numeric value",
412 inputMessage: &pb3.Enums{},
413 inputText: `{
414 "sEnum": 2,
415 "sNestedEnum": 2
416}`,
417 wantMessage: &pb3.Enums{
418 SEnum: pb3.Enum_TWO,
419 SNestedEnum: pb3.Enums_DOS,
420 },
421 }, {
422 desc: "enum unnamed numeric value",
423 inputMessage: &pb3.Enums{},
424 inputText: `{
425 "sEnum": 101,
426 "sNestedEnum": -101
427}`,
428 wantMessage: &pb3.Enums{
429 SEnum: 101,
430 SNestedEnum: -101,
431 },
432 }, {
433 desc: "enum set to number string",
434 inputMessage: &pb3.Enums{},
435 inputText: `{
Herbie Ong300b9fe2019-03-29 15:42:20 -0700436 "sEnum": "1"
Herbie Ongc96a79d2019-03-08 10:49:17 -0800437}`,
438 wantErr: true,
439 }, {
440 desc: "enum set to invalid named",
441 inputMessage: &pb3.Enums{},
442 inputText: `{
Herbie Ong300b9fe2019-03-29 15:42:20 -0700443 "sEnum": "UNNAMED"
Herbie Ongc96a79d2019-03-08 10:49:17 -0800444}`,
445 wantErr: true,
446 }, {
447 desc: "enum set to not enum",
448 inputMessage: &pb3.Enums{},
449 inputText: `{
Herbie Ong300b9fe2019-03-29 15:42:20 -0700450 "sEnum": true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800451}`,
452 wantErr: true,
453 }, {
Herbie Ong300b9fe2019-03-29 15:42:20 -0700454 desc: "enum set to JSON null",
455 inputMessage: &pb3.Enums{},
456 inputText: `{
457 "sEnum": null
458}`,
459 wantMessage: &pb3.Enums{},
460 }, {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800461 desc: "proto name",
462 inputMessage: &pb3.JSONNames{},
463 inputText: `{
464 "s_string": "proto name used"
465}`,
466 wantMessage: &pb3.JSONNames{
467 SString: "proto name used",
468 },
469 }, {
470 desc: "json_name",
471 inputMessage: &pb3.JSONNames{},
472 inputText: `{
473 "foo_bar": "json_name used"
474}`,
475 wantMessage: &pb3.JSONNames{
476 SString: "json_name used",
477 },
478 }, {
479 desc: "camelCase name",
480 inputMessage: &pb3.JSONNames{},
481 inputText: `{
482 "sString": "camelcase used"
483}`,
484 wantErr: true,
485 }, {
486 desc: "proto name and json_name",
487 inputMessage: &pb3.JSONNames{},
488 inputText: `{
489 "foo_bar": "json_name used",
490 "s_string": "proto name used"
491}`,
492 wantErr: true,
493 }, {
494 desc: "duplicate field names",
495 inputMessage: &pb3.JSONNames{},
496 inputText: `{
497 "foo_bar": "one",
498 "foo_bar": "two",
499}`,
500 wantErr: true,
501 }, {
502 desc: "null message",
503 inputMessage: &pb2.Nests{},
504 inputText: "null",
505 wantErr: true,
506 }, {
507 desc: "proto2 nested message not set",
508 inputMessage: &pb2.Nests{},
509 inputText: "{}",
510 wantMessage: &pb2.Nests{},
511 }, {
512 desc: "proto2 nested message set to null",
513 inputMessage: &pb2.Nests{},
514 inputText: `{
515 "optNested": null,
516 "optgroup": null
517}`,
518 wantMessage: &pb2.Nests{},
519 }, {
520 desc: "proto2 nested message set to empty",
521 inputMessage: &pb2.Nests{},
522 inputText: `{
523 "optNested": {},
524 "optgroup": {}
525}`,
526 wantMessage: &pb2.Nests{
527 OptNested: &pb2.Nested{},
528 Optgroup: &pb2.Nests_OptGroup{},
529 },
530 }, {
531 desc: "proto2 nested messages",
532 inputMessage: &pb2.Nests{},
533 inputText: `{
534 "optNested": {
535 "optString": "nested message",
536 "optNested": {
537 "optString": "another nested message"
538 }
539 }
540}`,
541 wantMessage: &pb2.Nests{
542 OptNested: &pb2.Nested{
543 OptString: scalar.String("nested message"),
544 OptNested: &pb2.Nested{
545 OptString: scalar.String("another nested message"),
546 },
547 },
548 },
549 }, {
550 desc: "proto2 groups",
551 inputMessage: &pb2.Nests{},
552 inputText: `{
553 "optgroup": {
554 "optString": "inside a group",
555 "optNested": {
556 "optString": "nested message inside a group"
557 },
558 "optnestedgroup": {
559 "optFixed32": 47
560 }
561 }
562}`,
563 wantMessage: &pb2.Nests{
564 Optgroup: &pb2.Nests_OptGroup{
565 OptString: scalar.String("inside a group"),
566 OptNested: &pb2.Nested{
567 OptString: scalar.String("nested message inside a group"),
568 },
569 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
570 OptFixed32: scalar.Uint32(47),
571 },
572 },
573 },
574 }, {
575 desc: "proto3 nested message not set",
576 inputMessage: &pb3.Nests{},
577 inputText: "{}",
578 wantMessage: &pb3.Nests{},
579 }, {
580 desc: "proto3 nested message set to null",
581 inputMessage: &pb3.Nests{},
582 inputText: `{"sNested": null}`,
583 wantMessage: &pb3.Nests{},
584 }, {
585 desc: "proto3 nested message set to empty",
586 inputMessage: &pb3.Nests{},
587 inputText: `{"sNested": {}}`,
588 wantMessage: &pb3.Nests{
589 SNested: &pb3.Nested{},
590 },
591 }, {
592 desc: "proto3 nested message",
593 inputMessage: &pb3.Nests{},
594 inputText: `{
595 "sNested": {
596 "sString": "nested message",
597 "sNested": {
598 "sString": "another nested message"
599 }
600 }
601}`,
602 wantMessage: &pb3.Nests{
603 SNested: &pb3.Nested{
604 SString: "nested message",
605 SNested: &pb3.Nested{
606 SString: "another nested message",
607 },
608 },
609 },
610 }, {
611 desc: "message set to non-message",
612 inputMessage: &pb3.Nests{},
613 inputText: `"not valid"`,
614 wantErr: true,
615 }, {
616 desc: "nested message set to non-message",
617 inputMessage: &pb3.Nests{},
618 inputText: `{"sNested": true}`,
619 wantErr: true,
620 }, {
621 desc: "oneof not set",
622 inputMessage: &pb3.Oneofs{},
623 inputText: "{}",
624 wantMessage: &pb3.Oneofs{},
625 }, {
626 desc: "oneof set to empty string",
627 inputMessage: &pb3.Oneofs{},
628 inputText: `{"oneofString": ""}`,
629 wantMessage: &pb3.Oneofs{
630 Union: &pb3.Oneofs_OneofString{},
631 },
632 }, {
633 desc: "oneof set to string",
634 inputMessage: &pb3.Oneofs{},
635 inputText: `{"oneofString": "hello"}`,
636 wantMessage: &pb3.Oneofs{
637 Union: &pb3.Oneofs_OneofString{
638 OneofString: "hello",
639 },
640 },
641 }, {
642 desc: "oneof set to enum",
643 inputMessage: &pb3.Oneofs{},
644 inputText: `{"oneofEnum": "ZERO"}`,
645 wantMessage: &pb3.Oneofs{
646 Union: &pb3.Oneofs_OneofEnum{
647 OneofEnum: pb3.Enum_ZERO,
648 },
649 },
650 }, {
651 desc: "oneof set to empty message",
652 inputMessage: &pb3.Oneofs{},
653 inputText: `{"oneofNested": {}}`,
654 wantMessage: &pb3.Oneofs{
655 Union: &pb3.Oneofs_OneofNested{
656 OneofNested: &pb3.Nested{},
657 },
658 },
659 }, {
660 desc: "oneof set to message",
661 inputMessage: &pb3.Oneofs{},
662 inputText: `{
663 "oneofNested": {
664 "sString": "nested message"
665 }
666}`,
667 wantMessage: &pb3.Oneofs{
668 Union: &pb3.Oneofs_OneofNested{
669 OneofNested: &pb3.Nested{
670 SString: "nested message",
671 },
672 },
673 },
674 }, {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700675 desc: "oneof set to more than one field",
676 inputMessage: &pb3.Oneofs{},
677 inputText: `{
678 "oneofEnum": "ZERO",
679 "oneofString": "hello"
680}`,
681 wantErr: true,
682 }, {
683 desc: "oneof set to null and value",
684 inputMessage: &pb3.Oneofs{},
685 inputText: `{
686 "oneofEnum": "ZERO",
687 "oneofString": null
688}`,
689 wantMessage: &pb3.Oneofs{
690 Union: &pb3.Oneofs_OneofEnum{
691 OneofEnum: pb3.Enum_ZERO,
692 },
693 },
694 }, {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800695 desc: "repeated null fields",
696 inputMessage: &pb2.Repeats{},
697 inputText: `{
698 "rptString": null,
699 "rptInt32" : null,
700 "rptFloat" : null,
701 "rptBytes" : null
702}`,
703 wantMessage: &pb2.Repeats{},
704 }, {
705 desc: "repeated scalars",
706 inputMessage: &pb2.Repeats{},
707 inputText: `{
708 "rptString": ["hello", "world"],
709 "rptInt32" : [-1, 0, 1],
710 "rptBool" : [false, true]
711}`,
712 wantMessage: &pb2.Repeats{
713 RptString: []string{"hello", "world"},
714 RptInt32: []int32{-1, 0, 1},
715 RptBool: []bool{false, true},
716 },
717 }, {
718 desc: "repeated enums",
719 inputMessage: &pb2.Enums{},
720 inputText: `{
721 "rptEnum" : ["TEN", 1, 42],
722 "rptNestedEnum": ["DOS", 2, -47]
723}`,
724 wantMessage: &pb2.Enums{
725 RptEnum: []pb2.Enum{pb2.Enum_TEN, pb2.Enum_ONE, 42},
726 RptNestedEnum: []pb2.Enums_NestedEnum{pb2.Enums_DOS, pb2.Enums_DOS, -47},
727 },
728 }, {
729 desc: "repeated messages",
730 inputMessage: &pb2.Nests{},
731 inputText: `{
732 "rptNested": [
733 {
734 "optString": "repeat nested one"
735 },
736 {
737 "optString": "repeat nested two",
738 "optNested": {
739 "optString": "inside repeat nested two"
740 }
741 },
742 {}
743 ]
744}`,
745 wantMessage: &pb2.Nests{
746 RptNested: []*pb2.Nested{
747 {
748 OptString: scalar.String("repeat nested one"),
749 },
750 {
751 OptString: scalar.String("repeat nested two"),
752 OptNested: &pb2.Nested{
753 OptString: scalar.String("inside repeat nested two"),
754 },
755 },
756 {},
757 },
758 },
759 }, {
760 desc: "repeated groups",
761 inputMessage: &pb2.Nests{},
762 inputText: `{
763 "rptgroup": [
764 {
765 "rptString": ["hello", "world"]
766 },
767 {}
768 ]
769}
770`,
771 wantMessage: &pb2.Nests{
772 Rptgroup: []*pb2.Nests_RptGroup{
773 {
774 RptString: []string{"hello", "world"},
775 },
776 {},
777 },
778 },
779 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -0700780 desc: "repeated string contains invalid UTF8",
781 inputMessage: &pb2.Repeats{},
782 inputText: `{"rptString": ["` + "abc\xff" + `"]}`,
Damien Neil8c86fc52019-06-19 09:28:29 -0700783 wantErr: true,
Herbie Onge63c4c42019-03-22 22:20:22 -0700784 }, {
785 desc: "repeated messages contain invalid UTF8",
786 inputMessage: &pb2.Nests{},
787 inputText: `{"rptNested": [{"optString": "` + "abc\xff" + `"}]}`,
Damien Neil8c86fc52019-06-19 09:28:29 -0700788 wantErr: true,
Herbie Onge63c4c42019-03-22 22:20:22 -0700789 }, {
790 desc: "repeated scalars contain invalid type",
Herbie Ongc96a79d2019-03-08 10:49:17 -0800791 inputMessage: &pb2.Repeats{},
792 inputText: `{"rptString": ["hello", null, "world"]}`,
793 wantErr: true,
794 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -0700795 desc: "repeated messages contain invalid type",
Herbie Ongc96a79d2019-03-08 10:49:17 -0800796 inputMessage: &pb2.Nests{},
797 inputText: `{"rptNested": [{}, null]}`,
798 wantErr: true,
799 }, {
800 desc: "map fields 1",
801 inputMessage: &pb3.Maps{},
802 inputText: `{
803 "int32ToStr": {
804 "-101": "-101",
805 "0" : "zero",
806 "255" : "0xff"
807 },
808 "boolToUint32": {
809 "false": 101,
810 "true" : "42"
811 }
812}`,
813 wantMessage: &pb3.Maps{
814 Int32ToStr: map[int32]string{
815 -101: "-101",
816 0xff: "0xff",
817 0: "zero",
818 },
819 BoolToUint32: map[bool]uint32{
820 true: 42,
821 false: 101,
822 },
823 },
824 }, {
825 desc: "map fields 2",
826 inputMessage: &pb3.Maps{},
827 inputText: `{
828 "uint64ToEnum": {
829 "1" : "ONE",
830 "2" : 2,
831 "10": 101
832 }
833}`,
834 wantMessage: &pb3.Maps{
835 Uint64ToEnum: map[uint64]pb3.Enum{
836 1: pb3.Enum_ONE,
837 2: pb3.Enum_TWO,
838 10: 101,
839 },
840 },
841 }, {
842 desc: "map fields 3",
843 inputMessage: &pb3.Maps{},
844 inputText: `{
845 "strToNested": {
846 "nested_one": {
847 "sString": "nested in a map"
848 },
849 "nested_two": {}
850 }
851}`,
852 wantMessage: &pb3.Maps{
853 StrToNested: map[string]*pb3.Nested{
854 "nested_one": {
855 SString: "nested in a map",
856 },
857 "nested_two": {},
858 },
859 },
860 }, {
861 desc: "map fields 4",
862 inputMessage: &pb3.Maps{},
863 inputText: `{
864 "strToOneofs": {
865 "nested": {
866 "oneofNested": {
867 "sString": "nested oneof in map field value"
868 }
869 },
870 "string": {
871 "oneofString": "hello"
872 }
873 }
874}`,
875 wantMessage: &pb3.Maps{
876 StrToOneofs: map[string]*pb3.Oneofs{
877 "string": {
878 Union: &pb3.Oneofs_OneofString{
879 OneofString: "hello",
880 },
881 },
882 "nested": {
883 Union: &pb3.Oneofs_OneofNested{
884 OneofNested: &pb3.Nested{
885 SString: "nested oneof in map field value",
886 },
887 },
888 },
889 },
890 },
891 }, {
892 desc: "map contains duplicate keys",
893 inputMessage: &pb3.Maps{},
894 inputText: `{
895 "int32ToStr": {
896 "0": "cero",
897 "0": "zero"
898 }
899}
900`,
901 wantErr: true,
902 }, {
903 desc: "map key empty string",
904 inputMessage: &pb3.Maps{},
905 inputText: `{
906 "strToNested": {
907 "": {}
908 }
909}`,
910 wantMessage: &pb3.Maps{
911 StrToNested: map[string]*pb3.Nested{
912 "": {},
913 },
914 },
915 }, {
916 desc: "map contains invalid key 1",
917 inputMessage: &pb3.Maps{},
918 inputText: `{
919 "int32ToStr": {
920 "invalid": "cero"
921}`,
922 wantErr: true,
923 }, {
924 desc: "map contains invalid key 2",
925 inputMessage: &pb3.Maps{},
926 inputText: `{
927 "int32ToStr": {
928 "1.02": "float"
929}`,
930 wantErr: true,
931 }, {
932 desc: "map contains invalid key 3",
933 inputMessage: &pb3.Maps{},
934 inputText: `{
935 "int32ToStr": {
936 "2147483648": "exceeds 32-bit integer max limit"
937}`,
938 wantErr: true,
939 }, {
940 desc: "map contains invalid key 4",
941 inputMessage: &pb3.Maps{},
942 inputText: `{
943 "uint64ToEnum": {
944 "-1": 0
945 }
946}`,
947 wantErr: true,
948 }, {
949 desc: "map contains invalid value",
950 inputMessage: &pb3.Maps{},
951 inputText: `{
952 "int32ToStr": {
953 "101": true
954}`,
955 wantErr: true,
956 }, {
957 desc: "map contains null for scalar value",
958 inputMessage: &pb3.Maps{},
959 inputText: `{
960 "int32ToStr": {
961 "101": null
962}`,
963 wantErr: true,
964 }, {
965 desc: "map contains null for message value",
966 inputMessage: &pb3.Maps{},
967 inputText: `{
968 "strToNested": {
969 "hello": null
970 }
971}`,
972 wantErr: true,
Herbie Onge52379a2019-03-15 18:00:19 -0700973 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -0700974 desc: "map contains contains message value with invalid UTF8",
975 inputMessage: &pb3.Maps{},
976 inputText: `{
977 "strToNested": {
978 "hello": {
979 "sString": "` + "abc\xff" + `"
980 }
981 }
982}`,
Herbie Onge63c4c42019-03-22 22:20:22 -0700983 wantErr: true,
984 }, {
985 desc: "map key contains invalid UTF8",
986 inputMessage: &pb3.Maps{},
987 inputText: `{
988 "strToNested": {
989 "` + "abc\xff" + `": {}
990 }
991}`,
Herbie Onge63c4c42019-03-22 22:20:22 -0700992 wantErr: true,
993 }, {
Herbie Ong329be5b2019-03-27 14:47:59 -0700994 desc: "required fields not set",
995 inputMessage: &pb2.Requireds{},
996 wantErr: true,
997 }, {
998 desc: "required field set",
999 inputMessage: &pb2.PartialRequired{},
1000 inputText: `{
1001 "reqString": "this is required"
1002}`,
1003 wantMessage: &pb2.PartialRequired{
1004 ReqString: scalar.String("this is required"),
1005 },
1006 }, {
1007 desc: "required fields partially set",
1008 inputMessage: &pb2.Requireds{},
1009 inputText: `{
1010 "reqBool": false,
1011 "reqSfixed64": 42,
1012 "reqString": "hello",
1013 "reqEnum": "ONE"
1014}`,
1015 wantMessage: &pb2.Requireds{
1016 ReqBool: scalar.Bool(false),
1017 ReqSfixed64: scalar.Int64(42),
1018 ReqString: scalar.String("hello"),
1019 ReqEnum: pb2.Enum_ONE.Enum(),
1020 },
1021 wantErr: true,
1022 }, {
1023 desc: "required fields partially set with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07001024 umo: protojson.UnmarshalOptions{AllowPartial: true},
Herbie Ong329be5b2019-03-27 14:47:59 -07001025 inputMessage: &pb2.Requireds{},
1026 inputText: `{
1027 "reqBool": false,
1028 "reqSfixed64": 42,
1029 "reqString": "hello",
1030 "reqEnum": "ONE"
1031}`,
1032 wantMessage: &pb2.Requireds{
1033 ReqBool: scalar.Bool(false),
1034 ReqSfixed64: scalar.Int64(42),
1035 ReqString: scalar.String("hello"),
1036 ReqEnum: pb2.Enum_ONE.Enum(),
1037 },
1038 }, {
1039 desc: "required fields all set",
1040 inputMessage: &pb2.Requireds{},
1041 inputText: `{
1042 "reqBool": false,
1043 "reqSfixed64": 42,
1044 "reqDouble": 1.23,
1045 "reqString": "hello",
1046 "reqEnum": "ONE",
1047 "reqNested": {}
1048}`,
1049 wantMessage: &pb2.Requireds{
1050 ReqBool: scalar.Bool(false),
1051 ReqSfixed64: scalar.Int64(42),
1052 ReqDouble: scalar.Float64(1.23),
1053 ReqString: scalar.String("hello"),
1054 ReqEnum: pb2.Enum_ONE.Enum(),
1055 ReqNested: &pb2.Nested{},
1056 },
1057 }, {
1058 desc: "indirect required field",
1059 inputMessage: &pb2.IndirectRequired{},
1060 inputText: `{
1061 "optNested": {}
1062}`,
1063 wantMessage: &pb2.IndirectRequired{
1064 OptNested: &pb2.NestedWithRequired{},
1065 },
1066 wantErr: true,
1067 }, {
1068 desc: "indirect required field with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07001069 umo: protojson.UnmarshalOptions{AllowPartial: true},
Herbie Ong329be5b2019-03-27 14:47:59 -07001070 inputMessage: &pb2.IndirectRequired{},
1071 inputText: `{
1072 "optNested": {}
1073}`,
1074 wantMessage: &pb2.IndirectRequired{
1075 OptNested: &pb2.NestedWithRequired{},
1076 },
1077 }, {
1078 desc: "indirect required field in repeated",
1079 inputMessage: &pb2.IndirectRequired{},
1080 inputText: `{
1081 "rptNested": [
1082 {"reqString": "one"},
1083 {}
1084 ]
1085}`,
1086 wantMessage: &pb2.IndirectRequired{
1087 RptNested: []*pb2.NestedWithRequired{
1088 {
1089 ReqString: scalar.String("one"),
1090 },
1091 {},
1092 },
1093 },
1094 wantErr: true,
1095 }, {
1096 desc: "indirect required field in repeated with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07001097 umo: protojson.UnmarshalOptions{AllowPartial: true},
Herbie Ong329be5b2019-03-27 14:47:59 -07001098 inputMessage: &pb2.IndirectRequired{},
1099 inputText: `{
1100 "rptNested": [
1101 {"reqString": "one"},
1102 {}
1103 ]
1104}`,
1105 wantMessage: &pb2.IndirectRequired{
1106 RptNested: []*pb2.NestedWithRequired{
1107 {
1108 ReqString: scalar.String("one"),
1109 },
1110 {},
1111 },
1112 },
1113 }, {
1114 desc: "indirect required field in map",
1115 inputMessage: &pb2.IndirectRequired{},
1116 inputText: `{
1117 "strToNested": {
1118 "missing": {},
1119 "contains": {
1120 "reqString": "here"
1121 }
1122 }
1123}`,
1124 wantMessage: &pb2.IndirectRequired{
1125 StrToNested: map[string]*pb2.NestedWithRequired{
1126 "missing": &pb2.NestedWithRequired{},
1127 "contains": &pb2.NestedWithRequired{
1128 ReqString: scalar.String("here"),
1129 },
1130 },
1131 },
1132 wantErr: true,
1133 }, {
1134 desc: "indirect required field in map with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07001135 umo: protojson.UnmarshalOptions{AllowPartial: true},
Herbie Ong329be5b2019-03-27 14:47:59 -07001136 inputMessage: &pb2.IndirectRequired{},
1137 inputText: `{
1138 "strToNested": {
1139 "missing": {},
1140 "contains": {
1141 "reqString": "here"
1142 }
1143 }
1144}`,
1145 wantMessage: &pb2.IndirectRequired{
1146 StrToNested: map[string]*pb2.NestedWithRequired{
1147 "missing": &pb2.NestedWithRequired{},
1148 "contains": &pb2.NestedWithRequired{
1149 ReqString: scalar.String("here"),
1150 },
1151 },
1152 },
1153 }, {
1154 desc: "indirect required field in oneof",
1155 inputMessage: &pb2.IndirectRequired{},
1156 inputText: `{
1157 "oneofNested": {}
1158}`,
1159 wantMessage: &pb2.IndirectRequired{
1160 Union: &pb2.IndirectRequired_OneofNested{
1161 OneofNested: &pb2.NestedWithRequired{},
1162 },
1163 },
1164 wantErr: true,
1165 }, {
1166 desc: "indirect required field in oneof with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07001167 umo: protojson.UnmarshalOptions{AllowPartial: true},
Herbie Ong329be5b2019-03-27 14:47:59 -07001168 inputMessage: &pb2.IndirectRequired{},
1169 inputText: `{
1170 "oneofNested": {}
1171}`,
1172 wantMessage: &pb2.IndirectRequired{
1173 Union: &pb2.IndirectRequired_OneofNested{
1174 OneofNested: &pb2.NestedWithRequired{},
1175 },
1176 },
1177 }, {
Herbie Onge52379a2019-03-15 18:00:19 -07001178 desc: "extensions of non-repeated fields",
1179 inputMessage: &pb2.Extensions{},
1180 inputText: `{
1181 "optString": "non-extension field",
1182 "optBool": true,
1183 "optInt32": 42,
1184 "[pb2.opt_ext_bool]": true,
1185 "[pb2.opt_ext_nested]": {
1186 "optString": "nested in an extension",
Herbie Onge63c4c42019-03-22 22:20:22 -07001187 "optNested": {
1188 "optString": "another nested in an extension"
Herbie Onge52379a2019-03-15 18:00:19 -07001189 }
1190 },
1191 "[pb2.opt_ext_string]": "extension field",
1192 "[pb2.opt_ext_enum]": "TEN"
1193}`,
1194 wantMessage: func() proto.Message {
1195 m := &pb2.Extensions{
1196 OptString: scalar.String("non-extension field"),
1197 OptBool: scalar.Bool(true),
1198 OptInt32: scalar.Int32(42),
1199 }
1200 setExtension(m, pb2.E_OptExtBool, true)
1201 setExtension(m, pb2.E_OptExtString, "extension field")
1202 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
1203 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
1204 OptString: scalar.String("nested in an extension"),
1205 OptNested: &pb2.Nested{
1206 OptString: scalar.String("another nested in an extension"),
1207 },
1208 })
1209 return m
1210 }(),
1211 }, {
1212 desc: "extensions of repeated fields",
1213 inputMessage: &pb2.Extensions{},
1214 inputText: `{
1215 "[pb2.rpt_ext_enum]": ["TEN", 101, "ONE"],
1216 "[pb2.rpt_ext_fixed32]": [42, 47],
1217 "[pb2.rpt_ext_nested]": [
1218 {"optString": "one"},
1219 {"optString": "two"},
1220 {"optString": "three"}
1221 ]
1222}`,
1223 wantMessage: func() proto.Message {
1224 m := &pb2.Extensions{}
1225 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
1226 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
1227 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
1228 &pb2.Nested{OptString: scalar.String("one")},
1229 &pb2.Nested{OptString: scalar.String("two")},
1230 &pb2.Nested{OptString: scalar.String("three")},
1231 })
1232 return m
1233 }(),
1234 }, {
1235 desc: "extensions of non-repeated fields in another message",
1236 inputMessage: &pb2.Extensions{},
1237 inputText: `{
1238 "[pb2.ExtensionsContainer.opt_ext_bool]": true,
1239 "[pb2.ExtensionsContainer.opt_ext_enum]": "TEN",
1240 "[pb2.ExtensionsContainer.opt_ext_nested]": {
1241 "optString": "nested in an extension",
1242 "optNested": {
1243 "optString": "another nested in an extension"
1244 }
1245 },
1246 "[pb2.ExtensionsContainer.opt_ext_string]": "extension field"
1247}`,
1248 wantMessage: func() proto.Message {
1249 m := &pb2.Extensions{}
1250 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1251 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
1252 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
1253 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
1254 OptString: scalar.String("nested in an extension"),
1255 OptNested: &pb2.Nested{
1256 OptString: scalar.String("another nested in an extension"),
1257 },
1258 })
1259 return m
1260 }(),
1261 }, {
1262 desc: "extensions of repeated fields in another message",
1263 inputMessage: &pb2.Extensions{},
1264 inputText: `{
1265 "optString": "non-extension field",
1266 "optBool": true,
1267 "optInt32": 42,
1268 "[pb2.ExtensionsContainer.rpt_ext_nested]": [
1269 {"optString": "one"},
1270 {"optString": "two"},
1271 {"optString": "three"}
1272 ],
1273 "[pb2.ExtensionsContainer.rpt_ext_enum]": ["TEN", 101, "ONE"],
1274 "[pb2.ExtensionsContainer.rpt_ext_string]": ["hello", "world"]
1275}`,
1276 wantMessage: func() proto.Message {
1277 m := &pb2.Extensions{
1278 OptString: scalar.String("non-extension field"),
1279 OptBool: scalar.Bool(true),
1280 OptInt32: scalar.Int32(42),
1281 }
1282 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
1283 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1284 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
1285 &pb2.Nested{OptString: scalar.String("one")},
1286 &pb2.Nested{OptString: scalar.String("two")},
1287 &pb2.Nested{OptString: scalar.String("three")},
1288 })
1289 return m
1290 }(),
1291 }, {
1292 desc: "invalid extension field name",
1293 inputMessage: &pb2.Extensions{},
1294 inputText: `{ "[pb2.invalid_message_field]": true }`,
1295 wantErr: true,
1296 }, {
1297 desc: "MessageSet",
1298 inputMessage: &pb2.MessageSet{},
1299 inputText: `{
1300 "[pb2.MessageSetExtension]": {
1301 "optString": "a messageset extension"
1302 },
1303 "[pb2.MessageSetExtension.ext_nested]": {
1304 "optString": "just a regular extension"
1305 },
1306 "[pb2.MessageSetExtension.not_message_set_extension]": {
1307 "optString": "not a messageset extension"
1308 }
1309}`,
1310 wantMessage: func() proto.Message {
1311 m := &pb2.MessageSet{}
1312 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1313 OptString: scalar.String("a messageset extension"),
1314 })
1315 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1316 OptString: scalar.String("not a messageset extension"),
1317 })
1318 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1319 OptString: scalar.String("just a regular extension"),
1320 })
1321 return m
1322 }(),
1323 }, {
Herbie Onge52379a2019-03-15 18:00:19 -07001324 desc: "extensions of repeated field contains null",
1325 inputMessage: &pb2.Extensions{},
1326 inputText: `{
1327 "[pb2.ExtensionsContainer.rpt_ext_nested]": [
1328 {"optString": "one"},
1329 null,
1330 {"optString": "three"}
1331 ],
1332}`,
1333 wantErr: true,
1334 }, {
1335 desc: "not real MessageSet 1",
1336 inputMessage: &pb2.FakeMessageSet{},
1337 inputText: `{
1338 "[pb2.FakeMessageSetExtension.message_set_extension]": {
1339 "optString": "not a messageset extension"
1340 }
1341}`,
1342 wantMessage: func() proto.Message {
1343 m := &pb2.FakeMessageSet{}
1344 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1345 OptString: scalar.String("not a messageset extension"),
1346 })
1347 return m
1348 }(),
1349 }, {
1350 desc: "not real MessageSet 2",
1351 inputMessage: &pb2.FakeMessageSet{},
1352 inputText: `{
1353 "[pb2.FakeMessageSetExtension]": {
1354 "optString": "not a messageset extension"
1355 }
1356}`,
1357 wantErr: true,
1358 }, {
1359 desc: "not real MessageSet 3",
1360 inputMessage: &pb2.MessageSet{},
1361 inputText: `{
1362 "[pb2.message_set_extension]": {
1363 "optString": "another not a messageset extension"
1364 }
1365}`,
1366 wantMessage: func() proto.Message {
1367 m := &pb2.MessageSet{}
1368 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1369 OptString: scalar.String("another not a messageset extension"),
1370 })
1371 return m
1372 }(),
Herbie Onge63c4c42019-03-22 22:20:22 -07001373 }, {
1374 desc: "Empty",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001375 inputMessage: &emptypb.Empty{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001376 inputText: `{}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001377 wantMessage: &emptypb.Empty{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001378 }, {
1379 desc: "Empty contains unknown",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001380 inputMessage: &emptypb.Empty{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001381 inputText: `{"unknown": null}`,
1382 wantErr: true,
1383 }, {
1384 desc: "BoolValue false",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001385 inputMessage: &wrapperspb.BoolValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001386 inputText: `false`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001387 wantMessage: &wrapperspb.BoolValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001388 }, {
1389 desc: "BoolValue true",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001390 inputMessage: &wrapperspb.BoolValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001391 inputText: `true`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001392 wantMessage: &wrapperspb.BoolValue{Value: true},
Herbie Onge63c4c42019-03-22 22:20:22 -07001393 }, {
1394 desc: "BoolValue invalid value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001395 inputMessage: &wrapperspb.BoolValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001396 inputText: `{}`,
1397 wantErr: true,
1398 }, {
1399 desc: "Int32Value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001400 inputMessage: &wrapperspb.Int32Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001401 inputText: `42`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001402 wantMessage: &wrapperspb.Int32Value{Value: 42},
Herbie Onge63c4c42019-03-22 22:20:22 -07001403 }, {
1404 desc: "Int32Value in JSON string",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001405 inputMessage: &wrapperspb.Int32Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001406 inputText: `"1.23e3"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001407 wantMessage: &wrapperspb.Int32Value{Value: 1230},
Herbie Onge63c4c42019-03-22 22:20:22 -07001408 }, {
1409 desc: "Int64Value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001410 inputMessage: &wrapperspb.Int64Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001411 inputText: `"42"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001412 wantMessage: &wrapperspb.Int64Value{Value: 42},
Herbie Onge63c4c42019-03-22 22:20:22 -07001413 }, {
1414 desc: "UInt32Value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001415 inputMessage: &wrapperspb.UInt32Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001416 inputText: `42`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001417 wantMessage: &wrapperspb.UInt32Value{Value: 42},
Herbie Onge63c4c42019-03-22 22:20:22 -07001418 }, {
1419 desc: "UInt64Value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001420 inputMessage: &wrapperspb.UInt64Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001421 inputText: `"42"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001422 wantMessage: &wrapperspb.UInt64Value{Value: 42},
Herbie Onge63c4c42019-03-22 22:20:22 -07001423 }, {
1424 desc: "FloatValue",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001425 inputMessage: &wrapperspb.FloatValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001426 inputText: `1.02`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001427 wantMessage: &wrapperspb.FloatValue{Value: 1.02},
Herbie Onge63c4c42019-03-22 22:20:22 -07001428 }, {
1429 desc: "FloatValue exceeds max limit",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001430 inputMessage: &wrapperspb.FloatValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001431 inputText: `1.23+40`,
1432 wantErr: true,
1433 }, {
1434 desc: "FloatValue Infinity",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001435 inputMessage: &wrapperspb.FloatValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001436 inputText: `"-Infinity"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001437 wantMessage: &wrapperspb.FloatValue{Value: float32(math.Inf(-1))},
Herbie Onge63c4c42019-03-22 22:20:22 -07001438 }, {
1439 desc: "DoubleValue",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001440 inputMessage: &wrapperspb.DoubleValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001441 inputText: `1.02`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001442 wantMessage: &wrapperspb.DoubleValue{Value: 1.02},
Herbie Onge63c4c42019-03-22 22:20:22 -07001443 }, {
1444 desc: "DoubleValue Infinity",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001445 inputMessage: &wrapperspb.DoubleValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001446 inputText: `"Infinity"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001447 wantMessage: &wrapperspb.DoubleValue{Value: math.Inf(+1)},
Herbie Onge63c4c42019-03-22 22:20:22 -07001448 }, {
1449 desc: "StringValue empty",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001450 inputMessage: &wrapperspb.StringValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001451 inputText: `""`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001452 wantMessage: &wrapperspb.StringValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001453 }, {
1454 desc: "StringValue",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001455 inputMessage: &wrapperspb.StringValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001456 inputText: `"谷歌"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001457 wantMessage: &wrapperspb.StringValue{Value: "谷歌"},
Herbie Onge63c4c42019-03-22 22:20:22 -07001458 }, {
1459 desc: "StringValue with invalid UTF8 error",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001460 inputMessage: &wrapperspb.StringValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001461 inputText: "\"abc\xff\"",
Herbie Onge63c4c42019-03-22 22:20:22 -07001462 wantErr: true,
1463 }, {
1464 desc: "StringValue field with invalid UTF8 error",
1465 inputMessage: &pb2.KnownTypes{},
1466 inputText: "{\n \"optString\": \"abc\xff\"\n}",
Damien Neil8c86fc52019-06-19 09:28:29 -07001467 wantErr: true,
Herbie Onge63c4c42019-03-22 22:20:22 -07001468 }, {
Herbie Ong300b9fe2019-03-29 15:42:20 -07001469 desc: "NullValue field with JSON null",
1470 inputMessage: &pb2.KnownTypes{},
1471 inputText: `{
1472 "optNull": null
1473}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001474 wantMessage: &pb2.KnownTypes{OptNull: new(structpb.NullValue)},
Herbie Ong300b9fe2019-03-29 15:42:20 -07001475 }, {
1476 desc: "NullValue field with string",
1477 inputMessage: &pb2.KnownTypes{},
1478 inputText: `{
1479 "optNull": "NULL_VALUE"
1480}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001481 wantMessage: &pb2.KnownTypes{OptNull: new(structpb.NullValue)},
Herbie Ong300b9fe2019-03-29 15:42:20 -07001482 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -07001483 desc: "BytesValue",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001484 inputMessage: &wrapperspb.BytesValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001485 inputText: `"aGVsbG8="`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001486 wantMessage: &wrapperspb.BytesValue{Value: []byte("hello")},
Herbie Onge63c4c42019-03-22 22:20:22 -07001487 }, {
1488 desc: "Value null",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001489 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001490 inputText: `null`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001491 wantMessage: &structpb.Value{Kind: &structpb.Value_NullValue{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001492 }, {
1493 desc: "Value field null",
1494 inputMessage: &pb2.KnownTypes{},
1495 inputText: `{
1496 "optValue": null
1497}`,
1498 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001499 OptValue: &structpb.Value{Kind: &structpb.Value_NullValue{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001500 },
1501 }, {
1502 desc: "Value bool",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001503 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001504 inputText: `false`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001505 wantMessage: &structpb.Value{Kind: &structpb.Value_BoolValue{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001506 }, {
1507 desc: "Value field bool",
1508 inputMessage: &pb2.KnownTypes{},
1509 inputText: `{
1510 "optValue": true
1511}`,
1512 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001513 OptValue: &structpb.Value{Kind: &structpb.Value_BoolValue{true}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001514 },
1515 }, {
1516 desc: "Value number",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001517 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001518 inputText: `1.02`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001519 wantMessage: &structpb.Value{Kind: &structpb.Value_NumberValue{1.02}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001520 }, {
1521 desc: "Value field number",
1522 inputMessage: &pb2.KnownTypes{},
1523 inputText: `{
1524 "optValue": 1.02
1525}`,
1526 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001527 OptValue: &structpb.Value{Kind: &structpb.Value_NumberValue{1.02}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001528 },
1529 }, {
1530 desc: "Value string",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001531 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001532 inputText: `"hello"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001533 wantMessage: &structpb.Value{Kind: &structpb.Value_StringValue{"hello"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001534 }, {
1535 desc: "Value string with invalid UTF8",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001536 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001537 inputText: "\"\xff\"",
Herbie Onge63c4c42019-03-22 22:20:22 -07001538 wantErr: true,
1539 }, {
1540 desc: "Value field string",
1541 inputMessage: &pb2.KnownTypes{},
1542 inputText: `{
1543 "optValue": "NaN"
1544}`,
1545 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001546 OptValue: &structpb.Value{Kind: &structpb.Value_StringValue{"NaN"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001547 },
1548 }, {
1549 desc: "Value field string with invalid UTF8",
1550 inputMessage: &pb2.KnownTypes{},
1551 inputText: `{
1552 "optValue": "` + "\xff" + `"
1553}`,
Herbie Onge63c4c42019-03-22 22:20:22 -07001554 wantErr: true,
1555 }, {
1556 desc: "Value empty struct",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001557 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001558 inputText: `{}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001559 wantMessage: &structpb.Value{
1560 Kind: &structpb.Value_StructValue{
1561 &structpb.Struct{Fields: map[string]*structpb.Value{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001562 },
1563 },
1564 }, {
1565 desc: "Value struct",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001566 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001567 inputText: `{
1568 "string": "hello",
1569 "number": 123,
1570 "null": null,
1571 "bool": false,
1572 "struct": {
1573 "string": "world"
1574 },
1575 "list": []
1576}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001577 wantMessage: &structpb.Value{
1578 Kind: &structpb.Value_StructValue{
1579 &structpb.Struct{
1580 Fields: map[string]*structpb.Value{
1581 "string": {Kind: &structpb.Value_StringValue{"hello"}},
1582 "number": {Kind: &structpb.Value_NumberValue{123}},
1583 "null": {Kind: &structpb.Value_NullValue{}},
1584 "bool": {Kind: &structpb.Value_BoolValue{false}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001585 "struct": {
Joe Tsaia95b29f2019-05-16 12:47:20 -07001586 Kind: &structpb.Value_StructValue{
1587 &structpb.Struct{
1588 Fields: map[string]*structpb.Value{
1589 "string": {Kind: &structpb.Value_StringValue{"world"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001590 },
1591 },
1592 },
1593 },
1594 "list": {
Joe Tsaia95b29f2019-05-16 12:47:20 -07001595 Kind: &structpb.Value_ListValue{&structpb.ListValue{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001596 },
1597 },
1598 },
1599 },
1600 },
1601 }, {
1602 desc: "Value struct with invalid UTF8 string",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001603 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001604 inputText: "{\"string\": \"abc\xff\"}",
Damien Neil8c86fc52019-06-19 09:28:29 -07001605 wantErr: true,
Herbie Onge63c4c42019-03-22 22:20:22 -07001606 }, {
1607 desc: "Value field struct",
1608 inputMessage: &pb2.KnownTypes{},
1609 inputText: `{
1610 "optValue": {
1611 "string": "hello"
1612 }
1613}`,
1614 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001615 OptValue: &structpb.Value{
1616 Kind: &structpb.Value_StructValue{
1617 &structpb.Struct{
1618 Fields: map[string]*structpb.Value{
1619 "string": {Kind: &structpb.Value_StringValue{"hello"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001620 },
1621 },
1622 },
1623 },
1624 },
1625 }, {
1626 desc: "Value empty list",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001627 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001628 inputText: `[]`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001629 wantMessage: &structpb.Value{
1630 Kind: &structpb.Value_ListValue{
1631 &structpb.ListValue{Values: []*structpb.Value{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001632 },
1633 },
1634 }, {
1635 desc: "Value list",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001636 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001637 inputText: `[
1638 "string",
1639 123,
1640 null,
1641 true,
1642 {},
1643 [
1644 "string",
1645 1.23,
1646 null,
1647 false
1648 ]
1649]`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001650 wantMessage: &structpb.Value{
1651 Kind: &structpb.Value_ListValue{
1652 &structpb.ListValue{
1653 Values: []*structpb.Value{
1654 {Kind: &structpb.Value_StringValue{"string"}},
1655 {Kind: &structpb.Value_NumberValue{123}},
1656 {Kind: &structpb.Value_NullValue{}},
1657 {Kind: &structpb.Value_BoolValue{true}},
1658 {Kind: &structpb.Value_StructValue{&structpb.Struct{}}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001659 {
Joe Tsaia95b29f2019-05-16 12:47:20 -07001660 Kind: &structpb.Value_ListValue{
1661 &structpb.ListValue{
1662 Values: []*structpb.Value{
1663 {Kind: &structpb.Value_StringValue{"string"}},
1664 {Kind: &structpb.Value_NumberValue{1.23}},
1665 {Kind: &structpb.Value_NullValue{}},
1666 {Kind: &structpb.Value_BoolValue{false}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001667 },
1668 },
1669 },
1670 },
1671 },
1672 },
1673 },
1674 },
1675 }, {
1676 desc: "Value list with invalid UTF8 string",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001677 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001678 inputText: "[\"abc\xff\"]",
Damien Neil8c86fc52019-06-19 09:28:29 -07001679 wantErr: true,
Herbie Onge63c4c42019-03-22 22:20:22 -07001680 }, {
1681 desc: "Value field list with invalid UTF8 string",
1682 inputMessage: &pb2.KnownTypes{},
1683 inputText: `{
1684 "optValue": [ "` + "abc\xff" + `"]
1685}`,
Herbie Onge63c4c42019-03-22 22:20:22 -07001686 wantErr: true,
1687 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001688 desc: "Duration empty string",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001689 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001690 inputText: `""`,
1691 wantErr: true,
1692 }, {
1693 desc: "Duration with secs",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001694 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001695 inputText: `"3s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001696 wantMessage: &durationpb.Duration{Seconds: 3},
Herbie Ongc4450372019-03-27 09:59:51 -07001697 }, {
1698 desc: "Duration with escaped unicode",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001699 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001700 inputText: `"\u0033s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001701 wantMessage: &durationpb.Duration{Seconds: 3},
Herbie Ongc4450372019-03-27 09:59:51 -07001702 }, {
1703 desc: "Duration with -secs",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001704 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001705 inputText: `"-3s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001706 wantMessage: &durationpb.Duration{Seconds: -3},
Herbie Ongc4450372019-03-27 09:59:51 -07001707 }, {
Herbie Ong17523eb2019-03-29 17:46:57 -07001708 desc: "Duration with plus sign",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001709 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001710 inputText: `"+3s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001711 wantMessage: &durationpb.Duration{Seconds: 3},
Herbie Ong17523eb2019-03-29 17:46:57 -07001712 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001713 desc: "Duration with nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001714 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001715 inputText: `"0.001s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001716 wantMessage: &durationpb.Duration{Nanos: 1e6},
Herbie Ongc4450372019-03-27 09:59:51 -07001717 }, {
1718 desc: "Duration with -nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001719 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001720 inputText: `"-0.001s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001721 wantMessage: &durationpb.Duration{Nanos: -1e6},
Herbie Ongc4450372019-03-27 09:59:51 -07001722 }, {
Herbie Ong17523eb2019-03-29 17:46:57 -07001723 desc: "Duration with -nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001724 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001725 inputText: `"-.001s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001726 wantMessage: &durationpb.Duration{Nanos: -1e6},
Herbie Ong17523eb2019-03-29 17:46:57 -07001727 }, {
1728 desc: "Duration with +nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001729 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001730 inputText: `"+.001s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001731 wantMessage: &durationpb.Duration{Nanos: 1e6},
Herbie Ong17523eb2019-03-29 17:46:57 -07001732 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001733 desc: "Duration with -secs -nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001734 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001735 inputText: `"-123.000000450s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001736 wantMessage: &durationpb.Duration{Seconds: -123, Nanos: -450},
Herbie Ongc4450372019-03-27 09:59:51 -07001737 }, {
1738 desc: "Duration with large secs",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001739 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001740 inputText: `"10000000000.000000001s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001741 wantMessage: &durationpb.Duration{Seconds: 1e10, Nanos: 1},
Herbie Ongc4450372019-03-27 09:59:51 -07001742 }, {
1743 desc: "Duration with decimal without fractional",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001744 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001745 inputText: `"3.s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001746 wantMessage: &durationpb.Duration{Seconds: 3},
Herbie Ongc4450372019-03-27 09:59:51 -07001747 }, {
1748 desc: "Duration with decimal without integer",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001749 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001750 inputText: `"0.5s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001751 wantMessage: &durationpb.Duration{Nanos: 5e8},
Herbie Ongc4450372019-03-27 09:59:51 -07001752 }, {
Herbie Ongad9c1252019-04-24 20:51:28 -07001753 desc: "Duration max value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001754 inputMessage: &durationpb.Duration{},
Herbie Ongad9c1252019-04-24 20:51:28 -07001755 inputText: `"315576000000.999999999s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001756 wantMessage: &durationpb.Duration{Seconds: 315576000000, Nanos: 999999999},
Herbie Ongad9c1252019-04-24 20:51:28 -07001757 }, {
1758 desc: "Duration min value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001759 inputMessage: &durationpb.Duration{},
Herbie Ongad9c1252019-04-24 20:51:28 -07001760 inputText: `"-315576000000.999999999s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001761 wantMessage: &durationpb.Duration{Seconds: -315576000000, Nanos: -999999999},
Herbie Ongad9c1252019-04-24 20:51:28 -07001762 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001763 desc: "Duration with +secs out of range",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001764 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001765 inputText: `"315576000001s"`,
1766 wantErr: true,
1767 }, {
1768 desc: "Duration with -secs out of range",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001769 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001770 inputText: `"-315576000001s"`,
1771 wantErr: true,
1772 }, {
1773 desc: "Duration with nanos beyond 9 digits",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001774 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001775 inputText: `"0.1000000000s"`,
Herbie Ongc4450372019-03-27 09:59:51 -07001776 wantErr: true,
1777 }, {
1778 desc: "Duration without suffix s",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001779 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001780 inputText: `"123"`,
1781 wantErr: true,
1782 }, {
Herbie Ong17523eb2019-03-29 17:46:57 -07001783 desc: "Duration invalid signed fraction",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001784 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001785 inputText: `"123.+123s"`,
1786 wantErr: true,
1787 }, {
1788 desc: "Duration invalid multiple .",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001789 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001790 inputText: `"123.123.s"`,
1791 wantErr: true,
1792 }, {
1793 desc: "Duration invalid integer",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001794 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001795 inputText: `"01s"`,
1796 wantErr: true,
1797 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001798 desc: "Timestamp zero",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001799 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001800 inputText: `"1970-01-01T00:00:00Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001801 wantMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001802 }, {
1803 desc: "Timestamp with tz adjustment",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001804 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001805 inputText: `"1970-01-01T00:00:00+01:00"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001806 wantMessage: &timestamppb.Timestamp{Seconds: -3600},
Herbie Ongc4450372019-03-27 09:59:51 -07001807 }, {
1808 desc: "Timestamp UTC",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001809 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001810 inputText: `"2019-03-19T23:03:21Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001811 wantMessage: &timestamppb.Timestamp{Seconds: 1553036601},
Herbie Ongc4450372019-03-27 09:59:51 -07001812 }, {
1813 desc: "Timestamp with escaped unicode",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001814 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001815 inputText: `"2019-0\u0033-19T23:03:21Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001816 wantMessage: &timestamppb.Timestamp{Seconds: 1553036601},
Herbie Ongc4450372019-03-27 09:59:51 -07001817 }, {
1818 desc: "Timestamp with nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001819 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001820 inputText: `"2019-03-19T23:03:21.000000001Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001821 wantMessage: &timestamppb.Timestamp{Seconds: 1553036601, Nanos: 1},
Herbie Ongc4450372019-03-27 09:59:51 -07001822 }, {
Herbie Ongad9c1252019-04-24 20:51:28 -07001823 desc: "Timestamp max value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001824 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001825 inputText: `"9999-12-31T23:59:59.999999999Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001826 wantMessage: &timestamppb.Timestamp{Seconds: 253402300799, Nanos: 999999999},
Herbie Ongc4450372019-03-27 09:59:51 -07001827 }, {
Herbie Ongad9c1252019-04-24 20:51:28 -07001828 desc: "Timestamp above max value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001829 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001830 inputText: `"9999-12-31T23:59:59-01:00"`,
1831 wantErr: true,
1832 }, {
Herbie Ongad9c1252019-04-24 20:51:28 -07001833 desc: "Timestamp min value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001834 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001835 inputText: `"0001-01-01T00:00:00Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001836 wantMessage: &timestamppb.Timestamp{Seconds: -62135596800},
Herbie Ongc4450372019-03-27 09:59:51 -07001837 }, {
Herbie Ongad9c1252019-04-24 20:51:28 -07001838 desc: "Timestamp below min value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001839 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001840 inputText: `"0001-01-01T00:00:00+01:00"`,
1841 wantErr: true,
1842 }, {
1843 desc: "Timestamp with nanos beyond 9 digits",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001844 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001845 inputText: `"1970-01-01T00:00:00.0000000001Z"`,
1846 wantErr: true,
1847 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -07001848 desc: "FieldMask empty",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001849 inputMessage: &fieldmaskpb.FieldMask{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001850 inputText: `""`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001851 wantMessage: &fieldmaskpb.FieldMask{Paths: []string{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001852 }, {
1853 desc: "FieldMask",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001854 inputMessage: &fieldmaskpb.FieldMask{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001855 inputText: `"foo,fooBar , foo.barQux ,Foo"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001856 wantMessage: &fieldmaskpb.FieldMask{
Herbie Onge63c4c42019-03-22 22:20:22 -07001857 Paths: []string{
1858 "foo",
1859 "foo_bar",
1860 "foo.bar_qux",
1861 "_foo",
1862 },
1863 },
1864 }, {
1865 desc: "FieldMask field",
1866 inputMessage: &pb2.KnownTypes{},
1867 inputText: `{
1868 "optFieldmask": "foo, qux.fooBar"
1869}`,
1870 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001871 OptFieldmask: &fieldmaskpb.FieldMask{
Herbie Onge63c4c42019-03-22 22:20:22 -07001872 Paths: []string{
1873 "foo",
1874 "qux.foo_bar",
1875 },
1876 },
1877 },
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001878 }, {
1879 desc: "Any empty",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001880 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001881 inputText: `{}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001882 wantMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001883 }, {
1884 desc: "Any with non-custom message",
Damien Neil5c5b5312019-05-14 12:44:37 -07001885 umo: protojson.UnmarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001886 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001887 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001888 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001889 inputText: `{
1890 "@type": "foo/pb2.Nested",
1891 "optString": "embedded inside Any",
1892 "optNested": {
1893 "optString": "inception"
1894 }
1895}`,
1896 wantMessage: func() proto.Message {
1897 m := &pb2.Nested{
1898 OptString: scalar.String("embedded inside Any"),
1899 OptNested: &pb2.Nested{
1900 OptString: scalar.String("inception"),
1901 },
1902 }
1903 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1904 if err != nil {
1905 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1906 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001907 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001908 TypeUrl: "foo/pb2.Nested",
1909 Value: b,
1910 }
1911 }(),
1912 }, {
1913 desc: "Any with empty embedded message",
Damien Neil5c5b5312019-05-14 12:44:37 -07001914 umo: protojson.UnmarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001915 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001916 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001917 inputMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07001918 inputText: `{"@type": "foo/pb2.Nested"}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001919 wantMessage: &anypb.Any{TypeUrl: "foo/pb2.Nested"},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001920 }, {
1921 desc: "Any without registered type",
Damien Neil5c5b5312019-05-14 12:44:37 -07001922 umo: protojson.UnmarshalOptions{Resolver: preg.NewTypes()},
Joe Tsaia95b29f2019-05-16 12:47:20 -07001923 inputMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07001924 inputText: `{"@type": "foo/pb2.Nested"}`,
1925 wantErr: true,
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001926 }, {
Damien Neil0c9f0a92019-06-19 10:41:09 -07001927 desc: "Any with missing required",
Damien Neil5c5b5312019-05-14 12:44:37 -07001928 umo: protojson.UnmarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001929 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001930 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001931 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001932 inputText: `{
1933 "@type": "pb2.PartialRequired",
1934 "optString": "embedded inside Any"
1935}`,
1936 wantMessage: func() proto.Message {
1937 m := &pb2.PartialRequired{
1938 OptString: scalar.String("embedded inside Any"),
1939 }
Damien Neil96c229a2019-04-03 12:17:24 -07001940 b, err := proto.MarshalOptions{
1941 Deterministic: true,
1942 AllowPartial: true,
1943 }.Marshal(m)
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001944 if err != nil {
1945 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1946 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001947 return &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001948 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001949 Value: b,
1950 }
1951 }(),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001952 }, {
1953 desc: "Any with partial required and AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07001954 umo: protojson.UnmarshalOptions{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001955 AllowPartial: true,
Joe Tsai0fc49f82019-05-01 12:29:25 -07001956 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001957 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001958 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001959 inputText: `{
1960 "@type": "pb2.PartialRequired",
1961 "optString": "embedded inside Any"
1962}`,
1963 wantMessage: func() proto.Message {
1964 m := &pb2.PartialRequired{
1965 OptString: scalar.String("embedded inside Any"),
1966 }
Damien Neil96c229a2019-04-03 12:17:24 -07001967 b, err := proto.MarshalOptions{
1968 Deterministic: true,
1969 AllowPartial: true,
1970 }.Marshal(m)
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001971 if err != nil {
1972 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1973 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001974 return &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001975 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001976 Value: b,
1977 }
1978 }(),
1979 }, {
1980 desc: "Any with invalid UTF8",
Damien Neil5c5b5312019-05-14 12:44:37 -07001981 umo: protojson.UnmarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001982 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001983 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001984 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001985 inputText: `{
1986 "optString": "` + "abc\xff" + `",
1987 "@type": "foo/pb2.Nested"
1988}`,
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001989 wantErr: true,
1990 }, {
1991 desc: "Any with BoolValue",
Damien Neil5c5b5312019-05-14 12:44:37 -07001992 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001993 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.BoolValue{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001994 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001995 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001996 inputText: `{
1997 "@type": "type.googleapis.com/google.protobuf.BoolValue",
1998 "value": true
1999}`,
2000 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002001 m := &wrapperspb.BoolValue{Value: true}
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002002 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2003 if err != nil {
2004 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2005 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002006 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002007 TypeUrl: "type.googleapis.com/google.protobuf.BoolValue",
2008 Value: b,
2009 }
2010 }(),
2011 }, {
2012 desc: "Any with Empty",
Damien Neil5c5b5312019-05-14 12:44:37 -07002013 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002014 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002015 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002016 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002017 inputText: `{
2018 "value": {},
2019 "@type": "type.googleapis.com/google.protobuf.Empty"
2020}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002021 wantMessage: &anypb.Any{
Herbie Ong4f0be712019-04-25 17:57:12 -07002022 TypeUrl: "type.googleapis.com/google.protobuf.Empty",
2023 },
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002024 }, {
2025 desc: "Any with missing Empty",
Damien Neil5c5b5312019-05-14 12:44:37 -07002026 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002027 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002028 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002029 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002030 inputText: `{
2031 "@type": "type.googleapis.com/google.protobuf.Empty"
2032}`,
2033 wantErr: true,
2034 }, {
2035 desc: "Any with StringValue containing invalid UTF8",
Damien Neil5c5b5312019-05-14 12:44:37 -07002036 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002037 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002038 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002039 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002040 inputText: `{
2041 "@type": "google.protobuf.StringValue",
2042 "value": "` + "abc\xff" + `"
2043}`,
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002044 wantErr: true,
2045 }, {
2046 desc: "Any with Int64Value",
Damien Neil5c5b5312019-05-14 12:44:37 -07002047 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002048 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.Int64Value{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002049 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002050 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002051 inputText: `{
2052 "@type": "google.protobuf.Int64Value",
2053 "value": "42"
2054}`,
2055 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002056 m := &wrapperspb.Int64Value{Value: 42}
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002057 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2058 if err != nil {
2059 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2060 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002061 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002062 TypeUrl: "google.protobuf.Int64Value",
2063 Value: b,
2064 }
2065 }(),
2066 }, {
2067 desc: "Any with invalid Int64Value",
Damien Neil5c5b5312019-05-14 12:44:37 -07002068 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002069 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.Int64Value{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002070 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002071 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002072 inputText: `{
2073 "@type": "google.protobuf.Int64Value",
2074 "value": "forty-two"
2075}`,
2076 wantErr: true,
2077 }, {
2078 desc: "Any with invalid UInt64Value",
Damien Neil5c5b5312019-05-14 12:44:37 -07002079 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002080 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.UInt64Value{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002081 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002082 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002083 inputText: `{
2084 "@type": "google.protobuf.UInt64Value",
2085 "value": -42
2086}`,
2087 wantErr: true,
2088 }, {
2089 desc: "Any with Duration",
Damien Neil5c5b5312019-05-14 12:44:37 -07002090 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002091 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&durationpb.Duration{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002092 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002093 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002094 inputText: `{
2095 "@type": "type.googleapis.com/google.protobuf.Duration",
2096 "value": "0s"
2097}`,
2098 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002099 m := &durationpb.Duration{}
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002100 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2101 if err != nil {
2102 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2103 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002104 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002105 TypeUrl: "type.googleapis.com/google.protobuf.Duration",
2106 Value: b,
2107 }
2108 }(),
2109 }, {
2110 desc: "Any with Value of StringValue",
Damien Neil5c5b5312019-05-14 12:44:37 -07002111 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002112 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&structpb.Value{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002113 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002114 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002115 inputText: `{
2116 "@type": "google.protobuf.Value",
2117 "value": "` + "abc\xff" + `"
2118}`,
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002119 wantErr: true,
2120 }, {
2121 desc: "Any with Value of NullValue",
Damien Neil5c5b5312019-05-14 12:44:37 -07002122 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002123 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&structpb.Value{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002124 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002125 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002126 inputText: `{
2127 "@type": "google.protobuf.Value",
2128 "value": null
2129}`,
2130 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002131 m := &structpb.Value{Kind: &structpb.Value_NullValue{}}
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002132 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 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002136 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002137 TypeUrl: "google.protobuf.Value",
2138 Value: b,
2139 }
2140 }(),
2141 }, {
2142 desc: "Any with Struct",
Damien Neil5c5b5312019-05-14 12:44:37 -07002143 umo: protojson.UnmarshalOptions{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002144 Resolver: preg.NewTypes(
Joe Tsaia95b29f2019-05-16 12:47:20 -07002145 pimpl.Export{}.MessageTypeOf(&structpb.Struct{}),
2146 pimpl.Export{}.MessageTypeOf(&structpb.Value{}),
2147 pimpl.Export{}.MessageTypeOf(&wrapperspb.BoolValue{}),
2148 pimpl.Export{}.EnumTypeOf(structpb.NullValue_NULL_VALUE),
2149 pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{}),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002150 ),
2151 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002152 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002153 inputText: `{
2154 "@type": "google.protobuf.Struct",
2155 "value": {
2156 "bool": true,
2157 "null": null,
2158 "string": "hello",
2159 "struct": {
2160 "string": "world"
2161 }
2162 }
2163}`,
2164 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002165 m := &structpb.Struct{
2166 Fields: map[string]*structpb.Value{
2167 "bool": {Kind: &structpb.Value_BoolValue{true}},
2168 "null": {Kind: &structpb.Value_NullValue{}},
2169 "string": {Kind: &structpb.Value_StringValue{"hello"}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002170 "struct": {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002171 Kind: &structpb.Value_StructValue{
2172 &structpb.Struct{
2173 Fields: map[string]*structpb.Value{
2174 "string": {Kind: &structpb.Value_StringValue{"world"}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002175 },
2176 },
2177 },
2178 },
2179 },
2180 }
2181 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2182 if err != nil {
2183 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2184 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002185 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002186 TypeUrl: "google.protobuf.Struct",
2187 Value: b,
2188 }
2189 }(),
2190 }, {
2191 desc: "Any with missing @type",
Damien Neil5c5b5312019-05-14 12:44:37 -07002192 umo: protojson.UnmarshalOptions{},
Joe Tsaia95b29f2019-05-16 12:47:20 -07002193 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002194 inputText: `{
2195 "value": {}
2196}`,
2197 wantErr: true,
2198 }, {
2199 desc: "Any with empty @type",
Joe Tsaia95b29f2019-05-16 12:47:20 -07002200 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002201 inputText: `{
2202 "@type": ""
2203}`,
2204 wantErr: true,
2205 }, {
2206 desc: "Any with duplicate @type",
Damien Neil5c5b5312019-05-14 12:44:37 -07002207 umo: protojson.UnmarshalOptions{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002208 Resolver: preg.NewTypes(
Joe Tsai0fc49f82019-05-01 12:29:25 -07002209 pimpl.Export{}.MessageTypeOf(&pb2.Nested{}),
Joe Tsaia95b29f2019-05-16 12:47:20 -07002210 pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{}),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002211 ),
2212 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002213 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002214 inputText: `{
2215 "@type": "google.protobuf.StringValue",
2216 "value": "hello",
2217 "@type": "pb2.Nested"
2218}`,
2219 wantErr: true,
2220 }, {
2221 desc: "Any with duplicate value",
Damien Neil5c5b5312019-05-14 12:44:37 -07002222 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002223 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002224 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002225 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002226 inputText: `{
2227 "@type": "google.protobuf.StringValue",
2228 "value": "hello",
2229 "value": "world"
2230}`,
2231 wantErr: true,
2232 }, {
2233 desc: "Any with unknown field",
Damien Neil5c5b5312019-05-14 12:44:37 -07002234 umo: protojson.UnmarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07002235 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002236 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002237 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002238 inputText: `{
2239 "@type": "pb2.Nested",
2240 "optString": "hello",
2241 "unknown": "world"
2242}`,
2243 wantErr: true,
2244 }, {
2245 desc: "Any with embedded type containing Any",
Damien Neil5c5b5312019-05-14 12:44:37 -07002246 umo: protojson.UnmarshalOptions{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002247 Resolver: preg.NewTypes(
Joe Tsai0fc49f82019-05-01 12:29:25 -07002248 pimpl.Export{}.MessageTypeOf(&pb2.KnownTypes{}),
Joe Tsaia95b29f2019-05-16 12:47:20 -07002249 pimpl.Export{}.MessageTypeOf(&anypb.Any{}),
2250 pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{}),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002251 ),
2252 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002253 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002254 inputText: `{
2255 "@type": "pb2.KnownTypes",
2256 "optAny": {
2257 "@type": "google.protobuf.StringValue",
2258 "value": "` + "abc\xff" + `"
2259 }
2260}`,
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002261 wantErr: true,
2262 }, {
2263 desc: "well known types as field values",
Damien Neil5c5b5312019-05-14 12:44:37 -07002264 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002265 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002266 },
2267 inputMessage: &pb2.KnownTypes{},
2268 inputText: `{
2269 "optBool": false,
2270 "optInt32": 42,
2271 "optInt64": "42",
2272 "optUint32": 42,
2273 "optUint64": "42",
2274 "optFloat": 1.23,
2275 "optDouble": 3.1415,
2276 "optString": "hello",
2277 "optBytes": "aGVsbG8=",
2278 "optDuration": "123s",
2279 "optTimestamp": "2019-03-19T23:03:21Z",
2280 "optStruct": {
2281 "string": "hello"
2282 },
2283 "optList": [
2284 null,
2285 "",
2286 {},
2287 []
2288 ],
2289 "optValue": "world",
2290 "optEmpty": {},
2291 "optAny": {
2292 "@type": "google.protobuf.Empty",
2293 "value": {}
2294 },
2295 "optFieldmask": "fooBar,barFoo"
2296}`,
2297 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002298 OptBool: &wrapperspb.BoolValue{Value: false},
2299 OptInt32: &wrapperspb.Int32Value{Value: 42},
2300 OptInt64: &wrapperspb.Int64Value{Value: 42},
2301 OptUint32: &wrapperspb.UInt32Value{Value: 42},
2302 OptUint64: &wrapperspb.UInt64Value{Value: 42},
2303 OptFloat: &wrapperspb.FloatValue{Value: 1.23},
2304 OptDouble: &wrapperspb.DoubleValue{Value: 3.1415},
2305 OptString: &wrapperspb.StringValue{Value: "hello"},
2306 OptBytes: &wrapperspb.BytesValue{Value: []byte("hello")},
2307 OptDuration: &durationpb.Duration{Seconds: 123},
2308 OptTimestamp: &timestamppb.Timestamp{Seconds: 1553036601},
2309 OptStruct: &structpb.Struct{
2310 Fields: map[string]*structpb.Value{
2311 "string": {Kind: &structpb.Value_StringValue{"hello"}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002312 },
2313 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002314 OptList: &structpb.ListValue{
2315 Values: []*structpb.Value{
2316 {Kind: &structpb.Value_NullValue{}},
2317 {Kind: &structpb.Value_StringValue{}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002318 {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002319 Kind: &structpb.Value_StructValue{
2320 &structpb.Struct{Fields: map[string]*structpb.Value{}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002321 },
2322 },
2323 {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002324 Kind: &structpb.Value_ListValue{
2325 &structpb.ListValue{Values: []*structpb.Value{}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002326 },
2327 },
2328 },
2329 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002330 OptValue: &structpb.Value{
2331 Kind: &structpb.Value_StringValue{"world"},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002332 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002333 OptEmpty: &emptypb.Empty{},
2334 OptAny: &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002335 TypeUrl: "google.protobuf.Empty",
2336 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002337 OptFieldmask: &fieldmaskpb.FieldMask{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002338 Paths: []string{"foo_bar", "bar_foo"},
2339 },
2340 },
Herbie Ong4f0be712019-04-25 17:57:12 -07002341 }, {
2342 desc: "DiscardUnknown: regular messages",
Damien Neil5c5b5312019-05-14 12:44:37 -07002343 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Herbie Ong4f0be712019-04-25 17:57:12 -07002344 inputMessage: &pb3.Nests{},
2345 inputText: `{
2346 "sNested": {
2347 "unknown": {
2348 "foo": 1,
2349 "bar": [1, 2, 3]
2350 }
2351 },
2352 "unknown": "not known"
2353}`,
2354 wantMessage: &pb3.Nests{SNested: &pb3.Nested{}},
2355 }, {
2356 desc: "DiscardUnknown: repeated",
Damien Neil5c5b5312019-05-14 12:44:37 -07002357 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Herbie Ong4f0be712019-04-25 17:57:12 -07002358 inputMessage: &pb2.Nests{},
2359 inputText: `{
2360 "rptNested": [
2361 {"unknown": "blah"},
2362 {"optString": "hello"}
2363 ]
2364}`,
2365 wantMessage: &pb2.Nests{
2366 RptNested: []*pb2.Nested{
2367 {},
2368 {OptString: scalar.String("hello")},
2369 },
2370 },
2371 }, {
2372 desc: "DiscardUnknown: map",
Damien Neil5c5b5312019-05-14 12:44:37 -07002373 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Herbie Ong4f0be712019-04-25 17:57:12 -07002374 inputMessage: &pb3.Maps{},
2375 inputText: `{
2376 "strToNested": {
2377 "nested_one": {
2378 "unknown": "what you see is not"
2379 }
2380 }
2381}`,
2382 wantMessage: &pb3.Maps{
2383 StrToNested: map[string]*pb3.Nested{
2384 "nested_one": {},
2385 },
2386 },
2387 }, {
2388 desc: "DiscardUnknown: extension",
Damien Neil5c5b5312019-05-14 12:44:37 -07002389 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Herbie Ong4f0be712019-04-25 17:57:12 -07002390 inputMessage: &pb2.Extensions{},
2391 inputText: `{
2392 "[pb2.opt_ext_nested]": {
2393 "unknown": []
2394 }
2395}`,
2396 wantMessage: func() proto.Message {
2397 m := &pb2.Extensions{}
2398 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{})
2399 return m
2400 }(),
2401 }, {
2402 desc: "DiscardUnknown: Empty",
Damien Neil5c5b5312019-05-14 12:44:37 -07002403 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Joe Tsaia95b29f2019-05-16 12:47:20 -07002404 inputMessage: &emptypb.Empty{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002405 inputText: `{"unknown": "something"}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002406 wantMessage: &emptypb.Empty{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002407 }, {
2408 desc: "DiscardUnknown: Any without type",
Damien Neil5c5b5312019-05-14 12:44:37 -07002409 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Joe Tsaia95b29f2019-05-16 12:47:20 -07002410 inputMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002411 inputText: `{
2412 "value": {"foo": "bar"},
2413 "unknown": true
2414}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002415 wantMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002416 }, {
2417 desc: "DiscardUnknown: Any",
Damien Neil5c5b5312019-05-14 12:44:37 -07002418 umo: protojson.UnmarshalOptions{
Herbie Ong4f0be712019-04-25 17:57:12 -07002419 DiscardUnknown: true,
Joe Tsai0fc49f82019-05-01 12:29:25 -07002420 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong4f0be712019-04-25 17:57:12 -07002421 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002422 inputMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002423 inputText: `{
2424 "@type": "foo/pb2.Nested",
2425 "unknown": "none"
2426}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002427 wantMessage: &anypb.Any{
Herbie Ong4f0be712019-04-25 17:57:12 -07002428 TypeUrl: "foo/pb2.Nested",
2429 },
2430 }, {
2431 desc: "DiscardUnknown: Any with Empty",
Damien Neil5c5b5312019-05-14 12:44:37 -07002432 umo: protojson.UnmarshalOptions{
Herbie Ong4f0be712019-04-25 17:57:12 -07002433 DiscardUnknown: true,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002434 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
Herbie Ong4f0be712019-04-25 17:57:12 -07002435 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002436 inputMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002437 inputText: `{
2438 "@type": "type.googleapis.com/google.protobuf.Empty",
2439 "value": {"unknown": 47}
2440}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002441 wantMessage: &anypb.Any{
Herbie Ong4f0be712019-04-25 17:57:12 -07002442 TypeUrl: "type.googleapis.com/google.protobuf.Empty",
2443 },
Herbie Ongc96a79d2019-03-08 10:49:17 -08002444 }}
2445
2446 for _, tt := range tests {
2447 tt := tt
2448 t.Run(tt.desc, func(t *testing.T) {
Joe Tsaicdb77732019-05-14 16:05:06 -07002449 err := tt.umo.Unmarshal([]byte(tt.inputText), tt.inputMessage)
Herbie Ongc96a79d2019-03-08 10:49:17 -08002450 if err != nil && !tt.wantErr {
2451 t.Errorf("Unmarshal() returned error: %v\n\n", err)
2452 }
2453 if err == nil && tt.wantErr {
2454 t.Error("Unmarshal() got nil error, want error\n\n")
2455 }
Joe Tsai8d30bbe2019-05-16 15:53:25 -07002456 if tt.wantMessage != nil && !proto.Equal(tt.inputMessage, tt.wantMessage) {
Herbie Ongc96a79d2019-03-08 10:49:17 -08002457 t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", tt.inputMessage, tt.wantMessage)
2458 }
2459 })
2460 }
2461}