OSDN Git Service

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