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.
15 // Tests of simple examples.
22 var examples
= []example
{
26 {`{"":2}`, "{\n\t\"\": 2\n}"},
28 {`[1,2,3]`, "[\n\t1,\n\t2,\n\t3\n]"},
29 {`{"x":1}`, "{\n\t\"x\": 1\n}"},
33 var ex1
= `[true,false,null,"x",1,1.5,0,-5e+2]`
46 func TestCompact(t
*testing
.T
) {
48 for _
, tt
:= range examples
{
50 if err
:= Compact(&buf
, []byte(tt
.compact
)); err
!= nil {
51 t
.Errorf("Compact(%#q): %v", tt
.compact
, err
)
52 } else if s
:= buf
.String(); s
!= tt
.compact
{
53 t
.Errorf("Compact(%#q) = %#q, want original", tt
.compact
, s
)
57 if err
:= Compact(&buf
, []byte(tt
.indent
)); err
!= nil {
58 t
.Errorf("Compact(%#q): %v", tt
.indent
, err
)
60 } else if s
:= buf
.String(); s
!= tt
.compact
{
61 t
.Errorf("Compact(%#q) = %#q, want %#q", tt
.indent
, s
, tt
.compact
)
66 func TestCompactSeparators(t
*testing
.T
) {
67 // U+2028 and U+2029 should be escaped inside strings.
68 // They should not appear outside strings.
72 {"{\"\u2028\": 1}", `{"\u2028":1}`},
73 {"{\"\u2029\" :2}", `{"\u2029":2}`},
75 for _
, tt
:= range tests
{
77 if err
:= Compact(&buf
, []byte(tt
.in
)); err
!= nil {
78 t
.Errorf("Compact(%q): %v", tt
.in
, err
)
79 } else if s
:= buf
.String(); s
!= tt
.compact
{
80 t
.Errorf("Compact(%q) = %q, want %q", tt
.in
, s
, tt
.compact
)
85 func TestIndent(t
*testing
.T
) {
87 for _
, tt
:= range examples
{
89 if err
:= Indent(&buf
, []byte(tt
.indent
), "", "\t"); err
!= nil {
90 t
.Errorf("Indent(%#q): %v", tt
.indent
, err
)
91 } else if s
:= buf
.String(); s
!= tt
.indent
{
92 t
.Errorf("Indent(%#q) = %#q, want original", tt
.indent
, s
)
96 if err
:= Indent(&buf
, []byte(tt
.compact
), "", "\t"); err
!= nil {
97 t
.Errorf("Indent(%#q): %v", tt
.compact
, err
)
99 } else if s
:= buf
.String(); s
!= tt
.indent
{
100 t
.Errorf("Indent(%#q) = %#q, want %#q", tt
.compact
, s
, tt
.indent
)
105 // Tests of a large random structure.
107 func TestCompactBig(t
*testing
.T
) {
110 if err
:= Compact(&buf
, jsonBig
); err
!= nil {
111 t
.Fatalf("Compact: %v", err
)
114 if !bytes
.Equal(b
, jsonBig
) {
115 t
.Error("Compact(jsonBig) != jsonBig")
121 func TestIndentBig(t
*testing
.T
) {
125 if err
:= Indent(&buf
, jsonBig
, "", "\t"); err
!= nil {
126 t
.Fatalf("Indent1: %v", err
)
129 if len(b
) == len(jsonBig
) {
130 // jsonBig is compact (no unnecessary spaces);
131 // indenting should make it bigger
132 t
.Fatalf("Indent(jsonBig) did not get bigger")
135 // should be idempotent
136 var buf1 bytes
.Buffer
137 if err
:= Indent(&buf1
, b
, "", "\t"); err
!= nil {
138 t
.Fatalf("Indent2: %v", err
)
141 if !bytes
.Equal(b1
, b
) {
142 t
.Error("Indent(Indent(jsonBig)) != Indent(jsonBig)")
147 // should get back to original
149 if err
:= Compact(&buf1
, b
); err
!= nil {
150 t
.Fatalf("Compact: %v", err
)
153 if !bytes
.Equal(b1
, jsonBig
) {
154 t
.Error("Compact(Indent(jsonBig)) != jsonBig")
160 type indentErrorTest
struct {
165 var indentErrorTests
= []indentErrorTest
{
166 {`{"X": "foo", "Y"}`, &SyntaxError
{"invalid character '}' after object key", 17}},
167 {`{"X": "foo" "Y": "bar"}`, &SyntaxError
{"invalid character '\"' after object key:value pair", 13}},
170 func TestIndentErrors(t
*testing
.T
) {
171 for i
, tt
:= range indentErrorTests
{
172 slice
:= make([]uint8, 0)
173 buf
:= bytes
.NewBuffer(slice
)
174 if err
:= Indent(buf
, []uint8(tt
.in
), "", ""); err
!= nil {
175 if !reflect
.DeepEqual(err
, tt
.err
) {
176 t
.Errorf("#%d: Indent: %#v", i
, err
)
183 func TestNextValueBig(t
*testing
.T
) {
186 item
, rest
, err
:= nextValue(jsonBig
, &scan
)
188 t
.Fatalf("nextValue: %s", err
)
190 if len(item
) != len(jsonBig
) ||
&item
[0] != &jsonBig
[0] {
191 t
.Errorf("invalid item: %d %d", len(item
), len(jsonBig
))
194 t
.Errorf("invalid rest: %d", len(rest
))
197 item
, rest
, err
= nextValue(append(jsonBig
, "HELLO WORLD"...), &scan
)
199 t
.Fatalf("nextValue extra: %s", err
)
201 if len(item
) != len(jsonBig
) {
202 t
.Errorf("invalid item: %d %d", len(item
), len(jsonBig
))
204 if string(rest
) != "HELLO WORLD" {
205 t
.Errorf("invalid rest: %d", len(rest
))
209 var benchScan scanner
211 func BenchmarkSkipValue(b
*testing
.B
) {
214 for i
:= 0; i
< b
.N
; i
++ {
215 nextValue(jsonBig
, &benchScan
)
217 b
.SetBytes(int64(len(jsonBig
)))
220 func diff(t
*testing
.T
, a
, b
[]byte) {
222 if i
>= len(a
) || i
>= len(b
) || a
[i
] != b
[i
] {
227 t
.Errorf("diverge at %d: «%s» vs «%s»", i
, trim(a
[j
:]), trim(b
[j
:]))
233 func trim(b
[]byte) []byte {
240 // Generate a random JSON object.
249 b
, err
:= Marshal(genValue(n
))
256 func genValue(n
int) interface{} {
258 switch rand
.Intn(2) {
265 switch rand
.Intn(3) {
267 return rand
.Intn(2) == 0
269 return rand
.NormFloat64()
276 func genString(stddev
float64) string {
277 n
:= int(math
.Abs(rand
.NormFloat64()*stddev
+ stddev
/2))
280 f
:= math
.Abs(rand
.NormFloat64()*64 + 32)
289 func genArray(n
int) []interface{} {
290 f
:= int(math
.Abs(rand
.NormFloat64()) * math
.Min(10, float64(n
/2)))
297 x
:= make([]interface{}, f
)
299 x
[i
] = genValue(((i
+1)*n
)/f
- (i
*n
)/f
)
304 func genMap(n
int) map[string]interface{} {
305 f
:= int(math
.Abs(rand
.NormFloat64()) * math
.Min(10, float64(n
/2)))
312 x
:= make(map[string]interface{})
313 for i
:= 0; i
< f
; i
++ {
314 x
[genString(10)] = genValue(((i
+1)*n
)/f
- (i
*n
)/f
)