OSDN Git Service

0d4de3246dd0fa4000df0b67acff73c4c42db420
[pf3gnuchains/gcc-fork.git] / libgo / go / json / scanner_test.go
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
5 package json
6
7 import (
8         "bytes"
9         "math"
10         "rand"
11         "testing"
12 )
13
14 // Tests of simple examples.
15
16 type example struct {
17         compact string
18         indent  string
19 }
20
21 var examples = []example{
22         {`1`, `1`},
23         {`{}`, `{}`},
24         {`[]`, `[]`},
25         {`{"":2}`, "{\n\t\"\": 2\n}"},
26         {`[3]`, "[\n\t3\n]"},
27         {`[1,2,3]`, "[\n\t1,\n\t2,\n\t3\n]"},
28         {`{"x":1}`, "{\n\t\"x\": 1\n}"},
29         {ex1, ex1i},
30 }
31
32 var ex1 = `[true,false,null,"x",1,1.5,0,-5e+2]`
33
34 var ex1i = `[
35         true,
36         false,
37         null,
38         "x",
39         1,
40         1.5,
41         0,
42         -5e+2
43 ]`
44
45 func TestCompact(t *testing.T) {
46         var buf bytes.Buffer
47         for _, tt := range examples {
48                 buf.Reset()
49                 if err := Compact(&buf, []byte(tt.compact)); err != nil {
50                         t.Errorf("Compact(%#q): %v", tt.compact, err)
51                 } else if s := buf.String(); s != tt.compact {
52                         t.Errorf("Compact(%#q) = %#q, want original", tt.compact, s)
53                 }
54
55                 buf.Reset()
56                 if err := Compact(&buf, []byte(tt.indent)); err != nil {
57                         t.Errorf("Compact(%#q): %v", tt.indent, err)
58                         continue
59                 } else if s := buf.String(); s != tt.compact {
60                         t.Errorf("Compact(%#q) = %#q, want %#q", tt.indent, s, tt.compact)
61                 }
62         }
63 }
64
65 func TestIndent(t *testing.T) {
66         var buf bytes.Buffer
67         for _, tt := range examples {
68                 buf.Reset()
69                 if err := Indent(&buf, []byte(tt.indent), "", "\t"); err != nil {
70                         t.Errorf("Indent(%#q): %v", tt.indent, err)
71                 } else if s := buf.String(); s != tt.indent {
72                         t.Errorf("Indent(%#q) = %#q, want original", tt.indent, s)
73                 }
74
75                 buf.Reset()
76                 if err := Indent(&buf, []byte(tt.compact), "", "\t"); err != nil {
77                         t.Errorf("Indent(%#q): %v", tt.compact, err)
78                         continue
79                 } else if s := buf.String(); s != tt.indent {
80                         t.Errorf("Indent(%#q) = %#q, want %#q", tt.compact, s, tt.indent)
81                 }
82         }
83 }
84
85 // Tests of a large random structure.
86
87 func TestCompactBig(t *testing.T) {
88         initBig()
89         var buf bytes.Buffer
90         if err := Compact(&buf, jsonBig); err != nil {
91                 t.Fatalf("Compact: %v", err)
92         }
93         b := buf.Bytes()
94         if bytes.Compare(b, jsonBig) != 0 {
95                 t.Error("Compact(jsonBig) != jsonBig")
96                 diff(t, b, jsonBig)
97                 return
98         }
99 }
100
101 func TestIndentBig(t *testing.T) {
102         initBig()
103         var buf bytes.Buffer
104         if err := Indent(&buf, jsonBig, "", "\t"); err != nil {
105                 t.Fatalf("Indent1: %v", err)
106         }
107         b := buf.Bytes()
108         if len(b) == len(jsonBig) {
109                 // jsonBig is compact (no unnecessary spaces);
110                 // indenting should make it bigger
111                 t.Fatalf("Indent(jsonBig) did not get bigger")
112         }
113
114         // should be idempotent
115         var buf1 bytes.Buffer
116         if err := Indent(&buf1, b, "", "\t"); err != nil {
117                 t.Fatalf("Indent2: %v", err)
118         }
119         b1 := buf1.Bytes()
120         if bytes.Compare(b1, b) != 0 {
121                 t.Error("Indent(Indent(jsonBig)) != Indent(jsonBig)")
122                 diff(t, b1, b)
123                 return
124         }
125
126         // should get back to original
127         buf1.Reset()
128         if err := Compact(&buf1, b); err != nil {
129                 t.Fatalf("Compact: %v", err)
130         }
131         b1 = buf1.Bytes()
132         if bytes.Compare(b1, jsonBig) != 0 {
133                 t.Error("Compact(Indent(jsonBig)) != jsonBig")
134                 diff(t, b1, jsonBig)
135                 return
136         }
137 }
138
139 func TestNextValueBig(t *testing.T) {
140         initBig()
141         var scan scanner
142         item, rest, err := nextValue(jsonBig, &scan)
143         if err != nil {
144                 t.Fatalf("nextValue: %s", err)
145         }
146         if len(item) != len(jsonBig) || &item[0] != &jsonBig[0] {
147                 t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
148         }
149         if len(rest) != 0 {
150                 t.Errorf("invalid rest: %d", len(rest))
151         }
152
153         item, rest, err = nextValue(append(jsonBig, []byte("HELLO WORLD")...), &scan)
154         if err != nil {
155                 t.Fatalf("nextValue extra: %s", err)
156         }
157         if len(item) != len(jsonBig) {
158                 t.Errorf("invalid item: %d %d", len(item), len(jsonBig))
159         }
160         if string(rest) != "HELLO WORLD" {
161                 t.Errorf("invalid rest: %d", len(rest))
162         }
163 }
164
165 func BenchmarkSkipValue(b *testing.B) {
166         initBig()
167         var scan scanner
168         for i := 0; i < b.N; i++ {
169                 nextValue(jsonBig, &scan)
170         }
171         b.SetBytes(int64(len(jsonBig)))
172 }
173
174 func diff(t *testing.T, a, b []byte) {
175         for i := 0; ; i++ {
176                 if i >= len(a) || i >= len(b) || a[i] != b[i] {
177                         j := i - 10
178                         if j < 0 {
179                                 j = 0
180                         }
181                         t.Errorf("diverge at %d: «%s» vs «%s»", i, trim(a[j:]), trim(b[j:]))
182                         return
183                 }
184         }
185 }
186
187 func trim(b []byte) []byte {
188         if len(b) > 20 {
189                 return b[0:20]
190         }
191         return b
192 }
193
194 // Generate a random JSON object.
195
196 var jsonBig []byte
197
198 const (
199         big   = 10000
200         small = 100
201 )
202
203 func initBig() {
204         n := big
205         if testing.Short() {
206                 n = small
207         }
208         if len(jsonBig) != n {
209                 b, err := Marshal(genValue(n))
210                 if err != nil {
211                         panic(err)
212                 }
213                 jsonBig = b
214         }
215 }
216
217 func genValue(n int) interface{} {
218         if n > 1 {
219                 switch rand.Intn(2) {
220                 case 0:
221                         return genArray(n)
222                 case 1:
223                         return genMap(n)
224                 }
225         }
226         switch rand.Intn(3) {
227         case 0:
228                 return rand.Intn(2) == 0
229         case 1:
230                 return rand.NormFloat64()
231         case 2:
232                 return genString(30)
233         }
234         panic("unreachable")
235 }
236
237 func genString(stddev float64) string {
238         n := int(math.Fabs(rand.NormFloat64()*stddev + stddev/2))
239         c := make([]int, n)
240         for i := range c {
241                 f := math.Fabs(rand.NormFloat64()*64 + 32)
242                 if f > 0x10ffff {
243                         f = 0x10ffff
244                 }
245                 c[i] = int(f)
246         }
247         return string(c)
248 }
249
250 func genArray(n int) []interface{} {
251         f := int(math.Fabs(rand.NormFloat64()) * math.Fmin(10, float64(n/2)))
252         if f > n {
253                 f = n
254         }
255         x := make([]interface{}, int(f))
256         for i := range x {
257                 x[i] = genValue(((i+1)*n)/f - (i*n)/f)
258         }
259         return x
260 }
261
262 func genMap(n int) map[string]interface{} {
263         f := int(math.Fabs(rand.NormFloat64()) * math.Fmin(10, float64(n/2)))
264         if f > n {
265                 f = n
266         }
267         if n > 0 && f == 0 {
268                 f = 1
269         }
270         x := make(map[string]interface{})
271         for i := 0; i < f; i++ {
272                 x[genString(10)] = genValue(((i+1)*n)/f - (i*n)/f)
273         }
274         return x
275 }