OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2010 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package json | 5 package json |
6 | 6 |
7 import ( | 7 import ( |
8 » "container/vector" | 8 » "bytes" |
9 "reflect" | 9 "reflect" |
| 10 "strings" |
10 "testing" | 11 "testing" |
11 ) | 12 ) |
12 | 13 |
13 func TestDecodeInt64(t *testing.T) { | 14 type unmarshalTest struct { |
14 nb := newDecoder(nil, nil) | 15 in string |
15 nb.Int64(-15) | 16 ptr interface{} |
16 assertResult(t, nb.Data(), float64(-15)) | 17 out interface{} |
17 } | 18 } |
18 | 19 |
19 func TestDecodeUint64(t *testing.T) { | 20 var unmarshalTests = []unmarshalTest{ |
20 nb := newDecoder(nil, nil) | 21 // basic types |
21 nb.Uint64(15) | 22 unmarshalTest{`true`, new(bool), true}, |
22 assertResult(t, nb.Data(), float64(15)) | 23 unmarshalTest{`1`, new(int), 1}, |
23 } | 24 unmarshalTest{`1.2`, new(float), 1.2}, |
24 | 25 unmarshalTest{`-5`, new(int16), int16(-5)}, |
25 func TestDecodeFloat64(t *testing.T) { | 26 unmarshalTest{`"a\u1234"`, new(string), "a\u1234"}, |
26 nb := newDecoder(nil, nil) | 27 unmarshalTest{`"g-clef: \uD834\uDD1E"`, new(string), "g-clef: \U0001D11E
"}, |
27 nb.Float64(3.14159) | 28 unmarshalTest{`"invalid: \uD834x\uDD1E"`, new(string), "invalid: \uFFFDx
\uFFFD"}, |
28 assertResult(t, nb.Data(), float64(3.14159)) | 29 unmarshalTest{"null", new(interface{}), nil}, |
29 } | 30 |
30 | 31 // composite tests |
31 func TestDecodeString(t *testing.T) { | 32 unmarshalTest{allValueIndent, new(All), allValue}, |
32 nb := newDecoder(nil, nil) | 33 unmarshalTest{allValueCompact, new(All), allValue}, |
33 nb.String("Some string") | 34 unmarshalTest{allValueIndent, new(*All), &allValue}, |
34 assertResult(t, nb.Data(), "Some string") | 35 unmarshalTest{allValueCompact, new(*All), &allValue}, |
35 } | 36 unmarshalTest{pallValueIndent, new(All), pallValue}, |
36 | 37 unmarshalTest{pallValueCompact, new(All), pallValue}, |
37 func TestDecodeBool(t *testing.T) { | 38 unmarshalTest{pallValueIndent, new(*All), &pallValue}, |
38 nb := newDecoder(nil, nil) | 39 unmarshalTest{pallValueCompact, new(*All), &pallValue}, |
39 nb.Bool(true) | 40 } |
40 assertResult(t, nb.Data(), true) | 41 |
41 } | 42 func TestMarshal(t *testing.T) { |
42 | 43 b, err := Marshal(allValue) |
43 func TestDecodeNull(t *testing.T) { | 44 if err != nil { |
44 nb := newDecoder(nil, nil) | 45 t.Fatalf("Marshal allValue: %v", err) |
45 nb.Null() | 46 } |
46 assertResult(t, nb.Data(), nil) | 47 if string(b) != allValueCompact { |
47 } | 48 t.Errorf("Marshal allValueCompact") |
48 | 49 diff(t, b, []byte(allValueCompact)) |
49 func TestDecodeEmptyArray(t *testing.T) { | 50 return |
50 nb := newDecoder(nil, nil) | 51 } |
51 nb.Array() | 52 |
52 assertResult(t, nb.Data(), []interface{}{}) | 53 b, err = Marshal(pallValue) |
53 } | 54 if err != nil { |
54 | 55 t.Fatalf("Marshal pallValue: %v", err) |
55 func TestDecodeEmptyMap(t *testing.T) { | 56 } |
56 nb := newDecoder(nil, nil) | 57 if string(b) != pallValueCompact { |
57 nb.Map() | 58 t.Errorf("Marshal pallValueCompact") |
58 assertResult(t, nb.Data(), map[string]interface{}{}) | 59 diff(t, b, []byte(pallValueCompact)) |
59 } | 60 return |
60 | 61 } |
61 func TestDecodeFlushElem(t *testing.T) { | 62 } |
62 testVec := new(vector.Vector).Resize(2, 2) | 63 |
63 nb := newDecoder(testVec, 1) | 64 func TestUnmarshal(t *testing.T) { |
64 nb.Float64(3.14159) | 65 var scan scanner |
65 nb.Flush() | 66 for i, tt := range unmarshalTests { |
66 assertResult(t, testVec.Data(), []interface{}{nil, float64(3.14159)}) | 67 in := []byte(tt.in) |
67 } | 68 if err := checkValid(in, &scan); err != nil { |
68 | 69 t.Errorf("#%d: checkValid: %v", i, err) |
69 func TestDecodeFlushKey(t *testing.T) { | 70 continue |
70 testMap := make(map[string]interface{}) | 71 } |
71 nb := newDecoder(testMap, "key") | 72 // v = new(right-type) |
72 nb.Float64(3.14159) | 73 v := reflect.NewValue(tt.ptr).(*reflect.PtrValue) |
73 nb.Flush() | 74 v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem())) |
74 assertResult(t, testMap, map[string]interface{}{"key": float64(3.14159)}
) | 75 if err := Unmarshal([]byte(in), v.Interface()); err != nil { |
75 } | 76 t.Errorf("#%d: %v", i, err) |
76 | 77 continue |
77 // Elem() and Key() are hard to test in isolation because all they do | 78 } |
78 // is create a new, properly initialized, decoder, and modify state of | 79 if !reflect.DeepEqual(v.Elem().Interface(), tt.out) { |
79 // the underlying decoder. I'm testing them through already tested | 80 t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.E
lem().Interface(), tt.out) |
80 // Array(), String(), and Flush(). | 81 data, _ := Marshal(v.Elem().Interface()) |
81 | 82 println(string(data)) |
82 func TestDecodeElem(t *testing.T) { | 83 data, _ = Marshal(tt.out) |
83 nb := newDecoder(nil, nil) | 84 println(string(data)) |
84 nb.Array() | 85 return |
85 var b Builder = nb.Elem(0) | 86 continue |
86 b.String("0") | 87 } |
87 b.Flush() | 88 } |
88 assertResult(t, nb.Data(), []interface{}{"0"}) | 89 } |
89 } | 90 |
90 | 91 func TestUnmarshalMarshal(t *testing.T) { |
91 func TestDecodeKey(t *testing.T) { | 92 var v interface{} |
92 nb := newDecoder(nil, nil) | 93 if err := Unmarshal(jsonBig, &v); err != nil { |
93 nb.Map() | 94 t.Fatalf("Unmarshal: %v", err) |
94 var b Builder = nb.Key("a") | 95 } |
95 b.String("0") | 96 b, err := Marshal(v) |
96 b.Flush() | 97 if err != nil { |
97 assertResult(t, nb.Data(), map[string]interface{}{"a": "0"}) | 98 t.Fatalf("Marshal: %v", err) |
98 } | 99 } |
99 | 100 if bytes.Compare(jsonBig, b) != 0 { |
100 func assertResult(t *testing.T, results, expected interface{}) { | 101 t.Errorf("Marshal jsonBig") |
101 if !reflect.DeepEqual(results, expected) { | 102 diff(t, b, jsonBig) |
102 t.Fatalf("have %T(%#v) want %T(%#v)", results, results, expected
, expected) | 103 return |
103 } | 104 } |
104 } | 105 } |
105 | 106 |
106 type decodeTest struct { | 107 func noSpace(c int) int { |
107 s string | 108 if isSpace(c) { |
108 r interface{} | 109 return -1 |
109 } | 110 } |
110 | 111 return c |
111 var tests = []decodeTest{ | 112 } |
112 decodeTest{`null`, nil}, | 113 |
113 decodeTest{`true`, true}, | 114 type All struct { |
114 decodeTest{`false`, false}, | 115 Bool bool |
115 decodeTest{`"abc"`, "abc"}, | 116 Int int |
116 decodeTest{`123`, float64(123)}, | 117 Int8 int8 |
117 decodeTest{`0.1`, float64(0.1)}, | 118 Int16 int16 |
118 decodeTest{`1e-10`, float64(1e-10)}, | 119 Int32 int32 |
119 decodeTest{`[]`, []interface{}{}}, | 120 Int64 int64 |
120 decodeTest{`[1,2,3,4]`, []interface{}{float64(1), float64(2), float64(3)
, float64(4)}}, | 121 Uint uint |
121 decodeTest{`[1,2,"abc",null,true,false]`, []interface{}{float64(1), floa
t64(2), "abc", nil, true, false}}, | 122 Uint8 uint8 |
122 decodeTest{`{}`, map[string]interface{}{}}, | 123 Uint16 uint16 |
123 decodeTest{`{"a":1}`, map[string]interface{}{"a": float64(1)}}, | 124 Uint32 uint32 |
124 decodeTest{`"q\u0302"`, "q\u0302"}, | 125 Uint64 uint64 |
125 } | 126 Uintptr uintptr |
126 | 127 Float float |
127 func TestDecode(t *testing.T) { | 128 Float32 float32 |
128 for _, test := range tests { | 129 Float64 float64 |
129 if val, err := Decode(test.s); err != nil || !reflect.DeepEqual(
val, test.r) { | 130 |
130 t.Errorf("Decode(%#q) = %v, %v want %v, nil", test.s, va
l, err, test.r) | 131 Foo string "bar" |
131 } | 132 |
132 } | 133 PBool *bool |
133 } | 134 PInt *int |
| 135 PInt8 *int8 |
| 136 PInt16 *int16 |
| 137 PInt32 *int32 |
| 138 PInt64 *int64 |
| 139 PUint *uint |
| 140 PUint8 *uint8 |
| 141 PUint16 *uint16 |
| 142 PUint32 *uint32 |
| 143 PUint64 *uint64 |
| 144 PUintptr *uintptr |
| 145 PFloat *float |
| 146 PFloat32 *float32 |
| 147 PFloat64 *float64 |
| 148 |
| 149 String string |
| 150 PString *string |
| 151 |
| 152 Map map[string]Small |
| 153 MapP map[string]*Small |
| 154 PMap *map[string]Small |
| 155 PMapP *map[string]*Small |
| 156 |
| 157 EmptyMap map[string]Small |
| 158 NilMap map[string]Small |
| 159 |
| 160 Slice []Small |
| 161 SliceP []*Small |
| 162 PSlice *[]Small |
| 163 PSliceP *[]*Small |
| 164 |
| 165 EmptySlice []Small |
| 166 NilSlice []Small |
| 167 |
| 168 StringSlice []string |
| 169 ByteSlice []byte |
| 170 |
| 171 Small Small |
| 172 PSmall *Small |
| 173 PPSmall **Small |
| 174 |
| 175 Interface interface{} |
| 176 PInterface *interface{} |
| 177 } |
| 178 |
| 179 type Small struct { |
| 180 Tag string |
| 181 } |
| 182 |
| 183 var allValue = All{ |
| 184 Bool: true, |
| 185 Int: 2, |
| 186 Int8: 3, |
| 187 Int16: 4, |
| 188 Int32: 5, |
| 189 Int64: 6, |
| 190 Uint: 7, |
| 191 Uint8: 8, |
| 192 Uint16: 9, |
| 193 Uint32: 10, |
| 194 Uint64: 11, |
| 195 Uintptr: 12, |
| 196 Float: 13.1, |
| 197 Float32: 14.1, |
| 198 Float64: 15.1, |
| 199 Foo: "foo", |
| 200 String: "16", |
| 201 Map: map[string]Small{ |
| 202 "17": Small{Tag: "tag17"}, |
| 203 "18": Small{Tag: "tag18"}, |
| 204 }, |
| 205 MapP: map[string]*Small{ |
| 206 "19": &Small{Tag: "tag19"}, |
| 207 "20": nil, |
| 208 }, |
| 209 EmptyMap: map[string]Small{}, |
| 210 Slice: []Small{Small{Tag: "tag20"}, Small{Tag: "tag21"}}, |
| 211 SliceP: []*Small{&Small{Tag: "tag22"}, nil, &Small{Tag: "tag23"}}, |
| 212 EmptySlice: []Small{}, |
| 213 StringSlice: []string{"str24", "str25", "str26"}, |
| 214 ByteSlice: []byte{27, 28, 29}, |
| 215 Small: Small{Tag: "tag30"}, |
| 216 PSmall: &Small{Tag: "tag31"}, |
| 217 Interface: float64(5.2), |
| 218 } |
| 219 |
| 220 var pallValue = All{ |
| 221 PBool: &allValue.Bool, |
| 222 PInt: &allValue.Int, |
| 223 PInt8: &allValue.Int8, |
| 224 PInt16: &allValue.Int16, |
| 225 PInt32: &allValue.Int32, |
| 226 PInt64: &allValue.Int64, |
| 227 PUint: &allValue.Uint, |
| 228 PUint8: &allValue.Uint8, |
| 229 PUint16: &allValue.Uint16, |
| 230 PUint32: &allValue.Uint32, |
| 231 PUint64: &allValue.Uint64, |
| 232 PUintptr: &allValue.Uintptr, |
| 233 PFloat: &allValue.Float, |
| 234 PFloat32: &allValue.Float32, |
| 235 PFloat64: &allValue.Float64, |
| 236 PString: &allValue.String, |
| 237 PMap: &allValue.Map, |
| 238 PMapP: &allValue.MapP, |
| 239 PSlice: &allValue.Slice, |
| 240 PSliceP: &allValue.SliceP, |
| 241 PPSmall: &allValue.PSmall, |
| 242 PInterface: &allValue.Interface, |
| 243 } |
| 244 |
| 245 var allValueIndent = `{ |
| 246 "bool": true, |
| 247 "int": 2, |
| 248 "int8": 3, |
| 249 "int16": 4, |
| 250 "int32": 5, |
| 251 "int64": 6, |
| 252 "uint": 7, |
| 253 "uint8": 8, |
| 254 "uint16": 9, |
| 255 "uint32": 10, |
| 256 "uint64": 11, |
| 257 "uintptr": 12, |
| 258 "float": 13.1, |
| 259 "float32": 14.1, |
| 260 "float64": 15.1, |
| 261 "bar": "foo", |
| 262 "pbool": null, |
| 263 "pint": null, |
| 264 "pint8": null, |
| 265 "pint16": null, |
| 266 "pint32": null, |
| 267 "pint64": null, |
| 268 "puint": null, |
| 269 "puint8": null, |
| 270 "puint16": null, |
| 271 "puint32": null, |
| 272 "puint64": null, |
| 273 "puintptr": null, |
| 274 "pfloat": null, |
| 275 "pfloat32": null, |
| 276 "pfloat64": null, |
| 277 "string": "16", |
| 278 "pstring": null, |
| 279 "map": { |
| 280 "17": { |
| 281 "tag": "tag17" |
| 282 }, |
| 283 "18": { |
| 284 "tag": "tag18" |
| 285 } |
| 286 }, |
| 287 "mapp": { |
| 288 "19": { |
| 289 "tag": "tag19" |
| 290 }, |
| 291 "20": null |
| 292 }, |
| 293 "pmap": null, |
| 294 "pmapp": null, |
| 295 "emptymap": {}, |
| 296 "nilmap": null, |
| 297 "slice": [ |
| 298 { |
| 299 "tag": "tag20" |
| 300 }, |
| 301 { |
| 302 "tag": "tag21" |
| 303 } |
| 304 ], |
| 305 "slicep": [ |
| 306 { |
| 307 "tag": "tag22" |
| 308 }, |
| 309 null, |
| 310 { |
| 311 "tag": "tag23" |
| 312 } |
| 313 ], |
| 314 "pslice": null, |
| 315 "pslicep": null, |
| 316 "emptyslice": [], |
| 317 "nilslice": [], |
| 318 "stringslice": [ |
| 319 "str24", |
| 320 "str25", |
| 321 "str26" |
| 322 ], |
| 323 "byteslice": [ |
| 324 27, |
| 325 28, |
| 326 29 |
| 327 ], |
| 328 "small": { |
| 329 "tag": "tag30" |
| 330 }, |
| 331 "psmall": { |
| 332 "tag": "tag31" |
| 333 }, |
| 334 "ppsmall": null, |
| 335 "interface": 5.2, |
| 336 "pinterface": null |
| 337 }` |
| 338 |
| 339 var allValueCompact = strings.Map(noSpace, allValueIndent) |
| 340 |
| 341 var pallValueIndent = `{ |
| 342 "bool": false, |
| 343 "int": 0, |
| 344 "int8": 0, |
| 345 "int16": 0, |
| 346 "int32": 0, |
| 347 "int64": 0, |
| 348 "uint": 0, |
| 349 "uint8": 0, |
| 350 "uint16": 0, |
| 351 "uint32": 0, |
| 352 "uint64": 0, |
| 353 "uintptr": 0, |
| 354 "float": 0, |
| 355 "float32": 0, |
| 356 "float64": 0, |
| 357 "bar": "", |
| 358 "pbool": true, |
| 359 "pint": 2, |
| 360 "pint8": 3, |
| 361 "pint16": 4, |
| 362 "pint32": 5, |
| 363 "pint64": 6, |
| 364 "puint": 7, |
| 365 "puint8": 8, |
| 366 "puint16": 9, |
| 367 "puint32": 10, |
| 368 "puint64": 11, |
| 369 "puintptr": 12, |
| 370 "pfloat": 13.1, |
| 371 "pfloat32": 14.1, |
| 372 "pfloat64": 15.1, |
| 373 "string": "", |
| 374 "pstring": "16", |
| 375 "map": null, |
| 376 "mapp": null, |
| 377 "pmap": { |
| 378 "17": { |
| 379 "tag": "tag17" |
| 380 }, |
| 381 "18": { |
| 382 "tag": "tag18" |
| 383 } |
| 384 }, |
| 385 "pmapp": { |
| 386 "19": { |
| 387 "tag": "tag19" |
| 388 }, |
| 389 "20": null |
| 390 }, |
| 391 "emptymap": null, |
| 392 "nilmap": null, |
| 393 "slice": [], |
| 394 "slicep": [], |
| 395 "pslice": [ |
| 396 { |
| 397 "tag": "tag20" |
| 398 }, |
| 399 { |
| 400 "tag": "tag21" |
| 401 } |
| 402 ], |
| 403 "pslicep": [ |
| 404 { |
| 405 "tag": "tag22" |
| 406 }, |
| 407 null, |
| 408 { |
| 409 "tag": "tag23" |
| 410 } |
| 411 ], |
| 412 "emptyslice": [], |
| 413 "nilslice": [], |
| 414 "stringslice": [], |
| 415 "byteslice": [], |
| 416 "small": { |
| 417 "tag": "" |
| 418 }, |
| 419 "psmall": null, |
| 420 "ppsmall": { |
| 421 "tag": "tag31" |
| 422 }, |
| 423 "interface": null, |
| 424 "pinterface": 5.2 |
| 425 }` |
| 426 |
| 427 var pallValueCompact = strings.Map(noSpace, pallValueIndent) |
OLD | NEW |