oj 3.13.23 → 3.16.9

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 (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +81 -0
  3. data/README.md +2 -2
  4. data/ext/oj/buf.h +7 -6
  5. data/ext/oj/cache.c +29 -26
  6. data/ext/oj/cache.h +3 -2
  7. data/ext/oj/cache8.c +10 -9
  8. data/ext/oj/circarray.c +7 -5
  9. data/ext/oj/circarray.h +2 -2
  10. data/ext/oj/code.c +5 -12
  11. data/ext/oj/code.h +2 -2
  12. data/ext/oj/compat.c +20 -60
  13. data/ext/oj/custom.c +26 -59
  14. data/ext/oj/debug.c +3 -9
  15. data/ext/oj/dump.c +103 -53
  16. data/ext/oj/dump.h +1 -4
  17. data/ext/oj/dump_compat.c +557 -592
  18. data/ext/oj/dump_leaf.c +3 -5
  19. data/ext/oj/dump_object.c +42 -48
  20. data/ext/oj/dump_strict.c +10 -22
  21. data/ext/oj/encoder.c +1 -1
  22. data/ext/oj/err.c +2 -13
  23. data/ext/oj/err.h +9 -12
  24. data/ext/oj/extconf.rb +16 -7
  25. data/ext/oj/fast.c +60 -92
  26. data/ext/oj/intern.c +62 -47
  27. data/ext/oj/intern.h +3 -7
  28. data/ext/oj/mem.c +318 -0
  29. data/ext/oj/mem.h +53 -0
  30. data/ext/oj/mimic_json.c +51 -32
  31. data/ext/oj/object.c +33 -43
  32. data/ext/oj/odd.c +8 -6
  33. data/ext/oj/odd.h +4 -4
  34. data/ext/oj/oj.c +243 -212
  35. data/ext/oj/oj.h +83 -81
  36. data/ext/oj/parse.c +94 -148
  37. data/ext/oj/parse.h +21 -24
  38. data/ext/oj/parser.c +80 -67
  39. data/ext/oj/parser.h +7 -8
  40. data/ext/oj/rails.c +70 -92
  41. data/ext/oj/reader.c +9 -14
  42. data/ext/oj/reader.h +4 -2
  43. data/ext/oj/resolve.c +3 -4
  44. data/ext/oj/rxclass.c +6 -5
  45. data/ext/oj/rxclass.h +1 -1
  46. data/ext/oj/saj.c +10 -9
  47. data/ext/oj/saj2.c +37 -49
  48. data/ext/oj/saj2.h +1 -1
  49. data/ext/oj/scp.c +3 -14
  50. data/ext/oj/sparse.c +22 -70
  51. data/ext/oj/stream_writer.c +45 -41
  52. data/ext/oj/strict.c +20 -52
  53. data/ext/oj/string_writer.c +64 -38
  54. data/ext/oj/trace.h +31 -4
  55. data/ext/oj/usual.c +125 -114
  56. data/ext/oj/usual.h +7 -6
  57. data/ext/oj/util.h +1 -1
  58. data/ext/oj/val_stack.c +13 -2
  59. data/ext/oj/val_stack.h +8 -7
  60. data/ext/oj/wab.c +25 -57
  61. data/lib/oj/active_support_helper.rb +1 -3
  62. data/lib/oj/bag.rb +7 -1
  63. data/lib/oj/easy_hash.rb +4 -5
  64. data/lib/oj/error.rb +0 -1
  65. data/lib/oj/json.rb +162 -150
  66. data/lib/oj/mimic.rb +7 -7
  67. data/lib/oj/schandler.rb +5 -4
  68. data/lib/oj/state.rb +8 -5
  69. data/lib/oj/version.rb +1 -2
  70. data/lib/oj.rb +2 -0
  71. data/pages/InstallOptions.md +20 -0
  72. data/pages/Options.md +4 -0
  73. data/test/_test_active.rb +8 -9
  74. data/test/_test_active_mimic.rb +7 -8
  75. data/test/_test_mimic_rails.rb +17 -20
  76. data/test/activerecord/result_test.rb +5 -6
  77. data/test/activesupport6/encoding_test.rb +63 -28
  78. data/test/activesupport7/abstract_unit.rb +4 -1
  79. data/test/activesupport7/encoding_test.rb +72 -22
  80. data/test/files.rb +15 -15
  81. data/test/foo.rb +18 -69
  82. data/test/helper.rb +5 -8
  83. data/test/isolated/shared.rb +3 -2
  84. data/test/json_gem/json_addition_test.rb +2 -2
  85. data/test/json_gem/json_common_interface_test.rb +8 -6
  86. data/test/json_gem/json_encoding_test.rb +0 -0
  87. data/test/json_gem/json_ext_parser_test.rb +1 -0
  88. data/test/json_gem/json_fixtures_test.rb +3 -2
  89. data/test/json_gem/json_generator_test.rb +50 -33
  90. data/test/json_gem/json_generic_object_test.rb +11 -11
  91. data/test/json_gem/json_parser_test.rb +46 -46
  92. data/test/json_gem/json_string_matching_test.rb +9 -9
  93. data/test/mem.rb +13 -12
  94. data/test/perf.rb +21 -26
  95. data/test/perf_compat.rb +31 -33
  96. data/test/perf_dump.rb +28 -28
  97. data/test/perf_fast.rb +80 -82
  98. data/test/perf_file.rb +27 -29
  99. data/test/perf_object.rb +65 -69
  100. data/test/perf_once.rb +12 -11
  101. data/test/perf_parser.rb +42 -48
  102. data/test/perf_saj.rb +46 -54
  103. data/test/perf_scp.rb +57 -69
  104. data/test/perf_simple.rb +41 -39
  105. data/test/perf_strict.rb +68 -70
  106. data/test/perf_wab.rb +67 -69
  107. data/test/prec.rb +5 -5
  108. data/test/sample/change.rb +0 -1
  109. data/test/sample/dir.rb +0 -1
  110. data/test/sample/doc.rb +0 -1
  111. data/test/sample/file.rb +0 -1
  112. data/test/sample/group.rb +0 -1
  113. data/test/sample/hasprops.rb +0 -1
  114. data/test/sample/layer.rb +0 -1
  115. data/test/sample/rect.rb +0 -1
  116. data/test/sample/shape.rb +0 -1
  117. data/test/sample/text.rb +0 -1
  118. data/test/sample.rb +16 -16
  119. data/test/sample_json.rb +8 -8
  120. data/test/test_compat.rb +81 -54
  121. data/test/test_custom.rb +63 -52
  122. data/test/test_debian.rb +7 -10
  123. data/test/test_fast.rb +86 -90
  124. data/test/test_file.rb +24 -29
  125. data/test/test_gc.rb +5 -5
  126. data/test/test_generate.rb +5 -5
  127. data/test/test_hash.rb +4 -4
  128. data/test/test_integer_range.rb +9 -9
  129. data/test/test_null.rb +20 -20
  130. data/test/test_object.rb +92 -87
  131. data/test/test_parser.rb +4 -4
  132. data/test/test_parser_debug.rb +5 -5
  133. data/test/test_parser_saj.rb +27 -25
  134. data/test/test_parser_usual.rb +44 -6
  135. data/test/test_rails.rb +2 -2
  136. data/test/test_saj.rb +10 -8
  137. data/test/test_scp.rb +35 -35
  138. data/test/test_strict.rb +38 -32
  139. data/test/test_various.rb +146 -97
  140. data/test/test_wab.rb +46 -44
  141. data/test/test_writer.rb +63 -47
  142. data/test/tests.rb +7 -7
  143. data/test/tests_mimic.rb +6 -6
  144. data/test/tests_mimic_addition.rb +6 -6
  145. metadata +46 -26
  146. data/test/activesupport4/decoding_test.rb +0 -108
  147. data/test/activesupport4/encoding_test.rb +0 -531
  148. data/test/activesupport4/test_helper.rb +0 -41
  149. data/test/activesupport5/abstract_unit.rb +0 -45
  150. data/test/activesupport5/decoding_test.rb +0 -133
  151. data/test/activesupport5/encoding_test.rb +0 -500
  152. data/test/activesupport5/encoding_test_cases.rb +0 -98
  153. data/test/activesupport5/test_helper.rb +0 -72
  154. data/test/activesupport5/time_zone_test_helpers.rb +0 -39
  155. data/test/bar.rb +0 -11
  156. data/test/baz.rb +0 -16
  157. data/test/bug.rb +0 -16
  158. data/test/zoo.rb +0 -13
data/test/test_various.rb CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: utf-8
2
+ # frozen_string_literal: false
3
3
 
4
- $: << File.dirname(__FILE__)
4
+ $LOAD_PATH << __dir__
5
5
 
6
6
  require 'helper'
7
7
 
8
8
  class Juice < Minitest::Test
9
- def gen_whitespaced_string(length = Random.new.rand(100))
10
- whitespace_chars = [" ", "\t", "\f", "\n", "\r"]
11
- result = ""
9
+ def gen_whitespaced_string(length=Random.new.rand(100))
10
+ whitespace_chars = [' ', "\t", "\f", "\n", "\r"]
11
+ result = ''
12
12
  length.times { result << whitespace_chars.sample }
13
13
  result
14
14
  end
@@ -32,59 +32,49 @@ class Juice < Minitest::Test
32
32
  end # Jam
33
33
 
34
34
  class Jeez < Jam
35
- def initialize(x, y)
36
- super
37
- end
38
35
 
39
- def to_json()
36
+ def to_json(*_args)
40
37
  %{{"json_class":"#{self.class}","x":#{@x},"y":#{@y}}}
41
38
  end
42
39
 
43
40
  def self.json_create(h)
44
- self.new(h['x'], h['y'])
41
+ new(h['x'], h['y'])
45
42
  end
46
43
  end # Jeez
47
44
 
48
45
  # contributed by sauliusg to fix as_json
49
46
  class Orange < Jam
50
- def initialize(x, y)
51
- super
52
- end
53
47
 
54
- def as_json()
48
+ def as_json
55
49
  { :json_class => self.class,
56
50
  :x => @x,
57
51
  :y => @y }
58
52
  end
59
53
 
60
54
  def self.json_create(h)
61
- self.new(h['x'], h['y'])
55
+ new(h['x'], h['y'])
62
56
  end
63
57
  end
64
58
 
65
59
  class Melon < Jam
66
- def initialize(x, y)
67
- super
68
- end
69
60
 
70
- def as_json(options)
61
+ def as_json(_options)
71
62
  "#{x} #{y}"
72
63
  end
73
64
 
74
65
  def self.json_create(h)
75
- self.new(h['x'], h['y'])
66
+ new(h['x'], h['y'])
76
67
  end
77
68
  end
78
69
 
79
70
  class Jazz < Jam
80
- def initialize(x, y)
81
- super
82
- end
83
- def to_hash()
71
+
72
+ def to_hash
84
73
  { 'json_class' => self.class.to_s, 'x' => @x, 'y' => @y }
85
74
  end
75
+
86
76
  def self.json_create(h)
87
- self.new(h['x'], h['y'])
77
+ new(h['x'], h['y'])
88
78
  end
89
79
  end # Jazz
90
80
 
@@ -99,7 +89,7 @@ class Juice < Minitest::Test
99
89
  def test_set_options
100
90
  orig = Oj.default_options()
101
91
  alt ={
102
- indent: " - ",
92
+ indent: ' - ',
103
93
  second_precision: 5,
104
94
  circular: true,
105
95
  class_cache: false,
@@ -115,6 +105,7 @@ class Juice < Minitest::Test
115
105
  allow_gc: false,
116
106
  quirks_mode: false,
117
107
  allow_invalid_unicode: true,
108
+ float_format: '%0.13g',
118
109
  float_precision: 13,
119
110
  mode: :strict,
120
111
  escape_mode: :ascii,
@@ -139,17 +130,18 @@ class Juice < Minitest::Test
139
130
  ignore_under: true,
140
131
  trace: true,
141
132
  safe: true,
133
+ omit_null_byte: false,
142
134
  }
143
135
  Oj.default_options = alt
144
- #keys = alt.keys
145
- #Oj.default_options.keys.each { |k| puts k unless keys.include? k}
136
+ # keys = alt.keys
137
+ # Oj.default_options.keys.each { |k| puts k unless keys.include? k}
146
138
  opts = Oj.default_options()
147
- assert_equal(alt, opts);
139
+ assert_equal(alt, opts)
148
140
 
149
141
  Oj.default_options = orig # return to original
150
142
  # verify back to original
151
143
  opts = Oj.default_options()
152
- assert_equal(orig, opts);
144
+ assert_equal(orig, opts)
153
145
  end
154
146
 
155
147
  def test_nil
@@ -166,8 +158,8 @@ class Juice < Minitest::Test
166
158
 
167
159
  def test_fixnum
168
160
  dump_and_load(0, false)
169
- dump_and_load(12345, false)
170
- dump_and_load(-54321, false)
161
+ dump_and_load(12_345, false)
162
+ dump_and_load(-54_321, false)
171
163
  dump_and_load(1, false)
172
164
  end
173
165
 
@@ -175,11 +167,11 @@ class Juice < Minitest::Test
175
167
  Oj.default_options = { :float_precision => 16, :bigdecimal_load => :auto }
176
168
  n = Oj.load('0.00001234567890123456')
177
169
  assert_equal(Float, n.class)
178
- assert_equal('1.234567890123456e-05', "%0.15e" % [n])
170
+ assert_equal('1.234567890123456e-05', '%0.15e' % [n])
179
171
 
180
172
  n = Oj.load('-0.00001234567890123456')
181
173
  assert_equal(Float, n.class)
182
- assert_equal('-1.234567890123456e-05', "%0.15e" % [n])
174
+ assert_equal('-1.234567890123456e-05', '%0.15e' % [n])
183
175
 
184
176
  n = Oj.load('1000.0000123456789')
185
177
  assert_equal(BigDecimal, n.class)
@@ -227,12 +219,12 @@ class Juice < Minitest::Test
227
219
  def test_encode
228
220
  opts = Oj.default_options
229
221
  Oj.default_options = { :ascii_only => false }
230
- dump_and_load("ぴーたー", false)
222
+ dump_and_load('ぴーたー', false)
231
223
 
232
224
  Oj.default_options = { :ascii_only => true }
233
- json = Oj.dump("ぴーたー")
225
+ json = Oj.dump('ぴーたー')
234
226
  assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json)
235
- dump_and_load("ぴーたー", false)
227
+ dump_and_load('ぴーたー', false)
236
228
  Oj.default_options = opts
237
229
  end
238
230
 
@@ -253,7 +245,7 @@ class Juice < Minitest::Test
253
245
  assert(true)
254
246
  return
255
247
  end
256
- assert(false, "*** expected an exception")
248
+ assert(false, '*** expected an exception')
257
249
  end
258
250
 
259
251
  def test_invalid_unicode_ok
@@ -267,11 +259,11 @@ class Juice < Minitest::Test
267
259
  def test_dump_options
268
260
  json = Oj.dump({ 'a' => 1, 'b' => [true, false]},
269
261
  :mode => :compat,
270
- :indent => "--",
262
+ :indent => '--',
271
263
  :array_nl => "\n",
272
264
  :object_nl => "#\n",
273
- :space => "*",
274
- :space_before => "~")
265
+ :space => '*',
266
+ :space_before => '~')
275
267
  assert(%{{#
276
268
  --"a"~:*1,#
277
269
  --"b"~:*[
@@ -286,7 +278,6 @@ class Juice < Minitest::Test
286
278
  --],#
287
279
  --"a"~:*1#
288
280
  }} == json)
289
-
290
281
  end
291
282
 
292
283
  def test_null_char
@@ -301,6 +292,7 @@ class Juice < Minitest::Test
301
292
  dump_and_load([[nil]], false)
302
293
  dump_and_load([[nil], 58], false)
303
294
  end
295
+
304
296
  def test_array_not_closed
305
297
  begin
306
298
  Oj.load('[')
@@ -308,7 +300,7 @@ class Juice < Minitest::Test
308
300
  assert(true)
309
301
  return
310
302
  end
311
- assert(false, "*** expected an exception")
303
+ assert(false, '*** expected an exception')
312
304
  end
313
305
 
314
306
  # multiple JSON in one string
@@ -319,7 +311,7 @@ class Juice < Minitest::Test
319
311
  }
320
312
  results = []
321
313
  Oj.load(json, :mode => :strict) { |x, start, len| results << [x, start, len] }
322
- assert_equal([[{"a"=>1}, 0, 7], [[1,2], 7, 6], [[3,4], 13, 5], [{"b"=>2}, 18, 8]], results)
314
+ assert_equal([[{'a'=>1}, 0, 7], [[1, 2], 7, 6], [[3, 4], 13, 5], [{'b'=>2}, 18, 8]], results)
323
315
  end
324
316
 
325
317
  def test_multiple_json_no_callback
@@ -339,33 +331,39 @@ class Juice < Minitest::Test
339
331
  out = Oj.dump(hash)
340
332
  assert_equal(json, out)
341
333
  end
334
+
342
335
  def test_escapes_entities_by_default_when_configured_to_do_so
343
- hash = {'key' => "I <3 this"}
336
+ hash = {'key' => 'I <3 this'}
344
337
  Oj.default_options = {:escape_mode => :xss_safe}
345
338
  out = Oj.dump hash
346
339
  assert_equal(%{{"key":"I \\u003c3 this"}}, out)
347
340
  end
341
+
348
342
  def test_escapes_slashes_by_default_when_configured_to_do_so
349
- hash = {'key' => "I <3 this </script>"}
343
+ hash = {'key' => 'I <3 this </script>'}
350
344
  Oj.default_options = {:escape_mode => :slash}
351
345
  out = Oj.dump hash
352
346
  assert_equal(%{{"key":"I <3 this <\\/script>"}}, out)
353
347
  end
348
+
354
349
  def test_escapes_entities_when_asked_to
355
- hash = {'key' => "I <3 this"}
350
+ hash = {'key' => 'I <3 this'}
356
351
  out = Oj.dump(hash, :escape_mode => :xss_safe)
357
352
  assert_equal(%{{"key":"I \\u003c3 this"}}, out)
358
353
  end
354
+
359
355
  def test_does_not_escape_entities_when_not_asked_to
360
- hash = {'key' => "I <3 this"}
356
+ hash = {'key' => 'I <3 this'}
361
357
  out = Oj.dump(hash, :escape_mode => :json)
362
358
  assert_equal(%{{"key":"I <3 this"}}, out)
363
359
  end
360
+
364
361
  def test_escapes_common_xss_vectors
365
- hash = {'key' => "<script>alert(123) && formatHD()</script>"}
362
+ hash = {'key' => '<script>alert(123) && formatHD()</script>'}
366
363
  out = Oj.dump(hash, :escape_mode => :xss_safe)
367
364
  assert_equal(%{{"key":"\\u003cscript\\u003ealert(123) \\u0026\\u0026 formatHD()\\u003c\\/script\\u003e"}}, out)
368
365
  end
366
+
369
367
  def test_escape_newline_by_default
370
368
  Oj.default_options = { :escape_mode => :json }
371
369
  json = %{["one","two\\n2"]}
@@ -373,6 +371,7 @@ class Juice < Minitest::Test
373
371
  out = Oj.dump(x)
374
372
  assert_equal(json, out)
375
373
  end
374
+
376
375
  def test_does_not_escape_newline
377
376
  Oj.default_options = { :escape_mode => :newline }
378
377
  json = %{["one","two\n2"]}
@@ -380,6 +379,7 @@ class Juice < Minitest::Test
380
379
  out = Oj.dump(x)
381
380
  assert_equal(json, out)
382
381
  end
382
+
383
383
  def test_dump_invalid_utf8
384
384
  Oj.default_options = { :escape_mode => :ascii }
385
385
  assert_raises(EncodingError) {
@@ -401,14 +401,14 @@ class Juice < Minitest::Test
401
401
  end
402
402
 
403
403
  def test_time_neg
404
- t = Time.parse("1900-01-01 00:18:59 UTC")
404
+ t = Time.parse('1900-01-01 00:18:59 UTC')
405
405
  json = Oj.dump(t, :mode => :custom, :time_format => :unix)
406
406
  assert_equal('-2208987661.000000000', json)
407
407
  end
408
408
 
409
409
  def test_time_years
410
410
  (-2020..2020).each { |year|
411
- s = "%04d-03-01T15:14:13Z" % [year]
411
+ s = '%04d-03-01T15:14:13Z' % [year]
412
412
  json = Oj.dump(Time.parse(s), mode: :custom, time_format: :xmlschema, second_precision: -1)
413
413
  assert_equal(s, json[1..-2])
414
414
 
@@ -417,6 +417,11 @@ class Juice < Minitest::Test
417
417
  }
418
418
  end
419
419
 
420
+ def test_dump_float
421
+ json = Oj.dump(1.23e-2, :mode => :null, :float_format => '%0.4f')
422
+ assert_equal('0.0123', json)
423
+ end
424
+
420
425
  # Class
421
426
  def test_class_null
422
427
  json = Oj.dump(Juice, :mode => :null)
@@ -437,7 +442,7 @@ class Juice < Minitest::Test
437
442
  assert(true)
438
443
  return
439
444
  end
440
- assert(false, "*** expected an exception")
445
+ assert(false, '*** expected an exception')
441
446
  end
442
447
 
443
448
  def test_hash_not_closed
@@ -447,7 +452,7 @@ class Juice < Minitest::Test
447
452
  assert(true)
448
453
  return
449
454
  end
450
- assert(false, "*** expected an exception")
455
+ assert(false, '*** expected an exception')
451
456
  end
452
457
 
453
458
  # Object with to_json()
@@ -457,7 +462,7 @@ class Juice < Minitest::Test
457
462
  assert_equal('null', json)
458
463
  end
459
464
 
460
- # Object with to_hash()
465
+ # Object with to_hash()
461
466
  def test_to_hash_object_null
462
467
  obj = Jazz.new(true, 58)
463
468
  json = Oj.dump(obj, :mode => :null)
@@ -505,7 +510,7 @@ class Juice < Minitest::Test
505
510
 
506
511
  def test_infinity
507
512
  n = Oj.load('Infinity', :mode => :object)
508
- assert_equal(BigDecimal('Infinity').to_f, n);
513
+ assert_equal(BigDecimal('Infinity').to_f, n)
509
514
  x = Oj.load('Infinity', :mode => :compat)
510
515
  assert_equal('Infinity', x.to_s)
511
516
  end
@@ -530,7 +535,7 @@ class Juice < Minitest::Test
530
535
  "y":58 }}
531
536
  obj = Oj.load(json, :mode => :object, :auto_define => true)
532
537
  assert_equal('Juice::Jem', obj.class.name)
533
- assert_equal(true, obj.x)
538
+ assert(obj.x)
534
539
  assert_equal(58, obj.y)
535
540
  end
536
541
 
@@ -538,19 +543,19 @@ class Juice < Minitest::Test
538
543
  def test_deep_nest_dump
539
544
  begin
540
545
  a = []
541
- 10000.times { a << [a] }
546
+ 10_000.times { a << [a] }
542
547
  Oj.dump(a)
543
548
  rescue Exception
544
549
  assert(true)
545
550
  return
546
551
  end
547
- assert(false, "*** expected an exception")
552
+ assert(false, '*** expected an exception')
548
553
  end
549
554
 
550
555
  # Stream IO
551
556
  def test_io_string
552
557
  src = { 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}
553
- output = StringIO.open("", "w+")
558
+ output = StringIO.open('', 'w+')
554
559
  Oj.to_stream(output, src)
555
560
 
556
561
  input = StringIO.new(output.string())
@@ -560,8 +565,8 @@ class Juice < Minitest::Test
560
565
 
561
566
  def test_io_file
562
567
  src = { 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}
563
- filename = File.join(File.dirname(__FILE__), 'open_file_test.json')
564
- File.open(filename, "w") { |f|
568
+ filename = File.join(__dir__, 'open_file_test.json')
569
+ File.open(filename, 'w') { |f|
565
570
  Oj.to_stream(f, src)
566
571
  }
567
572
  f = File.new(filename)
@@ -575,26 +580,26 @@ class Juice < Minitest::Test
575
580
 
576
581
  IO.pipe do |r, w|
577
582
  if fork
578
- r.close
579
- #w.nonblock = false
580
- a = []
581
- 10_000.times do |i|
582
- a << i
583
- end
584
- Oj.to_stream(w, a, indent: 2)
585
- w.close
583
+ r.close
584
+ # w.nonblock = false
585
+ a = []
586
+ 10_000.times do |i|
587
+ a << i
588
+ end
589
+ Oj.to_stream(w, a, indent: 2)
590
+ w.close
586
591
  else
587
- w.close
588
- sleep(0.1) # to force a busy
589
- cnt = 0
590
- r.each_line { cnt += 1 }
591
- r.close
592
- Process.exit(0)
592
+ w.close
593
+ sleep(0.1) # to force a busy
594
+ cnt = 0
595
+ r.each_line { cnt += 1 }
596
+ r.close
597
+ Process.exit(0)
593
598
  end
594
599
  end
595
600
  end
596
601
 
597
- # comments
602
+ # comments
598
603
  def test_comment_slash
599
604
  json = %{{
600
605
  "x":true,//three
@@ -638,7 +643,7 @@ class Juice < Minitest::Test
638
643
  assert(true)
639
644
  return
640
645
  end
641
- assert(false, "*** expected an exception")
646
+ assert(false, '*** expected an exception')
642
647
  end
643
648
 
644
649
  def test_nilnil_true
@@ -661,27 +666,27 @@ class Juice < Minitest::Test
661
666
  assert(Oj::ParseError == e.class || EncodingError == e.class)
662
667
  return
663
668
  end
664
- assert(false, "*** expected an exception")
669
+ assert(false, '*** expected an exception')
665
670
  end
666
671
 
667
672
  def test_quirks_null_mode
668
- assert_raises(Oj::ParseError) { Oj.load("null", :quirks_mode => false) }
669
- assert_nil(Oj.load("null", :quirks_mode => true))
673
+ assert_raises(Oj::ParseError) { Oj.load('null', :quirks_mode => false) }
674
+ assert_nil(Oj.load('null', :quirks_mode => true))
670
675
  end
671
676
 
672
677
  def test_quirks_bool_mode
673
- assert_raises(Oj::ParseError) { Oj.load("true", :quirks_mode => false) }
674
- assert_equal(true, Oj.load("true", :quirks_mode => true))
678
+ assert_raises(Oj::ParseError) { Oj.load('true', :quirks_mode => false) }
679
+ assert(Oj.load('true', :quirks_mode => true))
675
680
  end
676
681
 
677
682
  def test_quirks_number_mode
678
- assert_raises(Oj::ParseError) { Oj.load("123", :quirks_mode => false) }
679
- assert_equal(123, Oj.load("123", :quirks_mode => true))
683
+ assert_raises(Oj::ParseError) { Oj.load('123', :quirks_mode => false) }
684
+ assert_equal(123, Oj.load('123', :quirks_mode => true))
680
685
  end
681
686
 
682
687
  def test_quirks_decimal_mode
683
- assert_raises(Oj::ParseError) { Oj.load("123.45", :quirks_mode => false) }
684
- assert_equal(123.45, Oj.load("123.45", :quirks_mode => true))
688
+ assert_raises(Oj::ParseError) { Oj.load('123.45', :quirks_mode => false) }
689
+ assert_in_delta(123.45, Oj.load('123.45', :quirks_mode => true))
685
690
  end
686
691
 
687
692
  def test_quirks_string_mode
@@ -693,35 +698,33 @@ class Juice < Minitest::Test
693
698
  msg = ''
694
699
  assert_raises(Oj::ParseError) {
695
700
  begin
696
- Oj.load(%|{
701
+ Oj.load(%|{
697
702
  "first": [
698
703
  1, 2, { "third": 123x }
699
704
  ]
700
705
  }|)
701
706
  rescue Oj::ParseError => e
702
- msg = e.message
703
- raise e
707
+ msg = e.message
708
+ raise e
704
709
  end
705
710
  }
706
711
  assert_equal('after first[2].third', msg.split('(')[1].split(')')[0])
707
712
  end
708
713
 
709
714
  def test_bad_bignum
710
- if '2.4.0' < RUBY_VERSION
711
- assert_raises Oj::ParseError do
712
- Oj.load(%|{ "big": -e123456789 }|, mode: :strict)
713
- end
715
+ assert_raises Oj::ParseError do
716
+ Oj.load(%|{ "big": -e123456789 }|, mode: :strict)
714
717
  end
715
718
  end
716
719
 
717
720
  def test_quirks_array_mode
718
- assert_equal([], Oj.load("[]", :quirks_mode => false))
719
- assert_equal([], Oj.load("[]", :quirks_mode => true))
721
+ assert_empty(Oj.load('[]', :quirks_mode => false))
722
+ assert_empty(Oj.load('[]', :quirks_mode => true))
720
723
  end
721
724
 
722
725
  def test_quirks_object_mode
723
- assert_equal({}, Oj.load("{}", :quirks_mode => false))
724
- assert_equal({}, Oj.load("{}", :quirks_mode => true))
726
+ assert_empty(Oj.load('{}', :quirks_mode => false))
727
+ assert_empty(Oj.load('{}', :quirks_mode => true))
725
728
  end
726
729
 
727
730
  def test_omit_nil
@@ -737,6 +740,52 @@ class Juice < Minitest::Test
737
740
  assert_equal(%|{"x":{"a":1}}|, json)
738
741
  end
739
742
 
743
+ def test_omit_null_byte
744
+ Oj.default_options = { :omit_null_byte => true }
745
+
746
+ json = Oj.dump({ "fo\x00o" => "b\x00ar" })
747
+ assert_equal(%|{"foo":"bar"}|, json)
748
+
749
+ json = Oj.dump({ "foo\x00" => "\x00bar" })
750
+ assert_equal(%|{"foo":"bar"}|, json)
751
+
752
+ json = Oj.dump({ "\x00foo" => "bar\x00" })
753
+ assert_equal(%|{"foo":"bar"}|, json)
754
+
755
+ json = Oj.dump({ "fo\0o" => "ba\0r" })
756
+ assert_equal(%|{"foo":"bar"}|, json)
757
+
758
+ json = Oj.dump({ "foo\0" => "\0bar" })
759
+ assert_equal(%|{"foo":"bar"}|, json)
760
+
761
+ json = Oj.dump({ "\0foo" => "bar\0" })
762
+ assert_equal(%|{"foo":"bar"}|, json)
763
+
764
+ json = Oj.dump({ "fo\u0000o" => "ba\u0000r" })
765
+ assert_equal(%|{"foo":"bar"}|, json)
766
+
767
+ json = Oj.dump({ "foo\u0000" => "\u0000bar" })
768
+ assert_equal(%|{"foo":"bar"}|, json)
769
+
770
+ json = Oj.dump({ "\u0000foo" => "bar\u0000" })
771
+ assert_equal(%|{"foo":"bar"}|, json)
772
+
773
+ json = Oj.dump({ "\x00foo" => "bar\x00" }, :omit_null_byte => false)
774
+ assert_equal(%|{"\\u0000foo":"bar\\u0000"}|, json)
775
+
776
+ # no change from default set earlier so :omit_null_byte is still true
777
+ json = Oj.dump({ "\x00foo" => "bar\x00" }, :omit_null_byte => nil)
778
+ assert_equal(%|{"foo":"bar"}|, json)
779
+
780
+ Oj.default_options = { :omit_null_byte => false }
781
+
782
+ json = Oj.dump({ "\x00foo" => "bar\x00" })
783
+ assert_equal(%|{"\\u0000foo":"bar\\u0000"}|, json)
784
+
785
+ json = Oj.dump({ "\x00foo" => "bar\x00" }, :omit_null_byte => true)
786
+ assert_equal(%|{"foo":"bar"}|, json)
787
+ end
788
+
740
789
  def dump_and_load(obj, trace=false)
741
790
  json = Oj.dump(obj, :indent => 2)
742
791
  puts json if trace