oj 3.13.11 → 3.13.23

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -0
  3. data/README.md +2 -0
  4. data/ext/oj/buf.h +4 -0
  5. data/ext/oj/circarray.c +1 -1
  6. data/ext/oj/code.c +15 -22
  7. data/ext/oj/compat.c +10 -10
  8. data/ext/oj/custom.c +62 -108
  9. data/ext/oj/dump.c +85 -97
  10. data/ext/oj/dump.h +12 -8
  11. data/ext/oj/dump_compat.c +46 -88
  12. data/ext/oj/dump_leaf.c +14 -58
  13. data/ext/oj/dump_object.c +33 -156
  14. data/ext/oj/dump_strict.c +17 -29
  15. data/ext/oj/extconf.rb +5 -4
  16. data/ext/oj/fast.c +24 -22
  17. data/ext/oj/intern.c +15 -11
  18. data/ext/oj/intern.h +1 -1
  19. data/ext/oj/mimic_json.c +44 -32
  20. data/ext/oj/object.c +42 -41
  21. data/ext/oj/odd.c +83 -63
  22. data/ext/oj/odd.h +13 -13
  23. data/ext/oj/oj.c +57 -22
  24. data/ext/oj/oj.h +24 -3
  25. data/ext/oj/parse.c +114 -78
  26. data/ext/oj/parse.h +2 -0
  27. data/ext/oj/parser.c +77 -21
  28. data/ext/oj/parser.h +12 -0
  29. data/ext/oj/rails.c +41 -65
  30. data/ext/oj/rails.h +1 -1
  31. data/ext/oj/reader.c +2 -0
  32. data/ext/oj/saj.c +11 -23
  33. data/ext/oj/saj2.c +333 -85
  34. data/ext/oj/saj2.h +23 -0
  35. data/ext/oj/sparse.c +4 -0
  36. data/ext/oj/stream_writer.c +3 -1
  37. data/ext/oj/strict.c +13 -13
  38. data/ext/oj/string_writer.c +12 -5
  39. data/ext/oj/usual.c +82 -129
  40. data/ext/oj/usual.h +68 -0
  41. data/ext/oj/val_stack.c +1 -1
  42. data/ext/oj/validate.c +21 -26
  43. data/ext/oj/wab.c +21 -26
  44. data/lib/oj/saj.rb +20 -6
  45. data/lib/oj/state.rb +1 -1
  46. data/lib/oj/version.rb +1 -1
  47. data/pages/Compatibility.md +1 -1
  48. data/pages/Options.md +6 -0
  49. data/test/activesupport7/abstract_unit.rb +49 -0
  50. data/test/activesupport7/decoding_test.rb +125 -0
  51. data/test/activesupport7/encoding_test.rb +486 -0
  52. data/test/activesupport7/encoding_test_cases.rb +104 -0
  53. data/test/activesupport7/time_zone_test_helpers.rb +47 -0
  54. data/test/bar.rb +3 -8
  55. data/test/foo.rb +3 -3
  56. data/test/helper.rb +8 -2
  57. data/test/json_gem/json_generator_test.rb +5 -4
  58. data/test/json_gem/json_parser_test.rb +8 -1
  59. data/test/json_gem/test_helper.rb +7 -3
  60. data/test/perf_dump.rb +50 -0
  61. data/test/test_compat.rb +25 -0
  62. data/test/test_custom.rb +13 -2
  63. data/test/test_file.rb +23 -7
  64. data/test/test_gc.rb +11 -0
  65. data/test/test_object.rb +8 -10
  66. data/test/test_parser.rb +3 -19
  67. data/test/test_parser_debug.rb +27 -0
  68. data/test/test_parser_saj.rb +92 -2
  69. data/test/test_scp.rb +2 -4
  70. data/test/test_strict.rb +2 -0
  71. data/test/test_various.rb +8 -3
  72. data/test/test_wab.rb +2 -0
  73. data/test/tests.rb +9 -0
  74. data/test/tests_mimic.rb +9 -0
  75. data/test/tests_mimic_addition.rb +9 -0
  76. metadata +13 -116
data/test/helper.rb CHANGED
@@ -19,10 +19,16 @@ require 'pp'
19
19
  require 'oj'
20
20
 
21
21
 
22
- if defined?(GC.verify_compaction_references) == 'method'
22
+ def verify_gc_compaction
23
23
  # This method was added in Ruby 3.0.0. Calling it this way asks the GC to
24
24
  # move objects around, helping to find object movement bugs.
25
- GC.verify_compaction_references(double_heap: true, toward: :empty)
25
+ if defined?(GC.verify_compaction_references) == 'method' && !(RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/)
26
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.2.0")
27
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
28
+ else
29
+ GC.verify_compaction_references(double_heap: true, toward: :empty)
30
+ end
31
+ end
26
32
  end
27
33
 
28
34
 
@@ -72,6 +72,8 @@ 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
@@ -292,7 +294,9 @@ EOT
292
294
  assert_equal '2', state.indent
293
295
  end
294
296
 
295
- if defined?(JSON::Ext::Generator)
297
+ if defined?(JSON::Ext::Generator) && Process.respond_to?(:fork)
298
+ # forking to avoid modifying core class of a parent process and
299
+ # introducing race conditions of tests are run in parallel
296
300
  def test_broken_bignum # [ruby-core:38867]
297
301
  pid = fork do
298
302
  x = 1 << 64
@@ -309,9 +313,6 @@ EOT
309
313
  end
310
314
  _, status = Process.waitpid2(pid)
311
315
  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
316
  end
316
317
  end
317
318
 
@@ -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"')
@@ -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
@@ -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/perf_dump.rb ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << '.'
5
+ $: << File.join(File.dirname(__FILE__), "../lib")
6
+ $: << File.join(File.dirname(__FILE__), "../ext")
7
+
8
+ require 'optparse'
9
+ require 'oj'
10
+
11
+ $verbose = false
12
+ $indent = 2
13
+ $iter = 100_000
14
+ $size = 2
15
+
16
+ opts = OptionParser.new
17
+ opts.on("-v", "verbose") { $verbose = true }
18
+ opts.on("-c", "--count [Int]", Integer, "iterations") { |i| $iter = i }
19
+ opts.on("-i", "--indent [Int]", Integer, "indentation") { |i| $indent = i }
20
+ opts.on("-s", "--size [Int]", Integer, "size (~Kbytes)") { |i| $size = i }
21
+ opts.on("-h", "--help", "Show this display") { puts opts; Process.exit!(0) }
22
+ files = opts.parse(ARGV)
23
+
24
+ $obj = {
25
+ 'a' => 'Alpha', # string
26
+ 'b' => true, # boolean
27
+ 'c' => 12345, # number
28
+ 'd' => [ true, [false, [-123456789, nil], 3.9676, ['Something else.', false], nil]], # mix it up array
29
+ 'e' => { 'zero' => nil, 'one' => 1, 'two' => 2, 'three' => [3], 'four' => [0, 1, 2, 3, 4] }, # hash
30
+ 'f' => nil, # nil
31
+ 'h' => { 'a' => { 'b' => { 'c' => { 'd' => {'e' => { 'f' => { 'g' => nil }}}}}}}, # deep hash, not that deep
32
+ 'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
33
+ }
34
+
35
+ Oj.default_options = { :indent => $indent, :mode => :strict }
36
+
37
+ if 0 < $size
38
+ o = $obj
39
+ $obj = []
40
+ (4 * $size).times do
41
+ $obj << o
42
+ end
43
+ end
44
+
45
+ $json = Oj.dump($obj)
46
+ GC.start
47
+ start = Time.now
48
+ $iter.times { Oj.dump($obj) }
49
+ duration = Time.now - start
50
+ puts "Dumped #{$json.length} byte JSON #{$iter} times in %0.3f seconds or %0.3f iteration/sec." % [duration, $iter / duration]
data/test/test_compat.rb CHANGED
@@ -488,6 +488,31 @@ class CompatJuice < Minitest::Test
488
488
  assert_equal([1,2], Oj.load(s, :mode => :compat))
489
489
  end
490
490
 
491
+ def test_parse_large_string
492
+ error = assert_raises() { Oj.load(%|{"a":"aaaaaaaaaa\0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}|) }
493
+ assert(error.message.include?('NULL byte in string'))
494
+
495
+ error = assert_raises() { Oj.load(%|{"a":"aaaaaaaaaaaaaaaaaaaa }|) }
496
+ assert(error.message.include?('quoted string not terminated'))
497
+
498
+ json =<<~JSON
499
+ {
500
+ "a": "\\u3074\\u30fc\\u305f\\u30fc",
501
+ "b": "aaaaaaaaaaaaaaaaaaaaaaaaaaaa"
502
+ }
503
+ JSON
504
+ assert_equal("ぴーたー", Oj.load(json)['a'])
505
+ end
506
+
507
+ def test_parse_large_escaped_string
508
+ invalid_json = %|{"a":\"aaaa\\nbbbb\\rcccc\\tddd\\feee\\bf\/\\\\\\u3074\\u30fc\\u305f\\u30fc }|
509
+ error = assert_raises() { Oj.load(invalid_json) }
510
+ assert(error.message.include?('quoted string not terminated'))
511
+
512
+ json = "\"aaaa\\nbbbb\\rcccc\\tddd\\feee\\bf\/\\\\\\u3074\\u30fc\\u305f\\u30fc \""
513
+ assert_equal("aaaa\nbbbb\rcccc\tddd\feee\bf/\\ぴーたー ", Oj.load(json))
514
+ end
515
+
491
516
  def dump_and_load(obj, trace=false)
492
517
  json = Oj.dump(obj)
493
518
  puts json if trace
data/test/test_custom.rb CHANGED
@@ -200,6 +200,8 @@ class CustomJuice < Minitest::Test
200
200
  end
201
201
 
202
202
  def test_deep_nest
203
+ skip 'TruffleRuby causes SEGV' if RUBY_ENGINE == 'truffleruby'
204
+
203
205
  begin
204
206
  n = 10000
205
207
  Oj.strict_load('[' * n + ']' * n)
@@ -480,9 +482,18 @@ class CustomJuice < Minitest::Test
480
482
  end
481
483
 
482
484
  def test_time
485
+ skip 'TruffleRuby fails this spec' if RUBY_ENGINE == 'truffleruby'
486
+
483
487
  obj = Time.now()
484
- dump_load_dump(obj, false, :time_format => :unix, :create_id => "^o", :create_additions => true)
485
- dump_load_dump(obj, false, :time_format => :unix_zone, :create_id => "^o", :create_additions => true)
488
+ # These two forms should be able to recreate the time precisely,
489
+ # so we check they can load a dumped version and recreate the
490
+ # original object correctly.
491
+ dump_and_load(obj, false, :time_format => :unix, :create_id => "^o", :create_additions => true)
492
+ dump_and_load(obj, false, :time_format => :unix_zone, :create_id => "^o", :create_additions => true)
493
+ # These two forms will lose precision while dumping as they don't
494
+ # preserve full precision. We check that a dumped version is equal
495
+ # to that version loaded and dumped a second time, but don't check
496
+ # that the loaded Ruby objects is still the same as the original.
486
497
  dump_load_dump(obj, false, :time_format => :xmlschema, :create_id => "^o", :create_additions => true)
487
498
  dump_load_dump(obj, false, :time_format => :ruby, :create_id => "^o", :create_additions => true)
488
499
  end
data/test/test_file.rb CHANGED
@@ -130,8 +130,8 @@ class FileJuice < Minitest::Test
130
130
  dump_and_load(t, false)
131
131
  end
132
132
  def test_time_object_early
133
- # Windows does not support dates before 1970.
134
- return if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
133
+ skip 'Windows does not support dates before 1970.' if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
134
+
135
135
  t = Time.xmlschema("1954-01-05T00:00:00.123456")
136
136
  Oj.default_options = { :mode => :object, :time_format => :unix_zone }
137
137
  dump_and_load(t, false)
@@ -162,12 +162,10 @@ class FileJuice < Minitest::Test
162
162
  def test_range_object
163
163
  Oj.default_options = { :mode => :object }
164
164
  json = Oj.dump(1..7, :mode => :object, :indent => 0)
165
- if 'rubinius' == $ruby
166
- assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
167
- elsif 'jruby' == $ruby
168
- assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
169
- else
165
+ if $ruby == 'ruby'
170
166
  assert_equal(%{{"^u":["Range",1,7,false]}}, json)
167
+ else
168
+ assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
171
169
  end
172
170
  dump_and_load(1..7, false)
173
171
  dump_and_load(1..1, false)
@@ -212,6 +210,24 @@ class FileJuice < Minitest::Test
212
210
  dump_and_load(DateTime.new(2012, 6, 19), false)
213
211
  end
214
212
 
213
+ def test_load_unicode_path
214
+ json =<<~JSON
215
+ {
216
+ "x":true,
217
+ "y":58,
218
+ "z": [1,2,3]
219
+ }
220
+ JSON
221
+
222
+ Tempfile.create('file_test_conceição1.json') do |f|
223
+ f.write(json)
224
+ f.close
225
+
226
+ objects = Oj.load_file(f.path)
227
+ assert_equal(Oj.load(json), objects)
228
+ end
229
+ end
230
+
215
231
  def dump_and_load(obj, trace=false)
216
232
  filename = File.join(File.dirname(__FILE__), 'file_test.json')
217
233
  File.open(filename, "w") { |f|
data/test/test_gc.rb CHANGED
@@ -26,10 +26,12 @@ class GCTest < Minitest::Test
26
26
 
27
27
  def setup
28
28
  @default_options = Oj.default_options
29
+ GC.stress = true
29
30
  end
30
31
 
31
32
  def teardown
32
33
  Oj.default_options = @default_options
34
+ GC.stress = false
33
35
  end
34
36
 
35
37
  # if no crash then the GC marking is working
@@ -46,4 +48,13 @@ class GCTest < Minitest::Test
46
48
  json = Oj.dump(g, :mode => :object)
47
49
  Oj.object_load(json)
48
50
  end
51
+
52
+ def test_parse_gc
53
+ json = '{"a":"Alpha","b":true,"c":12345,"d":[true,[false,[-123456789,null],3.9676,["Something else.",false],null]],"e":{"zero":null,"one":1,"two":2,"three":[3],"four":[0,1,2,3,4]},"f":null,"h":{"a":{"b":{"c":{"d":{"e":{"f":{"g":null}}}}}}},"i":[[[[[[[null]]]]]]]}'
54
+
55
+ 50.times do
56
+ data = Oj.load(json)
57
+ assert_equal(json, Oj.dump(data))
58
+ end
59
+ end
49
60
  end
data/test/test_object.rb CHANGED
@@ -821,10 +821,10 @@ class ObjectJuice < Minitest::Test
821
821
  def test_range_object
822
822
  Oj.default_options = { :mode => :object }
823
823
  json = Oj.dump(1..7, :mode => :object, :indent => 0)
824
- if 'rubinius' == $ruby
825
- assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
826
- else
824
+ if 'ruby' == $ruby
827
825
  assert_equal(%{{"^u":["Range",1,7,false]}}, json)
826
+ else
827
+ assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
828
828
  end
829
829
  dump_and_load(1..7, false)
830
830
  dump_and_load(1..1, false)
@@ -948,6 +948,11 @@ class ObjectJuice < Minitest::Test
948
948
 
949
949
  def test_odd_date
950
950
  dump_and_load(Date.new(2012, 6, 19), false)
951
+
952
+ Oj.register_odd(Date, Date, :jd, :jd)
953
+ json = Oj.dump(Date.new(2015, 3, 7), :mode => :object)
954
+ assert_equal(%|{"^O":"Date","jd":2457089}|, json)
955
+ dump_and_load(Date.new(2012, 6, 19), false)
951
956
  end
952
957
 
953
958
  def test_odd_datetime
@@ -972,13 +977,6 @@ class ObjectJuice < Minitest::Test
972
977
  dump_and_load(s, false)
973
978
  end
974
979
 
975
- def test_odd_date_replaced
976
- Oj.register_odd(Date, Date, :jd, :jd)
977
- json = Oj.dump(Date.new(2015, 3, 7), :mode => :object)
978
- assert_equal(%|{"^O":"Date","jd":2457089}|, json)
979
- dump_and_load(Date.new(2012, 6, 19), false)
980
- end
981
-
982
980
  def test_odd_raw
983
981
  Oj.register_odd_raw(Raw, Raw, :create, :to_json)
984
982
  json = Oj.dump(Raw.new(%|{"a":1}|), :mode => :object)
data/test/test_parser.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: utf-8
2
+ # encoding: UTF-8
3
3
 
4
4
  $: << File.dirname(__FILE__)
5
5
  $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
@@ -7,21 +7,5 @@ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
7
7
  $: << File.join($oj_dir, dir)
8
8
  end
9
9
 
10
- require 'minitest'
11
- require 'minitest/autorun'
12
- require 'stringio'
13
- require 'date'
14
- require 'bigdecimal'
15
- require 'oj'
16
-
17
- class ParserJuice < Minitest::Test
18
-
19
- def test_array
20
- p = Oj::Parser.new(:debug)
21
- out = p.parse(%|[true, false, null, 123, -1.23, "abc"]|)
22
- puts out
23
- out = p.parse(%|{"abc": []}|)
24
- puts out
25
- end
26
-
27
- end
10
+ require 'test_parser_usual'
11
+ require 'test_parser_saj'
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
6
+ %w(lib ext).each do |dir|
7
+ $: << File.join($oj_dir, dir)
8
+ end
9
+
10
+ require 'minitest'
11
+ require 'minitest/autorun'
12
+ require 'stringio'
13
+ require 'date'
14
+ require 'bigdecimal'
15
+ require 'oj'
16
+
17
+ class ParserJuice < Minitest::Test
18
+
19
+ def test_array
20
+ p = Oj::Parser.new(:debug)
21
+ out = p.parse(%|[true, false, null, 123, -1.23, "abc"]|)
22
+ puts out
23
+ out = p.parse(%|{"abc": []}|)
24
+ puts out
25
+ end
26
+
27
+ end
@@ -5,7 +5,7 @@ $: << File.dirname(__FILE__)
5
5
 
6
6
  require 'helper'
7
7
 
8
- $json = %{{
8
+ $json = %|{
9
9
  "array": [
10
10
  {
11
11
  "num" : 3,
@@ -18,7 +18,7 @@ $json = %{{
18
18
  }
19
19
  ],
20
20
  "boolean" : true
21
- }}
21
+ }|
22
22
 
23
23
  class AllSaj < Oj::Saj
24
24
  attr_accessor :calls
@@ -53,6 +53,35 @@ class AllSaj < Oj::Saj
53
53
 
54
54
  end # AllSaj
55
55
 
56
+ class LocSaj
57
+ attr_accessor :calls
58
+
59
+ def initialize()
60
+ @calls = []
61
+ end
62
+
63
+ def hash_start(key, line, column)
64
+ @calls << [:hash_start, key, line, column]
65
+ end
66
+
67
+ def hash_end(key, line, column)
68
+ @calls << [:hash_end, key, line, column]
69
+ end
70
+
71
+ def array_start(key, line, column)
72
+ @calls << [:array_start, key, line, column]
73
+ end
74
+
75
+ def array_end(key, line, column)
76
+ @calls << [:array_end, key, line, column]
77
+ end
78
+
79
+ def add_value(value, key, line, column)
80
+ @calls << [:add_value, value, key, line, column]
81
+ end
82
+
83
+ end # LocSaj
84
+
56
85
  class SajTest < Minitest::Test
57
86
 
58
87
  def test_nil
@@ -120,6 +149,43 @@ class SajTest < Minitest::Test
120
149
  assert_equal((12345.6789e7 * 10000).to_i, (handler.calls[0][1] * 10000).to_i)
121
150
  end
122
151
 
152
+ def test_bignum
153
+ handler = AllSaj.new()
154
+ json = %{-11.899999999999999}
155
+ p = Oj::Parser.new(:saj)
156
+ p.handler = handler
157
+ p.parse(json)
158
+ assert_equal(1, handler.calls.size)
159
+ assert_equal(:add_value, handler.calls[0][0])
160
+ assert_equal(-118999, (handler.calls[0][1] * 10000).to_i)
161
+ end
162
+
163
+ def test_bignum_loc
164
+ handler = LocSaj.new()
165
+ json = <<~JSON
166
+ {
167
+ "width": 192.33800000000002,
168
+ "xaxis": {
169
+ "anchor": "y"
170
+ }
171
+ }
172
+ JSON
173
+
174
+ p = Oj::Parser.new(:saj)
175
+ p.handler = handler
176
+ p.parse(json)
177
+ assert_equal(6, handler.calls.size)
178
+ assert_equal(1_923_380, (handler.calls[1][1] * 10000).to_i)
179
+ handler.calls[1][1] = 1_923_380
180
+ assert_equal([[:hash_start, nil, 1, 1],
181
+ [:add_value, 1923380, 'width', 2, 30],
182
+ [:hash_start, 'xaxis', 3, 12],
183
+ [:add_value, 'y', 'anchor', 4, 17],
184
+ [:hash_end, 'xaxis', 5, 3],
185
+ [:hash_end, nil, 6, 1]],
186
+ handler.calls)
187
+ end
188
+
123
189
  def test_array_empty
124
190
  handler = AllSaj.new()
125
191
  json = %{[]}
@@ -242,4 +308,28 @@ class SajTest < Minitest::Test
242
308
  ], handler.calls)
243
309
  end
244
310
 
311
+ def test_loc
312
+ handler = LocSaj.new()
313
+ Oj::Parser.saj.handler = handler
314
+ Oj::Parser.saj.parse($json)
315
+ assert_equal([[:hash_start, nil, 1, 1],
316
+ [:array_start, 'array', 2, 12],
317
+ [:hash_start, nil, 3, 5],
318
+ [:add_value, 3, 'num', 4, 18],
319
+ [:add_value, 'message', 'string', 5, 25],
320
+ [:hash_start, 'hash', 6, 17],
321
+ [:hash_start, 'h2', 7, 17],
322
+ [:array_start, 'a', 8, 17],
323
+ [:add_value, 1, nil, 8, 20],
324
+ [:add_value, 2, nil, 8, 23],
325
+ [:add_value, 3, nil, 8, 26],
326
+ [:array_end, 'a', 8, 27],
327
+ [:hash_end, 'h2', 9, 9],
328
+ [:hash_end, 'hash', 10, 7],
329
+ [:hash_end, nil, 11, 5],
330
+ [:array_end, 'array', 12, 3],
331
+ [:add_value, true, 'boolean', 13, 18],
332
+ [:hash_end, nil, 14, 1]], handler.calls)
333
+ end
334
+
245
335
  end
data/test/test_scp.rb CHANGED
@@ -320,8 +320,7 @@ class ScpTest < Minitest::Test
320
320
  end
321
321
 
322
322
  def test_pipe
323
- # Windows does not support fork
324
- return if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
323
+ skip 'needs fork' unless Process.respond_to?(:fork)
325
324
 
326
325
  handler = AllHandler.new()
327
326
  json = %{{"one":true,"two":false}}
@@ -357,8 +356,7 @@ class ScpTest < Minitest::Test
357
356
  end
358
357
 
359
358
  def test_pipe_close
360
- # Windows does not support fork
361
- return if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
359
+ skip 'needs fork' unless Process.respond_to?(:fork)
362
360
 
363
361
  json = %{{"one":true,"two":false}}
364
362
  IO.pipe do |read_io, write_io|
data/test/test_strict.rb CHANGED
@@ -156,6 +156,8 @@ class StrictJuice < Minitest::Test
156
156
  end
157
157
 
158
158
  def test_deep_nest
159
+ skip 'TruffleRuby causes SEGV' if RUBY_ENGINE == 'truffleruby'
160
+
159
161
  begin
160
162
  n = 10000
161
163
  Oj.strict_load('[' * n + ']' * n)
data/test/test_various.rb CHANGED
@@ -345,6 +345,12 @@ class Juice < Minitest::Test
345
345
  out = Oj.dump hash
346
346
  assert_equal(%{{"key":"I \\u003c3 this"}}, out)
347
347
  end
348
+ def test_escapes_slashes_by_default_when_configured_to_do_so
349
+ hash = {'key' => "I <3 this </script>"}
350
+ Oj.default_options = {:escape_mode => :slash}
351
+ out = Oj.dump hash
352
+ assert_equal(%{{"key":"I <3 this <\\/script>"}}, out)
353
+ end
348
354
  def test_escapes_entities_when_asked_to
349
355
  hash = {'key' => "I <3 this"}
350
356
  out = Oj.dump(hash, :escape_mode => :xss_safe)
@@ -553,9 +559,6 @@ class Juice < Minitest::Test
553
559
  end
554
560
 
555
561
  def test_io_file
556
- # Windows does not support fork
557
- return if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
558
-
559
562
  src = { 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}
560
563
  filename = File.join(File.dirname(__FILE__), 'open_file_test.json')
561
564
  File.open(filename, "w") { |f|
@@ -568,6 +571,8 @@ class Juice < Minitest::Test
568
571
  end
569
572
 
570
573
  def test_io_stream
574
+ skip 'needs fork' unless Process.respond_to?(:fork)
575
+
571
576
  IO.pipe do |r, w|
572
577
  if fork
573
578
  r.close
data/test/test_wab.rb CHANGED
@@ -105,6 +105,8 @@ class WabJuice < Minitest::Test
105
105
  end
106
106
 
107
107
  def test_deep_nest
108
+ skip 'TruffleRuby causes SEGV' if RUBY_ENGINE == 'truffleruby'
109
+
108
110
  begin
109
111
  n = 10000
110
112
  Oj.wab_load('[' * n + ']' * n)
data/test/tests.rb CHANGED
@@ -22,3 +22,12 @@ require 'test_rails'
22
22
  require 'test_wab'
23
23
  require 'test_writer'
24
24
  require 'test_integer_range'
25
+
26
+ at_exit do
27
+ require 'helper'
28
+ if '3.1.0' <= RUBY_VERSION && !(RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/)
29
+ #Oj::debug_odd("teardown before GC.verify_compaction_references")
30
+ verify_gc_compaction
31
+ #Oj::debug_odd("teardown after GC.verify_compaction_references")
32
+ end
33
+ end
data/test/tests_mimic.rb CHANGED
@@ -12,3 +12,12 @@ require 'json_generator_test'
12
12
  require 'json_generic_object_test'
13
13
  require 'json_parser_test'
14
14
  require 'json_string_matching_test'
15
+
16
+ at_exit do
17
+ require 'helper'
18
+ if '3.1.0' <= RUBY_VERSION && !(RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/)
19
+ #Oj::debug_odd("teardown before GC.verify_compaction_references")
20
+ verify_gc_compaction
21
+ #Oj::debug_odd("teardown after GC.verify_compaction_references")
22
+ end
23
+ end
@@ -5,3 +5,12 @@ $: << File.dirname(__FILE__)
5
5
  $: << File.join(File.dirname(__FILE__), 'json_gem')
6
6
 
7
7
  require 'json_addition_test'
8
+
9
+ at_exit do
10
+ require 'helper'
11
+ if '3.1.0' <= RUBY_VERSION && !(RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/)
12
+ #Oj::debug_odd("teardown before GC.verify_compaction_references")
13
+ verify_gc_compaction
14
+ #Oj::debug_odd("teardown after GC.verify_compaction_references")
15
+ end
16
+ end