1
2
3
4
5 package json
6
7 import (
8 "bytes"
9 "io"
10 "io/ioutil"
11 "log"
12 "net"
13 "net/http"
14 "net/http/httptest"
15 "reflect"
16 "strings"
17 "testing"
18 )
19
20
21
22 var streamTest = []interface{}{
23 0.1,
24 "hello",
25 nil,
26 true,
27 false,
28 []interface{}{"a", "b", "c"},
29 map[string]interface{}{"K": "Kelvin", "ß": "long s"},
30 3.14,
31 }
32
33 var streamEncoded = `0.1
34 "hello"
35 null
36 true
37 false
38 ["a","b","c"]
39 {"ß":"long s","K":"Kelvin"}
40 3.14
41 `
42
43 func TestEncoder(t *testing.T) {
44 for i := 0; i <= len(streamTest); i++ {
45 var buf bytes.Buffer
46 enc := NewEncoder(&buf)
47 for j, v := range streamTest[0:i] {
48 if err := enc.Encode(v); err != nil {
49 t.Fatalf("encode #%d: %v", j, err)
50 }
51 }
52 if have, want := buf.String(), nlines(streamEncoded, i); have != want {
53 t.Errorf("encoding %d items: mismatch", i)
54 diff(t, []byte(have), []byte(want))
55 break
56 }
57 }
58 }
59
60 func TestDecoder(t *testing.T) {
61 for i := 0; i <= len(streamTest); i++ {
62
63
64
65
66
67 var buf bytes.Buffer
68 for _, c := range nlines(streamEncoded, i) {
69 if c != '\n' {
70 buf.WriteRune(c)
71 }
72 }
73 out := make([]interface{}, i)
74 dec := NewDecoder(&buf)
75 for j := range out {
76 if err := dec.Decode(&out[j]); err != nil {
77 t.Fatalf("decode #%d/%d: %v", j, i, err)
78 }
79 }
80 if !reflect.DeepEqual(out, streamTest[0:i]) {
81 t.Errorf("decoding %d items: mismatch", i)
82 for j := range out {
83 if !reflect.DeepEqual(out[j], streamTest[j]) {
84 t.Errorf("#%d: have %v want %v", j, out[j], streamTest[j])
85 }
86 }
87 break
88 }
89 }
90 }
91
92 func TestDecoderBuffered(t *testing.T) {
93 r := strings.NewReader(`{"Name": "Gopher"} extra `)
94 var m struct {
95 Name string
96 }
97 d := NewDecoder(r)
98 err := d.Decode(&m)
99 if err != nil {
100 t.Fatal(err)
101 }
102 if m.Name != "Gopher" {
103 t.Errorf("Name = %q; want Gopher", m.Name)
104 }
105 rest, err := ioutil.ReadAll(d.Buffered())
106 if err != nil {
107 t.Fatal(err)
108 }
109 if g, w := string(rest), " extra "; g != w {
110 t.Errorf("Remaining = %q; want %q", g, w)
111 }
112 }
113
114 func nlines(s string, n int) string {
115 if n <= 0 {
116 return ""
117 }
118 for i, c := range s {
119 if c == '\n' {
120 if n--; n == 0 {
121 return s[0 : i+1]
122 }
123 }
124 }
125 return s
126 }
127
128 func TestRawMessage(t *testing.T) {
129
130 var data struct {
131 X float64
132 Id *RawMessage
133 Y float32
134 }
135 const raw = `["\u0056",null]`
136 const msg = `{"X":0.1,"Id":["\u0056",null],"Y":0.2}`
137 err := Unmarshal([]byte(msg), &data)
138 if err != nil {
139 t.Fatalf("Unmarshal: %v", err)
140 }
141 if string([]byte(*data.Id)) != raw {
142 t.Fatalf("Raw mismatch: have %#q want %#q", []byte(*data.Id), raw)
143 }
144 b, err := Marshal(&data)
145 if err != nil {
146 t.Fatalf("Marshal: %v", err)
147 }
148 if string(b) != msg {
149 t.Fatalf("Marshal: have %#q want %#q", b, msg)
150 }
151 }
152
153 func TestNullRawMessage(t *testing.T) {
154
155 var data struct {
156 X float64
157 Id *RawMessage
158 Y float32
159 }
160 data.Id = new(RawMessage)
161 const msg = `{"X":0.1,"Id":null,"Y":0.2}`
162 err := Unmarshal([]byte(msg), &data)
163 if err != nil {
164 t.Fatalf("Unmarshal: %v", err)
165 }
166 if data.Id != nil {
167 t.Fatalf("Raw mismatch: have non-nil, want nil")
168 }
169 b, err := Marshal(&data)
170 if err != nil {
171 t.Fatalf("Marshal: %v", err)
172 }
173 if string(b) != msg {
174 t.Fatalf("Marshal: have %#q want %#q", b, msg)
175 }
176 }
177
178 var blockingTests = []string{
179 `{"x": 1}`,
180 `[1, 2, 3]`,
181 }
182
183 func TestBlocking(t *testing.T) {
184 for _, enc := range blockingTests {
185 r, w := net.Pipe()
186 go w.Write([]byte(enc))
187 var val interface{}
188
189
190
191 if err := NewDecoder(r).Decode(&val); err != nil {
192 t.Errorf("decoding %s: %v", enc, err)
193 }
194 r.Close()
195 w.Close()
196 }
197 }
198
199 func BenchmarkEncoderEncode(b *testing.B) {
200 b.ReportAllocs()
201 type T struct {
202 X, Y string
203 }
204 v := &T{"foo", "bar"}
205 for i := 0; i < b.N; i++ {
206 if err := NewEncoder(ioutil.Discard).Encode(v); err != nil {
207 b.Fatal(err)
208 }
209 }
210 }
211
212 type tokenStreamCase struct {
213 json string
214 expTokens []interface{}
215 }
216
217 type decodeThis struct {
218 v interface{}
219 }
220
221 var tokenStreamCases []tokenStreamCase = []tokenStreamCase{
222
223 {json: `10`, expTokens: []interface{}{float64(10)}},
224 {json: ` [10] `, expTokens: []interface{}{
225 Delim('['), float64(10), Delim(']')}},
226 {json: ` [false,10,"b"] `, expTokens: []interface{}{
227 Delim('['), false, float64(10), "b", Delim(']')}},
228 {json: `{ "a": 1 }`, expTokens: []interface{}{
229 Delim('{'), "a", float64(1), Delim('}')}},
230 {json: `{"a": 1, "b":"3"}`, expTokens: []interface{}{
231 Delim('{'), "a", float64(1), "b", "3", Delim('}')}},
232 {json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{
233 Delim('['),
234 Delim('{'), "a", float64(1), Delim('}'),
235 Delim('{'), "a", float64(2), Delim('}'),
236 Delim(']')}},
237 {json: `{"obj": {"a": 1}}`, expTokens: []interface{}{
238 Delim('{'), "obj", Delim('{'), "a", float64(1), Delim('}'),
239 Delim('}')}},
240 {json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{
241 Delim('{'), "obj", Delim('['),
242 Delim('{'), "a", float64(1), Delim('}'),
243 Delim(']'), Delim('}')}},
244
245
246 {json: `{ "a": 1 }`, expTokens: []interface{}{
247 Delim('{'), "a",
248 decodeThis{float64(1)},
249 Delim('}')}},
250 {json: ` [ { "a" : 1 } ] `, expTokens: []interface{}{
251 Delim('['),
252 decodeThis{map[string]interface{}{"a": float64(1)}},
253 Delim(']')}},
254 {json: ` [{"a": 1},{"a": 2}] `, expTokens: []interface{}{
255 Delim('['),
256 decodeThis{map[string]interface{}{"a": float64(1)}},
257 decodeThis{map[string]interface{}{"a": float64(2)}},
258 Delim(']')}},
259 {json: `{ "obj" : [ { "a" : 1 } ] }`, expTokens: []interface{}{
260 Delim('{'), "obj", Delim('['),
261 decodeThis{map[string]interface{}{"a": float64(1)}},
262 Delim(']'), Delim('}')}},
263
264 {json: `{"obj": {"a": 1}}`, expTokens: []interface{}{
265 Delim('{'), "obj",
266 decodeThis{map[string]interface{}{"a": float64(1)}},
267 Delim('}')}},
268 {json: `{"obj": [{"a": 1}]}`, expTokens: []interface{}{
269 Delim('{'), "obj",
270 decodeThis{[]interface{}{
271 map[string]interface{}{"a": float64(1)},
272 }},
273 Delim('}')}},
274 {json: ` [{"a": 1} {"a": 2}] `, expTokens: []interface{}{
275 Delim('['),
276 decodeThis{map[string]interface{}{"a": float64(1)}},
277 decodeThis{&SyntaxError{"expected comma after array element", 0}},
278 }},
279 {json: `{ "a" 1 }`, expTokens: []interface{}{
280 Delim('{'), "a",
281 decodeThis{&SyntaxError{"expected colon after object key", 0}},
282 }},
283 }
284
285 func TestDecodeInStream(t *testing.T) {
286
287 for ci, tcase := range tokenStreamCases {
288
289 dec := NewDecoder(strings.NewReader(tcase.json))
290 for i, etk := range tcase.expTokens {
291
292 var tk interface{}
293 var err error
294
295 if dt, ok := etk.(decodeThis); ok {
296 etk = dt.v
297 err = dec.Decode(&tk)
298 } else {
299 tk, err = dec.Token()
300 }
301 if experr, ok := etk.(error); ok {
302 if err == nil || err.Error() != experr.Error() {
303 t.Errorf("case %v: Expected error %v in %q, but was %v", ci, experr, tcase.json, err)
304 }
305 break
306 } else if err == io.EOF {
307 t.Errorf("case %v: Unexpected EOF in %q", ci, tcase.json)
308 break
309 } else if err != nil {
310 t.Errorf("case %v: Unexpected error '%v' in %q", ci, err, tcase.json)
311 break
312 }
313 if !reflect.DeepEqual(tk, etk) {
314 t.Errorf(`case %v: %q @ %v expected %T(%v) was %T(%v)`, ci, tcase.json, i, etk, etk, tk, tk)
315 break
316 }
317 }
318 }
319
320 }
321
322
323 func TestHTTPDecoding(t *testing.T) {
324 const raw = `{ "foo": "bar" }`
325
326 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
327 w.Write([]byte(raw))
328 }))
329 defer ts.Close()
330 res, err := http.Get(ts.URL)
331 if err != nil {
332 log.Fatalf("GET failed: %v", err)
333 }
334 defer res.Body.Close()
335
336 foo := struct {
337 Foo string `json:"foo"`
338 }{}
339
340 d := NewDecoder(res.Body)
341 err = d.Decode(&foo)
342 if err != nil {
343 t.Fatalf("Decode: %v", err)
344 }
345 if foo.Foo != "bar" {
346 t.Errorf("decoded %q; want \"bar\"", foo.Foo)
347 }
348
349
350 err = d.Decode(&foo)
351 if err != io.EOF {
352 t.Errorf("err = %v; want io.EOF", err)
353 }
354 }
355
View as plain text