oj 3.7.12

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