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.
20 // Test values for the stream test.
21 // One of each JSON kind.
22 var streamTest
= []interface{}{
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
33 var streamEncoded
= `0.1
39 {"ß":"long s","K":"Kelvin"}
43 func TestEncoder(t
*testing
.T
) {
44 for i
:= 0; i
<= len(streamTest
); i
++ {
46 enc
:= NewEncoder(&buf
)
47 // Check that enc.SetIndent("", "") turns off indentation.
48 enc
.SetIndent(">", ".")
50 for j
, v
:= range streamTest
[0:i
] {
51 if err
:= enc
.Encode(v
); err
!= nil {
52 t
.Fatalf("encode #%d: %v", j
, err
)
55 if have
, want
:= buf
.String(), nlines(streamEncoded
, i
); have
!= want
{
56 t
.Errorf("encoding %d items: mismatch", i
)
57 diff(t
, []byte(have
), []byte(want
))
63 var streamEncodedIndent
= `0.1
80 func TestEncoderIndent(t
*testing
.T
) {
82 enc
:= NewEncoder(&buf
)
83 enc
.SetIndent(">", ".")
84 for _
, v
:= range streamTest
{
87 if have
, want
:= buf
.String(), streamEncodedIndent
; have
!= want
{
88 t
.Error("indented encoding mismatch")
89 diff(t
, []byte(have
), []byte(want
))
93 func TestEncoderSetEscapeHTML(t
*testing
.T
) {
96 for _
, tt
:= range []struct {
102 {"c", c
, `"\u003c\u0026\u003e"`, `"<&>"`},
103 {"ct", ct
, `"\"\u003c\u0026\u003e\""`, `"\"<&>\""`},
104 {`"<&>"`, "<&>", `"\u003c\u0026\u003e"`, `"<&>"`},
107 enc
:= NewEncoder(&buf
)
108 if err
:= enc
.Encode(tt
.v
); err
!= nil {
109 t
.Fatalf("Encode(%s): %s", tt
.name
, err
)
111 if got
:= strings
.TrimSpace(buf
.String()); got
!= tt
.wantEscape
{
112 t
.Errorf("Encode(%s) = %#q, want %#q", tt
.name
, got
, tt
.wantEscape
)
115 enc
.SetEscapeHTML(false)
116 if err
:= enc
.Encode(tt
.v
); err
!= nil {
117 t
.Fatalf("SetEscapeHTML(false) Encode(%s): %s", tt
.name
, err
)
119 if got
:= strings
.TrimSpace(buf
.String()); got
!= tt
.want
{
120 t
.Errorf("SetEscapeHTML(false) Encode(%s) = %#q, want %#q",
121 tt
.name
, got
, tt
.want
)
126 func TestDecoder(t
*testing
.T
) {
127 for i
:= 0; i
<= len(streamTest
); i
++ {
128 // Use stream without newlines as input,
129 // just to stress the decoder even more.
130 // Our test input does not include back-to-back numbers.
131 // Otherwise stripping the newlines would
132 // merge two adjacent JSON values.
134 for _
, c
:= range nlines(streamEncoded
, i
) {
139 out
:= make([]interface{}, i
)
140 dec
:= NewDecoder(&buf
)
142 if err
:= dec
.Decode(&out
[j
]); err
!= nil {
143 t
.Fatalf("decode #%d/%d: %v", j
, i
, err
)
146 if !reflect
.DeepEqual(out
, streamTest
[0:i
]) {
147 t
.Errorf("decoding %d items: mismatch", i
)
149 if !reflect
.DeepEqual(out
[j
], streamTest
[j
]) {
150 t
.Errorf("#%d: have %v want %v", j
, out
[j
], streamTest
[j
])
158 func TestDecoderBuffered(t
*testing
.T
) {
159 r
:= strings
.NewReader(`{"Name": "Gopher"} extra `)
168 if m
.Name
!= "Gopher" {
169 t
.Errorf("Name = %q; want Gopher", m
.Name
)
171 rest
, err
:= ioutil
.ReadAll(d
.Buffered())
175 if g
, w
:= string(rest
), " extra "; g
!= w
{
176 t
.Errorf("Remaining = %q; want %q", g
, w
)
180 func nlines(s
string, n
int) string {
184 for i
, c
:= range s
{
194 func TestRawMessage(t
*testing
.T
) {
195 // TODO(rsc): Should not need the * in *RawMessage
201 const raw
= `["\u0056",null]`
202 const msg
= `{"X":0.1,"Id":["\u0056",null],"Y":0.2}`
203 err
:= Unmarshal([]byte(msg
), &data
)
205 t
.Fatalf("Unmarshal: %v", err
)
207 if string([]byte(*data
.Id
)) != raw
{
208 t
.Fatalf("Raw mismatch: have %#q want %#q", []byte(*data
.Id
), raw
)
210 b
, err
:= Marshal(&data
)
212 t
.Fatalf("Marshal: %v", err
)
214 if string(b
) != msg
{
215 t
.Fatalf("Marshal: have %#q want %#q", b
, msg
)
219 func TestNullRawMessage(t
*testing
.T
) {
220 // TODO(rsc): Should not need the * in *RawMessage
226 data
.Id
= new(RawMessage
)
227 const msg
= `{"X":0.1,"Id":null,"Y":0.2}`
228 err
:= Unmarshal([]byte(msg
), &data
)
230 t
.Fatalf("Unmarshal: %v", err
)
233 t
.Fatalf("Raw mismatch: have non-nil, want nil")
235 b
, err
:= Marshal(&data
)
237 t
.Fatalf("Marshal: %v", err
)
239 if string(b
) != msg
{
240 t
.Fatalf("Marshal: have %#q want %#q", b
, msg
)
244 var blockingTests
= []string{
249 func TestBlocking(t
*testing
.T
) {
250 for _
, enc
:= range blockingTests
{
252 go w
.Write([]byte(enc
))
255 // If Decode reads beyond what w.Write writes above,
256 // it will block, and the test will deadlock.
257 if err
:= NewDecoder(r
).Decode(&val
); err
!= nil {
258 t
.Errorf("decoding %s: %v", enc
, err
)
265 func BenchmarkEncoderEncode(b
*testing
.B
) {
270 v
:= &T
{"foo", "bar"}
271 b
.RunParallel(func(pb
*testing
.PB
) {
273 if err
:= NewEncoder(ioutil
.Discard
).Encode(v
); err
!= nil {
280 type tokenStreamCase
struct {
282 expTokens
[]interface{}
285 type decodeThis
struct {
289 var tokenStreamCases
[]tokenStreamCase
= []tokenStreamCase
{
290 // streaming token cases
291 {json
: `10`, expTokens
: []interface{}{float64(10)}},
292 {json
: ` [10] `, expTokens
: []interface{}{
293 Delim('['), float64(10), Delim(']')}},
294 {json
: ` [false,10,"b"] `, expTokens
: []interface{}{
295 Delim('['), false, float64(10), "b", Delim(']')}},
296 {json
: `{ "a": 1 }`, expTokens
: []interface{}{
297 Delim('{'), "a", float64(1), Delim('}')}},
298 {json
: `{"a": 1, "b":"3"}`, expTokens
: []interface{}{
299 Delim('{'), "a", float64(1), "b", "3", Delim('}')}},
300 {json
: ` [{"a": 1},{"a": 2}] `, expTokens
: []interface{}{
302 Delim('{'), "a", float64(1), Delim('}'),
303 Delim('{'), "a", float64(2), Delim('}'),
305 {json
: `{"obj": {"a": 1}}`, expTokens
: []interface{}{
306 Delim('{'), "obj", Delim('{'), "a", float64(1), Delim('}'),
308 {json
: `{"obj": [{"a": 1}]}`, expTokens
: []interface{}{
309 Delim('{'), "obj", Delim('['),
310 Delim('{'), "a", float64(1), Delim('}'),
311 Delim(']'), Delim('}')}},
313 // streaming tokens with intermittent Decode()
314 {json
: `{ "a": 1 }`, expTokens
: []interface{}{
316 decodeThis
{float64(1)},
318 {json
: ` [ { "a" : 1 } ] `, expTokens
: []interface{}{
320 decodeThis
{map[string]interface{}{"a": float64(1)}},
322 {json
: ` [{"a": 1},{"a": 2}] `, expTokens
: []interface{}{
324 decodeThis
{map[string]interface{}{"a": float64(1)}},
325 decodeThis
{map[string]interface{}{"a": float64(2)}},
327 {json
: `{ "obj" : [ { "a" : 1 } ] }`, expTokens
: []interface{}{
328 Delim('{'), "obj", Delim('['),
329 decodeThis
{map[string]interface{}{"a": float64(1)}},
330 Delim(']'), Delim('}')}},
332 {json
: `{"obj": {"a": 1}}`, expTokens
: []interface{}{
334 decodeThis
{map[string]interface{}{"a": float64(1)}},
336 {json
: `{"obj": [{"a": 1}]}`, expTokens
: []interface{}{
338 decodeThis
{[]interface{}{
339 map[string]interface{}{"a": float64(1)},
342 {json
: ` [{"a": 1} {"a": 2}] `, expTokens
: []interface{}{
344 decodeThis
{map[string]interface{}{"a": float64(1)}},
345 decodeThis
{&SyntaxError
{"expected comma after array element", 11}},
347 {json
: `{ "` + strings
.Repeat("a", 513) + `" 1 }`, expTokens
: []interface{}{
348 Delim('{'), strings
.Repeat("a", 513),
349 decodeThis
{&SyntaxError
{"expected colon after object key", 518}},
351 {json
: `{ "\a" }`, expTokens
: []interface{}{
353 &SyntaxError
{"invalid character 'a' in string escape code", 3},
355 {json
: ` \a`, expTokens
: []interface{}{
356 &SyntaxError
{"invalid character '\\\\' looking for beginning of value", 1},
360 func TestDecodeInStream(t
*testing
.T
) {
362 for ci
, tcase
:= range tokenStreamCases
{
364 dec
:= NewDecoder(strings
.NewReader(tcase
.json
))
365 for i
, etk
:= range tcase
.expTokens
{
370 if dt
, ok
:= etk
.(decodeThis
); ok
{
372 err
= dec
.Decode(&tk
)
374 tk
, err
= dec
.Token()
376 if experr
, ok
:= etk
.(error
); ok
{
377 if err
== nil ||
!reflect
.DeepEqual(err
, experr
) {
378 t
.Errorf("case %v: Expected error %#v in %q, but was %#v", ci
, experr
, tcase
.json
, err
)
381 } else if err
== io
.EOF
{
382 t
.Errorf("case %v: Unexpected EOF in %q", ci
, tcase
.json
)
384 } else if err
!= nil {
385 t
.Errorf("case %v: Unexpected error '%#v' in %q", ci
, err
, tcase
.json
)
388 if !reflect
.DeepEqual(tk
, etk
) {
389 t
.Errorf(`case %v: %q @ %v expected %T(%v) was %T(%v)`, ci
, tcase
.json
, i
, etk
, etk
, tk
, tk
)
397 // Test from golang.org/issue/11893
398 func TestHTTPDecoding(t
*testing
.T
) {
399 const raw
= `{ "foo": "bar" }`
401 ts
:= httptest
.NewServer(http
.HandlerFunc(func(w http
.ResponseWriter
, r
*http
.Request
) {
405 res
, err
:= http
.Get(ts
.URL
)
407 log
.Fatalf("GET failed: %v", err
)
409 defer res
.Body
.Close()
415 d
:= NewDecoder(res
.Body
)
418 t
.Fatalf("Decode: %v", err
)
420 if foo
.Foo
!= "bar" {
421 t
.Errorf("decoded %q; want \"bar\"", foo
.Foo
)
424 // make sure we get the EOF the second time
427 t
.Errorf("err = %v; want io.EOF", err
)