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.
24 var txType = reflect.Typeof((*tx)(nil)).(*reflect.PtrType).Elem().(*reflect.StructType)
26 // A type that can unmarshal itself.
28 type unmarshaler struct {
32 func (u *unmarshaler) UnmarshalJSON(b []byte) os.Error {
33 *u = unmarshaler{true} // All we need to see that UnmarshalJson is called.
38 um0, um1 unmarshaler // target2 of unmarshaling
40 umtrue = unmarshaler{true}
49 type unmarshalTest struct {
56 var unmarshalTests = []unmarshalTest{
58 {`true`, new(bool), true, nil},
59 {`1`, new(int), 1, nil},
60 {`1.2`, new(float64), 1.2, nil},
61 {`-5`, new(int16), int16(-5), nil},
62 {`"a\u1234"`, new(string), "a\u1234", nil},
63 {`"http:\/\/"`, new(string), "http://", nil},
64 {`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E", nil},
65 {`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx\uFFFD", nil},
66 {"null", new(interface{}), nil, nil},
67 {`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.Typeof("")}},
68 {`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
71 {`{"X":"a", "y":"b", "Z":"c"}`, new(badTag), badTag{"a", "b", "c"}, nil},
74 {`{"X": "foo", "Y"}`, nil, nil, SyntaxError("invalid character '}' after object key")},
77 {allValueIndent, new(All), allValue, nil},
78 {allValueCompact, new(All), allValue, nil},
79 {allValueIndent, new(*All), &allValue, nil},
80 {allValueCompact, new(*All), &allValue, nil},
81 {pallValueIndent, new(All), pallValue, nil},
82 {pallValueCompact, new(All), pallValue, nil},
83 {pallValueIndent, new(*All), &pallValue, nil},
84 {pallValueCompact, new(*All), &pallValue, nil},
86 // unmarshal interface test
87 {`{"T":false}`, &um0, umtrue, nil}, // use "false" so test will fail if custom unmarshaler is not called
88 {`{"T":false}`, &ump, &umtrue, nil},
91 func TestMarshal(t *testing.T) {
92 b, err := Marshal(allValue)
94 t.Fatalf("Marshal allValue: %v", err)
96 if string(b) != allValueCompact {
97 t.Errorf("Marshal allValueCompact")
98 diff(t, b, []byte(allValueCompact))
102 b, err = Marshal(pallValue)
104 t.Fatalf("Marshal pallValue: %v", err)
106 if string(b) != pallValueCompact {
107 t.Errorf("Marshal pallValueCompact")
108 diff(t, b, []byte(pallValueCompact))
113 func TestMarshalBadUTF8(t *testing.T) {
114 s := "hello\xffworld"
117 t.Fatal("Marshal bad UTF8: no error")
120 t.Fatal("Marshal returned data")
122 if _, ok := err.(*InvalidUTF8Error); !ok {
123 t.Fatalf("Marshal did not return InvalidUTF8Error: %T %v", err, err)
127 func TestUnmarshal(t *testing.T) {
129 for i, tt := range unmarshalTests {
131 if err := checkValid(in, &scan); err != nil {
132 if !reflect.DeepEqual(err, tt.err) {
133 t.Errorf("#%d: checkValid: %v", i, err)
140 // v = new(right-type)
141 v := reflect.NewValue(tt.ptr).(*reflect.PtrValue)
142 v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
143 if err := Unmarshal([]byte(in), v.Interface()); !reflect.DeepEqual(err, tt.err) {
144 t.Errorf("#%d: %v want %v", i, err, tt.err)
147 if !reflect.DeepEqual(v.Elem().Interface(), tt.out) {
148 t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), tt.out)
149 data, _ := Marshal(v.Elem().Interface())
150 println(string(data))
151 data, _ = Marshal(tt.out)
152 println(string(data))
159 func TestUnmarshalMarshal(t *testing.T) {
161 if err := Unmarshal(jsonBig, &v); err != nil {
162 t.Fatalf("Unmarshal: %v", err)
166 t.Fatalf("Marshal: %v", err)
168 if bytes.Compare(jsonBig, b) != 0 {
169 t.Errorf("Marshal jsonBig")
175 func TestLargeByteSlice(t *testing.T) {
176 s0 := make([]byte, 2000)
180 b, err := Marshal(s0)
182 t.Fatalf("Marshal: %v", err)
185 if err := Unmarshal(b, &s1); err != nil {
186 t.Fatalf("Unmarshal: %v", err)
188 if bytes.Compare(s0, s1) != 0 {
189 t.Errorf("Marshal large byte slice")
198 func TestUnmarshalInterface(t *testing.T) {
200 var i interface{} = &xint
201 if err := Unmarshal([]byte(`{"X":1}`), &i); err != nil {
202 t.Fatalf("Unmarshal: %v", err)
205 t.Fatalf("Did not write to xint")
209 func TestUnmarshalPtrPtr(t *testing.T) {
212 if err := Unmarshal([]byte(`{"X":1}`), &pxint); err != nil {
213 t.Fatalf("Unmarshal: %v", err)
216 t.Fatalf("Did not write to xint")
220 func TestHTMLEscape(t *testing.T) {
221 b, err := MarshalForHTML("foobarbaz<>&quux")
223 t.Fatalf("MarshalForHTML error: %v", err)
225 if !bytes.Equal(b, []byte(`"foobarbaz\u003c\u003e\u0026quux"`)) {
226 t.Fatalf("Unexpected encoding of \"<>&\": %s", b)
230 func noSpace(c int) int {
274 MapP map[string]*Small
275 PMap *map[string]Small
276 PMapP *map[string]*Small
278 EmptyMap map[string]Small
279 NilMap map[string]Small
296 Interface interface{}
297 PInterface *interface{}
323 Map: map[string]Small{
324 "17": {Tag: "tag17"},
325 "18": {Tag: "tag18"},
327 MapP: map[string]*Small{
328 "19": &Small{Tag: "tag19"},
331 EmptyMap: map[string]Small{},
332 Slice: []Small{{Tag: "tag20"}, {Tag: "tag21"}},
333 SliceP: []*Small{&Small{Tag: "tag22"}, nil, &Small{Tag: "tag23"}},
334 EmptySlice: []Small{},
335 StringSlice: []string{"str24", "str25", "str26"},
336 ByteSlice: []byte{27, 28, 29},
337 Small: Small{Tag: "tag30"},
338 PSmall: &Small{Tag: "tag31"},
343 PBool: &allValue.Bool,
345 PInt8: &allValue.Int8,
346 PInt16: &allValue.Int16,
347 PInt32: &allValue.Int32,
348 PInt64: &allValue.Int64,
349 PUint: &allValue.Uint,
350 PUint8: &allValue.Uint8,
351 PUint16: &allValue.Uint16,
352 PUint32: &allValue.Uint32,
353 PUint64: &allValue.Uint64,
354 PUintptr: &allValue.Uintptr,
355 PFloat32: &allValue.Float32,
356 PFloat64: &allValue.Float64,
357 PString: &allValue.String,
359 PMapP: &allValue.MapP,
360 PSlice: &allValue.Slice,
361 PSliceP: &allValue.SliceP,
362 PPSmall: &allValue.PSmall,
363 PInterface: &allValue.Interface,
366 var allValueIndent = `{
454 var allValueCompact = strings.Map(noSpace, allValueIndent)
456 var pallValueIndent = `{
540 var pallValueCompact = strings.Map(noSpace, pallValueIndent)