Print "Global Exported" to dump_file from set_range_info.
[official-gcc.git] / libgo / go / encoding / json / encode_test.go
blob0b021f0074991d49f218bbc7b0a0682e1a60f3d2
1 // Copyright 2011 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.
5 package json
7 import (
8 "bytes"
9 "encoding"
10 "fmt"
11 "log"
12 "math"
13 "reflect"
14 "regexp"
15 "strconv"
16 "testing"
17 "unicode"
20 type Optionals struct {
21 Sr string `json:"sr"`
22 So string `json:"so,omitempty"`
23 Sw string `json:"-"`
25 Ir int `json:"omitempty"` // actually named omitempty, not an option
26 Io int `json:"io,omitempty"`
28 Slr []string `json:"slr,random"`
29 Slo []string `json:"slo,omitempty"`
31 Mr map[string]any `json:"mr"`
32 Mo map[string]any `json:",omitempty"`
34 Fr float64 `json:"fr"`
35 Fo float64 `json:"fo,omitempty"`
37 Br bool `json:"br"`
38 Bo bool `json:"bo,omitempty"`
40 Ur uint `json:"ur"`
41 Uo uint `json:"uo,omitempty"`
43 Str struct{} `json:"str"`
44 Sto struct{} `json:"sto,omitempty"`
47 var optionalsExpected = `{
48 "sr": "",
49 "omitempty": 0,
50 "slr": null,
51 "mr": {},
52 "fr": 0,
53 "br": false,
54 "ur": 0,
55 "str": {},
56 "sto": {}
59 func TestOmitEmpty(t *testing.T) {
60 var o Optionals
61 o.Sw = "something"
62 o.Mr = map[string]any{}
63 o.Mo = map[string]any{}
65 got, err := MarshalIndent(&o, "", " ")
66 if err != nil {
67 t.Fatal(err)
69 if got := string(got); got != optionalsExpected {
70 t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
74 type StringTag struct {
75 BoolStr bool `json:",string"`
76 IntStr int64 `json:",string"`
77 UintptrStr uintptr `json:",string"`
78 StrStr string `json:",string"`
79 NumberStr Number `json:",string"`
82 func TestRoundtripStringTag(t *testing.T) {
83 tests := []struct {
84 name string
85 in StringTag
86 want string // empty to just test that we roundtrip
89 name: "AllTypes",
90 in: StringTag{
91 BoolStr: true,
92 IntStr: 42,
93 UintptrStr: 44,
94 StrStr: "xzbit",
95 NumberStr: "46",
97 want: `{
98 "BoolStr": "true",
99 "IntStr": "42",
100 "UintptrStr": "44",
101 "StrStr": "\"xzbit\"",
102 "NumberStr": "46"
106 // See golang.org/issues/38173.
107 name: "StringDoubleEscapes",
108 in: StringTag{
109 StrStr: "\b\f\n\r\t\"\\",
110 NumberStr: "0", // just to satisfy the roundtrip
112 want: `{
113 "BoolStr": "false",
114 "IntStr": "0",
115 "UintptrStr": "0",
116 "StrStr": "\"\\u0008\\u000c\\n\\r\\t\\\"\\\\\"",
117 "NumberStr": "0"
121 for _, test := range tests {
122 t.Run(test.name, func(t *testing.T) {
123 // Indent with a tab prefix to make the multi-line string
124 // literals in the table nicer to read.
125 got, err := MarshalIndent(&test.in, "\t\t\t", "\t")
126 if err != nil {
127 t.Fatal(err)
129 if got := string(got); got != test.want {
130 t.Fatalf(" got: %s\nwant: %s\n", got, test.want)
133 // Verify that it round-trips.
134 var s2 StringTag
135 if err := Unmarshal(got, &s2); err != nil {
136 t.Fatalf("Decode: %v", err)
138 if !reflect.DeepEqual(test.in, s2) {
139 t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", test.in, string(got), s2)
145 // byte slices are special even if they're renamed types.
146 type renamedByte byte
147 type renamedByteSlice []byte
148 type renamedRenamedByteSlice []renamedByte
150 func TestEncodeRenamedByteSlice(t *testing.T) {
151 s := renamedByteSlice("abc")
152 result, err := Marshal(s)
153 if err != nil {
154 t.Fatal(err)
156 expect := `"YWJj"`
157 if string(result) != expect {
158 t.Errorf(" got %s want %s", result, expect)
160 r := renamedRenamedByteSlice("abc")
161 result, err = Marshal(r)
162 if err != nil {
163 t.Fatal(err)
165 if string(result) != expect {
166 t.Errorf(" got %s want %s", result, expect)
170 type SamePointerNoCycle struct {
171 Ptr1, Ptr2 *SamePointerNoCycle
174 var samePointerNoCycle = &SamePointerNoCycle{}
176 type PointerCycle struct {
177 Ptr *PointerCycle
180 var pointerCycle = &PointerCycle{}
182 type PointerCycleIndirect struct {
183 Ptrs []any
186 type RecursiveSlice []RecursiveSlice
188 var (
189 pointerCycleIndirect = &PointerCycleIndirect{}
190 mapCycle = make(map[string]any)
191 sliceCycle = []any{nil}
192 sliceNoCycle = []any{nil, nil}
193 recursiveSliceCycle = []RecursiveSlice{nil}
196 func init() {
197 ptr := &SamePointerNoCycle{}
198 samePointerNoCycle.Ptr1 = ptr
199 samePointerNoCycle.Ptr2 = ptr
201 pointerCycle.Ptr = pointerCycle
202 pointerCycleIndirect.Ptrs = []any{pointerCycleIndirect}
204 mapCycle["x"] = mapCycle
205 sliceCycle[0] = sliceCycle
206 sliceNoCycle[1] = sliceNoCycle[:1]
207 for i := startDetectingCyclesAfter; i > 0; i-- {
208 sliceNoCycle = []any{sliceNoCycle}
210 recursiveSliceCycle[0] = recursiveSliceCycle
213 func TestSamePointerNoCycle(t *testing.T) {
214 if _, err := Marshal(samePointerNoCycle); err != nil {
215 t.Fatalf("unexpected error: %v", err)
219 func TestSliceNoCycle(t *testing.T) {
220 if _, err := Marshal(sliceNoCycle); err != nil {
221 t.Fatalf("unexpected error: %v", err)
225 var unsupportedValues = []any{
226 math.NaN(),
227 math.Inf(-1),
228 math.Inf(1),
229 pointerCycle,
230 pointerCycleIndirect,
231 mapCycle,
232 sliceCycle,
233 recursiveSliceCycle,
236 func TestUnsupportedValues(t *testing.T) {
237 for _, v := range unsupportedValues {
238 if _, err := Marshal(v); err != nil {
239 if _, ok := err.(*UnsupportedValueError); !ok {
240 t.Errorf("for %v, got %T want UnsupportedValueError", v, err)
242 } else {
243 t.Errorf("for %v, expected error", v)
248 // Issue 43207
249 func TestMarshalTextFloatMap(t *testing.T) {
250 m := map[textfloat]string{
251 textfloat(math.NaN()): "1",
252 textfloat(math.NaN()): "1",
254 got, err := Marshal(m)
255 if err != nil {
256 t.Errorf("Marshal() error: %v", err)
258 want := `{"TF:NaN":"1","TF:NaN":"1"}`
259 if string(got) != want {
260 t.Errorf("Marshal() = %s, want %s", got, want)
264 // Ref has Marshaler and Unmarshaler methods with pointer receiver.
265 type Ref int
267 func (*Ref) MarshalJSON() ([]byte, error) {
268 return []byte(`"ref"`), nil
271 func (r *Ref) UnmarshalJSON([]byte) error {
272 *r = 12
273 return nil
276 // Val has Marshaler methods with value receiver.
277 type Val int
279 func (Val) MarshalJSON() ([]byte, error) {
280 return []byte(`"val"`), nil
283 // RefText has Marshaler and Unmarshaler methods with pointer receiver.
284 type RefText int
286 func (*RefText) MarshalText() ([]byte, error) {
287 return []byte(`"ref"`), nil
290 func (r *RefText) UnmarshalText([]byte) error {
291 *r = 13
292 return nil
295 // ValText has Marshaler methods with value receiver.
296 type ValText int
298 func (ValText) MarshalText() ([]byte, error) {
299 return []byte(`"val"`), nil
302 func TestRefValMarshal(t *testing.T) {
303 var s = struct {
304 R0 Ref
305 R1 *Ref
306 R2 RefText
307 R3 *RefText
308 V0 Val
309 V1 *Val
310 V2 ValText
311 V3 *ValText
313 R0: 12,
314 R1: new(Ref),
315 R2: 14,
316 R3: new(RefText),
317 V0: 13,
318 V1: new(Val),
319 V2: 15,
320 V3: new(ValText),
322 const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
323 b, err := Marshal(&s)
324 if err != nil {
325 t.Fatalf("Marshal: %v", err)
327 if got := string(b); got != want {
328 t.Errorf("got %q, want %q", got, want)
332 // C implements Marshaler and returns unescaped JSON.
333 type C int
335 func (C) MarshalJSON() ([]byte, error) {
336 return []byte(`"<&>"`), nil
339 // CText implements Marshaler and returns unescaped text.
340 type CText int
342 func (CText) MarshalText() ([]byte, error) {
343 return []byte(`"<&>"`), nil
346 func TestMarshalerEscaping(t *testing.T) {
347 var c C
348 want := `"\u003c\u0026\u003e"`
349 b, err := Marshal(c)
350 if err != nil {
351 t.Fatalf("Marshal(c): %v", err)
353 if got := string(b); got != want {
354 t.Errorf("Marshal(c) = %#q, want %#q", got, want)
357 var ct CText
358 want = `"\"\u003c\u0026\u003e\""`
359 b, err = Marshal(ct)
360 if err != nil {
361 t.Fatalf("Marshal(ct): %v", err)
363 if got := string(b); got != want {
364 t.Errorf("Marshal(ct) = %#q, want %#q", got, want)
368 func TestAnonymousFields(t *testing.T) {
369 tests := []struct {
370 label string // Test name
371 makeInput func() any // Function to create input value
372 want string // Expected JSON output
374 // Both S1 and S2 have a field named X. From the perspective of S,
375 // it is ambiguous which one X refers to.
376 // This should not serialize either field.
377 label: "AmbiguousField",
378 makeInput: func() any {
379 type (
380 S1 struct{ x, X int }
381 S2 struct{ x, X int }
382 S struct {
387 return S{S1{1, 2}, S2{3, 4}}
389 want: `{}`,
390 }, {
391 label: "DominantField",
392 // Both S1 and S2 have a field named X, but since S has an X field as
393 // well, it takes precedence over S1.X and S2.X.
394 makeInput: func() any {
395 type (
396 S1 struct{ x, X int }
397 S2 struct{ x, X int }
398 S struct {
401 x, X int
404 return S{S1{1, 2}, S2{3, 4}, 5, 6}
406 want: `{"X":6}`,
407 }, {
408 // Unexported embedded field of non-struct type should not be serialized.
409 label: "UnexportedEmbeddedInt",
410 makeInput: func() any {
411 type (
412 myInt int
413 S struct{ myInt }
415 return S{5}
417 want: `{}`,
418 }, {
419 // Exported embedded field of non-struct type should be serialized.
420 label: "ExportedEmbeddedInt",
421 makeInput: func() any {
422 type (
423 MyInt int
424 S struct{ MyInt }
426 return S{5}
428 want: `{"MyInt":5}`,
429 }, {
430 // Unexported embedded field of pointer to non-struct type
431 // should not be serialized.
432 label: "UnexportedEmbeddedIntPointer",
433 makeInput: func() any {
434 type (
435 myInt int
436 S struct{ *myInt }
438 s := S{new(myInt)}
439 *s.myInt = 5
440 return s
442 want: `{}`,
443 }, {
444 // Exported embedded field of pointer to non-struct type
445 // should be serialized.
446 label: "ExportedEmbeddedIntPointer",
447 makeInput: func() any {
448 type (
449 MyInt int
450 S struct{ *MyInt }
452 s := S{new(MyInt)}
453 *s.MyInt = 5
454 return s
456 want: `{"MyInt":5}`,
457 }, {
458 // Exported fields of embedded structs should have their
459 // exported fields be serialized regardless of whether the struct types
460 // themselves are exported.
461 label: "EmbeddedStruct",
462 makeInput: func() any {
463 type (
464 s1 struct{ x, X int }
465 S2 struct{ y, Y int }
466 S struct {
471 return S{s1{1, 2}, S2{3, 4}}
473 want: `{"X":2,"Y":4}`,
474 }, {
475 // Exported fields of pointers to embedded structs should have their
476 // exported fields be serialized regardless of whether the struct types
477 // themselves are exported.
478 label: "EmbeddedStructPointer",
479 makeInput: func() any {
480 type (
481 s1 struct{ x, X int }
482 S2 struct{ y, Y int }
483 S struct {
488 return S{&s1{1, 2}, &S2{3, 4}}
490 want: `{"X":2,"Y":4}`,
491 }, {
492 // Exported fields on embedded unexported structs at multiple levels
493 // of nesting should still be serialized.
494 label: "NestedStructAndInts",
495 makeInput: func() any {
496 type (
497 MyInt1 int
498 MyInt2 int
499 myInt int
500 s2 struct {
501 MyInt2
502 myInt
504 s1 struct {
505 MyInt1
506 myInt
509 S struct {
511 myInt
514 return S{s1{1, 2, s2{3, 4}}, 6}
516 want: `{"MyInt1":1,"MyInt2":3}`,
517 }, {
518 // If an anonymous struct pointer field is nil, we should ignore
519 // the embedded fields behind it. Not properly doing so may
520 // result in the wrong output or reflect panics.
521 label: "EmbeddedFieldBehindNilPointer",
522 makeInput: func() any {
523 type (
524 S2 struct{ Field string }
525 S struct{ *S2 }
527 return S{}
529 want: `{}`,
532 for _, tt := range tests {
533 t.Run(tt.label, func(t *testing.T) {
534 b, err := Marshal(tt.makeInput())
535 if err != nil {
536 t.Fatalf("Marshal() = %v, want nil error", err)
538 if string(b) != tt.want {
539 t.Fatalf("Marshal() = %q, want %q", b, tt.want)
545 type BugA struct {
546 S string
549 type BugB struct {
550 BugA
551 S string
554 type BugC struct {
555 S string
558 // Legal Go: We never use the repeated embedded field (S).
559 type BugX struct {
560 A int
561 BugA
562 BugB
565 // golang.org/issue/16042.
566 // Even if a nil interface value is passed in, as long as
567 // it implements Marshaler, it should be marshaled.
568 type nilJSONMarshaler string
570 func (nm *nilJSONMarshaler) MarshalJSON() ([]byte, error) {
571 if nm == nil {
572 return Marshal("0zenil0")
574 return Marshal("zenil:" + string(*nm))
577 // golang.org/issue/34235.
578 // Even if a nil interface value is passed in, as long as
579 // it implements encoding.TextMarshaler, it should be marshaled.
580 type nilTextMarshaler string
582 func (nm *nilTextMarshaler) MarshalText() ([]byte, error) {
583 if nm == nil {
584 return []byte("0zenil0"), nil
586 return []byte("zenil:" + string(*nm)), nil
589 // See golang.org/issue/16042 and golang.org/issue/34235.
590 func TestNilMarshal(t *testing.T) {
591 testCases := []struct {
592 v any
593 want string
595 {v: nil, want: `null`},
596 {v: new(float64), want: `0`},
597 {v: []any(nil), want: `null`},
598 {v: []string(nil), want: `null`},
599 {v: map[string]string(nil), want: `null`},
600 {v: []byte(nil), want: `null`},
601 {v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`},
602 {v: struct{ M Marshaler }{}, want: `{"M":null}`},
603 {v: struct{ M Marshaler }{(*nilJSONMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
604 {v: struct{ M any }{(*nilJSONMarshaler)(nil)}, want: `{"M":null}`},
605 {v: struct{ M encoding.TextMarshaler }{}, want: `{"M":null}`},
606 {v: struct{ M encoding.TextMarshaler }{(*nilTextMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
607 {v: struct{ M any }{(*nilTextMarshaler)(nil)}, want: `{"M":null}`},
610 for _, tt := range testCases {
611 out, err := Marshal(tt.v)
612 if err != nil || string(out) != tt.want {
613 t.Errorf("Marshal(%#v) = %#q, %#v, want %#q, nil", tt.v, out, err, tt.want)
614 continue
619 // Issue 5245.
620 func TestEmbeddedBug(t *testing.T) {
621 v := BugB{
622 BugA{"A"},
623 "B",
625 b, err := Marshal(v)
626 if err != nil {
627 t.Fatal("Marshal:", err)
629 want := `{"S":"B"}`
630 got := string(b)
631 if got != want {
632 t.Fatalf("Marshal: got %s want %s", got, want)
634 // Now check that the duplicate field, S, does not appear.
635 x := BugX{
636 A: 23,
638 b, err = Marshal(x)
639 if err != nil {
640 t.Fatal("Marshal:", err)
642 want = `{"A":23}`
643 got = string(b)
644 if got != want {
645 t.Fatalf("Marshal: got %s want %s", got, want)
649 type BugD struct { // Same as BugA after tagging.
650 XXX string `json:"S"`
653 // BugD's tagged S field should dominate BugA's.
654 type BugY struct {
655 BugA
656 BugD
659 // Test that a field with a tag dominates untagged fields.
660 func TestTaggedFieldDominates(t *testing.T) {
661 v := BugY{
662 BugA{"BugA"},
663 BugD{"BugD"},
665 b, err := Marshal(v)
666 if err != nil {
667 t.Fatal("Marshal:", err)
669 want := `{"S":"BugD"}`
670 got := string(b)
671 if got != want {
672 t.Fatalf("Marshal: got %s want %s", got, want)
676 // There are no tags here, so S should not appear.
677 type BugZ struct {
678 BugA
679 BugC
680 BugY // Contains a tagged S field through BugD; should not dominate.
683 func TestDuplicatedFieldDisappears(t *testing.T) {
684 v := BugZ{
685 BugA{"BugA"},
686 BugC{"BugC"},
687 BugY{
688 BugA{"nested BugA"},
689 BugD{"nested BugD"},
692 b, err := Marshal(v)
693 if err != nil {
694 t.Fatal("Marshal:", err)
696 want := `{}`
697 got := string(b)
698 if got != want {
699 t.Fatalf("Marshal: got %s want %s", got, want)
703 func TestStringBytes(t *testing.T) {
704 t.Parallel()
705 // Test that encodeState.stringBytes and encodeState.string use the same encoding.
706 var r []rune
707 for i := '\u0000'; i <= unicode.MaxRune; i++ {
708 if testing.Short() && i > 1000 {
709 i = unicode.MaxRune
711 r = append(r, i)
713 s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too
715 for _, escapeHTML := range []bool{true, false} {
716 es := &encodeState{}
717 es.string(s, escapeHTML)
719 esBytes := &encodeState{}
720 esBytes.stringBytes([]byte(s), escapeHTML)
722 enc := es.Buffer.String()
723 encBytes := esBytes.Buffer.String()
724 if enc != encBytes {
725 i := 0
726 for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] {
729 enc = enc[i:]
730 encBytes = encBytes[i:]
731 i = 0
732 for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] {
735 enc = enc[:len(enc)-i]
736 encBytes = encBytes[:len(encBytes)-i]
738 if len(enc) > 20 {
739 enc = enc[:20] + "..."
741 if len(encBytes) > 20 {
742 encBytes = encBytes[:20] + "..."
745 t.Errorf("with escapeHTML=%t, encodings differ at %#q vs %#q",
746 escapeHTML, enc, encBytes)
751 func TestIssue10281(t *testing.T) {
752 type Foo struct {
753 N Number
755 x := Foo{Number(`invalid`)}
757 b, err := Marshal(&x)
758 if err == nil {
759 t.Errorf("Marshal(&x) = %#q; want error", b)
763 func TestHTMLEscape(t *testing.T) {
764 var b, want bytes.Buffer
765 m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`
766 want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`))
767 HTMLEscape(&b, []byte(m))
768 if !bytes.Equal(b.Bytes(), want.Bytes()) {
769 t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes())
773 // golang.org/issue/8582
774 func TestEncodePointerString(t *testing.T) {
775 type stringPointer struct {
776 N *int64 `json:"n,string"`
778 var n int64 = 42
779 b, err := Marshal(stringPointer{N: &n})
780 if err != nil {
781 t.Fatalf("Marshal: %v", err)
783 if got, want := string(b), `{"n":"42"}`; got != want {
784 t.Errorf("Marshal = %s, want %s", got, want)
786 var back stringPointer
787 err = Unmarshal(b, &back)
788 if err != nil {
789 t.Fatalf("Unmarshal: %v", err)
791 if back.N == nil {
792 t.Fatalf("Unmarshaled nil N field")
794 if *back.N != 42 {
795 t.Fatalf("*N = %d; want 42", *back.N)
799 var encodeStringTests = []struct {
800 in string
801 out string
803 {"\x00", `"\u0000"`},
804 {"\x01", `"\u0001"`},
805 {"\x02", `"\u0002"`},
806 {"\x03", `"\u0003"`},
807 {"\x04", `"\u0004"`},
808 {"\x05", `"\u0005"`},
809 {"\x06", `"\u0006"`},
810 {"\x07", `"\u0007"`},
811 {"\x08", `"\u0008"`},
812 {"\x09", `"\t"`},
813 {"\x0a", `"\n"`},
814 {"\x0b", `"\u000b"`},
815 {"\x0c", `"\u000c"`},
816 {"\x0d", `"\r"`},
817 {"\x0e", `"\u000e"`},
818 {"\x0f", `"\u000f"`},
819 {"\x10", `"\u0010"`},
820 {"\x11", `"\u0011"`},
821 {"\x12", `"\u0012"`},
822 {"\x13", `"\u0013"`},
823 {"\x14", `"\u0014"`},
824 {"\x15", `"\u0015"`},
825 {"\x16", `"\u0016"`},
826 {"\x17", `"\u0017"`},
827 {"\x18", `"\u0018"`},
828 {"\x19", `"\u0019"`},
829 {"\x1a", `"\u001a"`},
830 {"\x1b", `"\u001b"`},
831 {"\x1c", `"\u001c"`},
832 {"\x1d", `"\u001d"`},
833 {"\x1e", `"\u001e"`},
834 {"\x1f", `"\u001f"`},
837 func TestEncodeString(t *testing.T) {
838 for _, tt := range encodeStringTests {
839 b, err := Marshal(tt.in)
840 if err != nil {
841 t.Errorf("Marshal(%q): %v", tt.in, err)
842 continue
844 out := string(b)
845 if out != tt.out {
846 t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out)
851 type jsonbyte byte
853 func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) }
855 type textbyte byte
857 func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) }
859 type jsonint int
861 func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) }
863 type textint int
865 func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) }
867 func tenc(format string, a ...any) ([]byte, error) {
868 var buf bytes.Buffer
869 fmt.Fprintf(&buf, format, a...)
870 return buf.Bytes(), nil
873 type textfloat float64
875 func (f textfloat) MarshalText() ([]byte, error) { return tenc(`TF:%0.2f`, f) }
877 // Issue 13783
878 func TestEncodeBytekind(t *testing.T) {
879 testdata := []struct {
880 data any
881 want string
883 {byte(7), "7"},
884 {jsonbyte(7), `{"JB":7}`},
885 {textbyte(4), `"TB:4"`},
886 {jsonint(5), `{"JI":5}`},
887 {textint(1), `"TI:1"`},
888 {[]byte{0, 1}, `"AAE="`},
889 {[]jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`},
890 {[][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`},
891 {[]textbyte{2, 3}, `["TB:2","TB:3"]`},
892 {[]jsonint{5, 4}, `[{"JI":5},{"JI":4}]`},
893 {[]textint{9, 3}, `["TI:9","TI:3"]`},
894 {[]int{9, 3}, `[9,3]`},
895 {[]textfloat{12, 3}, `["TF:12.00","TF:3.00"]`},
897 for _, d := range testdata {
898 js, err := Marshal(d.data)
899 if err != nil {
900 t.Error(err)
901 continue
903 got, want := string(js), d.want
904 if got != want {
905 t.Errorf("got %s, want %s", got, want)
910 func TestTextMarshalerMapKeysAreSorted(t *testing.T) {
911 b, err := Marshal(map[unmarshalerText]int{
912 {"x", "y"}: 1,
913 {"y", "x"}: 2,
914 {"a", "z"}: 3,
915 {"z", "a"}: 4,
917 if err != nil {
918 t.Fatalf("Failed to Marshal text.Marshaler: %v", err)
920 const want = `{"a:z":3,"x:y":1,"y:x":2,"z:a":4}`
921 if string(b) != want {
922 t.Errorf("Marshal map with text.Marshaler keys: got %#q, want %#q", b, want)
926 // https://golang.org/issue/33675
927 func TestNilMarshalerTextMapKey(t *testing.T) {
928 b, err := Marshal(map[*unmarshalerText]int{
929 (*unmarshalerText)(nil): 1,
930 {"A", "B"}: 2,
932 if err != nil {
933 t.Fatalf("Failed to Marshal *text.Marshaler: %v", err)
935 const want = `{"":1,"A:B":2}`
936 if string(b) != want {
937 t.Errorf("Marshal map with *text.Marshaler keys: got %#q, want %#q", b, want)
941 var re = regexp.MustCompile
943 // syntactic checks on form of marshaled floating point numbers.
944 var badFloatREs = []*regexp.Regexp{
945 re(`p`), // no binary exponential notation
946 re(`^\+`), // no leading + sign
947 re(`^-?0[^.]`), // no unnecessary leading zeros
948 re(`^-?\.`), // leading zero required before decimal point
949 re(`\.(e|$)`), // no trailing decimal
950 re(`\.[0-9]+0(e|$)`), // no trailing zero in fraction
951 re(`^-?(0|[0-9]{2,})\..*e`), // exponential notation must have normalized mantissa
952 re(`e[0-9]`), // positive exponent must be signed
953 re(`e[+-]0`), // exponent must not have leading zeros
954 re(`e-[1-6]$`), // not tiny enough for exponential notation
955 re(`e+(.|1.|20)$`), // not big enough for exponential notation
956 re(`^-?0\.0000000`), // too tiny, should use exponential notation
957 re(`^-?[0-9]{22}`), // too big, should use exponential notation
958 re(`[1-9][0-9]{16}[1-9]`), // too many significant digits in integer
959 re(`[1-9][0-9.]{17}[1-9]`), // too many significant digits in decimal
960 // below here for float32 only
961 re(`[1-9][0-9]{8}[1-9]`), // too many significant digits in integer
962 re(`[1-9][0-9.]{9}[1-9]`), // too many significant digits in decimal
965 func TestMarshalFloat(t *testing.T) {
966 t.Parallel()
967 nfail := 0
968 test := func(f float64, bits int) {
969 vf := any(f)
970 if bits == 32 {
971 f = float64(float32(f)) // round
972 vf = float32(f)
974 bout, err := Marshal(vf)
975 if err != nil {
976 t.Errorf("Marshal(%T(%g)): %v", vf, vf, err)
977 nfail++
978 return
980 out := string(bout)
982 // result must convert back to the same float
983 g, err := strconv.ParseFloat(out, bits)
984 if err != nil {
985 t.Errorf("Marshal(%T(%g)) = %q, cannot parse back: %v", vf, vf, out, err)
986 nfail++
987 return
989 if f != g || fmt.Sprint(f) != fmt.Sprint(g) { // fmt.Sprint handles ±0
990 t.Errorf("Marshal(%T(%g)) = %q (is %g, not %g)", vf, vf, out, float32(g), vf)
991 nfail++
992 return
995 bad := badFloatREs
996 if bits == 64 {
997 bad = bad[:len(bad)-2]
999 for _, re := range bad {
1000 if re.MatchString(out) {
1001 t.Errorf("Marshal(%T(%g)) = %q, must not match /%s/", vf, vf, out, re)
1002 nfail++
1003 return
1008 var (
1009 bigger = math.Inf(+1)
1010 smaller = math.Inf(-1)
1013 var digits = "1.2345678901234567890123"
1014 for i := len(digits); i >= 2; i-- {
1015 if testing.Short() && i < len(digits)-4 {
1016 break
1018 for exp := -30; exp <= 30; exp++ {
1019 for _, sign := range "+-" {
1020 for bits := 32; bits <= 64; bits += 32 {
1021 s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp)
1022 f, err := strconv.ParseFloat(s, bits)
1023 if err != nil {
1024 log.Fatal(err)
1026 next := math.Nextafter
1027 if bits == 32 {
1028 next = func(g, h float64) float64 {
1029 return float64(math.Nextafter32(float32(g), float32(h)))
1032 test(f, bits)
1033 test(next(f, bigger), bits)
1034 test(next(f, smaller), bits)
1035 if nfail > 50 {
1036 t.Fatalf("stopping test early")
1042 test(0, 64)
1043 test(math.Copysign(0, -1), 64)
1044 test(0, 32)
1045 test(math.Copysign(0, -1), 32)
1048 func TestMarshalRawMessageValue(t *testing.T) {
1049 type (
1050 T1 struct {
1051 M RawMessage `json:",omitempty"`
1053 T2 struct {
1054 M *RawMessage `json:",omitempty"`
1058 var (
1059 rawNil = RawMessage(nil)
1060 rawEmpty = RawMessage([]byte{})
1061 rawText = RawMessage([]byte(`"foo"`))
1064 tests := []struct {
1065 in any
1066 want string
1067 ok bool
1069 // Test with nil RawMessage.
1070 {rawNil, "null", true},
1071 {&rawNil, "null", true},
1072 {[]any{rawNil}, "[null]", true},
1073 {&[]any{rawNil}, "[null]", true},
1074 {[]any{&rawNil}, "[null]", true},
1075 {&[]any{&rawNil}, "[null]", true},
1076 {struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
1077 {&struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
1078 {struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
1079 {&struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
1080 {map[string]any{"M": rawNil}, `{"M":null}`, true},
1081 {&map[string]any{"M": rawNil}, `{"M":null}`, true},
1082 {map[string]any{"M": &rawNil}, `{"M":null}`, true},
1083 {&map[string]any{"M": &rawNil}, `{"M":null}`, true},
1084 {T1{rawNil}, "{}", true},
1085 {T2{&rawNil}, `{"M":null}`, true},
1086 {&T1{rawNil}, "{}", true},
1087 {&T2{&rawNil}, `{"M":null}`, true},
1089 // Test with empty, but non-nil, RawMessage.
1090 {rawEmpty, "", false},
1091 {&rawEmpty, "", false},
1092 {[]any{rawEmpty}, "", false},
1093 {&[]any{rawEmpty}, "", false},
1094 {[]any{&rawEmpty}, "", false},
1095 {&[]any{&rawEmpty}, "", false},
1096 {struct{ X RawMessage }{rawEmpty}, "", false},
1097 {&struct{ X RawMessage }{rawEmpty}, "", false},
1098 {struct{ X *RawMessage }{&rawEmpty}, "", false},
1099 {&struct{ X *RawMessage }{&rawEmpty}, "", false},
1100 {map[string]any{"nil": rawEmpty}, "", false},
1101 {&map[string]any{"nil": rawEmpty}, "", false},
1102 {map[string]any{"nil": &rawEmpty}, "", false},
1103 {&map[string]any{"nil": &rawEmpty}, "", false},
1104 {T1{rawEmpty}, "{}", true},
1105 {T2{&rawEmpty}, "", false},
1106 {&T1{rawEmpty}, "{}", true},
1107 {&T2{&rawEmpty}, "", false},
1109 // Test with RawMessage with some text.
1111 // The tests below marked with Issue6458 used to generate "ImZvbyI=" instead "foo".
1112 // This behavior was intentionally changed in Go 1.8.
1113 // See https://golang.org/issues/14493#issuecomment-255857318
1114 {rawText, `"foo"`, true}, // Issue6458
1115 {&rawText, `"foo"`, true},
1116 {[]any{rawText}, `["foo"]`, true}, // Issue6458
1117 {&[]any{rawText}, `["foo"]`, true}, // Issue6458
1118 {[]any{&rawText}, `["foo"]`, true},
1119 {&[]any{&rawText}, `["foo"]`, true},
1120 {struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true}, // Issue6458
1121 {&struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true},
1122 {struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
1123 {&struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
1124 {map[string]any{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458
1125 {&map[string]any{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458
1126 {map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
1127 {&map[string]any{"M": &rawText}, `{"M":"foo"}`, true},
1128 {T1{rawText}, `{"M":"foo"}`, true}, // Issue6458
1129 {T2{&rawText}, `{"M":"foo"}`, true},
1130 {&T1{rawText}, `{"M":"foo"}`, true},
1131 {&T2{&rawText}, `{"M":"foo"}`, true},
1134 for i, tt := range tests {
1135 b, err := Marshal(tt.in)
1136 if ok := (err == nil); ok != tt.ok {
1137 if err != nil {
1138 t.Errorf("test %d, unexpected failure: %v", i, err)
1139 } else {
1140 t.Errorf("test %d, unexpected success", i)
1143 if got := string(b); got != tt.want {
1144 t.Errorf("test %d, Marshal(%#v) = %q, want %q", i, tt.in, got, tt.want)
1149 type marshalPanic struct{}
1151 func (marshalPanic) MarshalJSON() ([]byte, error) { panic(0xdead) }
1153 func TestMarshalPanic(t *testing.T) {
1154 defer func() {
1155 if got := recover(); !reflect.DeepEqual(got, 0xdead) {
1156 t.Errorf("panic() = (%T)(%v), want 0xdead", got, got)
1159 Marshal(&marshalPanic{})
1160 t.Error("Marshal should have panicked")
1163 func TestMarshalUncommonFieldNames(t *testing.T) {
1164 v := struct {
1165 A0, À,int
1167 b, err := Marshal(v)
1168 if err != nil {
1169 t.Fatal("Marshal:", err)
1171 want := `{"A0":0,"À":0,"Aβ":0}`
1172 got := string(b)
1173 if got != want {
1174 t.Fatalf("Marshal: got %s want %s", got, want)
1178 func TestMarshalerError(t *testing.T) {
1179 s := "test variable"
1180 st := reflect.TypeOf(s)
1181 errText := "json: test error"
1183 tests := []struct {
1184 err *MarshalerError
1185 want string
1188 &MarshalerError{st, fmt.Errorf(errText), ""},
1189 "json: error calling MarshalJSON for type " + st.String() + ": " + errText,
1192 &MarshalerError{st, fmt.Errorf(errText), "TestMarshalerError"},
1193 "json: error calling TestMarshalerError for type " + st.String() + ": " + errText,
1197 for i, tt := range tests {
1198 got := tt.err.Error()
1199 if got != tt.want {
1200 t.Errorf("MarshalerError test %d, got: %s, want: %s", i, got, tt.want)