oj 3.7.4 → 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 (147) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1360 -0
  3. data/README.md +31 -8
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +53 -72
  6. data/ext/oj/cache.c +326 -0
  7. data/ext/oj/cache.h +21 -0
  8. data/ext/oj/cache8.c +61 -64
  9. data/ext/oj/cache8.h +12 -39
  10. data/ext/oj/circarray.c +37 -43
  11. data/ext/oj/circarray.h +16 -17
  12. data/ext/oj/code.c +165 -179
  13. data/ext/oj/code.h +27 -29
  14. data/ext/oj/compat.c +174 -194
  15. data/ext/oj/custom.c +790 -866
  16. data/ext/oj/debug.c +132 -0
  17. data/ext/oj/dump.c +848 -863
  18. data/ext/oj/dump.h +81 -67
  19. data/ext/oj/dump_compat.c +85 -123
  20. data/ext/oj/dump_leaf.c +100 -188
  21. data/ext/oj/dump_object.c +527 -656
  22. data/ext/oj/dump_strict.c +315 -338
  23. data/ext/oj/encode.h +7 -34
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +40 -29
  26. data/ext/oj/err.h +48 -48
  27. data/ext/oj/extconf.rb +17 -4
  28. data/ext/oj/fast.c +1073 -1088
  29. data/ext/oj/intern.c +298 -0
  30. data/ext/oj/intern.h +26 -0
  31. data/ext/oj/mimic_json.c +469 -436
  32. data/ext/oj/object.c +532 -599
  33. data/ext/oj/odd.c +154 -138
  34. data/ext/oj/odd.h +37 -38
  35. data/ext/oj/oj.c +1333 -986
  36. data/ext/oj/oj.h +336 -316
  37. data/ext/oj/parse.c +1002 -846
  38. data/ext/oj/parse.h +92 -87
  39. data/ext/oj/parser.c +1587 -0
  40. data/ext/oj/parser.h +102 -0
  41. data/ext/oj/rails.c +888 -878
  42. data/ext/oj/rails.h +11 -14
  43. data/ext/oj/reader.c +141 -147
  44. data/ext/oj/reader.h +73 -89
  45. data/ext/oj/resolve.c +41 -62
  46. data/ext/oj/resolve.h +7 -9
  47. data/ext/oj/rxclass.c +71 -75
  48. data/ext/oj/rxclass.h +18 -19
  49. data/ext/oj/saj.c +443 -486
  50. data/ext/oj/saj2.c +596 -0
  51. data/ext/oj/saj2.h +23 -0
  52. data/ext/oj/scp.c +88 -113
  53. data/ext/oj/sparse.c +787 -709
  54. data/ext/oj/stream_writer.c +133 -159
  55. data/ext/oj/strict.c +127 -118
  56. data/ext/oj/string_writer.c +230 -249
  57. data/ext/oj/trace.c +34 -41
  58. data/ext/oj/trace.h +19 -19
  59. data/ext/oj/usual.c +1207 -0
  60. data/ext/oj/usual.h +68 -0
  61. data/ext/oj/util.c +136 -0
  62. data/ext/oj/util.h +20 -0
  63. data/ext/oj/val_stack.c +60 -68
  64. data/ext/oj/val_stack.h +91 -129
  65. data/ext/oj/validate.c +46 -0
  66. data/ext/oj/wab.c +342 -353
  67. data/lib/oj/bag.rb +1 -0
  68. data/lib/oj/easy_hash.rb +5 -4
  69. data/lib/oj/error.rb +1 -1
  70. data/lib/oj/json.rb +1 -1
  71. data/lib/oj/mimic.rb +48 -14
  72. data/lib/oj/saj.rb +20 -6
  73. data/lib/oj/state.rb +9 -8
  74. data/lib/oj/version.rb +2 -2
  75. data/lib/oj.rb +0 -8
  76. data/pages/Compatibility.md +1 -1
  77. data/pages/JsonGem.md +15 -0
  78. data/pages/Modes.md +53 -46
  79. data/pages/Options.md +78 -11
  80. data/pages/Parser.md +309 -0
  81. data/pages/Rails.md +73 -22
  82. data/pages/Security.md +1 -1
  83. data/test/activerecord/result_test.rb +7 -2
  84. data/test/activesupport5/abstract_unit.rb +45 -0
  85. data/test/activesupport5/decoding_test.rb +68 -60
  86. data/test/activesupport5/encoding_test.rb +111 -96
  87. data/test/activesupport5/encoding_test_cases.rb +33 -25
  88. data/test/activesupport5/test_helper.rb +43 -21
  89. data/test/activesupport5/time_zone_test_helpers.rb +18 -3
  90. data/test/activesupport6/abstract_unit.rb +44 -0
  91. data/test/activesupport6/decoding_test.rb +133 -0
  92. data/test/activesupport6/encoding_test.rb +507 -0
  93. data/test/activesupport6/encoding_test_cases.rb +98 -0
  94. data/test/activesupport6/test_common.rb +17 -0
  95. data/test/activesupport6/test_helper.rb +163 -0
  96. data/test/activesupport6/time_zone_test_helpers.rb +39 -0
  97. data/test/activesupport7/abstract_unit.rb +49 -0
  98. data/test/activesupport7/decoding_test.rb +125 -0
  99. data/test/activesupport7/encoding_test.rb +486 -0
  100. data/test/activesupport7/encoding_test_cases.rb +104 -0
  101. data/test/activesupport7/time_zone_test_helpers.rb +47 -0
  102. data/test/bar.rb +6 -12
  103. data/test/baz.rb +16 -0
  104. data/test/bug.rb +16 -0
  105. data/test/foo.rb +69 -75
  106. data/test/helper.rb +16 -0
  107. data/test/json_gem/json_common_interface_test.rb +8 -3
  108. data/test/json_gem/json_generator_test.rb +21 -8
  109. data/test/json_gem/json_parser_test.rb +8 -1
  110. data/test/json_gem/test_helper.rb +12 -0
  111. data/test/mem.rb +33 -0
  112. data/test/perf.rb +1 -1
  113. data/test/perf_dump.rb +50 -0
  114. data/test/perf_once.rb +58 -0
  115. data/test/perf_parser.rb +189 -0
  116. data/test/perf_scp.rb +11 -10
  117. data/test/perf_strict.rb +17 -23
  118. data/test/prec.rb +23 -0
  119. data/test/sample_json.rb +1 -1
  120. data/test/test_compat.rb +46 -10
  121. data/test/test_custom.rb +145 -7
  122. data/test/test_fast.rb +62 -2
  123. data/test/test_file.rb +23 -7
  124. data/test/test_gc.rb +11 -0
  125. data/test/test_generate.rb +21 -0
  126. data/test/test_hash.rb +11 -1
  127. data/test/test_integer_range.rb +1 -2
  128. data/test/test_object.rb +43 -12
  129. data/test/test_parser.rb +11 -0
  130. data/test/test_parser_debug.rb +27 -0
  131. data/test/test_parser_saj.rb +335 -0
  132. data/test/test_parser_usual.rb +217 -0
  133. data/test/test_rails.rb +35 -0
  134. data/test/test_saj.rb +1 -1
  135. data/test/test_scp.rb +3 -5
  136. data/test/test_strict.rb +26 -1
  137. data/test/test_various.rb +86 -65
  138. data/test/test_wab.rb +2 -0
  139. data/test/test_writer.rb +19 -2
  140. data/test/tests.rb +10 -1
  141. data/test/tests_mimic.rb +9 -0
  142. data/test/tests_mimic_addition.rb +9 -0
  143. data/test/zoo.rb +13 -0
  144. metadata +63 -110
  145. data/ext/oj/hash.c +0 -163
  146. data/ext/oj/hash.h +0 -46
  147. data/ext/oj/hash_test.c +0 -512
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+
6
+ require 'helper'
7
+
8
+ class UsualTest < Minitest::Test
9
+
10
+ def test_nil
11
+ p = Oj::Parser.new(:usual)
12
+ doc = p.parse('nil')
13
+ assert_nil(doc)
14
+ end
15
+
16
+ def test_primitive
17
+ p = Oj::Parser.new(:usual)
18
+ [
19
+ ['true', true],
20
+ ['false', false],
21
+ ['123', 123],
22
+ ['1.25', 1.25],
23
+ ['"abc"', 'abc'],
24
+ ].each { |x|
25
+ doc = p.parse(x[0])
26
+ assert_equal(x[1], doc)
27
+ }
28
+ end
29
+
30
+ def test_big
31
+ p = Oj::Parser.new(:usual)
32
+ doc = p.parse('12345678901234567890123456789')
33
+ assert_equal(BigDecimal, doc.class)
34
+ doc = p.parse('1234567890.1234567890123456789')
35
+ assert_equal(BigDecimal, doc.class)
36
+ end
37
+
38
+ def test_array
39
+ p = Oj::Parser.new(:usual)
40
+ [
41
+ ['[]', []],
42
+ ['[false]', [false]],
43
+ ['[true,false]', [true,false]],
44
+ ['[[]]', [[]]],
45
+ ['[true,[],false]', [true,[],false]],
46
+ ['[true,[true],false]', [true,[true],false]],
47
+ ].each { |x|
48
+ doc = p.parse(x[0])
49
+ assert_equal(x[1], doc)
50
+ }
51
+ end
52
+
53
+ def test_hash
54
+ p = Oj::Parser.new(:usual)
55
+ [
56
+ ['{}', {}],
57
+ ['{"a": null}', {'a' => nil}],
58
+ ['{"t": true, "f": false, "s": "abc"}', {'t' => true, 'f' => false, 's' => 'abc'}],
59
+ ['{"a": {}}', {'a' => {}}],
60
+ ['{"a": {"b": 2}}', {'a' => {'b' => 2}}],
61
+ ['{"a": [true]}', {'a' => [true]}],
62
+ ].each { |x|
63
+ doc = p.parse(x[0])
64
+ assert_equal(x[1], doc)
65
+ }
66
+ end
67
+
68
+ def test_symbol_keys
69
+ p = Oj::Parser.new(:usual)
70
+ assert_equal(false, p.symbol_keys)
71
+ p.symbol_keys = true
72
+ doc = p.parse('{"a": true, "b": false}')
73
+ assert_equal({a: true, b: false}, doc)
74
+ end
75
+
76
+ def test_strings
77
+ p = Oj::Parser.new(:usual)
78
+ doc = p.parse('{"ぴ": "", "ぴ ": "x", "c": "ぴーたー", "d": " ぴーたー "}')
79
+ assert_equal({'ぴ' => '', 'ぴ ' => 'x', 'c' => 'ぴーたー', 'd' => ' ぴーたー '}, doc)
80
+ end
81
+
82
+ def test_capacity
83
+ p = Oj::Parser.new(:usual, capacity: 1000)
84
+ assert_equal(4096, p.capacity)
85
+ p.capacity = 5000
86
+ assert_equal(5000, p.capacity)
87
+ end
88
+
89
+ def test_decimal
90
+ p = Oj::Parser.new(:usual)
91
+ assert_equal(:auto, p.decimal)
92
+ doc = p.parse('1.234567890123456789')
93
+ assert_equal(BigDecimal, doc.class)
94
+ assert_equal('0.1234567890123456789e1', doc.to_s)
95
+ doc = p.parse('1.25')
96
+ assert_equal(Float, doc.class)
97
+
98
+ p.decimal = :float
99
+ assert_equal(:float, p.decimal)
100
+ doc = p.parse('1.234567890123456789')
101
+ assert_equal(Float, doc.class)
102
+
103
+ p.decimal = :bigdecimal
104
+ assert_equal(:bigdecimal, p.decimal)
105
+ doc = p.parse('1.234567890123456789')
106
+ assert_equal(BigDecimal, doc.class)
107
+ doc = p.parse('1.25')
108
+ assert_equal(BigDecimal, doc.class)
109
+ assert_equal('0.125e1', doc.to_s)
110
+
111
+ p.decimal = :ruby
112
+ assert_equal(:ruby, p.decimal)
113
+ doc = p.parse('1.234567890123456789')
114
+ assert_equal(Float, doc.class)
115
+ end
116
+
117
+ def test_omit_null
118
+ p = Oj::Parser.new(:usual)
119
+ p.omit_null = true
120
+ doc = p.parse('{"a":true,"b":null}')
121
+ assert_equal({'a'=>true}, doc)
122
+
123
+ p.omit_null = false
124
+ doc = p.parse('{"a":true,"b":null}')
125
+ assert_equal({'a'=>true, 'b'=>nil}, doc)
126
+ end
127
+
128
+ class MyArray < Array
129
+ end
130
+
131
+ def test_array_class
132
+ p = Oj::Parser.new(:usual)
133
+ p.array_class = MyArray
134
+ assert_equal(MyArray, p.array_class)
135
+ doc = p.parse('[true]')
136
+ assert_equal(MyArray, doc.class)
137
+ end
138
+
139
+ class MyHash < Hash
140
+ end
141
+
142
+ def test_hash_class
143
+ p = Oj::Parser.new(:usual)
144
+ p.hash_class = MyHash
145
+ assert_equal(MyHash, p.hash_class)
146
+ doc = p.parse('{"a":true}')
147
+ assert_equal(MyHash, doc.class)
148
+ end
149
+
150
+ class MyClass
151
+ attr_accessor :a
152
+ attr_accessor :b
153
+
154
+ def to_s
155
+ "#{self.class}{a: #{@a} b: #{b}}"
156
+ end
157
+ end
158
+
159
+ class MyClass2 < MyClass
160
+ def self.json_create(arg)
161
+ obj = new
162
+ obj.a = arg['a']
163
+ obj.b = arg['b']
164
+ obj
165
+ end
166
+ end
167
+
168
+ def test_create_id
169
+ p = Oj::Parser.new(:usual)
170
+ p.create_id = '^'
171
+ doc = p.parse('{"a":true}')
172
+ assert_equal(Hash, doc.class)
173
+ doc = p.parse('{"a":true,"^":"UsualTest::MyClass","b":false}')
174
+ assert_equal('UsualTest::MyClass{a: true b: false}', doc.to_s)
175
+
176
+ doc = p.parse('{"a":true,"^":"UsualTest::MyClass2","b":false}')
177
+ assert_equal('UsualTest::MyClass2{a: true b: false}', doc.to_s)
178
+
179
+ p.hash_class = MyHash
180
+ assert_equal(MyHash, p.hash_class)
181
+ doc = p.parse('{"a":true}')
182
+ assert_equal(MyHash, doc.class)
183
+
184
+ doc = p.parse('{"a":true,"^":"UsualTest::MyClass","b":false}')
185
+ assert_equal('UsualTest::MyClass{a: true b: false}', doc.to_s)
186
+ end
187
+
188
+ def test_missing_class
189
+ p = Oj::Parser.new(:usual, create_id: '^')
190
+ json = '{"a":true,"^":"Auto","b":false}'
191
+ doc = p.parse(json)
192
+ assert_equal(Hash, doc.class)
193
+
194
+ p.missing_class = :auto
195
+ doc = p.parse(json)
196
+ # Auto should be defined after parsing
197
+ assert_equal(Auto, doc.class)
198
+ end
199
+
200
+ def test_class_cache
201
+ p = Oj::Parser.new(:usual)
202
+ p.create_id = '^'
203
+ p.class_cache = true
204
+ p.missing_class = :auto
205
+ json = '{"a":true,"^":"Auto2","b":false}'
206
+ doc = p.parse(json)
207
+ assert_equal(Auto2, doc.class)
208
+
209
+ doc = p.parse(json)
210
+ assert_equal(Auto2, doc.class)
211
+ end
212
+
213
+ def test_default_parser
214
+ doc = Oj::Parser.usual.parse('{"a":true,"b":null}')
215
+ assert_equal({'a'=>true, 'b'=>nil}, doc)
216
+ end
217
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+
6
+ require 'helper'
7
+
8
+ class RailsJuice < Minitest::Test
9
+
10
+ def test_bigdecimal_dump
11
+ orig = Oj.default_options
12
+ Oj.default_options = { mode: :rails, bigdecimal_as_decimal: true }
13
+ bd = BigDecimal('123')
14
+ json = Oj.dump(bd)
15
+ Oj.default_options = orig
16
+
17
+ assert_equal('0.123e3', json.downcase)
18
+
19
+ json = Oj.dump(bd, mode: :rails, bigdecimal_as_decimal: false)
20
+ assert_equal('"0.123e3"', json.downcase)
21
+
22
+ json = Oj.dump(bd, mode: :rails, bigdecimal_as_decimal: true)
23
+ assert_equal('0.123e3', json.downcase)
24
+ end
25
+
26
+ def test_invalid_encoding
27
+ assert_raises(EncodingError) {
28
+ Oj.dump("\"\xf3j", mode: :rails)
29
+ }
30
+ assert_raises(EncodingError) {
31
+ Oj.dump("\xf3j", mode: :rails)
32
+ }
33
+ end
34
+
35
+ end
data/test/test_saj.rb CHANGED
@@ -180,7 +180,7 @@ class SajTest < Minitest::Test
180
180
  assert_equal([:add_value, 12345, nil], handler.calls.first)
181
181
  type, message, line, column = handler.calls.last
182
182
  assert_equal([:error, 1, 6], [type, line, column])
183
- assert_match(%r{invalid format, extra characters at line 1, column 6 \[(?:[a-z\.]+/)*saj\.c:\d+\]}, message)
183
+ assert_match(%r{invalid format, extra characters at line 1, column 6 \[(?:[A-Za-z]:\/)?(?:[a-z\.]+/)*saj\.c:\d+\]}, message)
184
184
  end
185
185
 
186
186
  end
data/test/test_scp.rb CHANGED
@@ -320,15 +320,14 @@ 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}}
328
327
  IO.pipe do |read_io, write_io|
329
328
  if fork
330
329
  write_io.close
331
- Oj.sc_parse(handler, read_io) {|v| p v}
330
+ Oj.sc_parse(handler, read_io)
332
331
  read_io.close
333
332
  assert_equal([[:hash_start],
334
333
  [:hash_key, 'one'],
@@ -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
@@ -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__)))
@@ -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)
@@ -379,6 +381,29 @@ class StrictJuice < Minitest::Test
379
381
  assert_equal([{ 'x' => 1 }, { 'y' => 2 }], results)
380
382
  end
381
383
 
384
+ def test_invalid_decimal_dot_start
385
+ assert_raises(Oj::ParseError) {
386
+ Oj.load('.123', mode: :strict)
387
+ }
388
+ assert_raises(Oj::ParseError) {
389
+ Oj.load('-.123', mode: :strict)
390
+ }
391
+ end
392
+
393
+ def test_invalid_decimal_dot_end
394
+ json = '123.'
395
+ assert_raises(Oj::ParseError) {
396
+ Oj.load(json, mode: :strict)
397
+ }
398
+ end
399
+
400
+ def test_invalid_decimal_plus
401
+ json = '+12'
402
+ assert_raises(Oj::ParseError) {
403
+ Oj.load(json, mode: :strict)
404
+ }
405
+ end
406
+
382
407
  def test_circular_hash
383
408
  h = { 'a' => 7 }
384
409
  h['b'] = h
data/test/test_various.rb CHANGED
@@ -96,68 +96,49 @@ class Juice < Minitest::Test
96
96
  Oj.default_options = @default_options
97
97
  end
98
98
 
99
- =begin
100
- # Depending on the order the values may have changed. The set_options sets
101
- # should cover the function itself.
102
- def test_get_options
103
- opts = Oj.default_options()
104
- assert_equal({ :indent=>0,
105
- :second_precision=>9,
106
- :circular=>false,
107
- :class_cache=>true,
108
- :auto_define=>false,
109
- :symbol_keys=>false,
110
- :bigdecimal_as_decimal=>true,
111
- :use_to_json=>true,
112
- :nilnil=>false,
113
- :allow_gc=>true,
114
- :quirks_mode=>true,
115
- :allow_invalid_unicode=>false,
116
- :float_precision=>15,
117
- :mode=>:object,
118
- :escape_mode=>:json,
119
- :time_format=>:unix_zone,
120
- :bigdecimal_load=>:auto,
121
- :create_id=>'json_class'}, opts)
122
- end
123
- =end
124
99
  def test_set_options
125
100
  orig = Oj.default_options()
126
101
  alt ={
127
- :indent=>" - ",
128
- :second_precision=>5,
129
- :circular=>true,
130
- :class_cache=>false,
131
- :auto_define=>true,
132
- :symbol_keys=>true,
133
- :bigdecimal_as_decimal=>false,
134
- :use_to_json=>false,
135
- :use_to_hash=>false,
136
- :use_as_json=>false,
137
- :nilnil=>true,
138
- :empty_string=>true,
139
- :allow_gc=>false,
140
- :quirks_mode=>false,
141
- :allow_invalid_unicode=>true,
142
- :float_precision=>13,
143
- :mode=>:strict,
144
- :escape_mode=>:ascii,
145
- :time_format=>:unix_zone,
146
- :bigdecimal_load=>:float,
147
- :create_id=>'classy',
148
- :create_additions=>true,
149
- :space=>'z',
150
- :array_nl=>'a',
151
- :object_nl=>'o',
152
- :space_before=>'b',
153
- :nan=>:huge,
154
- :hash_class=>Hash,
155
- :omit_nil=>false,
156
- :allow_nan=>true,
157
- :integer_range=>nil,
158
- :array_class=>Array,
159
- :ignore=>nil,
160
- :trace=>true,
102
+ indent: " - ",
103
+ second_precision: 5,
104
+ circular: true,
105
+ class_cache: false,
106
+ auto_define: true,
107
+ symbol_keys: true,
108
+ bigdecimal_as_decimal: false,
109
+ use_to_json: false,
110
+ use_to_hash: false,
111
+ use_as_json: false,
112
+ use_raw_json: false,
113
+ nilnil: true,
114
+ empty_string: true,
115
+ allow_gc: false,
116
+ quirks_mode: false,
117
+ allow_invalid_unicode: true,
118
+ float_precision: 13,
119
+ mode: :strict,
120
+ escape_mode: :ascii,
121
+ time_format: :unix_zone,
122
+ bigdecimal_load: :float,
123
+ compat_bigdecimal: true,
124
+ create_id: 'classy',
125
+ create_additions: true,
126
+ cache_keys: false,
127
+ cache_str: 5,
128
+ space: 'z',
129
+ array_nl: 'a',
130
+ object_nl: 'o',
131
+ space_before: 'b',
132
+ nan: :huge,
133
+ hash_class: Hash,
134
+ omit_nil: false,
135
+ allow_nan: true,
136
+ integer_range: nil,
137
+ array_class: Array,
138
+ ignore: nil,
139
+ ignore_under: true,
140
+ trace: true,
141
+ safe: true,
161
142
  }
162
143
  Oj.default_options = alt
163
144
  #keys = alt.keys
@@ -207,7 +188,6 @@ class Juice < Minitest::Test
207
188
  n = Oj.load('-0.000012345678901234567')
208
189
  assert_equal(BigDecimal, n.class)
209
190
  assert_equal('-0.12345678901234567E-4', n.to_s.upcase)
210
-
211
191
  end
212
192
 
213
193
  =begin
@@ -365,6 +345,12 @@ class Juice < Minitest::Test
365
345
  out = Oj.dump hash
366
346
  assert_equal(%{{"key":"I \\u003c3 this"}}, out)
367
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
368
354
  def test_escapes_entities_when_asked_to
369
355
  hash = {'key' => "I <3 this"}
370
356
  out = Oj.dump(hash, :escape_mode => :xss_safe)
@@ -420,6 +406,17 @@ class Juice < Minitest::Test
420
406
  assert_equal('-2208987661.000000000', json)
421
407
  end
422
408
 
409
+ def test_time_years
410
+ (-2020..2020).each { |year|
411
+ s = "%04d-03-01T15:14:13Z" % [year]
412
+ json = Oj.dump(Time.parse(s), mode: :custom, time_format: :xmlschema, second_precision: -1)
413
+ assert_equal(s, json[1..-2])
414
+
415
+ json = Oj.dump(Time.parse(s), mode: :custom, time_format: :xmlschema, second_precision: 3)
416
+ assert_equal(s[0..-2] + '.000Z', json[1..-2])
417
+ }
418
+ end
419
+
423
420
  # Class
424
421
  def test_class_null
425
422
  json = Oj.dump(Juice, :mode => :null)
@@ -537,7 +534,7 @@ class Juice < Minitest::Test
537
534
  assert_equal(58, obj.y)
538
535
  end
539
536
 
540
- # Stream Deeply Nested
537
+ # Stream Deeply Nested
541
538
  def test_deep_nest_dump
542
539
  begin
543
540
  a = []
@@ -550,7 +547,7 @@ class Juice < Minitest::Test
550
547
  assert(false, "*** expected an exception")
551
548
  end
552
549
 
553
- # Stream IO
550
+ # Stream IO
554
551
  def test_io_string
555
552
  src = { 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}
556
553
  output = StringIO.open("", "w+")
@@ -573,6 +570,30 @@ class Juice < Minitest::Test
573
570
  assert_equal(src, obj)
574
571
  end
575
572
 
573
+ def test_io_stream
574
+ skip 'needs fork' unless Process.respond_to?(:fork)
575
+
576
+ IO.pipe do |r, w|
577
+ 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
586
+ 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)
593
+ end
594
+ end
595
+ end
596
+
576
597
  # comments
577
598
  def test_comment_slash
578
599
  json = %{{
@@ -682,13 +703,13 @@ class Juice < Minitest::Test
682
703
  raise e
683
704
  end
684
705
  }
685
- assert_equal('first[2].third', msg.split('(')[1].split(')')[0])
706
+ assert_equal('after first[2].third', msg.split('(')[1].split(')')[0])
686
707
  end
687
708
 
688
709
  def test_bad_bignum
689
710
  if '2.4.0' < RUBY_VERSION
690
- assert_raises Exception do # Can be either Oj::ParseError or ArgumentError depending on Ruby version
691
- Oj.load(%|{ "big": -e123456789 }|)
711
+ assert_raises Oj::ParseError do
712
+ Oj.load(%|{ "big": -e123456789 }|, mode: :strict)
692
713
  end
693
714
  end
694
715
  end
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/test_writer.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
 
@@ -227,6 +227,22 @@ class OjWriter < Minitest::Test
227
227
 
228
228
  # Stream Writer
229
229
 
230
+ class SString < ::String
231
+ alias :write :concat
232
+ end
233
+
234
+ def test_stream_writer_encoding
235
+ output = SString.new.force_encoding(::Encoding::UTF_8)
236
+ w = Oj::StreamWriter.new(output, :indent => 0)
237
+ # Oddly enough, when pushing ASCII characters with UTF-8 encoding or even
238
+ # ASCII-8BIT does not change the output encoding. Pushing any non-ASCII no
239
+ # matter what the encoding changes the output encoding to ASCII-8BIT.
240
+ x = "香港" # Hong Kong
241
+ x = x.force_encoding('ASCII-8BIT')
242
+ w.push_value(x)
243
+ assert_equal(::Encoding::UTF_8, output.encoding)
244
+ end
245
+
230
246
  def test_stream_writer_empty_array
231
247
  output = StringIO.open("", "w+")
232
248
  w = Oj::StreamWriter.new(output, :indent => 0)
@@ -251,7 +267,8 @@ class OjWriter < Minitest::Test
251
267
  w.push_object("a3")
252
268
  w.pop()
253
269
  w.pop()
254
- assert_equal(%|{"a1":{},"a2":{"b":[7,true,"string"]},"a3":{}}\n|, output.string())
270
+ result = output.string()
271
+ assert_equal(%|{"a1":{},"a2":{"b":[7,true,"string"]},"a3":{}}\n|, result)
255
272
  end
256
273
 
257
274
  def test_stream_writer_mixed_file
data/test/tests.rb CHANGED
@@ -18,7 +18,16 @@ require 'test_object'
18
18
  require 'test_saj'
19
19
  require 'test_scp'
20
20
  require 'test_strict'
21
- require 'test_various'
21
+ 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
data/test/zoo.rb ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #require 'json'
4
+
5
+ $: << File.dirname(__FILE__)
6
+ require 'helper'
7
+ require 'oj'
8
+
9
+ Oj.mimic_JSON
10
+ puts "\u3074"
11
+
12
+ puts JSON.dump(["\u3074"])
13
+ puts JSON.generate(["\u3074"])