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
5package json
6
7import (
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// Test values for the stream test.
21// One of each JSON kind.
22var 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, // another value to make sure something can follow map
31}
32
33var streamEncoded = `0.1
34"hello"
35null
36true
37false
38["a","b","c"]
39{"ß":"long s","K":"Kelvin"}
403.14
41`
42
43func 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
60func TestDecoder(t *testing.T) {
61	for i := 0; i <= len(streamTest); i++ {
62		// Use stream without newlines as input,
63		// just to stress the decoder even more.
64		// Our test input does not include back-to-back numbers.
65		// Otherwise stripping the newlines would
66		// merge two adjacent JSON values.
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
92func 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
114func 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
128func TestRawMessage(t *testing.T) {
129	// TODO(rsc): Should not need the * in *RawMessage
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
153func TestNullRawMessage(t *testing.T) {
154	// TODO(rsc): Should not need the * in *RawMessage
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
178var blockingTests = []string{
179	`{"x": 1}`,
180	`[1, 2, 3]`,
181}
182
183func 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		// If Decode reads beyond what w.Write writes above,
190		// it will block, and the test will deadlock.
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
199func 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
212type tokenStreamCase struct {
213	json      string
214	expTokens []interface{}
215}
216
217type decodeThis struct {
218	v interface{}
219}
220
221var tokenStreamCases []tokenStreamCase = []tokenStreamCase{
222	// streaming token cases
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	// streaming tokens with intermittent Decode()
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
285func 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// Test from golang.org/issue/11893
323func 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
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	// make sure we get the EOF the second time
350	err = d.Decode(&foo)
351	if err != io.EOF {
352		t.Errorf("err = %v; want io.EOF", err)
353	}
354}
355