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/ioutil"
10	"net"
11	"reflect"
12	"strings"
13	"testing"
14)
15
16// Test values for the stream test.
17// One of each JSON kind.
18var streamTest = []interface{}{
19	0.1,
20	"hello",
21	nil,
22	true,
23	false,
24	[]interface{}{"a", "b", "c"},
25	map[string]interface{}{"K": "Kelvin", "ß": "long s"},
26	3.14, // another value to make sure something can follow map
27}
28
29var streamEncoded = `0.1
30"hello"
31null
32true
33false
34["a","b","c"]
35{"ß":"long s","K":"Kelvin"}
363.14
37`
38
39func TestEncoder(t *testing.T) {
40	for i := 0; i <= len(streamTest); i++ {
41		var buf bytes.Buffer
42		enc := NewEncoder(&buf)
43		for j, v := range streamTest[0:i] {
44			if err := enc.Encode(v); err != nil {
45				t.Fatalf("encode #%d: %v", j, err)
46			}
47		}
48		if have, want := buf.String(), nlines(streamEncoded, i); have != want {
49			t.Errorf("encoding %d items: mismatch", i)
50			diff(t, []byte(have), []byte(want))
51			break
52		}
53	}
54}
55
56func TestDecoder(t *testing.T) {
57	for i := 0; i <= len(streamTest); i++ {
58		// Use stream without newlines as input,
59		// just to stress the decoder even more.
60		// Our test input does not include back-to-back numbers.
61		// Otherwise stripping the newlines would
62		// merge two adjacent JSON values.
63		var buf bytes.Buffer
64		for _, c := range nlines(streamEncoded, i) {
65			if c != '\n' {
66				buf.WriteRune(c)
67			}
68		}
69		out := make([]interface{}, i)
70		dec := NewDecoder(&buf)
71		for j := range out {
72			if err := dec.Decode(&out[j]); err != nil {
73				t.Fatalf("decode #%d/%d: %v", j, i, err)
74			}
75		}
76		if !reflect.DeepEqual(out, streamTest[0:i]) {
77			t.Errorf("decoding %d items: mismatch", i)
78			for j := range out {
79				if !reflect.DeepEqual(out[j], streamTest[j]) {
80					t.Errorf("#%d: have %v want %v", j, out[j], streamTest[j])
81				}
82			}
83			break
84		}
85	}
86}
87
88func TestDecoderBuffered(t *testing.T) {
89	r := strings.NewReader(`{"Name": "Gopher"} extra `)
90	var m struct {
91		Name string
92	}
93	d := NewDecoder(r)
94	err := d.Decode(&m)
95	if err != nil {
96		t.Fatal(err)
97	}
98	if m.Name != "Gopher" {
99		t.Errorf("Name = %q; want Gopher", m.Name)
100	}
101	rest, err := ioutil.ReadAll(d.Buffered())
102	if err != nil {
103		t.Fatal(err)
104	}
105	if g, w := string(rest), " extra "; g != w {
106		t.Errorf("Remaining = %q; want %q", g, w)
107	}
108}
109
110func nlines(s string, n int) string {
111	if n <= 0 {
112		return ""
113	}
114	for i, c := range s {
115		if c == '\n' {
116			if n--; n == 0 {
117				return s[0 : i+1]
118			}
119		}
120	}
121	return s
122}
123
124func TestRawMessage(t *testing.T) {
125	// TODO(rsc): Should not need the * in *RawMessage
126	var data struct {
127		X  float64
128		Id *RawMessage
129		Y  float32
130	}
131	const raw = `["\u0056",null]`
132	const msg = `{"X":0.1,"Id":["\u0056",null],"Y":0.2}`
133	err := Unmarshal([]byte(msg), &data)
134	if err != nil {
135		t.Fatalf("Unmarshal: %v", err)
136	}
137	if string([]byte(*data.Id)) != raw {
138		t.Fatalf("Raw mismatch: have %#q want %#q", []byte(*data.Id), raw)
139	}
140	b, err := Marshal(&data)
141	if err != nil {
142		t.Fatalf("Marshal: %v", err)
143	}
144	if string(b) != msg {
145		t.Fatalf("Marshal: have %#q want %#q", b, msg)
146	}
147}
148
149func TestNullRawMessage(t *testing.T) {
150	// TODO(rsc): Should not need the * in *RawMessage
151	var data struct {
152		X  float64
153		Id *RawMessage
154		Y  float32
155	}
156	data.Id = new(RawMessage)
157	const msg = `{"X":0.1,"Id":null,"Y":0.2}`
158	err := Unmarshal([]byte(msg), &data)
159	if err != nil {
160		t.Fatalf("Unmarshal: %v", err)
161	}
162	if data.Id != nil {
163		t.Fatalf("Raw mismatch: have non-nil, want nil")
164	}
165	b, err := Marshal(&data)
166	if err != nil {
167		t.Fatalf("Marshal: %v", err)
168	}
169	if string(b) != msg {
170		t.Fatalf("Marshal: have %#q want %#q", b, msg)
171	}
172}
173
174var blockingTests = []string{
175	`{"x": 1}`,
176	`[1, 2, 3]`,
177}
178
179func TestBlocking(t *testing.T) {
180	for _, enc := range blockingTests {
181		r, w := net.Pipe()
182		go w.Write([]byte(enc))
183		var val interface{}
184
185		// If Decode reads beyond what w.Write writes above,
186		// it will block, and the test will deadlock.
187		if err := NewDecoder(r).Decode(&val); err != nil {
188			t.Errorf("decoding %s: %v", enc, err)
189		}
190		r.Close()
191		w.Close()
192	}
193}
194
195func BenchmarkEncoderEncode(b *testing.B) {
196	b.ReportAllocs()
197	type T struct {
198		X, Y string
199	}
200	v := &T{"foo", "bar"}
201	for i := 0; i < b.N; i++ {
202		if err := NewEncoder(ioutil.Discard).Encode(v); err != nil {
203			b.Fatal(err)
204		}
205	}
206}
207