json 1.8.3 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.travis.yml +9 -12
  4. data/{CHANGES → CHANGES.md} +219 -90
  5. data/Gemfile +10 -6
  6. data/{COPYING-json-jruby → LICENSE} +5 -6
  7. data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
  8. data/{README.rdoc → README.md} +201 -134
  9. data/Rakefile +35 -113
  10. data/VERSION +1 -1
  11. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  12. data/ext/json/ext/generator/generator.c +255 -101
  13. data/ext/json/ext/generator/generator.h +12 -4
  14. data/ext/json/ext/parser/extconf.rb +28 -0
  15. data/ext/json/ext/parser/parser.c +410 -462
  16. data/ext/json/ext/parser/parser.h +5 -5
  17. data/ext/json/ext/parser/parser.rl +166 -181
  18. data/ext/json/extconf.rb +1 -1
  19. data/java/src/json/ext/ByteListTranscoder.java +1 -2
  20. data/java/src/json/ext/Generator.java +39 -36
  21. data/java/src/json/ext/GeneratorMethods.java +1 -2
  22. data/java/src/json/ext/GeneratorService.java +1 -2
  23. data/java/src/json/ext/GeneratorState.java +33 -56
  24. data/java/src/json/ext/OptionsReader.java +2 -3
  25. data/java/src/json/ext/Parser.java +146 -417
  26. data/java/src/json/ext/Parser.rl +62 -126
  27. data/java/src/json/ext/ParserService.java +1 -2
  28. data/java/src/json/ext/RuntimeInfo.java +1 -6
  29. data/java/src/json/ext/StringDecoder.java +1 -2
  30. data/java/src/json/ext/StringEncoder.java +13 -2
  31. data/java/src/json/ext/Utils.java +1 -2
  32. data/json-java.gemspec +22 -7
  33. data/json.gemspec +0 -0
  34. data/json_pure.gemspec +22 -29
  35. data/lib/json/add/bigdecimal.rb +3 -2
  36. data/lib/json/add/complex.rb +4 -4
  37. data/lib/json/add/core.rb +1 -0
  38. data/lib/json/add/date.rb +1 -1
  39. data/lib/json/add/date_time.rb +1 -1
  40. data/lib/json/add/exception.rb +1 -1
  41. data/lib/json/add/ostruct.rb +3 -3
  42. data/lib/json/add/range.rb +1 -1
  43. data/lib/json/add/rational.rb +3 -3
  44. data/lib/json/add/regexp.rb +3 -3
  45. data/lib/json/add/set.rb +29 -0
  46. data/lib/json/add/struct.rb +1 -1
  47. data/lib/json/add/symbol.rb +1 -1
  48. data/lib/json/add/time.rb +1 -1
  49. data/lib/json/common.rb +350 -152
  50. data/lib/json/ext.rb +0 -6
  51. data/lib/json/generic_object.rb +5 -4
  52. data/lib/json/pure/generator.rb +83 -126
  53. data/lib/json/pure/parser.rb +62 -84
  54. data/lib/json/pure.rb +2 -8
  55. data/lib/json/version.rb +2 -1
  56. data/lib/json.rb +550 -29
  57. data/references/rfc7159.txt +899 -0
  58. data/tests/fixtures/obsolete_fail1.json +1 -0
  59. data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
  60. data/tests/json_common_interface_test.rb +169 -0
  61. data/tests/json_encoding_test.rb +107 -0
  62. data/tests/json_ext_parser_test.rb +15 -0
  63. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +13 -8
  64. data/tests/{test_json_generate.rb → json_generator_test.rb} +134 -39
  65. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  66. data/tests/json_parser_test.rb +497 -0
  67. data/tests/json_string_matching_test.rb +38 -0
  68. data/tests/test_helper.rb +17 -0
  69. data/tools/diff.sh +18 -0
  70. data/tools/fuzz.rb +1 -9
  71. metadata +47 -53
  72. data/COPYING +0 -58
  73. data/GPL +0 -340
  74. data/TODO +0 -1
  75. data/data/example.json +0 -1
  76. data/data/index.html +0 -38
  77. data/data/prototype.js +0 -4184
  78. data/tests/fixtures/fail1.json +0 -1
  79. data/tests/setup_variant.rb +0 -11
  80. data/tests/test_json.rb +0 -553
  81. data/tests/test_json_encoding.rb +0 -65
  82. data/tests/test_json_string_matching.rb +0 -39
  83. data/tests/test_json_unicode.rb +0 -72
@@ -0,0 +1,497 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: false
3
+ require 'test_helper'
4
+ require 'stringio'
5
+ require 'tempfile'
6
+ require 'ostruct'
7
+ require 'bigdecimal'
8
+
9
+ class JSONParserTest < Test::Unit::TestCase
10
+ include JSON
11
+
12
+ def test_construction
13
+ parser = JSON::Parser.new('test')
14
+ assert_equal 'test', parser.source
15
+ end
16
+
17
+ def test_argument_encoding
18
+ source = "{}".encode("UTF-16")
19
+ JSON::Parser.new(source)
20
+ assert_equal Encoding::UTF_16, source.encoding
21
+ end if defined?(Encoding::UTF_16)
22
+
23
+ def test_error_message_encoding
24
+ bug10705 = '[ruby-core:67386] [Bug #10705]'
25
+ json = ".\"\xE2\x88\x9A\"".force_encoding(Encoding::UTF_8)
26
+ e = assert_raise(JSON::ParserError) {
27
+ JSON::Ext::Parser.new(json).parse
28
+ }
29
+ assert_equal(Encoding::UTF_8, e.message.encoding, bug10705)
30
+ assert_include(e.message, json, bug10705)
31
+ end if defined?(Encoding::UTF_8) and defined?(JSON::Ext::Parser)
32
+
33
+ def test_parsing
34
+ parser = JSON::Parser.new('"test"')
35
+ assert_equal 'test', parser.parse
36
+ end
37
+
38
+ def test_parser_reset
39
+ parser = Parser.new('{"a":"b"}')
40
+ assert_equal({ 'a' => 'b' }, parser.parse)
41
+ assert_equal({ 'a' => 'b' }, parser.parse)
42
+ end
43
+
44
+ def test_parse_values
45
+ assert_equal(nil, parse('null'))
46
+ assert_equal(false, parse('false'))
47
+ assert_equal(true, parse('true'))
48
+ assert_equal(-23, parse('-23'))
49
+ assert_equal(23, parse('23'))
50
+ assert_in_delta(0.23, parse('0.23'), 1e-2)
51
+ assert_in_delta(0.0, parse('0e0'), 1e-2)
52
+ assert_equal("", parse('""'))
53
+ assert_equal("foobar", parse('"foobar"'))
54
+ end
55
+
56
+ def test_parse_simple_arrays
57
+ assert_equal([], parse('[]'))
58
+ assert_equal([], parse(' [ ] '))
59
+ assert_equal([ nil ], parse('[null]'))
60
+ assert_equal([ false ], parse('[false]'))
61
+ assert_equal([ true ], parse('[true]'))
62
+ assert_equal([ -23 ], parse('[-23]'))
63
+ assert_equal([ 23 ], parse('[23]'))
64
+ assert_equal_float([ 0.23 ], parse('[0.23]'))
65
+ assert_equal_float([ 0.0 ], parse('[0e0]'))
66
+ assert_equal([""], parse('[""]'))
67
+ assert_equal(["foobar"], parse('["foobar"]'))
68
+ assert_equal([{}], parse('[{}]'))
69
+ end
70
+
71
+ def test_parse_simple_objects
72
+ assert_equal({}, parse('{}'))
73
+ assert_equal({}, parse(' { } '))
74
+ assert_equal({ "a" => nil }, parse('{ "a" : null}'))
75
+ assert_equal({ "a" => nil }, parse('{"a":null}'))
76
+ assert_equal({ "a" => false }, parse('{ "a" : false } '))
77
+ assert_equal({ "a" => false }, parse('{"a":false}'))
78
+ assert_raise(JSON::ParserError) { parse('{false}') }
79
+ assert_equal({ "a" => true }, parse('{"a":true}'))
80
+ assert_equal({ "a" => true }, parse(' { "a" : true } '))
81
+ assert_equal({ "a" => -23 }, parse(' { "a" : -23 } '))
82
+ assert_equal({ "a" => -23 }, parse(' { "a" : -23 } '))
83
+ assert_equal({ "a" => 23 }, parse('{"a":23 } '))
84
+ assert_equal({ "a" => 23 }, parse(' { "a" : 23 } '))
85
+ assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
86
+ assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
87
+ end
88
+
89
+ def test_parse_numbers
90
+ assert_raise(JSON::ParserError) { parse('+23.2') }
91
+ assert_raise(JSON::ParserError) { parse('+23') }
92
+ assert_raise(JSON::ParserError) { parse('.23') }
93
+ assert_raise(JSON::ParserError) { parse('023') }
94
+ assert_equal(23, parse('23'))
95
+ assert_equal(-23, parse('-23'))
96
+ assert_equal_float(3.141, parse('3.141'))
97
+ assert_equal_float(-3.141, parse('-3.141'))
98
+ assert_equal_float(3.141, parse('3141e-3'))
99
+ assert_equal_float(3.141, parse('3141.1e-3'))
100
+ assert_equal_float(3.141, parse('3141E-3'))
101
+ assert_equal_float(3.141, parse('3141.0E-3'))
102
+ assert_equal_float(-3.141, parse('-3141.0e-3'))
103
+ assert_equal_float(-3.141, parse('-3141e-3'))
104
+ assert_raise(ParserError) { parse('NaN') }
105
+ assert parse('NaN', :allow_nan => true).nan?
106
+ assert_raise(ParserError) { parse('Infinity') }
107
+ assert_equal(1.0/0, parse('Infinity', :allow_nan => true))
108
+ assert_raise(ParserError) { parse('-Infinity') }
109
+ assert_equal(-1.0/0, parse('-Infinity', :allow_nan => true))
110
+ end
111
+
112
+ def test_parse_bigdecimals
113
+ assert_equal(BigDecimal, JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"].class)
114
+ assert_equal(BigDecimal("0.901234567890123456789E1"),JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"] )
115
+ end
116
+
117
+ if Array.method_defined?(:permutation)
118
+ def test_parse_more_complex_arrays
119
+ a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
120
+ a.permutation.each do |perm|
121
+ json = pretty_generate(perm)
122
+ assert_equal perm, parse(json)
123
+ end
124
+ end
125
+
126
+ def test_parse_complex_objects
127
+ a = [ nil, false, true, "foßbar", [ "n€st€d", true ], { "nested" => true, "n€ßt€ð2" => {} }]
128
+ a.permutation.each do |perm|
129
+ s = "a"
130
+ orig_obj = perm.inject({}) { |h, x| h[s.dup] = x; s = s.succ; h }
131
+ json = pretty_generate(orig_obj)
132
+ assert_equal orig_obj, parse(json)
133
+ end
134
+ end
135
+ end
136
+
137
+ def test_parse_arrays
138
+ assert_equal([1,2,3], parse('[1,2,3]'))
139
+ assert_equal([1.2,2,3], parse('[1.2,2,3]'))
140
+ assert_equal([[],[[],[]]], parse('[[],[[],[]]]'))
141
+ assert_equal([], parse('[]'))
142
+ assert_equal([], parse(' [ ] '))
143
+ assert_equal([1], parse('[1]'))
144
+ assert_equal([1], parse(' [ 1 ] '))
145
+ ary = [[1], ["foo"], [3.14], [4711.0], [2.718], [nil],
146
+ [[1, -2, 3]], [false], [true]]
147
+ assert_equal(ary,
148
+ parse('[[1],["foo"],[3.14],[47.11e+2],[2718.0E-3],[null],[[1,-2,3]],[false],[true]]'))
149
+ assert_equal(ary, parse(%Q{ [ [1] , ["foo"] , [3.14] \t , [47.11e+2]\s
150
+ , [2718.0E-3 ],\r[ null] , [[1, -2, 3 ]], [false ],[ true]\n ] }))
151
+ end
152
+
153
+ def test_parse_json_primitive_values
154
+ assert_raise(JSON::ParserError) { parse('') }
155
+ assert_raise(TypeError) { parse(nil) }
156
+ assert_raise(JSON::ParserError) { parse(' /* foo */ ') }
157
+ assert_equal nil, parse('null')
158
+ assert_equal false, parse('false')
159
+ assert_equal true, parse('true')
160
+ assert_equal 23, parse('23')
161
+ assert_equal 1, parse('1')
162
+ assert_equal_float 3.141, parse('3.141'), 1E-3
163
+ assert_equal 2 ** 64, parse('18446744073709551616')
164
+ assert_equal 'foo', parse('"foo"')
165
+ assert parse('NaN', :allow_nan => true).nan?
166
+ assert parse('Infinity', :allow_nan => true).infinite?
167
+ assert parse('-Infinity', :allow_nan => true).infinite?
168
+ assert_raise(JSON::ParserError) { parse('[ 1, ]') }
169
+ end
170
+
171
+ def test_parse_some_strings
172
+ assert_equal([""], parse('[""]'))
173
+ assert_equal(["\\"], parse('["\\\\"]'))
174
+ assert_equal(['"'], parse('["\""]'))
175
+ assert_equal(['\\"\\'], parse('["\\\\\\"\\\\"]'))
176
+ assert_equal(
177
+ ["\"\b\n\r\t\0\037"],
178
+ parse('["\"\b\n\r\t\u0000\u001f"]')
179
+ )
180
+ end
181
+
182
+ def test_parse_big_integers
183
+ json1 = JSON(orig = (1 << 31) - 1)
184
+ assert_equal orig, parse(json1)
185
+ json2 = JSON(orig = 1 << 31)
186
+ assert_equal orig, parse(json2)
187
+ json3 = JSON(orig = (1 << 62) - 1)
188
+ assert_equal orig, parse(json3)
189
+ json4 = JSON(orig = 1 << 62)
190
+ assert_equal orig, parse(json4)
191
+ json5 = JSON(orig = 1 << 64)
192
+ assert_equal orig, parse(json5)
193
+ end
194
+
195
+ def test_some_wrong_inputs
196
+ assert_raise(ParserError) { parse('[] bla') }
197
+ assert_raise(ParserError) { parse('[] 1') }
198
+ assert_raise(ParserError) { parse('[] []') }
199
+ assert_raise(ParserError) { parse('[] {}') }
200
+ assert_raise(ParserError) { parse('{} []') }
201
+ assert_raise(ParserError) { parse('{} {}') }
202
+ assert_raise(ParserError) { parse('[NULL]') }
203
+ assert_raise(ParserError) { parse('[FALSE]') }
204
+ assert_raise(ParserError) { parse('[TRUE]') }
205
+ assert_raise(ParserError) { parse('[07] ') }
206
+ assert_raise(ParserError) { parse('[0a]') }
207
+ assert_raise(ParserError) { parse('[1.]') }
208
+ assert_raise(ParserError) { parse(' ') }
209
+ end
210
+
211
+ def test_symbolize_names
212
+ assert_equal({ "foo" => "bar", "baz" => "quux" },
213
+ parse('{"foo":"bar", "baz":"quux"}'))
214
+ assert_equal({ :foo => "bar", :baz => "quux" },
215
+ parse('{"foo":"bar", "baz":"quux"}', :symbolize_names => true))
216
+ assert_raise(ArgumentError) do
217
+ parse('{}', :symbolize_names => true, :create_additions => true)
218
+ end
219
+ end
220
+
221
+ def test_freeze
222
+ assert_predicate parse('{}', :freeze => true), :frozen?
223
+ assert_predicate parse('[]', :freeze => true), :frozen?
224
+ assert_predicate parse('"foo"', :freeze => true), :frozen?
225
+
226
+ if string_deduplication_available?
227
+ assert_same(-'foo', parse('"foo"', :freeze => true))
228
+ assert_same(-'foo', parse('{"foo": 1}', :freeze => true).keys.first)
229
+ end
230
+ end
231
+
232
+ def test_parse_comments
233
+ json = <<EOT
234
+ {
235
+ "key1":"value1", // eol comment
236
+ "key2":"value2" /* multi line
237
+ * comment */,
238
+ "key3":"value3" /* multi line
239
+ // nested eol comment
240
+ * comment */
241
+ }
242
+ EOT
243
+ assert_equal(
244
+ { "key1" => "value1", "key2" => "value2", "key3" => "value3" },
245
+ parse(json))
246
+ json = <<EOT
247
+ {
248
+ "key1":"value1" /* multi line
249
+ // nested eol comment
250
+ /* illegal nested multi line comment */
251
+ * comment */
252
+ }
253
+ EOT
254
+ assert_raise(ParserError) { parse(json) }
255
+ json = <<EOT
256
+ {
257
+ "key1":"value1" /* multi line
258
+ // nested eol comment
259
+ closed multi comment */
260
+ and again, throw an Error */
261
+ }
262
+ EOT
263
+ assert_raise(ParserError) { parse(json) }
264
+ json = <<EOT
265
+ {
266
+ "key1":"value1" /*/*/
267
+ }
268
+ EOT
269
+ assert_equal({ "key1" => "value1" }, parse(json))
270
+ end
271
+
272
+ def test_nesting
273
+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
274
+ too_deep_ary = eval too_deep
275
+ assert_raise(JSON::NestingError) { parse too_deep }
276
+ assert_raise(JSON::NestingError) { parse too_deep, :max_nesting => 100 }
277
+ ok = parse too_deep, :max_nesting => 101
278
+ assert_equal too_deep_ary, ok
279
+ ok = parse too_deep, :max_nesting => nil
280
+ assert_equal too_deep_ary, ok
281
+ ok = parse too_deep, :max_nesting => false
282
+ assert_equal too_deep_ary, ok
283
+ ok = parse too_deep, :max_nesting => 0
284
+ assert_equal too_deep_ary, ok
285
+ end
286
+
287
+ def test_backslash
288
+ data = [ '\\.(?i:gif|jpe?g|png)$' ]
289
+ json = '["\\\\.(?i:gif|jpe?g|png)$"]'
290
+ assert_equal data, parse(json)
291
+ #
292
+ data = [ '\\"' ]
293
+ json = '["\\\\\""]'
294
+ assert_equal data, parse(json)
295
+ #
296
+ json = '["/"]'
297
+ data = [ '/' ]
298
+ assert_equal data, parse(json)
299
+ #
300
+ json = '["\""]'
301
+ data = ['"']
302
+ assert_equal data, parse(json)
303
+ #
304
+ json = '["\\\'"]'
305
+ data = ["'"]
306
+ assert_equal data, parse(json)
307
+
308
+ json = '["\/"]'
309
+ data = [ '/' ]
310
+ assert_equal data, parse(json)
311
+ end
312
+
313
+ class SubArray < Array
314
+ def <<(v)
315
+ @shifted = true
316
+ super
317
+ end
318
+
319
+ def shifted?
320
+ @shifted
321
+ end
322
+ end
323
+
324
+ class SubArray2 < Array
325
+ def to_json(*a)
326
+ {
327
+ JSON.create_id => self.class.name,
328
+ 'ary' => to_a,
329
+ }.to_json(*a)
330
+ end
331
+
332
+ def self.json_create(o)
333
+ o.delete JSON.create_id
334
+ o['ary']
335
+ end
336
+ end
337
+
338
+ class SubArrayWrapper
339
+ def initialize
340
+ @data = []
341
+ end
342
+
343
+ attr_reader :data
344
+
345
+ def [](index)
346
+ @data[index]
347
+ end
348
+
349
+ def <<(value)
350
+ @data << value
351
+ @shifted = true
352
+ end
353
+
354
+ def shifted?
355
+ @shifted
356
+ end
357
+ end
358
+
359
+ def test_parse_array_custom_array_derived_class
360
+ res = parse('[1,2]', :array_class => SubArray)
361
+ assert_equal([1,2], res)
362
+ assert_equal(SubArray, res.class)
363
+ assert res.shifted?
364
+ end
365
+
366
+ def test_parse_array_custom_non_array_derived_class
367
+ res = parse('[1,2]', :array_class => SubArrayWrapper)
368
+ assert_equal([1,2], res.data)
369
+ assert_equal(SubArrayWrapper, res.class)
370
+ assert res.shifted?
371
+ end
372
+
373
+ def test_parse_object
374
+ assert_equal({}, parse('{}'))
375
+ assert_equal({}, parse(' { } '))
376
+ assert_equal({'foo'=>'bar'}, parse('{"foo":"bar"}'))
377
+ assert_equal({'foo'=>'bar'}, parse(' { "foo" : "bar" } '))
378
+ end
379
+
380
+ class SubHash < Hash
381
+ def []=(k, v)
382
+ @item_set = true
383
+ super
384
+ end
385
+
386
+ def item_set?
387
+ @item_set
388
+ end
389
+ end
390
+
391
+ class SubHash2 < Hash
392
+ def to_json(*a)
393
+ {
394
+ JSON.create_id => self.class.name,
395
+ }.merge(self).to_json(*a)
396
+ end
397
+
398
+ def self.json_create(o)
399
+ o.delete JSON.create_id
400
+ self[o]
401
+ end
402
+ end
403
+
404
+ class SubOpenStruct < OpenStruct
405
+ def [](k)
406
+ __send__(k)
407
+ end
408
+
409
+ def []=(k, v)
410
+ @item_set = true
411
+ __send__("#{k}=", v)
412
+ end
413
+
414
+ def item_set?
415
+ @item_set
416
+ end
417
+ end
418
+
419
+ def test_parse_object_custom_hash_derived_class
420
+ res = parse('{"foo":"bar"}', :object_class => SubHash)
421
+ assert_equal({"foo" => "bar"}, res)
422
+ assert_equal(SubHash, res.class)
423
+ assert res.item_set?
424
+ end
425
+
426
+ def test_parse_object_custom_non_hash_derived_class
427
+ res = parse('{"foo":"bar"}', :object_class => SubOpenStruct)
428
+ assert_equal "bar", res.foo
429
+ assert_equal(SubOpenStruct, res.class)
430
+ assert res.item_set?
431
+ end
432
+
433
+ def test_parse_generic_object
434
+ res = parse(
435
+ '{"foo":"bar", "baz":{}}',
436
+ :object_class => JSON::GenericObject
437
+ )
438
+ assert_equal(JSON::GenericObject, res.class)
439
+ assert_equal "bar", res.foo
440
+ assert_equal "bar", res["foo"]
441
+ assert_equal "bar", res[:foo]
442
+ assert_equal "bar", res.to_hash[:foo]
443
+ assert_equal(JSON::GenericObject, res.baz.class)
444
+ end
445
+
446
+ def test_generate_core_subclasses_with_new_to_json
447
+ obj = SubHash2["foo" => SubHash2["bar" => true]]
448
+ obj_json = JSON(obj)
449
+ obj_again = parse(obj_json, :create_additions => true)
450
+ assert_kind_of SubHash2, obj_again
451
+ assert_kind_of SubHash2, obj_again['foo']
452
+ assert obj_again['foo']['bar']
453
+ assert_equal obj, obj_again
454
+ assert_equal ["foo"],
455
+ JSON(JSON(SubArray2["foo"]), :create_additions => true)
456
+ end
457
+
458
+ def test_generate_core_subclasses_with_default_to_json
459
+ assert_equal '{"foo":"bar"}', JSON(SubHash["foo" => "bar"])
460
+ assert_equal '["foo"]', JSON(SubArray["foo"])
461
+ end
462
+
463
+ def test_generate_of_core_subclasses
464
+ obj = SubHash["foo" => SubHash["bar" => true]]
465
+ obj_json = JSON(obj)
466
+ obj_again = JSON(obj_json)
467
+ assert_kind_of Hash, obj_again
468
+ assert_kind_of Hash, obj_again['foo']
469
+ assert obj_again['foo']['bar']
470
+ assert_equal obj, obj_again
471
+ end
472
+
473
+ def test_parsing_frozen_ascii8bit_string
474
+ assert_equal(
475
+ { 'foo' => 'bar' },
476
+ JSON('{ "foo": "bar" }'.force_encoding(Encoding::ASCII_8BIT).freeze)
477
+ )
478
+ end
479
+
480
+ private
481
+
482
+ def string_deduplication_available?
483
+ r1 = rand.to_s
484
+ r2 = r1.dup
485
+ begin
486
+ (-r1).equal?(-r2)
487
+ rescue NoMethodError
488
+ false # No String#-@
489
+ end
490
+ end
491
+
492
+ def assert_equal_float(expected, actual, delta = 1e-2)
493
+ Array === expected and expected = expected.first
494
+ Array === actual and actual = actual.first
495
+ assert_in_delta(expected, actual, delta)
496
+ end
497
+ end
@@ -0,0 +1,38 @@
1
+ #frozen_string_literal: false
2
+ require 'test_helper'
3
+ require 'time'
4
+
5
+ class JSONStringMatchingTest < Test::Unit::TestCase
6
+ include JSON
7
+
8
+ class TestTime < ::Time
9
+ def self.json_create(string)
10
+ Time.parse(string)
11
+ end
12
+
13
+ def to_json(*)
14
+ %{"#{strftime('%FT%T%z')}"}
15
+ end
16
+
17
+ def ==(other)
18
+ to_i == other.to_i
19
+ end
20
+ end
21
+
22
+ def test_match_date
23
+ t = TestTime.new
24
+ t_json = [ t ].to_json
25
+ time_regexp = /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4}\z/
26
+ assert_equal [ t ],
27
+ parse(
28
+ t_json,
29
+ :create_additions => true,
30
+ :match_string => { time_regexp => TestTime }
31
+ )
32
+ assert_equal [ t.strftime('%FT%T%z') ],
33
+ parse(
34
+ t_json,
35
+ :match_string => { time_regexp => TestTime }
36
+ )
37
+ end
38
+ end
@@ -0,0 +1,17 @@
1
+ case ENV['JSON']
2
+ when 'pure'
3
+ $:.unshift File.join(__dir__, '../lib')
4
+ require 'json/pure'
5
+ when 'ext'
6
+ $:.unshift File.join(__dir__, '../ext'), File.join(__dir__, '../lib')
7
+ require 'json/ext'
8
+ else
9
+ $:.unshift File.join(__dir__, '../ext'), File.join(__dir__, '../lib')
10
+ require 'json'
11
+ end
12
+
13
+ require 'test/unit'
14
+ begin
15
+ require 'byebug'
16
+ rescue LoadError
17
+ end
data/tools/diff.sh ADDED
@@ -0,0 +1,18 @@
1
+ #!/bin/sh
2
+
3
+ files=`find ext -name '*.[ch]' -o -name parser.rl`
4
+
5
+ for f in $files
6
+ do
7
+ b=`basename $f`
8
+ g=`find ../ruby/ext/json -name $b`
9
+ d=`diff -u $f $g`
10
+ test -z "$d" && continue
11
+ echo "$d"
12
+ read -p "Edit diff of $b? " a
13
+ case $a in
14
+ [yY]*)
15
+ vimdiff $f $g
16
+ ;;
17
+ esac
18
+ done
data/tools/fuzz.rb CHANGED
@@ -1,13 +1,5 @@
1
1
  require 'json'
2
2
 
3
- require 'iconv'
4
- ISO_8859_1_TO_UTF8 = Iconv.new('utf-8', 'iso-8859-15')
5
- class ::String
6
- def to_utf8
7
- ISO_8859_1_TO_UTF8.iconv self
8
- end
9
- end
10
-
11
3
  class Fuzzer
12
4
  def initialize(n, freqs = {})
13
5
  sum = freqs.inject(0.0) { |s, x| s + x.last }
@@ -25,7 +17,7 @@ class Fuzzer
25
17
  def random_string
26
18
  s = ''
27
19
  30.times { s << @alpha[rand(@alpha.size)] }
28
- s.to_utf8
20
+ s
29
21
  end
30
22
 
31
23
  def pick