OLD | NEW |
| (Empty) |
1 // Copyright 2009 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 "reflect" | |
10 "strconv" | |
11 "testing" | |
12 ) | |
13 | |
14 type myStruct struct { | |
15 T bool | |
16 F bool | |
17 S string | |
18 I8 int8 | |
19 I16 int16 | |
20 I32 int32 | |
21 I64 int64 | |
22 U8 uint8 | |
23 U16 uint16 | |
24 U32 uint32 | |
25 U64 uint64 | |
26 I int | |
27 U uint | |
28 Fl float | |
29 Fl32 float32 | |
30 Fl64 float64 | |
31 A []string | |
32 My *myStruct | |
33 Map map[string][]int | |
34 MapStruct map[string]myStruct | |
35 MapPtrStruct map[string]*myStruct | |
36 } | |
37 | |
38 const encoded = `{"t":true,"f":false,"s":"abc","i8":1,"i16":2,"i32":3,"i64":4,`
+ | |
39 ` "u8":5,"u16":6,"u32":7,"u64":8,` + | |
40 ` "i":-9,"u":10,"bogusfield":"should be ignored",` + | |
41 ` "fl":11.5,"fl32":12.25,"fl64":13.75,` + | |
42 ` "a":["x","y","z"],"my":{"s":"subguy"},` + | |
43 `"map":{"k1":[1,2,3],"k2":[],"k3":[3,4]},` + | |
44 `"mapstruct":{"m1":{"u8":8}},` + | |
45 `"mapptrstruct":{"m1":{"u8":8}}}` | |
46 | |
47 var decodedMap = map[string][]int{ | |
48 "k1": []int{1, 2, 3}, | |
49 "k2": []int{}, | |
50 "k3": []int{3, 4}, | |
51 } | |
52 | |
53 var decodedMapStruct = map[string]myStruct{ | |
54 "m1": myStruct{U8: 8}, | |
55 } | |
56 | |
57 var decodedMapPtrStruct = map[string]*myStruct{ | |
58 "m1": &myStruct{U8: 8}, | |
59 } | |
60 | |
61 func check(t *testing.T, ok bool, name string, v interface{}) { | |
62 if !ok { | |
63 t.Errorf("%s = %v (BAD)", name, v) | |
64 } else { | |
65 t.Logf("%s = %v (good)", name, v) | |
66 } | |
67 } | |
68 | |
69 const whiteSpaceEncoded = " \t{\n\"s\"\r:\"string\"\v}" | |
70 | |
71 func TestUnmarshalWhitespace(t *testing.T) { | |
72 var m myStruct | |
73 ok, errtok := Unmarshal(whiteSpaceEncoded, &m) | |
74 if !ok { | |
75 t.Fatalf("Unmarshal failed near %s", errtok) | |
76 } | |
77 check(t, m.S == "string", "string", m.S) | |
78 } | |
79 | |
80 func TestUnmarshal(t *testing.T) { | |
81 var m myStruct | |
82 m.F = true | |
83 ok, errtok := Unmarshal(encoded, &m) | |
84 if !ok { | |
85 t.Fatalf("Unmarshal failed near %s", errtok) | |
86 } | |
87 check(t, m.T == true, "t", m.T) | |
88 check(t, m.F == false, "f", m.F) | |
89 check(t, m.S == "abc", "s", m.S) | |
90 check(t, m.I8 == 1, "i8", m.I8) | |
91 check(t, m.I16 == 2, "i16", m.I16) | |
92 check(t, m.I32 == 3, "i32", m.I32) | |
93 check(t, m.I64 == 4, "i64", m.I64) | |
94 check(t, m.U8 == 5, "u8", m.U8) | |
95 check(t, m.U16 == 6, "u16", m.U16) | |
96 check(t, m.U32 == 7, "u32", m.U32) | |
97 check(t, m.U64 == 8, "u64", m.U64) | |
98 check(t, m.I == -9, "i", m.I) | |
99 check(t, m.U == 10, "u", m.U) | |
100 check(t, m.Fl == 11.5, "fl", m.Fl) | |
101 check(t, m.Fl32 == 12.25, "fl32", m.Fl32) | |
102 check(t, m.Fl64 == 13.75, "fl64", m.Fl64) | |
103 check(t, m.A != nil, "a", m.A) | |
104 if m.A != nil { | |
105 check(t, m.A[0] == "x", "a[0]", m.A[0]) | |
106 check(t, m.A[1] == "y", "a[1]", m.A[1]) | |
107 check(t, m.A[2] == "z", "a[2]", m.A[2]) | |
108 } | |
109 check(t, m.My != nil, "my", m.My) | |
110 if m.My != nil { | |
111 check(t, m.My.S == "subguy", "my.s", m.My.S) | |
112 } | |
113 check(t, reflect.DeepEqual(m.Map, decodedMap), "map", m.Map) | |
114 check(t, reflect.DeepEqual(m.MapStruct, decodedMapStruct), "mapstruct",
m.MapStruct) | |
115 check(t, reflect.DeepEqual(m.MapPtrStruct, decodedMapPtrStruct), "mapptr
struct", m.MapPtrStruct) | |
116 } | |
117 | |
118 type Issue147Text struct { | |
119 Text string | |
120 } | |
121 | |
122 type Issue147 struct { | |
123 Test []Issue147Text | |
124 } | |
125 | |
126 const issue147Input = `{"test": [{"text":"0"},{"text":"1"},{"text":"2"}, | |
127 {"text":"3"},{"text":"4"},{"text":"5"}, | |
128 {"text":"6"},{"text":"7"},{"text":"8"}, | |
129 {"text":"9"},{"text":"10"},{"text":"11"}, | |
130 {"text":"12"},{"text":"13"},{"text":"14"}, | |
131 {"text":"15"},{"text":"16"},{"text":"17"}, | |
132 {"text":"18"},{"text":"19"},{"text":"20"}, | |
133 {"text":"21"},{"text":"22"},{"text":"23"}, | |
134 {"text":"24"},{"text":"25"},{"text":"26"}, | |
135 {"text":"27"},{"text":"28"},{"text":"29"}]}` | |
136 | |
137 func TestIssue147(t *testing.T) { | |
138 var timeline Issue147 | |
139 Unmarshal(issue147Input, &timeline) | |
140 | |
141 if len(timeline.Test) != 30 { | |
142 t.Errorf("wrong length: got %d want 30", len(timeline.Test)) | |
143 } | |
144 | |
145 for i, e := range timeline.Test { | |
146 if e.Text != strconv.Itoa(i) { | |
147 t.Errorf("index: %d got: %s want: %d", i, e.Text, i) | |
148 } | |
149 } | |
150 } | |
151 | |
152 type Issue114 struct { | |
153 Text string | |
154 } | |
155 | |
156 const issue114Input = `[{"text" : "0"}, {"text" : "1"}, {"text" : "2"}, {"text"
: "3"}]` | |
157 | |
158 func TestIssue114(t *testing.T) { | |
159 var items []Issue114 | |
160 Unmarshal(issue114Input, &items) | |
161 | |
162 if len(items) != 4 { | |
163 t.Errorf("wrong length: got %d want 4", len(items)) | |
164 } | |
165 | |
166 for i, e := range items { | |
167 if e.Text != strconv.Itoa(i) { | |
168 t.Errorf("index: %d got: %s want: %d", i, e.Text, i) | |
169 } | |
170 } | |
171 } | |
172 | |
173 type marshalTest struct { | |
174 val interface{} | |
175 out string | |
176 } | |
177 | |
178 type MTE string | |
179 | |
180 type OneField struct { | |
181 a int | |
182 } | |
183 | |
184 type ScalarWithString int | |
185 | |
186 const ( | |
187 AA ScalarWithString = iota | |
188 BB | |
189 CC | |
190 ) | |
191 | |
192 var scalarStrings = []string{"AA", "BB", "CC"} | |
193 | |
194 func (x ScalarWithString) String() string { return scalarStrings[x] } | |
195 | |
196 var marshalTests = []marshalTest{ | |
197 // basic string | |
198 marshalTest{nil, "null"}, | |
199 marshalTest{true, "true"}, | |
200 marshalTest{false, "false"}, | |
201 marshalTest{123, "123"}, | |
202 marshalTest{0.1, "0.1"}, | |
203 marshalTest{1e-10, "1e-10"}, | |
204 marshalTest{"teststring", `"teststring"`}, | |
205 marshalTest{[4]int{1, 2, 3, 4}, "[1,2,3,4]"}, | |
206 marshalTest{[]int{1, 2, 3, 4}, "[1,2,3,4]"}, | |
207 marshalTest{[]interface{}{nil}, "[null]"}, | |
208 marshalTest{[][]int{[]int{1, 2}, []int{3, 4}}, "[[1,2],[3,4]]"}, | |
209 marshalTest{map[string]string{"one": "one"}, `{"one":"one"}`}, | |
210 marshalTest{map[string]int{"one": 1}, `{"one":1}`}, | |
211 marshalTest{map[string]interface{}{"null": nil}, `{"null":null}`}, | |
212 marshalTest{struct{}{}, "{}"}, | |
213 marshalTest{struct{ a int }{1}, `{"a":1}`}, | |
214 marshalTest{struct{ a interface{} }{nil}, `{"a":null}`}, | |
215 marshalTest{struct { | |
216 a int | |
217 b string | |
218 }{1, "hello"}, | |
219 `{"a":1,"b":"hello"}`, | |
220 }, | |
221 marshalTest{map[string][]int{"3": []int{1, 2, 3}}, `{"3":[1,2,3]}`}, | |
222 marshalTest{map[string]*MTE{"hi": nil}, `{"hi":null}`}, | |
223 marshalTest{map[string]interface{}{"hi": 3}, `{"hi":3}`}, | |
224 marshalTest{&OneField{3}, `{"a":3}`}, | |
225 marshalTest{"\x05\x06", `"\u0005\u0006"`}, | |
226 marshalTest{uintptr(50000), "50000"}, | |
227 marshalTest{uint64(50000), "50000"}, | |
228 marshalTest{uint32(50000), "50000"}, | |
229 marshalTest{uint16(50000), "50000"}, | |
230 marshalTest{uint8(50), "50"}, | |
231 marshalTest{int64(50000), "50000"}, | |
232 marshalTest{int32(50000), "50000"}, | |
233 marshalTest{int16(10000), "10000"}, | |
234 marshalTest{int8(50), "50"}, | |
235 marshalTest{BB, "1"}, | |
236 } | |
237 | |
238 func TestMarshal(t *testing.T) { | |
239 for _, tt := range marshalTests { | |
240 var buf bytes.Buffer | |
241 | |
242 err := Marshal(&buf, tt.val) | |
243 if err != nil { | |
244 t.Fatalf("Marshal(%T): %s", tt.val, err) | |
245 } | |
246 | |
247 s := buf.String() | |
248 if s != tt.out { | |
249 t.Errorf("Marshal(%T) = %q, want %q\n", tt.val, s, tt.ou
t) | |
250 } | |
251 } | |
252 } | |
253 | |
254 type marshalIndentTest struct { | |
255 val interface{} | |
256 indent string | |
257 out string | |
258 } | |
259 | |
260 const marshalIndentTest1 = `[ | |
261 1, | |
262 2, | |
263 3, | |
264 4 | |
265 ] | |
266 ` | |
267 const marshalIndentTest2 = `[ | |
268 [ | |
269 1, | |
270 2 | |
271 ], | |
272 [ | |
273 3, | |
274 4 | |
275 ] | |
276 ] | |
277 ` | |
278 const marshalIndentTest3 = `[ | |
279 [ | |
280 1, | |
281 2 | |
282 ], | |
283 [ | |
284 3, | |
285 4 | |
286 ] | |
287 ] | |
288 ` | |
289 const marshalIndentTest4 = `[ | |
290 [ | |
291 1, | |
292 2 | |
293 ], | |
294 [ | |
295 3, | |
296 4 | |
297 ] | |
298 ] | |
299 ` | |
300 const marshalIndentTest5 = `{ | |
301 "a":1, | |
302 "b":"hello" | |
303 } | |
304 ` | |
305 const marshalIndentTest6 = `{ | |
306 "3":[ | |
307 1, | |
308 2, | |
309 3 | |
310 ] | |
311 } | |
312 ` | |
313 | |
314 var marshalIndentTests = []marshalIndentTest{ | |
315 marshalIndentTest{[]int{1, 2, 3, 4}, " ", marshalIndentTest1}, | |
316 marshalIndentTest{[][]int{[]int{1, 2}, []int{3, 4}}, "", marshalIndentTe
st2}, | |
317 marshalIndentTest{[][]int{[]int{1, 2}, []int{3, 4}}, " ", marshalIndentT
est3}, | |
318 marshalIndentTest{[][]int{[]int{1, 2}, []int{3, 4}}, " ", marshalIndent
Test4}, | |
319 marshalIndentTest{struct { | |
320 a int | |
321 b string | |
322 }{1, "hello"}, | |
323 " ", | |
324 marshalIndentTest5, | |
325 }, | |
326 marshalIndentTest{map[string][]int{"3": []int{1, 2, 3}}, " ", marshalInd
entTest6}, | |
327 } | |
328 | |
329 func TestMarshalIndent(t *testing.T) { | |
330 for _, tt := range marshalIndentTests { | |
331 var buf bytes.Buffer | |
332 | |
333 err := MarshalIndent(&buf, tt.val, tt.indent) | |
334 if err != nil { | |
335 t.Fatalf("MarshalIndent(%v): %s", tt.val, err) | |
336 } | |
337 | |
338 s := buf.String() | |
339 if s != tt.out { | |
340 t.Errorf("MarshalIndent(%v) = %q, want %q\n", tt.val, s,
tt.out) | |
341 } | |
342 } | |
343 } | |
344 | |
345 type marshalErrorTest struct { | |
346 val interface{} | |
347 error string | |
348 } | |
349 | |
350 type ChanVal struct { | |
351 C chan int | |
352 } | |
353 | |
354 var marshalErrorTests = []marshalErrorTest{ | |
355 marshalErrorTest{map[chan int]string{make(chan int): "one"}, "json canno
t encode value of type map[chan int] string"}, | |
356 marshalErrorTest{make(chan int, 100), "json cannot encode value of type
chan int"}, | |
357 marshalErrorTest{new(ChanVal), "json cannot encode value of type chan in
t"}, | |
358 } | |
359 | |
360 func TestMarshalError(t *testing.T) { | |
361 for _, tt := range marshalErrorTests { | |
362 var buf bytes.Buffer | |
363 | |
364 err := Marshal(&buf, tt.val) | |
365 | |
366 if err == nil { | |
367 t.Fatalf("Marshal(%T): no error, want error %s", tt.val,
tt.error) | |
368 } | |
369 | |
370 if err.String() != tt.error { | |
371 t.Fatalf("Marshal(%T) = error %s, want error %s", tt.val
, err, tt.error) | |
372 } | |
373 | |
374 } | |
375 } | |
OLD | NEW |