oj 3.9.1 → 3.16.11

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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1452 -0
  3. data/README.md +21 -6
  4. data/RELEASE_NOTES.md +61 -0
  5. data/ext/oj/buf.h +50 -68
  6. data/ext/oj/cache.c +329 -0
  7. data/ext/oj/cache.h +22 -0
  8. data/ext/oj/cache8.c +60 -62
  9. data/ext/oj/cache8.h +9 -36
  10. data/ext/oj/circarray.c +38 -42
  11. data/ext/oj/circarray.h +12 -13
  12. data/ext/oj/code.c +158 -179
  13. data/ext/oj/code.h +20 -22
  14. data/ext/oj/compat.c +145 -205
  15. data/ext/oj/custom.c +740 -880
  16. data/ext/oj/debug.c +126 -0
  17. data/ext/oj/dump.c +1145 -844
  18. data/ext/oj/dump.h +71 -57
  19. data/ext/oj/dump_compat.c +575 -655
  20. data/ext/oj/dump_leaf.c +96 -186
  21. data/ext/oj/dump_object.c +533 -660
  22. data/ext/oj/dump_strict.c +306 -340
  23. data/ext/oj/encode.h +4 -33
  24. data/ext/oj/encoder.c +43 -0
  25. data/ext/oj/err.c +28 -28
  26. data/ext/oj/err.h +39 -42
  27. data/ext/oj/extconf.rb +28 -7
  28. data/ext/oj/fast.c +1052 -1113
  29. data/ext/oj/intern.c +313 -0
  30. data/ext/oj/intern.h +22 -0
  31. data/ext/oj/mem.c +318 -0
  32. data/ext/oj/mem.h +53 -0
  33. data/ext/oj/mimic_json.c +471 -430
  34. data/ext/oj/object.c +532 -580
  35. data/ext/oj/odd.c +156 -142
  36. data/ext/oj/odd.h +25 -26
  37. data/ext/oj/oj.c +1346 -961
  38. data/ext/oj/oj.h +307 -290
  39. data/ext/oj/parse.c +954 -858
  40. data/ext/oj/parse.h +74 -72
  41. data/ext/oj/parser.c +1600 -0
  42. data/ext/oj/parser.h +103 -0
  43. data/ext/oj/rails.c +819 -836
  44. data/ext/oj/rails.h +8 -11
  45. data/ext/oj/reader.c +136 -147
  46. data/ext/oj/reader.h +69 -83
  47. data/ext/oj/resolve.c +41 -63
  48. data/ext/oj/resolve.h +4 -6
  49. data/ext/oj/rxclass.c +69 -72
  50. data/ext/oj/rxclass.h +12 -13
  51. data/ext/oj/saj.c +440 -485
  52. data/ext/oj/saj2.c +584 -0
  53. data/ext/oj/saj2.h +23 -0
  54. data/ext/oj/scp.c +79 -118
  55. data/ext/oj/simd.h +10 -0
  56. data/ext/oj/sparse.c +739 -709
  57. data/ext/oj/stream_writer.c +141 -175
  58. data/ext/oj/strict.c +103 -128
  59. data/ext/oj/string_writer.c +244 -261
  60. data/ext/oj/trace.c +34 -41
  61. data/ext/oj/trace.h +42 -15
  62. data/ext/oj/usual.c +1218 -0
  63. data/ext/oj/usual.h +69 -0
  64. data/ext/oj/util.c +107 -107
  65. data/ext/oj/util.h +4 -3
  66. data/ext/oj/val_stack.c +61 -78
  67. data/ext/oj/val_stack.h +80 -114
  68. data/ext/oj/validate.c +46 -0
  69. data/ext/oj/wab.c +316 -361
  70. data/lib/oj/active_support_helper.rb +1 -3
  71. data/lib/oj/bag.rb +8 -1
  72. data/lib/oj/easy_hash.rb +9 -9
  73. data/lib/oj/error.rb +1 -2
  74. data/lib/oj/json.rb +162 -150
  75. data/lib/oj/mimic.rb +54 -20
  76. data/lib/oj/saj.rb +20 -6
  77. data/lib/oj/schandler.rb +5 -4
  78. data/lib/oj/state.rb +12 -8
  79. data/lib/oj/version.rb +1 -2
  80. data/lib/oj.rb +2 -8
  81. data/pages/Compatibility.md +1 -1
  82. data/pages/Encoding.md +1 -1
  83. data/pages/InstallOptions.md +20 -0
  84. data/pages/JsonGem.md +15 -0
  85. data/pages/Modes.md +9 -3
  86. data/pages/Options.md +62 -12
  87. data/pages/Parser.md +309 -0
  88. data/pages/Rails.md +73 -22
  89. metadata +68 -192
  90. data/ext/oj/hash.c +0 -163
  91. data/ext/oj/hash.h +0 -46
  92. data/ext/oj/hash_test.c +0 -512
  93. data/test/_test_active.rb +0 -76
  94. data/test/_test_active_mimic.rb +0 -96
  95. data/test/_test_mimic_rails.rb +0 -126
  96. data/test/activerecord/result_test.rb +0 -27
  97. data/test/activesupport4/decoding_test.rb +0 -108
  98. data/test/activesupport4/encoding_test.rb +0 -531
  99. data/test/activesupport4/test_helper.rb +0 -41
  100. data/test/activesupport5/decoding_test.rb +0 -125
  101. data/test/activesupport5/encoding_test.rb +0 -485
  102. data/test/activesupport5/encoding_test_cases.rb +0 -90
  103. data/test/activesupport5/test_helper.rb +0 -50
  104. data/test/activesupport5/time_zone_test_helpers.rb +0 -24
  105. data/test/bar.rb +0 -25
  106. data/test/files.rb +0 -29
  107. data/test/foo.rb +0 -21
  108. data/test/helper.rb +0 -26
  109. data/test/isolated/shared.rb +0 -308
  110. data/test/isolated/test_mimic_after.rb +0 -13
  111. data/test/isolated/test_mimic_alone.rb +0 -12
  112. data/test/isolated/test_mimic_as_json.rb +0 -45
  113. data/test/isolated/test_mimic_before.rb +0 -13
  114. data/test/isolated/test_mimic_define.rb +0 -28
  115. data/test/isolated/test_mimic_rails_after.rb +0 -22
  116. data/test/isolated/test_mimic_rails_before.rb +0 -21
  117. data/test/isolated/test_mimic_redefine.rb +0 -15
  118. data/test/json_gem/json_addition_test.rb +0 -216
  119. data/test/json_gem/json_common_interface_test.rb +0 -148
  120. data/test/json_gem/json_encoding_test.rb +0 -107
  121. data/test/json_gem/json_ext_parser_test.rb +0 -20
  122. data/test/json_gem/json_fixtures_test.rb +0 -35
  123. data/test/json_gem/json_generator_test.rb +0 -383
  124. data/test/json_gem/json_generic_object_test.rb +0 -90
  125. data/test/json_gem/json_parser_test.rb +0 -470
  126. data/test/json_gem/json_string_matching_test.rb +0 -42
  127. data/test/json_gem/test_helper.rb +0 -18
  128. data/test/perf.rb +0 -107
  129. data/test/perf_compat.rb +0 -130
  130. data/test/perf_fast.rb +0 -164
  131. data/test/perf_file.rb +0 -64
  132. data/test/perf_object.rb +0 -138
  133. data/test/perf_saj.rb +0 -109
  134. data/test/perf_scp.rb +0 -151
  135. data/test/perf_simple.rb +0 -287
  136. data/test/perf_strict.rb +0 -145
  137. data/test/perf_wab.rb +0 -131
  138. data/test/sample/change.rb +0 -14
  139. data/test/sample/dir.rb +0 -19
  140. data/test/sample/doc.rb +0 -36
  141. data/test/sample/file.rb +0 -48
  142. data/test/sample/group.rb +0 -16
  143. data/test/sample/hasprops.rb +0 -16
  144. data/test/sample/layer.rb +0 -12
  145. data/test/sample/line.rb +0 -20
  146. data/test/sample/oval.rb +0 -10
  147. data/test/sample/rect.rb +0 -10
  148. data/test/sample/shape.rb +0 -35
  149. data/test/sample/text.rb +0 -20
  150. data/test/sample.rb +0 -54
  151. data/test/sample_json.rb +0 -37
  152. data/test/test_compat.rb +0 -509
  153. data/test/test_custom.rb +0 -503
  154. data/test/test_debian.rb +0 -53
  155. data/test/test_fast.rb +0 -470
  156. data/test/test_file.rb +0 -239
  157. data/test/test_gc.rb +0 -49
  158. data/test/test_hash.rb +0 -29
  159. data/test/test_integer_range.rb +0 -73
  160. data/test/test_null.rb +0 -376
  161. data/test/test_object.rb +0 -1018
  162. data/test/test_saj.rb +0 -186
  163. data/test/test_scp.rb +0 -433
  164. data/test/test_strict.rb +0 -410
  165. data/test/test_various.rb +0 -741
  166. data/test/test_wab.rb +0 -307
  167. data/test/test_writer.rb +0 -380
  168. data/test/tests.rb +0 -24
  169. data/test/tests_mimic.rb +0 -14
  170. data/test/tests_mimic_addition.rb +0 -7
  171. data/test/zoo.rb +0 -13
data/test/test_various.rb DELETED
@@ -1,741 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
-
4
- $: << File.dirname(__FILE__)
5
-
6
- require 'helper'
7
-
8
- class Juice < Minitest::Test
9
- def gen_whitespaced_string(length = Random.new.rand(100))
10
- whitespace_chars = [" ", "\t", "\f", "\n", "\r"]
11
- result = ""
12
- length.times { result << whitespace_chars.sample }
13
- result
14
- end
15
-
16
- module TestModule
17
- end
18
-
19
- class Jam
20
- attr_accessor :x, :y
21
-
22
- def initialize(x, y)
23
- @x = x
24
- @y = y
25
- end
26
-
27
- def eql?(o)
28
- self.class == o.class && @x == o.x && @y == o.y
29
- end
30
- alias == eql?
31
-
32
- end # Jam
33
-
34
- class Jeez < Jam
35
- def initialize(x, y)
36
- super
37
- end
38
-
39
- def to_json()
40
- %{{"json_class":"#{self.class}","x":#{@x},"y":#{@y}}}
41
- end
42
-
43
- def self.json_create(h)
44
- self.new(h['x'], h['y'])
45
- end
46
- end # Jeez
47
-
48
- # contributed by sauliusg to fix as_json
49
- class Orange < Jam
50
- def initialize(x, y)
51
- super
52
- end
53
-
54
- def as_json()
55
- { :json_class => self.class,
56
- :x => @x,
57
- :y => @y }
58
- end
59
-
60
- def self.json_create(h)
61
- self.new(h['x'], h['y'])
62
- end
63
- end
64
-
65
- class Melon < Jam
66
- def initialize(x, y)
67
- super
68
- end
69
-
70
- def as_json(options)
71
- "#{x} #{y}"
72
- end
73
-
74
- def self.json_create(h)
75
- self.new(h['x'], h['y'])
76
- end
77
- end
78
-
79
- class Jazz < Jam
80
- def initialize(x, y)
81
- super
82
- end
83
- def to_hash()
84
- { 'json_class' => self.class.to_s, 'x' => @x, 'y' => @y }
85
- end
86
- def self.json_create(h)
87
- self.new(h['x'], h['y'])
88
- end
89
- end # Jazz
90
-
91
- def setup
92
- @default_options = Oj.default_options
93
- end
94
-
95
- def teardown
96
- Oj.default_options = @default_options
97
- end
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
- def test_set_options
125
- orig = Oj.default_options()
126
- 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
- :use_raw_json=>false,
138
- :nilnil=>true,
139
- :empty_string=>true,
140
- :allow_gc=>false,
141
- :quirks_mode=>false,
142
- :allow_invalid_unicode=>true,
143
- :float_precision=>13,
144
- :mode=>:strict,
145
- :escape_mode=>:ascii,
146
- :time_format=>:unix_zone,
147
- :bigdecimal_load=>:float,
148
- :create_id=>'classy',
149
- :create_additions=>true,
150
- :space=>'z',
151
- :array_nl=>'a',
152
- :object_nl=>'o',
153
- :space_before=>'b',
154
- :nan=>:huge,
155
- :hash_class=>Hash,
156
- :omit_nil=>false,
157
- :allow_nan=>true,
158
- :integer_range=>nil,
159
- :array_class=>Array,
160
- :ignore=>nil,
161
- :trace=>true,
162
- :safe=>true,
163
- }
164
- Oj.default_options = alt
165
- #keys = alt.keys
166
- #Oj.default_options.keys.each { |k| puts k unless keys.include? k}
167
- opts = Oj.default_options()
168
- assert_equal(alt, opts);
169
-
170
- Oj.default_options = orig # return to original
171
- # verify back to original
172
- opts = Oj.default_options()
173
- assert_equal(orig, opts);
174
- end
175
-
176
- def test_nil
177
- dump_and_load(nil, false)
178
- end
179
-
180
- def test_true
181
- dump_and_load(true, false)
182
- end
183
-
184
- def test_false
185
- dump_and_load(false, false)
186
- end
187
-
188
- def test_fixnum
189
- dump_and_load(0, false)
190
- dump_and_load(12345, false)
191
- dump_and_load(-54321, false)
192
- dump_and_load(1, false)
193
- end
194
-
195
- def test_float_parse
196
- Oj.default_options = { :float_precision => 16, :bigdecimal_load => :auto }
197
- n = Oj.load('0.00001234567890123456')
198
- assert_equal(Float, n.class)
199
- assert_equal('1.234567890123456e-05', "%0.15e" % [n])
200
-
201
- n = Oj.load('-0.00001234567890123456')
202
- assert_equal(Float, n.class)
203
- assert_equal('-1.234567890123456e-05', "%0.15e" % [n])
204
-
205
- n = Oj.load('1000.0000123456789')
206
- assert_equal(BigDecimal, n.class)
207
- assert_equal('0.10000000123456789E4', n.to_s.upcase)
208
-
209
- n = Oj.load('-0.000012345678901234567')
210
- assert_equal(BigDecimal, n.class)
211
- assert_equal('-0.12345678901234567E-4', n.to_s.upcase)
212
-
213
- end
214
-
215
- =begin
216
- # TBD move to custom
217
- def test_float_dump
218
- Oj.default_options = { :float_precision => 16 }
219
- assert_equal('1405460727.723866', Oj.dump(1405460727.723866))
220
- Oj.default_options = { :float_precision => 5 }
221
- assert_equal('1.4055', Oj.dump(1.405460727))
222
- Oj.default_options = { :float_precision => 0 }
223
- assert_equal('1405460727.723866', Oj.dump(1405460727.723866))
224
- Oj.default_options = { :float_precision => 15 }
225
- assert_equal('0.56', Oj.dump(0.56))
226
- assert_equal('0.5773', Oj.dump(0.5773))
227
- assert_equal('0.6768', Oj.dump(0.6768))
228
- assert_equal('0.685', Oj.dump(0.685))
229
- assert_equal('0.7032', Oj.dump(0.7032))
230
- assert_equal('0.7051', Oj.dump(0.7051))
231
- assert_equal('0.8274', Oj.dump(0.8274))
232
- assert_equal('0.9149', Oj.dump(0.9149))
233
- assert_equal('64.4', Oj.dump(64.4))
234
- assert_equal('71.6', Oj.dump(71.6))
235
- assert_equal('73.4', Oj.dump(73.4))
236
- assert_equal('80.6', Oj.dump(80.6))
237
- assert_equal('-95.640172', Oj.dump(-95.640172))
238
- end
239
- =end
240
-
241
- def test_string
242
- dump_and_load('', false)
243
- dump_and_load('abc', false)
244
- dump_and_load("abc\ndef", false)
245
- dump_and_load("a\u0041", false)
246
- assert_equal("a\u0000a", dump_and_load("a\u0000a", false))
247
- end
248
-
249
- def test_encode
250
- opts = Oj.default_options
251
- Oj.default_options = { :ascii_only => false }
252
- dump_and_load("ぴーたー", false)
253
-
254
- Oj.default_options = { :ascii_only => true }
255
- json = Oj.dump("ぴーたー")
256
- assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json)
257
- dump_and_load("ぴーたー", false)
258
- Oj.default_options = opts
259
- end
260
-
261
- def test_unicode
262
- # hits the 3 normal ranges and one extended surrogate pair
263
- json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e"}
264
- obj = Oj.load(json)
265
- json2 = Oj.dump(obj, :ascii_only => true)
266
- assert_equal(json, json2)
267
- end
268
-
269
- def test_invalid_unicode_raise
270
- # validate that an invalid unicode raises unless the :allow_invalid_unicode is true
271
- json = %{"x\\ud83dy"}
272
- begin
273
- Oj.load(json)
274
- rescue Exception
275
- assert(true)
276
- return
277
- end
278
- assert(false, "*** expected an exception")
279
- end
280
-
281
- def test_invalid_unicode_ok
282
- # validate that an invalid unicode raises unless the :allow_invalid_unicode is true
283
- json = %{"x\\ud83dy"}
284
- obj = Oj.load(json, :allow_invalid_unicode => true)
285
- # The same as what ruby would do with the invalid encoding.
286
- assert_equal("x\xED\xA0\xBDy", obj.to_s)
287
- end
288
-
289
- def test_dump_options
290
- json = Oj.dump({ 'a' => 1, 'b' => [true, false]},
291
- :mode => :compat,
292
- :indent => "--",
293
- :array_nl => "\n",
294
- :object_nl => "#\n",
295
- :space => "*",
296
- :space_before => "~")
297
- assert(%{{#
298
- --"a"~:*1,#
299
- --"b"~:*[
300
- ----true,
301
- ----false
302
- --]#
303
- }} == json ||
304
- %{{#
305
- --"b"~:*[
306
- ----true,
307
- ----false
308
- --],#
309
- --"a"~:*1#
310
- }} == json)
311
-
312
- end
313
-
314
- def test_null_char
315
- assert_raises(Oj::ParseError) { Oj.load("\"\0\"") }
316
- assert_raises(Oj::ParseError) { Oj.load("\"\\\0\"") }
317
- end
318
-
319
- def test_array
320
- dump_and_load([], false)
321
- dump_and_load([true, false], false)
322
- dump_and_load(['a', 1, nil], false)
323
- dump_and_load([[nil]], false)
324
- dump_and_load([[nil], 58], false)
325
- end
326
- def test_array_not_closed
327
- begin
328
- Oj.load('[')
329
- rescue Exception
330
- assert(true)
331
- return
332
- end
333
- assert(false, "*** expected an exception")
334
- end
335
-
336
- # multiple JSON in one string
337
- def test_multiple_json_callback
338
- json = %{{"a":1}
339
- [1,2][3,4]
340
- {"b":2}
341
- }
342
- results = []
343
- Oj.load(json, :mode => :strict) { |x, start, len| results << [x, start, len] }
344
- assert_equal([[{"a"=>1}, 0, 7], [[1,2], 7, 6], [[3,4], 13, 5], [{"b"=>2}, 18, 8]], results)
345
- end
346
-
347
- def test_multiple_json_no_callback
348
- json = %{{"a":1}
349
- [1,2][3,4]
350
- {"b":2}
351
- }
352
- assert_raises(Oj::ParseError) { Oj.load(json) }
353
- end
354
-
355
- # encoding tests
356
- def test_does_not_escape_entities_by_default
357
- Oj.default_options = { :escape_mode => :ascii } # set in mimic mode
358
- # use Oj to create the hash since some Rubies don't deal nicely with unicode.
359
- json = %{{"key":"I <3 this\\u2028space"}}
360
- hash = Oj.load(json)
361
- out = Oj.dump(hash)
362
- assert_equal(json, out)
363
- end
364
- def test_escapes_entities_by_default_when_configured_to_do_so
365
- hash = {'key' => "I <3 this"}
366
- Oj.default_options = {:escape_mode => :xss_safe}
367
- out = Oj.dump hash
368
- assert_equal(%{{"key":"I \\u003c3 this"}}, out)
369
- end
370
- def test_escapes_entities_when_asked_to
371
- hash = {'key' => "I <3 this"}
372
- out = Oj.dump(hash, :escape_mode => :xss_safe)
373
- assert_equal(%{{"key":"I \\u003c3 this"}}, out)
374
- end
375
- def test_does_not_escape_entities_when_not_asked_to
376
- hash = {'key' => "I <3 this"}
377
- out = Oj.dump(hash, :escape_mode => :json)
378
- assert_equal(%{{"key":"I <3 this"}}, out)
379
- end
380
- def test_escapes_common_xss_vectors
381
- hash = {'key' => "<script>alert(123) && formatHD()</script>"}
382
- out = Oj.dump(hash, :escape_mode => :xss_safe)
383
- assert_equal(%{{"key":"\\u003cscript\\u003ealert(123) \\u0026\\u0026 formatHD()\\u003c\\/script\\u003e"}}, out)
384
- end
385
- def test_escape_newline_by_default
386
- Oj.default_options = { :escape_mode => :json }
387
- json = %{["one","two\\n2"]}
388
- x = Oj.load(json)
389
- out = Oj.dump(x)
390
- assert_equal(json, out)
391
- end
392
- def test_does_not_escape_newline
393
- Oj.default_options = { :escape_mode => :newline }
394
- json = %{["one","two\n2"]}
395
- x = Oj.load(json)
396
- out = Oj.dump(x)
397
- assert_equal(json, out)
398
- end
399
- def test_dump_invalid_utf8
400
- Oj.default_options = { :escape_mode => :ascii }
401
- assert_raises(EncodingError) {
402
- Oj.dump(["abc\xbe\x1f\x11"], mode: :strict)
403
- }
404
- end
405
-
406
- # Symbol
407
- def test_symbol_null
408
- json = Oj.dump(:abc, :mode => :null)
409
- assert_equal('"abc"', json)
410
- end
411
-
412
- # Time
413
- def test_time_null
414
- t = Time.local(2012, 1, 5, 23, 58, 7)
415
- json = Oj.dump(t, :mode => :null)
416
- assert_equal('null', json)
417
- end
418
-
419
- def test_time_neg
420
- t = Time.parse("1900-01-01 00:18:59 UTC")
421
- json = Oj.dump(t, :mode => :custom, :time_format => :unix)
422
- assert_equal('-2208987661.000000000', json)
423
- end
424
-
425
- def test_time_years
426
- (-2020..2020).each { |year|
427
- s = "%04d-03-01T15:14:13Z" % [year]
428
- json = Oj.dump(Time.parse(s), mode: :custom, time_format: :xmlschema)
429
- assert_equal(s, json[1..-2])
430
- }
431
- end
432
-
433
- # Class
434
- def test_class_null
435
- json = Oj.dump(Juice, :mode => :null)
436
- assert_equal('null', json)
437
- end
438
-
439
- # Module
440
- def test_module_null
441
- json = Oj.dump(TestModule, :mode => :null)
442
- assert_equal('null', json)
443
- end
444
-
445
- # Hash
446
- def test_non_str_hash_null
447
- begin
448
- Oj.dump({ 1 => true, 0 => false }, :mode => :null)
449
- rescue Exception
450
- assert(true)
451
- return
452
- end
453
- assert(false, "*** expected an exception")
454
- end
455
-
456
- def test_hash_not_closed
457
- begin
458
- Oj.load('{')
459
- rescue Exception
460
- assert(true)
461
- return
462
- end
463
- assert(false, "*** expected an exception")
464
- end
465
-
466
- # Object with to_json()
467
- def test_json_object_null
468
- obj = Jeez.new(true, 58)
469
- json = Oj.dump(obj, :mode => :null)
470
- assert_equal('null', json)
471
- end
472
-
473
- # Object with to_hash()
474
- def test_to_hash_object_null
475
- obj = Jazz.new(true, 58)
476
- json = Oj.dump(obj, :mode => :null)
477
- assert_equal('null', json)
478
- end
479
-
480
- # Object with as_json() # contributed by sauliusg
481
- def test_as_json_object_null
482
- obj = Orange.new(true, 58)
483
- json = Oj.dump(obj, :mode => :null)
484
- assert_equal('null', json)
485
- end
486
-
487
- # Object without to_json() or to_hash()
488
- def test_object_null
489
- obj = Jam.new(true, 58)
490
- json = Oj.dump(obj, :mode => :null)
491
- assert_equal('null', json)
492
- end
493
-
494
- # Range
495
- def test_range_null
496
- json = Oj.dump(1..7, :mode => :null)
497
- assert_equal('null', json)
498
- end
499
-
500
- # BigNum
501
- def test_bignum_null
502
- json = Oj.dump(7 ** 55, :mode => :null)
503
- assert_equal('30226801971775055948247051683954096612865741943', json)
504
- end
505
-
506
- def test_bignum_object
507
- dump_and_load(7 ** 55, false)
508
- dump_and_load(10 ** 19, false)
509
- end
510
-
511
- # BigDecimal
512
- def test_bigdecimal_null
513
- mode = Oj.default_options[:mode]
514
- Oj.default_options = {:mode => :null}
515
- dump_and_load(BigDecimal('3.14159265358979323846'), false)
516
- Oj.default_options = {:mode => mode}
517
- end
518
-
519
- def test_infinity
520
- n = Oj.load('Infinity', :mode => :object)
521
- assert_equal(BigDecimal('Infinity').to_f, n);
522
- x = Oj.load('Infinity', :mode => :compat)
523
- assert_equal('Infinity', x.to_s)
524
- end
525
-
526
- # Date
527
- def test_date_null
528
- json = Oj.dump(Date.new(2012, 6, 19), :mode => :null)
529
- assert_equal('null', json)
530
- end
531
-
532
- # DateTime
533
- def test_datetime_null
534
- json = Oj.dump(DateTime.new(2012, 6, 19, 20, 19, 27), :mode => :null)
535
- assert_equal('null', json)
536
- end
537
-
538
- # autodefine Oj::Bag
539
- def test_bag
540
- json = %{{
541
- "^o":"Juice::Jem",
542
- "x":true,
543
- "y":58 }}
544
- obj = Oj.load(json, :mode => :object, :auto_define => true)
545
- assert_equal('Juice::Jem', obj.class.name)
546
- assert_equal(true, obj.x)
547
- assert_equal(58, obj.y)
548
- end
549
-
550
- # Stream Deeply Nested
551
- def test_deep_nest_dump
552
- begin
553
- a = []
554
- 10000.times { a << [a] }
555
- Oj.dump(a)
556
- rescue Exception
557
- assert(true)
558
- return
559
- end
560
- assert(false, "*** expected an exception")
561
- end
562
-
563
- # Stream IO
564
- def test_io_string
565
- src = { 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}
566
- output = StringIO.open("", "w+")
567
- Oj.to_stream(output, src)
568
-
569
- input = StringIO.new(output.string())
570
- obj = Oj.load(input, :mode => :strict)
571
- assert_equal(src, obj)
572
- end
573
-
574
- def test_io_file
575
- src = { 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}
576
- filename = File.join(File.dirname(__FILE__), 'open_file_test.json')
577
- File.open(filename, "w") { |f|
578
- Oj.to_stream(f, src)
579
- }
580
- f = File.new(filename)
581
- obj = Oj.load(f, :mode => :strict)
582
- f.close()
583
- assert_equal(src, obj)
584
- end
585
-
586
- # comments
587
- def test_comment_slash
588
- json = %{{
589
- "x":true,//three
590
- "y":58,
591
- "z": [1,2,
592
- 3 // six
593
- ]}
594
- }
595
- obj = Oj.load(json, :mode => :strict)
596
- assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
597
- end
598
-
599
- def test_comment_c
600
- json = %{/*before*/
601
- {
602
- "x"/*one*/:/*two*/true,
603
- "y":58,
604
- "z": [1,2,3]}
605
- }
606
- obj = Oj.load(json, :mode => :strict)
607
- assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
608
- end
609
-
610
- def test_comment
611
- json = %{{
612
- "x"/*one*/:/*two*/true,//three
613
- "y":58/*four*/,
614
- "z": [1,2/*five*/,
615
- 3 // six
616
- ]
617
- }
618
- }
619
- obj = Oj.load(json, :mode => :strict)
620
- assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
621
- end
622
-
623
- def test_nilnil_false
624
- begin
625
- Oj.load(nil, :nilnil => false)
626
- rescue Exception
627
- assert(true)
628
- return
629
- end
630
- assert(false, "*** expected an exception")
631
- end
632
-
633
- def test_nilnil_true
634
- obj = Oj.load(nil, :nilnil => true)
635
- assert_nil(obj)
636
- end
637
-
638
- def test_empty_string_true
639
- result = Oj.load(gen_whitespaced_string, :empty_string => true, mode: :strict)
640
- assert_nil(result)
641
- end
642
-
643
- def test_empty_string_false
644
- # Could be either a Oj::ParseError or an EncodingError depending on
645
- # whether mimic_JSON has been called. Since we don't know when the test
646
- # will be called either is okay.
647
- begin
648
- Oj.load(gen_whitespaced_string, :empty_string => false)
649
- rescue Exception => e
650
- assert(Oj::ParseError == e.class || EncodingError == e.class)
651
- return
652
- end
653
- assert(false, "*** expected an exception")
654
- end
655
-
656
- def test_quirks_null_mode
657
- assert_raises(Oj::ParseError) { Oj.load("null", :quirks_mode => false) }
658
- assert_nil(Oj.load("null", :quirks_mode => true))
659
- end
660
-
661
- def test_quirks_bool_mode
662
- assert_raises(Oj::ParseError) { Oj.load("true", :quirks_mode => false) }
663
- assert_equal(true, Oj.load("true", :quirks_mode => true))
664
- end
665
-
666
- def test_quirks_number_mode
667
- assert_raises(Oj::ParseError) { Oj.load("123", :quirks_mode => false) }
668
- assert_equal(123, Oj.load("123", :quirks_mode => true))
669
- end
670
-
671
- def test_quirks_decimal_mode
672
- assert_raises(Oj::ParseError) { Oj.load("123.45", :quirks_mode => false) }
673
- assert_equal(123.45, Oj.load("123.45", :quirks_mode => true))
674
- end
675
-
676
- def test_quirks_string_mode
677
- assert_raises(Oj::ParseError) { Oj.load('"string"', :quirks_mode => false) }
678
- assert_equal('string', Oj.load('"string"', :quirks_mode => true))
679
- end
680
-
681
- def test_error_path
682
- msg = ''
683
- assert_raises(Oj::ParseError) {
684
- begin
685
- Oj.load(%|{
686
- "first": [
687
- 1, 2, { "third": 123x }
688
- ]
689
- }|)
690
- rescue Oj::ParseError => e
691
- msg = e.message
692
- raise e
693
- end
694
- }
695
- assert_equal('first[2].third', msg.split('(')[1].split(')')[0])
696
- end
697
-
698
- def test_bad_bignum
699
- if '2.4.0' < RUBY_VERSION
700
- assert_raises Oj::ParseError do
701
- Oj.load(%|{ "big": -e123456789 }|, mode: :strict)
702
- end
703
- end
704
- end
705
-
706
- def test_quirks_array_mode
707
- assert_equal([], Oj.load("[]", :quirks_mode => false))
708
- assert_equal([], Oj.load("[]", :quirks_mode => true))
709
- end
710
-
711
- def test_quirks_object_mode
712
- assert_equal({}, Oj.load("{}", :quirks_mode => false))
713
- assert_equal({}, Oj.load("{}", :quirks_mode => true))
714
- end
715
-
716
- def test_omit_nil
717
- jam = Jam.new({'a' => 1, 'b' => nil }, nil)
718
-
719
- json = Oj.dump(jam, :omit_nil => true, :mode => :object)
720
- assert_equal(%|{"^o":"Juice::Jam","x":{"a":1}}|, json)
721
-
722
- json = Oj.dump({'x' => {'a' => 1, 'b' => nil }, 'y' => nil}, :omit_nil => true, :mode => :strict)
723
- assert_equal(%|{"x":{"a":1}}|, json)
724
-
725
- json = Oj.dump({'x' => {'a' => 1, 'b' => nil }, 'y' => nil}, :omit_nil => true, :mode => :null)
726
- assert_equal(%|{"x":{"a":1}}|, json)
727
- end
728
-
729
- def dump_and_load(obj, trace=false)
730
- json = Oj.dump(obj, :indent => 2)
731
- puts json if trace
732
- loaded = Oj.load(json)
733
- if obj.nil?
734
- assert_nil(loaded)
735
- else
736
- assert_equal(obj, loaded)
737
- end
738
- loaded
739
- end
740
-
741
- end