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 var validTests
= []struct {
23 {`{"foo":"bar"}`, true},
24 {`{"foo":"bar","bar":{"baz":["qux"]}}`, true},
27 func TestValid(t
*testing
.T
) {
28 for _
, tt
:= range validTests
{
29 if ok
:= Valid([]byte(tt
.data
)); ok
!= tt
.ok
{
30 t
.Errorf("Valid(%#q) = %v, want %v", tt
.data
, ok
, tt
.ok
)
35 // Tests of simple examples.
42 var examples
= []example
{
46 {`{"":2}`, "{\n\t\"\": 2\n}"},
48 {`[1,2,3]`, "[\n\t1,\n\t2,\n\t3\n]"},
49 {`{"x":1}`, "{\n\t\"x\": 1\n}"},
51 {"{\"\":\"<>&\u2028\u2029\"}", "{\n\t\"\": \"<>&\u2028\u2029\"\n}"}, // See golang.org/issue/34070
54 var ex1
= `[true,false,null,"x",1,1.5,0,-5e+2]`
67 func TestCompact(t
*testing
.T
) {
69 for _
, tt
:= range examples
{
71 if err
:= Compact(&buf
, []byte(tt
.compact
)); err
!= nil {
72 t
.Errorf("Compact(%#q): %v", tt
.compact
, err
)
73 } else if s
:= buf
.String(); s
!= tt
.compact
{
74 t
.Errorf("Compact(%#q) = %#q, want original", tt
.compact
, s
)
78 if err
:= Compact(&buf
, []byte(tt
.indent
)); err
!= nil {
79 t
.Errorf("Compact(%#q): %v", tt
.indent
, err
)
81 } else if s
:= buf
.String(); s
!= tt
.compact
{
82 t
.Errorf("Compact(%#q) = %#q, want %#q", tt
.indent
, s
, tt
.compact
)
87 func TestCompactSeparators(t
*testing
.T
) {
88 // U+2028 and U+2029 should be escaped inside strings.
89 // They should not appear outside strings.
93 {"{\"\u2028\": 1}", "{\"\u2028\":1}"},
94 {"{\"\u2029\" :2}", "{\"\u2029\":2}"},
96 for _
, tt
:= range tests
{
98 if err
:= Compact(&buf
, []byte(tt
.in
)); err
!= nil {
99 t
.Errorf("Compact(%q): %v", tt
.in
, err
)
100 } else if s
:= buf
.String(); s
!= tt
.compact
{
101 t
.Errorf("Compact(%q) = %q, want %q", tt
.in
, s
, tt
.compact
)
106 func TestIndent(t
*testing
.T
) {
108 for _
, tt
:= range examples
{
110 if err
:= Indent(&buf
, []byte(tt
.indent
), "", "\t"); err
!= nil {
111 t
.Errorf("Indent(%#q): %v", tt
.indent
, err
)
112 } else if s
:= buf
.String(); s
!= tt
.indent
{
113 t
.Errorf("Indent(%#q) = %#q, want original", tt
.indent
, s
)
117 if err
:= Indent(&buf
, []byte(tt
.compact
), "", "\t"); err
!= nil {
118 t
.Errorf("Indent(%#q): %v", tt
.compact
, err
)
120 } else if s
:= buf
.String(); s
!= tt
.indent
{
121 t
.Errorf("Indent(%#q) = %#q, want %#q", tt
.compact
, s
, tt
.indent
)
126 // Tests of a large random structure.
128 func TestCompactBig(t
*testing
.T
) {
131 if err
:= Compact(&buf
, jsonBig
); err
!= nil {
132 t
.Fatalf("Compact: %v", err
)
135 if !bytes
.Equal(b
, jsonBig
) {
136 t
.Error("Compact(jsonBig) != jsonBig")
142 func TestIndentBig(t
*testing
.T
) {
146 if err
:= Indent(&buf
, jsonBig
, "", "\t"); err
!= nil {
147 t
.Fatalf("Indent1: %v", err
)
150 if len(b
) == len(jsonBig
) {
151 // jsonBig is compact (no unnecessary spaces);
152 // indenting should make it bigger
153 t
.Fatalf("Indent(jsonBig) did not get bigger")
156 // should be idempotent
157 var buf1 bytes
.Buffer
158 if err
:= Indent(&buf1
, b
, "", "\t"); err
!= nil {
159 t
.Fatalf("Indent2: %v", err
)
162 if !bytes
.Equal(b1
, b
) {
163 t
.Error("Indent(Indent(jsonBig)) != Indent(jsonBig)")
168 // should get back to original
170 if err
:= Compact(&buf1
, b
); err
!= nil {
171 t
.Fatalf("Compact: %v", err
)
174 if !bytes
.Equal(b1
, jsonBig
) {
175 t
.Error("Compact(Indent(jsonBig)) != jsonBig")
181 type indentErrorTest
struct {
186 var indentErrorTests
= []indentErrorTest
{
187 {`{"X": "foo", "Y"}`, &SyntaxError
{"invalid character '}' after object key", 17}},
188 {`{"X": "foo" "Y": "bar"}`, &SyntaxError
{"invalid character '\"' after object key:value pair", 13}},
191 func TestIndentErrors(t
*testing
.T
) {
192 for i
, tt
:= range indentErrorTests
{
193 slice
:= make([]uint8, 0)
194 buf
:= bytes
.NewBuffer(slice
)
195 if err
:= Indent(buf
, []uint8(tt
.in
), "", ""); err
!= nil {
196 if !reflect
.DeepEqual(err
, tt
.err
) {
197 t
.Errorf("#%d: Indent: %#v", i
, err
)
204 func diff(t
*testing
.T
, a
, b
[]byte) {
206 if i
>= len(a
) || i
>= len(b
) || a
[i
] != b
[i
] {
211 t
.Errorf("diverge at %d: «%s» vs «%s»", i
, trim(a
[j
:]), trim(b
[j
:]))
217 func trim(b
[]byte) []byte {
224 // Generate a random JSON object.
233 b
, err
:= Marshal(genValue(n
))
240 func genValue(n
int) any
{
242 switch rand
.Intn(2) {
249 switch rand
.Intn(3) {
251 return rand
.Intn(2) == 0
253 return rand
.NormFloat64()
260 func genString(stddev
float64) string {
261 n
:= int(math
.Abs(rand
.NormFloat64()*stddev
+ stddev
/2))
264 f
:= math
.Abs(rand
.NormFloat64()*64 + 32)
273 func genArray(n
int) []any
{
274 f
:= int(math
.Abs(rand
.NormFloat64()) * math
.Min(10, float64(n
/2)))
283 x
[i
] = genValue(((i
+1)*n
)/f
- (i
*n
)/f
)
288 func genMap(n
int) map[string]any
{
289 f
:= int(math
.Abs(rand
.NormFloat64()) * math
.Min(10, float64(n
/2)))
296 x
:= make(map[string]any
)
297 for i
:= 0; i
< f
; i
++ {
298 x
[genString(10)] = genValue(((i
+1)*n
)/f
- (i
*n
)/f
)