oj 3.11.5 → 3.16.5

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.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1421 -0
  3. data/README.md +19 -5
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +20 -6
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +10 -9
  9. data/ext/oj/circarray.c +8 -6
  10. data/ext/oj/circarray.h +2 -2
  11. data/ext/oj/code.c +19 -33
  12. data/ext/oj/code.h +2 -2
  13. data/ext/oj/compat.c +27 -77
  14. data/ext/oj/custom.c +86 -179
  15. data/ext/oj/debug.c +126 -0
  16. data/ext/oj/dump.c +256 -249
  17. data/ext/oj/dump.h +26 -12
  18. data/ext/oj/dump_compat.c +565 -642
  19. data/ext/oj/dump_leaf.c +17 -63
  20. data/ext/oj/dump_object.c +65 -187
  21. data/ext/oj/dump_strict.c +27 -51
  22. data/ext/oj/encoder.c +43 -0
  23. data/ext/oj/err.c +2 -13
  24. data/ext/oj/err.h +24 -8
  25. data/ext/oj/extconf.rb +21 -6
  26. data/ext/oj/fast.c +149 -149
  27. data/ext/oj/intern.c +313 -0
  28. data/ext/oj/intern.h +22 -0
  29. data/ext/oj/mem.c +318 -0
  30. data/ext/oj/mem.h +53 -0
  31. data/ext/oj/mimic_json.c +121 -106
  32. data/ext/oj/object.c +85 -162
  33. data/ext/oj/odd.c +89 -67
  34. data/ext/oj/odd.h +15 -15
  35. data/ext/oj/oj.c +542 -411
  36. data/ext/oj/oj.h +99 -73
  37. data/ext/oj/parse.c +175 -187
  38. data/ext/oj/parse.h +26 -24
  39. data/ext/oj/parser.c +1600 -0
  40. data/ext/oj/parser.h +101 -0
  41. data/ext/oj/rails.c +112 -159
  42. data/ext/oj/rails.h +1 -1
  43. data/ext/oj/reader.c +11 -14
  44. data/ext/oj/reader.h +4 -2
  45. data/ext/oj/resolve.c +5 -24
  46. data/ext/oj/rxclass.c +7 -6
  47. data/ext/oj/rxclass.h +1 -1
  48. data/ext/oj/saj.c +22 -33
  49. data/ext/oj/saj2.c +584 -0
  50. data/ext/oj/saj2.h +23 -0
  51. data/ext/oj/scp.c +5 -28
  52. data/ext/oj/sparse.c +28 -72
  53. data/ext/oj/stream_writer.c +50 -40
  54. data/ext/oj/strict.c +56 -61
  55. data/ext/oj/string_writer.c +72 -39
  56. data/ext/oj/trace.h +31 -4
  57. data/ext/oj/usual.c +1218 -0
  58. data/ext/oj/usual.h +69 -0
  59. data/ext/oj/util.h +1 -1
  60. data/ext/oj/val_stack.c +14 -3
  61. data/ext/oj/val_stack.h +8 -7
  62. data/ext/oj/validate.c +46 -0
  63. data/ext/oj/wab.c +63 -88
  64. data/lib/oj/active_support_helper.rb +1 -3
  65. data/lib/oj/bag.rb +7 -1
  66. data/lib/oj/easy_hash.rb +4 -5
  67. data/lib/oj/error.rb +1 -2
  68. data/lib/oj/json.rb +162 -150
  69. data/lib/oj/mimic.rb +9 -7
  70. data/lib/oj/saj.rb +20 -6
  71. data/lib/oj/schandler.rb +5 -4
  72. data/lib/oj/state.rb +12 -8
  73. data/lib/oj/version.rb +1 -2
  74. data/lib/oj.rb +2 -0
  75. data/pages/Compatibility.md +1 -1
  76. data/pages/InstallOptions.md +20 -0
  77. data/pages/JsonGem.md +15 -0
  78. data/pages/Modes.md +8 -3
  79. data/pages/Options.md +43 -5
  80. data/pages/Parser.md +309 -0
  81. data/pages/Rails.md +14 -2
  82. data/test/_test_active.rb +8 -9
  83. data/test/_test_active_mimic.rb +7 -8
  84. data/test/_test_mimic_rails.rb +17 -20
  85. data/test/activerecord/result_test.rb +5 -6
  86. data/test/activesupport6/encoding_test.rb +63 -28
  87. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  88. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  89. data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
  90. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  91. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  92. data/test/files.rb +15 -15
  93. data/test/foo.rb +16 -45
  94. data/test/helper.rb +11 -8
  95. data/test/isolated/shared.rb +3 -2
  96. data/test/json_gem/json_addition_test.rb +2 -2
  97. data/test/json_gem/json_common_interface_test.rb +8 -6
  98. data/test/json_gem/json_encoding_test.rb +0 -0
  99. data/test/json_gem/json_ext_parser_test.rb +1 -0
  100. data/test/json_gem/json_fixtures_test.rb +3 -2
  101. data/test/json_gem/json_generator_test.rb +56 -38
  102. data/test/json_gem/json_generic_object_test.rb +11 -11
  103. data/test/json_gem/json_parser_test.rb +54 -47
  104. data/test/json_gem/json_string_matching_test.rb +9 -9
  105. data/test/json_gem/test_helper.rb +7 -3
  106. data/test/mem.rb +34 -0
  107. data/test/perf.rb +22 -27
  108. data/test/perf_compat.rb +31 -33
  109. data/test/perf_dump.rb +50 -0
  110. data/test/perf_fast.rb +80 -82
  111. data/test/perf_file.rb +27 -29
  112. data/test/perf_object.rb +65 -69
  113. data/test/perf_once.rb +59 -0
  114. data/test/perf_parser.rb +183 -0
  115. data/test/perf_saj.rb +46 -54
  116. data/test/perf_scp.rb +58 -69
  117. data/test/perf_simple.rb +41 -39
  118. data/test/perf_strict.rb +74 -82
  119. data/test/perf_wab.rb +67 -69
  120. data/test/prec.rb +5 -5
  121. data/test/sample/change.rb +0 -1
  122. data/test/sample/dir.rb +0 -1
  123. data/test/sample/doc.rb +0 -1
  124. data/test/sample/file.rb +0 -1
  125. data/test/sample/group.rb +0 -1
  126. data/test/sample/hasprops.rb +0 -1
  127. data/test/sample/layer.rb +0 -1
  128. data/test/sample/rect.rb +0 -1
  129. data/test/sample/shape.rb +0 -1
  130. data/test/sample/text.rb +0 -1
  131. data/test/sample.rb +16 -16
  132. data/test/sample_json.rb +8 -8
  133. data/test/test_compat.rb +95 -43
  134. data/test/test_custom.rb +73 -51
  135. data/test/test_debian.rb +7 -10
  136. data/test/test_fast.rb +135 -79
  137. data/test/test_file.rb +41 -30
  138. data/test/test_gc.rb +16 -5
  139. data/test/test_generate.rb +5 -5
  140. data/test/test_hash.rb +5 -5
  141. data/test/test_integer_range.rb +9 -9
  142. data/test/test_null.rb +20 -20
  143. data/test/test_object.rb +99 -96
  144. data/test/test_parser.rb +11 -0
  145. data/test/test_parser_debug.rb +27 -0
  146. data/test/test_parser_saj.rb +337 -0
  147. data/test/test_parser_usual.rb +251 -0
  148. data/test/test_rails.rb +2 -2
  149. data/test/test_saj.rb +10 -8
  150. data/test/test_scp.rb +37 -39
  151. data/test/test_strict.rb +40 -32
  152. data/test/test_various.rb +165 -84
  153. data/test/test_wab.rb +48 -44
  154. data/test/test_writer.rb +47 -47
  155. data/test/tests.rb +13 -5
  156. data/test/tests_mimic.rb +12 -3
  157. data/test/tests_mimic_addition.rb +12 -3
  158. metadata +74 -128
  159. data/ext/oj/hash.c +0 -131
  160. data/ext/oj/hash.h +0 -19
  161. data/ext/oj/hash_test.c +0 -491
  162. data/test/activesupport4/decoding_test.rb +0 -108
  163. data/test/activesupport4/encoding_test.rb +0 -531
  164. data/test/activesupport4/test_helper.rb +0 -41
  165. data/test/activesupport5/test_helper.rb +0 -72
  166. data/test/bar.rb +0 -35
  167. data/test/baz.rb +0 -16
  168. data/test/zoo.rb +0 -13
@@ -2,6 +2,7 @@
2
2
  # encoding: UTF-8
3
3
 
4
4
  #frozen_string_literal: false
5
+
5
6
  require 'json_gem/test_helper'
6
7
 
7
8
  class JSONFixturesTest < Test::Unit::TestCase
@@ -16,7 +17,7 @@ class JSONFixturesTest < Test::Unit::TestCase
16
17
  for name, source in @passed
17
18
  begin
18
19
  assert JSON.parse(source),
19
- "Did not pass for fixture '#{name}': #{source.inspect}"
20
+ "Did not pass for fixture '#{name}': #{source.inspect}"
20
21
  rescue => e
21
22
  warn "\nCaught #{e.class}(#{e}) for fixture '#{name}': #{source.inspect}\n#{e.backtrace * "\n"}"
22
23
  raise e
@@ -27,7 +28,7 @@ class JSONFixturesTest < Test::Unit::TestCase
27
28
  def test_failing
28
29
  for name, source in @failed
29
30
  assert_raise(JSON::ParserError, JSON::NestingError,
30
- "Did not fail for fixture '#{name}': #{source.inspect}") do
31
+ "Did not fail for fixture '#{name}': #{source.inspect}") do
31
32
  JSON.parse(source)
32
33
  end
33
34
  end
@@ -22,24 +22,24 @@ class JSONGeneratorTest < Test::Unit::TestCase
22
22
  }
23
23
  @json2 = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},' +
24
24
  '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
25
- @json3 = <<'EOT'.chomp
26
- {
27
- "a": 2,
28
- "b": 3.141,
29
- "c": "c",
30
- "d": [
31
- 1,
32
- "b",
33
- 3.14
34
- ],
35
- "e": {
36
- "foo": "bar"
37
- },
38
- "g": "\"\u0000\u001f",
39
- "h": 1000.0,
40
- "i": 0.001
41
- }
42
- EOT
25
+ @json3 = <<~'EOT'.chomp
26
+ {
27
+ "a": 2,
28
+ "b": 3.141,
29
+ "c": "c",
30
+ "d": [
31
+ 1,
32
+ "b",
33
+ 3.14
34
+ ],
35
+ "e": {
36
+ "foo": "bar"
37
+ },
38
+ "g": "\"\u0000\u001f",
39
+ "h": 1000.0,
40
+ "i": 0.001
41
+ }
42
+ EOT
43
43
  end
44
44
 
45
45
  def test_generate
@@ -64,27 +64,29 @@ EOT
64
64
  parsed_json = JSON.parse(json)
65
65
  assert_equal(@hash, parsed_json)
66
66
  json = JSON.pretty_generate({1=>2})
67
- assert_equal(<<'EOT'.chomp, json)
68
- {
69
- "1": 2
70
- }
71
- EOT
67
+ assert_equal(<<~'EOT'.chomp, json)
68
+ {
69
+ "1": 2
70
+ }
71
+ EOT
72
72
  parsed_json = JSON.parse(json)
73
73
  assert_equal({"1"=>2}, parsed_json)
74
74
  assert_equal '666', JSON.pretty_generate(666)
75
+ json_nil_opts = JSON.pretty_generate({1=>2}, nil)
76
+ assert_equal json, json_nil_opts
75
77
  end
76
78
 
77
79
  def test_generate_custom
78
80
  state = JSON::State.new(:space_before => " ", :space => " ", :indent => "<i>", :object_nl => "\n", :array_nl => "<a_nl>")
79
- json = JSON.generate({1=>{2=>3,4=>[5,6]}}, state)
80
- assert_equal(<<'EOT'.chomp, json)
81
- {
82
- <i>"1" : {
83
- <i><i>"2" : 3,
84
- <i><i>"4" : [<a_nl><i><i><i>5,<a_nl><i><i><i>6<a_nl><i><i>]
85
- <i>}
86
- }
87
- EOT
81
+ json = JSON.generate({1=>{2=>3, 4=>[5, 6]}}, state)
82
+ assert_equal(<<~'EOT'.chomp, json)
83
+ {
84
+ <i>"1" : {
85
+ <i><i>"2" : 3,
86
+ <i><i>"4" : [<a_nl><i><i><i>5,<a_nl><i><i><i>6<a_nl><i><i>]
87
+ <i>}
88
+ }
89
+ EOT
88
90
  end
89
91
 
90
92
  def test_fast_generate
@@ -113,7 +115,7 @@ EOT
113
115
  end
114
116
 
115
117
  # TBD Implement JSON.state to return state class.
116
- # set state attibutes from defaults
118
+ # set state attributes from defaults
117
119
  # implement methods
118
120
  # circular should use circular in defaults or maybe always set to true, allow changes with [:check_circular]=
119
121
  def test_states
@@ -140,6 +142,8 @@ EOT
140
142
  # seems to occur on travis but not locally.
141
143
  actual = state.to_h
142
144
  actual.delete(:escape_slash)
145
+ actual.delete(:strict)
146
+ actual.delete(:script_safe)
143
147
  assert_equal({
144
148
  :allow_nan => false,
145
149
  :array_nl => "\n",
@@ -160,6 +164,8 @@ EOT
160
164
  # seems to occur on travis but not locally.
161
165
  actual = state.to_h
162
166
  actual.delete(:escape_slash)
167
+ actual.delete(:strict)
168
+ actual.delete(:script_safe)
163
169
  assert_equal({
164
170
  :allow_nan => false,
165
171
  :array_nl => "",
@@ -180,6 +186,8 @@ EOT
180
186
  # seems to occur on travis but not locally.
181
187
  actual = state.to_h
182
188
  actual.delete(:escape_slash)
189
+ actual.delete(:strict)
190
+ actual.delete(:script_safe)
183
191
  assert_equal({
184
192
  :allow_nan => false,
185
193
  :array_nl => "",
@@ -292,7 +300,9 @@ EOT
292
300
  assert_equal '2', state.indent
293
301
  end
294
302
 
295
- if defined?(JSON::Ext::Generator)
303
+ if defined?(JSON::Ext::Generator) && Process.respond_to?(:fork)
304
+ # forking to avoid modifying core class of a parent process and
305
+ # introducing race conditions of tests are run in parallel
296
306
  def test_broken_bignum # [ruby-core:38867]
297
307
  pid = fork do
298
308
  x = 1 << 64
@@ -309,9 +319,6 @@ EOT
309
319
  end
310
320
  _, status = Process.waitpid2(pid)
311
321
  assert status.success?
312
- rescue NotImplementedError
313
- # forking to avoid modifying core class of a parent process and
314
- # introducing race conditions of tests are run in parallel
315
322
  end
316
323
  end
317
324
 
@@ -351,7 +358,7 @@ EOT
351
358
  too_deep_ary = eval too_deep
352
359
  assert_raise(JSON::NestingError) { JSON.generate too_deep_ary }
353
360
  assert_raise(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 100 }
354
- ok = JSON.generate too_deep_ary, :max_nesting => 101
361
+ ok = JSON.generate too_deep_ary, :max_nesting => 102
355
362
  assert_equal too_deep, ok
356
363
  ok = JSON.generate too_deep_ary, :max_nesting => nil
357
364
  assert_equal too_deep, ok
@@ -392,4 +399,15 @@ EOT
392
399
  assert_equal '["foo"]', JSON.generate([s.new('foo')])
393
400
  end
394
401
  end
402
+
403
+ def test_invalid_to_json
404
+ omit if REAL_JSON_GEM
405
+
406
+ data = Object.new
407
+ def data.to_json(*)
408
+ nil
409
+ end
410
+
411
+ assert_raises(TypeError) { JSON.generate(data) }
412
+ end
395
413
  end
@@ -29,26 +29,26 @@ class JSONGenericObjectTest < Test::Unit::TestCase
29
29
 
30
30
  def test_parse_json
31
31
  x = JSON(
32
- '{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
33
- :create_additions => true
34
- )
35
- assert_kind_of Hash,
36
- JSON(
37
32
  '{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
38
33
  :create_additions => true
39
34
  )
35
+ assert_kind_of Hash,
36
+ JSON(
37
+ '{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
38
+ :create_additions => true
39
+ )
40
40
  switch_json_creatable do
41
41
  assert_equal @go, l =
42
- JSON(
43
- '{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
44
- :create_additions => true
45
- )
42
+ JSON(
43
+ '{ "json_class": "JSON::GenericObject", "a": 1, "b": 2 }',
44
+ :create_additions => true
45
+ )
46
46
  assert_equal 1, l.a
47
47
  assert_equal @go,
48
- l = JSON('{ "a": 1, "b": 2 }', :object_class => JSON::GenericObject)
48
+ l = JSON('{ "a": 1, "b": 2 }', :object_class => JSON::GenericObject)
49
49
  assert_equal 1, l.a
50
50
  assert_equal JSON::GenericObject[:a => JSON::GenericObject[:b => 2]],
51
- l = JSON('{ "a": { "b": 2 } }', :object_class => JSON::GenericObject)
51
+ l = JSON('{ "a": { "b": 2 } }', :object_class => JSON::GenericObject)
52
52
  assert_equal 2, l.a.b
53
53
  end
54
54
  end
@@ -31,7 +31,7 @@ class JSONParserTest < Test::Unit::TestCase
31
31
  }
32
32
  assert_equal(Encoding::UTF_8, e.message.encoding, bug10705)
33
33
  assert_include(e.message, json, bug10705)
34
- end if defined?(Encoding::UTF_8)
34
+ end if defined?(Encoding::UTF_8) and defined?(JSON::Ext::Parser)
35
35
 
36
36
  def test_parsing
37
37
  parser = JSON::Parser.new('"test"')
@@ -95,21 +95,21 @@ class JSONParserTest < Test::Unit::TestCase
95
95
  assert_raise(JSON::ParserError) { JSON.parse('.23') }
96
96
  assert_raise(JSON::ParserError) { JSON.parse('023') }
97
97
  assert_equal 23, JSON.parse('23')
98
- assert_equal -23, JSON.parse('-23')
98
+ assert_equal(-23, JSON.parse('-23'))
99
99
  assert_equal_float 3.141, JSON.parse('3.141')
100
- assert_equal_float -3.141, JSON.parse('-3.141')
100
+ assert_equal_float(-3.141, JSON.parse('-3.141'))
101
101
  assert_equal_float 3.141, JSON.parse('3141e-3')
102
102
  assert_equal_float 3.141, JSON.parse('3141.1e-3')
103
103
  assert_equal_float 3.141, JSON.parse('3141E-3')
104
104
  assert_equal_float 3.141, JSON.parse('3141.0E-3')
105
- assert_equal_float -3.141, JSON.parse('-3141.0e-3')
106
- assert_equal_float -3.141, JSON.parse('-3141e-3')
105
+ assert_equal_float(-3.141, JSON.parse('-3141.0e-3'))
106
+ assert_equal_float(-3.141, JSON.parse('-3141e-3'))
107
107
  assert_raise(JSON::ParserError) { JSON.parse('NaN') }
108
108
  assert JSON.parse('NaN', :allow_nan => true).nan?
109
109
  assert_raise(JSON::ParserError) { JSON.parse('Infinity') }
110
110
  assert_equal 1.0/0, JSON.parse('Infinity', :allow_nan => true)
111
111
  assert_raise(JSON::ParserError) { JSON.parse('-Infinity') }
112
- assert_equal -1.0/0, JSON.parse('-Infinity', :allow_nan => true)
112
+ assert_equal(-1.0/0, JSON.parse('-Infinity', :allow_nan => true))
113
113
  end
114
114
 
115
115
  if Array.method_defined?(:permutation)
@@ -133,17 +133,17 @@ class JSONParserTest < Test::Unit::TestCase
133
133
  end
134
134
 
135
135
  def test_parse_arrays
136
- assert_equal([1,2,3], JSON.parse('[1,2,3]'))
137
- assert_equal([1.2,2,3], JSON.parse('[1.2,2,3]'))
138
- assert_equal([[],[[],[]]], JSON.parse('[[],[[],[]]]'))
136
+ assert_equal([1, 2, 3], JSON.parse('[1,2,3]'))
137
+ assert_equal([1.2, 2, 3], JSON.parse('[1.2,2,3]'))
138
+ assert_equal([[], [[], []]], JSON.parse('[[],[[],[]]]'))
139
139
  assert_equal([], JSON.parse('[]'))
140
140
  assert_equal([], JSON.parse(' [ ] '))
141
141
  assert_equal([1], JSON.parse('[1]'))
142
142
  assert_equal([1], JSON.parse(' [ 1 ] '))
143
143
  ary = [[1], ["foo"], [3.14], [4711.0], [2.718], [nil],
144
- [[1, -2, 3]], [false], [true]]
144
+ [[1, -2, 3]], [false], [true]]
145
145
  assert_equal(ary,
146
- JSON.parse('[[1],["foo"],[3.14],[47.11e+2],[2718.0E-3],[null],[[1,-2,3]],[false],[true]]'))
146
+ JSON.parse('[[1],["foo"],[3.14],[47.11e+2],[2718.0E-3],[null],[[1,-2,3]],[false],[true]]'))
147
147
  assert_equal(ary, JSON.parse(%Q{ [ [1] , ["foo"] , [3.14] \t , [47.11e+2]\s
148
148
  , [2718.0E-3 ],\r[ null] , [[1, -2, 3 ]], [false ],[ true]\n ] }))
149
149
  end
@@ -208,51 +208,51 @@ class JSONParserTest < Test::Unit::TestCase
208
208
 
209
209
  def test_symbolize_names
210
210
  assert_equal({ "foo" => "bar", "baz" => "quux" },
211
- JSON.parse('{"foo":"bar", "baz":"quux"}'))
211
+ JSON.parse('{"foo":"bar", "baz":"quux"}'))
212
212
  assert_equal({ :foo => "bar", :baz => "quux" },
213
- JSON.parse('{"foo":"bar", "baz":"quux"}', :symbolize_names => true))
213
+ JSON.parse('{"foo":"bar", "baz":"quux"}', :symbolize_names => true))
214
214
  assert_raise(ArgumentError) do
215
215
  JSON.parse('{}', :symbolize_names => true, :create_additions => true)
216
216
  end
217
217
  end
218
218
 
219
219
  def test_parse_comments
220
- json = <<EOT
221
- {
222
- "key1":"value1", // eol comment
223
- "key2":"value2" /* multi line
224
- * comment */,
225
- "key3":"value3" /* multi line
226
- // nested eol comment
227
- * comment */
228
- }
229
- EOT
220
+ json = <<~EOT
221
+ {
222
+ "key1":"value1", // eol comment
223
+ "key2":"value2" /* multi line
224
+ * comment */,
225
+ "key3":"value3" /* multi line
226
+ // nested eol comment
227
+ * comment */
228
+ }
229
+ EOT
230
230
  assert_equal(
231
231
  { "key1" => "value1", "key2" => "value2", "key3" => "value3" },
232
232
  JSON.parse(json))
233
- json = <<EOT
234
- {
235
- "key1":"value1" /* multi line
236
- // nested eol comment
237
- /* illegal nested multi line comment */
238
- * comment */
239
- }
240
- EOT
233
+ json = <<~EOT
234
+ {
235
+ "key1":"value1" /* multi line
236
+ // nested eol comment
237
+ /* illegal nested multi line comment */
238
+ * comment */
239
+ }
240
+ EOT
241
241
  assert_raise(JSON::ParserError) { JSON.parse(json) }
242
- json = <<EOT
243
- {
244
- "key1":"value1" /* multi line
245
- // nested eol comment
246
- closed multi comment */
247
- and again, throw an Error */
248
- }
249
- EOT
242
+ json = <<~EOT
243
+ {
244
+ "key1":"value1" /* multi line
245
+ // nested eol comment
246
+ closed multi comment */
247
+ and again, throw an Error */
248
+ }
249
+ EOT
250
250
  assert_raise(JSON::ParserError) { JSON.parse(json) }
251
- json = <<EOT
252
- {
253
- "key1":"value1" /*/*/
254
- }
255
- EOT
251
+ json = <<~EOT
252
+ {
253
+ "key1":"value1" /*/*/
254
+ }
255
+ EOT
256
256
  assert_equal({ "key1" => "value1" }, JSON.parse(json))
257
257
  end
258
258
 
@@ -269,6 +269,13 @@ EOT
269
269
  assert_equal too_deep_ary, ok
270
270
  ok = JSON.parse too_deep, :max_nesting => 0
271
271
  assert_equal too_deep_ary, ok
272
+
273
+ unless ENV['REAL_JSON_GEM']
274
+ # max_nesting should be reset to 0 if not included in options
275
+ # This behavior is not compatible with Ruby standard JSON gem
276
+ ok = JSON.parse too_deep, {}
277
+ assert_equal too_deep_ary, ok
278
+ end
272
279
  end
273
280
 
274
281
  def test_backslash
@@ -341,7 +348,7 @@ EOT
341
348
 
342
349
  def test_parse_array_custom_array_derived_class
343
350
  res = JSON.parse('[1,2]', :array_class => SubArray)
344
- assert_equal([1,2], res)
351
+ assert_equal([1, 2], res)
345
352
  assert_equal(SubArray, res.class)
346
353
  assert res.shifted?
347
354
  end
@@ -349,7 +356,7 @@ EOT
349
356
  def test_parse_array_custom_non_array_derived_class
350
357
  res = JSON.parse('[1,2]', :array_class => SubArrayWrapper)
351
358
  assert_equal(SubArrayWrapper, res.class)
352
- assert_equal([1,2], res.data)
359
+ assert_equal([1, 2], res.data)
353
360
  assert res.shifted?
354
361
  end
355
362
 
@@ -435,7 +442,7 @@ EOT
435
442
  assert obj_again['foo']['bar']
436
443
  assert_equal obj, obj_again
437
444
  assert_equal ["foo"],
438
- JSON(JSON(SubArray2["foo"]), :create_additions => true)
445
+ JSON(JSON(SubArray2["foo"]), :create_additions => true)
439
446
  end
440
447
 
441
448
  def test_generate_core_subclasses_with_default_to_json
@@ -28,15 +28,15 @@ class JSONStringMatchingTest < Test::Unit::TestCase
28
28
  t_json = [ t ].to_json
29
29
  time_regexp = /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{4}\z/
30
30
  assert_equal [ t ],
31
- JSON.parse(
32
- t_json,
33
- :create_additions => true,
34
- :match_string => { time_regexp => TestTime }
35
- )
31
+ JSON.parse(
32
+ t_json,
33
+ :create_additions => true,
34
+ :match_string => { time_regexp => TestTime }
35
+ )
36
36
  assert_equal [ t.strftime('%FT%T%z') ],
37
- JSON.parse(
38
- t_json,
39
- :match_string => { time_regexp => TestTime }
40
- )
37
+ JSON.parse(
38
+ t_json,
39
+ :match_string => { time_regexp => TestTime }
40
+ )
41
41
  end
42
42
  end
@@ -15,10 +15,14 @@ else
15
15
  require 'oj'
16
16
  Oj.mimic_JSON
17
17
 
18
+ # This method was added in Ruby 3.0.0. Calling it this way asks the GC to
19
+ # move objects around, helping to find object movement bugs.
18
20
  if defined?(GC.verify_compaction_references) == 'method'
19
- # This method was added in Ruby 3.0.0. Calling it this way asks the GC to
20
- # move objects around, helping to find object movement bugs.
21
- GC.verify_compaction_references(double_heap: true, toward: :empty)
21
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.2.0")
22
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
23
+ else
24
+ GC.verify_compaction_references(double_heap: true, toward: :empty)
25
+ end
22
26
  end
23
27
  end
24
28
 
data/test/mem.rb ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'English'
5
+ $LOAD_PATH << '.'
6
+ $LOAD_PATH << File.join(__dir__, '../lib')
7
+ $LOAD_PATH << File.join(__dir__, '../ext')
8
+
9
+ require 'oj'
10
+
11
+ Oj.default_options = { mode: :rails, cache_keys: false, cache_str: -1 }
12
+
13
+ def mem
14
+ `ps -o rss= -p #{$PROCESS_ID}`.to_i
15
+ end
16
+
17
+ ('a'..'z').each { |a|
18
+ ('a'..'z').each { |b|
19
+ ('a'..'z').each { |c|
20
+ ('a'..'z').each { |d|
21
+ ('a'..'z').each { |e|
22
+ ('a'..'z').each { |f|
23
+ key = "#{a}#{b}#{c}#{d}#{e}#{f}"
24
+ Oj.load(%|{ "#{key}": 101}|)
25
+ # Oj.dump(x)
26
+ }
27
+ }
28
+ }
29
+ }
30
+ puts "#{a}#{b} #{mem}"
31
+ }
32
+ }
33
+
34
+ Oj::Parser.new(:usual)
data/test/perf.rb CHANGED
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  class Perf
3
4
 
4
- def initialize()
5
+ def initialize
5
6
  @items = []
6
7
  end
7
8
 
@@ -17,9 +18,9 @@ class Perf
17
18
  end
18
19
  end
19
20
  end
20
-
21
+
21
22
  def run(iter)
22
- base = Item.new(nil, nil) { }
23
+ base = Item.new(nil, nil) {}
23
24
  base.run(iter, 0.0)
24
25
  @items.each do |i|
25
26
  i.run(iter, base.duration)
@@ -32,35 +33,31 @@ class Perf
32
33
  summary()
33
34
  end
34
35
 
35
- def summary()
36
- fastest = nil
37
- slowest = nil
36
+ def summary
38
37
  width = 6
39
38
  @items.each do |i|
40
39
  next if i.duration.nil?
40
+
41
41
  width = i.title.size if width < i.title.size
42
42
  end
43
43
  iva = @items.clone
44
44
  iva.delete_if { |i| i.duration.nil? }
45
45
  iva = iva.sort_by { |i| i.duration }
46
46
  puts
47
- puts "Summary:"
48
- puts "%*s time (secs) rate (ops/sec)" % [width, 'System']
47
+ puts 'Summary:'
48
+ puts '%*s time (secs) rate (ops/sec)' % [width, 'System']
49
49
  puts "#{'-' * width} ----------- --------------"
50
50
  iva.each do |i|
51
- if i.duration.nil?
52
- else
53
- puts "%*s %11.3f %14.3f" % [width, i.title, i.duration, i.rate ]
54
- end
51
+ puts '%*s %11.3f %14.3f' % [width, i.title, i.duration, i.rate ] unless i.duration.nil?
55
52
  end
56
53
  puts
57
54
  puts "Comparison Matrix\n(performance factor, 2.0 means row is twice as fast as column)"
58
- puts ([' ' * width] + iva.map { |i| "%*s" % [width, i.title] }).join(' ')
59
- puts (['-' * width] + iva.map { |i| '-' * width }).join(' ')
55
+ puts ([' ' * width] + iva.map { |i| '%*s' % [width, i.title] }).join(' ')
56
+ puts (['-' * width] + iva.map { |_i| '-' * width }).join(' ')
60
57
  iva.each do |i|
61
- line = ["%*s" % [width, i.title]]
58
+ line = ['%*s' % [width, i.title]]
62
59
  iva.each do |o|
63
- line << "%*.2f" % [width, o.duration / i.duration]
60
+ line << ('%*.2f' % [width, o.duration / i.duration])
64
61
  end
65
62
  puts line.join(' ')
66
63
  end
@@ -90,17 +87,15 @@ class Perf
90
87
  end
91
88
 
92
89
  def run(iter, base)
93
- begin
94
- GC.start
95
- @before.call unless @before.nil?
96
- start = Time.now
97
- iter.times { @blk.call }
98
- @duration = Time.now - start - base
99
- @duration = 0.0 if @duration < 0.0
100
- @rate = iter / @duration
101
- rescue Exception => e
102
- @error = "#{e.class}: #{e.message}"
103
- end
90
+ GC.start
91
+ @before.call unless @before.nil?
92
+ start = Time.now
93
+ iter.times { @blk.call }
94
+ @duration = Time.now - start - base
95
+ @duration = 0.0 if @duration < 0.0
96
+ @rate = iter / @duration
97
+ rescue Exception => e
98
+ @error = "#{e.class}: #{e.message}"
104
99
  end
105
100
 
106
101
  end # Item