Rebase.
[official-gcc.git] / libgo / go / encoding / json / encode_test.go
blob2e89a78eb9fd01d75631f1b9a7cc1e6002e38009
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 "math"
10 "reflect"
11 "testing"
12 "unicode"
15 type Optionals struct {
16 Sr string `json:"sr"`
17 So string `json:"so,omitempty"`
18 Sw string `json:"-"`
20 Ir int `json:"omitempty"` // actually named omitempty, not an option
21 Io int `json:"io,omitempty"`
23 Slr []string `json:"slr,random"`
24 Slo []string `json:"slo,omitempty"`
26 Mr map[string]interface{} `json:"mr"`
27 Mo map[string]interface{} `json:",omitempty"`
29 Fr float64 `json:"fr"`
30 Fo float64 `json:"fo,omitempty"`
32 Br bool `json:"br"`
33 Bo bool `json:"bo,omitempty"`
35 Ur uint `json:"ur"`
36 Uo uint `json:"uo,omitempty"`
38 Str struct{} `json:"str"`
39 Sto struct{} `json:"sto,omitempty"`
42 var optionalsExpected = `{
43 "sr": "",
44 "omitempty": 0,
45 "slr": null,
46 "mr": {},
47 "fr": 0,
48 "br": false,
49 "ur": 0,
50 "str": {},
51 "sto": {}
54 func TestOmitEmpty(t *testing.T) {
55 var o Optionals
56 o.Sw = "something"
57 o.Mr = map[string]interface{}{}
58 o.Mo = map[string]interface{}{}
60 got, err := MarshalIndent(&o, "", " ")
61 if err != nil {
62 t.Fatal(err)
64 if got := string(got); got != optionalsExpected {
65 t.Errorf(" got: %s\nwant: %s\n", got, optionalsExpected)
69 type StringTag struct {
70 BoolStr bool `json:",string"`
71 IntStr int64 `json:",string"`
72 StrStr string `json:",string"`
75 var stringTagExpected = `{
76 "BoolStr": "true",
77 "IntStr": "42",
78 "StrStr": "\"xzbit\""
81 func TestStringTag(t *testing.T) {
82 var s StringTag
83 s.BoolStr = true
84 s.IntStr = 42
85 s.StrStr = "xzbit"
86 got, err := MarshalIndent(&s, "", " ")
87 if err != nil {
88 t.Fatal(err)
90 if got := string(got); got != stringTagExpected {
91 t.Fatalf(" got: %s\nwant: %s\n", got, stringTagExpected)
94 // Verify that it round-trips.
95 var s2 StringTag
96 err = NewDecoder(bytes.NewReader(got)).Decode(&s2)
97 if err != nil {
98 t.Fatalf("Decode: %v", err)
100 if !reflect.DeepEqual(s, s2) {
101 t.Fatalf("decode didn't match.\nsource: %#v\nEncoded as:\n%s\ndecode: %#v", s, string(got), s2)
105 // byte slices are special even if they're renamed types.
106 type renamedByte byte
107 type renamedByteSlice []byte
108 type renamedRenamedByteSlice []renamedByte
110 func TestEncodeRenamedByteSlice(t *testing.T) {
111 s := renamedByteSlice("abc")
112 result, err := Marshal(s)
113 if err != nil {
114 t.Fatal(err)
116 expect := `"YWJj"`
117 if string(result) != expect {
118 t.Errorf(" got %s want %s", result, expect)
120 r := renamedRenamedByteSlice("abc")
121 result, err = Marshal(r)
122 if err != nil {
123 t.Fatal(err)
125 if string(result) != expect {
126 t.Errorf(" got %s want %s", result, expect)
130 var unsupportedValues = []interface{}{
131 math.NaN(),
132 math.Inf(-1),
133 math.Inf(1),
136 func TestUnsupportedValues(t *testing.T) {
137 for _, v := range unsupportedValues {
138 if _, err := Marshal(v); err != nil {
139 if _, ok := err.(*UnsupportedValueError); !ok {
140 t.Errorf("for %v, got %T want UnsupportedValueError", v, err)
142 } else {
143 t.Errorf("for %v, expected error", v)
148 // Ref has Marshaler and Unmarshaler methods with pointer receiver.
149 type Ref int
151 func (*Ref) MarshalJSON() ([]byte, error) {
152 return []byte(`"ref"`), nil
155 func (r *Ref) UnmarshalJSON([]byte) error {
156 *r = 12
157 return nil
160 // Val has Marshaler methods with value receiver.
161 type Val int
163 func (Val) MarshalJSON() ([]byte, error) {
164 return []byte(`"val"`), nil
167 // RefText has Marshaler and Unmarshaler methods with pointer receiver.
168 type RefText int
170 func (*RefText) MarshalText() ([]byte, error) {
171 return []byte(`"ref"`), nil
174 func (r *RefText) UnmarshalText([]byte) error {
175 *r = 13
176 return nil
179 // ValText has Marshaler methods with value receiver.
180 type ValText int
182 func (ValText) MarshalText() ([]byte, error) {
183 return []byte(`"val"`), nil
186 func TestRefValMarshal(t *testing.T) {
187 var s = struct {
188 R0 Ref
189 R1 *Ref
190 R2 RefText
191 R3 *RefText
192 V0 Val
193 V1 *Val
194 V2 ValText
195 V3 *ValText
197 R0: 12,
198 R1: new(Ref),
199 R2: 14,
200 R3: new(RefText),
201 V0: 13,
202 V1: new(Val),
203 V2: 15,
204 V3: new(ValText),
206 const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
207 b, err := Marshal(&s)
208 if err != nil {
209 t.Fatalf("Marshal: %v", err)
211 if got := string(b); got != want {
212 t.Errorf("got %q, want %q", got, want)
216 // C implements Marshaler and returns unescaped JSON.
217 type C int
219 func (C) MarshalJSON() ([]byte, error) {
220 return []byte(`"<&>"`), nil
223 // CText implements Marshaler and returns unescaped text.
224 type CText int
226 func (CText) MarshalText() ([]byte, error) {
227 return []byte(`"<&>"`), nil
230 func TestMarshalerEscaping(t *testing.T) {
231 var c C
232 want := `"\u003c\u0026\u003e"`
233 b, err := Marshal(c)
234 if err != nil {
235 t.Fatalf("Marshal(c): %v", err)
237 if got := string(b); got != want {
238 t.Errorf("Marshal(c) = %#q, want %#q", got, want)
241 var ct CText
242 want = `"\"\u003c\u0026\u003e\""`
243 b, err = Marshal(ct)
244 if err != nil {
245 t.Fatalf("Marshal(ct): %v", err)
247 if got := string(b); got != want {
248 t.Errorf("Marshal(ct) = %#q, want %#q", got, want)
252 type IntType int
254 type MyStruct struct {
255 IntType
258 func TestAnonymousNonstruct(t *testing.T) {
259 var i IntType = 11
260 a := MyStruct{i}
261 const want = `{"IntType":11}`
263 b, err := Marshal(a)
264 if err != nil {
265 t.Fatalf("Marshal: %v", err)
267 if got := string(b); got != want {
268 t.Errorf("got %q, want %q", got, want)
272 type BugA struct {
273 S string
276 type BugB struct {
277 BugA
278 S string
281 type BugC struct {
282 S string
285 // Legal Go: We never use the repeated embedded field (S).
286 type BugX struct {
287 A int
288 BugA
289 BugB
292 // Issue 5245.
293 func TestEmbeddedBug(t *testing.T) {
294 v := BugB{
295 BugA{"A"},
296 "B",
298 b, err := Marshal(v)
299 if err != nil {
300 t.Fatal("Marshal:", err)
302 want := `{"S":"B"}`
303 got := string(b)
304 if got != want {
305 t.Fatalf("Marshal: got %s want %s", got, want)
307 // Now check that the duplicate field, S, does not appear.
308 x := BugX{
309 A: 23,
311 b, err = Marshal(x)
312 if err != nil {
313 t.Fatal("Marshal:", err)
315 want = `{"A":23}`
316 got = string(b)
317 if got != want {
318 t.Fatalf("Marshal: got %s want %s", got, want)
322 type BugD struct { // Same as BugA after tagging.
323 XXX string `json:"S"`
326 // BugD's tagged S field should dominate BugA's.
327 type BugY struct {
328 BugA
329 BugD
332 // Test that a field with a tag dominates untagged fields.
333 func TestTaggedFieldDominates(t *testing.T) {
334 v := BugY{
335 BugA{"BugA"},
336 BugD{"BugD"},
338 b, err := Marshal(v)
339 if err != nil {
340 t.Fatal("Marshal:", err)
342 want := `{"S":"BugD"}`
343 got := string(b)
344 if got != want {
345 t.Fatalf("Marshal: got %s want %s", got, want)
349 // There are no tags here, so S should not appear.
350 type BugZ struct {
351 BugA
352 BugC
353 BugY // Contains a tagged S field through BugD; should not dominate.
356 func TestDuplicatedFieldDisappears(t *testing.T) {
357 v := BugZ{
358 BugA{"BugA"},
359 BugC{"BugC"},
360 BugY{
361 BugA{"nested BugA"},
362 BugD{"nested BugD"},
365 b, err := Marshal(v)
366 if err != nil {
367 t.Fatal("Marshal:", err)
369 want := `{}`
370 got := string(b)
371 if got != want {
372 t.Fatalf("Marshal: got %s want %s", got, want)
376 func TestStringBytes(t *testing.T) {
377 // Test that encodeState.stringBytes and encodeState.string use the same encoding.
378 es := &encodeState{}
379 var r []rune
380 for i := '\u0000'; i <= unicode.MaxRune; i++ {
381 r = append(r, i)
383 s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too
384 _, err := es.string(s)
385 if err != nil {
386 t.Fatal(err)
389 esBytes := &encodeState{}
390 _, err = esBytes.stringBytes([]byte(s))
391 if err != nil {
392 t.Fatal(err)
395 enc := es.Buffer.String()
396 encBytes := esBytes.Buffer.String()
397 if enc != encBytes {
398 i := 0
399 for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] {
402 enc = enc[i:]
403 encBytes = encBytes[i:]
404 i = 0
405 for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] {
408 enc = enc[:len(enc)-i]
409 encBytes = encBytes[:len(encBytes)-i]
411 if len(enc) > 20 {
412 enc = enc[:20] + "..."
414 if len(encBytes) > 20 {
415 encBytes = encBytes[:20] + "..."
418 t.Errorf("encodings differ at %#q vs %#q", enc, encBytes)
422 func TestIssue6458(t *testing.T) {
423 type Foo struct {
424 M RawMessage
426 x := Foo{RawMessage(`"foo"`)}
428 b, err := Marshal(&x)
429 if err != nil {
430 t.Fatal(err)
432 if want := `{"M":"foo"}`; string(b) != want {
433 t.Errorf("Marshal(&x) = %#q; want %#q", b, want)
436 b, err = Marshal(x)
437 if err != nil {
438 t.Fatal(err)
441 if want := `{"M":"ImZvbyI="}`; string(b) != want {
442 t.Errorf("Marshal(x) = %#q; want %#q", b, want)
446 func TestHTMLEscape(t *testing.T) {
447 var b, want bytes.Buffer
448 m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`
449 want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`))
450 HTMLEscape(&b, []byte(m))
451 if !bytes.Equal(b.Bytes(), want.Bytes()) {
452 t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes())