json 1.8.3 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +5 -5
  2. data/{CHANGES → CHANGES.md} +241 -90
  3. data/Gemfile +10 -6
  4. data/{COPYING-json-jruby → LICENSE} +5 -6
  5. data/{README.rdoc → README.md} +201 -134
  6. data/VERSION +1 -1
  7. data/ext/json/ext/fbuffer/fbuffer.h +0 -3
  8. data/ext/json/ext/generator/generator.c +264 -104
  9. data/ext/json/ext/generator/generator.h +12 -4
  10. data/ext/json/ext/parser/extconf.rb +28 -0
  11. data/ext/json/ext/parser/parser.c +425 -462
  12. data/ext/json/ext/parser/parser.h +5 -5
  13. data/ext/json/ext/parser/parser.rl +181 -181
  14. data/ext/json/extconf.rb +1 -1
  15. data/json.gemspec +0 -0
  16. data/lib/json.rb +550 -29
  17. data/lib/json/add/bigdecimal.rb +3 -2
  18. data/lib/json/add/complex.rb +4 -4
  19. data/lib/json/add/core.rb +1 -0
  20. data/lib/json/add/date.rb +1 -1
  21. data/lib/json/add/date_time.rb +1 -1
  22. data/lib/json/add/exception.rb +1 -1
  23. data/lib/json/add/ostruct.rb +3 -3
  24. data/lib/json/add/range.rb +1 -1
  25. data/lib/json/add/rational.rb +3 -3
  26. data/lib/json/add/regexp.rb +3 -3
  27. data/lib/json/add/set.rb +29 -0
  28. data/lib/json/add/struct.rb +1 -1
  29. data/lib/json/add/symbol.rb +1 -1
  30. data/lib/json/add/time.rb +1 -1
  31. data/lib/json/common.rb +381 -162
  32. data/lib/json/ext.rb +0 -6
  33. data/lib/json/generic_object.rb +5 -4
  34. data/lib/json/pure.rb +2 -8
  35. data/lib/json/pure/generator.rb +83 -126
  36. data/lib/json/pure/parser.rb +62 -84
  37. data/lib/json/version.rb +2 -1
  38. data/tests/fixtures/fail29.json +1 -0
  39. data/tests/fixtures/fail30.json +1 -0
  40. data/tests/fixtures/fail31.json +1 -0
  41. data/tests/fixtures/fail32.json +1 -0
  42. data/tests/fixtures/obsolete_fail1.json +1 -0
  43. data/tests/{test_json_addition.rb → json_addition_test.rb} +28 -25
  44. data/tests/json_common_interface_test.rb +169 -0
  45. data/tests/json_encoding_test.rb +107 -0
  46. data/tests/json_ext_parser_test.rb +15 -0
  47. data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +13 -8
  48. data/tests/{test_json_generate.rb → json_generator_test.rb} +109 -47
  49. data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
  50. data/tests/json_parser_test.rb +497 -0
  51. data/tests/json_string_matching_test.rb +38 -0
  52. data/tests/lib/core_assertions.rb +763 -0
  53. data/tests/lib/envutil.rb +365 -0
  54. data/tests/lib/find_executable.rb +22 -0
  55. data/tests/lib/helper.rb +4 -0
  56. data/tests/ractor_test.rb +30 -0
  57. data/tests/test_helper.rb +17 -0
  58. metadata +48 -76
  59. data/.gitignore +0 -16
  60. data/.travis.yml +0 -26
  61. data/COPYING +0 -58
  62. data/GPL +0 -340
  63. data/README-json-jruby.markdown +0 -33
  64. data/Rakefile +0 -412
  65. data/TODO +0 -1
  66. data/data/example.json +0 -1
  67. data/data/index.html +0 -38
  68. data/data/prototype.js +0 -4184
  69. data/diagrams/.keep +0 -0
  70. data/install.rb +0 -23
  71. data/java/src/json/ext/ByteListTranscoder.java +0 -167
  72. data/java/src/json/ext/Generator.java +0 -444
  73. data/java/src/json/ext/GeneratorMethods.java +0 -232
  74. data/java/src/json/ext/GeneratorService.java +0 -43
  75. data/java/src/json/ext/GeneratorState.java +0 -543
  76. data/java/src/json/ext/OptionsReader.java +0 -114
  77. data/java/src/json/ext/Parser.java +0 -2645
  78. data/java/src/json/ext/Parser.rl +0 -969
  79. data/java/src/json/ext/ParserService.java +0 -35
  80. data/java/src/json/ext/RuntimeInfo.java +0 -121
  81. data/java/src/json/ext/StringDecoder.java +0 -167
  82. data/java/src/json/ext/StringEncoder.java +0 -106
  83. data/java/src/json/ext/Utils.java +0 -89
  84. data/json-java.gemspec +0 -23
  85. data/json_pure.gemspec +0 -40
  86. data/tests/fixtures/fail1.json +0 -1
  87. data/tests/setup_variant.rb +0 -11
  88. data/tests/test_json.rb +0 -553
  89. data/tests/test_json_encoding.rb +0 -65
  90. data/tests/test_json_string_matching.rb +0 -39
  91. data/tests/test_json_unicode.rb +0 -72
  92. data/tools/fuzz.rb +0 -139
  93. data/tools/server.rb +0 -62
@@ -1,18 +1,16 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
1
+ #frozen_string_literal: false
2
+ require 'test_helper'
3
3
 
4
- require 'test/unit'
5
- require File.join(File.dirname(__FILE__), 'setup_variant')
6
-
7
- class TestJSONFixtures < Test::Unit::TestCase
4
+ class JSONFixturesTest < Test::Unit::TestCase
8
5
  def setup
9
- fixtures = File.join(File.dirname(__FILE__), 'fixtures/*.json')
6
+ fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}*.json')
10
7
  passed, failed = Dir[fixtures].partition { |f| f['pass'] }
11
8
  @passed = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
12
9
  @failed = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
13
10
  end
14
11
 
15
12
  def test_passing
13
+ verbose_bak, $VERBOSE = $VERBOSE, nil
16
14
  for name, source in @passed
17
15
  begin
18
16
  assert JSON.parse(source),
@@ -22,14 +20,21 @@ class TestJSONFixtures < Test::Unit::TestCase
22
20
  raise e
23
21
  end
24
22
  end
23
+ ensure
24
+ $VERBOSE = verbose_bak
25
25
  end
26
26
 
27
27
  def test_failing
28
28
  for name, source in @failed
29
- assert_raises(JSON::ParserError, JSON::NestingError,
29
+ assert_raise(JSON::ParserError, JSON::NestingError,
30
30
  "Did not fail for fixture '#{name}': #{source.inspect}") do
31
31
  JSON.parse(source)
32
32
  end
33
33
  end
34
34
  end
35
+
36
+ def test_sanity
37
+ assert(@passed.size > 5)
38
+ assert(@failed.size > 20)
39
+ end
35
40
  end
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
+ # frozen_string_literal: false
3
4
 
4
- require 'test/unit'
5
- require File.join(File.dirname(__FILE__), 'setup_variant')
5
+ require 'test_helper'
6
6
 
7
- class TestJSONGenerate < Test::Unit::TestCase
7
+ class JSONGeneratorTest < Test::Unit::TestCase
8
8
  include JSON
9
9
 
10
10
  def setup
@@ -40,25 +40,38 @@ class TestJSONGenerate < Test::Unit::TestCase
40
40
  EOT
41
41
  end
42
42
 
43
+ def silence
44
+ v = $VERBOSE
45
+ $VERBOSE = nil
46
+ yield
47
+ ensure
48
+ $VERBOSE = v
49
+ end
50
+
43
51
  def test_generate
44
52
  json = generate(@hash)
45
- assert_equal(JSON.parse(@json2), JSON.parse(json))
53
+ assert_equal(parse(@json2), parse(json))
46
54
  json = JSON[@hash]
47
- assert_equal(JSON.parse(@json2), JSON.parse(json))
55
+ assert_equal(parse(@json2), parse(json))
48
56
  parsed_json = parse(json)
49
57
  assert_equal(@hash, parsed_json)
50
58
  json = generate({1=>2})
51
59
  assert_equal('{"1":2}', json)
52
60
  parsed_json = parse(json)
53
61
  assert_equal({"1"=>2}, parsed_json)
54
- assert_raise(GeneratorError) { generate(666) }
55
- assert_equal '666', generate(666, :quirks_mode => true)
62
+ assert_equal '666', generate(666)
56
63
  end
57
64
 
58
65
  def test_generate_pretty
66
+ json = pretty_generate({})
67
+ assert_equal(<<'EOT'.chomp, json)
68
+ {
69
+ }
70
+ EOT
59
71
  json = pretty_generate(@hash)
60
- # hashes aren't (insertion) ordered on every ruby implementation assert_equal(@json3, json)
61
- assert_equal(JSON.parse(@json3), JSON.parse(json))
72
+ # hashes aren't (insertion) ordered on every ruby implementation
73
+ # assert_equal(@json3, json)
74
+ assert_equal(parse(@json3), parse(json))
62
75
  parsed_json = parse(json)
63
76
  assert_equal(@hash, parsed_json)
64
77
  json = pretty_generate({1=>2})
@@ -69,8 +82,7 @@ EOT
69
82
  EOT
70
83
  parsed_json = parse(json)
71
84
  assert_equal({"1"=>2}, parsed_json)
72
- assert_raise(GeneratorError) { pretty_generate(666) }
73
- assert_equal '666', pretty_generate(666, :quirks_mode => true)
85
+ assert_equal '666', pretty_generate(666)
74
86
  end
75
87
 
76
88
  def test_generate_custom
@@ -88,30 +100,26 @@ EOT
88
100
 
89
101
  def test_fast_generate
90
102
  json = fast_generate(@hash)
91
- assert_equal(JSON.parse(@json2), JSON.parse(json))
103
+ assert_equal(parse(@json2), parse(json))
92
104
  parsed_json = parse(json)
93
105
  assert_equal(@hash, parsed_json)
94
106
  json = fast_generate({1=>2})
95
107
  assert_equal('{"1":2}', json)
96
108
  parsed_json = parse(json)
97
109
  assert_equal({"1"=>2}, parsed_json)
98
- assert_raise(GeneratorError) { fast_generate(666) }
99
- assert_equal '666', fast_generate(666, :quirks_mode => true)
110
+ assert_equal '666', fast_generate(666)
100
111
  end
101
112
 
102
113
  def test_own_state
103
114
  state = State.new
104
115
  json = generate(@hash, state)
105
- assert_equal(JSON.parse(@json2), JSON.parse(json))
116
+ assert_equal(parse(@json2), parse(json))
106
117
  parsed_json = parse(json)
107
118
  assert_equal(@hash, parsed_json)
108
119
  json = generate({1=>2}, state)
109
120
  assert_equal('{"1":2}', json)
110
121
  parsed_json = parse(json)
111
122
  assert_equal({"1"=>2}, parsed_json)
112
- assert_raise(GeneratorError) { generate(666, state) }
113
- state.quirks_mode = true
114
- assert state.quirks_mode?
115
123
  assert_equal '666', generate(666, state)
116
124
  end
117
125
 
@@ -123,25 +131,25 @@ EOT
123
131
  assert s[:check_circular?]
124
132
  h = { 1=>2 }
125
133
  h[3] = h
126
- assert_raises(JSON::NestingError) { generate(h) }
127
- assert_raises(JSON::NestingError) { generate(h, s) }
134
+ assert_raise(JSON::NestingError) { generate(h) }
135
+ assert_raise(JSON::NestingError) { generate(h, s) }
128
136
  s = JSON.state.new
129
137
  a = [ 1, 2 ]
130
138
  a << a
131
- assert_raises(JSON::NestingError) { generate(a, s) }
139
+ assert_raise(JSON::NestingError) { generate(a, s) }
132
140
  assert s.check_circular?
133
141
  assert s[:check_circular?]
134
142
  end
135
143
 
136
144
  def test_pretty_state
137
- state = PRETTY_STATE_PROTOTYPE.dup
145
+ state = JSON.create_pretty_state
138
146
  assert_equal({
139
147
  :allow_nan => false,
140
148
  :array_nl => "\n",
141
149
  :ascii_only => false,
142
150
  :buffer_initial_length => 1024,
143
- :quirks_mode => false,
144
151
  :depth => 0,
152
+ :escape_slash => false,
145
153
  :indent => " ",
146
154
  :max_nesting => 100,
147
155
  :object_nl => "\n",
@@ -151,14 +159,14 @@ EOT
151
159
  end
152
160
 
153
161
  def test_safe_state
154
- state = SAFE_STATE_PROTOTYPE.dup
162
+ state = JSON::State.new
155
163
  assert_equal({
156
164
  :allow_nan => false,
157
165
  :array_nl => "",
158
166
  :ascii_only => false,
159
167
  :buffer_initial_length => 1024,
160
- :quirks_mode => false,
161
168
  :depth => 0,
169
+ :escape_slash => false,
162
170
  :indent => "",
163
171
  :max_nesting => 100,
164
172
  :object_nl => "",
@@ -168,14 +176,14 @@ EOT
168
176
  end
169
177
 
170
178
  def test_fast_state
171
- state = FAST_STATE_PROTOTYPE.dup
179
+ state = JSON.create_fast_state
172
180
  assert_equal({
173
181
  :allow_nan => false,
174
182
  :array_nl => "",
175
183
  :ascii_only => false,
176
184
  :buffer_initial_length => 1024,
177
- :quirks_mode => false,
178
185
  :depth => 0,
186
+ :escape_slash => false,
179
187
  :indent => "",
180
188
  :max_nesting => 0,
181
189
  :object_nl => "",
@@ -185,34 +193,30 @@ EOT
185
193
  end
186
194
 
187
195
  def test_allow_nan
188
- assert_raises(GeneratorError) { generate([JSON::NaN]) }
196
+ assert_raise(GeneratorError) { generate([JSON::NaN]) }
189
197
  assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
190
- assert_raises(GeneratorError) { fast_generate([JSON::NaN]) }
191
- assert_raises(GeneratorError) { pretty_generate([JSON::NaN]) }
198
+ assert_raise(GeneratorError) { fast_generate([JSON::NaN]) }
199
+ assert_raise(GeneratorError) { pretty_generate([JSON::NaN]) }
192
200
  assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
193
- assert_raises(GeneratorError) { generate([JSON::Infinity]) }
201
+ assert_raise(GeneratorError) { generate([JSON::Infinity]) }
194
202
  assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
195
- assert_raises(GeneratorError) { fast_generate([JSON::Infinity]) }
196
- assert_raises(GeneratorError) { pretty_generate([JSON::Infinity]) }
203
+ assert_raise(GeneratorError) { fast_generate([JSON::Infinity]) }
204
+ assert_raise(GeneratorError) { pretty_generate([JSON::Infinity]) }
197
205
  assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
198
- assert_raises(GeneratorError) { generate([JSON::MinusInfinity]) }
206
+ assert_raise(GeneratorError) { generate([JSON::MinusInfinity]) }
199
207
  assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
200
- assert_raises(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
201
- assert_raises(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
208
+ assert_raise(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
209
+ assert_raise(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
202
210
  assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
203
211
  end
204
212
 
205
213
  def test_depth
206
214
  ary = []; ary << ary
207
- assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
208
- assert_raises(JSON::NestingError) { JSON.generate(ary) }
209
- assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
210
- assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
211
- assert_raises(JSON::NestingError) { JSON.pretty_generate(ary) }
212
- assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
215
+ assert_raise(JSON::NestingError) { generate(ary) }
216
+ assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) }
213
217
  s = JSON.state.new
214
218
  assert_equal 0, s.depth
215
- assert_raises(JSON::NestingError) { ary.to_json(s) }
219
+ assert_raise(JSON::NestingError) { ary.to_json(s) }
216
220
  assert_equal 100, s.depth
217
221
  end
218
222
 
@@ -228,7 +232,7 @@ EOT
228
232
  end
229
233
 
230
234
  def test_gc
231
- if respond_to?(:assert_in_out_err)
235
+ if respond_to?(:assert_in_out_err) && !(RUBY_PLATFORM =~ /java/)
232
236
  assert_in_out_err(%w[-rjson --disable-gems], <<-EOS, [], [])
233
237
  bignum_too_long_to_embed_as_string = 1234567890123456789012345
234
238
  expect = bignum_too_long_to_embed_as_string.to_s
@@ -285,12 +289,13 @@ EOT
285
289
  if defined?(JSON::Ext::Generator)
286
290
  def test_broken_bignum # [ruby-core:38867]
287
291
  pid = fork do
288
- Bignum.class_eval do
292
+ x = 1 << 64
293
+ x.class.class_eval do
289
294
  def to_s
290
295
  end
291
296
  end
292
297
  begin
293
- JSON::Ext::Generator::State.new.generate(1<<64)
298
+ JSON::Ext::Generator::State.new.generate(x)
294
299
  exit 1
295
300
  rescue TypeError
296
301
  exit 0
@@ -331,7 +336,64 @@ EOT
331
336
 
332
337
  def test_json_generate
333
338
  assert_raise JSON::GeneratorError do
334
- assert_equal true, JSON.generate(["\xea"])
339
+ assert_equal true, generate(["\xea"])
340
+ end
341
+ end
342
+
343
+ def test_nesting
344
+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
345
+ too_deep_ary = eval too_deep
346
+ assert_raise(JSON::NestingError) { generate too_deep_ary }
347
+ assert_raise(JSON::NestingError) { generate too_deep_ary, :max_nesting => 100 }
348
+ ok = generate too_deep_ary, :max_nesting => 101
349
+ assert_equal too_deep, ok
350
+ ok = generate too_deep_ary, :max_nesting => nil
351
+ assert_equal too_deep, ok
352
+ ok = generate too_deep_ary, :max_nesting => false
353
+ assert_equal too_deep, ok
354
+ ok = generate too_deep_ary, :max_nesting => 0
355
+ assert_equal too_deep, ok
356
+ end
357
+
358
+ def test_backslash
359
+ data = [ '\\.(?i:gif|jpe?g|png)$' ]
360
+ json = '["\\\\.(?i:gif|jpe?g|png)$"]'
361
+ assert_equal json, generate(data)
362
+ #
363
+ data = [ '\\"' ]
364
+ json = '["\\\\\""]'
365
+ assert_equal json, generate(data)
366
+ #
367
+ data = [ '/' ]
368
+ json = '["/"]'
369
+ assert_equal json, generate(data)
370
+ #
371
+ data = [ '/' ]
372
+ json = '["\/"]'
373
+ assert_equal json, generate(data, :escape_slash => true)
374
+ #
375
+ data = ['"']
376
+ json = '["\""]'
377
+ assert_equal json, generate(data)
378
+ #
379
+ data = ["'"]
380
+ json = '["\\\'"]'
381
+ assert_equal '["\'"]', generate(data)
382
+ end
383
+
384
+ def test_string_subclass
385
+ s = Class.new(String) do
386
+ def to_s; self; end
387
+ undef to_json
388
+ end
389
+ assert_nothing_raised(SystemStackError) do
390
+ assert_equal '["foo"]', JSON.generate([s.new('foo')])
391
+ end
392
+ end
393
+
394
+ if defined?(Encoding)
395
+ def test_nonutf8_encoding
396
+ assert_equal("\"5\u{b0}\"", "5\xb0".force_encoding("iso-8859-1").to_json)
335
397
  end
336
398
  end
337
399
  end
@@ -1,9 +1,7 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
1
+ #frozen_string_literal: false
2
+ require 'test_helper'
3
3
 
4
- require 'test/unit'
5
- require File.join(File.dirname(__FILE__), 'setup_variant')
6
- class TestJSONGenericObject < Test::Unit::TestCase
4
+ class JSONGenericObjectTest < Test::Unit::TestCase
7
5
  include JSON
8
6
 
9
7
  def setup
@@ -26,11 +24,20 @@ class TestJSONGenericObject < Test::Unit::TestCase
26
24
  end
27
25
 
28
26
  def test_parse_json
29
- assert_kind_of Hash, JSON('{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }', :create_additions => true)
27
+ assert_kind_of Hash,
28
+ JSON(
29
+ '{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
30
+ :create_additions => true
31
+ )
30
32
  switch_json_creatable do
31
- assert_equal @go, l = JSON('{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }', :create_additions => true)
33
+ assert_equal @go, l =
34
+ JSON(
35
+ '{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
36
+ :create_additions => true
37
+ )
32
38
  assert_equal 1, l.a
33
- assert_equal @go, l = JSON('{ "a": 1, "b": 2 }', :object_class => GenericObject)
39
+ assert_equal @go,
40
+ l = JSON('{ "a": 1, "b": 2 }', :object_class => GenericObject)
34
41
  assert_equal 1, l.a
35
42
  assert_equal GenericObject[:a => GenericObject[:b => 2]],
36
43
  l = JSON('{ "a": { "b": 2 } }', :object_class => GenericObject)
@@ -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