OSDN Git Service

Update Go library to last weekly.
[pf3gnuchains/gcc-fork.git] / libgo / go / json / decode_test.go
1 // Copyright 2010 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         "os"
10         "reflect"
11         "strings"
12         "testing"
13 )
14
15 type T struct {
16         X string
17         Y int
18         Z int `json:"-"`
19 }
20
21 type tx struct {
22         x int
23 }
24
25 var txType = reflect.TypeOf((*tx)(nil)).Elem()
26
27 // A type that can unmarshal itself.
28
29 type unmarshaler struct {
30         T bool
31 }
32
33 func (u *unmarshaler) UnmarshalJSON(b []byte) os.Error {
34         *u = unmarshaler{true} // All we need to see that UnmarshalJson is called.
35         return nil
36 }
37
38 type ustruct struct {
39         M unmarshaler
40 }
41
42 var (
43         um0, um1 unmarshaler // target2 of unmarshaling
44         ump      = &um1
45         umtrue   = unmarshaler{true}
46         umslice  = []unmarshaler{{true}}
47         umslicep = new([]unmarshaler)
48         umstruct = ustruct{unmarshaler{true}}
49 )
50
51 type unmarshalTest struct {
52         in  string
53         ptr interface{}
54         out interface{}
55         err os.Error
56 }
57
58 var unmarshalTests = []unmarshalTest{
59         // basic types
60         {`true`, new(bool), true, nil},
61         {`1`, new(int), 1, nil},
62         {`1.2`, new(float64), 1.2, nil},
63         {`-5`, new(int16), int16(-5), nil},
64         {`"a\u1234"`, new(string), "a\u1234", nil},
65         {`"http:\/\/"`, new(string), "http://", nil},
66         {`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E", nil},
67         {`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
68         {"null", new(interface{}), nil, nil},
69         {`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.TypeOf("")}},
70         {`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
71
72         // Z has a "-" tag.
73         {`{"Y": 1, "Z": 2}`, new(T), T{Y: 1}, nil},
74
75         // syntax errors
76         {`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}},
77
78         // composite tests
79         {allValueIndent, new(All), allValue, nil},
80         {allValueCompact, new(All), allValue, nil},
81         {allValueIndent, new(*All), &allValue, nil},
82         {allValueCompact, new(*All), &allValue, nil},
83         {pallValueIndent, new(All), pallValue, nil},
84         {pallValueCompact, new(All), pallValue, nil},
85         {pallValueIndent, new(*All), &pallValue, nil},
86         {pallValueCompact, new(*All), &pallValue, nil},
87
88         // unmarshal interface test
89         {`{"T":false}`, &um0, umtrue, nil}, // use "false" so test will fail if custom unmarshaler is not called
90         {`{"T":false}`, &ump, &umtrue, nil},
91         {`[{"T":false}]`, &umslice, umslice, nil},
92         {`[{"T":false}]`, &umslicep, &umslice, nil},
93         {`{"M":{"T":false}}`, &umstruct, umstruct, nil},
94 }
95
96 func TestMarshal(t *testing.T) {
97         b, err := Marshal(allValue)
98         if err != nil {
99                 t.Fatalf("Marshal allValue: %v", err)
100         }
101         if string(b) != allValueCompact {
102                 t.Errorf("Marshal allValueCompact")
103                 diff(t, b, []byte(allValueCompact))
104                 return
105         }
106
107         b, err = Marshal(pallValue)
108         if err != nil {
109                 t.Fatalf("Marshal pallValue: %v", err)
110         }
111         if string(b) != pallValueCompact {
112                 t.Errorf("Marshal pallValueCompact")
113                 diff(t, b, []byte(pallValueCompact))
114                 return
115         }
116 }
117
118 func TestMarshalBadUTF8(t *testing.T) {
119         s := "hello\xffworld"
120         b, err := Marshal(s)
121         if err == nil {
122                 t.Fatal("Marshal bad UTF8: no error")
123         }
124         if len(b) != 0 {
125                 t.Fatal("Marshal returned data")
126         }
127         if _, ok := err.(*InvalidUTF8Error); !ok {
128                 t.Fatalf("Marshal did not return InvalidUTF8Error: %T %v", err, err)
129         }
130 }
131
132 func TestUnmarshal(t *testing.T) {
133         for i, tt := range unmarshalTests {
134                 var scan scanner
135                 in := []byte(tt.in)
136                 if err := checkValid(in, &scan); err != nil {
137                         if !reflect.DeepEqual(err, tt.err) {
138                                 t.Errorf("#%d: checkValid: %#v", i, err)
139                                 continue
140                         }
141                 }
142                 if tt.ptr == nil {
143                         continue
144                 }
145                 // v = new(right-type)
146                 v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
147                 if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) {
148                         t.Errorf("#%d: %v want %v", i, err, tt.err)
149                         continue
150                 }
151                 if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
152                         t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
153                         data, _ := Marshal(v.Elem().Interface())
154                         println(string(data))
155                         data, _ = Marshal(tt.out)
156                         println(string(data))
157                         continue
158                 }
159         }
160 }
161
162 func TestUnmarshalMarshal(t *testing.T) {
163         initBig()
164         var v interface{}
165         if err := Unmarshal(jsonBig, &v); err != nil {
166                 t.Fatalf("Unmarshal: %v", err)
167         }
168         b, err := Marshal(v)
169         if err != nil {
170                 t.Fatalf("Marshal: %v", err)
171         }
172         if bytes.Compare(jsonBig, b) != 0 {
173                 t.Errorf("Marshal jsonBig")
174                 diff(t, b, jsonBig)
175                 return
176         }
177 }
178
179 func TestLargeByteSlice(t *testing.T) {
180         s0 := make([]byte, 2000)
181         for i := range s0 {
182                 s0[i] = byte(i)
183         }
184         b, err := Marshal(s0)
185         if err != nil {
186                 t.Fatalf("Marshal: %v", err)
187         }
188         var s1 []byte
189         if err := Unmarshal(b, &s1); err != nil {
190                 t.Fatalf("Unmarshal: %v", err)
191         }
192         if bytes.Compare(s0, s1) != 0 {
193                 t.Errorf("Marshal large byte slice")
194                 diff(t, s0, s1)
195         }
196 }
197
198 type Xint struct {
199         X int
200 }
201
202 func TestUnmarshalInterface(t *testing.T) {
203         var xint Xint
204         var i interface{} = &xint
205         if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
206                 t.Fatalf("Unmarshal: %v", err)
207         }
208         if xint.X != 1 {
209                 t.Fatalf("Did not write to xint")
210         }
211 }
212
213 func TestUnmarshalPtrPtr(t *testing.T) {
214         var xint Xint
215         pxint := &xint
216         if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil {
217                 t.Fatalf("Unmarshal: %v", err)
218         }
219         if xint.X != 1 {
220                 t.Fatalf("Did not write to xint")
221         }
222 }
223
224 func TestEscape(t *testing.T) {
225         const input = `"foobar"<html>`
226         const expected = `"\"foobar\"\u003chtml\u003e"`
227         b, err := Marshal(input)
228         if err != nil {
229                 t.Fatalf("Marshal error: %v", err)
230         }
231         if s := string(b); s != expected {
232                 t.Errorf("Encoding of [%s] was [%s], want [%s]", input, s, expected)
233         }
234 }
235
236 func TestHTMLEscape(t *testing.T) {
237         b, err := MarshalForHTML("foobarbaz<>&quux")
238         if err != nil {
239                 t.Fatalf("MarshalForHTML error: %v", err)
240         }
241         if !bytes.Equal(b, []byte(`"foobarbaz\u003c\u003e\u0026quux"`)) {
242                 t.Fatalf("Unexpected encoding of \"<>&\": %s", b)
243         }
244 }
245
246 func noSpace(c int) int {
247         if isSpace(c) {
248                 return -1
249         }
250         return c
251 }
252
253 type All struct {
254         Bool    bool
255         Int     int
256         Int8    int8
257         Int16   int16
258         Int32   int32
259         Int64   int64
260         Uint    uint
261         Uint8   uint8
262         Uint16  uint16
263         Uint32  uint32
264         Uint64  uint64
265         Uintptr uintptr
266         Float32 float32
267         Float64 float64
268
269         Foo  string `json:"bar"`
270         Foo2 string `json:"bar2,dummyopt"`
271
272         IntStr int64 `json:",string"`
273
274         PBool    *bool
275         PInt     *int
276         PInt8    *int8
277         PInt16   *int16
278         PInt32   *int32
279         PInt64   *int64
280         PUint    *uint
281         PUint8   *uint8
282         PUint16  *uint16
283         PUint32  *uint32
284         PUint64  *uint64
285         PUintptr *uintptr
286         PFloat32 *float32
287         PFloat64 *float64
288
289         String  string
290         PString *string
291
292         Map   map[string]Small
293         MapP  map[string]*Small
294         PMap  *map[string]Small
295         PMapP *map[string]*Small
296
297         EmptyMap map[string]Small
298         NilMap   map[string]Small
299
300         Slice   []Small
301         SliceP  []*Small
302         PSlice  *[]Small
303         PSliceP *[]*Small
304
305         EmptySlice []Small
306         NilSlice   []Small
307
308         StringSlice []string
309         ByteSlice   []byte
310
311         Small   Small
312         PSmall  *Small
313         PPSmall **Small
314
315         Interface  interface{}
316         PInterface *interface{}
317
318         unexported int
319 }
320
321 type Small struct {
322         Tag string
323 }
324
325 var allValue = All{
326         Bool:    true,
327         Int:     2,
328         Int8:    3,
329         Int16:   4,
330         Int32:   5,
331         Int64:   6,
332         Uint:    7,
333         Uint8:   8,
334         Uint16:  9,
335         Uint32:  10,
336         Uint64:  11,
337         Uintptr: 12,
338         Float32: 14.1,
339         Float64: 15.1,
340         Foo:     "foo",
341         Foo2:    "foo2",
342         IntStr:  42,
343         String:  "16",
344         Map: map[string]Small{
345                 "17": {Tag: "tag17"},
346                 "18": {Tag: "tag18"},
347         },
348         MapP: map[string]*Small{
349                 "19": &Small{Tag: "tag19"},
350                 "20": nil,
351         },
352         EmptyMap:    map[string]Small{},
353         Slice:       []Small{{Tag: "tag20"}, {Tag: "tag21"}},
354         SliceP:      []*Small{&Small{Tag: "tag22"}, nil, &Small{Tag: "tag23"}},
355         EmptySlice:  []Small{},
356         StringSlice: []string{"str24", "str25", "str26"},
357         ByteSlice:   []byte{27, 28, 29},
358         Small:       Small{Tag: "tag30"},
359         PSmall:      &Small{Tag: "tag31"},
360         Interface:   5.2,
361 }
362
363 var pallValue = All{
364         PBool:      &allValue.Bool,
365         PInt:       &allValue.Int,
366         PInt8:      &allValue.Int8,
367         PInt16:     &allValue.Int16,
368         PInt32:     &allValue.Int32,
369         PInt64:     &allValue.Int64,
370         PUint:      &allValue.Uint,
371         PUint8:     &allValue.Uint8,
372         PUint16:    &allValue.Uint16,
373         PUint32:    &allValue.Uint32,
374         PUint64:    &allValue.Uint64,
375         PUintptr:   &allValue.Uintptr,
376         PFloat32:   &allValue.Float32,
377         PFloat64:   &allValue.Float64,
378         PString:    &allValue.String,
379         PMap:       &allValue.Map,
380         PMapP:      &allValue.MapP,
381         PSlice:     &allValue.Slice,
382         PSliceP:    &allValue.SliceP,
383         PPSmall:    &allValue.PSmall,
384         PInterface: &allValue.Interface,
385 }
386
387 var allValueIndent = `{
388         "Bool": true,
389         "Int": 2,
390         "Int8": 3,
391         "Int16": 4,
392         "Int32": 5,
393         "Int64": 6,
394         "Uint": 7,
395         "Uint8": 8,
396         "Uint16": 9,
397         "Uint32": 10,
398         "Uint64": 11,
399         "Uintptr": 12,
400         "Float32": 14.1,
401         "Float64": 15.1,
402         "bar": "foo",
403         "bar2": "foo2",
404         "IntStr": "42",
405         "PBool": null,
406         "PInt": null,
407         "PInt8": null,
408         "PInt16": null,
409         "PInt32": null,
410         "PInt64": null,
411         "PUint": null,
412         "PUint8": null,
413         "PUint16": null,
414         "PUint32": null,
415         "PUint64": null,
416         "PUintptr": null,
417         "PFloat32": null,
418         "PFloat64": null,
419         "String": "16",
420         "PString": null,
421         "Map": {
422                 "17": {
423                         "Tag": "tag17"
424                 },
425                 "18": {
426                         "Tag": "tag18"
427                 }
428         },
429         "MapP": {
430                 "19": {
431                         "Tag": "tag19"
432                 },
433                 "20": null
434         },
435         "PMap": null,
436         "PMapP": null,
437         "EmptyMap": {},
438         "NilMap": null,
439         "Slice": [
440                 {
441                         "Tag": "tag20"
442                 },
443                 {
444                         "Tag": "tag21"
445                 }
446         ],
447         "SliceP": [
448                 {
449                         "Tag": "tag22"
450                 },
451                 null,
452                 {
453                         "Tag": "tag23"
454                 }
455         ],
456         "PSlice": null,
457         "PSliceP": null,
458         "EmptySlice": [],
459         "NilSlice": [],
460         "StringSlice": [
461                 "str24",
462                 "str25",
463                 "str26"
464         ],
465         "ByteSlice": "Gxwd",
466         "Small": {
467                 "Tag": "tag30"
468         },
469         "PSmall": {
470                 "Tag": "tag31"
471         },
472         "PPSmall": null,
473         "Interface": 5.2,
474         "PInterface": null
475 }`
476
477 var allValueCompact = strings.Map(noSpace, allValueIndent)
478
479 var pallValueIndent = `{
480         "Bool": false,
481         "Int": 0,
482         "Int8": 0,
483         "Int16": 0,
484         "Int32": 0,
485         "Int64": 0,
486         "Uint": 0,
487         "Uint8": 0,
488         "Uint16": 0,
489         "Uint32": 0,
490         "Uint64": 0,
491         "Uintptr": 0,
492         "Float32": 0,
493         "Float64": 0,
494         "bar": "",
495         "bar2": "",
496         "IntStr": "0",
497         "PBool": true,
498         "PInt": 2,
499         "PInt8": 3,
500         "PInt16": 4,
501         "PInt32": 5,
502         "PInt64": 6,
503         "PUint": 7,
504         "PUint8": 8,
505         "PUint16": 9,
506         "PUint32": 10,
507         "PUint64": 11,
508         "PUintptr": 12,
509         "PFloat32": 14.1,
510         "PFloat64": 15.1,
511         "String": "",
512         "PString": "16",
513         "Map": null,
514         "MapP": null,
515         "PMap": {
516                 "17": {
517                         "Tag": "tag17"
518                 },
519                 "18": {
520                         "Tag": "tag18"
521                 }
522         },
523         "PMapP": {
524                 "19": {
525                         "Tag": "tag19"
526                 },
527                 "20": null
528         },
529         "EmptyMap": null,
530         "NilMap": null,
531         "Slice": [],
532         "SliceP": [],
533         "PSlice": [
534                 {
535                         "Tag": "tag20"
536                 },
537                 {
538                         "Tag": "tag21"
539                 }
540         ],
541         "PSliceP": [
542                 {
543                         "Tag": "tag22"
544                 },
545                 null,
546                 {
547                         "Tag": "tag23"
548                 }
549         ],
550         "EmptySlice": [],
551         "NilSlice": [],
552         "StringSlice": [],
553         "ByteSlice": "",
554         "Small": {
555                 "Tag": ""
556         },
557         "PSmall": null,
558         "PPSmall": {
559                 "Tag": "tag31"
560         },
561         "Interface": null,
562         "PInterface": 5.2
563 }`
564
565 var pallValueCompact = strings.Map(noSpace, pallValueIndent)