1
2
3
4
5 package json_test
6
7 import (
8 "fmt"
9 "math"
10 "strings"
11 "testing"
12 "unicode/utf8"
13
14 "github.com/google/go-cmp/cmp"
15
16 "google.golang.org/protobuf/internal/encoding/json"
17 )
18
19 type R struct {
20
21 E string
22
23 V checker
24
25 P int
26
27 RS string
28 }
29
30
31 type checker interface {
32
33
34
35 check(json.Token) string
36 }
37
38
39 var (
40 EOF = kindOnly{json.EOF}
41 Null = kindOnly{json.Null}
42 ObjectOpen = kindOnly{json.ObjectOpen}
43 ObjectClose = kindOnly{json.ObjectClose}
44 ArrayOpen = kindOnly{json.ArrayOpen}
45 ArrayClose = kindOnly{json.ArrayClose}
46 )
47
48 type kindOnly struct {
49 want json.Kind
50 }
51
52 func (x kindOnly) check(tok json.Token) string {
53 if got := tok.Kind(); got != x.want {
54 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, x.want)
55 }
56 return ""
57 }
58
59 type Name struct {
60 val string
61 }
62
63 func (x Name) check(tok json.Token) string {
64 if got := tok.Kind(); got != json.Name {
65 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Name)
66 }
67
68 if got := tok.Name(); got != x.val {
69 return fmt.Sprintf("Token.Name(): got %v, want %v", got, x.val)
70 }
71 return ""
72 }
73
74 type Bool struct {
75 val bool
76 }
77
78 func (x Bool) check(tok json.Token) string {
79 if got := tok.Kind(); got != json.Bool {
80 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Bool)
81 }
82
83 if got := tok.Bool(); got != x.val {
84 return fmt.Sprintf("Token.Bool(): got %v, want %v", got, x.val)
85 }
86 return ""
87 }
88
89 type Str struct {
90 val string
91 }
92
93 func (x Str) check(tok json.Token) string {
94 if got := tok.Kind(); got != json.String {
95 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.String)
96 }
97
98 if got := tok.ParsedString(); got != x.val {
99 return fmt.Sprintf("Token.ParsedString(): got %v, want %v", got, x.val)
100 }
101 return ""
102 }
103
104 type F64 struct {
105 val float64
106 }
107
108 func (x F64) check(tok json.Token) string {
109 if got := tok.Kind(); got != json.Number {
110 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
111 }
112
113 got, ok := tok.Float(64)
114 if !ok {
115 return fmt.Sprintf("Token.Float(64): returned not ok")
116 }
117 if got != x.val {
118 return fmt.Sprintf("Token.Float(64): got %v, want %v", got, x.val)
119 }
120 return ""
121 }
122
123 type F32 struct {
124 val float32
125 }
126
127 func (x F32) check(tok json.Token) string {
128 if got := tok.Kind(); got != json.Number {
129 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
130 }
131
132 got, ok := tok.Float(32)
133 if !ok {
134 return fmt.Sprintf("Token.Float(32): returned not ok")
135 }
136 if float32(got) != x.val {
137 return fmt.Sprintf("Token.Float(32): got %v, want %v", got, x.val)
138 }
139 return ""
140 }
141
142
143 var NotF64 = xf64{}
144
145 type xf64 struct{}
146
147 func (x xf64) check(tok json.Token) string {
148 if got := tok.Kind(); got != json.Number {
149 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
150 }
151
152 _, ok := tok.Float(64)
153 if ok {
154 return fmt.Sprintf("Token.Float(64): returned ok")
155 }
156 return ""
157 }
158
159
160 var NotF32 = xf32{}
161
162 type xf32 struct{}
163
164 func (x xf32) check(tok json.Token) string {
165 if got := tok.Kind(); got != json.Number {
166 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
167 }
168
169 _, ok := tok.Float(32)
170 if ok {
171 return fmt.Sprintf("Token.Float(32): returned ok")
172 }
173 return ""
174 }
175
176 type I64 struct {
177 val int64
178 }
179
180 func (x I64) check(tok json.Token) string {
181 if got := tok.Kind(); got != json.Number {
182 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
183 }
184
185 got, ok := tok.Int(64)
186 if !ok {
187 return fmt.Sprintf("Token.Int(64): returned not ok")
188 }
189 if got != x.val {
190 return fmt.Sprintf("Token.Int(64): got %v, want %v", got, x.val)
191 }
192 return ""
193 }
194
195 type I32 struct {
196 val int32
197 }
198
199 func (x I32) check(tok json.Token) string {
200 if got := tok.Kind(); got != json.Number {
201 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
202 }
203
204 got, ok := tok.Int(32)
205 if !ok {
206 return fmt.Sprintf("Token.Int(32): returned not ok")
207 }
208 if int32(got) != x.val {
209 return fmt.Sprintf("Token.Int(32): got %v, want %v", got, x.val)
210 }
211 return ""
212 }
213
214
215 var NotI64 = xi64{}
216
217 type xi64 struct{}
218
219 func (x xi64) check(tok json.Token) string {
220 if got := tok.Kind(); got != json.Number {
221 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
222 }
223
224 _, ok := tok.Int(64)
225 if ok {
226 return fmt.Sprintf("Token.Int(64): returned ok")
227 }
228 return ""
229 }
230
231
232 var NotI32 = xi32{}
233
234 type xi32 struct{}
235
236 func (x xi32) check(tok json.Token) string {
237 if got := tok.Kind(); got != json.Number {
238 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
239 }
240
241 _, ok := tok.Int(32)
242 if ok {
243 return fmt.Sprintf("Token.Int(32): returned ok")
244 }
245 return ""
246 }
247
248 type Ui64 struct {
249 val uint64
250 }
251
252 func (x Ui64) check(tok json.Token) string {
253 if got := tok.Kind(); got != json.Number {
254 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
255 }
256
257 got, ok := tok.Uint(64)
258 if !ok {
259 return fmt.Sprintf("Token.Uint(64): returned not ok")
260 }
261 if got != x.val {
262 return fmt.Sprintf("Token.Uint(64): got %v, want %v", got, x.val)
263 }
264 return ""
265 }
266
267 type Ui32 struct {
268 val uint32
269 }
270
271 func (x Ui32) check(tok json.Token) string {
272 if got := tok.Kind(); got != json.Number {
273 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
274 }
275
276 got, ok := tok.Uint(32)
277 if !ok {
278 return fmt.Sprintf("Token.Uint(32): returned not ok")
279 }
280 if uint32(got) != x.val {
281 return fmt.Sprintf("Token.Uint(32): got %v, want %v", got, x.val)
282 }
283 return ""
284 }
285
286
287 var NotUi64 = xui64{}
288
289 type xui64 struct{}
290
291 func (x xui64) check(tok json.Token) string {
292 if got := tok.Kind(); got != json.Number {
293 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
294 }
295
296 _, ok := tok.Uint(64)
297 if ok {
298 return fmt.Sprintf("Token.Uint(64): returned ok")
299 }
300 return ""
301 }
302
303
304 var NotUi32 = xui32{}
305
306 type xui32 struct{}
307
308 func (x xui32) check(tok json.Token) string {
309 if got := tok.Kind(); got != json.Number {
310 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number)
311 }
312
313 _, ok := tok.Uint(32)
314 if ok {
315 return fmt.Sprintf("Token.Uint(32): returned ok")
316 }
317 return ""
318 }
319
320 var errEOF = json.ErrUnexpectedEOF.Error()
321
322 func TestDecoder(t *testing.T) {
323 const space = " \n\r\t"
324
325 tests := []struct {
326 in string
327
328
329
330
331 want []R
332 }{
333 {
334 in: ``,
335 want: []R{{V: EOF}},
336 },
337 {
338 in: space,
339 want: []R{{V: EOF}},
340 },
341 {
342
343
344 in: space,
345 want: []R{
346 {V: EOF},
347 {V: EOF},
348 {V: EOF},
349 },
350 },
351
352
353 {
354 in: space + `null` + space,
355 want: []R{
356 {V: Null, P: len(space), RS: `null`},
357 {V: EOF},
358 },
359 },
360 {
361 in: space + `true` + space,
362 want: []R{
363 {V: Bool{true}},
364 {V: EOF},
365 },
366 },
367 {
368 in: space + `false` + space,
369 want: []R{
370 {V: Bool{false}},
371 {V: EOF},
372 },
373 },
374 {
375
376 in: space + `foo` + space,
377 want: []R{
378 {E: `invalid value foo`},
379 {E: `invalid value foo`},
380 },
381 },
382
383
384 {
385 in: space + `""` + space,
386 want: []R{
387 {V: Str{}},
388 {V: EOF},
389 },
390 },
391 {
392 in: space + `"hello"` + space,
393 want: []R{
394 {V: Str{"hello"}, RS: `"hello"`},
395 {V: EOF},
396 },
397 },
398 {
399 in: `"hello`,
400 want: []R{{E: errEOF}},
401 },
402 {
403 in: "\"\x00\"",
404 want: []R{{E: `invalid character '\x00' in string`}},
405 },
406 {
407 in: "\"\u0031\u0032\"",
408 want: []R{
409 {V: Str{"12"}, RS: "\"\u0031\u0032\""},
410 {V: EOF},
411 },
412 },
413 {
414
415 in: "\"\xff\"",
416 want: []R{{E: `syntax error (line 1:1): invalid UTF-8 in string`}},
417 },
418 {
419 in: `"` + string(utf8.RuneError) + `"`,
420 want: []R{
421 {V: Str{string(utf8.RuneError)}},
422 {V: EOF},
423 },
424 },
425 {
426 in: `"\uFFFD"`,
427 want: []R{
428 {V: Str{string(utf8.RuneError)}},
429 {V: EOF},
430 },
431 },
432 {
433 in: `"\x"`,
434 want: []R{{E: `invalid escape code "\\x" in string`}},
435 },
436 {
437 in: `"\uXXXX"`,
438 want: []R{{E: `invalid escape code "\\uXXXX" in string`}},
439 },
440 {
441 in: `"\uDEAD"`,
442 want: []R{{E: errEOF}},
443 },
444 {
445 in: `"\uDEAD\uBEEF"`,
446 want: []R{{E: `invalid escape code "\\uBEEF" in string`}},
447 },
448 {
449 in: `"\uD800\udead"`,
450 want: []R{
451 {V: Str{`𐊭`}},
452 {V: EOF},
453 },
454 },
455 {
456 in: `"\u0000\"\\\/\b\f\n\r\t"`,
457 want: []R{
458 {V: Str{"\u0000\"\\/\b\f\n\r\t"}},
459 {V: EOF},
460 },
461 },
462
463
464 {
465 in: `-`,
466 want: []R{{E: `invalid value -`}},
467 },
468 {
469 in: `+0`,
470 want: []R{{E: `invalid value +0`}},
471 },
472 {
473 in: `-+`,
474 want: []R{{E: `invalid value -+`}},
475 },
476 {
477 in: `0.`,
478 want: []R{{E: `invalid value 0.`}},
479 },
480 {
481 in: `.1`,
482 want: []R{{E: `invalid value .1`}},
483 },
484 {
485 in: `1.0.1`,
486 want: []R{{E: `invalid value 1.0.1`}},
487 },
488 {
489 in: `1..1`,
490 want: []R{{E: `invalid value 1..1`}},
491 },
492 {
493 in: `-1-2`,
494 want: []R{{E: `invalid value -1-2`}},
495 },
496 {
497 in: `01`,
498 want: []R{{E: `invalid value 01`}},
499 },
500 {
501 in: `1e`,
502 want: []R{{E: `invalid value 1e`}},
503 },
504 {
505 in: `1e1.2`,
506 want: []R{{E: `invalid value 1e1.2`}},
507 },
508 {
509 in: `1Ee`,
510 want: []R{{E: `invalid value 1Ee`}},
511 },
512 {
513 in: `1.e1`,
514 want: []R{{E: `invalid value 1.e1`}},
515 },
516 {
517 in: `1.e+`,
518 want: []R{{E: `invalid value 1.e+`}},
519 },
520 {
521 in: `1e+-2`,
522 want: []R{{E: `invalid value 1e+-2`}},
523 },
524 {
525 in: `1e--2`,
526 want: []R{{E: `invalid value 1e--2`}},
527 },
528 {
529 in: `1.0true`,
530 want: []R{{E: `invalid value 1.0true`}},
531 },
532
533
534 {
535 in: space + `0.0` + space,
536 want: []R{
537 {V: F32{0}, P: len(space), RS: `0.0`},
538 {V: EOF},
539 },
540 },
541 {
542 in: space + `0` + space,
543 want: []R{
544 {V: F32{0}},
545 {V: EOF},
546 },
547 },
548 {
549 in: space + `-0` + space,
550 want: []R{
551 {V: F32{float32(math.Copysign(0, -1))}},
552 {V: EOF},
553 },
554 },
555 {
556 in: `-0`,
557 want: []R{
558 {V: F64{math.Copysign(0, -1)}},
559 {V: EOF},
560 },
561 },
562 {
563 in: `-0.0`,
564 want: []R{
565 {V: F32{float32(math.Copysign(0, -1))}},
566 {V: EOF},
567 },
568 },
569 {
570 in: `-0.0`,
571 want: []R{
572 {V: F64{math.Copysign(0, -1)}},
573 {V: EOF},
574 },
575 },
576 {
577 in: `-1.02`,
578 want: []R{
579 {V: F32{-1.02}},
580 {V: EOF},
581 },
582 },
583 {
584 in: `1.020000`,
585 want: []R{
586 {V: F32{1.02}},
587 {V: EOF},
588 },
589 },
590 {
591 in: `-1.0e0`,
592 want: []R{
593 {V: F32{-1}},
594 {V: EOF},
595 },
596 },
597 {
598 in: `1.0e-000`,
599 want: []R{
600 {V: F32{1}},
601 {V: EOF},
602 },
603 },
604 {
605 in: `1e+00`,
606 want: []R{
607 {V: F32{1}},
608 {V: EOF},
609 },
610 },
611 {
612 in: `1.02e3`,
613 want: []R{
614 {V: F32{1.02e3}},
615 {V: EOF},
616 },
617 },
618 {
619 in: `-1.02E03`,
620 want: []R{
621 {V: F32{-1.02e3}},
622 {V: EOF},
623 },
624 },
625 {
626 in: `1.0200e+3`,
627 want: []R{
628 {V: F32{1.02e3}},
629 {V: EOF},
630 },
631 },
632 {
633 in: `-1.0200E+03`,
634 want: []R{
635 {V: F32{-1.02e3}},
636 {V: EOF},
637 },
638 },
639 {
640 in: `1.0200e-3`,
641 want: []R{
642 {V: F32{1.02e-3}},
643 {V: EOF},
644 },
645 },
646 {
647 in: `-1.0200E-03`,
648 want: []R{
649 {V: F32{-1.02e-3}},
650 {V: EOF},
651 },
652 },
653 {
654
655 in: `3.4e39`,
656 want: []R{
657 {V: F64{3.4e39}},
658 {V: EOF},
659 },
660 },
661
662 {
663
664 in: `3.4e39`,
665 want: []R{
666 {V: NotF32},
667 {V: EOF},
668 },
669 },
670 {
671
672 in: `-3.4e39`,
673 want: []R{
674 {V: NotF32},
675 {V: EOF},
676 },
677 },
678 {
679
680 in: `1.79e+309`,
681 want: []R{
682 {V: NotF64},
683 {V: EOF},
684 },
685 },
686 {
687
688 in: `-1.79e+309`,
689 want: []R{
690 {V: NotF64},
691 {V: EOF},
692 },
693 },
694
695
696 {
697 in: space + `0` + space,
698 want: []R{
699 {V: I32{0}},
700 {V: EOF},
701 },
702 },
703 {
704 in: space + `-0` + space,
705 want: []R{
706 {V: I32{0}},
707 {V: EOF},
708 },
709 },
710 {
711
712 in: `1.00000`,
713 want: []R{
714 {V: I32{1}},
715 {V: EOF},
716 },
717 },
718 {
719
720 in: `1.0000000001`,
721 want: []R{
722 {V: NotI32},
723 {V: EOF},
724 },
725 },
726 {
727 in: `0e0`,
728 want: []R{
729 {V: I32{0}},
730 {V: EOF},
731 },
732 },
733 {
734 in: `0.0E0`,
735 want: []R{
736 {V: I32{0}},
737 {V: EOF},
738 },
739 },
740 {
741 in: `0.0E10`,
742 want: []R{
743 {V: I32{0}},
744 {V: EOF},
745 },
746 },
747 {
748 in: `-1`,
749 want: []R{
750 {V: I32{-1}},
751 {V: EOF},
752 },
753 },
754 {
755 in: `1.0e+0`,
756 want: []R{
757 {V: I32{1}},
758 {V: EOF},
759 },
760 },
761 {
762 in: `-1E-0`,
763 want: []R{
764 {V: I32{-1}},
765 {V: EOF},
766 },
767 },
768 {
769 in: `1E1`,
770 want: []R{
771 {V: I32{10}},
772 {V: EOF},
773 },
774 },
775 {
776 in: `-100.00e-02`,
777 want: []R{
778 {V: I32{-1}},
779 {V: EOF},
780 },
781 },
782 {
783 in: `0.1200E+02`,
784 want: []R{
785 {V: I64{12}},
786 {V: EOF},
787 },
788 },
789 {
790 in: `0.012e2`,
791 want: []R{
792 {V: NotI32},
793 {V: EOF},
794 },
795 },
796 {
797 in: `12e-2`,
798 want: []R{
799 {V: NotI32},
800 {V: EOF},
801 },
802 },
803 {
804
805 in: `2147483648`,
806 want: []R{
807 {V: NotI32},
808 {V: EOF},
809 },
810 },
811 {
812
813 in: `-2147483649`,
814 want: []R{
815 {V: NotI32},
816 {V: EOF},
817 },
818 },
819 {
820
821 in: `2147483648`,
822 want: []R{
823 {V: I64{2147483648}},
824 {V: EOF},
825 },
826 },
827 {
828
829 in: `-2147483649`,
830 want: []R{
831 {V: I64{-2147483649}},
832 {V: EOF},
833 },
834 },
835 {
836
837 in: `9223372036854775808`,
838 want: []R{
839 {V: NotI64},
840 {V: EOF},
841 },
842 },
843 {
844
845 in: `-9223372036854775809`,
846 want: []R{
847 {V: NotI64},
848 {V: EOF},
849 },
850 },
851
852
853 {
854 in: space + `0` + space,
855 want: []R{
856 {V: Ui32{0}},
857 {V: EOF},
858 },
859 },
860 {
861 in: space + `-0` + space,
862 want: []R{
863 {V: Ui32{0}},
864 {V: EOF},
865 },
866 },
867 {
868 in: `-1`,
869 want: []R{
870 {V: NotUi32},
871 {V: EOF},
872 },
873 },
874 {
875
876 in: `4294967296`,
877 want: []R{
878 {V: NotUi32},
879 {V: EOF},
880 },
881 },
882 {
883
884 in: `18446744073709551616`,
885 want: []R{
886 {V: NotUi64},
887 {V: EOF},
888 },
889 },
890
891
892 {
893 in: `true null`,
894 want: []R{
895 {V: Bool{true}},
896 {E: `(line 1:6): unexpected token null`},
897 },
898 },
899 {
900 in: "null false",
901 want: []R{
902 {V: Null},
903 {E: `unexpected token false`},
904 },
905 },
906 {
907 in: `true,false`,
908 want: []R{
909 {V: Bool{true}},
910 {E: `unexpected token ,`},
911 },
912 },
913 {
914 in: `47"hello"`,
915 want: []R{
916 {V: I32{47}},
917 {E: `unexpected token "hello"`},
918 },
919 },
920 {
921 in: `47 "hello"`,
922 want: []R{
923 {V: I32{47}},
924 {E: `unexpected token "hello"`},
925 },
926 },
927 {
928 in: `true 42`,
929 want: []R{
930 {V: Bool{true}},
931 {E: `unexpected token 42`},
932 },
933 },
934
935
936 {
937 in: space + `[]` + space,
938 want: []R{
939 {V: ArrayOpen},
940 {V: ArrayClose},
941 {V: EOF},
942 },
943 },
944 {
945 in: space + `[` + space + `]` + space,
946 want: []R{
947 {V: ArrayOpen, P: len(space), RS: `[`},
948 {V: ArrayClose},
949 {V: EOF},
950 },
951 },
952 {
953 in: space + `[` + space,
954 want: []R{
955 {V: ArrayOpen},
956 {E: errEOF},
957 },
958 },
959 {
960 in: space + `]` + space,
961 want: []R{{E: `unexpected token ]`}},
962 },
963 {
964 in: `[null,true,false, 1e1, "hello" ]`,
965 want: []R{
966 {V: ArrayOpen},
967 {V: Null},
968 {V: Bool{true}},
969 {V: Bool{false}},
970 {V: I32{10}},
971 {V: Str{"hello"}},
972 {V: ArrayClose},
973 {V: EOF},
974 },
975 },
976 {
977 in: `[` + space + `true` + space + `,` + space + `"hello"` + space + `]`,
978 want: []R{
979 {V: ArrayOpen},
980 {V: Bool{true}},
981 {V: Str{"hello"}},
982 {V: ArrayClose},
983 {V: EOF},
984 },
985 },
986 {
987 in: `[` + space + `true` + space + `,` + space + `]`,
988 want: []R{
989 {V: ArrayOpen},
990 {V: Bool{true}},
991 {E: `unexpected token ]`},
992 },
993 },
994 {
995 in: `[` + space + `false` + space + `]`,
996 want: []R{
997 {V: ArrayOpen},
998 {V: Bool{false}},
999 {V: ArrayClose},
1000 {V: EOF},
1001 },
1002 },
1003 {
1004 in: `[` + space + `1` + space + `0` + space + `]`,
1005 want: []R{
1006 {V: ArrayOpen},
1007 {V: I64{1}},
1008 {E: `unexpected token 0`},
1009 },
1010 },
1011 {
1012 in: `[null`,
1013 want: []R{
1014 {V: ArrayOpen},
1015 {V: Null},
1016 {E: errEOF},
1017 },
1018 },
1019 {
1020 in: `[foo]`,
1021 want: []R{
1022 {V: ArrayOpen},
1023 {E: `invalid value foo`},
1024 },
1025 },
1026 {
1027 in: `[{}, "hello", [true, false], null]`,
1028 want: []R{
1029 {V: ArrayOpen},
1030 {V: ObjectOpen},
1031 {V: ObjectClose},
1032 {V: Str{"hello"}},
1033 {V: ArrayOpen},
1034 {V: Bool{true}},
1035 {V: Bool{false}},
1036 {V: ArrayClose},
1037 {V: Null},
1038 {V: ArrayClose},
1039 {V: EOF},
1040 },
1041 },
1042 {
1043 in: `[{ ]`,
1044 want: []R{
1045 {V: ArrayOpen},
1046 {V: ObjectOpen},
1047 {E: `unexpected token ]`},
1048 },
1049 },
1050 {
1051 in: `[[ ]`,
1052 want: []R{
1053 {V: ArrayOpen},
1054 {V: ArrayOpen},
1055 {V: ArrayClose},
1056 {E: errEOF},
1057 },
1058 },
1059 {
1060 in: `[,]`,
1061 want: []R{
1062 {V: ArrayOpen},
1063 {E: `unexpected token ,`},
1064 },
1065 },
1066 {
1067 in: `[true "hello"]`,
1068 want: []R{
1069 {V: ArrayOpen},
1070 {V: Bool{true}},
1071 {E: `unexpected token "hello"`},
1072 },
1073 },
1074 {
1075 in: `[] null`,
1076 want: []R{
1077 {V: ArrayOpen},
1078 {V: ArrayClose},
1079 {E: `unexpected token null`},
1080 },
1081 },
1082 {
1083 in: `true []`,
1084 want: []R{
1085 {V: Bool{true}},
1086 {E: `unexpected token [`},
1087 },
1088 },
1089
1090
1091 {
1092 in: space + `{}` + space,
1093 want: []R{
1094 {V: ObjectOpen},
1095 {V: ObjectClose},
1096 {V: EOF},
1097 },
1098 },
1099 {
1100 in: space + `{` + space + `}` + space,
1101 want: []R{
1102 {V: ObjectOpen},
1103 {V: ObjectClose},
1104 {V: EOF},
1105 },
1106 },
1107 {
1108 in: space + `{` + space,
1109 want: []R{
1110 {V: ObjectOpen},
1111 {E: errEOF},
1112 },
1113 },
1114 {
1115 in: space + `}` + space,
1116 want: []R{{E: `unexpected token }`}},
1117 },
1118 {
1119 in: `{` + space + `null` + space + `}`,
1120 want: []R{
1121 {V: ObjectOpen},
1122 {E: `unexpected token null`},
1123 },
1124 },
1125 {
1126 in: `{[]}`,
1127 want: []R{
1128 {V: ObjectOpen},
1129 {E: `(line 1:2): unexpected token [`},
1130 },
1131 },
1132 {
1133 in: `{,}`,
1134 want: []R{
1135 {V: ObjectOpen},
1136 {E: `unexpected token ,`},
1137 },
1138 },
1139 {
1140 in: `{"345678"}`,
1141 want: []R{
1142 {V: ObjectOpen},
1143 {E: `(line 1:10): unexpected character }, missing ":" after field name`},
1144 },
1145 },
1146 {
1147 in: `{` + space + `"hello"` + space + `:` + space + `"world"` + space + `}`,
1148 want: []R{
1149 {V: ObjectOpen},
1150 {V: Name{"hello"}, P: len(space) + 1, RS: `"hello"`},
1151 {V: Str{"world"}, RS: `"world"`},
1152 {V: ObjectClose},
1153 {V: EOF},
1154 },
1155 },
1156 {
1157 in: `{"hello" "world"}`,
1158 want: []R{
1159 {V: ObjectOpen},
1160 {E: `(line 1:10): unexpected character ", missing ":" after field name`},
1161 },
1162 },
1163 {
1164 in: `{"hello":`,
1165 want: []R{
1166 {V: ObjectOpen},
1167 {V: Name{"hello"}},
1168 {E: errEOF},
1169 },
1170 },
1171 {
1172 in: `{"hello":"world"`,
1173 want: []R{
1174 {V: ObjectOpen},
1175 {V: Name{"hello"}},
1176 {V: Str{"world"}},
1177 {E: errEOF},
1178 },
1179 },
1180 {
1181 in: `{"hello":"world",`,
1182 want: []R{
1183 {V: ObjectOpen},
1184 {V: Name{"hello"}},
1185 {V: Str{"world"}},
1186 {E: errEOF},
1187 },
1188 },
1189 {
1190 in: `{""`,
1191 want: []R{
1192 {V: ObjectOpen},
1193 {E: errEOF},
1194 },
1195 },
1196 {
1197 in: `{"34":"89",}`,
1198 want: []R{
1199 {V: ObjectOpen},
1200 {V: Name{"34"}, RS: `"34"`},
1201 {V: Str{"89"}},
1202 {E: `syntax error (line 1:12): unexpected token }`},
1203 },
1204 },
1205 {
1206 in: `{
1207 "number": 123e2,
1208 "bool" : false,
1209 "object": {"string": "world"},
1210 "null" : null,
1211 "array" : [1.01, "hello", true],
1212 "string": "hello"
1213 }`,
1214 want: []R{
1215 {V: ObjectOpen},
1216
1217 {V: Name{"number"}},
1218 {V: I32{12300}},
1219
1220 {V: Name{"bool"}},
1221 {V: Bool{false}},
1222
1223 {V: Name{"object"}},
1224 {V: ObjectOpen},
1225 {V: Name{"string"}},
1226 {V: Str{"world"}},
1227 {V: ObjectClose},
1228
1229 {V: Name{"null"}},
1230 {V: Null},
1231
1232 {V: Name{"array"}},
1233 {V: ArrayOpen},
1234 {V: F32{1.01}},
1235 {V: Str{"hello"}},
1236 {V: Bool{true}},
1237 {V: ArrayClose},
1238
1239 {V: Name{"string"}},
1240 {V: Str{"hello"}},
1241
1242 {V: ObjectClose},
1243 {V: EOF},
1244 },
1245 },
1246 {
1247 in: `[
1248 {"object": {"number": 47}},
1249 ["list"],
1250 null
1251 ]`,
1252 want: []R{
1253 {V: ArrayOpen},
1254
1255 {V: ObjectOpen},
1256 {V: Name{"object"}},
1257 {V: ObjectOpen},
1258 {V: Name{"number"}},
1259 {V: I32{47}},
1260 {V: ObjectClose},
1261 {V: ObjectClose},
1262
1263 {V: ArrayOpen},
1264 {V: Str{"list"}},
1265 {V: ArrayClose},
1266
1267 {V: Null},
1268
1269 {V: ArrayClose},
1270 {V: EOF},
1271 },
1272 },
1273
1274
1275 {
1276 in: `12345678 x`,
1277 want: []R{
1278 {V: I64{12345678}},
1279 {E: `syntax error (line 1:10): invalid value x`},
1280 },
1281 },
1282 {
1283 in: "\ntrue\n x",
1284 want: []R{
1285 {V: Bool{true}},
1286 {E: `syntax error (line 3:4): invalid value x`},
1287 },
1288 },
1289 {
1290 in: `"💩"x`,
1291 want: []R{
1292 {V: Str{"💩"}},
1293 {E: `syntax error (line 1:4): invalid value x`},
1294 },
1295 },
1296 {
1297 in: "\n\n[\"🔥🔥🔥\"x",
1298 want: []R{
1299 {V: ArrayOpen},
1300 {V: Str{"🔥🔥🔥"}},
1301 {E: `syntax error (line 3:7): invalid value x`},
1302 },
1303 },
1304 {
1305
1306 in: `["👍🏻👍🏿"x`,
1307 want: []R{
1308 {V: ArrayOpen},
1309 {V: Str{"👍🏻👍🏿"}},
1310 {E: `syntax error (line 1:8): invalid value x`},
1311 },
1312 },
1313 }
1314
1315 for _, tc := range tests {
1316 tc := tc
1317 t.Run("", func(t *testing.T) {
1318 dec := json.NewDecoder([]byte(tc.in))
1319 for i, want := range tc.want {
1320 peekTok, peekErr := dec.Peek()
1321 tok, err := dec.Read()
1322 if err != nil {
1323 if want.E == "" {
1324 errorf(t, tc.in, "want#%d: Read() got unexpected error: %v", i, err)
1325 } else if !strings.Contains(err.Error(), want.E) {
1326 errorf(t, tc.in, "want#%d: Read() got %q, want %q", i, err, want.E)
1327 }
1328 return
1329 }
1330 if want.E != "" {
1331 errorf(t, tc.in, "want#%d: Read() got nil error, want %q", i, want.E)
1332 return
1333 }
1334 checkToken(t, tok, i, want, tc.in)
1335 if !cmp.Equal(tok, peekTok, cmp.Comparer(json.TokenEquals)) {
1336 errorf(t, tc.in, "want#%d: Peek() %+v != Read() token %+v", i, peekTok, tok)
1337 }
1338 if err != peekErr {
1339 errorf(t, tc.in, "want#%d: Peek() error %v != Read() error %v", i, err, peekErr)
1340 }
1341 }
1342 })
1343 }
1344 }
1345
1346 func checkToken(t *testing.T, tok json.Token, idx int, r R, in string) {
1347
1348 if r.P > 0 {
1349 got := tok.Pos()
1350 if got != r.P {
1351 errorf(t, in, "want#%d: Token.Pos() got %v want %v", idx, got, r.P)
1352 }
1353 }
1354
1355 if len(r.RS) > 0 {
1356 got := tok.RawString()
1357 if got != r.RS {
1358 errorf(t, in, "want#%d: Token.RawString() got %v want %v", idx, got, r.P)
1359 }
1360 }
1361
1362
1363 if r.V == nil {
1364 return
1365 }
1366
1367 if err := r.V.check(tok); err != "" {
1368 errorf(t, in, "want#%d: %s", idx, err)
1369 }
1370 return
1371 }
1372
1373 func errorf(t *testing.T, in string, fmtStr string, args ...interface{}) {
1374 t.Helper()
1375 vargs := []interface{}{in}
1376 for _, arg := range args {
1377 vargs = append(vargs, arg)
1378 }
1379 t.Errorf("input:\n%s\n~end~\n"+fmtStr, vargs...)
1380 }
1381
1382 func TestClone(t *testing.T) {
1383 input := `{"outer":{"str":"hello", "number": 123}}`
1384 dec := json.NewDecoder([]byte(input))
1385
1386
1387 clone := dec.Clone()
1388 compareDecoders(t, dec, clone)
1389
1390
1391 dec.Read()
1392 dec.Read()
1393 clone = dec.Clone()
1394 compareDecoders(t, dec, clone)
1395 }
1396
1397 func compareDecoders(t *testing.T, d1 *json.Decoder, d2 *json.Decoder) {
1398 for {
1399 tok1, err1 := d1.Read()
1400 tok2, err2 := d2.Read()
1401 if tok1.Kind() != tok2.Kind() {
1402 t.Errorf("cloned decoder: got Kind %v, want %v", tok2.Kind(), tok1.Kind())
1403 }
1404 if tok1.RawString() != tok2.RawString() {
1405 t.Errorf("cloned decoder: got RawString %v, want %v", tok2.RawString(), tok1.RawString())
1406 }
1407 if err1 != err2 {
1408 t.Errorf("cloned decoder: got error %v, want %v", err2, err1)
1409 }
1410 if tok1.Kind() == json.EOF {
1411 break
1412 }
1413 }
1414 }
1415
View as plain text