yajl-ffi 0.1.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/spec/parser_spec.rb DELETED
@@ -1,900 +0,0 @@
1
- require 'yajl/ffi'
2
- require 'minitest/autorun'
3
-
4
- describe Yajl::FFI::Parser do
5
- subject { Yajl::FFI::Parser.new }
6
-
7
- describe 'parsing a document' do
8
- it 'rejects documents containing bad start character' do
9
- expected = [:error]
10
- assert_equal expected, events('a')
11
- end
12
-
13
- it 'rejects documents starting with period' do
14
- expected = [:error]
15
- assert_equal expected, events('.')
16
- end
17
-
18
- it 'parses a null value document' do
19
- expected = [:start_document, [:value, nil], :end_document]
20
- assert_equal expected, events('null')
21
- end
22
-
23
- it 'parses a false value document' do
24
- expected = [:start_document, [:value, false], :end_document]
25
- assert_equal expected, events('false')
26
- end
27
-
28
- it 'parses a true value document' do
29
- expected = [:start_document, [:value, true], :end_document]
30
- assert_equal expected, events('true')
31
- end
32
-
33
- it 'parses a string document' do
34
- expected = [:start_document, [:value, "test"], :end_document]
35
- assert_equal expected, events('"test"')
36
- end
37
-
38
- it 'parses a single digit integer value document' do
39
- expected = [:start_document, [:value, 2], :end_document]
40
- events = events('2', subject)
41
- assert events.empty?
42
- subject.finish
43
- assert_equal expected, events
44
- end
45
-
46
- it 'parses a multiple digit integer value document' do
47
- expected = [:start_document, [:value, 12], :end_document]
48
- events = events('12', subject)
49
- assert events.empty?
50
- subject.finish
51
- assert_equal expected, events
52
- end
53
-
54
- it 'parses a zero literal document' do
55
- expected = [:start_document, [:value, 0], :end_document]
56
- events = events('0', subject)
57
- assert events.empty?
58
- subject.finish
59
- assert_equal expected, events
60
- end
61
-
62
- it 'parses a negative integer document' do
63
- expected = [:start_document, [:value, -1], :end_document]
64
- events = events('-1', subject)
65
- assert events.empty?
66
- subject.finish
67
- assert_equal expected, events
68
- end
69
-
70
- it 'parses an exponent literal document' do
71
- expected = [:start_document, [:value, 200.0], :end_document]
72
- events = events('2e2', subject)
73
- assert events.empty?
74
- subject.finish
75
- assert_equal expected, events
76
- end
77
-
78
- it 'parses a float value document' do
79
- expected = [:start_document, [:value, 12.1], :end_document]
80
- events = events('12.1', subject)
81
- assert events.empty?
82
- subject.finish
83
- assert_equal expected, events
84
- end
85
-
86
- it 'parses a value document with leading whitespace' do
87
- expected = [:start_document, [:value, false], :end_document]
88
- assert_equal expected, events(' false ')
89
- end
90
-
91
- it 'parses array documents' do
92
- expected = [:start_document, :start_array, :end_array, :end_document]
93
- assert_equal expected, events('[]')
94
- assert_equal expected, events('[ ]')
95
- assert_equal expected, events(' [] ')
96
- assert_equal expected, events(' [ ] ')
97
- end
98
-
99
- it 'parses object documents' do
100
- expected = [:start_document, :start_object, :end_object, :end_document]
101
- assert_equal expected, events('{}')
102
- assert_equal expected, events('{ }')
103
- assert_equal expected, events(' {} ')
104
- assert_equal expected, events(' { } ')
105
- end
106
-
107
- it 'rejects documents with trailing characters' do
108
- expected = [:start_document, :start_object, :end_object, :end_document, :error]
109
- assert_equal expected, events('{}a')
110
- assert_equal expected, events('{ } 12')
111
- assert_equal expected, events(' {} false')
112
- assert_equal expected, events(' { }, {}')
113
- end
114
-
115
- it 'ignores whitespace around tokens, preserves it within strings' do
116
- json = %Q{
117
- { " key 1 " : \t [
118
- 1, 2, " my string ",\r
119
- false, true, null ]
120
- }
121
- }
122
- expected = [
123
- :start_document,
124
- :start_object,
125
- [:key, " key 1 "],
126
- :start_array,
127
- [:value, 1],
128
- [:value, 2],
129
- [:value, " my string "],
130
- [:value, false],
131
- [:value, true],
132
- [:value, nil],
133
- :end_array,
134
- :end_object,
135
- :end_document
136
- ]
137
- assert_equal expected, events(json)
138
- end
139
-
140
- it 'rejects partial keyword tokens' do
141
- expected = [:start_document, :start_array, :error]
142
- assert_equal expected, events('[tru]')
143
- assert_equal expected, events('[fal]')
144
- assert_equal expected, events('[nul,true]')
145
- assert_equal expected, events('[fals1]')
146
- end
147
-
148
- it 'rejects scrambled keyword tokens' do
149
- expected = [:start_document, :start_array, :error]
150
- assert_equal expected, events('[ture]')
151
- assert_equal expected, events('[fales]')
152
- assert_equal expected, events('[nlul]')
153
- end
154
-
155
- it 'parses single keyword tokens' do
156
- expected = [:start_document, :start_array, [:value, true], :end_array, :end_document]
157
- assert_equal expected, events('[true]')
158
- end
159
-
160
- it 'parses keywords in series' do
161
- expected = [:start_document, :start_array, [:value, true], [:value, nil], :end_array, :end_document]
162
- assert_equal expected, events('[true, null]')
163
- end
164
- end
165
-
166
- describe 'finishing the parse' do
167
- it 'rejects finish with no json data provided' do
168
- -> { subject.finish }.must_raise Yajl::FFI::ParserError
169
- end
170
-
171
- it 'rejects partial null keyword' do
172
- subject << 'nul'
173
- -> { subject.finish }.must_raise Yajl::FFI::ParserError
174
- end
175
-
176
- it 'rejects partial true keyword' do
177
- subject << 'tru'
178
- -> { subject.finish }.must_raise Yajl::FFI::ParserError
179
- end
180
-
181
- it 'rejects partial false keyword' do
182
- subject << 'fals'
183
- -> { subject.finish }.must_raise Yajl::FFI::ParserError
184
- end
185
-
186
- it 'rejects partial float literal' do
187
- subject << '42.'
188
- -> { subject.finish }.must_raise Yajl::FFI::ParserError
189
- end
190
-
191
- it 'rejects partial exponent' do
192
- subject << '42e'
193
- -> { subject.finish }.must_raise Yajl::FFI::ParserError
194
- end
195
-
196
- it 'rejects malformed exponent' do
197
- subject << '42e+'
198
- -> { subject.finish }.must_raise Yajl::FFI::ParserError
199
- end
200
-
201
- it 'rejects partial negative number' do
202
- subject << '-'
203
- -> { subject.finish }.must_raise Yajl::FFI::ParserError
204
- end
205
-
206
- it 'rejects partial string literal' do
207
- subject << '"test'
208
- -> { subject.finish }.must_raise Yajl::FFI::ParserError
209
- end
210
-
211
- it 'rejects partial object ending in literal value' do
212
- subject << '{"test": 42'
213
- -> { subject.finish }.must_raise Yajl::FFI::ParserError
214
- end
215
-
216
- it 'rejects partial array ending in literal value' do
217
- subject << '[42'
218
- -> { subject.finish }.must_raise Yajl::FFI::ParserError
219
- end
220
-
221
- it 'does nothing on subsequent finish' do
222
- begin
223
- subject << 'false'
224
- subject.finish
225
- subject.finish
226
- rescue
227
- fail 'raised unexpected error'
228
- end
229
- end
230
- end
231
-
232
- describe 'parsing number tokens' do
233
- it 'rejects invalid negative numbers' do
234
- expected = [:start_document, :start_array, :error]
235
- assert_equal expected, events('[-]')
236
-
237
- expected = [:start_document, :start_array, [:value, 1], :error]
238
- assert_equal expected, events('[1-0]')
239
- end
240
-
241
- it 'parses integer zero' do
242
- expected = [:start_document, :start_array, [:value, 0], :end_array, :end_document]
243
- assert_equal expected, events('[0]')
244
- assert_equal expected, events('[-0]')
245
- end
246
-
247
- it 'parses float zero' do
248
- expected = [:start_document, :start_array, [:value, 0.0], :end_array, :end_document]
249
- assert_equal expected, events('[0.0]')
250
- assert_equal expected, events('[-0.0]')
251
- end
252
-
253
- it 'rejects multi zero' do
254
- expected = [:start_document, :start_array, [:value, 0], :error]
255
- assert_equal expected, events('[00]')
256
- assert_equal expected, events('[-00]')
257
- end
258
-
259
- it 'rejects integers that start with zero' do
260
- expected = [:start_document, :start_array, [:value, 0], :error]
261
- assert_equal expected, events('[01]')
262
- assert_equal expected, events('[-01]')
263
- end
264
-
265
- it 'parses integer tokens' do
266
- expected = [:start_document, :start_array, [:value, 1], :end_array, :end_document]
267
- assert_equal expected, events('[1]')
268
-
269
- expected = [:start_document, :start_array, [:value, -1], :end_array, :end_document]
270
- assert_equal expected, events('[-1]')
271
-
272
- expected = [:start_document, :start_array, [:value, 123], :end_array, :end_document]
273
- assert_equal expected, events('[123]')
274
-
275
- expected = [:start_document, :start_array, [:value, -123], :end_array, :end_document]
276
- assert_equal expected, events('[-123]')
277
- end
278
-
279
- it 'parses float tokens' do
280
- expected = [:start_document, :start_array, [:value, 1.0], :end_array, :end_document]
281
- assert_equal expected, events('[1.0]')
282
- assert_equal expected, events('[1.00]')
283
- end
284
-
285
- it 'parses negative floats' do
286
- expected = [:start_document, :start_array, [:value, -1.0], :end_array, :end_document]
287
- assert_equal expected, events('[-1.0]')
288
- assert_equal expected, events('[-1.00]')
289
- end
290
-
291
- it 'parses multi-digit floats' do
292
- expected = [:start_document, :start_array, [:value, 123.012], :end_array, :end_document]
293
- assert_equal expected, events('[123.012]')
294
- assert_equal expected, events('[123.0120]')
295
- end
296
-
297
- it 'parses negative multi-digit floats' do
298
- expected = [:start_document, :start_array, [:value, -123.012], :end_array, :end_document]
299
- assert_equal expected, events('[-123.012]')
300
- assert_equal expected, events('[-123.0120]')
301
- end
302
-
303
- it 'rejects floats missing leading zero' do
304
- expected = [:start_document, :start_array, :error]
305
- assert_equal expected, events('[.1]')
306
- assert_equal expected, events('[-.1]')
307
- assert_equal expected, events('[.01]')
308
- assert_equal expected, events('[-.01]')
309
- end
310
-
311
- it 'rejects float missing fraction' do
312
- expected = [:start_document, :start_array, :error]
313
- assert_equal expected, events('[.]')
314
- assert_equal expected, events('[..]')
315
- assert_equal expected, events('[0.]')
316
- assert_equal expected, events('[12.]')
317
- end
318
-
319
- it 'parses zero with implicit positive exponent as float' do
320
- expected = [:start_document, :start_array, [:value, 0.0], :end_array, :end_document]
321
- events = events('[0e2]')
322
- assert_equal expected, events
323
- assert_kind_of Float, events[2][1]
324
- end
325
-
326
- it 'parses zero with explicit positive exponent as float' do
327
- expected = [:start_document, :start_array, [:value, 0.0], :end_array, :end_document]
328
- events = events('[0e+2]')
329
- assert_equal expected, events
330
- assert_kind_of Float, events[2][1]
331
- end
332
-
333
- it 'parses zero with negative exponent as float' do
334
- expected = [:start_document, :start_array, [:value, 0.0], :end_array, :end_document]
335
- events = events('[0e-2]')
336
- assert_equal expected, events
337
- assert_kind_of Float, events[2][1]
338
- end
339
-
340
- it 'parses positive exponent integers as floats' do
341
- expected = [:start_document, :start_array, [:value, 212.0], :end_array, :end_document]
342
-
343
- events = events('[2.12e2]')
344
- assert_equal expected, events('[2.12e2]')
345
- assert_kind_of Float, events[2][1]
346
-
347
- assert_equal expected, events('[2.12e02]')
348
- assert_equal expected, events('[2.12e+2]')
349
- assert_equal expected, events('[2.12e+02]')
350
- end
351
-
352
- it 'parses positive exponent floats' do
353
- expected = [:start_document, :start_array, [:value, 21.2], :end_array, :end_document]
354
- assert_equal expected, events('[2.12e1]')
355
- assert_equal expected, events('[2.12e01]')
356
- assert_equal expected, events('[2.12e+1]')
357
- assert_equal expected, events('[2.12e+01]')
358
- end
359
-
360
- it 'parses negative exponent' do
361
- expected = [:start_document, :start_array, [:value, 0.0212], :end_array, :end_document]
362
- assert_equal expected, events('[2.12e-2]')
363
- assert_equal expected, events('[2.12e-02]')
364
- assert_equal expected, events('[2.12e-2]')
365
- assert_equal expected, events('[2.12e-02]')
366
- end
367
-
368
- it 'parses zero exponent floats' do
369
- expected = [:start_document, :start_array, [:value, 2.12], :end_array, :end_document]
370
- assert_equal expected, events('[2.12e0]')
371
- assert_equal expected, events('[2.12e00]')
372
- assert_equal expected, events('[2.12e-0]')
373
- assert_equal expected, events('[2.12e-00]')
374
- end
375
-
376
- it 'parses zero exponent integers' do
377
- expected = [:start_document, :start_array, [:value, 2.0], :end_array, :end_document]
378
- assert_equal expected, events('[2e0]')
379
- assert_equal expected, events('[2e00]')
380
- assert_equal expected, events('[2e-0]')
381
- assert_equal expected, events('[2e-00]')
382
- end
383
-
384
- it 'rejects missing exponent' do
385
- expected = [:start_document, :start_array, :error]
386
- assert_equal expected, events('[e]')
387
- assert_equal expected, events('[1e]')
388
- assert_equal expected, events('[1e-]')
389
- assert_equal expected, events('[1e--]')
390
- assert_equal expected, events('[1e+]')
391
- assert_equal expected, events('[1e++]')
392
- assert_equal expected, events('[0.e]')
393
- assert_equal expected, events('[10.e]')
394
- end
395
-
396
- it 'rejects float with trailing character' do
397
- expected = [:start_document, :start_array, [:value, 0.0], :error]
398
- assert_equal expected, events('[0.0q]')
399
- end
400
-
401
- it 'rejects integer with trailing character' do
402
- expected = [:start_document, :start_array, [:value, 1], :error]
403
- assert_equal expected, events('[1q]')
404
- end
405
- end
406
-
407
- describe 'parsing string tokens' do
408
- describe 'parsing two-character escapes' do
409
- it 'rejects invalid escape characters' do
410
- expected = [:start_document, :start_array, :error]
411
- assert_equal expected, events('["\\a"]')
412
- end
413
-
414
- it 'parses quotation mark' do
415
- expected = [:start_document, :start_array, [:value, "\""], :end_array, :end_document]
416
- assert_equal expected, events('["\""]')
417
- end
418
-
419
- it 'parses reverse solidus' do
420
- expected = [:start_document, :start_array, [:value, "\\"], :end_array, :end_document]
421
- assert_equal expected, events('["\\\"]')
422
- end
423
-
424
- it 'parses solidus' do
425
- expected = [:start_document, :start_array, [:value, "/"], :end_array, :end_document]
426
- assert_equal expected, events('["\/"]')
427
- end
428
-
429
- it 'parses backspace' do
430
- expected = [:start_document, :start_array, [:value, "\b"], :end_array, :end_document]
431
- assert_equal expected, events('["\b"]')
432
- end
433
-
434
- it 'parses form feed' do
435
- expected = [:start_document, :start_array, [:value, "\f"], :end_array, :end_document]
436
- assert_equal expected, events('["\f"]')
437
- end
438
-
439
- it 'parses line feed' do
440
- expected = [:start_document, :start_array, [:value, "\n"], :end_array, :end_document]
441
- assert_equal expected, events('["\n"]')
442
- end
443
-
444
- it 'parses carriage return' do
445
- expected = [:start_document, :start_array, [:value, "\r"], :end_array, :end_document]
446
- assert_equal expected, events('["\r"]')
447
- end
448
-
449
- it 'parses tab' do
450
- expected = [:start_document, :start_array, [:value, "\t"], :end_array, :end_document]
451
- assert_equal expected, events('["\t"]')
452
- end
453
-
454
- it 'parses a series of escapes with whitespace' do
455
- expected = [:start_document, :start_array, [:value, "\" \\ / \b \f \n \r \t"], :end_array, :end_document]
456
- assert_equal expected, events('["\" \\\ \/ \b \f \n \r \t"]')
457
- end
458
-
459
- it 'parses a series of escapes without whitespace' do
460
- expected = [:start_document, :start_array, [:value, "\"\\/\b\f\n\r\t"], :end_array, :end_document]
461
- assert_equal expected, events('["\"\\\\/\b\f\n\r\t"]')
462
- end
463
-
464
- it 'parses a series of escapes with duplicate characters between them' do
465
- expected = [:start_document, :start_array, [:value, "\"t\\b/f\bn\f/\nn\rr\t"], :end_array, :end_document]
466
- assert_equal expected, events('["\"t\\\b\/f\bn\f/\nn\rr\t"]')
467
- end
468
- end
469
-
470
- describe 'parsing control characters' do
471
- it 'rejects control character in array' do
472
- expected = [:start_document, :start_array, :error]
473
- assert_equal expected, events("[\" \u0000 \"]")
474
- end
475
-
476
- it 'rejects control character in object' do
477
- expected = [:start_document, :start_object, :error]
478
- assert_equal expected, events("{\" \u0000 \":12}")
479
- end
480
-
481
- it 'parses escaped control character' do
482
- expected = [:start_document, :start_array, [:value, "\u0000"], :end_array, :end_document]
483
- assert_equal expected, events('["\\u0000"]')
484
- end
485
-
486
- it 'parses escaped control character in object key' do
487
- expected = [:start_document, :start_object, [:key, "\u0000"], [:value, 12], :end_object, :end_document]
488
- assert_equal expected, events('{"\\u0000": 12}')
489
- end
490
-
491
- it 'parses non-control character' do
492
- # del ascii 127 is allowed unescaped in json
493
- expected = [:start_document, :start_array, [:value, " \u007F "], :end_array, :end_document]
494
- assert_equal expected, events("[\" \u007f \"]")
495
- end
496
- end
497
-
498
- describe 'parsing unicode escape sequences' do
499
- it 'parses escaped ascii character' do
500
- a = "\x61"
501
- escaped = '\u0061'
502
- expected = [:start_document, :start_array, [:value, a], :end_array, :end_document]
503
- assert_equal expected, events('["' + escaped + '"]')
504
- end
505
-
506
- it 'parses un-escaped raw unicode' do
507
- # U+1F602 face with tears of joy
508
- face = "\xf0\x9f\x98\x82"
509
- expected = [:start_document, :start_array, [:value, face], :end_array, :end_document]
510
- assert_equal expected, events('["' + face + '"]')
511
- end
512
-
513
- it 'parses escaped unicode surrogate pairs' do
514
- # U+1F602 face with tears of joy
515
- face = "\xf0\x9f\x98\x82"
516
- escaped = '\uD83D\uDE02'
517
- expected = [:start_document, :start_array, [:value, face], :end_array, :end_document]
518
- assert_equal expected, events('["' + escaped + '"]')
519
- end
520
-
521
- it 'rejects partial unicode escapes' do
522
- expected = [:start_document, :start_array, :error]
523
- assert_equal expected, events('[" \\u "]')
524
- assert_equal expected, events('[" \\u2 "]')
525
- assert_equal expected, events('[" \\u26 "]')
526
- assert_equal expected, events('[" \\u260 "]')
527
- end
528
-
529
- it 'parses unicode escapes' do
530
- # U+2603 snowman
531
- snowman = "\xe2\x98\x83"
532
- escaped = '\u2603'
533
-
534
- expected = [:start_document, :start_array, [:value, snowman], :end_array, :end_document]
535
- assert_equal expected, events('["' + escaped + '"]')
536
-
537
- expected = [:start_document, :start_array, [:value, 'snow' + snowman + ' man'], :end_array, :end_document]
538
- assert_equal expected, events('["snow' + escaped + ' man"]')
539
-
540
- expected = [:start_document, :start_array, [:value, 'snow' + snowman + '3 man'], :end_array, :end_document]
541
- assert_equal expected, events('["snow' + escaped + '3 man"]')
542
-
543
- expected = [:start_document, :start_object, [:key, 'snow' + snowman + '3 man'], [:value, 1], :end_object, :end_document]
544
- assert_equal expected, events('{"snow\\u26033 man": 1}')
545
- end
546
- end
547
-
548
- describe 'parsing unicode escapes with surrogate pairs' do
549
- it 'converts missing second pair to question mark' do
550
- expected = [:start_document, :start_array, [:value, '?'], :end_array, :end_document]
551
- assert_equal expected, events('["\uD834"]')
552
- end
553
-
554
- it 'rejects missing first pair' do
555
- expected = [:start_document, :start_array, :error]
556
- assert_equal expected, events('["\uDD1E"]')
557
- end
558
-
559
- it 'rejects double first pair' do
560
- skip 'yajl incorrectly allows this'
561
- expected = [:start_document, :start_array, :error]
562
- assert_equal expected, events('["\uD834\uD834"]')
563
- end
564
-
565
- it 'rejects double second pair' do
566
- expected = [:start_document, :start_array, :error]
567
- assert_equal expected, events('["\uDD1E\uDD1E"]')
568
- end
569
-
570
- it 'rejects reversed pair' do
571
- expected = [:start_document, :start_array, :error]
572
- assert_equal expected, events('["\uDD1E\uD834"]')
573
- end
574
-
575
- it 'parses correct pairs in object keys and values' do
576
- # U+1D11E G-Clef
577
- clef = "\xf0\x9d\x84\x9e"
578
- expected = [
579
- :start_document,
580
- :start_object,
581
- [:key, clef],
582
- [:value, "g\u{1D11E}clef"],
583
- :end_object,
584
- :end_document
585
- ]
586
- assert_equal expected, events(%q{ {"\uD834\uDD1E": "g\uD834\uDD1Eclef"} })
587
- end
588
- end
589
- end
590
-
591
- describe 'parsing arrays' do
592
- it 'rejects trailing comma' do
593
- expected = [:start_document, :start_array, [:value, 12], :error]
594
- assert_equal expected, events('[12, ]')
595
- end
596
-
597
- it 'parses nested empty array' do
598
- expected = [:start_document, :start_array, :start_array, :end_array, :end_array, :end_document]
599
- assert_equal expected, events('[[]]')
600
- end
601
-
602
- it 'parses nested array with value' do
603
- expected = [:start_document, :start_array, :start_array, [:value, 2.1], :end_array, :end_array, :end_document]
604
- assert_equal expected, events('[[ 2.10 ]]')
605
- end
606
-
607
- it 'rejects malformed arrays' do
608
- expected = [:start_document, :start_array, :error]
609
- assert_equal expected, events('[}')
610
- assert_equal expected, events('[,]')
611
- assert_equal expected, events('[, 12]')
612
- end
613
-
614
- it 'rejects malformed nested arrays' do
615
- expected = [:start_document, :start_array, :start_array, :error]
616
- assert_equal(expected, events('[[}]'))
617
- assert_equal expected, events('[[}]')
618
- assert_equal expected, events('[[,]]')
619
- end
620
-
621
- it 'rejects malformed array value lists' do
622
- expected = [:start_document, :start_array, [:value, "test"], :error]
623
- assert_equal expected, events('["test"}')
624
- assert_equal expected, events('["test",]')
625
- assert_equal expected, events('["test" "test"]')
626
- assert_equal expected, events('["test" 12]')
627
- end
628
-
629
- it 'parses array with value' do
630
- expected = [:start_document, :start_array, [:value, "test"], :end_array, :end_document]
631
- assert_equal expected, events('["test"]')
632
- end
633
-
634
- it 'parses array with value list' do
635
- expected = [
636
- :start_document,
637
- :start_array,
638
- [:value, 1],
639
- [:value, 2],
640
- [:value, nil],
641
- [:value, 12.1],
642
- [:value, "test"],
643
- :end_array,
644
- :end_document
645
- ]
646
- assert_equal expected, events('[1,2, null, 12.1,"test"]')
647
- end
648
- end
649
-
650
- describe 'parsing objects' do
651
- it 'rejects malformed objects' do
652
- expected = [:start_document, :start_object, :error]
653
- assert_equal expected, events('{]')
654
- assert_equal expected, events('{:}')
655
- end
656
-
657
- it 'parses single key object' do
658
- expected = [:start_document, :start_object, [:key, "key 1"], [:value, 12], :end_object, :end_document]
659
- assert_equal expected, events('{"key 1" : 12}')
660
- end
661
-
662
- it 'parses object key value list' do
663
- expected = [
664
- :start_document,
665
- :start_object,
666
- [:key, "key 1"], [:value, 12],
667
- [:key, "key 2"], [:value, "two"],
668
- :end_object,
669
- :end_document
670
- ]
671
- assert_equal expected, events('{"key 1" : 12, "key 2":"two"}')
672
- end
673
-
674
- it 'rejects object key with no value' do
675
- expected = [
676
- :start_document,
677
- :start_object,
678
- [:key, "key"],
679
- :start_array,
680
- [:value, nil],
681
- [:value, false],
682
- [:value, true],
683
- :end_array,
684
- [:key, "key 2"],
685
- :error
686
- ]
687
- assert_equal expected, events('{"key": [ null , false , true ] ,"key 2"}')
688
- end
689
-
690
- it 'rejects object with trailing comma' do
691
- expected = [:start_document, :start_object, [:key, "key 1"], [:value, 12], :error]
692
- assert_equal expected, events('{"key 1" : 12,}')
693
- end
694
- end
695
-
696
- describe 'parsing unicode bytes' do
697
- it 'parses single byte utf-8' do
698
- expected = [:start_document, :start_array, [:value, "test"], :end_array, :end_document]
699
- assert_equal expected, events('["test"]')
700
- end
701
-
702
- it 'parses full two byte utf-8' do
703
- expected = [
704
- :start_document,
705
- :start_array,
706
- [:value, "résumé"],
707
- [:value, "éé"],
708
- :end_array,
709
- :end_document
710
- ]
711
- assert_equal expected, events("[\"résumé\", \"é\xC3\xA9\"]")
712
- end
713
-
714
- # Parser should throw an error when only one byte of a two byte character
715
- # is available. The \xC3 byte is the first byte of the é character.
716
- it 'rejects a partial two byte utf-8 string' do
717
- expected = [:start_document, :start_array, :error]
718
- assert_equal expected, events("[\"\xC3\"]")
719
- end
720
-
721
- it 'parses valid two byte utf-8 string' do
722
- expected = [:start_document, :start_array, [:value, 'é'], :end_array, :end_document]
723
- assert_equal expected, events("[\"\xC3\xA9\"]")
724
- end
725
-
726
- it 'parses full three byte utf-8 string' do
727
- expected = [
728
- :start_document,
729
- :start_array,
730
- [:value, "snow\u2603man"],
731
- [:value, "\u2603\u2603"],
732
- :end_array,
733
- :end_document
734
- ]
735
- assert_equal expected, events("[\"snow\u2603man\", \"\u2603\u2603\"]")
736
- end
737
-
738
- it 'rejects one byte of three byte utf-8 string' do
739
- expected = [:start_document, :start_array, :error]
740
- assert_equal expected, events("[\"\xE2\"]")
741
- end
742
-
743
- it 'rejects two bytes of three byte utf-8 string' do
744
- expected = [:start_document, :start_array, :error]
745
- assert_equal expected, events("[\"\xE2\x98\"]")
746
- end
747
-
748
- it 'parses full three byte utf-8 string' do
749
- expected = [:start_document, :start_array, [:value, "\u2603"], :end_array, :end_document]
750
- assert_equal expected, events("[\"\xE2\x98\x83\"]")
751
- end
752
-
753
- it 'parses full four byte utf-8 string' do
754
- expected = [
755
- :start_document,
756
- :start_array,
757
- [:value, "\u{10102} check mark"],
758
- :end_array,
759
- :end_document
760
- ]
761
- assert_equal expected, events("[\"\u{10102} check mark\"]")
762
- end
763
-
764
- it 'rejects one byte of four byte utf-8 string' do
765
- expected = [:start_document, :start_array, :error]
766
- assert_equal expected, events("[\"\xF0\"]")
767
- end
768
-
769
- it 'rejects two bytes of four byte utf-8 string' do
770
- expected = [:start_document, :start_array, :error]
771
- assert_equal expected, events("[\"\xF0\x90\"]")
772
- end
773
-
774
- it 'rejects three bytes of four byte utf-8 string' do
775
- expected = [:start_document, :start_array, :error]
776
- assert_equal expected, events("[\"\xF0\x90\x84\"]")
777
- end
778
-
779
- it 'parses full four byte utf-8 string' do
780
- expected = [:start_document, :start_array, [:value, "\u{10102}"], :end_array, :end_document]
781
- assert_equal expected, events("[\"\xF0\x90\x84\x82\"]")
782
- end
783
- end
784
-
785
- describe 'parsing json text from the module' do
786
- it 'parses an array document' do
787
- result = Yajl::FFI::Parser.parse('[1,2,3]')
788
- assert_equal [1, 2, 3], result
789
- end
790
-
791
- it 'parses a true keyword literal document' do
792
- result = Yajl::FFI::Parser.parse('true')
793
- assert_equal true, result
794
- end
795
-
796
- it 'parses a false keyword literal document' do
797
- result = Yajl::FFI::Parser.parse('false')
798
- assert_equal false, result
799
- end
800
-
801
- it 'parses a null keyword literal document' do
802
- result = Yajl::FFI::Parser.parse('null')
803
- assert_equal nil, result
804
- end
805
-
806
- it 'parses a string literal document' do
807
- result = Yajl::FFI::Parser.parse('"hello"')
808
- assert_equal 'hello', result
809
- end
810
-
811
- it 'parses an integer literal document' do
812
- result = Yajl::FFI::Parser.parse('42')
813
- assert_equal 42, result
814
- end
815
-
816
- it 'parses a float literal document' do
817
- result = Yajl::FFI::Parser.parse('42.12')
818
- assert_equal 42.12, result
819
- end
820
-
821
- it 'rejects a partial float literal document' do
822
- assert_raises(Yajl::FFI::ParserError) do
823
- Yajl::FFI::Parser.parse('42.')
824
- end
825
- end
826
-
827
- it 'rejects a partial document' do
828
- assert_raises(Yajl::FFI::ParserError) do
829
- Yajl::FFI::Parser.parse('{')
830
- end
831
- end
832
-
833
- it 'rejects an empty document' do
834
- assert_raises(Yajl::FFI::ParserError) do
835
- Yajl::FFI::Parser.parse('')
836
- end
837
- end
838
- end
839
-
840
- it 'registers observers in initializer block' do
841
- events = []
842
- parser = Yajl::FFI::Parser.new do
843
- start_document { events << :start_document }
844
- end_document { events << :end_document }
845
- start_object { events << :start_object }
846
- end_object { events << :end_object }
847
- key {|k| events << [:key, k] }
848
- value {|v| events << [:value, v] }
849
- end
850
- parser << '{"key":12}'
851
- expected = [:start_document, :start_object, [:key, "key"], [:value, 12], :end_object, :end_document]
852
- assert_equal expected, events
853
- end
854
-
855
- private
856
-
857
- # Run a worst case, one byte at a time, parse against the JSON string and
858
- # return a list of events generated by the parser. A special :error event is
859
- # included if the parser threw an exception.
860
- #
861
- # json - The String to parse.
862
- # parser - The optional Parser instance to use.
863
- #
864
- # Returns an Events instance.
865
- def events(json, parser = nil)
866
- parser ||= Yajl::FFI::Parser.new
867
- collector = Events.new(parser)
868
- begin
869
- json.each_byte {|byte| parser << [byte].pack('C') }
870
- rescue Yajl::FFI::ParserError
871
- collector.error
872
- end
873
- collector.events
874
- end
875
-
876
- # Dynamically map methods in this class to parser callback methods
877
- # so we can collect parser events for inspection by test cases.
878
- class Events
879
- METHODS = %w[start_document end_document start_object end_object start_array end_array key value]
880
-
881
- attr_reader :events
882
-
883
- def initialize(parser)
884
- @events = []
885
- METHODS.each do |name|
886
- parser.send(name, &method(name))
887
- end
888
- end
889
-
890
- METHODS.each do |name|
891
- define_method(name) do |*args|
892
- @events << (args.empty? ? name.to_sym : [name.to_sym, *args])
893
- end
894
- end
895
-
896
- def error
897
- @events << :error
898
- end
899
- end
900
- end