1 package jlexer
2
3 import (
4 "bytes"
5 "encoding/json"
6 "reflect"
7 "testing"
8 )
9
10 func TestString(t *testing.T) {
11 for i, test := range []struct {
12 toParse string
13 want string
14 wantError bool
15 }{
16 {toParse: `"simple string"`, want: "simple string"},
17 {toParse: " \r\r\n\t " + `"test"`, want: "test"},
18 {toParse: `"\n\t\"\/\\\f\r"`, want: "\n\t\"/\\\f\r"},
19 {toParse: `"\u0020"`, want: " "},
20 {toParse: `"\u0020-\t"`, want: " -\t"},
21 {toParse: `"\ufffd\uFFFD"`, want: "\ufffd\ufffd"},
22 {toParse: `"\ud83d\ude00"`, want: "😀"},
23 {toParse: `"\ud83d\ude08"`, want: "😈"},
24 {toParse: `"\ud8"`, wantError: true},
25
26 {toParse: `"test"junk`, want: "test"},
27
28 {toParse: `5`, wantError: true},
29 {toParse: `"\x"`, wantError: true},
30 {toParse: `"\ud800"`, want: "�"},
31 } {
32 {
33 l := Lexer{Data: []byte(test.toParse)}
34
35 got := l.String()
36 if got != test.want {
37 t.Errorf("[%d, %q] String() = %v; want %v", i, test.toParse, got, test.want)
38 }
39 err := l.Error()
40 if err != nil && !test.wantError {
41 t.Errorf("[%d, %q] String() error: %v", i, test.toParse, err)
42 } else if err == nil && test.wantError {
43 t.Errorf("[%d, %q] String() ok; want error", i, test.toParse)
44 }
45 }
46 {
47 l := Lexer{Data: []byte(test.toParse)}
48
49 got := l.StringIntern()
50 if got != test.want {
51 t.Errorf("[%d, %q] String() = %v; want %v", i, test.toParse, got, test.want)
52 }
53 err := l.Error()
54 if err != nil && !test.wantError {
55 t.Errorf("[%d, %q] String() error: %v", i, test.toParse, err)
56 } else if err == nil && test.wantError {
57 t.Errorf("[%d, %q] String() ok; want error", i, test.toParse)
58 }
59 }
60 }
61 }
62
63 func TestStringIntern(t *testing.T) {
64 data := []byte(`"string interning test"`)
65 var l Lexer
66
67 allocsPerRun := testing.AllocsPerRun(1000, func() {
68 l = Lexer{Data: data}
69 _ = l.StringIntern()
70 })
71 if allocsPerRun != 0 {
72 t.Fatalf("expected 0 allocs, got %f", allocsPerRun)
73 }
74
75 allocsPerRun = testing.AllocsPerRun(1000, func() {
76 l = Lexer{Data: data}
77 _ = l.String()
78 })
79 if allocsPerRun != 1 {
80 t.Fatalf("expected 1 allocs, got %f", allocsPerRun)
81 }
82 }
83
84 func TestBytes(t *testing.T) {
85 for i, test := range []struct {
86 toParse string
87 want string
88 wantError bool
89 }{
90 {toParse: `"c2ltcGxlIHN0cmluZw=="`, want: "simple string"},
91 {toParse: " \r\r\n\t " + `"dGVzdA=="`, want: "test"},
92 {toParse: `"c3ViamVjdHM\/X2Q9MQ=="`, want: "subjects?_d=1"},
93
94 {toParse: `5`, wantError: true},
95 {toParse: `"foobar"`, wantError: true},
96 {toParse: `"c2ltcGxlIHN0cmluZw="`, wantError: true},
97 } {
98 l := Lexer{Data: []byte(test.toParse)}
99
100 got := l.Bytes()
101 if bytes.Compare(got, []byte(test.want)) != 0 {
102 t.Errorf("[%d, %q] Bytes() = %v; want: %v", i, test.toParse, got, []byte(test.want))
103 }
104 err := l.Error()
105 if err != nil && !test.wantError {
106 t.Errorf("[%d, %q] Bytes() error: %v", i, test.toParse, err)
107 } else if err == nil && test.wantError {
108 t.Errorf("[%d, %q] Bytes() ok; want error", i, test.toParse)
109 }
110 }
111 }
112
113 func TestNumber(t *testing.T) {
114 for i, test := range []struct {
115 toParse string
116 want string
117 wantError bool
118 }{
119 {toParse: "123", want: "123"},
120 {toParse: "-123", want: "-123"},
121 {toParse: "\r\n12.35", want: "12.35"},
122 {toParse: "12.35e+1", want: "12.35e+1"},
123 {toParse: "12.35e-15", want: "12.35e-15"},
124 {toParse: "12.35E-15", want: "12.35E-15"},
125 {toParse: "12.35E15", want: "12.35E15"},
126
127 {toParse: `"a"`, wantError: true},
128 {toParse: "123junk", wantError: true},
129 {toParse: "1.2.3", wantError: true},
130 {toParse: "1e2e3", wantError: true},
131 {toParse: "1e2.3", wantError: true},
132 } {
133 l := Lexer{Data: []byte(test.toParse)}
134
135 got := l.number()
136 if got != test.want {
137 t.Errorf("[%d, %q] number() = %v; want %v", i, test.toParse, got, test.want)
138 }
139 err := l.Error()
140 if err != nil && !test.wantError {
141 t.Errorf("[%d, %q] number() error: %v", i, test.toParse, err)
142 } else if err == nil && test.wantError {
143 t.Errorf("[%d, %q] number() ok; want error", i, test.toParse)
144 }
145 }
146 }
147
148 func TestBool(t *testing.T) {
149 for i, test := range []struct {
150 toParse string
151 want bool
152 wantError bool
153 }{
154 {toParse: "true", want: true},
155 {toParse: "false", want: false},
156
157 {toParse: "1", wantError: true},
158 {toParse: "truejunk", wantError: true},
159 {toParse: `false"junk"`, wantError: true},
160 {toParse: "True", wantError: true},
161 {toParse: "False", wantError: true},
162 } {
163 l := Lexer{Data: []byte(test.toParse)}
164
165 got := l.Bool()
166 if got != test.want {
167 t.Errorf("[%d, %q] Bool() = %v; want %v", i, test.toParse, got, test.want)
168 }
169 err := l.Error()
170 if err != nil && !test.wantError {
171 t.Errorf("[%d, %q] Bool() error: %v", i, test.toParse, err)
172 } else if err == nil && test.wantError {
173 t.Errorf("[%d, %q] Bool() ok; want error", i, test.toParse)
174 }
175 }
176 }
177
178 func TestSkipRecursive(t *testing.T) {
179 for i, test := range []struct {
180 toParse string
181 left string
182 wantError bool
183 }{
184 {toParse: "5, 4", left: ", 4"},
185 {toParse: "[5, 6], 4", left: ", 4"},
186 {toParse: "[5, [7,8]]: 4", left: ": 4"},
187
188 {toParse: `{"a":1}, 4`, left: ", 4"},
189 {toParse: `{"a":1, "b":{"c": 5}, "e":[12,15]}, 4`, left: ", 4"},
190
191
192 {toParse: `[5, "]"], 4`, left: ", 4"},
193 {toParse: `[5, "\"]"], 4`, left: ", 4"},
194 {toParse: `[5, "["], 4`, left: ", 4"},
195 {toParse: `[5, "\"["], 4`, left: ", 4"},
196
197
198 {toParse: `{"a}":1}, 4`, left: ", 4"},
199 {toParse: `{"a\"}":1}, 4`, left: ", 4"},
200 {toParse: `{"a{":1}, 4`, left: ", 4"},
201 {toParse: `{"a\"{":1}, 4`, left: ", 4"},
202
203
204 {toParse: `{"a":"hey\\"}, 4`, left: ", 4"},
205
206
207 {toParse: `{"a": [ ##invalid json## ]}, 4`, wantError: true},
208 {toParse: `{"a": [ [1], [ ##invalid json## ]]}, 4`, wantError: true},
209 } {
210 l := Lexer{Data: []byte(test.toParse)}
211
212 l.SkipRecursive()
213
214 got := string(l.Data[l.pos:])
215 if got != test.left {
216 t.Errorf("[%d, %q] SkipRecursive() left = %v; want %v", i, test.toParse, got, test.left)
217 }
218 err := l.Error()
219 if err != nil && !test.wantError {
220 t.Errorf("[%d, %q] SkipRecursive() error: %v", i, test.toParse, err)
221 } else if err == nil && test.wantError {
222 t.Errorf("[%d, %q] SkipRecursive() ok; want error", i, test.toParse)
223 }
224 }
225 }
226
227 func TestInterface(t *testing.T) {
228 for i, test := range []struct {
229 toParse string
230 want interface{}
231 wantError bool
232 }{
233 {toParse: "null", want: nil},
234 {toParse: "true", want: true},
235 {toParse: `"a"`, want: "a"},
236 {toParse: "5", want: float64(5)},
237
238 {toParse: `{}`, want: map[string]interface{}{}},
239 {toParse: `[]`, want: []interface{}{}},
240
241 {toParse: `{"a": "b"}`, want: map[string]interface{}{"a": "b"}},
242 {toParse: `[5]`, want: []interface{}{float64(5)}},
243
244 {toParse: `{"a":5 , "b" : "string"}`, want: map[string]interface{}{"a": float64(5), "b": "string"}},
245 {toParse: `["a", 5 , null, true]`, want: []interface{}{"a", float64(5), nil, true}},
246
247 {toParse: `{"a" "b"}`, wantError: true},
248 {toParse: `{"a": "b",}`, wantError: true},
249 {toParse: `{"a":"b","c" "b"}`, wantError: true},
250 {toParse: `{"a": "b","c":"d",}`, wantError: true},
251 {toParse: `{,}`, wantError: true},
252
253 {toParse: `[1, 2,]`, wantError: true},
254 {toParse: `[1 2]`, wantError: true},
255 {toParse: `[,]`, wantError: true},
256 } {
257 l := Lexer{Data: []byte(test.toParse)}
258
259 got := l.Interface()
260 if !reflect.DeepEqual(got, test.want) {
261 t.Errorf("[%d, %q] Interface() = %v; want %v", i, test.toParse, got, test.want)
262 }
263 err := l.Error()
264 if err != nil && !test.wantError {
265 t.Errorf("[%d, %q] Interface() error: %v", i, test.toParse, err)
266 } else if err == nil && test.wantError {
267 t.Errorf("[%d, %q] Interface() ok; want error", i, test.toParse)
268 }
269 }
270 }
271
272 func TestConsumed(t *testing.T) {
273 for i, test := range []struct {
274 toParse string
275 wantError bool
276 }{
277 {toParse: "", wantError: false},
278 {toParse: " ", wantError: false},
279 {toParse: "\r\n", wantError: false},
280 {toParse: "\t\t", wantError: false},
281
282 {toParse: "{", wantError: true},
283 } {
284 l := Lexer{Data: []byte(test.toParse)}
285 l.Consumed()
286
287 err := l.Error()
288 if err != nil && !test.wantError {
289 t.Errorf("[%d, %q] Consumed() error: %v", i, test.toParse, err)
290 } else if err == nil && test.wantError {
291 t.Errorf("[%d, %q] Consumed() ok; want error", i, test.toParse)
292 }
293 }
294 }
295
296 func TestJsonNumber(t *testing.T) {
297 for i, test := range []struct {
298 toParse string
299 want json.Number
300 wantLexerError bool
301 wantValue interface{}
302 wantValueError bool
303 }{
304 {toParse: `10`, want: json.Number("10"), wantValue: int64(10)},
305 {toParse: `0`, want: json.Number("0"), wantValue: int64(0)},
306 {toParse: `0.12`, want: json.Number("0.12"), wantValue: 0.12},
307 {toParse: `25E-4`, want: json.Number("25E-4"), wantValue: 25e-4},
308
309 {toParse: `"10"`, want: json.Number("10"), wantValue: int64(10)},
310 {toParse: `"0"`, want: json.Number("0"), wantValue: int64(0)},
311 {toParse: `"0.12"`, want: json.Number("0.12"), wantValue: 0.12},
312 {toParse: `"25E-4"`, want: json.Number("25E-4"), wantValue: 25e-4},
313
314 {toParse: `"foo"`, want: json.Number("foo"), wantValueError: true},
315 {toParse: `null`, want: json.Number(""), wantValueError: true},
316
317 {toParse: `"a""`, want: json.Number("a"), wantValueError: true},
318
319 {toParse: `[1]`, want: json.Number(""), wantLexerError: true, wantValueError: true},
320 {toParse: `{}`, want: json.Number(""), wantLexerError: true, wantValueError: true},
321 {toParse: `a`, want: json.Number(""), wantLexerError: true, wantValueError: true},
322 } {
323 l := Lexer{Data: []byte(test.toParse)}
324
325 got := l.JsonNumber()
326 if got != test.want {
327 t.Errorf("[%d, %q] JsonNumber() = %v; want %v", i, test.toParse, got, test.want)
328 }
329
330 err := l.Error()
331 if err != nil && !test.wantLexerError {
332 t.Errorf("[%d, %q] JsonNumber() lexer error: %v", i, test.toParse, err)
333 } else if err == nil && test.wantLexerError {
334 t.Errorf("[%d, %q] JsonNumber() ok; want lexer error", i, test.toParse)
335 }
336
337 var valueErr error
338 var gotValue interface{}
339 switch test.wantValue.(type) {
340 case float64:
341 gotValue, valueErr = got.Float64()
342 default:
343 gotValue, valueErr = got.Int64()
344 }
345
346 if !reflect.DeepEqual(gotValue, test.wantValue) && !test.wantLexerError && !test.wantValueError {
347 t.Errorf("[%d, %q] JsonNumber() = %v; want %v", i, test.toParse, gotValue, test.wantValue)
348 }
349
350 if valueErr != nil && !test.wantValueError {
351 t.Errorf("[%d, %q] JsonNumber() value error: %v", i, test.toParse, valueErr)
352 } else if valueErr == nil && test.wantValueError {
353 t.Errorf("[%d, %q] JsonNumber() ok; want value error", i, test.toParse)
354 }
355 }
356 }
357
358 func TestFetchStringUnterminatedString(t *testing.T) {
359 for _, test := range []struct {
360 data []byte
361 }{
362 {data: []byte(`"sting without trailing quote`)},
363 {data: []byte(`"\"`)},
364 {data: []byte{'"'}},
365 } {
366 l := Lexer{Data: test.data}
367 l.fetchString()
368 if l.pos > len(l.Data) {
369 t.Errorf("fetchString(%s): pos=%v should not be greater than length of Data = %v", test.data, l.pos, len(l.Data))
370 }
371 if l.Error() == nil {
372 t.Errorf("fetchString(%s): should add parsing error", test.data)
373 }
374 }
375 }
376
View as plain text