oj 3.11.0 → 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 (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1421 -0
  3. data/README.md +20 -5
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +48 -38
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +60 -62
  9. data/ext/oj/cache8.h +8 -7
  10. data/ext/oj/circarray.c +35 -35
  11. data/ext/oj/circarray.h +11 -9
  12. data/ext/oj/code.c +156 -174
  13. data/ext/oj/code.h +19 -18
  14. data/ext/oj/compat.c +140 -197
  15. data/ext/oj/custom.c +737 -879
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +830 -835
  18. data/ext/oj/dump.h +65 -53
  19. data/ext/oj/dump_compat.c +566 -642
  20. data/ext/oj/dump_leaf.c +95 -182
  21. data/ext/oj/dump_object.c +518 -659
  22. data/ext/oj/dump_strict.c +301 -334
  23. data/ext/oj/encode.h +3 -4
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +27 -24
  26. data/ext/oj/err.h +38 -13
  27. data/ext/oj/extconf.rb +23 -7
  28. data/ext/oj/fast.c +1043 -1073
  29. data/ext/oj/intern.c +313 -0
  30. data/ext/oj/intern.h +22 -0
  31. data/ext/oj/mem.c +318 -0
  32. data/ext/oj/mem.h +53 -0
  33. data/ext/oj/mimic_json.c +449 -423
  34. data/ext/oj/object.c +530 -576
  35. data/ext/oj/odd.c +155 -138
  36. data/ext/oj/odd.h +24 -22
  37. data/ext/oj/oj.c +1331 -993
  38. data/ext/oj/oj.h +306 -292
  39. data/ext/oj/parse.c +934 -938
  40. data/ext/oj/parse.h +73 -70
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +101 -0
  43. data/ext/oj/rails.c +795 -845
  44. data/ext/oj/rails.h +7 -7
  45. data/ext/oj/reader.c +132 -140
  46. data/ext/oj/reader.h +67 -78
  47. data/ext/oj/resolve.c +40 -59
  48. data/ext/oj/resolve.h +3 -2
  49. data/ext/oj/rxclass.c +67 -67
  50. data/ext/oj/rxclass.h +11 -9
  51. data/ext/oj/saj.c +441 -480
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +78 -111
  55. data/ext/oj/sparse.c +726 -730
  56. data/ext/oj/stream_writer.c +146 -165
  57. data/ext/oj/strict.c +103 -123
  58. data/ext/oj/string_writer.c +241 -253
  59. data/ext/oj/trace.c +29 -33
  60. data/ext/oj/trace.h +41 -11
  61. data/ext/oj/usual.c +1218 -0
  62. data/ext/oj/usual.h +69 -0
  63. data/ext/oj/util.c +103 -103
  64. data/ext/oj/util.h +3 -2
  65. data/ext/oj/val_stack.c +60 -49
  66. data/ext/oj/val_stack.h +79 -85
  67. data/ext/oj/validate.c +46 -0
  68. data/ext/oj/wab.c +307 -350
  69. data/lib/oj/active_support_helper.rb +1 -3
  70. data/lib/oj/bag.rb +8 -1
  71. data/lib/oj/easy_hash.rb +9 -9
  72. data/lib/oj/error.rb +1 -2
  73. data/lib/oj/json.rb +162 -150
  74. data/lib/oj/mimic.rb +9 -19
  75. data/lib/oj/saj.rb +20 -6
  76. data/lib/oj/schandler.rb +5 -4
  77. data/lib/oj/state.rb +12 -8
  78. data/lib/oj/version.rb +1 -2
  79. data/lib/oj.rb +2 -0
  80. data/pages/Compatibility.md +1 -1
  81. data/pages/InstallOptions.md +20 -0
  82. data/pages/JsonGem.md +15 -0
  83. data/pages/Modes.md +8 -3
  84. data/pages/Options.md +43 -5
  85. data/pages/Parser.md +309 -0
  86. data/pages/Rails.md +14 -2
  87. data/test/_test_active.rb +8 -9
  88. data/test/_test_active_mimic.rb +7 -8
  89. data/test/_test_mimic_rails.rb +17 -20
  90. data/test/activerecord/result_test.rb +12 -8
  91. data/test/activesupport6/encoding_test.rb +63 -28
  92. data/test/{activesupport5 → activesupport7}/abstract_unit.rb +16 -12
  93. data/test/{activesupport5 → activesupport7}/decoding_test.rb +2 -10
  94. data/test/{activesupport5 → activesupport7}/encoding_test.rb +86 -50
  95. data/test/{activesupport5 → activesupport7}/encoding_test_cases.rb +6 -0
  96. data/test/{activesupport5 → activesupport7}/time_zone_test_helpers.rb +8 -0
  97. data/test/files.rb +15 -15
  98. data/test/foo.rb +17 -43
  99. data/test/helper.rb +16 -3
  100. data/test/isolated/shared.rb +3 -2
  101. data/test/json_gem/json_addition_test.rb +2 -2
  102. data/test/json_gem/json_common_interface_test.rb +8 -6
  103. data/test/json_gem/json_encoding_test.rb +0 -0
  104. data/test/json_gem/json_ext_parser_test.rb +1 -0
  105. data/test/json_gem/json_fixtures_test.rb +3 -2
  106. data/test/json_gem/json_generator_test.rb +71 -41
  107. data/test/json_gem/json_generic_object_test.rb +11 -11
  108. data/test/json_gem/json_parser_test.rb +54 -47
  109. data/test/json_gem/json_string_matching_test.rb +9 -9
  110. data/test/json_gem/test_helper.rb +12 -0
  111. data/test/mem.rb +34 -0
  112. data/test/perf.rb +22 -27
  113. data/test/perf_compat.rb +31 -33
  114. data/test/perf_dump.rb +50 -0
  115. data/test/perf_fast.rb +80 -82
  116. data/test/perf_file.rb +27 -29
  117. data/test/perf_object.rb +65 -69
  118. data/test/perf_once.rb +59 -0
  119. data/test/perf_parser.rb +183 -0
  120. data/test/perf_saj.rb +46 -54
  121. data/test/perf_scp.rb +58 -69
  122. data/test/perf_simple.rb +41 -39
  123. data/test/perf_strict.rb +74 -82
  124. data/test/perf_wab.rb +67 -69
  125. data/test/prec.rb +5 -5
  126. data/test/sample/change.rb +0 -1
  127. data/test/sample/dir.rb +0 -1
  128. data/test/sample/doc.rb +0 -1
  129. data/test/sample/file.rb +0 -1
  130. data/test/sample/group.rb +0 -1
  131. data/test/sample/hasprops.rb +0 -1
  132. data/test/sample/layer.rb +0 -1
  133. data/test/sample/rect.rb +0 -1
  134. data/test/sample/shape.rb +0 -1
  135. data/test/sample/text.rb +0 -1
  136. data/test/sample.rb +16 -16
  137. data/test/sample_json.rb +8 -8
  138. data/test/test_compat.rb +97 -45
  139. data/test/test_custom.rb +73 -51
  140. data/test/test_debian.rb +7 -10
  141. data/test/test_fast.rb +135 -79
  142. data/test/test_file.rb +41 -30
  143. data/test/test_gc.rb +16 -5
  144. data/test/test_generate.rb +21 -0
  145. data/test/test_hash.rb +15 -5
  146. data/test/test_integer_range.rb +9 -9
  147. data/test/test_null.rb +20 -20
  148. data/test/test_object.rb +99 -96
  149. data/test/test_parser.rb +11 -0
  150. data/test/test_parser_debug.rb +27 -0
  151. data/test/test_parser_saj.rb +337 -0
  152. data/test/test_parser_usual.rb +251 -0
  153. data/test/test_rails.rb +2 -2
  154. data/test/test_saj.rb +10 -8
  155. data/test/test_scp.rb +38 -40
  156. data/test/test_strict.rb +40 -32
  157. data/test/test_various.rb +165 -84
  158. data/test/test_wab.rb +48 -44
  159. data/test/test_writer.rb +47 -47
  160. data/test/tests.rb +13 -5
  161. data/test/tests_mimic.rb +12 -3
  162. data/test/tests_mimic_addition.rb +12 -3
  163. metadata +75 -127
  164. data/ext/oj/hash.c +0 -135
  165. data/ext/oj/hash.h +0 -18
  166. data/ext/oj/hash_test.c +0 -484
  167. data/test/activesupport4/decoding_test.rb +0 -108
  168. data/test/activesupport4/encoding_test.rb +0 -531
  169. data/test/activesupport4/test_helper.rb +0 -41
  170. data/test/activesupport5/test_helper.rb +0 -72
  171. data/test/bar.rb +0 -35
  172. data/test/baz.rb +0 -16
  173. data/test/zoo.rb +0 -13
data/test/foo.rb CHANGED
@@ -1,52 +1,26 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- $: << File.dirname(__FILE__)
4
- $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
5
- %w(lib ext).each do |dir|
6
- $: << File.join($oj_dir, dir)
7
- end
8
-
9
- require 'json'
10
-
11
- t = [Time.now.utc]
12
-
13
- puts "t.to_json - #{t.to_json}"
14
-
15
- puts "--- active support"
16
-
17
- require 'active_support'
18
- require "active_support/json"
19
-
20
- ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
21
-
22
- puts "t.as_json - #{t.as_json}"
23
- puts "t.to_json - #{t.to_json}"
4
+ $LOAD_PATH << '.'
5
+ $LOAD_PATH << File.join(__dir__, '../lib')
6
+ $LOAD_PATH << File.join(__dir__, '../ext')
24
7
 
25
8
  require 'oj'
26
9
 
27
- t = [Time.now.utc]
28
-
29
- puts "-----------------------"
30
-
31
- #puts "t.as_json - #{t.as_json}"
32
- puts "t.to_json - #{t.to_json}"
33
-
34
- #Oj.mimic_JSON
35
-
36
- #puts "Oj - t.as_json - #{t.as_json}"
37
-
38
- puts "--- active support"
39
-
40
- require 'active_support'
41
- require "active_support/json"
10
+ reader, writer = IO.pipe
42
11
 
43
- ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
12
+ thread =
13
+ Thread.new do
14
+ 5.times do |id|
15
+ Oj.to_stream(writer, { "id" => id })
16
+ sleep(1)
17
+ end
44
18
 
45
- puts "t.as_json - #{t.as_json}"
46
- puts "t.to_json - #{t.to_json}"
19
+ writer.close
20
+ end
47
21
 
48
- puts "--- optimize"
49
- Oj.optimize_rails
22
+ p = Oj::Parser.new(:usual)
23
+ p.load(reader) { |data| puts "#{Time.now} -- ID: #{data["id"]}" }
50
24
 
51
- puts "t.as_json - #{t.as_json}"
52
- puts "t.to_json - #{t.to_json}"
25
+ reader.close
26
+ thread.join
data/test/helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
2
4
  # required. That can be set in the RUBYOPT environment variable.
3
5
  # export RUBYOPT=-w
@@ -13,14 +15,25 @@ require 'minitest/autorun'
13
15
  require 'stringio'
14
16
  require 'date'
15
17
  require 'bigdecimal'
16
- require 'pp'
17
18
  require 'oj'
18
19
 
20
+ def verify_gc_compaction
21
+ # This method was added in Ruby 3.0.0. Calling it this way asks the GC to
22
+ # move objects around, helping to find object movement bugs.
23
+ if defined?(GC.verify_compaction_references) == 'method' && RbConfig::CONFIG['host_os'] !~ /(mingw|mswin)/
24
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.2.0')
25
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
26
+ else
27
+ GC.verify_compaction_references(double_heap: true, toward: :empty)
28
+ end
29
+ end
30
+ end
31
+
19
32
  $ruby = RUBY_DESCRIPTION.split(' ')[0]
20
33
  $ruby = 'ree' if 'ruby' == $ruby && RUBY_DESCRIPTION.include?('Ruby Enterprise Edition')
21
34
 
22
35
  class Range
23
- def to_hash()
24
- { 'begin' => self.begin, 'end' => self.end, 'exclude_end' => self.exclude_end? }
36
+ def to_hash
37
+ { 'begin' => self.begin, 'end' => self.end, 'exclude_end' => exclude_end? }
25
38
  end
26
39
  end
@@ -21,7 +21,7 @@ class SharedMimicTest < Minitest::Test
21
21
  alias == eql?
22
22
 
23
23
  def as_json()
24
- {"json_class" => self.class.to_s,"x" => @x,"y" => @y}
24
+ {"json_class" => self.class.to_s, "x" => @x, "y" => @y}
25
25
  end
26
26
 
27
27
  def self.json_create(h)
@@ -207,7 +207,6 @@ class SharedMimicTest < Minitest::Test
207
207
  --],#
208
208
  --"a"~:*1#
209
209
  }} == json)
210
-
211
210
  end
212
211
 
213
212
  # fast_generate
@@ -261,6 +260,8 @@ class SharedMimicTest < Minitest::Test
261
260
  obj = JSON.parse(json, :create_additions => true)
262
261
  JSON.create_id = 'json_class'
263
262
  assert_equal(jam, obj)
263
+
264
+ assert_nothing_raised { JSON.create_id = nil }
264
265
  end
265
266
  def test_parse_bang
266
267
  json = %{{"a":1,"b":[true,false]}}
@@ -191,9 +191,9 @@ class JSONAdditionTest < Test::Unit::TestCase
191
191
  assert_equal d, JSON.parse(d.to_json, :create_additions => true)
192
192
  d = DateTime.parse(now.utc.to_s) # of = 0
193
193
  assert_equal d, JSON.parse(d.to_json, :create_additions => true)
194
- d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(1,24))
194
+ d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(1, 24))
195
195
  assert_equal d, JSON.parse(d.to_json, :create_additions => true)
196
- d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(12,24))
196
+ d = DateTime.civil(2008, 6, 17, 11, 48, 32, Rational(12, 24))
197
197
  assert_equal d, JSON.parse(d.to_json, :create_additions => true)
198
198
  end
199
199
 
@@ -29,7 +29,7 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
29
29
  #@json = '{"a":2,"b":5.23683071,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
30
30
  #'"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
31
31
  @json = '{"a":2,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},'\
32
- '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
32
+ '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
33
33
  end
34
34
 
35
35
  def test_index
@@ -43,15 +43,15 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
43
43
  # functionality and perform better.
44
44
 
45
45
  def test_parser
46
- assert_match /::Parser\z/, JSON.parser.name
46
+ assert_match(/::Parser\z/, JSON.parser.name)
47
47
  end
48
48
 
49
49
  def test_generator
50
- assert_match /::Generator\z/, JSON.generator.name
50
+ assert_match(/::Generator\z/, JSON.generator.name)
51
51
  end
52
52
 
53
53
  def test_state
54
- assert_match /::Generator::State\z/, JSON.state.name
54
+ assert_match(/::Generator::State\z/, JSON.state.name)
55
55
  end
56
56
 
57
57
  # This doesn't have anything to do with JSON parsing or generation. It seems
@@ -128,8 +128,10 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
128
128
  too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
129
129
  assert_equal too_deep, JSON.dump(eval(too_deep))
130
130
  assert_kind_of String, Marshal.dump(eval(too_deep))
131
- assert_raise(ArgumentError) { JSON.dump(eval(too_deep), 100) }
132
- assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
131
+ if RUBY_ENGINE != 'truffleruby'
132
+ assert_raise(ArgumentError) { JSON.dump(eval(too_deep), 100) }
133
+ assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
134
+ end
133
135
  assert_equal too_deep, JSON.dump(eval(too_deep), 101)
134
136
  assert_kind_of String, Marshal.dump(eval(too_deep), 101)
135
137
  output = StringIO.new
File without changes
@@ -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 JSONExtParserTest < Test::Unit::TestCase
@@ -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
@@ -136,6 +138,12 @@ EOT
136
138
 
137
139
  def test_pretty_state
138
140
  state = JSON::PRETTY_STATE_PROTOTYPE.dup
141
+ # In come cases in Ruby 3.0 an :escape_slash is included in the state. It
142
+ # seems to occur on travis but not locally.
143
+ actual = state.to_h
144
+ actual.delete(:escape_slash)
145
+ actual.delete(:strict)
146
+ actual.delete(:script_safe)
139
147
  assert_equal({
140
148
  :allow_nan => false,
141
149
  :array_nl => "\n",
@@ -147,11 +155,17 @@ EOT
147
155
  :object_nl => "\n",
148
156
  :space => " ",
149
157
  :space_before => "",
150
- }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
158
+ }.sort_by { |n,| n.to_s }, actual.sort_by { |n,| n.to_s })
151
159
  end
152
160
 
153
161
  def test_safe_state
154
162
  state = JSON::SAFE_STATE_PROTOTYPE.dup
163
+ # In come cases in Ruby 3.0 an :escape_slash is included in the state. It
164
+ # seems to occur on travis but not locally.
165
+ actual = state.to_h
166
+ actual.delete(:escape_slash)
167
+ actual.delete(:strict)
168
+ actual.delete(:script_safe)
155
169
  assert_equal({
156
170
  :allow_nan => false,
157
171
  :array_nl => "",
@@ -163,11 +177,17 @@ EOT
163
177
  :object_nl => "",
164
178
  :space => "",
165
179
  :space_before => "",
166
- }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
180
+ }.sort_by { |n,| n.to_s }, actual.sort_by { |n,| n.to_s })
167
181
  end
168
182
 
169
183
  def test_fast_state
170
184
  state = JSON::FAST_STATE_PROTOTYPE.dup
185
+ # In come cases in Ruby 3.0 an :escape_slash is included in the state. It
186
+ # seems to occur on travis but not locally.
187
+ actual = state.to_h
188
+ actual.delete(:escape_slash)
189
+ actual.delete(:strict)
190
+ actual.delete(:script_safe)
171
191
  assert_equal({
172
192
  :allow_nan => false,
173
193
  :array_nl => "",
@@ -179,7 +199,7 @@ EOT
179
199
  :object_nl => "",
180
200
  :space => "",
181
201
  :space_before => "",
182
- }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
202
+ }.sort_by { |n,| n.to_s }, actual.sort_by { |n,| n.to_s })
183
203
  end
184
204
 
185
205
  def test_allow_nan
@@ -280,7 +300,9 @@ EOT
280
300
  assert_equal '2', state.indent
281
301
  end
282
302
 
283
- 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
284
306
  def test_broken_bignum # [ruby-core:38867]
285
307
  pid = fork do
286
308
  x = 1 << 64
@@ -297,9 +319,6 @@ EOT
297
319
  end
298
320
  _, status = Process.waitpid2(pid)
299
321
  assert status.success?
300
- rescue NotImplementedError
301
- # forking to avoid modifying core class of a parent process and
302
- # introducing race conditions of tests are run in parallel
303
322
  end
304
323
  end
305
324
 
@@ -339,7 +358,7 @@ EOT
339
358
  too_deep_ary = eval too_deep
340
359
  assert_raise(JSON::NestingError) { JSON.generate too_deep_ary }
341
360
  assert_raise(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 100 }
342
- ok = JSON.generate too_deep_ary, :max_nesting => 101
361
+ ok = JSON.generate too_deep_ary, :max_nesting => 102
343
362
  assert_equal too_deep, ok
344
363
  ok = JSON.generate too_deep_ary, :max_nesting => nil
345
364
  assert_equal too_deep, ok
@@ -380,4 +399,15 @@ EOT
380
399
  assert_equal '["foo"]', JSON.generate([s.new('foo')])
381
400
  end
382
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
383
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