oj 2.18.5 → 3.0.0

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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +33 -226
  3. data/ext/oj/circarray.c +0 -25
  4. data/ext/oj/circarray.h +0 -25
  5. data/ext/oj/code.c +227 -0
  6. data/ext/oj/code.h +40 -0
  7. data/ext/oj/compat.c +126 -38
  8. data/ext/oj/custom.c +1097 -0
  9. data/ext/oj/dump.c +658 -2376
  10. data/ext/oj/dump.h +92 -0
  11. data/ext/oj/dump_compat.c +937 -0
  12. data/ext/oj/dump_leaf.c +254 -0
  13. data/ext/oj/dump_object.c +810 -0
  14. data/ext/oj/dump_rails.c +329 -0
  15. data/ext/oj/dump_strict.c +416 -0
  16. data/ext/oj/err.c +0 -25
  17. data/ext/oj/err.h +8 -2
  18. data/ext/oj/fast.c +24 -24
  19. data/ext/oj/mimic_json.c +817 -0
  20. data/ext/oj/mimic_rails.c +806 -0
  21. data/ext/oj/mimic_rails.h +17 -0
  22. data/ext/oj/object.c +18 -72
  23. data/ext/oj/odd.c +0 -25
  24. data/ext/oj/odd.h +2 -27
  25. data/ext/oj/oj.c +655 -1503
  26. data/ext/oj/oj.h +93 -40
  27. data/ext/oj/parse.c +99 -46
  28. data/ext/oj/parse.h +12 -26
  29. data/ext/oj/reader.c +1 -25
  30. data/ext/oj/reader.h +3 -25
  31. data/ext/oj/resolve.c +9 -11
  32. data/ext/oj/resolve.h +2 -2
  33. data/ext/oj/rxclass.c +133 -0
  34. data/ext/oj/rxclass.h +27 -0
  35. data/ext/oj/saj.c +4 -25
  36. data/ext/oj/scp.c +3 -25
  37. data/ext/oj/sparse.c +89 -13
  38. data/ext/oj/stream_writer.c +301 -0
  39. data/ext/oj/strict.c +4 -27
  40. data/ext/oj/string_writer.c +480 -0
  41. data/ext/oj/val_stack.h +6 -2
  42. data/lib/oj.rb +1 -23
  43. data/lib/oj/easy_hash.rb +12 -4
  44. data/lib/oj/json.rb +172 -0
  45. data/lib/oj/mimic.rb +123 -18
  46. data/lib/oj/state.rb +131 -0
  47. data/lib/oj/version.rb +1 -1
  48. data/pages/Advanced.md +22 -0
  49. data/pages/Compatibility.md +25 -0
  50. data/pages/Custom.md +23 -0
  51. data/pages/Encoding.md +65 -0
  52. data/pages/JsonGem.md +79 -0
  53. data/pages/Modes.md +140 -0
  54. data/pages/Options.md +250 -0
  55. data/pages/Rails.md +60 -0
  56. data/pages/Security.md +20 -0
  57. data/test/activesupport4/decoding_test.rb +105 -0
  58. data/test/activesupport4/encoding_test.rb +531 -0
  59. data/test/activesupport4/test_helper.rb +41 -0
  60. data/test/activesupport5/decoding_test.rb +125 -0
  61. data/test/activesupport5/encoding_test.rb +483 -0
  62. data/test/activesupport5/encoding_test_cases.rb +90 -0
  63. data/test/activesupport5/test_helper.rb +50 -0
  64. data/test/activesupport5/time_zone_test_helpers.rb +24 -0
  65. data/test/json_gem/json_addition_test.rb +216 -0
  66. data/test/json_gem/json_common_interface_test.rb +143 -0
  67. data/test/json_gem/json_encoding_test.rb +109 -0
  68. data/test/json_gem/json_ext_parser_test.rb +20 -0
  69. data/test/json_gem/json_fixtures_test.rb +35 -0
  70. data/test/json_gem/json_generator_test.rb +383 -0
  71. data/test/json_gem/json_generic_object_test.rb +90 -0
  72. data/test/json_gem/json_parser_test.rb +470 -0
  73. data/test/json_gem/json_string_matching_test.rb +42 -0
  74. data/test/json_gem/test_helper.rb +18 -0
  75. data/test/perf_compat.rb +30 -28
  76. data/test/perf_object.rb +1 -1
  77. data/test/perf_strict.rb +18 -1
  78. data/test/sample.rb +0 -1
  79. data/test/test_compat.rb +169 -93
  80. data/test/test_custom.rb +355 -0
  81. data/test/test_file.rb +0 -8
  82. data/test/test_null.rb +376 -0
  83. data/test/test_object.rb +268 -3
  84. data/test/test_scp.rb +22 -1
  85. data/test/test_strict.rb +160 -4
  86. data/test/test_various.rb +52 -620
  87. data/test/tests.rb +14 -0
  88. data/test/tests_mimic.rb +14 -0
  89. data/test/tests_mimic_addition.rb +7 -0
  90. metadata +89 -47
  91. data/test/activesupport_datetime_test.rb +0 -23
  92. data/test/bug.rb +0 -51
  93. data/test/bug2.rb +0 -10
  94. data/test/bug3.rb +0 -46
  95. data/test/bug_fast.rb +0 -32
  96. data/test/bug_load.rb +0 -24
  97. data/test/crash.rb +0 -111
  98. data/test/curl/curl_oj.rb +0 -46
  99. data/test/curl/get_oj.rb +0 -24
  100. data/test/curl/just_curl.rb +0 -31
  101. data/test/curl/just_oj.rb +0 -51
  102. data/test/example.rb +0 -11
  103. data/test/foo.rb +0 -24
  104. data/test/io.rb +0 -48
  105. data/test/isolated/test_mimic_rails_datetime.rb +0 -27
  106. data/test/mod.rb +0 -16
  107. data/test/rails.rb +0 -50
  108. data/test/russian.rb +0 -18
  109. data/test/struct.rb +0 -29
  110. data/test/test_serializer.rb +0 -59
  111. data/test/write_timebars.rb +0 -31
@@ -0,0 +1,355 @@
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 CustomJuice < Minitest::Test
18
+
19
+ module TestModule
20
+ end
21
+
22
+ class Jeez
23
+ attr_accessor :x, :y
24
+
25
+ def initialize(x, y)
26
+ @x = x
27
+ @y = y
28
+ end
29
+ def ==(o)
30
+ self.class == o.class && @x == o.x && @y = o.y
31
+ end
32
+ def to_json(*args)
33
+ %|{"xx":#{@x},"yy":#{y}}|
34
+ end
35
+ def as_json(*args)
36
+ {'a' => @x, :b => @y }
37
+ end
38
+ def to_hash()
39
+ {'b' => @x, 'n' => @y }
40
+ end
41
+ end
42
+
43
+ def setup
44
+ @default_options = Oj.default_options
45
+ Oj.default_options = { :mode => :custom }
46
+ end
47
+
48
+ def teardown
49
+ Oj.default_options = @default_options
50
+ end
51
+
52
+ def test_nil
53
+ dump_and_load(nil, false)
54
+ end
55
+
56
+ def test_true
57
+ dump_and_load(true, false)
58
+ end
59
+
60
+ def test_false
61
+ dump_and_load(false, false)
62
+ end
63
+
64
+ def test_fixnum
65
+ dump_and_load(0, false)
66
+ dump_and_load(12345, false)
67
+ dump_and_load(-54321, false)
68
+ dump_and_load(1, false)
69
+ end
70
+
71
+ def test_float
72
+ dump_and_load(0.0, false)
73
+ dump_and_load(12345.6789, false)
74
+ dump_and_load(70.35, false)
75
+ dump_and_load(-54321.012, false)
76
+ dump_and_load(1.7775, false)
77
+ dump_and_load(2.5024, false)
78
+ dump_and_load(2.48e16, false)
79
+ dump_and_load(2.48e100 * 1.0e10, false)
80
+ dump_and_load(-2.48e100 * 1.0e10, false)
81
+ end
82
+
83
+ def test_nan_dump
84
+ assert_equal('null', Oj.dump(0/0.0, :nan => :null))
85
+ assert_equal('3.3e14159265358979323846', Oj.dump(0/0.0, :nan => :huge))
86
+ assert_equal('NaN', Oj.dump(0/0.0, :nan => :word))
87
+ begin
88
+ Oj.dump(0/0.0, :nan => :raise)
89
+ rescue Exception
90
+ assert(true)
91
+ return
92
+ end
93
+ assert(false, "*** expected an exception")
94
+ end
95
+
96
+ def test_infinity_dump
97
+ assert_equal('null', Oj.dump(1/0.0, :nan => :null))
98
+ assert_equal('3.0e14159265358979323846', Oj.dump(1/0.0, :nan => :huge))
99
+ assert_equal('Infinity', Oj.dump(1/0.0, :nan => :word))
100
+ begin
101
+ Oj.dump(1/0.0, :nan => :raise)
102
+ rescue Exception
103
+ assert(true)
104
+ return
105
+ end
106
+ assert(false, "*** expected an exception")
107
+ end
108
+
109
+ def test_neg_infinity_dump
110
+ assert_equal('null', Oj.dump(-1/0.0, :nan => :null))
111
+ assert_equal('-3.0e14159265358979323846', Oj.dump(-1/0.0, :nan => :huge))
112
+ assert_equal('-Infinity', Oj.dump(-1/0.0, :nan => :word))
113
+ begin
114
+ Oj.dump(-1/0.0, :nan => :raise)
115
+ rescue Exception
116
+ assert(true)
117
+ return
118
+ end
119
+ assert(false, "*** expected an exception")
120
+ end
121
+
122
+ def test_string
123
+ dump_and_load('', false)
124
+ dump_and_load('abc', false)
125
+ dump_and_load("abc\ndef", false)
126
+ dump_and_load("a\u0041", false)
127
+ end
128
+
129
+ def test_string_ascii
130
+ json = Oj.dump("ぴーたー", :escape_mode => :ascii)
131
+ assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json)
132
+ dump_and_load("ぴーたー", false, :escape_mode => :ascii)
133
+ end
134
+
135
+ def test_string_json
136
+ json = Oj.dump("ぴーたー", :escape_mode => :json)
137
+ assert_equal(%{"ぴーたー"}, json)
138
+ dump_and_load("ぴーたー", false, :escape_mode => :json)
139
+ end
140
+
141
+ def test_array
142
+ dump_and_load([], false)
143
+ dump_and_load([true, false], false)
144
+ dump_and_load(['a', 1, nil], false)
145
+ dump_and_load([[nil]], false)
146
+ dump_and_load([[nil], 58], false)
147
+ end
148
+
149
+ def test_array_deep
150
+ dump_and_load([1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20]]]]]]]]]]]]]]]]]]]], false)
151
+ end
152
+
153
+ def test_deep_nest
154
+ begin
155
+ n = 10000
156
+ Oj.strict_load('[' * n + ']' * n)
157
+ rescue Exception => e
158
+ assert(false, e.message)
159
+ end
160
+ end
161
+
162
+ def test_hash
163
+ dump_and_load({}, false)
164
+ dump_and_load({ 'true' => true, 'false' => false}, false)
165
+ dump_and_load({ 'true' => true, 'array' => [], 'hash' => { }}, false)
166
+ end
167
+
168
+ def test_hash_deep
169
+ dump_and_load({'1' => {
170
+ '2' => {
171
+ '3' => {
172
+ '4' => {
173
+ '5' => {
174
+ '6' => {
175
+ '7' => {
176
+ '8' => {
177
+ '9' => {
178
+ '10' => {
179
+ '11' => {
180
+ '12' => {
181
+ '13' => {
182
+ '14' => {
183
+ '15' => {
184
+ '16' => {
185
+ '17' => {
186
+ '18' => {
187
+ '19' => {
188
+ '20' => {}}}}}}}}}}}}}}}}}}}}}, false)
189
+ end
190
+
191
+ def test_hash_escaped_key
192
+ json = %{{"a\nb":true,"c\td":false}}
193
+ obj = Oj.load(json)
194
+ assert_equal({"a\nb" => true, "c\td" => false}, obj)
195
+ end
196
+
197
+ def test_hash_non_string_key
198
+ assert_equal(%|{"1":true}|, Oj.dump({ 1 => true }, :indent => 0))
199
+ end
200
+
201
+ def test_bignum_object
202
+ dump_and_load(7 ** 55, false)
203
+ end
204
+
205
+ def test_bigdecimal
206
+ assert_equal('0.314159265358979323846e1', Oj.dump(BigDecimal.new('3.14159265358979323846'), :bigdecimal_load => true))
207
+ dump_and_load(BigDecimal.new('3.14159265358979323846'), false, :bigdecimal_load => true)
208
+ end
209
+
210
+ def test_object
211
+ obj = Jeez.new(true, 58)
212
+ json = Oj.dump(obj, :create_id => "^o", :use_to_json => false, :use_as_json => false, :use_to_hash => false)
213
+ #puts "*** #{json}"
214
+ dump_and_load(obj, false, :create_id => "^o", :create_additions => true)
215
+ end
216
+
217
+ def test_object_to_json
218
+ obj = Jeez.new(true, 58)
219
+ json = Oj.dump(obj, :use_to_json => true, :use_as_json => false, :use_to_hash => false)
220
+ assert_equal(%|{"xx":true,"yy":58}|, json)
221
+ end
222
+
223
+ def test_object_as_json
224
+ obj = Jeez.new(true, 58)
225
+ json = Oj.dump(obj, :use_to_json => false, :use_as_json => true, :use_to_hash => false)
226
+ assert_equal(%|{"a":true,"b":58}|, json)
227
+ end
228
+
229
+ def test_object_to_hash
230
+ obj = Jeez.new(true, 58)
231
+ json = Oj.dump(obj, :use_to_json => false, :use_as_json => false, :use_to_hash => true)
232
+ assert_equal(%|{"b":true,"n":58}|, json)
233
+ end
234
+
235
+ def test_symbol
236
+ json = Oj.dump(:abc)
237
+ assert_equal('"abc"', json)
238
+ end
239
+
240
+ def test_class
241
+ assert_equal(%|"CustomJuice"|, Oj.dump(CustomJuice))
242
+ end
243
+
244
+ def test_module
245
+ assert_equal(%|"CustomJuice::TestModule"|, Oj.dump(TestModule))
246
+ end
247
+
248
+ def test_symbol_keys
249
+ json = %|{
250
+ "x":true,
251
+ "y":58,
252
+ "z": [1,2,3]
253
+ }
254
+ |
255
+ obj = Oj.load(json, :symbol_keys => true)
256
+ assert_equal({ :x => true, :y => 58, :z => [1, 2, 3]}, obj)
257
+ end
258
+
259
+ def test_double
260
+ json = %{{ "x": 1}{ "y": 2}}
261
+ results = []
262
+ Oj.load(json, :mode => :strict) { |x| results << x }
263
+
264
+ assert_equal([{ 'x' => 1 }, { 'y' => 2 }], results)
265
+ end
266
+
267
+ def test_circular_hash
268
+ h = { 'a' => 7 }
269
+ h['b'] = h
270
+ json = Oj.dump(h, :indent => 2, :circular => true)
271
+ assert_equal(%|{
272
+ "a":7,
273
+ "b":null
274
+ }
275
+ |, json)
276
+ end
277
+
278
+ def test_omit_nil
279
+ json = Oj.dump({'x' => {'a' => 1, 'b' => nil }, 'y' => nil}, :omit_nil => true)
280
+ assert_equal(%|{"x":{"a":1}}|, json)
281
+ end
282
+
283
+ def test_complex
284
+ obj = Complex(2, 9)
285
+ dump_and_load(obj, false, :create_id => "^o", :create_additions => true)
286
+ end
287
+
288
+ def test_rational
289
+ obj = Rational(2, 9)
290
+ dump_and_load(obj, false, :create_id => "^o", :create_additions => true)
291
+ end
292
+
293
+ def test_range
294
+ obj = 3..8
295
+ dump_and_load(obj, false, :create_id => "^o", :create_additions => true)
296
+ end
297
+
298
+ def test_date
299
+ obj = Date.new(2017, 1, 5)
300
+ dump_and_load(obj, false, :create_id => "^o", :create_additions => true)
301
+ end
302
+
303
+ def test_datetime
304
+ obj = DateTime.new(2017, 1, 5, 10, 20, 30)
305
+ dump_and_load(obj, false, :create_id => "^o", :create_additions => true)
306
+ end
307
+
308
+ def test_regexp
309
+ # this notation must be used to get an == match later
310
+ obj = /(?ix-m:^yes$)/
311
+ dump_and_load(obj, false, :create_id => "^o", :create_additions => true)
312
+ end
313
+
314
+ def test_openstruct
315
+ obj = OpenStruct.new(:a => 1, 'b' => 2)
316
+ dump_and_load(obj, false, :create_id => "^o", :create_additions => true)
317
+ end
318
+
319
+ def test_time
320
+ obj = Time.now()
321
+ dump_and_load(obj, false, :time_format => :unix, :create_id => "^o", :create_additions => true)
322
+ dump_and_load_inspect(obj, false, :time_format => :unix_zone, :create_id => "^o", :create_additions => true)
323
+ dump_and_load_inspect(obj, false, :time_format => :xmlschema, :create_id => "^o", :create_additions => true)
324
+ dump_and_load_inspect(obj, false, :time_format => :ruby, :create_id => "^o", :create_additions => true)
325
+ end
326
+
327
+ def dump_and_load(obj, trace=false, options={})
328
+ options = options.merge(:indent => 2, :mode => :custom)
329
+ json = Oj.dump(obj, options)
330
+ puts json if trace
331
+
332
+ loaded = Oj.load(json, options);
333
+ if obj.nil?
334
+ assert_nil(loaded)
335
+ else
336
+ assert_equal(obj, loaded)
337
+ end
338
+ loaded
339
+ end
340
+
341
+ def dump_and_load_inspect(obj, trace=false, options={})
342
+ options = options.merge(:indent => 2, :mode => :custom)
343
+ json = Oj.dump(obj, options)
344
+ puts json if trace
345
+
346
+ loaded = Oj.load(json, options);
347
+ if obj.nil?
348
+ assert_nil(loaded)
349
+ else
350
+ assert_equal(obj.inspect, loaded.inspect)
351
+ end
352
+ loaded
353
+ end
354
+
355
+ end
@@ -156,14 +156,6 @@ class FileJuice < Minitest::Test
156
156
  Oj.default_options = { :mode => :compat, :use_to_json => false }
157
157
  end
158
158
 
159
- def test_as_json_object_compat_hash
160
- Oj.default_options = { :mode => :compat, :use_as_json => true }
161
- obj = Orange.new(true, 58)
162
- json = Oj.dump(obj, :indent => 2)
163
- assert(!json.nil?)
164
- dump_and_load(obj, false)
165
- end
166
-
167
159
  # Range
168
160
  def test_range_object
169
161
  unless RUBY_VERSION.start_with?('1.8')
@@ -0,0 +1,376 @@
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 NullJuice < Minitest::Test
18
+
19
+ module TestModule
20
+ end
21
+
22
+ class Jeez
23
+ attr_accessor :x, :y
24
+
25
+ def initialize(x, y)
26
+ @x = x
27
+ @y = y
28
+ end
29
+ end
30
+
31
+ def setup
32
+ @default_options = Oj.default_options
33
+ # in null mode other options other than the number formats are not used.
34
+ Oj.default_options = { :mode => :null }
35
+ end
36
+
37
+ def teardown
38
+ Oj.default_options = @default_options
39
+ end
40
+
41
+ def test_nil
42
+ dump_and_load(nil, false)
43
+ end
44
+
45
+ def test_true
46
+ dump_and_load(true, false)
47
+ end
48
+
49
+ def test_false
50
+ dump_and_load(false, false)
51
+ end
52
+
53
+ def test_fixnum
54
+ dump_and_load(0, false)
55
+ dump_and_load(12345, false)
56
+ dump_and_load(-54321, false)
57
+ dump_and_load(1, false)
58
+ end
59
+
60
+ def test_float
61
+ dump_and_load(0.0, false)
62
+ dump_and_load(12345.6789, false)
63
+ dump_and_load(70.35, false)
64
+ dump_and_load(-54321.012, false)
65
+ dump_and_load(1.7775, false)
66
+ dump_and_load(2.5024, false)
67
+ dump_and_load(2.48e16, false)
68
+ dump_and_load(2.48e100 * 1.0e10, false)
69
+ dump_and_load(-2.48e100 * 1.0e10, false)
70
+ end
71
+
72
+ def test_nan_dump
73
+ assert_equal('null', Oj.dump(0/0.0, :nan => :null))
74
+ assert_equal('3.3e14159265358979323846', Oj.dump(0/0.0, :nan => :huge))
75
+ begin
76
+ Oj.dump(0/0.0, :nan => :word)
77
+ rescue Exception
78
+ assert(true)
79
+ return
80
+ end
81
+ assert(false, "*** expected an exception")
82
+ end
83
+
84
+ def test_infinity_dump
85
+ assert_equal('null', Oj.dump(1/0.0, :nan => :null))
86
+ assert_equal('3.0e14159265358979323846', Oj.dump(1/0.0, :nan => :huge))
87
+ begin
88
+ Oj.dump(1/0.0, :nan => :word)
89
+ rescue Exception
90
+ assert(true)
91
+ return
92
+ end
93
+ assert(false, "*** expected an exception")
94
+ end
95
+
96
+ def test_neg_infinity_dump
97
+ assert_equal('null', Oj.dump(-1/0.0, :nan => :null))
98
+ assert_equal('-3.0e14159265358979323846', Oj.dump(-1/0.0, :nan => :huge))
99
+ begin
100
+ Oj.dump(-1/0.0, :nan => :word)
101
+ rescue Exception
102
+ assert(true)
103
+ return
104
+ end
105
+ assert(false, "*** expected an exception")
106
+ end
107
+
108
+ def test_string
109
+ dump_and_load('', false)
110
+ dump_and_load('abc', false)
111
+ dump_and_load("abc\ndef", false)
112
+ dump_and_load("a\u0041", false)
113
+ end
114
+
115
+ def test_encode
116
+ opts = Oj.default_options
117
+ Oj.default_options = { :ascii_only => false }
118
+ unless 'jruby' == $ruby
119
+ dump_and_load("ぴーたー", false)
120
+ end
121
+ Oj.default_options = { :ascii_only => true }
122
+ json = Oj.dump("ぴーたー")
123
+ assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json)
124
+ unless 'jruby' == $ruby
125
+ dump_and_load("ぴーたー", false)
126
+ end
127
+ Oj.default_options = opts
128
+ end
129
+
130
+ def test_unicode
131
+ # hits the 3 normal ranges and one extended surrogate pair
132
+ json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e"}
133
+ obj = Oj.load(json)
134
+ json2 = Oj.dump(obj, :ascii_only => true)
135
+ assert_equal(json, json2)
136
+ end
137
+
138
+ def test_unicode_long
139
+ # tests buffer overflow
140
+ json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e #{'x' * 2000}"}
141
+ obj = Oj.load(json)
142
+ json2 = Oj.dump(obj, :ascii_only => true)
143
+ assert_equal(json, json2)
144
+ end
145
+
146
+ def test_array
147
+ dump_and_load([], false)
148
+ dump_and_load([true, false], false)
149
+ dump_and_load(['a', 1, nil], false)
150
+ dump_and_load([[nil]], false)
151
+ dump_and_load([[nil], 58], false)
152
+ end
153
+
154
+ def test_array_deep
155
+ dump_and_load([1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20]]]]]]]]]]]]]]]]]]]], false)
156
+ end
157
+
158
+ # Hash
159
+ def test_hash
160
+ dump_and_load({}, false)
161
+ dump_and_load({ 'true' => true, 'false' => false}, false)
162
+ dump_and_load({ 'true' => true, 'array' => [], 'hash' => { }}, false)
163
+ end
164
+
165
+ def test_hash_deep
166
+ dump_and_load({'1' => {
167
+ '2' => {
168
+ '3' => {
169
+ '4' => {
170
+ '5' => {
171
+ '6' => {
172
+ '7' => {
173
+ '8' => {
174
+ '9' => {
175
+ '10' => {
176
+ '11' => {
177
+ '12' => {
178
+ '13' => {
179
+ '14' => {
180
+ '15' => {
181
+ '16' => {
182
+ '17' => {
183
+ '18' => {
184
+ '19' => {
185
+ '20' => {}}}}}}}}}}}}}}}}}}}}}, false)
186
+ end
187
+
188
+ def test_hash_escaped_key
189
+ json = %{{"a\nb":true,"c\td":false}}
190
+ obj = Oj.strict_load(json)
191
+ assert_equal({"a\nb" => true, "c\td" => false}, obj)
192
+ end
193
+
194
+ def test_non_str_hash
195
+ begin
196
+ Oj.dump({ 1 => true, 0 => false })
197
+ rescue Exception
198
+ assert(true)
199
+ return
200
+ end
201
+ assert(false, "*** expected an exception")
202
+ end
203
+
204
+ def test_bignum_object
205
+ dump_and_load(7 ** 55, false)
206
+ end
207
+
208
+ # BigDecimal
209
+ def test_bigdecimal_strict
210
+ Oj.default_options = { :bigdecimal_load => true}
211
+ dump_and_load(BigDecimal.new('3.14159265358979323846'), false)
212
+ end
213
+
214
+ def test_bigdecimal_load
215
+ orig = BigDecimal.new('80.51')
216
+ json = Oj.dump(orig, :mode => :strict, :bigdecimal_as_decimal => true)
217
+ bg = Oj.load(json, :mode => :strict, :bigdecimal_load => true)
218
+ assert_equal(BigDecimal, bg.class)
219
+ assert_equal(orig, bg)
220
+ end
221
+
222
+ def test_json_object
223
+ obj = Jeez.new(true, 58)
224
+ json = Oj.dump(obj)
225
+ assert_equal('null', json)
226
+ end
227
+
228
+ def test_range
229
+ json = Oj.dump(1..7)
230
+ assert_equal('null', json)
231
+ end
232
+
233
+ # Stream IO
234
+ def test_io_string
235
+ json = %{{
236
+ "x":true,
237
+ "y":58,
238
+ "z": [1,2,3]
239
+ }
240
+ }
241
+ input = StringIO.new(json)
242
+ obj = Oj.strict_load(input)
243
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
244
+ end
245
+
246
+ def test_io_file
247
+ filename = File.join(File.dirname(__FILE__), 'open_file_test.json')
248
+ File.open(filename, 'w') { |f| f.write(%{{
249
+ "x":true,
250
+ "y":58,
251
+ "z": [1,2,3]
252
+ }
253
+ }) }
254
+ f = File.new(filename)
255
+ obj = Oj.strict_load(f)
256
+ f.close()
257
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
258
+ end
259
+
260
+ def test_symbol
261
+ json = Oj.dump(:abc)
262
+ assert_equal('"abc"', json)
263
+ end
264
+
265
+ def test_time
266
+ t = Time.local(2012, 1, 5, 23, 58, 7)
267
+ json = Oj.dump(t)
268
+ assert_equal('null', json)
269
+ end
270
+
271
+ def test_class
272
+ json = Oj.dump(NullJuice)
273
+ assert_equal('null', json)
274
+ end
275
+
276
+ def test_module
277
+ json = Oj.dump(TestModule)
278
+ assert_equal('null', json)
279
+ end
280
+
281
+ # symbol_keys option
282
+ def test_symbol_keys
283
+ json = %{{
284
+ "x":true,
285
+ "y":58,
286
+ "z": [1,2,3]
287
+ }
288
+ }
289
+ obj = Oj.strict_load(json, :symbol_keys => true)
290
+ assert_equal({ :x => true, :y => 58, :z => [1, 2, 3]}, obj)
291
+ end
292
+
293
+ def test_symbol_keys_safe
294
+ json = %{{
295
+ "x":true,
296
+ "y":58,
297
+ "z": [1,2,3]
298
+ }
299
+ }
300
+ obj = Oj.safe_load(json)
301
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
302
+ end
303
+
304
+ # comments
305
+ def test_comment_slash
306
+ json = %{{
307
+ "x":true,//three
308
+ "y":58,
309
+ "z": [1,2,
310
+ 3 // six
311
+ ]}
312
+ }
313
+ obj = Oj.strict_load(json)
314
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
315
+ end
316
+
317
+ def test_comment_c
318
+ json = %{{
319
+ "x"/*one*/:/*two*/true,
320
+ "y":58,
321
+ "z": [1,2,3]}
322
+ }
323
+ obj = Oj.strict_load(json)
324
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
325
+ end
326
+
327
+ def test_comment
328
+ json = %{{
329
+ "x"/*one*/:/*two*/true,//three
330
+ "y":58/*four*/,
331
+ "z": [1,2/*five*/,
332
+ 3 // six
333
+ ]
334
+ }
335
+ }
336
+ obj = Oj.strict_load(json)
337
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
338
+ end
339
+
340
+ def test_double
341
+ json = %{{ "x": 1}{ "y": 2}}
342
+ results = []
343
+ Oj.load(json, :mode => :strict) { |x| results << x }
344
+
345
+ assert_equal([{ 'x' => 1 }, { 'y' => 2 }], results)
346
+ end
347
+
348
+ def test_circular_hash
349
+ h = { 'a' => 7 }
350
+ h['b'] = h
351
+ json = Oj.dump(h, :indent => 2, :circular => true, :mode => :null)
352
+ assert_equal(%|{
353
+ "a":7,
354
+ "b":null
355
+ }
356
+ |, json)
357
+ end
358
+
359
+ def test_omit_nil
360
+ json = Oj.dump({'x' => {'a' => 1, 'b' => nil }, 'y' => nil}, :omit_nil => true)
361
+ assert_equal(%|{"x":{"a":1}}|, json)
362
+ end
363
+
364
+ def dump_and_load(obj, trace=false)
365
+ json = Oj.dump(obj, :indent => 2)
366
+ puts json if trace
367
+ loaded = Oj.strict_load(json);
368
+ if obj.nil?
369
+ assert_nil(loaded)
370
+ else
371
+ assert_equal(obj, loaded)
372
+ end
373
+ loaded
374
+ end
375
+
376
+ end