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
) {
124 if err
:= Indent(&buf
, jsonBig
, "", "\t"); err
!= nil {
125 t
.Fatalf("Indent1: %v", err
)
128 if len(b
) == len(jsonBig
) {
129 // jsonBig is compact (no unnecessary spaces);
130 // indenting should make it bigger
131 t
.Fatalf("Indent(jsonBig) did not get bigger")
134 // should be idempotent
135 var buf1 bytes
.Buffer
136 if err
:= Indent(&buf1
, b
, "", "\t"); err
!= nil {
137 t
.Fatalf("Indent2: %v", err
)
140 if !bytes
.Equal(b1
, b
) {
141 t
.Error("Indent(Indent(jsonBig)) != Indent(jsonBig)")
146 // should get back to original
148 if err
:= Compact(&buf1
, b
); err
!= nil {
149 t
.Fatalf("Compact: %v", err
)
152 if !bytes
.Equal(b1
, jsonBig
) {
153 t
.Error("Compact(Indent(jsonBig)) != jsonBig")
159 type indentErrorTest
struct {
164 var indentErrorTests
= []indentErrorTest
{
165 {`{"X": "foo", "Y"}`, &SyntaxError
{"invalid character '}' after object key", 17}},
166 {`{"X": "foo" "Y": "bar"}`, &SyntaxError
{"invalid character '\"' after object key:value pair", 13}},
169 func TestIndentErrors(t
*testing
.T
) {
170 for i
, tt
:= range indentErrorTests
{
171 slice
:= make([]uint8, 0)
172 buf
:= bytes
.NewBuffer(slice
)
173 if err
:= Indent(buf
, []uint8(tt
.in
), "", ""); err
!= nil {
174 if !reflect
.DeepEqual(err
, tt
.err
) {
175 t
.Errorf("#%d: Indent: %#v", i
, err
)
182 func TestNextValueBig(t
*testing
.T
) {
185 item
, rest
, err
:= nextValue(jsonBig
, &scan
)
187 t
.Fatalf("nextValue: %s", err
)
189 if len(item
) != len(jsonBig
) ||
&item
[0] != &jsonBig
[0] {
190 t
.Errorf("invalid item: %d %d", len(item
), len(jsonBig
))
193 t
.Errorf("invalid rest: %d", len(rest
))
196 item
, rest
, err
= nextValue(append(jsonBig
, "HELLO WORLD"...), &scan
)
198 t
.Fatalf("nextValue extra: %s", err
)
200 if len(item
) != len(jsonBig
) {
201 t
.Errorf("invalid item: %d %d", len(item
), len(jsonBig
))
203 if string(rest
) != "HELLO WORLD" {
204 t
.Errorf("invalid rest: %d", len(rest
))
208 var benchScan scanner
210 func BenchmarkSkipValue(b
*testing
.B
) {
212 for i
:= 0; i
< b
.N
; i
++ {
213 nextValue(jsonBig
, &benchScan
)
215 b
.SetBytes(int64(len(jsonBig
)))
218 func diff(t
*testing
.T
, a
, b
[]byte) {
220 if i
>= len(a
) || i
>= len(b
) || a
[i
] != b
[i
] {
225 t
.Errorf("diverge at %d: «%s» vs «%s»", i
, trim(a
[j
:]), trim(b
[j
:]))
231 func trim(b
[]byte) []byte {
238 // Generate a random JSON object.
247 b
, err
:= Marshal(genValue(n
))
254 func genValue(n
int) interface{} {
256 switch rand
.Intn(2) {
263 switch rand
.Intn(3) {
265 return rand
.Intn(2) == 0
267 return rand
.NormFloat64()
274 func genString(stddev
float64) string {
275 n
:= int(math
.Abs(rand
.NormFloat64()*stddev
+ stddev
/2))
278 f
:= math
.Abs(rand
.NormFloat64()*64 + 32)
287 func genArray(n
int) []interface{} {
288 f
:= int(math
.Abs(rand
.NormFloat64()) * math
.Min(10, float64(n
/2)))
295 x
:= make([]interface{}, f
)
297 x
[i
] = genValue(((i
+1)*n
)/f
- (i
*n
)/f
)
302 func genMap(n
int) map[string]interface{} {
303 f
:= int(math
.Abs(rand
.NormFloat64()) * math
.Min(10, float64(n
/2)))
310 x
:= make(map[string]interface{})
311 for i
:= 0; i
< f
; i
++ {
312 x
[genString(10)] = genValue(((i
+1)*n
)/f
- (i
*n
)/f
)