oj 3.13.7 → 3.13.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +75 -0
  3. data/README.md +11 -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 +66 -112
  9. data/ext/oj/dump.c +147 -184
  10. data/ext/oj/dump.h +25 -8
  11. data/ext/oj/dump_compat.c +47 -89
  12. data/ext/oj/dump_leaf.c +14 -58
  13. data/ext/oj/dump_object.c +72 -188
  14. data/ext/oj/dump_strict.c +19 -31
  15. data/ext/oj/encoder.c +43 -0
  16. data/ext/oj/extconf.rb +5 -4
  17. data/ext/oj/fast.c +36 -24
  18. data/ext/oj/intern.c +22 -12
  19. data/ext/oj/intern.h +1 -1
  20. data/ext/oj/mimic_json.c +74 -73
  21. data/ext/oj/object.c +54 -72
  22. data/ext/oj/odd.c +83 -63
  23. data/ext/oj/odd.h +13 -13
  24. data/ext/oj/oj.c +166 -175
  25. data/ext/oj/oj.h +25 -3
  26. data/ext/oj/parse.c +123 -79
  27. data/ext/oj/parse.h +2 -0
  28. data/ext/oj/parser.c +77 -21
  29. data/ext/oj/parser.h +12 -0
  30. data/ext/oj/rails.c +46 -70
  31. data/ext/oj/rails.h +1 -1
  32. data/ext/oj/reader.c +2 -0
  33. data/ext/oj/saj.c +11 -23
  34. data/ext/oj/saj2.c +333 -85
  35. data/ext/oj/saj2.h +23 -0
  36. data/ext/oj/sparse.c +4 -0
  37. data/ext/oj/stream_writer.c +3 -1
  38. data/ext/oj/strict.c +13 -13
  39. data/ext/oj/string_writer.c +12 -5
  40. data/ext/oj/usual.c +86 -131
  41. data/ext/oj/usual.h +68 -0
  42. data/ext/oj/val_stack.c +1 -1
  43. data/ext/oj/validate.c +21 -26
  44. data/ext/oj/wab.c +22 -27
  45. data/lib/oj/saj.rb +20 -6
  46. data/lib/oj/state.rb +1 -1
  47. data/lib/oj/version.rb +1 -1
  48. data/pages/Compatibility.md +1 -1
  49. data/pages/JsonGem.md +15 -0
  50. data/pages/Modes.md +6 -3
  51. data/pages/Options.md +6 -0
  52. data/pages/Rails.md +12 -0
  53. data/test/activesupport7/abstract_unit.rb +49 -0
  54. data/test/activesupport7/decoding_test.rb +125 -0
  55. data/test/activesupport7/encoding_test.rb +486 -0
  56. data/test/activesupport7/encoding_test_cases.rb +104 -0
  57. data/test/activesupport7/time_zone_test_helpers.rb +47 -0
  58. data/test/bar.rb +3 -8
  59. data/test/bug.rb +16 -0
  60. data/test/foo.rb +71 -7
  61. data/test/helper.rb +8 -2
  62. data/test/json_gem/json_generator_test.rb +5 -4
  63. data/test/json_gem/json_parser_test.rb +8 -1
  64. data/test/json_gem/test_helper.rb +7 -3
  65. data/test/perf_dump.rb +50 -0
  66. data/test/test_compat.rb +25 -0
  67. data/test/test_custom.rb +13 -2
  68. data/test/test_fast.rb +37 -7
  69. data/test/test_file.rb +23 -7
  70. data/test/test_gc.rb +11 -0
  71. data/test/test_object.rb +8 -10
  72. data/test/test_parser.rb +3 -19
  73. data/test/test_parser_debug.rb +27 -0
  74. data/test/test_parser_saj.rb +92 -2
  75. data/test/test_saj.rb +1 -1
  76. data/test/test_scp.rb +2 -4
  77. data/test/test_strict.rb +2 -0
  78. data/test/test_various.rb +32 -2
  79. data/test/test_wab.rb +2 -0
  80. data/test/tests.rb +9 -1
  81. data/test/tests_mimic.rb +9 -0
  82. data/test/tests_mimic_addition.rb +9 -0
  83. metadata +15 -115
data/test/foo.rb CHANGED
@@ -1,13 +1,77 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'oj'
3
+ $: << '.'
4
+ $: << File.join(File.dirname(__FILE__), "../lib")
5
+ $: << File.join(File.dirname(__FILE__), "../ext")
4
6
 
5
- Oj::default_options = {cache_str: 0, cache_keys: true, mode: :strict}
7
+ require "oj"
8
+ require "socket"
9
+ require 'io/nonblock'
6
10
 
7
- puts "Ruby version: #{RUBY_VERSION}"
8
- puts "Oj version: #{Oj::VERSION}"
11
+ #pid = spawn("nc -d 0.1 -l 5000", out: "/dev/null")
12
+ pid = spawn("nc -i 1 -l 7777", out: "/dev/null")
13
+ at_exit { Process.kill 9, pid }
14
+ sleep 0.2
15
+ s = Socket.tcp("localhost", 7777)
16
+ s.nonblock = false
17
+ 1_000_000.times do |x|
18
+ Oj.to_stream(s, { x: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]})
19
+ end
9
20
 
10
- puts "cache_keys: #{Oj::default_options[:cache_keys]}"
11
- puts "cache_str: #{Oj::default_options[:cache_str]}"
21
+ =begin
22
+ IO.pipe do |r, w|
23
+ if fork
24
+ r.close
25
+ #w.nonblock = false
26
+ 1_000_000.times do |i|
27
+ begin
28
+ Oj.to_stream(w, { x: i})
29
+ rescue IOError => e
30
+ puts "*** #{i} raised #{e.class}: #{e}"
31
+ IO.select(nil, [w])
32
+ retry
33
+ end
34
+ w.puts
35
+ end
36
+ else
37
+ w.close
38
+ sleep(0.1)
39
+ r.each_line { |b|
40
+ #print b
41
+ }
42
+ r.close
43
+ Process.exit(0)
44
+ end
45
+ end
46
+ =end
12
47
 
13
- Oj.load('{"":""}').each_pair {|k,v| puts "k.frozen?: #{k.frozen?}\nv.frozen?: #{v.frozen?}"}
48
+ =begin
49
+ IO.pipe do |r, w|
50
+ if fork
51
+ r.close
52
+ #w.nonblock = false
53
+ a = []
54
+ 10_000.times do |i|
55
+ a << i
56
+ end
57
+ begin
58
+ Oj.to_stream(w, a, indent: 2)
59
+ rescue IOError => e
60
+ puts "*** raised #{e.class}: #{e}"
61
+ puts "*** fileno: #{w.fileno}"
62
+ puts "*** is an IO?: #{w.kind_of?(IO)}"
63
+ IO.select(nil, [w])
64
+ retry
65
+ end
66
+ w.puts
67
+ else
68
+ w.close
69
+ sleep(0.5)
70
+ r.each_line { |b|
71
+ #print b
72
+ }
73
+ r.close
74
+ Process.exit(0)
75
+ end
76
+ end
77
+ =end
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_fast.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: utf-8
2
+ # coding: utf-8
3
+ # frozen_string_literal: true
3
4
 
4
5
  $: << File.dirname(__FILE__)
5
6
 
@@ -36,6 +37,17 @@ class DocTest < Minitest::Test
36
37
  end
37
38
  end
38
39
 
40
+ def test_leaf_of_existing_path
41
+ json = %{{"foo": 1, "fizz": true}}
42
+ Oj::Doc.open(json) do |doc|
43
+ %w(/foo/bar /fizz/bar).each do |path|
44
+ assert_nil(doc.fetch(path))
45
+ assert_equal(:default, doc.fetch(path, :default))
46
+ refute(doc.exists?(path))
47
+ end
48
+ end
49
+ end
50
+
39
51
  def test_true
40
52
  json = %{true}
41
53
  Oj::Doc.open(json) do |doc|
@@ -282,11 +294,11 @@ class DocTest < Minitest::Test
282
294
  ['/nothing', nil],
283
295
  ['/array/10', nil],
284
296
  ].each do |path,val|
285
- if val.nil?
286
- assert_nil(doc.fetch(path))
287
- else
297
+ if val.nil?
298
+ assert_nil(doc.fetch(path))
299
+ else
288
300
  assert_equal(val, doc.fetch(path))
289
- end
301
+ end
290
302
  end
291
303
  end
292
304
  # verify empty hash and arrays return nil when a member is requested
@@ -313,7 +325,7 @@ class DocTest < Minitest::Test
313
325
  end
314
326
  end
315
327
 
316
- def test_exisits
328
+ def test_exists
317
329
  Oj::Doc.open(@json1) do |doc|
318
330
  [['/array/1', true],
319
331
  ['/array/1', true],
@@ -322,7 +334,7 @@ class DocTest < Minitest::Test
322
334
  ['/array/3', false],
323
335
  ['/nothing', false],
324
336
  ].each do |path,val|
325
- assert_equal(val, doc.exists?(path))
337
+ assert_equal(val, doc.exists?(path), "failed for #{path.inspect}")
326
338
  end
327
339
  end
328
340
  end
@@ -384,6 +396,19 @@ class DocTest < Minitest::Test
384
396
  end
385
397
  end
386
398
 
399
+ def test_nested_each_child
400
+ h = {}
401
+ Oj::Doc.open('{"a":1,"c":[2],"d":3}') do |doc|
402
+ doc.each_child('/') do |child|
403
+ h[child.path] = child.fetch
404
+ child.each_child do |grandchild|
405
+ h[grandchild.path] = grandchild.fetch
406
+ end
407
+ end
408
+ end
409
+ assert_equal({"/a"=>1, "/c"=>[2], "/c/1"=>2, "/d"=>3}, h)
410
+ end
411
+
387
412
  def test_size
388
413
  Oj::Doc.open('[1,2,3]') do |doc|
389
414
  assert_equal(4, doc.size)
@@ -480,6 +505,11 @@ class DocTest < Minitest::Test
480
505
  assert_equal({'/a/x' => 2, '/b/y' => 4}, results)
481
506
  end
482
507
 
508
+ def test_doc_empty
509
+ result = Oj::Doc.open("") { |doc| doc.each_child {} }
510
+ assert_nil(result)
511
+ end
512
+
483
513
  def test_comment
484
514
  json = %{{
485
515
  "x"/*one*/:/*two*/true,//three
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