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