oj 3.10.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +104 -0
  4. data/ext/oj/buf.h +103 -0
  5. data/ext/oj/cache8.c +107 -0
  6. data/ext/oj/cache8.h +48 -0
  7. data/ext/oj/circarray.c +68 -0
  8. data/ext/oj/circarray.h +23 -0
  9. data/ext/oj/code.c +235 -0
  10. data/ext/oj/code.h +42 -0
  11. data/ext/oj/compat.c +299 -0
  12. data/ext/oj/custom.c +1218 -0
  13. data/ext/oj/dump.c +1249 -0
  14. data/ext/oj/dump.h +96 -0
  15. data/ext/oj/dump_compat.c +975 -0
  16. data/ext/oj/dump_leaf.c +252 -0
  17. data/ext/oj/dump_object.c +844 -0
  18. data/ext/oj/dump_strict.c +434 -0
  19. data/ext/oj/encode.h +45 -0
  20. data/ext/oj/err.c +57 -0
  21. data/ext/oj/err.h +70 -0
  22. data/ext/oj/extconf.rb +53 -0
  23. data/ext/oj/fast.c +1771 -0
  24. data/ext/oj/hash.c +163 -0
  25. data/ext/oj/hash.h +46 -0
  26. data/ext/oj/hash_test.c +512 -0
  27. data/ext/oj/mimic_json.c +890 -0
  28. data/ext/oj/object.c +775 -0
  29. data/ext/oj/odd.c +231 -0
  30. data/ext/oj/odd.h +44 -0
  31. data/ext/oj/oj.c +1723 -0
  32. data/ext/oj/oj.h +387 -0
  33. data/ext/oj/parse.c +1134 -0
  34. data/ext/oj/parse.h +112 -0
  35. data/ext/oj/rails.c +1528 -0
  36. data/ext/oj/rails.h +21 -0
  37. data/ext/oj/reader.c +231 -0
  38. data/ext/oj/reader.h +151 -0
  39. data/ext/oj/resolve.c +102 -0
  40. data/ext/oj/resolve.h +14 -0
  41. data/ext/oj/rxclass.c +147 -0
  42. data/ext/oj/rxclass.h +27 -0
  43. data/ext/oj/saj.c +714 -0
  44. data/ext/oj/scp.c +224 -0
  45. data/ext/oj/sparse.c +924 -0
  46. data/ext/oj/stream_writer.c +363 -0
  47. data/ext/oj/strict.c +212 -0
  48. data/ext/oj/string_writer.c +534 -0
  49. data/ext/oj/trace.c +79 -0
  50. data/ext/oj/trace.h +28 -0
  51. data/ext/oj/util.c +136 -0
  52. data/ext/oj/util.h +19 -0
  53. data/ext/oj/val_stack.c +118 -0
  54. data/ext/oj/val_stack.h +185 -0
  55. data/ext/oj/wab.c +631 -0
  56. data/lib/oj.rb +21 -0
  57. data/lib/oj/active_support_helper.rb +41 -0
  58. data/lib/oj/bag.rb +88 -0
  59. data/lib/oj/easy_hash.rb +52 -0
  60. data/lib/oj/error.rb +22 -0
  61. data/lib/oj/json.rb +176 -0
  62. data/lib/oj/mimic.rb +267 -0
  63. data/lib/oj/saj.rb +66 -0
  64. data/lib/oj/schandler.rb +142 -0
  65. data/lib/oj/state.rb +131 -0
  66. data/lib/oj/version.rb +5 -0
  67. data/pages/Advanced.md +22 -0
  68. data/pages/Compatibility.md +25 -0
  69. data/pages/Custom.md +23 -0
  70. data/pages/Encoding.md +65 -0
  71. data/pages/JsonGem.md +79 -0
  72. data/pages/Modes.md +155 -0
  73. data/pages/Options.md +287 -0
  74. data/pages/Rails.md +155 -0
  75. data/pages/Security.md +20 -0
  76. data/pages/WAB.md +13 -0
  77. data/test/_test_active.rb +76 -0
  78. data/test/_test_active_mimic.rb +96 -0
  79. data/test/_test_mimic_rails.rb +126 -0
  80. data/test/activerecord/result_test.rb +27 -0
  81. data/test/activesupport4/decoding_test.rb +108 -0
  82. data/test/activesupport4/encoding_test.rb +531 -0
  83. data/test/activesupport4/test_helper.rb +41 -0
  84. data/test/activesupport5/abstract_unit.rb +45 -0
  85. data/test/activesupport5/decoding_test.rb +133 -0
  86. data/test/activesupport5/encoding_test.rb +500 -0
  87. data/test/activesupport5/encoding_test_cases.rb +98 -0
  88. data/test/activesupport5/test_helper.rb +72 -0
  89. data/test/activesupport5/time_zone_test_helpers.rb +39 -0
  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/bar.rb +35 -0
  98. data/test/baz.rb +16 -0
  99. data/test/files.rb +29 -0
  100. data/test/foo.rb +52 -0
  101. data/test/helper.rb +26 -0
  102. data/test/isolated/shared.rb +308 -0
  103. data/test/isolated/test_mimic_after.rb +13 -0
  104. data/test/isolated/test_mimic_alone.rb +12 -0
  105. data/test/isolated/test_mimic_as_json.rb +45 -0
  106. data/test/isolated/test_mimic_before.rb +13 -0
  107. data/test/isolated/test_mimic_define.rb +28 -0
  108. data/test/isolated/test_mimic_rails_after.rb +22 -0
  109. data/test/isolated/test_mimic_rails_before.rb +21 -0
  110. data/test/isolated/test_mimic_redefine.rb +15 -0
  111. data/test/json_gem/json_addition_test.rb +216 -0
  112. data/test/json_gem/json_common_interface_test.rb +148 -0
  113. data/test/json_gem/json_encoding_test.rb +107 -0
  114. data/test/json_gem/json_ext_parser_test.rb +20 -0
  115. data/test/json_gem/json_fixtures_test.rb +35 -0
  116. data/test/json_gem/json_generator_test.rb +383 -0
  117. data/test/json_gem/json_generic_object_test.rb +90 -0
  118. data/test/json_gem/json_parser_test.rb +470 -0
  119. data/test/json_gem/json_string_matching_test.rb +42 -0
  120. data/test/json_gem/test_helper.rb +18 -0
  121. data/test/perf.rb +107 -0
  122. data/test/perf_compat.rb +130 -0
  123. data/test/perf_fast.rb +164 -0
  124. data/test/perf_file.rb +64 -0
  125. data/test/perf_object.rb +138 -0
  126. data/test/perf_saj.rb +109 -0
  127. data/test/perf_scp.rb +151 -0
  128. data/test/perf_simple.rb +287 -0
  129. data/test/perf_strict.rb +145 -0
  130. data/test/perf_wab.rb +131 -0
  131. data/test/prec.rb +23 -0
  132. data/test/sample.rb +54 -0
  133. data/test/sample/change.rb +14 -0
  134. data/test/sample/dir.rb +19 -0
  135. data/test/sample/doc.rb +36 -0
  136. data/test/sample/file.rb +48 -0
  137. data/test/sample/group.rb +16 -0
  138. data/test/sample/hasprops.rb +16 -0
  139. data/test/sample/layer.rb +12 -0
  140. data/test/sample/line.rb +20 -0
  141. data/test/sample/oval.rb +10 -0
  142. data/test/sample/rect.rb +10 -0
  143. data/test/sample/shape.rb +35 -0
  144. data/test/sample/text.rb +20 -0
  145. data/test/sample_json.rb +37 -0
  146. data/test/test_compat.rb +502 -0
  147. data/test/test_custom.rb +527 -0
  148. data/test/test_debian.rb +53 -0
  149. data/test/test_fast.rb +470 -0
  150. data/test/test_file.rb +239 -0
  151. data/test/test_gc.rb +49 -0
  152. data/test/test_hash.rb +29 -0
  153. data/test/test_integer_range.rb +72 -0
  154. data/test/test_null.rb +376 -0
  155. data/test/test_object.rb +1027 -0
  156. data/test/test_rails.rb +26 -0
  157. data/test/test_saj.rb +186 -0
  158. data/test/test_scp.rb +433 -0
  159. data/test/test_strict.rb +433 -0
  160. data/test/test_various.rb +719 -0
  161. data/test/test_wab.rb +307 -0
  162. data/test/test_writer.rb +380 -0
  163. data/test/tests.rb +25 -0
  164. data/test/tests_mimic.rb +14 -0
  165. data/test/tests_mimic_addition.rb +7 -0
  166. data/test/zoo.rb +13 -0
  167. metadata +381 -0
@@ -0,0 +1,1027 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+
6
+ require 'helper'
7
+
8
+ class ObjectJuice < Minitest::Test
9
+ class Jeez
10
+ attr_accessor :x, :y, :_z
11
+
12
+ def initialize(x, y)
13
+ @x = x
14
+ @y = y
15
+ @_z = x.to_s
16
+ end
17
+
18
+ def eql?(o)
19
+ self.class == o.class && @x == o.x && @y == o.y
20
+ end
21
+ alias == eql?
22
+
23
+ def to_json(*a)
24
+ %{{"json_class":"#{self.class}","x":#{@x},"y":#{@y}}}
25
+ end
26
+
27
+ def self.json_create(h)
28
+ self.new(h['x'], h['y'])
29
+ end
30
+ end # Jeez
31
+
32
+ class Jam
33
+ attr_accessor :x, :y
34
+
35
+ def initialize(x, y)
36
+ @x = x
37
+ @y = y
38
+ end
39
+
40
+ def eql?(o)
41
+ self.class == o.class && @x == o.x && @y == o.y
42
+ end
43
+ alias == eql?
44
+
45
+ end # Jam
46
+
47
+ class Jazz < Jam
48
+ def initialize(x, y)
49
+ super
50
+ end
51
+ def to_hash()
52
+ { 'json_class' => self.class.to_s, 'x' => @x, 'y' => @y }
53
+ end
54
+ def self.json_create(h)
55
+ self.new(h['x'], h['y'])
56
+ end
57
+ end # Jazz
58
+
59
+ class Orange < Jam
60
+ def initialize(x, y)
61
+ super
62
+ end
63
+
64
+ def as_json()
65
+ { :json_class => self.class,
66
+ :x => @x,
67
+ :y => @y }
68
+ end
69
+
70
+ def self.json_create(h)
71
+ self.new(h['x'], h['y'])
72
+ end
73
+ end
74
+
75
+ module One
76
+ module Two
77
+ module Three
78
+ class Deep
79
+
80
+ def initialize()
81
+ end
82
+
83
+ def eql?(o)
84
+ self.class == o.class
85
+ end
86
+ alias == eql?
87
+
88
+ def to_hash()
89
+ {'json_class' => "#{self.class.name}"}
90
+ end
91
+
92
+ def to_json(*a)
93
+ %{{"json_class":"#{self.class.name}"}}
94
+ end
95
+
96
+ def self.json_create(h)
97
+ self.new()
98
+ end
99
+ end # Deep
100
+ end # Three
101
+ end # Two
102
+
103
+ class Stuck2 < Struct.new(:a, :b)
104
+ end
105
+
106
+ end # One
107
+
108
+ class Stuck < Struct.new(:a, :b)
109
+ end
110
+
111
+ class Strung < String
112
+
113
+ def initialize(str, safe)
114
+ super(str)
115
+ @safe = safe
116
+ end
117
+
118
+ def safe?()
119
+ @safe
120
+ end
121
+
122
+ def self.create(str, safe)
123
+ new(str, safe)
124
+ end
125
+
126
+ def eql?(o)
127
+ super && self.class == o.class && @safe == o.safe?
128
+ end
129
+ alias == eql?
130
+
131
+ def inspect()
132
+ return super + '(' + @safe + ')'
133
+ end
134
+ end
135
+
136
+ class AutoStrung < String
137
+ attr_accessor :safe
138
+
139
+ def initialize(str, safe)
140
+ super(str)
141
+ @safe = safe
142
+ end
143
+
144
+ def eql?(o)
145
+ self.class == o.class && super(o) && @safe == o.safe
146
+ end
147
+ alias == eql?
148
+ end
149
+
150
+ class AutoArray < Array
151
+ attr_accessor :safe
152
+
153
+ def initialize(a, safe)
154
+ super(a)
155
+ @safe = safe
156
+ end
157
+
158
+ def eql?(o)
159
+ self.class == o.class && super(o) && @safe == o.safe
160
+ end
161
+ alias == eql?
162
+ end
163
+
164
+ class AutoHash < Hash
165
+ attr_accessor :safe
166
+
167
+ def initialize(h, safe)
168
+ super(h)
169
+ @safe = safe
170
+ end
171
+
172
+ def eql?(o)
173
+ self.class == o.class && super(o) && @safe == o.safe
174
+ end
175
+ alias == eql?
176
+ end
177
+
178
+ class Raw
179
+ attr_accessor :json
180
+
181
+ def initialize(j)
182
+ @json = j
183
+ end
184
+
185
+ def to_json(*a)
186
+ @json
187
+ end
188
+
189
+ def self.create(h)
190
+ h
191
+ end
192
+ end # Raw
193
+
194
+ module Ichi
195
+ module Ni
196
+ def self.direct(h)
197
+ h
198
+ end
199
+
200
+ module San
201
+ class Shi
202
+
203
+ attr_accessor :hash
204
+
205
+ def initialize(h)
206
+ @hash = h
207
+ end
208
+
209
+ def dump()
210
+ @hash
211
+ end
212
+
213
+ end # Shi
214
+ end # San
215
+ end # Ni
216
+ end # Ichi
217
+
218
+ def setup
219
+ @default_options = Oj.default_options
220
+ end
221
+
222
+ def teardown
223
+ Oj.default_options = @default_options
224
+ end
225
+
226
+ def test_nil
227
+ dump_and_load(nil, false)
228
+ end
229
+
230
+ def test_true
231
+ dump_and_load(true, false)
232
+ end
233
+
234
+ def test_false
235
+ dump_and_load(false, false)
236
+ end
237
+
238
+ def test_fixnum
239
+ dump_and_load(0, false)
240
+ dump_and_load(12345, false)
241
+ dump_and_load(-54321, false)
242
+ dump_and_load(1, false)
243
+ end
244
+
245
+ def test_float
246
+ dump_and_load(0.0, false)
247
+ dump_and_load(12345.6789, false)
248
+ dump_and_load(70.35, false)
249
+ dump_and_load(-54321.012, false)
250
+ dump_and_load(1.7775, false)
251
+ dump_and_load(2.5024, false)
252
+ dump_and_load(2.48e16, false)
253
+ dump_and_load(2.48e100 * 1.0e10, false)
254
+ dump_and_load(-2.48e100 * 1.0e10, false)
255
+ dump_and_load(1/0.0, false)
256
+ # NaN does not always == NaN
257
+ json = Oj.dump(0/0.0, :mode => :object)
258
+ assert_equal('3.3e14159265358979323846', json)
259
+ loaded = Oj.load(json);
260
+ assert_equal(true, loaded.nan?)
261
+ end
262
+
263
+ def test_string
264
+ dump_and_load('', false)
265
+ dump_and_load('abc', false)
266
+ dump_and_load("abc\ndef", false)
267
+ dump_and_load("a\u0041", false)
268
+ end
269
+
270
+ def test_symbol
271
+ dump_and_load(:abc, false)
272
+ dump_and_load(":abc", false)
273
+ dump_and_load(':xyz'.to_sym, false)
274
+ end
275
+
276
+ def test_encode
277
+ opts = Oj.default_options
278
+ Oj.default_options = { :ascii_only => false }
279
+ dump_and_load("ぴーたー", false)
280
+ Oj.default_options = { :ascii_only => true }
281
+ json = Oj.dump("ぴーたー")
282
+ assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json)
283
+ dump_and_load("ぴーたー", false)
284
+ Oj.default_options = opts
285
+ end
286
+
287
+ def test_unicode
288
+ # hits the 3 normal ranges and one extended surrogate pair
289
+ json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e"}
290
+ obj = Oj.load(json)
291
+ json2 = Oj.dump(obj, :ascii_only => true)
292
+ assert_equal(json, json2)
293
+ end
294
+
295
+ def test_array
296
+ dump_and_load([], false)
297
+ dump_and_load([true, false], false)
298
+ dump_and_load(['a', 1, nil], false)
299
+ dump_and_load([[nil]], false)
300
+ dump_and_load([[nil], 58], false)
301
+ end
302
+
303
+ def test_array_deep
304
+ dump_and_load([1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20]]]]]]]]]]]]]]]]]]]], false)
305
+ end
306
+
307
+ # Hash
308
+ def test_hash
309
+ dump_and_load({}, false)
310
+ dump_and_load({ 'true' => true, 'false' => false}, false)
311
+ dump_and_load({ 'true' => true, 'array' => [], 'hash' => { }}, false)
312
+ end
313
+
314
+ def test_hash_deep
315
+ dump_and_load({'1' => {
316
+ '2' => {
317
+ '3' => {
318
+ '4' => {
319
+ '5' => {
320
+ '6' => {
321
+ '7' => {
322
+ '8' => {
323
+ '9' => {
324
+ '10' => {
325
+ '11' => {
326
+ '12' => {
327
+ '13' => {
328
+ '14' => {
329
+ '15' => {
330
+ '16' => {
331
+ '17' => {
332
+ '18' => {
333
+ '19' => {
334
+ '20' => {}}}}}}}}}}}}}}}}}}}}}, false)
335
+ end
336
+
337
+ def test_hash_escaped_key
338
+ json = %{{"a\nb":true,"c\td":false}}
339
+ obj = Oj.object_load(json)
340
+ assert_equal({"a\nb" => true, "c\td" => false}, obj)
341
+ end
342
+
343
+ def test_bignum_object
344
+ dump_and_load(7 ** 55, false)
345
+ end
346
+
347
+ # BigDecimal
348
+ def test_bigdecimal_object
349
+ dump_and_load(BigDecimal('3.14159265358979323846'), false)
350
+ end
351
+
352
+ def test_bigdecimal_load
353
+ orig = BigDecimal('80.51')
354
+ json = Oj.dump(orig, :mode => :object, :bigdecimal_as_decimal => true)
355
+ bg = Oj.load(json, :mode => :object, :bigdecimal_load => true)
356
+ assert_equal(BigDecimal, bg.class)
357
+ assert_equal(orig, bg)
358
+ # Infinity is the same for Float and BigDecimal
359
+ json = Oj.dump(BigDecimal('Infinity'), :mode => :object)
360
+ assert_equal('Infinity', json)
361
+ json = Oj.dump(BigDecimal('-Infinity'), :mode => :object)
362
+ assert_equal('-Infinity', json)
363
+ end
364
+
365
+ # Stream IO
366
+ def test_io_string
367
+ json = %{{
368
+ "x":true,
369
+ "y":58,
370
+ "z": [1,2,3]
371
+ }
372
+ }
373
+ input = StringIO.new(json)
374
+ obj = Oj.object_load(input)
375
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
376
+ end
377
+
378
+ def test_io_file
379
+ filename = File.join(File.dirname(__FILE__), 'open_file_test.json')
380
+ File.open(filename, 'w') { |f| f.write(%{{
381
+ "x":true,
382
+ "y":58,
383
+ "z": [1,2,3]
384
+ }
385
+ }) }
386
+ f = File.new(filename)
387
+ obj = Oj.object_load(f)
388
+ f.close()
389
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
390
+ end
391
+
392
+ # symbol_keys option
393
+ def test_symbol_keys
394
+ json = %{{
395
+ "x":true,
396
+ "y":58,
397
+ "z": [1,2,3]
398
+ }
399
+ }
400
+ obj = Oj.object_load(json, :symbol_keys => true)
401
+ assert_equal({ :x => true, :y => 58, :z => [1, 2, 3]}, obj)
402
+ end
403
+
404
+ def test_class_object
405
+ dump_and_load(ObjectJuice, false)
406
+ end
407
+
408
+ def test_module_object
409
+ dump_and_load(One, false)
410
+ end
411
+
412
+ def test_non_str_hash_object
413
+ json = Oj.dump({ 1 => true, :sim => nil }, :mode => :object)
414
+ h = Oj.load(json, :mode => :strict)
415
+ assert_equal({"^#1" => [1, true], ":sim" => nil}, h)
416
+ h = Oj.load(json, :mode => :object)
417
+ assert_equal({ 1 => true, :sim => nil }, h)
418
+ end
419
+
420
+ # comments
421
+ def test_comment_slash
422
+ json = %{{
423
+ "x":true,//three
424
+ "y":58,
425
+ "z": [1,2,
426
+ 3 // six
427
+ ]}
428
+ }
429
+ obj = Oj.object_load(json)
430
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
431
+ end
432
+
433
+ def test_comment_c
434
+ json = %{{
435
+ "x"/*one*/:/*two*/true,
436
+ "y":58,
437
+ "z": [1,2,3]}
438
+ }
439
+ obj = Oj.object_load(json)
440
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
441
+ end
442
+
443
+ def test_comment
444
+ json = %{{
445
+ "x"/*one*/:/*two*/true,//three
446
+ "y":58/*four*/,
447
+ "z": [1,2/*five*/,
448
+ 3 // six
449
+ ]
450
+ }
451
+ }
452
+ obj = Oj.object_load(json)
453
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
454
+ end
455
+
456
+ def test_json_module_object
457
+ obj = One::Two::Three::Deep.new()
458
+ dump_and_load(obj, false)
459
+ end
460
+
461
+ def test_xml_time
462
+ t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
463
+ # The fractional seconds are not always recreated exactly which causes a
464
+ # mismatch so instead the seconds, nsecs, and gmt_offset are checked
465
+ # separately along with utc.
466
+ json = Oj.dump(t, :mode => :object, :time_format => :xmlschema)
467
+ #puts "*** json for test_xml_time '#{json}'"
468
+ loaded = Oj.object_load(json);
469
+ assert_equal(t.tv_sec, loaded.tv_sec)
470
+ if t.respond_to?(:tv_nsec)
471
+ assert_equal(t.tv_nsec, loaded.tv_nsec)
472
+ else
473
+ assert_equal(t.tv_usec, loaded.tv_usec)
474
+ end
475
+ assert_equal(t.utc?, loaded.utc?)
476
+ assert_equal(t.utc_offset, loaded.utc_offset)
477
+ end
478
+
479
+ def test_xml_time_utc
480
+ t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
481
+ # The fractional seconds are not always recreated exactly which causes a
482
+ # mismatch so instead the seconds, nsecs, and gmt_offset are checked
483
+ # separately along with utc.
484
+ json = Oj.dump(t, :mode => :object, :time_format => :xmlschema)
485
+ loaded = Oj.object_load(json);
486
+ assert_equal(t.tv_sec, loaded.tv_sec)
487
+ if t.respond_to?(:tv_nsec)
488
+ assert_equal(t.tv_nsec, loaded.tv_nsec)
489
+ else
490
+ assert_equal(t.tv_usec, loaded.tv_usec)
491
+ end
492
+ assert_equal(t.utc?, loaded.utc?)
493
+ assert_equal(t.utc_offset, loaded.utc_offset)
494
+ end
495
+
496
+ def test_ruby_time
497
+ t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
498
+ # The fractional seconds are not always recreated exactly which causes a
499
+ # mismatch so instead the seconds, nsecs, and gmt_offset are checked
500
+ # separately along with utc.
501
+ json = Oj.dump(t, :mode => :object, :time_format => :ruby)
502
+ #puts "*** json for test_ruby_time '#{json}'"
503
+ loaded = Oj.object_load(json);
504
+ assert_equal(t.tv_sec, loaded.tv_sec)
505
+ if t.respond_to?(:tv_nsec)
506
+ assert_equal(t.tv_nsec, loaded.tv_nsec)
507
+ else
508
+ assert_equal(t.tv_usec, loaded.tv_usec)
509
+ end
510
+ assert_equal(t.utc?, loaded.utc?)
511
+ assert_equal(t.utc_offset, loaded.utc_offset)
512
+ end
513
+
514
+ def test_ruby_time_12345
515
+ t = Time.new(2015, 1, 5, 21, 37, 7.123456789, 12345/60*60)
516
+ # The fractional seconds are not always recreated exactly which causes a
517
+ # mismatch so instead the seconds, nsecs, and gmt_offset are checked
518
+ # separately along with utc.
519
+ json = Oj.dump(t, :mode => :object, :time_format => :ruby)
520
+ #puts "*** json for test_ruby_time '#{json}'"
521
+ loaded = Oj.object_load(json);
522
+ #puts "*** loaded: #{loaded}"
523
+ assert_equal(t.tv_sec, loaded.tv_sec)
524
+ if t.respond_to?(:tv_nsec)
525
+ assert_equal(t.tv_nsec, loaded.tv_nsec)
526
+ else
527
+ assert_equal(t.tv_usec, loaded.tv_usec)
528
+ end
529
+ assert_equal(t.utc?, loaded.utc?)
530
+ assert_equal(t.utc_offset, loaded.utc_offset)
531
+ end
532
+
533
+ def test_ruby_time_utc
534
+ t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
535
+ # The fractional seconds are not always recreated exactly which causes a
536
+ # mismatch so instead the seconds, nsecs, and gmt_offset are checked
537
+ # separately along with utc.
538
+ json = Oj.dump(t, :mode => :object, :time_format => :ruby)
539
+ #puts json
540
+ loaded = Oj.object_load(json);
541
+ assert_equal(t.tv_sec, loaded.tv_sec)
542
+ if t.respond_to?(:tv_nsec)
543
+ assert_equal(t.tv_nsec, loaded.tv_nsec)
544
+ else
545
+ assert_equal(t.tv_usec, loaded.tv_usec)
546
+ end
547
+ assert_equal(t.utc?, loaded.utc?)
548
+ assert_equal(t.utc_offset, loaded.utc_offset)
549
+ end
550
+
551
+ def test_time_early
552
+ # Windows does not support dates before 1970.
553
+ return if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
554
+
555
+ t = Time.new(1954, 1, 5, 21, 37, 7.123456789, -8 * 3600)
556
+ # The fractional seconds are not always recreated exactly which causes a
557
+ # mismatch so instead the seconds, nsecs, and gmt_offset are checked
558
+ # separately along with utc.
559
+ json = Oj.dump(t, :mode => :object, :time_format => :unix_zone)
560
+ #puts json
561
+ loaded = Oj.object_load(json);
562
+ assert_equal(t.tv_sec, loaded.tv_sec)
563
+ if t.respond_to?(:tv_nsec)
564
+ assert_equal(t.tv_nsec, loaded.tv_nsec)
565
+ else
566
+ assert_equal(t.tv_usec, loaded.tv_usec)
567
+ end
568
+ assert_equal(t.utc?, loaded.utc?)
569
+ assert_equal(t.utc_offset, loaded.utc_offset)
570
+ end
571
+
572
+ def test_time_unix_zone
573
+ t = Time.new(2015, 1, 5, 21, 37, 7.123456789, -8 * 3600)
574
+ # The fractional seconds are not always recreated exactly which causes a
575
+ # mismatch so instead the seconds, nsecs, and gmt_offset are checked
576
+ # separately along with utc.
577
+ json = Oj.dump(t, :mode => :object, :time_format => :unix_zone)
578
+ #puts json
579
+ loaded = Oj.object_load(json);
580
+ assert_equal(t.tv_sec, loaded.tv_sec)
581
+ if t.respond_to?(:tv_nsec)
582
+ assert_equal(t.tv_nsec, loaded.tv_nsec)
583
+ else
584
+ assert_equal(t.tv_usec, loaded.tv_usec)
585
+ end
586
+ assert_equal(t.utc?, loaded.utc?)
587
+ assert_equal(t.utc_offset, loaded.utc_offset)
588
+ end
589
+
590
+ def test_time_unix_zone_12345
591
+ t = Time.new(2015, 1, 5, 21, 37, 7.123456789, 12345)
592
+ # The fractional seconds are not always recreated exactly which causes a
593
+ # mismatch so instead the seconds, nsecs, and gmt_offset are checked
594
+ # separately along with utc.
595
+ json = Oj.dump(t, :mode => :object, :time_format => :unix_zone)
596
+ #puts json
597
+ loaded = Oj.object_load(json);
598
+ assert_equal(t.tv_sec, loaded.tv_sec)
599
+ if t.respond_to?(:tv_nsec)
600
+ assert_equal(t.tv_nsec, loaded.tv_nsec)
601
+ else
602
+ assert_equal(t.tv_usec, loaded.tv_usec)
603
+ end
604
+ assert_equal(t.utc?, loaded.utc?)
605
+ assert_equal(t.utc_offset, loaded.utc_offset)
606
+ end
607
+
608
+ def test_time_unix_zone_utc
609
+ t = Time.utc(2015, 1, 5, 21, 37, 7.123456789)
610
+ # The fractional seconds are not always recreated exactly which causes a
611
+ # mismatch so instead the seconds, nsecs, and gmt_offset are checked
612
+ # separately along with utc.
613
+ json = Oj.dump(t, :mode => :object, :time_format => :unix_zone)
614
+ #puts json
615
+ loaded = Oj.object_load(json);
616
+ assert_equal(t.tv_sec, loaded.tv_sec)
617
+ if t.respond_to?(:tv_nsec)
618
+ assert_equal(t.tv_nsec, loaded.tv_nsec)
619
+ else
620
+ assert_equal(t.tv_usec, loaded.tv_usec)
621
+ end
622
+ assert_equal(t.utc?, loaded.utc?)
623
+ assert_equal(t.utc_offset, loaded.utc_offset)
624
+ end
625
+
626
+ def test_json_object
627
+ obj = Jeez.new(true, 58)
628
+ dump_and_load(obj, false)
629
+ end
630
+
631
+ def test_json_object_create_deep
632
+ obj = One::Two::Three::Deep.new()
633
+ dump_and_load(obj, false)
634
+ end
635
+
636
+ def test_json_object_bad
637
+ json = %{{"^o":"Junk","x":true}}
638
+ begin
639
+ Oj.object_load(json)
640
+ rescue Exception => e
641
+ assert_equal("ArgumentError", e.class().name)
642
+ return
643
+ end
644
+ assert(false, "*** expected an exception")
645
+ end
646
+
647
+ def test_json_object_not_hat_hash
648
+ json = %{{"^#x":[1,2]}}
649
+ h = Oj.object_load(json)
650
+ assert_equal({1 => 2}, h);
651
+
652
+ json = %{{"~#x":[1,2]}}
653
+ h = Oj.object_load(json)
654
+ assert_equal({'~#x' => [1,2]}, h);
655
+ end
656
+
657
+ def test_json_struct
658
+ obj = Stuck.new(false, 7)
659
+ dump_and_load(obj, false)
660
+ end
661
+
662
+ def test_json_struct2
663
+ obj = One::Stuck2.new(false, 7)
664
+ dump_and_load(obj, false)
665
+ end
666
+
667
+ def test_json_anonymous_struct
668
+ s = Struct.new(:x, :y)
669
+ obj = s.new(1, 2)
670
+ json = Oj.dump(obj, :indent => 2, :mode => :object)
671
+ #puts json
672
+ loaded = Oj.object_load(json);
673
+ assert_equal(obj.members, loaded.members)
674
+ assert_equal(obj.values, loaded.values)
675
+ end
676
+
677
+ def test_json_non_str_hash
678
+ obj = { 59 => "young", false => true }
679
+ dump_and_load(obj, false)
680
+ end
681
+
682
+ def test_mixed_hash_object
683
+ Oj.default_options = { :mode => :object }
684
+ json = Oj.dump({ 1 => true, 'nil' => nil, :sim => 4 })
685
+ h = Oj.object_load(json)
686
+ assert_equal({ 1 => true, 'nil' => nil, :sim => 4 }, h)
687
+ end
688
+
689
+ def test_json_object_object
690
+ obj = Jeez.new(true, 58)
691
+ json = Oj.dump(obj, mode: :object, indent: 2, ignore_under: true)
692
+ assert(%{{
693
+ "^o":"ObjectJuice::Jeez",
694
+ "x":true,
695
+ "y":58
696
+ }
697
+ } == json ||
698
+ %{{
699
+ "^o":"ObjectJuice::Jeez",
700
+ "y":58,
701
+ "x":true
702
+ }
703
+ } == json)
704
+ obj2 = Oj.load(json, :mode => :object)
705
+ assert_equal(obj, obj2)
706
+ end
707
+
708
+ def test_to_hash_object_object
709
+ obj = Jazz.new(true, 58)
710
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
711
+ assert(%{{
712
+ "^o":"ObjectJuice::Jazz",
713
+ "x":true,
714
+ "y":58
715
+ }
716
+ } == json ||
717
+ %{{
718
+ "^o":"ObjectJuice::Jazz",
719
+ "y":58,
720
+ "x":true
721
+ }
722
+ } == json)
723
+ obj2 = Oj.load(json, :mode => :object)
724
+ assert_equal(obj, obj2)
725
+ end
726
+
727
+ def test_as_json_object_object
728
+ obj = Orange.new(true, 58)
729
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
730
+ assert(%{{
731
+ "^o":"ObjectJuice::Orange",
732
+ "x":true,
733
+ "y":58
734
+ }
735
+ } == json ||
736
+ %{{
737
+ "^o":"ObjectJuice::Orange",
738
+ "y":58,
739
+ "x":true
740
+ }
741
+ } == json)
742
+ obj2 = Oj.load(json, :mode => :object)
743
+ assert_equal(obj, obj2)
744
+ end
745
+
746
+ def test_object_object_no_cache
747
+ obj = Jam.new(true, 58)
748
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
749
+ assert(%{{
750
+ "^o":"ObjectJuice::Jam",
751
+ "x":true,
752
+ "y":58
753
+ }
754
+ } == json ||
755
+ %{{
756
+ "^o":"ObjectJuice::Jam",
757
+ "y":58,
758
+ "x":true
759
+ }
760
+ } == json)
761
+ obj2 = Oj.load(json, :mode => :object, :class_cache => false)
762
+ assert_equal(obj, obj2)
763
+ end
764
+
765
+ def test_ignore
766
+ obj = Jeez.new(true, 58)
767
+ json = Oj.dump({ 'a' => 7, 'b' => obj }, :mode => :object, :indent => 2, :ignore => [ Jeez ])
768
+ assert_equal(%|{
769
+ "a":7
770
+ }
771
+ |, json)
772
+ end
773
+
774
+ def test_exception
775
+ err = nil
776
+ begin
777
+ raise StandardError.new('A Message')
778
+ rescue Exception => e
779
+ err = e
780
+ end
781
+ json = Oj.dump(err, :mode => :object, :indent => 2)
782
+ #puts "*** #{json}"
783
+ e2 = Oj.load(json, :mode => :strict)
784
+ assert_equal(err.class.to_s, e2['^o'])
785
+ assert_equal(err.message, e2['~mesg'])
786
+ assert_equal(err.backtrace, e2['~bt'])
787
+ e2 = Oj.load(json, :mode => :object)
788
+ if 'rubinius' == $ruby
789
+ assert_equal(e.class, e2.class);
790
+ assert_equal(e.message, e2.message);
791
+ assert_equal(e.backtrace, e2.backtrace);
792
+ else
793
+ assert_equal(e, e2);
794
+ end
795
+ end
796
+
797
+ class SubX < Exception
798
+ def initialize
799
+ super("sub")
800
+ @xyz = 123
801
+ end
802
+ end
803
+
804
+ def test_exception_subclass
805
+ err = nil
806
+ begin
807
+ raise SubX.new
808
+ rescue Exception => e
809
+ err = e
810
+ end
811
+ json = Oj.dump(err, :mode => :object, :indent => 2)
812
+ #puts "*** #{json}"
813
+ e2 = Oj.load(json, :mode => :strict)
814
+ assert_equal(err.class.to_s, e2['^o'])
815
+ assert_equal(err.message, e2['~mesg'])
816
+ assert_equal(err.backtrace, e2['~bt'])
817
+ e2 = Oj.load(json, :mode => :object)
818
+ assert_equal(e, e2);
819
+ end
820
+
821
+ def test_range_object
822
+ Oj.default_options = { :mode => :object }
823
+ json = Oj.dump(1..7, :mode => :object, :indent => 0)
824
+ if 'rubinius' == $ruby
825
+ assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
826
+ else
827
+ assert_equal(%{{"^u":["Range",1,7,false]}}, json)
828
+ end
829
+ dump_and_load(1..7, false)
830
+ dump_and_load(1..1, false)
831
+ dump_and_load(1...7, false)
832
+ end
833
+
834
+ def test_circular_hash
835
+ h = { 'a' => 7 }
836
+ h['b'] = h
837
+ json = Oj.dump(h, :mode => :object, :indent => 2, :circular => true)
838
+ h2 = Oj.object_load(json, :circular => true)
839
+ assert_equal(h2['b'].__id__, h2.__id__)
840
+ end
841
+
842
+
843
+ def test_json_object_missing_fields
844
+ json = %{{ "^u": [ "ObjectJuice::Stuck",1]}}
845
+
846
+ obj = Oj.load(json, mode: :object)
847
+ assert_nil(obj['b'])
848
+ end
849
+
850
+ def test_circular_array
851
+ a = [7]
852
+ a << a
853
+ json = Oj.dump(a, :mode => :object, :indent => 2, :circular => true)
854
+ a2 = Oj.object_load(json, :circular => true)
855
+ assert_equal(a2[1].__id__, a2.__id__)
856
+ end
857
+
858
+ def test_circular_array2
859
+ a = [7]
860
+ a << a
861
+ json = Oj.dump(a, :mode => :object, :indent => 2, :circular => true)
862
+ assert_equal(%{[
863
+ "^i1",
864
+ 7,
865
+ "^r1"
866
+ ]
867
+ }, json)
868
+ a2 = Oj.load(json, :mode => :object, :circular => true)
869
+ assert_equal(a2[1].__id__, a2.__id__)
870
+ end
871
+
872
+ def test_circular_array3
873
+ a = ['^r1']
874
+ json = Oj.dump(a, mode: :object, circular: true)
875
+ assert_equal(%{["^i1","\\u005er1"]}, json)
876
+ a2 = Oj.load(json, mode: :object, circular: true)
877
+ assert_equal(a, a2)
878
+ end
879
+
880
+ def test_circular_hash2
881
+ h = { 'a' => 7 }
882
+ h['b'] = h
883
+ json = Oj.dump(h, :mode => :object, :indent => 2, :circular => true)
884
+ ha = Oj.load(json, :mode => :strict)
885
+ assert_equal({'^i' => 1, 'a' => 7, 'b' => '^r1'}, ha)
886
+ Oj.load(json, :mode => :object, :circular => true)
887
+ assert_equal(h['b'].__id__, h.__id__)
888
+ end
889
+
890
+ def test_circular_object
891
+ obj = Jeez.new(nil, 58)
892
+ obj.x = obj
893
+ json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
894
+ obj2 = Oj.object_load(json, :circular => true)
895
+ assert_equal(obj2.x.__id__, obj2.__id__)
896
+ end
897
+
898
+ def test_circular_object2
899
+ obj = Jam.new(nil, 58)
900
+ obj.x = obj
901
+ json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
902
+ assert(%{{
903
+ "^o":"ObjectJuice::Jam",
904
+ "^i":1,
905
+ "x":"^r1",
906
+ "y":58
907
+ }
908
+ } == json ||
909
+ %{{
910
+ "^o":"ObjectJuice::Jam",
911
+ "^i":1,
912
+ "y":58,
913
+ "x":"^r1"
914
+ }
915
+ } == json)
916
+ obj2 = Oj.load(json, :mode => :object, :circular => true)
917
+ assert_equal(obj2.x.__id__, obj2.__id__)
918
+ end
919
+
920
+ def test_circular
921
+ h = { 'a' => 7 }
922
+ obj = Jeez.new(h, 58)
923
+ obj.x['b'] = obj
924
+ json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
925
+ Oj.object_load(json, :circular => true)
926
+ assert_equal(obj.x.__id__, h.__id__)
927
+ assert_equal(h['b'].__id__, obj.__id__)
928
+ end
929
+
930
+ def test_circular2
931
+ h = { 'a' => 7 }
932
+ obj = Jam.new(h, 58)
933
+ obj.x['b'] = obj
934
+ json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
935
+ ha = Oj.load(json, :mode => :strict)
936
+ assert_equal({'^o' => 'ObjectJuice::Jam', '^i' => 1, 'x' => { '^i' => 2, 'a' => 7, 'b' => '^r1' }, 'y' => 58 }, ha)
937
+ Oj.load(json, :mode => :object, :circular => true)
938
+ assert_equal(obj.x.__id__, h.__id__)
939
+ assert_equal(h['b'].__id__, obj.__id__)
940
+ end
941
+
942
+ def test_omit_nil
943
+ jam = Jam.new({'a' => 1, 'b' => nil }, nil)
944
+
945
+ json = Oj.dump(jam, :omit_nil => true, :mode => :object)
946
+ assert_equal(%|{"^o":"ObjectJuice::Jam","x":{"a":1}}|, json)
947
+ end
948
+
949
+ def test_odd_date
950
+ dump_and_load(Date.new(2012, 6, 19), false)
951
+ end
952
+
953
+ def test_odd_datetime
954
+ dump_and_load(DateTime.new(2012, 6, 19, 13, 5, Rational(4, 3)), false)
955
+ dump_and_load(DateTime.new(2012, 6, 19, 13, 5, Rational(7123456789, 1000000000)), false)
956
+ end
957
+
958
+ def test_bag
959
+ json = %{{
960
+ "^o":"ObjectJuice::Jem",
961
+ "x":true,
962
+ "y":58 }}
963
+ obj = Oj.load(json, :mode => :object, :auto_define => true)
964
+ assert_equal('ObjectJuice::Jem', obj.class.name)
965
+ assert_equal(true, obj.x)
966
+ assert_equal(58, obj.y)
967
+ end
968
+
969
+ def test_odd_string
970
+ Oj.register_odd(Strung, Strung, :create, :to_s, 'safe?')
971
+ s = Strung.new("Pete", true)
972
+ dump_and_load(s, false)
973
+ end
974
+
975
+ def test_odd_date_replaced
976
+ Oj.register_odd(Date, Date, :jd, :jd)
977
+ json = Oj.dump(Date.new(2015, 3, 7), :mode => :object)
978
+ assert_equal(%|{"^O":"Date","jd":2457089}|, json)
979
+ dump_and_load(Date.new(2012, 6, 19), false)
980
+ end
981
+
982
+ def test_odd_raw
983
+ Oj.register_odd_raw(Raw, Raw, :create, :to_json)
984
+ json = Oj.dump(Raw.new(%|{"a":1}|), :mode => :object)
985
+ assert_equal(%|{"^O":"ObjectJuice::Raw","to_json":{"a":1}}|, json)
986
+ h = Oj.load(json, :mode => :object)
987
+ assert_equal({'a' => 1}, h)
988
+ end
989
+
990
+ def test_odd_mod
991
+ Oj.register_odd(Ichi::Ni, Ichi::Ni, :direct, :dump)
992
+ json = Oj.dump(Ichi::Ni::San::Shi.new({'a' => 1}), :mode => :object)
993
+ assert_equal(%|{"^O":"ObjectJuice::Ichi::Ni::San::Shi","dump":{"a":1}}|, json)
994
+ h = Oj.load(json, :mode => :object)
995
+ assert_equal({'a' => 1}, h)
996
+ end
997
+
998
+ def test_auto_string
999
+ s = AutoStrung.new("Pete", true)
1000
+ dump_and_load(s, false)
1001
+ end
1002
+
1003
+ def test_auto_array
1004
+ a = AutoArray.new([1, 'abc', nil], true)
1005
+ dump_and_load(a, false)
1006
+ end
1007
+
1008
+ def test_auto_hash
1009
+ h = AutoHash.new(nil, true)
1010
+ h['a'] = 1
1011
+ h['b'] = 2
1012
+ dump_and_load(h, false)
1013
+ end
1014
+
1015
+ def dump_and_load(obj, trace=false)
1016
+ json = Oj.dump(obj, :indent => 2, :mode => :object)
1017
+ puts json if trace
1018
+ loaded = Oj.object_load(json);
1019
+ if obj.nil?
1020
+ assert_nil(loaded)
1021
+ else
1022
+ assert_equal(obj, loaded)
1023
+ end
1024
+ loaded
1025
+ end
1026
+
1027
+ end