diff options
Diffstat (limited to 'src/pkg/encoding/json/encode_test.go')
-rw-r--r-- | src/pkg/encoding/json/encode_test.go | 123 |
1 files changed, 119 insertions, 4 deletions
diff --git a/src/pkg/encoding/json/encode_test.go b/src/pkg/encoding/json/encode_test.go index 5be0a992e..9395db7cb 100644 --- a/src/pkg/encoding/json/encode_test.go +++ b/src/pkg/encoding/json/encode_test.go @@ -9,6 +9,7 @@ import ( "math" "reflect" "testing" + "unicode" ) type Optionals struct { @@ -146,19 +147,46 @@ func (Val) MarshalJSON() ([]byte, error) { return []byte(`"val"`), nil } +// RefText has Marshaler and Unmarshaler methods with pointer receiver. +type RefText int + +func (*RefText) MarshalText() ([]byte, error) { + return []byte(`"ref"`), nil +} + +func (r *RefText) UnmarshalText([]byte) error { + *r = 13 + return nil +} + +// ValText has Marshaler methods with value receiver. +type ValText int + +func (ValText) MarshalText() ([]byte, error) { + return []byte(`"val"`), nil +} + func TestRefValMarshal(t *testing.T) { var s = struct { R0 Ref R1 *Ref + R2 RefText + R3 *RefText V0 Val V1 *Val + V2 ValText + V3 *ValText }{ R0: 12, R1: new(Ref), + R2: 14, + R3: new(RefText), V0: 13, V1: new(Val), + V2: 15, + V3: new(ValText), } - const want = `{"R0":"ref","R1":"ref","V0":"val","V1":"val"}` + const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}` b, err := Marshal(&s) if err != nil { t.Fatalf("Marshal: %v", err) @@ -175,15 +203,32 @@ func (C) MarshalJSON() ([]byte, error) { return []byte(`"<&>"`), nil } +// CText implements Marshaler and returns unescaped text. +type CText int + +func (CText) MarshalText() ([]byte, error) { + return []byte(`"<&>"`), nil +} + func TestMarshalerEscaping(t *testing.T) { var c C - const want = `"\u003c\u0026\u003e"` + want := `"\u003c\u0026\u003e"` b, err := Marshal(c) if err != nil { - t.Fatalf("Marshal: %v", err) + t.Fatalf("Marshal(c): %v", err) } if got := string(b); got != want { - t.Errorf("got %q, want %q", got, want) + t.Errorf("Marshal(c) = %#q, want %#q", got, want) + } + + var ct CText + want = `"\"\u003c\u0026\u003e\""` + b, err = Marshal(ct) + if err != nil { + t.Fatalf("Marshal(ct): %v", err) + } + if got := string(b); got != want { + t.Errorf("Marshal(ct) = %#q, want %#q", got, want) } } @@ -310,3 +355,73 @@ func TestDuplicatedFieldDisappears(t *testing.T) { t.Fatalf("Marshal: got %s want %s", got, want) } } + +func TestStringBytes(t *testing.T) { + // Test that encodeState.stringBytes and encodeState.string use the same encoding. + es := &encodeState{} + var r []rune + for i := '\u0000'; i <= unicode.MaxRune; i++ { + r = append(r, i) + } + s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too + _, err := es.string(s) + if err != nil { + t.Fatal(err) + } + + esBytes := &encodeState{} + _, err = esBytes.stringBytes([]byte(s)) + if err != nil { + t.Fatal(err) + } + + enc := es.Buffer.String() + encBytes := esBytes.Buffer.String() + if enc != encBytes { + i := 0 + for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] { + i++ + } + enc = enc[i:] + encBytes = encBytes[i:] + i = 0 + for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] { + i++ + } + enc = enc[:len(enc)-i] + encBytes = encBytes[:len(encBytes)-i] + + if len(enc) > 20 { + enc = enc[:20] + "..." + } + if len(encBytes) > 20 { + encBytes = encBytes[:20] + "..." + } + + t.Errorf("encodings differ at %#q vs %#q", enc, encBytes) + } +} + +func TestIssue6458(t *testing.T) { + type Foo struct { + M RawMessage + } + x := Foo{RawMessage(`"foo"`)} + + b, err := Marshal(&x) + if err != nil { + t.Fatal(err) + } + if want := `{"M":"foo"}`; string(b) != want { + t.Errorf("Marshal(&x) = %#q; want %#q", b, want) + } + + b, err = Marshal(x) + if err != nil { + t.Fatal(err) + } + + if want := `{"M":"ImZvbyI="}`; string(b) != want { + t.Errorf("Marshal(x) = %#q; want %#q", b, want) + } +} |