538 lines · 10.5 KB · Go
RawDownload
// Copyright 2011 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file. package json import (	"bytes"	"math"	"reflect"	"testing"	"unicode") type Optionals struct {	Sr string `json:"sr"`	So string `json:"so,omitempty"`	Sw string `json:"-"` 	Ir int `json:"omitempty"` // actually named omitempty, not an option	Io int `json:"io,omitempty"` 	Slr []string `json:"slr,random"`	Slo []string `json:"slo,omitempty"` 	Mr map[string]interface{} `json:"mr"`	Mo map[string]interface{} `json:",omitempty"` 	Fr float64 `json:"fr"`	Fo float64 `json:"fo,omitempty"` 	Br bool `json:"br"`	Bo bool `json:"bo,omitempty"` 	Ur uint `json:"ur"`	Uo uint `json:"uo,omitempty"` 	Str struct{} `json:"str"`	Sto struct{} `json:"sto,omitempty"`} var optionalsExpected = `{ "sr": "", "omitempty": 0, "slr": null, "mr": {}, "fr": 0, "br": false, "ur": 0, "str": {}, "sto": {}}` func TestOmitEmpty(t *testing.T) {	var o Optionals	o.Sw = "something"	o.Mr = map[string]interface{}{}	o.Mo = map[string]interface{}{} 	got, err := MarshalIndent(&o, "", " ")	if err != nil {		t.Fatal(err)	}	if got := string(got); got != optionalsExpected {		t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)	}} type StringTag struct {	BoolStr bool   `json:",string"`	IntStr  int64  `json:",string"`	StrStr  string `json:",string"`} var stringTagExpected = `{ "BoolStr": "true", "IntStr": "42", "StrStr": "\"xzbit\""}` func TestStringTag(t *testing.T) {	var s StringTag	s.BoolStr = true	s.IntStr = 42	s.StrStr = "xzbit"	got, err := MarshalIndent(&s, "", " ")	if err != nil {		t.Fatal(err)	}	if got := string(got); got != stringTagExpected {		t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected)	} 	// Verify that it round-trips.	var s2 StringTag	err = NewDecoder(bytes.NewReader(got)).Decode(&s2)	if err != nil {		t.Fatalf("Decode: %v", err)	}	if !reflect.DeepEqual(s, s2) {		t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)	}} // byte slices are special even if they're renamed types.type renamedByte bytetype renamedByteSlice []bytetype renamedRenamedByteSlice []renamedByte func TestEncodeRenamedByteSlice(t *testing.T) {	s := renamedByteSlice("abc")	result, err := Marshal(s)	if err != nil {		t.Fatal(err)	}	expect := `"YWJj"`	if string(result) != expect {		t.Errorf(" got %s want %s", result, expect)	}	r := renamedRenamedByteSlice("abc")	result, err = Marshal(r)	if err != nil {		t.Fatal(err)	}	if string(result) != expect {		t.Errorf(" got %s want %s", result, expect)	}} var unsupportedValues = []interface{}{	math.NaN(),	math.Inf(-1),	math.Inf(1),} func TestUnsupportedValues(t *testing.T) {	for _, v := range unsupportedValues {		if _, err := Marshal(v); err != nil {			if _, ok := err.(*UnsupportedValueError); !ok {				t.Errorf("for %v, got %T want UnsupportedValueError", v, err)			}		} else {			t.Errorf("for %v, expected error", v)		}	}} // Ref has Marshaler and Unmarshaler methods with pointer receiver.type Ref int func (*Ref) MarshalJSON() ([]byte, error) {	return []byte(`"ref"`), nil} func (r *Ref) UnmarshalJSON([]byte) error {	*r = 12	return nil} // Val has Marshaler methods with value receiver.type Val int 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","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`	b, err := Marshal(&s)	if err != nil {		t.Fatalf("Marshal: %v", err)	}	if got := string(b); got != want {		t.Errorf("got %q, want %q", got, want)	}} // C implements Marshaler and returns unescaped JSON.type C int 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	want := `"\u003c\u0026\u003e"`	b, err := Marshal(c)	if err != nil {		t.Fatalf("Marshal(c): %v", err)	}	if got := string(b); 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)	}} type IntType int type MyStruct struct {	IntType} func TestAnonymousNonstruct(t *testing.T) {	var i IntType = 11	a := MyStruct{i}	const want = `{"IntType":11}` 	b, err := Marshal(a)	if err != nil {		t.Fatalf("Marshal: %v", err)	}	if got := string(b); got != want {		t.Errorf("got %q, want %q", got, want)	}} type BugA struct {	S string} type BugB struct {	BugA	S string} type BugC struct {	S string} // Legal Go: We never use the repeated embedded field (S).type BugX struct {	A int	BugA	BugB} // Issue 5245.func TestEmbeddedBug(t *testing.T) {	v := BugB{		BugA{"A"},		"B",	}	b, err := Marshal(v)	if err != nil {		t.Fatal("Marshal:", err)	}	want := `{"S":"B"}`	got := string(b)	if got != want {		t.Fatalf("Marshal: got %s want %s", got, want)	}	// Now check that the duplicate field, S, does not appear.	x := BugX{		A: 23,	}	b, err = Marshal(x)	if err != nil {		t.Fatal("Marshal:", err)	}	want = `{"A":23}`	got = string(b)	if got != want {		t.Fatalf("Marshal: got %s want %s", got, want)	}} type BugD struct { // Same as BugA after tagging.	XXX string `json:"S"`} // BugD's tagged S field should dominate BugA's.type BugY struct {	BugA	BugD} // Test that a field with a tag dominates untagged fields.func TestTaggedFieldDominates(t *testing.T) {	v := BugY{		BugA{"BugA"},		BugD{"BugD"},	}	b, err := Marshal(v)	if err != nil {		t.Fatal("Marshal:", err)	}	want := `{"S":"BugD"}`	got := string(b)	if got != want {		t.Fatalf("Marshal: got %s want %s", got, want)	}} // There are no tags here, so S should not appear.type BugZ struct {	BugA	BugC	BugY // Contains a tagged S field through BugD; should not dominate.} func TestDuplicatedFieldDisappears(t *testing.T) {	v := BugZ{		BugA{"BugA"},		BugC{"BugC"},		BugY{			BugA{"nested BugA"},			BugD{"nested BugD"},		},	}	b, err := Marshal(v)	if err != nil {		t.Fatal("Marshal:", err)	}	want := `{}`	got := string(b)	if got != want {		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	es.string(s) 	esBytes := &encodeState{}	esBytes.stringBytes([]byte(s)) 	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)	}} func TestIssue10281(t *testing.T) {	type Foo struct {		N Number	}	x := Foo{Number(`invalid`)} 	b, err := Marshal(&x)	if err == nil {		t.Errorf("Marshal(&x) = %#q; want error", b)	}} func TestHTMLEscape(t *testing.T) {	var b, want bytes.Buffer	m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`	want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`))	HTMLEscape(&b, []byte(m))	if !bytes.Equal(b.Bytes(), want.Bytes()) {		t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes())	}} // golang.org/issue/8582func TestEncodePointerString(t *testing.T) {	type stringPointer struct {		N *int64 `json:"n,string"`	}	var n int64 = 42	b, err := Marshal(stringPointer{N: &n})	if err != nil {		t.Fatalf("Marshal: %v", err)	}	if got, want := string(b), `{"n":"42"}`; got != want {		t.Errorf("Marshal = %s, want %s", got, want)	}	var back stringPointer	err = Unmarshal(b, &back)	if err != nil {		t.Fatalf("Unmarshal: %v", err)	}	if back.N == nil {		t.Fatalf("Unmarshalled nil N field")	}	if *back.N != 42 {		t.Fatalf("*N = %d; want 42", *back.N)	}} var encodeStringTests = []struct {	in  string	out string}{	{"\x00", `"\u0000"`},	{"\x01", `"\u0001"`},	{"\x02", `"\u0002"`},	{"\x03", `"\u0003"`},	{"\x04", `"\u0004"`},	{"\x05", `"\u0005"`},	{"\x06", `"\u0006"`},	{"\x07", `"\u0007"`},	{"\x08", `"\u0008"`},

Lines 1–500 of 538.