github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/encoding/json/encode_test.go (about)

     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.
     4  
     5  package json
     6  
     7  import (
     8  	"bytes"
     9  	"math"
    10  	"reflect"
    11  	"testing"
    12  	"unicode"
    13  )
    14  
    15  type Optionals struct {
    16  	Sr string `json:"sr"`
    17  	So string `json:"so,omitempty"`
    18  	Sw string `json:"-"`
    19  
    20  	Ir int `json:"omitempty"` // actually named omitempty, not an option
    21  	Io int `json:"io,omitempty"`
    22  
    23  	Slr []string `json:"slr,random"`
    24  	Slo []string `json:"slo,omitempty"`
    25  
    26  	Mr map[string]interface{} `json:"mr"`
    27  	Mo map[string]interface{} `json:",omitempty"`
    28  }
    29  
    30  var optionalsExpected = `{
    31   "sr": "",
    32   "omitempty": 0,
    33   "slr": null,
    34   "mr": {}
    35  }`
    36  
    37  func TestOmitEmpty(t *testing.T) {
    38  	var o Optionals
    39  	o.Sw = "something"
    40  	o.Mr = map[string]interface{}{}
    41  	o.Mo = map[string]interface{}{}
    42  
    43  	got, err := MarshalIndent(&o, "", " ")
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  	if got := string(got); got != optionalsExpected {
    48  		t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
    49  	}
    50  }
    51  
    52  type StringTag struct {
    53  	BoolStr bool   `json:",string"`
    54  	IntStr  int64  `json:",string"`
    55  	StrStr  string `json:",string"`
    56  }
    57  
    58  var stringTagExpected = `{
    59   "BoolStr": "true",
    60   "IntStr": "42",
    61   "StrStr": "\"xzbit\""
    62  }`
    63  
    64  func TestStringTag(t *testing.T) {
    65  	var s StringTag
    66  	s.BoolStr = true
    67  	s.IntStr = 42
    68  	s.StrStr = "xzbit"
    69  	got, err := MarshalIndent(&s, "", " ")
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  	if got := string(got); got != stringTagExpected {
    74  		t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected)
    75  	}
    76  
    77  	// Verify that it round-trips.
    78  	var s2 StringTag
    79  	err = NewDecoder(bytes.NewBuffer(got)).Decode(&s2)
    80  	if err != nil {
    81  		t.Fatalf("Decode: %v", err)
    82  	}
    83  	if !reflect.DeepEqual(s, s2) {
    84  		t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)
    85  	}
    86  }
    87  
    88  // byte slices are special even if they're renamed types.
    89  type renamedByte byte
    90  type renamedByteSlice []byte
    91  type renamedRenamedByteSlice []renamedByte
    92  
    93  func TestEncodeRenamedByteSlice(t *testing.T) {
    94  	s := renamedByteSlice("abc")
    95  	result, err := Marshal(s)
    96  	if err != nil {
    97  		t.Fatal(err)
    98  	}
    99  	expect := `"YWJj"`
   100  	if string(result) != expect {
   101  		t.Errorf(" got %s want %s", result, expect)
   102  	}
   103  	r := renamedRenamedByteSlice("abc")
   104  	result, err = Marshal(r)
   105  	if err != nil {
   106  		t.Fatal(err)
   107  	}
   108  	if string(result) != expect {
   109  		t.Errorf(" got %s want %s", result, expect)
   110  	}
   111  }
   112  
   113  var unsupportedValues = []interface{}{
   114  	math.NaN(),
   115  	math.Inf(-1),
   116  	math.Inf(1),
   117  }
   118  
   119  func TestUnsupportedValues(t *testing.T) {
   120  	for _, v := range unsupportedValues {
   121  		if _, err := Marshal(v); err != nil {
   122  			if _, ok := err.(*UnsupportedValueError); !ok {
   123  				t.Errorf("for %v, got %T want UnsupportedValueError", v, err)
   124  			}
   125  		} else {
   126  			t.Errorf("for %v, expected error", v)
   127  		}
   128  	}
   129  }
   130  
   131  // Ref has Marshaler and Unmarshaler methods with pointer receiver.
   132  type Ref int
   133  
   134  func (*Ref) MarshalJSON() ([]byte, error) {
   135  	return []byte(`"ref"`), nil
   136  }
   137  
   138  func (r *Ref) UnmarshalJSON([]byte) error {
   139  	*r = 12
   140  	return nil
   141  }
   142  
   143  // Val has Marshaler methods with value receiver.
   144  type Val int
   145  
   146  func (Val) MarshalJSON() ([]byte, error) {
   147  	return []byte(`"val"`), nil
   148  }
   149  
   150  // RefText has Marshaler and Unmarshaler methods with pointer receiver.
   151  type RefText int
   152  
   153  func (*RefText) MarshalText() ([]byte, error) {
   154  	return []byte(`"ref"`), nil
   155  }
   156  
   157  func (r *RefText) UnmarshalText([]byte) error {
   158  	*r = 13
   159  	return nil
   160  }
   161  
   162  // ValText has Marshaler methods with value receiver.
   163  type ValText int
   164  
   165  func (ValText) MarshalText() ([]byte, error) {
   166  	return []byte(`"val"`), nil
   167  }
   168  
   169  func TestRefValMarshal(t *testing.T) {
   170  	var s = struct {
   171  		R0 Ref
   172  		R1 *Ref
   173  		R2 RefText
   174  		R3 *RefText
   175  		V0 Val
   176  		V1 *Val
   177  		V2 ValText
   178  		V3 *ValText
   179  	}{
   180  		R0: 12,
   181  		R1: new(Ref),
   182  		R2: 14,
   183  		R3: new(RefText),
   184  		V0: 13,
   185  		V1: new(Val),
   186  		V2: 15,
   187  		V3: new(ValText),
   188  	}
   189  	const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
   190  	b, err := Marshal(&s)
   191  	if err != nil {
   192  		t.Fatalf("Marshal: %v", err)
   193  	}
   194  	if got := string(b); got != want {
   195  		t.Errorf("got %q, want %q", got, want)
   196  	}
   197  }
   198  
   199  // C implements Marshaler and returns unescaped JSON.
   200  type C int
   201  
   202  func (C) MarshalJSON() ([]byte, error) {
   203  	return []byte(`"<&>"`), nil
   204  }
   205  
   206  // CText implements Marshaler and returns unescaped text.
   207  type CText int
   208  
   209  func (CText) MarshalText() ([]byte, error) {
   210  	return []byte(`"<&>"`), nil
   211  }
   212  
   213  func TestMarshalerEscaping(t *testing.T) {
   214  	var c C
   215  	want := `"\u003c\u0026\u003e"`
   216  	b, err := Marshal(c)
   217  	if err != nil {
   218  		t.Fatalf("Marshal(c): %v", err)
   219  	}
   220  	if got := string(b); got != want {
   221  		t.Errorf("Marshal(c) = %#q, want %#q", got, want)
   222  	}
   223  
   224  	var ct CText
   225  	want = `"\"\u003c\u0026\u003e\""`
   226  	b, err = Marshal(ct)
   227  	if err != nil {
   228  		t.Fatalf("Marshal(ct): %v", err)
   229  	}
   230  	if got := string(b); got != want {
   231  		t.Errorf("Marshal(ct) = %#q, want %#q", got, want)
   232  	}
   233  }
   234  
   235  type IntType int
   236  
   237  type MyStruct struct {
   238  	IntType
   239  }
   240  
   241  func TestAnonymousNonstruct(t *testing.T) {
   242  	var i IntType = 11
   243  	a := MyStruct{i}
   244  	const want = `{"IntType":11}`
   245  
   246  	b, err := Marshal(a)
   247  	if err != nil {
   248  		t.Fatalf("Marshal: %v", err)
   249  	}
   250  	if got := string(b); got != want {
   251  		t.Errorf("got %q, want %q", got, want)
   252  	}
   253  }
   254  
   255  type BugA struct {
   256  	S string
   257  }
   258  
   259  type BugB struct {
   260  	BugA
   261  	S string
   262  }
   263  
   264  type BugC struct {
   265  	S string
   266  }
   267  
   268  // Legal Go: We never use the repeated embedded field (S).
   269  type BugX struct {
   270  	A int
   271  	BugA
   272  	BugB
   273  }
   274  
   275  // Issue 5245.
   276  func TestEmbeddedBug(t *testing.T) {
   277  	v := BugB{
   278  		BugA{"A"},
   279  		"B",
   280  	}
   281  	b, err := Marshal(v)
   282  	if err != nil {
   283  		t.Fatal("Marshal:", err)
   284  	}
   285  	want := `{"S":"B"}`
   286  	got := string(b)
   287  	if got != want {
   288  		t.Fatalf("Marshal: got %s want %s", got, want)
   289  	}
   290  	// Now check that the duplicate field, S, does not appear.
   291  	x := BugX{
   292  		A: 23,
   293  	}
   294  	b, err = Marshal(x)
   295  	if err != nil {
   296  		t.Fatal("Marshal:", err)
   297  	}
   298  	want = `{"A":23}`
   299  	got = string(b)
   300  	if got != want {
   301  		t.Fatalf("Marshal: got %s want %s", got, want)
   302  	}
   303  }
   304  
   305  type BugD struct { // Same as BugA after tagging.
   306  	XXX string `json:"S"`
   307  }
   308  
   309  // BugD's tagged S field should dominate BugA's.
   310  type BugY struct {
   311  	BugA
   312  	BugD
   313  }
   314  
   315  // Test that a field with a tag dominates untagged fields.
   316  func TestTaggedFieldDominates(t *testing.T) {
   317  	v := BugY{
   318  		BugA{"BugA"},
   319  		BugD{"BugD"},
   320  	}
   321  	b, err := Marshal(v)
   322  	if err != nil {
   323  		t.Fatal("Marshal:", err)
   324  	}
   325  	want := `{"S":"BugD"}`
   326  	got := string(b)
   327  	if got != want {
   328  		t.Fatalf("Marshal: got %s want %s", got, want)
   329  	}
   330  }
   331  
   332  // There are no tags here, so S should not appear.
   333  type BugZ struct {
   334  	BugA
   335  	BugC
   336  	BugY // Contains a tagged S field through BugD; should not dominate.
   337  }
   338  
   339  func TestDuplicatedFieldDisappears(t *testing.T) {
   340  	v := BugZ{
   341  		BugA{"BugA"},
   342  		BugC{"BugC"},
   343  		BugY{
   344  			BugA{"nested BugA"},
   345  			BugD{"nested BugD"},
   346  		},
   347  	}
   348  	b, err := Marshal(v)
   349  	if err != nil {
   350  		t.Fatal("Marshal:", err)
   351  	}
   352  	want := `{}`
   353  	got := string(b)
   354  	if got != want {
   355  		t.Fatalf("Marshal: got %s want %s", got, want)
   356  	}
   357  }
   358  
   359  func TestStringBytes(t *testing.T) {
   360  	// Test that encodeState.stringBytes and encodeState.string use the same encoding.
   361  	es := &encodeState{}
   362  	var r []rune
   363  	for i := '\u0000'; i <= unicode.MaxRune; i++ {
   364  		r = append(r, i)
   365  	}
   366  	s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too
   367  	_, err := es.string(s)
   368  	if err != nil {
   369  		t.Fatal(err)
   370  	}
   371  
   372  	esBytes := &encodeState{}
   373  	_, err = esBytes.stringBytes([]byte(s))
   374  	if err != nil {
   375  		t.Fatal(err)
   376  	}
   377  
   378  	enc := es.Buffer.String()
   379  	encBytes := esBytes.Buffer.String()
   380  	if enc != encBytes {
   381  		i := 0
   382  		for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] {
   383  			i++
   384  		}
   385  		enc = enc[i:]
   386  		encBytes = encBytes[i:]
   387  		i = 0
   388  		for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] {
   389  			i++
   390  		}
   391  		enc = enc[:len(enc)-i]
   392  		encBytes = encBytes[:len(encBytes)-i]
   393  
   394  		if len(enc) > 20 {
   395  			enc = enc[:20] + "..."
   396  		}
   397  		if len(encBytes) > 20 {
   398  			encBytes = encBytes[:20] + "..."
   399  		}
   400  
   401  		t.Errorf("encodings differ at %#q vs %#q", enc, encBytes)
   402  	}
   403  }