blob: b713a3819158d53cb542a002fea0d6b6a0ee34a4 [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 (
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 Neil5c5b5312019-05-14 12:44:37 -070013 "google.golang.org/protobuf/encoding/protojson"
Damien Neile89e6242019-05-13 23:55:40 -070014 "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
Joe Tsaia95b29f2019-05-16 12:47:20 -070022 "google.golang.org/protobuf/types/known/anypb"
23 "google.golang.org/protobuf/types/known/durationpb"
24 "google.golang.org/protobuf/types/known/emptypb"
25 "google.golang.org/protobuf/types/known/fieldmaskpb"
26 "google.golang.org/protobuf/types/known/structpb"
27 "google.golang.org/protobuf/types/known/timestamppb"
28 "google.golang.org/protobuf/types/known/wrapperspb"
Herbie Ongc96a79d2019-03-08 10:49:17 -080029)
30
Herbie Onge52379a2019-03-15 18:00:19 -070031func init() {
32 // TODO: remove these registerExtension calls when generated code registers
33 // to V2 global registry.
34 registerExtension(pb2.E_OptExtBool)
35 registerExtension(pb2.E_OptExtString)
36 registerExtension(pb2.E_OptExtEnum)
37 registerExtension(pb2.E_OptExtNested)
38 registerExtension(pb2.E_RptExtFixed32)
39 registerExtension(pb2.E_RptExtEnum)
40 registerExtension(pb2.E_RptExtNested)
41 registerExtension(pb2.E_ExtensionsContainer_OptExtBool)
42 registerExtension(pb2.E_ExtensionsContainer_OptExtString)
43 registerExtension(pb2.E_ExtensionsContainer_OptExtEnum)
44 registerExtension(pb2.E_ExtensionsContainer_OptExtNested)
45 registerExtension(pb2.E_ExtensionsContainer_RptExtString)
46 registerExtension(pb2.E_ExtensionsContainer_RptExtEnum)
47 registerExtension(pb2.E_ExtensionsContainer_RptExtNested)
48 registerExtension(pb2.E_MessageSetExtension)
49 registerExtension(pb2.E_MessageSetExtension_MessageSetExtension)
50 registerExtension(pb2.E_MessageSetExtension_NotMessageSetExtension)
51 registerExtension(pb2.E_MessageSetExtension_ExtNested)
52 registerExtension(pb2.E_FakeMessageSetExtension_MessageSetExtension)
53}
54
Joe Tsai4fddeba2019-03-20 18:29:32 -070055func registerExtension(xd *protoiface.ExtensionDescV1) {
Herbie Onge52379a2019-03-15 18:00:19 -070056 preg.GlobalTypes.Register(xd.Type)
57}
58
Herbie Ongc96a79d2019-03-08 10:49:17 -080059func TestUnmarshal(t *testing.T) {
60 tests := []struct {
61 desc string
Damien Neil5c5b5312019-05-14 12:44:37 -070062 umo protojson.UnmarshalOptions
Herbie Ongc96a79d2019-03-08 10:49:17 -080063 inputMessage proto.Message
64 inputText string
65 wantMessage proto.Message
66 // TODO: verify expected error message substring.
67 wantErr bool
68 }{{
69 desc: "proto2 empty message",
70 inputMessage: &pb2.Scalars{},
71 inputText: "{}",
72 wantMessage: &pb2.Scalars{},
73 }, {
74 desc: "unexpected value instead of EOF",
75 inputMessage: &pb2.Scalars{},
76 inputText: "{} {}",
77 wantErr: true,
78 }, {
79 desc: "proto2 optional scalars set to zero values",
80 inputMessage: &pb2.Scalars{},
81 inputText: `{
82 "optBool": false,
83 "optInt32": 0,
84 "optInt64": 0,
85 "optUint32": 0,
86 "optUint64": 0,
87 "optSint32": 0,
88 "optSint64": 0,
89 "optFixed32": 0,
90 "optFixed64": 0,
91 "optSfixed32": 0,
92 "optSfixed64": 0,
93 "optFloat": 0,
94 "optDouble": 0,
95 "optBytes": "",
96 "optString": ""
97}`,
98 wantMessage: &pb2.Scalars{
99 OptBool: scalar.Bool(false),
100 OptInt32: scalar.Int32(0),
101 OptInt64: scalar.Int64(0),
102 OptUint32: scalar.Uint32(0),
103 OptUint64: scalar.Uint64(0),
104 OptSint32: scalar.Int32(0),
105 OptSint64: scalar.Int64(0),
106 OptFixed32: scalar.Uint32(0),
107 OptFixed64: scalar.Uint64(0),
108 OptSfixed32: scalar.Int32(0),
109 OptSfixed64: scalar.Int64(0),
110 OptFloat: scalar.Float32(0),
111 OptDouble: scalar.Float64(0),
112 OptBytes: []byte{},
113 OptString: scalar.String(""),
114 },
115 }, {
116 desc: "proto3 scalars set to zero values",
117 inputMessage: &pb3.Scalars{},
118 inputText: `{
119 "sBool": false,
120 "sInt32": 0,
121 "sInt64": 0,
122 "sUint32": 0,
123 "sUint64": 0,
124 "sSint32": 0,
125 "sSint64": 0,
126 "sFixed32": 0,
127 "sFixed64": 0,
128 "sSfixed32": 0,
129 "sSfixed64": 0,
130 "sFloat": 0,
131 "sDouble": 0,
132 "sBytes": "",
133 "sString": ""
134}`,
135 wantMessage: &pb3.Scalars{},
136 }, {
137 desc: "proto2 optional scalars set to null",
138 inputMessage: &pb2.Scalars{},
139 inputText: `{
140 "optBool": null,
141 "optInt32": null,
142 "optInt64": null,
143 "optUint32": null,
144 "optUint64": null,
145 "optSint32": null,
146 "optSint64": null,
147 "optFixed32": null,
148 "optFixed64": null,
149 "optSfixed32": null,
150 "optSfixed64": null,
151 "optFloat": null,
152 "optDouble": null,
153 "optBytes": null,
154 "optString": null
155}`,
156 wantMessage: &pb2.Scalars{},
157 }, {
158 desc: "proto3 scalars set to null",
159 inputMessage: &pb3.Scalars{},
160 inputText: `{
161 "sBool": null,
162 "sInt32": null,
163 "sInt64": null,
164 "sUint32": null,
165 "sUint64": null,
166 "sSint32": null,
167 "sSint64": null,
168 "sFixed32": null,
169 "sFixed64": null,
170 "sSfixed32": null,
171 "sSfixed64": null,
172 "sFloat": null,
173 "sDouble": null,
174 "sBytes": null,
175 "sString": null
176}`,
177 wantMessage: &pb3.Scalars{},
178 }, {
179 desc: "boolean",
180 inputMessage: &pb3.Scalars{},
181 inputText: `{"sBool": true}`,
182 wantMessage: &pb3.Scalars{
183 SBool: true,
184 },
185 }, {
186 desc: "not boolean",
187 inputMessage: &pb3.Scalars{},
188 inputText: `{"sBool": "true"}`,
189 wantErr: true,
190 }, {
191 desc: "float and double",
192 inputMessage: &pb3.Scalars{},
193 inputText: `{
194 "sFloat": 1.234,
195 "sDouble": 5.678
196}`,
197 wantMessage: &pb3.Scalars{
198 SFloat: 1.234,
199 SDouble: 5.678,
200 },
201 }, {
202 desc: "float and double in string",
203 inputMessage: &pb3.Scalars{},
204 inputText: `{
205 "sFloat": "1.234",
206 "sDouble": "5.678"
207}`,
208 wantMessage: &pb3.Scalars{
209 SFloat: 1.234,
210 SDouble: 5.678,
211 },
212 }, {
213 desc: "float and double in E notation",
214 inputMessage: &pb3.Scalars{},
215 inputText: `{
216 "sFloat": 12.34E-1,
217 "sDouble": 5.678e4
218}`,
219 wantMessage: &pb3.Scalars{
220 SFloat: 1.234,
221 SDouble: 56780,
222 },
223 }, {
224 desc: "float and double in string E notation",
225 inputMessage: &pb3.Scalars{},
226 inputText: `{
227 "sFloat": "12.34E-1",
228 "sDouble": "5.678e4"
229}`,
230 wantMessage: &pb3.Scalars{
231 SFloat: 1.234,
232 SDouble: 56780,
233 },
234 }, {
235 desc: "float exceeds limit",
236 inputMessage: &pb3.Scalars{},
237 inputText: `{"sFloat": 3.4e39}`,
238 wantErr: true,
239 }, {
240 desc: "float in string exceeds limit",
241 inputMessage: &pb3.Scalars{},
242 inputText: `{"sFloat": "-3.4e39"}`,
243 wantErr: true,
244 }, {
245 desc: "double exceeds limit",
246 inputMessage: &pb3.Scalars{},
247 inputText: `{"sFloat": -1.79e+309}`,
248 wantErr: true,
249 }, {
250 desc: "double in string exceeds limit",
251 inputMessage: &pb3.Scalars{},
252 inputText: `{"sFloat": "1.79e+309"}`,
253 wantErr: true,
254 }, {
255 desc: "infinites",
256 inputMessage: &pb3.Scalars{},
257 inputText: `{"sFloat": "Infinity", "sDouble": "-Infinity"}`,
258 wantMessage: &pb3.Scalars{
259 SFloat: float32(math.Inf(+1)),
260 SDouble: math.Inf(-1),
261 },
262 }, {
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700263 desc: "float string with leading space",
264 inputMessage: &pb3.Scalars{},
265 inputText: `{"sFloat": " 1.234"}`,
266 wantErr: true,
267 }, {
268 desc: "double string with trailing space",
269 inputMessage: &pb3.Scalars{},
270 inputText: `{"sDouble": "5.678 "}`,
271 wantErr: true,
272 }, {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800273 desc: "not float",
274 inputMessage: &pb3.Scalars{},
275 inputText: `{"sFloat": true}`,
276 wantErr: true,
277 }, {
278 desc: "not double",
279 inputMessage: &pb3.Scalars{},
280 inputText: `{"sDouble": "not a number"}`,
281 wantErr: true,
282 }, {
283 desc: "integers",
284 inputMessage: &pb3.Scalars{},
285 inputText: `{
286 "sInt32": 1234,
287 "sInt64": -1234,
288 "sUint32": 1e2,
289 "sUint64": 100E-2,
290 "sSint32": 1.0,
291 "sSint64": -1.0,
292 "sFixed32": 1.234e+5,
293 "sFixed64": 1200E-2,
294 "sSfixed32": -1.234e05,
295 "sSfixed64": -1200e-02
296}`,
297 wantMessage: &pb3.Scalars{
298 SInt32: 1234,
299 SInt64: -1234,
300 SUint32: 100,
301 SUint64: 1,
302 SSint32: 1,
303 SSint64: -1,
304 SFixed32: 123400,
305 SFixed64: 12,
306 SSfixed32: -123400,
307 SSfixed64: -12,
308 },
309 }, {
310 desc: "integers in string",
311 inputMessage: &pb3.Scalars{},
312 inputText: `{
313 "sInt32": "1234",
314 "sInt64": "-1234",
315 "sUint32": "1e2",
316 "sUint64": "100E-2",
317 "sSint32": "1.0",
318 "sSint64": "-1.0",
319 "sFixed32": "1.234e+5",
320 "sFixed64": "1200E-2",
321 "sSfixed32": "-1.234e05",
322 "sSfixed64": "-1200e-02"
323}`,
324 wantMessage: &pb3.Scalars{
325 SInt32: 1234,
326 SInt64: -1234,
327 SUint32: 100,
328 SUint64: 1,
329 SSint32: 1,
330 SSint64: -1,
331 SFixed32: 123400,
332 SFixed64: 12,
333 SSfixed32: -123400,
334 SSfixed64: -12,
335 },
336 }, {
337 desc: "integers in escaped string",
338 inputMessage: &pb3.Scalars{},
339 inputText: `{"sInt32": "\u0031\u0032"}`,
340 wantMessage: &pb3.Scalars{
341 SInt32: 12,
342 },
343 }, {
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700344 desc: "integer string with leading space",
345 inputMessage: &pb3.Scalars{},
346 inputText: `{"sInt32": " 1234"}`,
347 wantErr: true,
348 }, {
349 desc: "integer string with trailing space",
350 inputMessage: &pb3.Scalars{},
351 inputText: `{"sUint32": "1e2 "}`,
352 wantErr: true,
353 }, {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800354 desc: "number is not an integer",
355 inputMessage: &pb3.Scalars{},
356 inputText: `{"sInt32": 1.001}`,
357 wantErr: true,
358 }, {
359 desc: "32-bit int exceeds limit",
360 inputMessage: &pb3.Scalars{},
361 inputText: `{"sInt32": 2e10}`,
362 wantErr: true,
363 }, {
364 desc: "64-bit int exceeds limit",
365 inputMessage: &pb3.Scalars{},
366 inputText: `{"sSfixed64": -9e19}`,
367 wantErr: true,
368 }, {
369 desc: "not integer",
370 inputMessage: &pb3.Scalars{},
371 inputText: `{"sInt32": "not a number"}`,
372 wantErr: true,
373 }, {
374 desc: "not unsigned integer",
375 inputMessage: &pb3.Scalars{},
376 inputText: `{"sUint32": "not a number"}`,
377 wantErr: true,
378 }, {
379 desc: "number is not an unsigned integer",
380 inputMessage: &pb3.Scalars{},
381 inputText: `{"sUint32": -1}`,
382 wantErr: true,
383 }, {
384 desc: "string",
385 inputMessage: &pb2.Scalars{},
386 inputText: `{"optString": "谷歌"}`,
387 wantMessage: &pb2.Scalars{
388 OptString: scalar.String("谷歌"),
389 },
390 }, {
391 desc: "string with invalid UTF-8",
392 inputMessage: &pb3.Scalars{},
393 inputText: "{\"sString\": \"\xff\"}",
394 wantMessage: &pb3.Scalars{
395 SString: "\xff",
396 },
397 wantErr: true,
398 }, {
399 desc: "not string",
400 inputMessage: &pb2.Scalars{},
401 inputText: `{"optString": 42}`,
402 wantErr: true,
403 }, {
404 desc: "bytes",
405 inputMessage: &pb3.Scalars{},
406 inputText: `{"sBytes": "aGVsbG8gd29ybGQ"}`,
407 wantMessage: &pb3.Scalars{
408 SBytes: []byte("hello world"),
409 },
410 }, {
411 desc: "bytes padded",
412 inputMessage: &pb3.Scalars{},
413 inputText: `{"sBytes": "aGVsbG8gd29ybGQ="}`,
414 wantMessage: &pb3.Scalars{
415 SBytes: []byte("hello world"),
416 },
417 }, {
418 desc: "not bytes",
419 inputMessage: &pb3.Scalars{},
420 inputText: `{"sBytes": true}`,
421 wantErr: true,
422 }, {
423 desc: "proto2 enum",
424 inputMessage: &pb2.Enums{},
425 inputText: `{
426 "optEnum": "ONE",
427 "optNestedEnum": "UNO"
428}`,
429 wantMessage: &pb2.Enums{
430 OptEnum: pb2.Enum_ONE.Enum(),
431 OptNestedEnum: pb2.Enums_UNO.Enum(),
432 },
433 }, {
434 desc: "proto3 enum",
435 inputMessage: &pb3.Enums{},
436 inputText: `{
437 "sEnum": "ONE",
438 "sNestedEnum": "DIEZ"
439}`,
440 wantMessage: &pb3.Enums{
441 SEnum: pb3.Enum_ONE,
442 SNestedEnum: pb3.Enums_DIEZ,
443 },
444 }, {
445 desc: "enum numeric value",
446 inputMessage: &pb3.Enums{},
447 inputText: `{
448 "sEnum": 2,
449 "sNestedEnum": 2
450}`,
451 wantMessage: &pb3.Enums{
452 SEnum: pb3.Enum_TWO,
453 SNestedEnum: pb3.Enums_DOS,
454 },
455 }, {
456 desc: "enum unnamed numeric value",
457 inputMessage: &pb3.Enums{},
458 inputText: `{
459 "sEnum": 101,
460 "sNestedEnum": -101
461}`,
462 wantMessage: &pb3.Enums{
463 SEnum: 101,
464 SNestedEnum: -101,
465 },
466 }, {
467 desc: "enum set to number string",
468 inputMessage: &pb3.Enums{},
469 inputText: `{
Herbie Ong300b9fe2019-03-29 15:42:20 -0700470 "sEnum": "1"
Herbie Ongc96a79d2019-03-08 10:49:17 -0800471}`,
472 wantErr: true,
473 }, {
474 desc: "enum set to invalid named",
475 inputMessage: &pb3.Enums{},
476 inputText: `{
Herbie Ong300b9fe2019-03-29 15:42:20 -0700477 "sEnum": "UNNAMED"
Herbie Ongc96a79d2019-03-08 10:49:17 -0800478}`,
479 wantErr: true,
480 }, {
481 desc: "enum set to not enum",
482 inputMessage: &pb3.Enums{},
483 inputText: `{
Herbie Ong300b9fe2019-03-29 15:42:20 -0700484 "sEnum": true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800485}`,
486 wantErr: true,
487 }, {
Herbie Ong300b9fe2019-03-29 15:42:20 -0700488 desc: "enum set to JSON null",
489 inputMessage: &pb3.Enums{},
490 inputText: `{
491 "sEnum": null
492}`,
493 wantMessage: &pb3.Enums{},
494 }, {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800495 desc: "proto name",
496 inputMessage: &pb3.JSONNames{},
497 inputText: `{
498 "s_string": "proto name used"
499}`,
500 wantMessage: &pb3.JSONNames{
501 SString: "proto name used",
502 },
503 }, {
504 desc: "json_name",
505 inputMessage: &pb3.JSONNames{},
506 inputText: `{
507 "foo_bar": "json_name used"
508}`,
509 wantMessage: &pb3.JSONNames{
510 SString: "json_name used",
511 },
512 }, {
513 desc: "camelCase name",
514 inputMessage: &pb3.JSONNames{},
515 inputText: `{
516 "sString": "camelcase used"
517}`,
518 wantErr: true,
519 }, {
520 desc: "proto name and json_name",
521 inputMessage: &pb3.JSONNames{},
522 inputText: `{
523 "foo_bar": "json_name used",
524 "s_string": "proto name used"
525}`,
526 wantErr: true,
527 }, {
528 desc: "duplicate field names",
529 inputMessage: &pb3.JSONNames{},
530 inputText: `{
531 "foo_bar": "one",
532 "foo_bar": "two",
533}`,
534 wantErr: true,
535 }, {
536 desc: "null message",
537 inputMessage: &pb2.Nests{},
538 inputText: "null",
539 wantErr: true,
540 }, {
541 desc: "proto2 nested message not set",
542 inputMessage: &pb2.Nests{},
543 inputText: "{}",
544 wantMessage: &pb2.Nests{},
545 }, {
546 desc: "proto2 nested message set to null",
547 inputMessage: &pb2.Nests{},
548 inputText: `{
549 "optNested": null,
550 "optgroup": null
551}`,
552 wantMessage: &pb2.Nests{},
553 }, {
554 desc: "proto2 nested message set to empty",
555 inputMessage: &pb2.Nests{},
556 inputText: `{
557 "optNested": {},
558 "optgroup": {}
559}`,
560 wantMessage: &pb2.Nests{
561 OptNested: &pb2.Nested{},
562 Optgroup: &pb2.Nests_OptGroup{},
563 },
564 }, {
565 desc: "proto2 nested messages",
566 inputMessage: &pb2.Nests{},
567 inputText: `{
568 "optNested": {
569 "optString": "nested message",
570 "optNested": {
571 "optString": "another nested message"
572 }
573 }
574}`,
575 wantMessage: &pb2.Nests{
576 OptNested: &pb2.Nested{
577 OptString: scalar.String("nested message"),
578 OptNested: &pb2.Nested{
579 OptString: scalar.String("another nested message"),
580 },
581 },
582 },
583 }, {
584 desc: "proto2 groups",
585 inputMessage: &pb2.Nests{},
586 inputText: `{
587 "optgroup": {
588 "optString": "inside a group",
589 "optNested": {
590 "optString": "nested message inside a group"
591 },
592 "optnestedgroup": {
593 "optFixed32": 47
594 }
595 }
596}`,
597 wantMessage: &pb2.Nests{
598 Optgroup: &pb2.Nests_OptGroup{
599 OptString: scalar.String("inside a group"),
600 OptNested: &pb2.Nested{
601 OptString: scalar.String("nested message inside a group"),
602 },
603 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
604 OptFixed32: scalar.Uint32(47),
605 },
606 },
607 },
608 }, {
609 desc: "proto3 nested message not set",
610 inputMessage: &pb3.Nests{},
611 inputText: "{}",
612 wantMessage: &pb3.Nests{},
613 }, {
614 desc: "proto3 nested message set to null",
615 inputMessage: &pb3.Nests{},
616 inputText: `{"sNested": null}`,
617 wantMessage: &pb3.Nests{},
618 }, {
619 desc: "proto3 nested message set to empty",
620 inputMessage: &pb3.Nests{},
621 inputText: `{"sNested": {}}`,
622 wantMessage: &pb3.Nests{
623 SNested: &pb3.Nested{},
624 },
625 }, {
626 desc: "proto3 nested message",
627 inputMessage: &pb3.Nests{},
628 inputText: `{
629 "sNested": {
630 "sString": "nested message",
631 "sNested": {
632 "sString": "another nested message"
633 }
634 }
635}`,
636 wantMessage: &pb3.Nests{
637 SNested: &pb3.Nested{
638 SString: "nested message",
639 SNested: &pb3.Nested{
640 SString: "another nested message",
641 },
642 },
643 },
644 }, {
645 desc: "message set to non-message",
646 inputMessage: &pb3.Nests{},
647 inputText: `"not valid"`,
648 wantErr: true,
649 }, {
650 desc: "nested message set to non-message",
651 inputMessage: &pb3.Nests{},
652 inputText: `{"sNested": true}`,
653 wantErr: true,
654 }, {
655 desc: "oneof not set",
656 inputMessage: &pb3.Oneofs{},
657 inputText: "{}",
658 wantMessage: &pb3.Oneofs{},
659 }, {
660 desc: "oneof set to empty string",
661 inputMessage: &pb3.Oneofs{},
662 inputText: `{"oneofString": ""}`,
663 wantMessage: &pb3.Oneofs{
664 Union: &pb3.Oneofs_OneofString{},
665 },
666 }, {
667 desc: "oneof set to string",
668 inputMessage: &pb3.Oneofs{},
669 inputText: `{"oneofString": "hello"}`,
670 wantMessage: &pb3.Oneofs{
671 Union: &pb3.Oneofs_OneofString{
672 OneofString: "hello",
673 },
674 },
675 }, {
676 desc: "oneof set to enum",
677 inputMessage: &pb3.Oneofs{},
678 inputText: `{"oneofEnum": "ZERO"}`,
679 wantMessage: &pb3.Oneofs{
680 Union: &pb3.Oneofs_OneofEnum{
681 OneofEnum: pb3.Enum_ZERO,
682 },
683 },
684 }, {
685 desc: "oneof set to empty message",
686 inputMessage: &pb3.Oneofs{},
687 inputText: `{"oneofNested": {}}`,
688 wantMessage: &pb3.Oneofs{
689 Union: &pb3.Oneofs_OneofNested{
690 OneofNested: &pb3.Nested{},
691 },
692 },
693 }, {
694 desc: "oneof set to message",
695 inputMessage: &pb3.Oneofs{},
696 inputText: `{
697 "oneofNested": {
698 "sString": "nested message"
699 }
700}`,
701 wantMessage: &pb3.Oneofs{
702 Union: &pb3.Oneofs_OneofNested{
703 OneofNested: &pb3.Nested{
704 SString: "nested message",
705 },
706 },
707 },
708 }, {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700709 desc: "oneof set to more than one field",
710 inputMessage: &pb3.Oneofs{},
711 inputText: `{
712 "oneofEnum": "ZERO",
713 "oneofString": "hello"
714}`,
715 wantErr: true,
716 }, {
717 desc: "oneof set to null and value",
718 inputMessage: &pb3.Oneofs{},
719 inputText: `{
720 "oneofEnum": "ZERO",
721 "oneofString": null
722}`,
723 wantMessage: &pb3.Oneofs{
724 Union: &pb3.Oneofs_OneofEnum{
725 OneofEnum: pb3.Enum_ZERO,
726 },
727 },
728 }, {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800729 desc: "repeated null fields",
730 inputMessage: &pb2.Repeats{},
731 inputText: `{
732 "rptString": null,
733 "rptInt32" : null,
734 "rptFloat" : null,
735 "rptBytes" : null
736}`,
737 wantMessage: &pb2.Repeats{},
738 }, {
739 desc: "repeated scalars",
740 inputMessage: &pb2.Repeats{},
741 inputText: `{
742 "rptString": ["hello", "world"],
743 "rptInt32" : [-1, 0, 1],
744 "rptBool" : [false, true]
745}`,
746 wantMessage: &pb2.Repeats{
747 RptString: []string{"hello", "world"},
748 RptInt32: []int32{-1, 0, 1},
749 RptBool: []bool{false, true},
750 },
751 }, {
752 desc: "repeated enums",
753 inputMessage: &pb2.Enums{},
754 inputText: `{
755 "rptEnum" : ["TEN", 1, 42],
756 "rptNestedEnum": ["DOS", 2, -47]
757}`,
758 wantMessage: &pb2.Enums{
759 RptEnum: []pb2.Enum{pb2.Enum_TEN, pb2.Enum_ONE, 42},
760 RptNestedEnum: []pb2.Enums_NestedEnum{pb2.Enums_DOS, pb2.Enums_DOS, -47},
761 },
762 }, {
763 desc: "repeated messages",
764 inputMessage: &pb2.Nests{},
765 inputText: `{
766 "rptNested": [
767 {
768 "optString": "repeat nested one"
769 },
770 {
771 "optString": "repeat nested two",
772 "optNested": {
773 "optString": "inside repeat nested two"
774 }
775 },
776 {}
777 ]
778}`,
779 wantMessage: &pb2.Nests{
780 RptNested: []*pb2.Nested{
781 {
782 OptString: scalar.String("repeat nested one"),
783 },
784 {
785 OptString: scalar.String("repeat nested two"),
786 OptNested: &pb2.Nested{
787 OptString: scalar.String("inside repeat nested two"),
788 },
789 },
790 {},
791 },
792 },
793 }, {
794 desc: "repeated groups",
795 inputMessage: &pb2.Nests{},
796 inputText: `{
797 "rptgroup": [
798 {
799 "rptString": ["hello", "world"]
800 },
801 {}
802 ]
803}
804`,
805 wantMessage: &pb2.Nests{
806 Rptgroup: []*pb2.Nests_RptGroup{
807 {
808 RptString: []string{"hello", "world"},
809 },
810 {},
811 },
812 },
813 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -0700814 desc: "repeated string contains invalid UTF8",
815 inputMessage: &pb2.Repeats{},
816 inputText: `{"rptString": ["` + "abc\xff" + `"]}`,
817 wantMessage: &pb2.Repeats{
818 RptString: []string{"abc\xff"},
819 },
820 wantErr: true,
821 }, {
822 desc: "repeated messages contain invalid UTF8",
823 inputMessage: &pb2.Nests{},
824 inputText: `{"rptNested": [{"optString": "` + "abc\xff" + `"}]}`,
825 wantMessage: &pb2.Nests{
826 RptNested: []*pb2.Nested{{OptString: scalar.String("abc\xff")}},
827 },
828 wantErr: true,
829 }, {
830 desc: "repeated scalars contain invalid type",
Herbie Ongc96a79d2019-03-08 10:49:17 -0800831 inputMessage: &pb2.Repeats{},
832 inputText: `{"rptString": ["hello", null, "world"]}`,
833 wantErr: true,
834 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -0700835 desc: "repeated messages contain invalid type",
Herbie Ongc96a79d2019-03-08 10:49:17 -0800836 inputMessage: &pb2.Nests{},
837 inputText: `{"rptNested": [{}, null]}`,
838 wantErr: true,
839 }, {
840 desc: "map fields 1",
841 inputMessage: &pb3.Maps{},
842 inputText: `{
843 "int32ToStr": {
844 "-101": "-101",
845 "0" : "zero",
846 "255" : "0xff"
847 },
848 "boolToUint32": {
849 "false": 101,
850 "true" : "42"
851 }
852}`,
853 wantMessage: &pb3.Maps{
854 Int32ToStr: map[int32]string{
855 -101: "-101",
856 0xff: "0xff",
857 0: "zero",
858 },
859 BoolToUint32: map[bool]uint32{
860 true: 42,
861 false: 101,
862 },
863 },
864 }, {
865 desc: "map fields 2",
866 inputMessage: &pb3.Maps{},
867 inputText: `{
868 "uint64ToEnum": {
869 "1" : "ONE",
870 "2" : 2,
871 "10": 101
872 }
873}`,
874 wantMessage: &pb3.Maps{
875 Uint64ToEnum: map[uint64]pb3.Enum{
876 1: pb3.Enum_ONE,
877 2: pb3.Enum_TWO,
878 10: 101,
879 },
880 },
881 }, {
882 desc: "map fields 3",
883 inputMessage: &pb3.Maps{},
884 inputText: `{
885 "strToNested": {
886 "nested_one": {
887 "sString": "nested in a map"
888 },
889 "nested_two": {}
890 }
891}`,
892 wantMessage: &pb3.Maps{
893 StrToNested: map[string]*pb3.Nested{
894 "nested_one": {
895 SString: "nested in a map",
896 },
897 "nested_two": {},
898 },
899 },
900 }, {
901 desc: "map fields 4",
902 inputMessage: &pb3.Maps{},
903 inputText: `{
904 "strToOneofs": {
905 "nested": {
906 "oneofNested": {
907 "sString": "nested oneof in map field value"
908 }
909 },
910 "string": {
911 "oneofString": "hello"
912 }
913 }
914}`,
915 wantMessage: &pb3.Maps{
916 StrToOneofs: map[string]*pb3.Oneofs{
917 "string": {
918 Union: &pb3.Oneofs_OneofString{
919 OneofString: "hello",
920 },
921 },
922 "nested": {
923 Union: &pb3.Oneofs_OneofNested{
924 OneofNested: &pb3.Nested{
925 SString: "nested oneof in map field value",
926 },
927 },
928 },
929 },
930 },
931 }, {
932 desc: "map contains duplicate keys",
933 inputMessage: &pb3.Maps{},
934 inputText: `{
935 "int32ToStr": {
936 "0": "cero",
937 "0": "zero"
938 }
939}
940`,
941 wantErr: true,
942 }, {
943 desc: "map key empty string",
944 inputMessage: &pb3.Maps{},
945 inputText: `{
946 "strToNested": {
947 "": {}
948 }
949}`,
950 wantMessage: &pb3.Maps{
951 StrToNested: map[string]*pb3.Nested{
952 "": {},
953 },
954 },
955 }, {
956 desc: "map contains invalid key 1",
957 inputMessage: &pb3.Maps{},
958 inputText: `{
959 "int32ToStr": {
960 "invalid": "cero"
961}`,
962 wantErr: true,
963 }, {
964 desc: "map contains invalid key 2",
965 inputMessage: &pb3.Maps{},
966 inputText: `{
967 "int32ToStr": {
968 "1.02": "float"
969}`,
970 wantErr: true,
971 }, {
972 desc: "map contains invalid key 3",
973 inputMessage: &pb3.Maps{},
974 inputText: `{
975 "int32ToStr": {
976 "2147483648": "exceeds 32-bit integer max limit"
977}`,
978 wantErr: true,
979 }, {
980 desc: "map contains invalid key 4",
981 inputMessage: &pb3.Maps{},
982 inputText: `{
983 "uint64ToEnum": {
984 "-1": 0
985 }
986}`,
987 wantErr: true,
988 }, {
989 desc: "map contains invalid value",
990 inputMessage: &pb3.Maps{},
991 inputText: `{
992 "int32ToStr": {
993 "101": true
994}`,
995 wantErr: true,
996 }, {
997 desc: "map contains null for scalar value",
998 inputMessage: &pb3.Maps{},
999 inputText: `{
1000 "int32ToStr": {
1001 "101": null
1002}`,
1003 wantErr: true,
1004 }, {
1005 desc: "map contains null for message value",
1006 inputMessage: &pb3.Maps{},
1007 inputText: `{
1008 "strToNested": {
1009 "hello": null
1010 }
1011}`,
1012 wantErr: true,
Herbie Onge52379a2019-03-15 18:00:19 -07001013 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -07001014 desc: "map contains contains message value with invalid UTF8",
1015 inputMessage: &pb3.Maps{},
1016 inputText: `{
1017 "strToNested": {
1018 "hello": {
1019 "sString": "` + "abc\xff" + `"
1020 }
1021 }
1022}`,
1023 wantMessage: &pb3.Maps{
1024 StrToNested: map[string]*pb3.Nested{
1025 "hello": {SString: "abc\xff"},
1026 },
1027 },
1028 wantErr: true,
1029 }, {
1030 desc: "map key contains invalid UTF8",
1031 inputMessage: &pb3.Maps{},
1032 inputText: `{
1033 "strToNested": {
1034 "` + "abc\xff" + `": {}
1035 }
1036}`,
1037 wantMessage: &pb3.Maps{
1038 StrToNested: map[string]*pb3.Nested{
1039 "abc\xff": {},
1040 },
1041 },
1042 wantErr: true,
1043 }, {
Herbie Ong329be5b2019-03-27 14:47:59 -07001044 desc: "required fields not set",
1045 inputMessage: &pb2.Requireds{},
1046 wantErr: true,
1047 }, {
1048 desc: "required field set",
1049 inputMessage: &pb2.PartialRequired{},
1050 inputText: `{
1051 "reqString": "this is required"
1052}`,
1053 wantMessage: &pb2.PartialRequired{
1054 ReqString: scalar.String("this is required"),
1055 },
1056 }, {
1057 desc: "required fields partially set",
1058 inputMessage: &pb2.Requireds{},
1059 inputText: `{
1060 "reqBool": false,
1061 "reqSfixed64": 42,
1062 "reqString": "hello",
1063 "reqEnum": "ONE"
1064}`,
1065 wantMessage: &pb2.Requireds{
1066 ReqBool: scalar.Bool(false),
1067 ReqSfixed64: scalar.Int64(42),
1068 ReqString: scalar.String("hello"),
1069 ReqEnum: pb2.Enum_ONE.Enum(),
1070 },
1071 wantErr: true,
1072 }, {
1073 desc: "required fields partially set with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07001074 umo: protojson.UnmarshalOptions{AllowPartial: true},
Herbie Ong329be5b2019-03-27 14:47:59 -07001075 inputMessage: &pb2.Requireds{},
1076 inputText: `{
1077 "reqBool": false,
1078 "reqSfixed64": 42,
1079 "reqString": "hello",
1080 "reqEnum": "ONE"
1081}`,
1082 wantMessage: &pb2.Requireds{
1083 ReqBool: scalar.Bool(false),
1084 ReqSfixed64: scalar.Int64(42),
1085 ReqString: scalar.String("hello"),
1086 ReqEnum: pb2.Enum_ONE.Enum(),
1087 },
1088 }, {
1089 desc: "required fields all set",
1090 inputMessage: &pb2.Requireds{},
1091 inputText: `{
1092 "reqBool": false,
1093 "reqSfixed64": 42,
1094 "reqDouble": 1.23,
1095 "reqString": "hello",
1096 "reqEnum": "ONE",
1097 "reqNested": {}
1098}`,
1099 wantMessage: &pb2.Requireds{
1100 ReqBool: scalar.Bool(false),
1101 ReqSfixed64: scalar.Int64(42),
1102 ReqDouble: scalar.Float64(1.23),
1103 ReqString: scalar.String("hello"),
1104 ReqEnum: pb2.Enum_ONE.Enum(),
1105 ReqNested: &pb2.Nested{},
1106 },
1107 }, {
1108 desc: "indirect required field",
1109 inputMessage: &pb2.IndirectRequired{},
1110 inputText: `{
1111 "optNested": {}
1112}`,
1113 wantMessage: &pb2.IndirectRequired{
1114 OptNested: &pb2.NestedWithRequired{},
1115 },
1116 wantErr: true,
1117 }, {
1118 desc: "indirect required field with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07001119 umo: protojson.UnmarshalOptions{AllowPartial: true},
Herbie Ong329be5b2019-03-27 14:47:59 -07001120 inputMessage: &pb2.IndirectRequired{},
1121 inputText: `{
1122 "optNested": {}
1123}`,
1124 wantMessage: &pb2.IndirectRequired{
1125 OptNested: &pb2.NestedWithRequired{},
1126 },
1127 }, {
1128 desc: "indirect required field in repeated",
1129 inputMessage: &pb2.IndirectRequired{},
1130 inputText: `{
1131 "rptNested": [
1132 {"reqString": "one"},
1133 {}
1134 ]
1135}`,
1136 wantMessage: &pb2.IndirectRequired{
1137 RptNested: []*pb2.NestedWithRequired{
1138 {
1139 ReqString: scalar.String("one"),
1140 },
1141 {},
1142 },
1143 },
1144 wantErr: true,
1145 }, {
1146 desc: "indirect required field in repeated with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07001147 umo: protojson.UnmarshalOptions{AllowPartial: true},
Herbie Ong329be5b2019-03-27 14:47:59 -07001148 inputMessage: &pb2.IndirectRequired{},
1149 inputText: `{
1150 "rptNested": [
1151 {"reqString": "one"},
1152 {}
1153 ]
1154}`,
1155 wantMessage: &pb2.IndirectRequired{
1156 RptNested: []*pb2.NestedWithRequired{
1157 {
1158 ReqString: scalar.String("one"),
1159 },
1160 {},
1161 },
1162 },
1163 }, {
1164 desc: "indirect required field in map",
1165 inputMessage: &pb2.IndirectRequired{},
1166 inputText: `{
1167 "strToNested": {
1168 "missing": {},
1169 "contains": {
1170 "reqString": "here"
1171 }
1172 }
1173}`,
1174 wantMessage: &pb2.IndirectRequired{
1175 StrToNested: map[string]*pb2.NestedWithRequired{
1176 "missing": &pb2.NestedWithRequired{},
1177 "contains": &pb2.NestedWithRequired{
1178 ReqString: scalar.String("here"),
1179 },
1180 },
1181 },
1182 wantErr: true,
1183 }, {
1184 desc: "indirect required field in map with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07001185 umo: protojson.UnmarshalOptions{AllowPartial: true},
Herbie Ong329be5b2019-03-27 14:47:59 -07001186 inputMessage: &pb2.IndirectRequired{},
1187 inputText: `{
1188 "strToNested": {
1189 "missing": {},
1190 "contains": {
1191 "reqString": "here"
1192 }
1193 }
1194}`,
1195 wantMessage: &pb2.IndirectRequired{
1196 StrToNested: map[string]*pb2.NestedWithRequired{
1197 "missing": &pb2.NestedWithRequired{},
1198 "contains": &pb2.NestedWithRequired{
1199 ReqString: scalar.String("here"),
1200 },
1201 },
1202 },
1203 }, {
1204 desc: "indirect required field in oneof",
1205 inputMessage: &pb2.IndirectRequired{},
1206 inputText: `{
1207 "oneofNested": {}
1208}`,
1209 wantMessage: &pb2.IndirectRequired{
1210 Union: &pb2.IndirectRequired_OneofNested{
1211 OneofNested: &pb2.NestedWithRequired{},
1212 },
1213 },
1214 wantErr: true,
1215 }, {
1216 desc: "indirect required field in oneof with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07001217 umo: protojson.UnmarshalOptions{AllowPartial: true},
Herbie Ong329be5b2019-03-27 14:47:59 -07001218 inputMessage: &pb2.IndirectRequired{},
1219 inputText: `{
1220 "oneofNested": {}
1221}`,
1222 wantMessage: &pb2.IndirectRequired{
1223 Union: &pb2.IndirectRequired_OneofNested{
1224 OneofNested: &pb2.NestedWithRequired{},
1225 },
1226 },
1227 }, {
Herbie Onge52379a2019-03-15 18:00:19 -07001228 desc: "extensions of non-repeated fields",
1229 inputMessage: &pb2.Extensions{},
1230 inputText: `{
1231 "optString": "non-extension field",
1232 "optBool": true,
1233 "optInt32": 42,
1234 "[pb2.opt_ext_bool]": true,
1235 "[pb2.opt_ext_nested]": {
1236 "optString": "nested in an extension",
Herbie Onge63c4c42019-03-22 22:20:22 -07001237 "optNested": {
1238 "optString": "another nested in an extension"
Herbie Onge52379a2019-03-15 18:00:19 -07001239 }
1240 },
1241 "[pb2.opt_ext_string]": "extension field",
1242 "[pb2.opt_ext_enum]": "TEN"
1243}`,
1244 wantMessage: func() proto.Message {
1245 m := &pb2.Extensions{
1246 OptString: scalar.String("non-extension field"),
1247 OptBool: scalar.Bool(true),
1248 OptInt32: scalar.Int32(42),
1249 }
1250 setExtension(m, pb2.E_OptExtBool, true)
1251 setExtension(m, pb2.E_OptExtString, "extension field")
1252 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
1253 setExtension(m, pb2.E_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",
1263 inputMessage: &pb2.Extensions{},
1264 inputText: `{
1265 "[pb2.rpt_ext_enum]": ["TEN", 101, "ONE"],
1266 "[pb2.rpt_ext_fixed32]": [42, 47],
1267 "[pb2.rpt_ext_nested]": [
1268 {"optString": "one"},
1269 {"optString": "two"},
1270 {"optString": "three"}
1271 ]
1272}`,
1273 wantMessage: func() proto.Message {
1274 m := &pb2.Extensions{}
1275 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
1276 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
1277 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
1278 &pb2.Nested{OptString: scalar.String("one")},
1279 &pb2.Nested{OptString: scalar.String("two")},
1280 &pb2.Nested{OptString: scalar.String("three")},
1281 })
1282 return m
1283 }(),
1284 }, {
1285 desc: "extensions of non-repeated fields in another message",
1286 inputMessage: &pb2.Extensions{},
1287 inputText: `{
1288 "[pb2.ExtensionsContainer.opt_ext_bool]": true,
1289 "[pb2.ExtensionsContainer.opt_ext_enum]": "TEN",
1290 "[pb2.ExtensionsContainer.opt_ext_nested]": {
1291 "optString": "nested in an extension",
1292 "optNested": {
1293 "optString": "another nested in an extension"
1294 }
1295 },
1296 "[pb2.ExtensionsContainer.opt_ext_string]": "extension field"
1297}`,
1298 wantMessage: func() proto.Message {
1299 m := &pb2.Extensions{}
1300 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1301 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
1302 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
1303 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
1304 OptString: scalar.String("nested in an extension"),
1305 OptNested: &pb2.Nested{
1306 OptString: scalar.String("another nested in an extension"),
1307 },
1308 })
1309 return m
1310 }(),
1311 }, {
1312 desc: "extensions of repeated fields in another message",
1313 inputMessage: &pb2.Extensions{},
1314 inputText: `{
1315 "optString": "non-extension field",
1316 "optBool": true,
1317 "optInt32": 42,
1318 "[pb2.ExtensionsContainer.rpt_ext_nested]": [
1319 {"optString": "one"},
1320 {"optString": "two"},
1321 {"optString": "three"}
1322 ],
1323 "[pb2.ExtensionsContainer.rpt_ext_enum]": ["TEN", 101, "ONE"],
1324 "[pb2.ExtensionsContainer.rpt_ext_string]": ["hello", "world"]
1325}`,
1326 wantMessage: func() proto.Message {
1327 m := &pb2.Extensions{
1328 OptString: scalar.String("non-extension field"),
1329 OptBool: scalar.Bool(true),
1330 OptInt32: scalar.Int32(42),
1331 }
1332 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
1333 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1334 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
1335 &pb2.Nested{OptString: scalar.String("one")},
1336 &pb2.Nested{OptString: scalar.String("two")},
1337 &pb2.Nested{OptString: scalar.String("three")},
1338 })
1339 return m
1340 }(),
1341 }, {
1342 desc: "invalid extension field name",
1343 inputMessage: &pb2.Extensions{},
1344 inputText: `{ "[pb2.invalid_message_field]": true }`,
1345 wantErr: true,
1346 }, {
1347 desc: "MessageSet",
1348 inputMessage: &pb2.MessageSet{},
1349 inputText: `{
1350 "[pb2.MessageSetExtension]": {
1351 "optString": "a messageset extension"
1352 },
1353 "[pb2.MessageSetExtension.ext_nested]": {
1354 "optString": "just a regular extension"
1355 },
1356 "[pb2.MessageSetExtension.not_message_set_extension]": {
1357 "optString": "not a messageset extension"
1358 }
1359}`,
1360 wantMessage: func() proto.Message {
1361 m := &pb2.MessageSet{}
1362 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1363 OptString: scalar.String("a messageset extension"),
1364 })
1365 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1366 OptString: scalar.String("not a messageset extension"),
1367 })
1368 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1369 OptString: scalar.String("just a regular extension"),
1370 })
1371 return m
1372 }(),
1373 }, {
1374 desc: "extension field set to null",
1375 inputMessage: &pb2.Extensions{},
1376 inputText: `{
1377 "[pb2.ExtensionsContainer.opt_ext_bool]": null,
1378 "[pb2.ExtensionsContainer.opt_ext_nested]": null
1379}`,
1380 wantMessage: func() proto.Message {
1381 m := &pb2.Extensions{}
1382 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, nil)
1383 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, nil)
1384 return m
1385 }(),
1386 }, {
1387 desc: "extensions of repeated field contains null",
1388 inputMessage: &pb2.Extensions{},
1389 inputText: `{
1390 "[pb2.ExtensionsContainer.rpt_ext_nested]": [
1391 {"optString": "one"},
1392 null,
1393 {"optString": "three"}
1394 ],
1395}`,
1396 wantErr: true,
1397 }, {
1398 desc: "not real MessageSet 1",
1399 inputMessage: &pb2.FakeMessageSet{},
1400 inputText: `{
1401 "[pb2.FakeMessageSetExtension.message_set_extension]": {
1402 "optString": "not a messageset extension"
1403 }
1404}`,
1405 wantMessage: func() proto.Message {
1406 m := &pb2.FakeMessageSet{}
1407 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1408 OptString: scalar.String("not a messageset extension"),
1409 })
1410 return m
1411 }(),
1412 }, {
1413 desc: "not real MessageSet 2",
1414 inputMessage: &pb2.FakeMessageSet{},
1415 inputText: `{
1416 "[pb2.FakeMessageSetExtension]": {
1417 "optString": "not a messageset extension"
1418 }
1419}`,
1420 wantErr: true,
1421 }, {
1422 desc: "not real MessageSet 3",
1423 inputMessage: &pb2.MessageSet{},
1424 inputText: `{
1425 "[pb2.message_set_extension]": {
1426 "optString": "another not a messageset extension"
1427 }
1428}`,
1429 wantMessage: func() proto.Message {
1430 m := &pb2.MessageSet{}
1431 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1432 OptString: scalar.String("another not a messageset extension"),
1433 })
1434 return m
1435 }(),
Herbie Onge63c4c42019-03-22 22:20:22 -07001436 }, {
1437 desc: "Empty",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001438 inputMessage: &emptypb.Empty{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001439 inputText: `{}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001440 wantMessage: &emptypb.Empty{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001441 }, {
1442 desc: "Empty contains unknown",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001443 inputMessage: &emptypb.Empty{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001444 inputText: `{"unknown": null}`,
1445 wantErr: true,
1446 }, {
1447 desc: "BoolValue false",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001448 inputMessage: &wrapperspb.BoolValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001449 inputText: `false`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001450 wantMessage: &wrapperspb.BoolValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001451 }, {
1452 desc: "BoolValue true",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001453 inputMessage: &wrapperspb.BoolValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001454 inputText: `true`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001455 wantMessage: &wrapperspb.BoolValue{Value: true},
Herbie Onge63c4c42019-03-22 22:20:22 -07001456 }, {
1457 desc: "BoolValue invalid value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001458 inputMessage: &wrapperspb.BoolValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001459 inputText: `{}`,
1460 wantErr: true,
1461 }, {
1462 desc: "Int32Value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001463 inputMessage: &wrapperspb.Int32Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001464 inputText: `42`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001465 wantMessage: &wrapperspb.Int32Value{Value: 42},
Herbie Onge63c4c42019-03-22 22:20:22 -07001466 }, {
1467 desc: "Int32Value in JSON string",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001468 inputMessage: &wrapperspb.Int32Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001469 inputText: `"1.23e3"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001470 wantMessage: &wrapperspb.Int32Value{Value: 1230},
Herbie Onge63c4c42019-03-22 22:20:22 -07001471 }, {
1472 desc: "Int64Value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001473 inputMessage: &wrapperspb.Int64Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001474 inputText: `"42"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001475 wantMessage: &wrapperspb.Int64Value{Value: 42},
Herbie Onge63c4c42019-03-22 22:20:22 -07001476 }, {
1477 desc: "UInt32Value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001478 inputMessage: &wrapperspb.UInt32Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001479 inputText: `42`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001480 wantMessage: &wrapperspb.UInt32Value{Value: 42},
Herbie Onge63c4c42019-03-22 22:20:22 -07001481 }, {
1482 desc: "UInt64Value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001483 inputMessage: &wrapperspb.UInt64Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001484 inputText: `"42"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001485 wantMessage: &wrapperspb.UInt64Value{Value: 42},
Herbie Onge63c4c42019-03-22 22:20:22 -07001486 }, {
1487 desc: "FloatValue",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001488 inputMessage: &wrapperspb.FloatValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001489 inputText: `1.02`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001490 wantMessage: &wrapperspb.FloatValue{Value: 1.02},
Herbie Onge63c4c42019-03-22 22:20:22 -07001491 }, {
1492 desc: "FloatValue exceeds max limit",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001493 inputMessage: &wrapperspb.FloatValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001494 inputText: `1.23+40`,
1495 wantErr: true,
1496 }, {
1497 desc: "FloatValue Infinity",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001498 inputMessage: &wrapperspb.FloatValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001499 inputText: `"-Infinity"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001500 wantMessage: &wrapperspb.FloatValue{Value: float32(math.Inf(-1))},
Herbie Onge63c4c42019-03-22 22:20:22 -07001501 }, {
1502 desc: "DoubleValue",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001503 inputMessage: &wrapperspb.DoubleValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001504 inputText: `1.02`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001505 wantMessage: &wrapperspb.DoubleValue{Value: 1.02},
Herbie Onge63c4c42019-03-22 22:20:22 -07001506 }, {
1507 desc: "DoubleValue Infinity",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001508 inputMessage: &wrapperspb.DoubleValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001509 inputText: `"Infinity"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001510 wantMessage: &wrapperspb.DoubleValue{Value: math.Inf(+1)},
Herbie Onge63c4c42019-03-22 22:20:22 -07001511 }, {
1512 desc: "StringValue empty",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001513 inputMessage: &wrapperspb.StringValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001514 inputText: `""`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001515 wantMessage: &wrapperspb.StringValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001516 }, {
1517 desc: "StringValue",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001518 inputMessage: &wrapperspb.StringValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001519 inputText: `"谷歌"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001520 wantMessage: &wrapperspb.StringValue{Value: "谷歌"},
Herbie Onge63c4c42019-03-22 22:20:22 -07001521 }, {
1522 desc: "StringValue with invalid UTF8 error",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001523 inputMessage: &wrapperspb.StringValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001524 inputText: "\"abc\xff\"",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001525 wantMessage: &wrapperspb.StringValue{Value: "abc\xff"},
Herbie Onge63c4c42019-03-22 22:20:22 -07001526 wantErr: true,
1527 }, {
1528 desc: "StringValue field with invalid UTF8 error",
1529 inputMessage: &pb2.KnownTypes{},
1530 inputText: "{\n \"optString\": \"abc\xff\"\n}",
1531 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001532 OptString: &wrapperspb.StringValue{Value: "abc\xff"},
Herbie Onge63c4c42019-03-22 22:20:22 -07001533 },
1534 wantErr: true,
1535 }, {
Herbie Ong300b9fe2019-03-29 15:42:20 -07001536 desc: "NullValue field with JSON null",
1537 inputMessage: &pb2.KnownTypes{},
1538 inputText: `{
1539 "optNull": null
1540}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001541 wantMessage: &pb2.KnownTypes{OptNull: new(structpb.NullValue)},
Herbie Ong300b9fe2019-03-29 15:42:20 -07001542 }, {
1543 desc: "NullValue field with string",
1544 inputMessage: &pb2.KnownTypes{},
1545 inputText: `{
1546 "optNull": "NULL_VALUE"
1547}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001548 wantMessage: &pb2.KnownTypes{OptNull: new(structpb.NullValue)},
Herbie Ong300b9fe2019-03-29 15:42:20 -07001549 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -07001550 desc: "BytesValue",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001551 inputMessage: &wrapperspb.BytesValue{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001552 inputText: `"aGVsbG8="`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001553 wantMessage: &wrapperspb.BytesValue{Value: []byte("hello")},
Herbie Onge63c4c42019-03-22 22:20:22 -07001554 }, {
1555 desc: "Value null",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001556 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001557 inputText: `null`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001558 wantMessage: &structpb.Value{Kind: &structpb.Value_NullValue{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001559 }, {
1560 desc: "Value field null",
1561 inputMessage: &pb2.KnownTypes{},
1562 inputText: `{
1563 "optValue": null
1564}`,
1565 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001566 OptValue: &structpb.Value{Kind: &structpb.Value_NullValue{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001567 },
1568 }, {
1569 desc: "Value bool",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001570 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001571 inputText: `false`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001572 wantMessage: &structpb.Value{Kind: &structpb.Value_BoolValue{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001573 }, {
1574 desc: "Value field bool",
1575 inputMessage: &pb2.KnownTypes{},
1576 inputText: `{
1577 "optValue": true
1578}`,
1579 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001580 OptValue: &structpb.Value{Kind: &structpb.Value_BoolValue{true}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001581 },
1582 }, {
1583 desc: "Value number",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001584 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001585 inputText: `1.02`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001586 wantMessage: &structpb.Value{Kind: &structpb.Value_NumberValue{1.02}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001587 }, {
1588 desc: "Value field number",
1589 inputMessage: &pb2.KnownTypes{},
1590 inputText: `{
1591 "optValue": 1.02
1592}`,
1593 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001594 OptValue: &structpb.Value{Kind: &structpb.Value_NumberValue{1.02}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001595 },
1596 }, {
1597 desc: "Value string",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001598 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001599 inputText: `"hello"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001600 wantMessage: &structpb.Value{Kind: &structpb.Value_StringValue{"hello"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001601 }, {
1602 desc: "Value string with invalid UTF8",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001603 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001604 inputText: "\"\xff\"",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001605 wantMessage: &structpb.Value{Kind: &structpb.Value_StringValue{"\xff"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001606 wantErr: true,
1607 }, {
1608 desc: "Value field string",
1609 inputMessage: &pb2.KnownTypes{},
1610 inputText: `{
1611 "optValue": "NaN"
1612}`,
1613 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001614 OptValue: &structpb.Value{Kind: &structpb.Value_StringValue{"NaN"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001615 },
1616 }, {
1617 desc: "Value field string with invalid UTF8",
1618 inputMessage: &pb2.KnownTypes{},
1619 inputText: `{
1620 "optValue": "` + "\xff" + `"
1621}`,
1622 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001623 OptValue: &structpb.Value{Kind: &structpb.Value_StringValue{"\xff"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001624 },
1625 wantErr: true,
1626 }, {
1627 desc: "Value empty struct",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001628 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001629 inputText: `{}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001630 wantMessage: &structpb.Value{
1631 Kind: &structpb.Value_StructValue{
1632 &structpb.Struct{Fields: map[string]*structpb.Value{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001633 },
1634 },
1635 }, {
1636 desc: "Value struct",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001637 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001638 inputText: `{
1639 "string": "hello",
1640 "number": 123,
1641 "null": null,
1642 "bool": false,
1643 "struct": {
1644 "string": "world"
1645 },
1646 "list": []
1647}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001648 wantMessage: &structpb.Value{
1649 Kind: &structpb.Value_StructValue{
1650 &structpb.Struct{
1651 Fields: map[string]*structpb.Value{
1652 "string": {Kind: &structpb.Value_StringValue{"hello"}},
1653 "number": {Kind: &structpb.Value_NumberValue{123}},
1654 "null": {Kind: &structpb.Value_NullValue{}},
1655 "bool": {Kind: &structpb.Value_BoolValue{false}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001656 "struct": {
Joe Tsaia95b29f2019-05-16 12:47:20 -07001657 Kind: &structpb.Value_StructValue{
1658 &structpb.Struct{
1659 Fields: map[string]*structpb.Value{
1660 "string": {Kind: &structpb.Value_StringValue{"world"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001661 },
1662 },
1663 },
1664 },
1665 "list": {
Joe Tsaia95b29f2019-05-16 12:47:20 -07001666 Kind: &structpb.Value_ListValue{&structpb.ListValue{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001667 },
1668 },
1669 },
1670 },
1671 },
1672 }, {
1673 desc: "Value struct with invalid UTF8 string",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001674 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001675 inputText: "{\"string\": \"abc\xff\"}",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001676 wantMessage: &structpb.Value{
1677 Kind: &structpb.Value_StructValue{
1678 &structpb.Struct{
1679 Fields: map[string]*structpb.Value{
1680 "string": {Kind: &structpb.Value_StringValue{"abc\xff"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001681 },
1682 },
1683 },
1684 },
1685 wantErr: true,
1686 }, {
1687 desc: "Value field struct",
1688 inputMessage: &pb2.KnownTypes{},
1689 inputText: `{
1690 "optValue": {
1691 "string": "hello"
1692 }
1693}`,
1694 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001695 OptValue: &structpb.Value{
1696 Kind: &structpb.Value_StructValue{
1697 &structpb.Struct{
1698 Fields: map[string]*structpb.Value{
1699 "string": {Kind: &structpb.Value_StringValue{"hello"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001700 },
1701 },
1702 },
1703 },
1704 },
1705 }, {
1706 desc: "Value empty list",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001707 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001708 inputText: `[]`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001709 wantMessage: &structpb.Value{
1710 Kind: &structpb.Value_ListValue{
1711 &structpb.ListValue{Values: []*structpb.Value{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001712 },
1713 },
1714 }, {
1715 desc: "Value list",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001716 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001717 inputText: `[
1718 "string",
1719 123,
1720 null,
1721 true,
1722 {},
1723 [
1724 "string",
1725 1.23,
1726 null,
1727 false
1728 ]
1729]`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001730 wantMessage: &structpb.Value{
1731 Kind: &structpb.Value_ListValue{
1732 &structpb.ListValue{
1733 Values: []*structpb.Value{
1734 {Kind: &structpb.Value_StringValue{"string"}},
1735 {Kind: &structpb.Value_NumberValue{123}},
1736 {Kind: &structpb.Value_NullValue{}},
1737 {Kind: &structpb.Value_BoolValue{true}},
1738 {Kind: &structpb.Value_StructValue{&structpb.Struct{}}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001739 {
Joe Tsaia95b29f2019-05-16 12:47:20 -07001740 Kind: &structpb.Value_ListValue{
1741 &structpb.ListValue{
1742 Values: []*structpb.Value{
1743 {Kind: &structpb.Value_StringValue{"string"}},
1744 {Kind: &structpb.Value_NumberValue{1.23}},
1745 {Kind: &structpb.Value_NullValue{}},
1746 {Kind: &structpb.Value_BoolValue{false}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001747 },
1748 },
1749 },
1750 },
1751 },
1752 },
1753 },
1754 },
1755 }, {
1756 desc: "Value list with invalid UTF8 string",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001757 inputMessage: &structpb.Value{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001758 inputText: "[\"abc\xff\"]",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001759 wantMessage: &structpb.Value{
1760 Kind: &structpb.Value_ListValue{
1761 &structpb.ListValue{
1762 Values: []*structpb.Value{
1763 {Kind: &structpb.Value_StringValue{"abc\xff"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001764 },
1765 },
1766 },
1767 },
1768 wantErr: true,
1769 }, {
1770 desc: "Value field list with invalid UTF8 string",
1771 inputMessage: &pb2.KnownTypes{},
1772 inputText: `{
1773 "optValue": [ "` + "abc\xff" + `"]
1774}`,
1775 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001776 OptValue: &structpb.Value{
1777 Kind: &structpb.Value_ListValue{
1778 &structpb.ListValue{
1779 Values: []*structpb.Value{
1780 {Kind: &structpb.Value_StringValue{"abc\xff"}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001781 },
1782 },
1783 },
1784 },
1785 },
1786 wantErr: true,
1787 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001788 desc: "Duration empty string",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001789 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001790 inputText: `""`,
1791 wantErr: true,
1792 }, {
1793 desc: "Duration with secs",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001794 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001795 inputText: `"3s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001796 wantMessage: &durationpb.Duration{Seconds: 3},
Herbie Ongc4450372019-03-27 09:59:51 -07001797 }, {
1798 desc: "Duration with escaped unicode",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001799 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001800 inputText: `"\u0033s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001801 wantMessage: &durationpb.Duration{Seconds: 3},
Herbie Ongc4450372019-03-27 09:59:51 -07001802 }, {
1803 desc: "Duration with -secs",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001804 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001805 inputText: `"-3s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001806 wantMessage: &durationpb.Duration{Seconds: -3},
Herbie Ongc4450372019-03-27 09:59:51 -07001807 }, {
Herbie Ong17523eb2019-03-29 17:46:57 -07001808 desc: "Duration with plus sign",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001809 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001810 inputText: `"+3s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001811 wantMessage: &durationpb.Duration{Seconds: 3},
Herbie Ong17523eb2019-03-29 17:46:57 -07001812 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001813 desc: "Duration with nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001814 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001815 inputText: `"0.001s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001816 wantMessage: &durationpb.Duration{Nanos: 1e6},
Herbie Ongc4450372019-03-27 09:59:51 -07001817 }, {
1818 desc: "Duration with -nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001819 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001820 inputText: `"-0.001s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001821 wantMessage: &durationpb.Duration{Nanos: -1e6},
Herbie Ongc4450372019-03-27 09:59:51 -07001822 }, {
Herbie Ong17523eb2019-03-29 17:46:57 -07001823 desc: "Duration with -nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001824 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001825 inputText: `"-.001s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001826 wantMessage: &durationpb.Duration{Nanos: -1e6},
Herbie Ong17523eb2019-03-29 17:46:57 -07001827 }, {
1828 desc: "Duration with +nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001829 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001830 inputText: `"+.001s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001831 wantMessage: &durationpb.Duration{Nanos: 1e6},
Herbie Ong17523eb2019-03-29 17:46:57 -07001832 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001833 desc: "Duration with -secs -nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001834 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001835 inputText: `"-123.000000450s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001836 wantMessage: &durationpb.Duration{Seconds: -123, Nanos: -450},
Herbie Ongc4450372019-03-27 09:59:51 -07001837 }, {
1838 desc: "Duration with large secs",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001839 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001840 inputText: `"10000000000.000000001s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001841 wantMessage: &durationpb.Duration{Seconds: 1e10, Nanos: 1},
Herbie Ongc4450372019-03-27 09:59:51 -07001842 }, {
1843 desc: "Duration with decimal without fractional",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001844 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001845 inputText: `"3.s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001846 wantMessage: &durationpb.Duration{Seconds: 3},
Herbie Ongc4450372019-03-27 09:59:51 -07001847 }, {
1848 desc: "Duration with decimal without integer",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001849 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001850 inputText: `"0.5s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001851 wantMessage: &durationpb.Duration{Nanos: 5e8},
Herbie Ongc4450372019-03-27 09:59:51 -07001852 }, {
Herbie Ongad9c1252019-04-24 20:51:28 -07001853 desc: "Duration max value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001854 inputMessage: &durationpb.Duration{},
Herbie Ongad9c1252019-04-24 20:51:28 -07001855 inputText: `"315576000000.999999999s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001856 wantMessage: &durationpb.Duration{Seconds: 315576000000, Nanos: 999999999},
Herbie Ongad9c1252019-04-24 20:51:28 -07001857 }, {
1858 desc: "Duration min value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001859 inputMessage: &durationpb.Duration{},
Herbie Ongad9c1252019-04-24 20:51:28 -07001860 inputText: `"-315576000000.999999999s"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001861 wantMessage: &durationpb.Duration{Seconds: -315576000000, Nanos: -999999999},
Herbie Ongad9c1252019-04-24 20:51:28 -07001862 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001863 desc: "Duration with +secs out of range",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001864 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001865 inputText: `"315576000001s"`,
1866 wantErr: true,
1867 }, {
1868 desc: "Duration with -secs out of range",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001869 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001870 inputText: `"-315576000001s"`,
1871 wantErr: true,
1872 }, {
1873 desc: "Duration with nanos beyond 9 digits",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001874 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001875 inputText: `"0.1000000000s"`,
Herbie Ongc4450372019-03-27 09:59:51 -07001876 wantErr: true,
1877 }, {
1878 desc: "Duration without suffix s",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001879 inputMessage: &durationpb.Duration{},
Herbie Ongc4450372019-03-27 09:59:51 -07001880 inputText: `"123"`,
1881 wantErr: true,
1882 }, {
Herbie Ong17523eb2019-03-29 17:46:57 -07001883 desc: "Duration invalid signed fraction",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001884 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001885 inputText: `"123.+123s"`,
1886 wantErr: true,
1887 }, {
1888 desc: "Duration invalid multiple .",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001889 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001890 inputText: `"123.123.s"`,
1891 wantErr: true,
1892 }, {
1893 desc: "Duration invalid integer",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001894 inputMessage: &durationpb.Duration{},
Herbie Ong17523eb2019-03-29 17:46:57 -07001895 inputText: `"01s"`,
1896 wantErr: true,
1897 }, {
Herbie Ongc4450372019-03-27 09:59:51 -07001898 desc: "Timestamp zero",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001899 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001900 inputText: `"1970-01-01T00:00:00Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001901 wantMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001902 }, {
1903 desc: "Timestamp with tz adjustment",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001904 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001905 inputText: `"1970-01-01T00:00:00+01:00"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001906 wantMessage: &timestamppb.Timestamp{Seconds: -3600},
Herbie Ongc4450372019-03-27 09:59:51 -07001907 }, {
1908 desc: "Timestamp UTC",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001909 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001910 inputText: `"2019-03-19T23:03:21Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001911 wantMessage: &timestamppb.Timestamp{Seconds: 1553036601},
Herbie Ongc4450372019-03-27 09:59:51 -07001912 }, {
1913 desc: "Timestamp with escaped unicode",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001914 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001915 inputText: `"2019-0\u0033-19T23:03:21Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001916 wantMessage: &timestamppb.Timestamp{Seconds: 1553036601},
Herbie Ongc4450372019-03-27 09:59:51 -07001917 }, {
1918 desc: "Timestamp with nanos",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001919 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001920 inputText: `"2019-03-19T23:03:21.000000001Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001921 wantMessage: &timestamppb.Timestamp{Seconds: 1553036601, Nanos: 1},
Herbie Ongc4450372019-03-27 09:59:51 -07001922 }, {
Herbie Ongad9c1252019-04-24 20:51:28 -07001923 desc: "Timestamp max value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001924 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001925 inputText: `"9999-12-31T23:59:59.999999999Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001926 wantMessage: &timestamppb.Timestamp{Seconds: 253402300799, Nanos: 999999999},
Herbie Ongc4450372019-03-27 09:59:51 -07001927 }, {
Herbie Ongad9c1252019-04-24 20:51:28 -07001928 desc: "Timestamp above max value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001929 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001930 inputText: `"9999-12-31T23:59:59-01:00"`,
1931 wantErr: true,
1932 }, {
Herbie Ongad9c1252019-04-24 20:51:28 -07001933 desc: "Timestamp min value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001934 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001935 inputText: `"0001-01-01T00:00:00Z"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001936 wantMessage: &timestamppb.Timestamp{Seconds: -62135596800},
Herbie Ongc4450372019-03-27 09:59:51 -07001937 }, {
Herbie Ongad9c1252019-04-24 20:51:28 -07001938 desc: "Timestamp below min value",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001939 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001940 inputText: `"0001-01-01T00:00:00+01:00"`,
1941 wantErr: true,
1942 }, {
1943 desc: "Timestamp with nanos beyond 9 digits",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001944 inputMessage: &timestamppb.Timestamp{},
Herbie Ongc4450372019-03-27 09:59:51 -07001945 inputText: `"1970-01-01T00:00:00.0000000001Z"`,
1946 wantErr: true,
1947 }, {
Herbie Onge63c4c42019-03-22 22:20:22 -07001948 desc: "FieldMask empty",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001949 inputMessage: &fieldmaskpb.FieldMask{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001950 inputText: `""`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001951 wantMessage: &fieldmaskpb.FieldMask{Paths: []string{}},
Herbie Onge63c4c42019-03-22 22:20:22 -07001952 }, {
1953 desc: "FieldMask",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001954 inputMessage: &fieldmaskpb.FieldMask{},
Herbie Onge63c4c42019-03-22 22:20:22 -07001955 inputText: `"foo,fooBar , foo.barQux ,Foo"`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001956 wantMessage: &fieldmaskpb.FieldMask{
Herbie Onge63c4c42019-03-22 22:20:22 -07001957 Paths: []string{
1958 "foo",
1959 "foo_bar",
1960 "foo.bar_qux",
1961 "_foo",
1962 },
1963 },
1964 }, {
1965 desc: "FieldMask field",
1966 inputMessage: &pb2.KnownTypes{},
1967 inputText: `{
1968 "optFieldmask": "foo, qux.fooBar"
1969}`,
1970 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07001971 OptFieldmask: &fieldmaskpb.FieldMask{
Herbie Onge63c4c42019-03-22 22:20:22 -07001972 Paths: []string{
1973 "foo",
1974 "qux.foo_bar",
1975 },
1976 },
1977 },
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001978 }, {
1979 desc: "Any empty",
Joe Tsaia95b29f2019-05-16 12:47:20 -07001980 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001981 inputText: `{}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07001982 wantMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001983 }, {
1984 desc: "Any with non-custom message",
Damien Neil5c5b5312019-05-14 12:44:37 -07001985 umo: protojson.UnmarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001986 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001987 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001988 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07001989 inputText: `{
1990 "@type": "foo/pb2.Nested",
1991 "optString": "embedded inside Any",
1992 "optNested": {
1993 "optString": "inception"
1994 }
1995}`,
1996 wantMessage: func() proto.Message {
1997 m := &pb2.Nested{
1998 OptString: scalar.String("embedded inside Any"),
1999 OptNested: &pb2.Nested{
2000 OptString: scalar.String("inception"),
2001 },
2002 }
2003 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2004 if err != nil {
2005 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2006 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002007 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002008 TypeUrl: "foo/pb2.Nested",
2009 Value: b,
2010 }
2011 }(),
2012 }, {
2013 desc: "Any with empty embedded message",
Damien Neil5c5b5312019-05-14 12:44:37 -07002014 umo: protojson.UnmarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07002015 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002016 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002017 inputMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002018 inputText: `{"@type": "foo/pb2.Nested"}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002019 wantMessage: &anypb.Any{TypeUrl: "foo/pb2.Nested"},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002020 }, {
2021 desc: "Any without registered type",
Damien Neil5c5b5312019-05-14 12:44:37 -07002022 umo: protojson.UnmarshalOptions{Resolver: preg.NewTypes()},
Joe Tsaia95b29f2019-05-16 12:47:20 -07002023 inputMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002024 inputText: `{"@type": "foo/pb2.Nested"}`,
2025 wantErr: true,
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002026 }, {
2027 desc: "Any with missing required error",
Damien Neil5c5b5312019-05-14 12:44:37 -07002028 umo: protojson.UnmarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07002029 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002030 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002031 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002032 inputText: `{
2033 "@type": "pb2.PartialRequired",
2034 "optString": "embedded inside Any"
2035}`,
2036 wantMessage: func() proto.Message {
2037 m := &pb2.PartialRequired{
2038 OptString: scalar.String("embedded inside Any"),
2039 }
Damien Neil96c229a2019-04-03 12:17:24 -07002040 b, err := proto.MarshalOptions{
2041 Deterministic: true,
2042 AllowPartial: true,
2043 }.Marshal(m)
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002044 if err != nil {
2045 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2046 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002047 return &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07002048 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002049 Value: b,
2050 }
2051 }(),
2052 wantErr: true,
2053 }, {
2054 desc: "Any with partial required and AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -07002055 umo: protojson.UnmarshalOptions{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002056 AllowPartial: true,
Joe Tsai0fc49f82019-05-01 12:29:25 -07002057 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002058 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002059 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002060 inputText: `{
2061 "@type": "pb2.PartialRequired",
2062 "optString": "embedded inside Any"
2063}`,
2064 wantMessage: func() proto.Message {
2065 m := &pb2.PartialRequired{
2066 OptString: scalar.String("embedded inside Any"),
2067 }
Damien Neil96c229a2019-04-03 12:17:24 -07002068 b, err := proto.MarshalOptions{
2069 Deterministic: true,
2070 AllowPartial: true,
2071 }.Marshal(m)
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002072 if err != nil {
2073 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2074 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002075 return &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07002076 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002077 Value: b,
2078 }
2079 }(),
2080 }, {
2081 desc: "Any with invalid UTF8",
Damien Neil5c5b5312019-05-14 12:44:37 -07002082 umo: protojson.UnmarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07002083 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002084 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002085 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002086 inputText: `{
2087 "optString": "` + "abc\xff" + `",
2088 "@type": "foo/pb2.Nested"
2089}`,
2090 wantMessage: func() proto.Message {
2091 m := &pb2.Nested{
2092 OptString: scalar.String("abc\xff"),
2093 }
2094 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2095 if err != nil {
2096 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2097 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002098 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002099 TypeUrl: "foo/pb2.Nested",
2100 Value: b,
2101 }
2102 }(),
2103 wantErr: true,
2104 }, {
2105 desc: "Any with BoolValue",
Damien Neil5c5b5312019-05-14 12:44:37 -07002106 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002107 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.BoolValue{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002108 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002109 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002110 inputText: `{
2111 "@type": "type.googleapis.com/google.protobuf.BoolValue",
2112 "value": true
2113}`,
2114 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002115 m := &wrapperspb.BoolValue{Value: true}
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002116 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2117 if err != nil {
2118 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2119 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002120 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002121 TypeUrl: "type.googleapis.com/google.protobuf.BoolValue",
2122 Value: b,
2123 }
2124 }(),
2125 }, {
2126 desc: "Any with Empty",
Damien Neil5c5b5312019-05-14 12:44:37 -07002127 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002128 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002129 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002130 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002131 inputText: `{
2132 "value": {},
2133 "@type": "type.googleapis.com/google.protobuf.Empty"
2134}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002135 wantMessage: &anypb.Any{
Herbie Ong4f0be712019-04-25 17:57:12 -07002136 TypeUrl: "type.googleapis.com/google.protobuf.Empty",
2137 },
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002138 }, {
2139 desc: "Any with missing Empty",
Damien Neil5c5b5312019-05-14 12:44:37 -07002140 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002141 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002142 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002143 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002144 inputText: `{
2145 "@type": "type.googleapis.com/google.protobuf.Empty"
2146}`,
2147 wantErr: true,
2148 }, {
2149 desc: "Any with StringValue containing invalid UTF8",
Damien Neil5c5b5312019-05-14 12:44:37 -07002150 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002151 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002152 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002153 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002154 inputText: `{
2155 "@type": "google.protobuf.StringValue",
2156 "value": "` + "abc\xff" + `"
2157}`,
2158 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002159 m := &wrapperspb.StringValue{Value: "abcd"}
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002160 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2161 if err != nil {
2162 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2163 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002164 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002165 TypeUrl: "google.protobuf.StringValue",
Damien Neilbc310b52019-04-11 11:46:55 -07002166 Value: bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002167 }
2168 }(),
2169 wantErr: true,
2170 }, {
2171 desc: "Any with Int64Value",
Damien Neil5c5b5312019-05-14 12:44:37 -07002172 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002173 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.Int64Value{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002174 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002175 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002176 inputText: `{
2177 "@type": "google.protobuf.Int64Value",
2178 "value": "42"
2179}`,
2180 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002181 m := &wrapperspb.Int64Value{Value: 42}
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002182 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2183 if err != nil {
2184 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2185 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002186 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002187 TypeUrl: "google.protobuf.Int64Value",
2188 Value: b,
2189 }
2190 }(),
2191 }, {
2192 desc: "Any with invalid Int64Value",
Damien Neil5c5b5312019-05-14 12:44:37 -07002193 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002194 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.Int64Value{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002195 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002196 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002197 inputText: `{
2198 "@type": "google.protobuf.Int64Value",
2199 "value": "forty-two"
2200}`,
2201 wantErr: true,
2202 }, {
2203 desc: "Any with invalid UInt64Value",
Damien Neil5c5b5312019-05-14 12:44:37 -07002204 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002205 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.UInt64Value{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002206 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002207 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002208 inputText: `{
2209 "@type": "google.protobuf.UInt64Value",
2210 "value": -42
2211}`,
2212 wantErr: true,
2213 }, {
2214 desc: "Any with Duration",
Damien Neil5c5b5312019-05-14 12:44:37 -07002215 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002216 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&durationpb.Duration{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002217 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002218 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002219 inputText: `{
2220 "@type": "type.googleapis.com/google.protobuf.Duration",
2221 "value": "0s"
2222}`,
2223 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002224 m := &durationpb.Duration{}
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002225 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2226 if err != nil {
2227 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2228 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002229 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002230 TypeUrl: "type.googleapis.com/google.protobuf.Duration",
2231 Value: b,
2232 }
2233 }(),
2234 }, {
2235 desc: "Any with Value of StringValue",
Damien Neil5c5b5312019-05-14 12:44:37 -07002236 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002237 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&structpb.Value{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002238 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002239 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002240 inputText: `{
2241 "@type": "google.protobuf.Value",
2242 "value": "` + "abc\xff" + `"
2243}`,
2244 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002245 m := &structpb.Value{Kind: &structpb.Value_StringValue{"abcd"}}
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002246 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2247 if err != nil {
2248 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2249 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002250 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002251 TypeUrl: "google.protobuf.Value",
Damien Neilbc310b52019-04-11 11:46:55 -07002252 Value: bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002253 }
2254 }(),
2255 wantErr: true,
2256 }, {
2257 desc: "Any with Value of NullValue",
Damien Neil5c5b5312019-05-14 12:44:37 -07002258 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002259 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&structpb.Value{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002260 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002261 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002262 inputText: `{
2263 "@type": "google.protobuf.Value",
2264 "value": null
2265}`,
2266 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002267 m := &structpb.Value{Kind: &structpb.Value_NullValue{}}
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002268 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2269 if err != nil {
2270 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2271 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002272 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002273 TypeUrl: "google.protobuf.Value",
2274 Value: b,
2275 }
2276 }(),
2277 }, {
2278 desc: "Any with Struct",
Damien Neil5c5b5312019-05-14 12:44:37 -07002279 umo: protojson.UnmarshalOptions{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002280 Resolver: preg.NewTypes(
Joe Tsaia95b29f2019-05-16 12:47:20 -07002281 pimpl.Export{}.MessageTypeOf(&structpb.Struct{}),
2282 pimpl.Export{}.MessageTypeOf(&structpb.Value{}),
2283 pimpl.Export{}.MessageTypeOf(&wrapperspb.BoolValue{}),
2284 pimpl.Export{}.EnumTypeOf(structpb.NullValue_NULL_VALUE),
2285 pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{}),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002286 ),
2287 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002288 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002289 inputText: `{
2290 "@type": "google.protobuf.Struct",
2291 "value": {
2292 "bool": true,
2293 "null": null,
2294 "string": "hello",
2295 "struct": {
2296 "string": "world"
2297 }
2298 }
2299}`,
2300 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002301 m := &structpb.Struct{
2302 Fields: map[string]*structpb.Value{
2303 "bool": {Kind: &structpb.Value_BoolValue{true}},
2304 "null": {Kind: &structpb.Value_NullValue{}},
2305 "string": {Kind: &structpb.Value_StringValue{"hello"}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002306 "struct": {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002307 Kind: &structpb.Value_StructValue{
2308 &structpb.Struct{
2309 Fields: map[string]*structpb.Value{
2310 "string": {Kind: &structpb.Value_StringValue{"world"}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002311 },
2312 },
2313 },
2314 },
2315 },
2316 }
2317 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
2318 if err != nil {
2319 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2320 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002321 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002322 TypeUrl: "google.protobuf.Struct",
2323 Value: b,
2324 }
2325 }(),
2326 }, {
2327 desc: "Any with missing @type",
Damien Neil5c5b5312019-05-14 12:44:37 -07002328 umo: protojson.UnmarshalOptions{},
Joe Tsaia95b29f2019-05-16 12:47:20 -07002329 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002330 inputText: `{
2331 "value": {}
2332}`,
2333 wantErr: true,
2334 }, {
2335 desc: "Any with empty @type",
Joe Tsaia95b29f2019-05-16 12:47:20 -07002336 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002337 inputText: `{
2338 "@type": ""
2339}`,
2340 wantErr: true,
2341 }, {
2342 desc: "Any with duplicate @type",
Damien Neil5c5b5312019-05-14 12:44:37 -07002343 umo: protojson.UnmarshalOptions{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002344 Resolver: preg.NewTypes(
Joe Tsai0fc49f82019-05-01 12:29:25 -07002345 pimpl.Export{}.MessageTypeOf(&pb2.Nested{}),
Joe Tsaia95b29f2019-05-16 12:47:20 -07002346 pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{}),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002347 ),
2348 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002349 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002350 inputText: `{
2351 "@type": "google.protobuf.StringValue",
2352 "value": "hello",
2353 "@type": "pb2.Nested"
2354}`,
2355 wantErr: true,
2356 }, {
2357 desc: "Any with duplicate value",
Damien Neil5c5b5312019-05-14 12:44:37 -07002358 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002359 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002360 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002361 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002362 inputText: `{
2363 "@type": "google.protobuf.StringValue",
2364 "value": "hello",
2365 "value": "world"
2366}`,
2367 wantErr: true,
2368 }, {
2369 desc: "Any with unknown field",
Damien Neil5c5b5312019-05-14 12:44:37 -07002370 umo: protojson.UnmarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07002371 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002372 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002373 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002374 inputText: `{
2375 "@type": "pb2.Nested",
2376 "optString": "hello",
2377 "unknown": "world"
2378}`,
2379 wantErr: true,
2380 }, {
2381 desc: "Any with embedded type containing Any",
Damien Neil5c5b5312019-05-14 12:44:37 -07002382 umo: protojson.UnmarshalOptions{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002383 Resolver: preg.NewTypes(
Joe Tsai0fc49f82019-05-01 12:29:25 -07002384 pimpl.Export{}.MessageTypeOf(&pb2.KnownTypes{}),
Joe Tsaia95b29f2019-05-16 12:47:20 -07002385 pimpl.Export{}.MessageTypeOf(&anypb.Any{}),
2386 pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{}),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002387 ),
2388 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002389 inputMessage: &anypb.Any{},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002390 inputText: `{
2391 "@type": "pb2.KnownTypes",
2392 "optAny": {
2393 "@type": "google.protobuf.StringValue",
2394 "value": "` + "abc\xff" + `"
2395 }
2396}`,
2397 wantMessage: func() proto.Message {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002398 m1 := &wrapperspb.StringValue{Value: "abcd"}
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002399 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
2400 if err != nil {
2401 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2402 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002403 m2 := &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002404 TypeUrl: "google.protobuf.StringValue",
2405 Value: b,
2406 }
2407 m3 := &pb2.KnownTypes{OptAny: m2}
2408 b, err = proto.MarshalOptions{Deterministic: true}.Marshal(m3)
2409 if err != nil {
2410 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
2411 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07002412 return &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002413 TypeUrl: "pb2.KnownTypes",
Damien Neilbc310b52019-04-11 11:46:55 -07002414 Value: bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002415 }
2416 }(),
2417 wantErr: true,
2418 }, {
2419 desc: "well known types as field values",
Damien Neil5c5b5312019-05-14 12:44:37 -07002420 umo: protojson.UnmarshalOptions{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002421 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002422 },
2423 inputMessage: &pb2.KnownTypes{},
2424 inputText: `{
2425 "optBool": false,
2426 "optInt32": 42,
2427 "optInt64": "42",
2428 "optUint32": 42,
2429 "optUint64": "42",
2430 "optFloat": 1.23,
2431 "optDouble": 3.1415,
2432 "optString": "hello",
2433 "optBytes": "aGVsbG8=",
2434 "optDuration": "123s",
2435 "optTimestamp": "2019-03-19T23:03:21Z",
2436 "optStruct": {
2437 "string": "hello"
2438 },
2439 "optList": [
2440 null,
2441 "",
2442 {},
2443 []
2444 ],
2445 "optValue": "world",
2446 "optEmpty": {},
2447 "optAny": {
2448 "@type": "google.protobuf.Empty",
2449 "value": {}
2450 },
2451 "optFieldmask": "fooBar,barFoo"
2452}`,
2453 wantMessage: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -07002454 OptBool: &wrapperspb.BoolValue{Value: false},
2455 OptInt32: &wrapperspb.Int32Value{Value: 42},
2456 OptInt64: &wrapperspb.Int64Value{Value: 42},
2457 OptUint32: &wrapperspb.UInt32Value{Value: 42},
2458 OptUint64: &wrapperspb.UInt64Value{Value: 42},
2459 OptFloat: &wrapperspb.FloatValue{Value: 1.23},
2460 OptDouble: &wrapperspb.DoubleValue{Value: 3.1415},
2461 OptString: &wrapperspb.StringValue{Value: "hello"},
2462 OptBytes: &wrapperspb.BytesValue{Value: []byte("hello")},
2463 OptDuration: &durationpb.Duration{Seconds: 123},
2464 OptTimestamp: &timestamppb.Timestamp{Seconds: 1553036601},
2465 OptStruct: &structpb.Struct{
2466 Fields: map[string]*structpb.Value{
2467 "string": {Kind: &structpb.Value_StringValue{"hello"}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002468 },
2469 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002470 OptList: &structpb.ListValue{
2471 Values: []*structpb.Value{
2472 {Kind: &structpb.Value_NullValue{}},
2473 {Kind: &structpb.Value_StringValue{}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002474 {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002475 Kind: &structpb.Value_StructValue{
2476 &structpb.Struct{Fields: map[string]*structpb.Value{}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002477 },
2478 },
2479 {
Joe Tsaia95b29f2019-05-16 12:47:20 -07002480 Kind: &structpb.Value_ListValue{
2481 &structpb.ListValue{Values: []*structpb.Value{}},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002482 },
2483 },
2484 },
2485 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002486 OptValue: &structpb.Value{
2487 Kind: &structpb.Value_StringValue{"world"},
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002488 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002489 OptEmpty: &emptypb.Empty{},
2490 OptAny: &anypb.Any{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002491 TypeUrl: "google.protobuf.Empty",
2492 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002493 OptFieldmask: &fieldmaskpb.FieldMask{
Herbie Ong8ac9dd22019-03-27 12:20:50 -07002494 Paths: []string{"foo_bar", "bar_foo"},
2495 },
2496 },
Herbie Ong4f0be712019-04-25 17:57:12 -07002497 }, {
2498 desc: "DiscardUnknown: regular messages",
Damien Neil5c5b5312019-05-14 12:44:37 -07002499 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Herbie Ong4f0be712019-04-25 17:57:12 -07002500 inputMessage: &pb3.Nests{},
2501 inputText: `{
2502 "sNested": {
2503 "unknown": {
2504 "foo": 1,
2505 "bar": [1, 2, 3]
2506 }
2507 },
2508 "unknown": "not known"
2509}`,
2510 wantMessage: &pb3.Nests{SNested: &pb3.Nested{}},
2511 }, {
2512 desc: "DiscardUnknown: repeated",
Damien Neil5c5b5312019-05-14 12:44:37 -07002513 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Herbie Ong4f0be712019-04-25 17:57:12 -07002514 inputMessage: &pb2.Nests{},
2515 inputText: `{
2516 "rptNested": [
2517 {"unknown": "blah"},
2518 {"optString": "hello"}
2519 ]
2520}`,
2521 wantMessage: &pb2.Nests{
2522 RptNested: []*pb2.Nested{
2523 {},
2524 {OptString: scalar.String("hello")},
2525 },
2526 },
2527 }, {
2528 desc: "DiscardUnknown: map",
Damien Neil5c5b5312019-05-14 12:44:37 -07002529 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Herbie Ong4f0be712019-04-25 17:57:12 -07002530 inputMessage: &pb3.Maps{},
2531 inputText: `{
2532 "strToNested": {
2533 "nested_one": {
2534 "unknown": "what you see is not"
2535 }
2536 }
2537}`,
2538 wantMessage: &pb3.Maps{
2539 StrToNested: map[string]*pb3.Nested{
2540 "nested_one": {},
2541 },
2542 },
2543 }, {
2544 desc: "DiscardUnknown: extension",
Damien Neil5c5b5312019-05-14 12:44:37 -07002545 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Herbie Ong4f0be712019-04-25 17:57:12 -07002546 inputMessage: &pb2.Extensions{},
2547 inputText: `{
2548 "[pb2.opt_ext_nested]": {
2549 "unknown": []
2550 }
2551}`,
2552 wantMessage: func() proto.Message {
2553 m := &pb2.Extensions{}
2554 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{})
2555 return m
2556 }(),
2557 }, {
2558 desc: "DiscardUnknown: Empty",
Damien Neil5c5b5312019-05-14 12:44:37 -07002559 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Joe Tsaia95b29f2019-05-16 12:47:20 -07002560 inputMessage: &emptypb.Empty{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002561 inputText: `{"unknown": "something"}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002562 wantMessage: &emptypb.Empty{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002563 }, {
2564 desc: "DiscardUnknown: Any without type",
Damien Neil5c5b5312019-05-14 12:44:37 -07002565 umo: protojson.UnmarshalOptions{DiscardUnknown: true},
Joe Tsaia95b29f2019-05-16 12:47:20 -07002566 inputMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002567 inputText: `{
2568 "value": {"foo": "bar"},
2569 "unknown": true
2570}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002571 wantMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002572 }, {
2573 desc: "DiscardUnknown: Any",
Damien Neil5c5b5312019-05-14 12:44:37 -07002574 umo: protojson.UnmarshalOptions{
Herbie Ong4f0be712019-04-25 17:57:12 -07002575 DiscardUnknown: true,
Joe Tsai0fc49f82019-05-01 12:29:25 -07002576 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong4f0be712019-04-25 17:57:12 -07002577 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002578 inputMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002579 inputText: `{
2580 "@type": "foo/pb2.Nested",
2581 "unknown": "none"
2582}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002583 wantMessage: &anypb.Any{
Herbie Ong4f0be712019-04-25 17:57:12 -07002584 TypeUrl: "foo/pb2.Nested",
2585 },
2586 }, {
2587 desc: "DiscardUnknown: Any with Empty",
Damien Neil5c5b5312019-05-14 12:44:37 -07002588 umo: protojson.UnmarshalOptions{
Herbie Ong4f0be712019-04-25 17:57:12 -07002589 DiscardUnknown: true,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002590 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
Herbie Ong4f0be712019-04-25 17:57:12 -07002591 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07002592 inputMessage: &anypb.Any{},
Herbie Ong4f0be712019-04-25 17:57:12 -07002593 inputText: `{
2594 "@type": "type.googleapis.com/google.protobuf.Empty",
2595 "value": {"unknown": 47}
2596}`,
Joe Tsaia95b29f2019-05-16 12:47:20 -07002597 wantMessage: &anypb.Any{
Herbie Ong4f0be712019-04-25 17:57:12 -07002598 TypeUrl: "type.googleapis.com/google.protobuf.Empty",
2599 },
Herbie Ongc96a79d2019-03-08 10:49:17 -08002600 }}
2601
2602 for _, tt := range tests {
2603 tt := tt
2604 t.Run(tt.desc, func(t *testing.T) {
Joe Tsaicdb77732019-05-14 16:05:06 -07002605 err := tt.umo.Unmarshal([]byte(tt.inputText), tt.inputMessage)
Herbie Ongc96a79d2019-03-08 10:49:17 -08002606 if err != nil && !tt.wantErr {
2607 t.Errorf("Unmarshal() returned error: %v\n\n", err)
2608 }
2609 if err == nil && tt.wantErr {
2610 t.Error("Unmarshal() got nil error, want error\n\n")
2611 }
2612 if tt.wantMessage != nil && !protoV1.Equal(tt.inputMessage.(protoV1.Message), tt.wantMessage.(protoV1.Message)) {
2613 t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", tt.inputMessage, tt.wantMessage)
2614 }
2615 })
2616 }
2617}