oj 2.1.3 → 2.1.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of oj might be problematic. Click here for more details.

Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -4
  3. data/ext/oj/compat.c +3 -4
  4. data/ext/oj/encode.h +51 -0
  5. data/ext/oj/fast.c +4 -9
  6. data/ext/oj/object.c +7 -19
  7. data/ext/oj/oj.c +32 -12
  8. data/ext/oj/oj.h +3 -0
  9. data/ext/oj/parse.c +2 -3
  10. data/ext/oj/saj.c +4 -9
  11. data/ext/oj/scp.c +5 -12
  12. data/ext/oj/strict.c +5 -12
  13. data/lib/oj/version.rb +1 -1
  14. data/test/a.rb +38 -0
  15. data/test/bug.rb +15 -0
  16. data/test/e.rb +12 -0
  17. data/test/files.rb +29 -0
  18. data/test/foo.rb +24 -0
  19. data/test/mj.rb +48 -0
  20. data/test/perf.rb +107 -0
  21. data/test/perf_compat.rb +128 -0
  22. data/test/perf_fast.rb +164 -0
  23. data/test/perf_object.rb +136 -0
  24. data/test/perf_saj.rb +109 -0
  25. data/test/perf_scp.rb +151 -0
  26. data/test/perf_simple.rb +287 -0
  27. data/test/perf_strict.rb +127 -0
  28. data/test/sample.rb +55 -0
  29. data/test/sample/change.rb +14 -0
  30. data/test/sample/dir.rb +19 -0
  31. data/test/sample/doc.rb +36 -0
  32. data/test/sample/file.rb +48 -0
  33. data/test/sample/group.rb +16 -0
  34. data/test/sample/hasprops.rb +16 -0
  35. data/test/sample/layer.rb +12 -0
  36. data/test/sample/line.rb +20 -0
  37. data/test/sample/oval.rb +10 -0
  38. data/test/sample/rect.rb +10 -0
  39. data/test/sample/shape.rb +35 -0
  40. data/test/sample/text.rb +20 -0
  41. data/test/sample_json.rb +37 -0
  42. data/test/test_compat.rb +342 -0
  43. data/test/test_fast.rb +416 -0
  44. data/test/test_mimic.rb +208 -0
  45. data/test/test_mimic_after.rb +35 -0
  46. data/test/test_object.rb +390 -0
  47. data/test/test_saj.rb +184 -0
  48. data/test/test_scp.rb +224 -0
  49. data/test/test_strict.rb +259 -0
  50. data/test/tests.rb +1017 -0
  51. data/test/x.rb +59 -0
  52. metadata +41 -2
@@ -0,0 +1,1017 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
5
+ # required. That can be set in the RUBYOPT environment variable.
6
+ # export RUBYOPT=-w
7
+
8
+ $VERBOSE = true
9
+
10
+ $: << File.join(File.dirname(__FILE__), "../lib")
11
+ $: << File.join(File.dirname(__FILE__), "../ext")
12
+
13
+ require 'test/unit'
14
+ require 'stringio'
15
+ require 'date'
16
+ require 'bigdecimal'
17
+ require 'oj'
18
+
19
+ $ruby = RUBY_DESCRIPTION.split(' ')[0]
20
+ $ruby = 'ree' if 'ruby' == $ruby && RUBY_DESCRIPTION.include?('Ruby Enterprise Edition')
21
+
22
+ def hash_eql(h1, h2)
23
+ return false if h1.size != h2.size
24
+ h1.keys.each do |k|
25
+ return false unless h1[k] == h2[k]
26
+ end
27
+ true
28
+ end
29
+
30
+ class Jam
31
+ attr_accessor :x, :y
32
+
33
+ def initialize(x, y)
34
+ @x = x
35
+ @y = y
36
+ end
37
+
38
+ def eql?(o)
39
+ self.class == o.class && @x == o.x && @y == o.y
40
+ end
41
+ alias == eql?
42
+
43
+ end # Jam
44
+
45
+ class Jeez < Jam
46
+ def initialize(x, y)
47
+ super
48
+ end
49
+
50
+ def to_json()
51
+ %{{"json_class":"#{self.class}","x":#{@x},"y":#{@y}}}
52
+ end
53
+
54
+ def self.json_create(h)
55
+ self.new(h['x'], h['y'])
56
+ end
57
+ end # Jeez
58
+
59
+ # contributed by sauliusg to fix as_json
60
+ class Orange < Jam
61
+ def initialize(x, y)
62
+ super
63
+ end
64
+
65
+ def as_json()
66
+ { :json_class => self.class,
67
+ :x => @x,
68
+ :y => @y }
69
+ end
70
+
71
+ def self.json_create(h)
72
+ self.new(h['x'], h['y'])
73
+ end
74
+ end
75
+
76
+ class Melon < Jam
77
+ def initialize(x, y)
78
+ super
79
+ end
80
+
81
+ def as_json()
82
+ "#{x} #{y}"
83
+ end
84
+
85
+ def self.json_create(h)
86
+ self.new(h['x'], h['y'])
87
+ end
88
+ end
89
+
90
+ class Jazz < Jam
91
+ def initialize(x, y)
92
+ super
93
+ end
94
+ def to_hash()
95
+ { 'json_class' => self.class.to_s, 'x' => @x, 'y' => @y }
96
+ end
97
+ def self.json_create(h)
98
+ self.new(h['x'], h['y'])
99
+ end
100
+ end # Jazz
101
+
102
+ class Range
103
+ def to_hash()
104
+ { 'begin' => self.begin, 'end' => self.end, 'exclude_end' => self.exclude_end? }
105
+ end
106
+ end # Range
107
+
108
+ class Juice < ::Test::Unit::TestCase
109
+
110
+ def test0_get_options
111
+ opts = Oj.default_options()
112
+ assert_equal({ :indent=>0,
113
+ :second_precision=>9,
114
+ :circular=>false,
115
+ :auto_define=>false,
116
+ :symbol_keys=>false,
117
+ :class_cache=>true,
118
+ :ascii_only=>false,
119
+ :mode=>:object,
120
+ :time_format=>:unix,
121
+ :bigdecimal_as_decimal=>true,
122
+ :bigdecimal_load=>false,
123
+ :create_id=>'json_class'}, opts)
124
+ end
125
+
126
+ def test0_set_options
127
+ orig = {
128
+ :indent=>0,
129
+ :second_precision=>9,
130
+ :circular=>false,
131
+ :auto_define=>false,
132
+ :symbol_keys=>false,
133
+ :class_cache=>true,
134
+ :ascii_only=>false,
135
+ :mode=>:object,
136
+ :time_format=>:unix,
137
+ :bigdecimal_as_decimal=>true,
138
+ :bigdecimal_load=>false,
139
+ :create_id=>'json_class'}
140
+ o2 = {
141
+ :indent=>4,
142
+ :second_precision=>7,
143
+ :circular=>true,
144
+ :auto_define=>true,
145
+ :symbol_keys=>true,
146
+ :class_cache=>false,
147
+ :ascii_only=>true,
148
+ :mode=>:compat,
149
+ :time_format=>:ruby,
150
+ :bigdecimal_as_decimal=>false,
151
+ :bigdecimal_load=>true,
152
+ :create_id=>nil}
153
+ o3 = { :indent => 4 }
154
+ Oj.default_options = o2
155
+ opts = Oj.default_options()
156
+ assert_equal(o2, opts);
157
+ Oj.default_options = o3 # see if it throws an exception
158
+ Oj.default_options = orig # return to original
159
+ end
160
+
161
+ def test_nil
162
+ dump_and_load(nil, false)
163
+ end
164
+
165
+ def test_true
166
+ dump_and_load(true, false)
167
+ end
168
+
169
+ def test_false
170
+ dump_and_load(false, false)
171
+ end
172
+
173
+ def test_fixnum
174
+ dump_and_load(0, false)
175
+ dump_and_load(12345, false)
176
+ dump_and_load(-54321, false)
177
+ dump_and_load(1, false)
178
+ end
179
+
180
+ def test_float
181
+ dump_and_load(0.0, false)
182
+ dump_and_load(12345.6789, false)
183
+ dump_and_load(70.35, false)
184
+ dump_and_load(-54321.012, false)
185
+ dump_and_load(2.48e16, false)
186
+ dump_and_load(2.48e100 * 1.0e10, false)
187
+ dump_and_load(-2.48e100 * 1.0e10, false)
188
+ end
189
+
190
+ def test_string
191
+ dump_and_load('', false)
192
+ dump_and_load('abc', false)
193
+ dump_and_load("abc\ndef", false)
194
+ dump_and_load("a\u0041", false)
195
+ end
196
+
197
+ def test_string_object
198
+ dump_and_load('abc', false)
199
+ dump_and_load(':abc', false)
200
+ end
201
+
202
+ def test_encode
203
+ opts = Oj.default_options
204
+ Oj.default_options = { :ascii_only => false }
205
+ unless 'jruby' == $ruby
206
+ dump_and_load("ぴーたー", false)
207
+ end
208
+ Oj.default_options = { :ascii_only => true }
209
+ json = Oj.dump("ぴーたー")
210
+ assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json)
211
+ unless 'jruby' == $ruby
212
+ dump_and_load("ぴーたー", false)
213
+ end
214
+ Oj.default_options = opts
215
+ end
216
+
217
+ def test_unicode
218
+ # hits the 3 normal ranges and one extended surrogate pair
219
+ json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e"}
220
+ obj = Oj.load(json)
221
+ json2 = Oj.dump(obj, :ascii_only => true)
222
+ assert_equal(json, json2)
223
+ end
224
+
225
+ def test_array
226
+ dump_and_load([], false)
227
+ dump_and_load([true, false], false)
228
+ dump_and_load(['a', 1, nil], false)
229
+ dump_and_load([[nil]], false)
230
+ dump_and_load([[nil], 58], false)
231
+ end
232
+
233
+ # Symbol
234
+ def test_symbol_strict
235
+ begin
236
+ Oj.dump(:abc, :mode => :strict)
237
+ rescue Exception
238
+ assert(true)
239
+ return
240
+ end
241
+ assert(false, "*** expected an exception")
242
+ end
243
+ def test_symbol_null
244
+ json = Oj.dump(:abc, :mode => :null)
245
+ assert_equal('null', json)
246
+ end
247
+ def test_symbol_compat
248
+ json = Oj.dump(:abc, :mode => :compat)
249
+ assert_equal('"abc"', json)
250
+ end
251
+ def test_symbol_object
252
+ Oj.default_options = { :mode => :object }
253
+ #dump_and_load(''.to_sym, false)
254
+ dump_and_load(:abc, false)
255
+ dump_and_load(':xyz'.to_sym, false)
256
+ end
257
+
258
+ # Time
259
+ def test_time_strict
260
+ t = Time.local(2012, 1, 5, 23, 58, 7)
261
+ begin
262
+ Oj.dump(t, :mode => :strict)
263
+ assert(false)
264
+ rescue Exception
265
+ assert(true)
266
+ end
267
+ end
268
+ def test_time_null
269
+ t = Time.local(2012, 1, 5, 23, 58, 7)
270
+ json = Oj.dump(t, :mode => :null)
271
+ assert_equal('null', json)
272
+ end
273
+ def test_unix_time_compat
274
+ t = Time.xmlschema("2012-01-05T23:58:07.123456000+09:00")
275
+ #t = Time.local(2012, 1, 5, 23, 58, 7, 123456)
276
+ json = Oj.dump(t, :mode => :compat)
277
+ assert_equal(%{1325775487.123456000}, json)
278
+ end
279
+ def test_unix_time_compat_precision
280
+ t = Time.xmlschema("2012-01-05T23:58:07.123456789+09:00")
281
+ #t = Time.local(2012, 1, 5, 23, 58, 7, 123456)
282
+ json = Oj.dump(t, :mode => :compat, :second_precision => 5)
283
+ assert_equal(%{1325775487.12346}, json)
284
+ t = Time.xmlschema("2012-01-05T23:58:07.999600+09:00")
285
+ json = Oj.dump(t, :mode => :compat, :second_precision => 3)
286
+ assert_equal(%{1325775488.000}, json)
287
+ end
288
+ def test_unix_time_compat_early
289
+ t = Time.xmlschema("1954-01-05T00:00:00.123456789+00:00")
290
+ json = Oj.dump(t, :mode => :compat, :second_precision => 5)
291
+ assert_equal(%{-504575999.87654}, json)
292
+ end
293
+ def test_unix_time_compat_1970
294
+ t = Time.xmlschema("1970-01-01T00:00:00.123456789+00:00")
295
+ json = Oj.dump(t, :mode => :compat, :second_precision => 5)
296
+ assert_equal(%{0.12346}, json)
297
+ end
298
+ def test_ruby_time_compat
299
+ t = Time.xmlschema("2012-01-05T23:58:07.123456000+09:00")
300
+ json = Oj.dump(t, :mode => :compat, :time_format => :ruby)
301
+ #assert_equal(%{"2012-01-05 23:58:07 +0900"}, json)
302
+ assert_equal(%{"#{t.to_s}"}, json)
303
+ end
304
+ def test_xml_time_compat
305
+ begin
306
+ t = Time.new(2012, 1, 5, 23, 58, 7.123456000, 34200)
307
+ json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema)
308
+ assert_equal(%{"2012-01-05T23:58:07.123456000+09:30"}, json)
309
+ rescue Exception
310
+ # some Rubies (1.8.7) do not allow the timezome to be set
311
+ t = Time.local(2012, 1, 5, 23, 58, 7, 123456)
312
+ json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema)
313
+ tz = t.utc_offset
314
+ # Ruby does not handle a %+02d properly so...
315
+ sign = '+'
316
+ if 0 > tz
317
+ sign = '-'
318
+ tz = -tz
319
+ end
320
+ assert_equal(%{"2012-01-05T23:58:07.123456000%s%02d:%02d"} % [sign, tz / 3600, tz / 60 % 60], json)
321
+ end
322
+ end
323
+ def test_xml_time_compat_no_secs
324
+ begin
325
+ t = Time.new(2012, 1, 5, 23, 58, 7.0, 34200)
326
+ json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema)
327
+ assert_equal(%{"2012-01-05T23:58:07+09:30"}, json)
328
+ rescue Exception
329
+ # some Rubies (1.8.7) do not allow the timezome to be set
330
+ t = Time.local(2012, 1, 5, 23, 58, 7, 0)
331
+ json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema)
332
+ tz = t.utc_offset
333
+ # Ruby does not handle a %+02d properly so...
334
+ sign = '+'
335
+ if 0 > tz
336
+ sign = '-'
337
+ tz = -tz
338
+ end
339
+ assert_equal(%{"2012-01-05T23:58:07%s%02d:%02d"} % [sign, tz / 3600, tz / 60 % 60], json)
340
+ end
341
+ end
342
+ def test_xml_time_compat_precision
343
+ begin
344
+ t = Time.new(2012, 1, 5, 23, 58, 7.123456789, 32400)
345
+ json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema, :second_precision => 5)
346
+ assert_equal(%{"2012-01-05T23:58:07.12346+09:00"}, json)
347
+ rescue Exception
348
+ # some Rubies (1.8.7) do not allow the timezome to be set
349
+ t = Time.local(2012, 1, 5, 23, 58, 7, 123456)
350
+ json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema, :second_precision => 5)
351
+ tz = t.utc_offset
352
+ # Ruby does not handle a %+02d properly so...
353
+ sign = '+'
354
+ if 0 > tz
355
+ sign = '-'
356
+ tz = -tz
357
+ end
358
+ assert_equal(%{"2012-01-05T23:58:07.12346%s%02d:%02d"} % [sign, tz / 3600, tz / 60 % 60], json)
359
+ end
360
+ end
361
+ def test_xml_time_compat_precision_round
362
+ begin
363
+ t = Time.new(2012, 1, 5, 23, 58, 7.9996, 32400)
364
+ json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema, :second_precision => 3)
365
+ assert_equal(%{"2012-01-05T23:58:08+09:00"}, json)
366
+ rescue Exception
367
+ # some Rubies (1.8.7) do not allow the timezome to be set
368
+ t = Time.local(2012, 1, 5, 23, 58, 7, 999600)
369
+ json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema, :second_precision => 3)
370
+ tz = t.utc_offset
371
+ # Ruby does not handle a %+02d properly so...
372
+ sign = '+'
373
+ if 0 > tz
374
+ sign = '-'
375
+ tz = -tz
376
+ end
377
+ assert_equal(%{"2012-01-05T23:58:08%s%02d:%02d"} % [sign, tz / 3600, tz / 60 % 60], json)
378
+ end
379
+ end
380
+ def test_xml_time_compat_zulu
381
+ begin
382
+ t = Time.new(2012, 1, 5, 23, 58, 7.0, 0)
383
+ json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema)
384
+ assert_equal(%{"2012-01-05T23:58:07Z"}, json)
385
+ rescue Exception
386
+ # some Rubies (1.8.7) do not allow the timezome to be set
387
+ t = Time.utc(2012, 1, 5, 23, 58, 7, 0)
388
+ json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema)
389
+ #tz = t.utc_offset
390
+ assert_equal(%{"2012-01-05T23:58:07Z"}, json)
391
+ end
392
+ end
393
+ def test_time_object
394
+ t = Time.now()
395
+ Oj.default_options = { :mode => :object }
396
+ dump_and_load(t, false)
397
+ end
398
+ def test_time_object_early
399
+ t = Time.xmlschema("1954-01-05T00:00:00.123456")
400
+ Oj.default_options = { :mode => :object }
401
+ dump_and_load(t, false)
402
+ end
403
+
404
+ # Class
405
+ def test_class_strict
406
+ begin
407
+ Oj.dump(Juice, :mode => :strict)
408
+ assert(false)
409
+ rescue Exception
410
+ assert(true)
411
+ end
412
+ end
413
+ def test_class_null
414
+ json = Oj.dump(Juice, :mode => :null)
415
+ assert_equal('null', json)
416
+ end
417
+ def test_class_compat
418
+ json = Oj.dump(Juice, :mode => :compat)
419
+ assert_equal(%{"Juice"}, json)
420
+ end
421
+ def test_class_object
422
+ Oj.default_options = { :mode => :object }
423
+ dump_and_load(Juice, false)
424
+ end
425
+
426
+ # Hash
427
+ def test_hash
428
+ Oj.default_options = { :mode => :strict }
429
+ dump_and_load({}, false)
430
+ dump_and_load({ 'true' => true, 'false' => false}, false)
431
+ dump_and_load({ 'true' => true, 'array' => [], 'hash' => { }}, false)
432
+ end
433
+ def test_non_str_hash_strict
434
+ begin
435
+ Oj.dump({ 1 => true, 0 => false }, :mode => :strict)
436
+ assert(false)
437
+ rescue Exception
438
+ assert(true)
439
+ end
440
+ end
441
+ def test_non_str_hash_null
442
+ begin
443
+ Oj.dump({ 1 => true, 0 => false }, :mode => :null)
444
+ assert(false)
445
+ rescue Exception
446
+ assert(true)
447
+ end
448
+ end
449
+ def test_non_str_hash_compat
450
+ json = Oj.dump({ 1 => true, 0 => false }, :mode => :compat)
451
+ h = Oj.load(json, :mode => :strict)
452
+ assert_equal({ "1" => true, "0" => false }, h)
453
+ end
454
+ def test_non_str_hash_object
455
+ Oj.default_options = { :mode => :object }
456
+ json = Oj.dump({ 1 => true, :sim => nil })
457
+ h = Oj.load(json, :mode => :strict)
458
+ assert_equal({"^#1" => [1, true], ":sim" => nil}, h)
459
+ h = Oj.load(json)
460
+ assert_equal({ 1 => true, :sim => nil }, h)
461
+ end
462
+ def test_mixed_hash_object
463
+ Oj.default_options = { :mode => :object }
464
+ json = Oj.dump({ 1 => true, 'nil' => nil, :sim => 4 })
465
+ h = Oj.load(json, :mode => :strict)
466
+ assert_equal({"^#1" => [1, true], "nil" => nil, ":sim" => 4}, h)
467
+ h = Oj.load(json)
468
+ assert_equal({ 1 => true, 'nil' => nil, :sim => 4 }, h)
469
+ end
470
+
471
+ # Object with to_json()
472
+ def test_json_object_strict
473
+ obj = Jeez.new(true, 58)
474
+ begin
475
+ Oj.dump(obj, :mode => :strict)
476
+ assert(false)
477
+ rescue Exception
478
+ assert(true)
479
+ end
480
+ end
481
+ def test_json_object_null
482
+ obj = Jeez.new(true, 58)
483
+ json = Oj.dump(obj, :mode => :null)
484
+ assert_equal('null', json)
485
+ end
486
+ def test_json_object_compat
487
+ Oj.default_options = { :mode => :compat }
488
+ obj = Jeez.new(true, 58)
489
+ json = Oj.dump(obj, :indent => 2)
490
+ assert(%{{"json_class":"Jeez","x":true,"y":58}} == json ||
491
+ %{{"json_class":"Jeez","y":58,"x":true}} == json)
492
+ dump_and_load(obj, false)
493
+ end
494
+ def test_json_object_create_id
495
+ Oj.default_options = { :mode => :compat, :create_id => 'kson_class' }
496
+ expected = Jeez.new(true, 58)
497
+ json = %{{"kson_class":"Jeez","x":true,"y":58}}
498
+ obj = Oj.load(json)
499
+ assert_equal(expected, obj)
500
+ Oj.default_options = { :create_id => 'json_class' }
501
+ end
502
+ def test_json_object_object
503
+ obj = Jeez.new(true, 58)
504
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
505
+ assert(%{{
506
+ "^o":"Jeez",
507
+ "x":true,
508
+ "y":58
509
+ }} == json ||
510
+ %{{
511
+ "^o":"Jeez",
512
+ "y":58,
513
+ "x":true
514
+ }} == json)
515
+ obj2 = Oj.load(json, :mode => :object)
516
+ assert_equal(obj, obj2)
517
+ end
518
+
519
+ # Object with to_hash()
520
+ def test_to_hash_object_strict
521
+ obj = Jazz.new(true, 58)
522
+ begin
523
+ Oj.dump(obj, :mode => :strict)
524
+ assert(false)
525
+ rescue Exception
526
+ assert(true)
527
+ end
528
+ end
529
+ def test_to_hash_object_null
530
+ obj = Jazz.new(true, 58)
531
+ json = Oj.dump(obj, :mode => :null)
532
+ assert_equal('null', json)
533
+ end
534
+ def test_to_hash_object_compat
535
+ obj = Jazz.new(true, 58)
536
+ json = Oj.dump(obj, :mode => :compat, :indent => 2)
537
+ h = Oj.load(json, :mode => :strict)
538
+ assert_equal(obj.to_hash, h)
539
+ end
540
+ def test_to_hash_object_object
541
+ obj = Jazz.new(true, 58)
542
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
543
+ assert(%{{
544
+ "^o":"Jazz",
545
+ "x":true,
546
+ "y":58
547
+ }} == json ||
548
+ %{{
549
+ "^o":"Jazz",
550
+ "y":58,
551
+ "x":true
552
+ }} == json)
553
+ obj2 = Oj.load(json, :mode => :object)
554
+ assert_equal(obj, obj2)
555
+ end
556
+
557
+ # Object with as_json() # contributed by sauliusg
558
+ def test_as_json_object_strict
559
+ obj = Orange.new(true, 58)
560
+ begin
561
+ Oj.dump(obj, :mode => :strict)
562
+ assert(false)
563
+ rescue Exception
564
+ assert(true)
565
+ end
566
+ end
567
+
568
+ def test_as_json_object_null
569
+ obj = Orange.new(true, 58)
570
+ json = Oj.dump(obj, :mode => :null)
571
+ assert_equal('null', json)
572
+ end
573
+
574
+ def test_as_json_object_compat_hash
575
+ Oj.default_options = { :mode => :compat }
576
+ obj = Orange.new(true, 58)
577
+ json = Oj.dump(obj, :indent => 2)
578
+ assert(!json.nil?)
579
+ dump_and_load(obj, false)
580
+ end
581
+
582
+ def test_as_json_object_compat_non_hash
583
+ Oj.default_options = { :mode => :compat }
584
+ obj = Melon.new(true, 58)
585
+ json = Oj.dump(obj, :indent => 2)
586
+ assert_equal(%{"true 58"}, json)
587
+ end
588
+
589
+ def test_as_json_object_object
590
+ obj = Orange.new(true, 58)
591
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
592
+ assert(%{{
593
+ "^o":"Orange",
594
+ "x":true,
595
+ "y":58
596
+ }} == json ||
597
+ %{{
598
+ "^o":"Orange",
599
+ "y":58,
600
+ "x":true
601
+ }} == json)
602
+ obj2 = Oj.load(json, :mode => :object)
603
+ assert_equal(obj, obj2)
604
+ end
605
+
606
+ # Object without to_json() or to_hash()
607
+ def test_object_strict
608
+ obj = Jam.new(true, 58)
609
+ begin
610
+ Oj.dump(obj, :mode => :strict)
611
+ assert(false)
612
+ rescue Exception
613
+ assert(true)
614
+ end
615
+ end
616
+ def test_object_null
617
+ obj = Jam.new(true, 58)
618
+ json = Oj.dump(obj, :mode => :null)
619
+ assert_equal('null', json)
620
+ end
621
+ def test_object_compat
622
+ obj = Jam.new(true, 58)
623
+ json = Oj.dump(obj, :mode => :compat, :indent => 2)
624
+ assert(%{{
625
+ "x":true,
626
+ "y":58
627
+ }} == json ||
628
+ %{{
629
+ "y":58,
630
+ "x":true
631
+ }} == json)
632
+ end
633
+ def test_object_object
634
+ obj = Jam.new(true, 58)
635
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
636
+ assert(%{{
637
+ "^o":"Jam",
638
+ "x":true,
639
+ "y":58
640
+ }} == json ||
641
+ %{{
642
+ "^o":"Jam",
643
+ "y":58,
644
+ "x":true
645
+ }} == json)
646
+ obj2 = Oj.load(json, :mode => :object)
647
+ assert_equal(obj, obj2)
648
+ end
649
+
650
+ def test_object_object_no_cache
651
+ obj = Jam.new(true, 58)
652
+ json = Oj.dump(obj, :mode => :object, :indent => 2)
653
+ assert(%{{
654
+ "^o":"Jam",
655
+ "x":true,
656
+ "y":58
657
+ }} == json ||
658
+ %{{
659
+ "^o":"Jam",
660
+ "y":58,
661
+ "x":true
662
+ }} == json)
663
+ obj2 = Oj.load(json, :mode => :object, :class_cache => false)
664
+ assert_equal(obj, obj2)
665
+ end
666
+
667
+ # Exception
668
+ def test_exception
669
+ err = nil
670
+ begin
671
+ raise StandardError.new('A Message')
672
+ assert(false)
673
+ rescue Exception => e
674
+ err = e
675
+ end
676
+ json = Oj.dump(err, :mode => :object, :indent => 2)
677
+ #puts "*** #{json}"
678
+ e2 = Oj.load(json, :mode => :strict)
679
+ assert_equal(err.class.to_s, e2['^o'])
680
+ assert_equal(err.message, e2['~mesg'])
681
+ assert_equal(err.backtrace, e2['~bt'])
682
+ e2 = Oj.load(json, :mode => :object)
683
+ if RUBY_VERSION.start_with?('1.8') || 'rubinius' == $ruby
684
+ assert_equal(e.class, e2.class);
685
+ assert_equal(e.message, e2.message);
686
+ assert_equal(e.backtrace, e2.backtrace);
687
+ else
688
+ assert_equal(e, e2);
689
+ end
690
+ end
691
+
692
+ # Range
693
+ def test_range_strict
694
+ begin
695
+ Oj.dump(1..7, :mode => :strict)
696
+ assert(false)
697
+ rescue Exception
698
+ assert(true)
699
+ end
700
+ end
701
+ def test_range_null
702
+ json = Oj.dump(1..7, :mode => :null)
703
+ assert_equal('null', json)
704
+ end
705
+ def test_range_compat
706
+ json = Oj.dump(1..7, :mode => :compat)
707
+ h = Oj.load(json, :mode => :strict)
708
+ assert_equal({'begin' => 1, 'end' => 7, 'exclude_end' => false}, h)
709
+ json = Oj.dump(1...7, :mode => :compat)
710
+ h = Oj.load(json, :mode => :strict)
711
+ assert_equal({'begin' => 1, 'end' => 7, 'exclude_end' => true}, h)
712
+ end
713
+ def test_range_object
714
+ unless RUBY_VERSION.start_with?('1.8')
715
+ Oj.default_options = { :mode => :object }
716
+ json = Oj.dump(1..7, :mode => :object, :indent => 0)
717
+ if 'rubinius' == $ruby
718
+ assert(%{{"^o":"Range","excl":false,"begin":1,"end":7}} == json ||
719
+ %{{"^o":"Range","begin":1,"end":7,"excl":false}} == json)
720
+ elsif 'jruby' == $ruby
721
+ assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
722
+ else
723
+ assert_equal(%{{"^u":["Range",1,7,false]}}, json)
724
+ end
725
+ dump_and_load(1..7, false)
726
+ dump_and_load(1..1, false)
727
+ dump_and_load(1...7, false)
728
+ end
729
+ end
730
+
731
+ # BigNum
732
+ def test_bignum_strict
733
+ json = Oj.dump(7 ** 55, :mode => :strict)
734
+ assert_equal('30226801971775055948247051683954096612865741943', json)
735
+ end
736
+ def test_bignum_null
737
+ json = Oj.dump(7 ** 55, :mode => :null)
738
+ assert_equal('30226801971775055948247051683954096612865741943', json)
739
+ end
740
+ def test_bignum_compat
741
+ json = Oj.dump(7 ** 55, :mode => :compat)
742
+ b = Oj.load(json, :mode => :strict)
743
+ assert_equal(30226801971775055948247051683954096612865741943, b)
744
+ end
745
+ def test_bignum_object
746
+ dump_and_load(7 ** 55, false)
747
+ end
748
+
749
+ # BigDecimal
750
+ def test_bigdecimal_strict
751
+ mode = Oj.default_options[:mode]
752
+ Oj.default_options = {:mode => :strict}
753
+ dump_and_load(BigDecimal.new('3.14159265358979323846'), false)
754
+ Oj.default_options = {:mode => mode}
755
+ end
756
+ def test_bigdecimal_null
757
+ mode = Oj.default_options[:mode]
758
+ Oj.default_options = {:mode => :null}
759
+ dump_and_load(BigDecimal.new('3.14159265358979323846'), false)
760
+ Oj.default_options = {:mode => mode}
761
+ end
762
+ def test_bigdecimal_compat
763
+ orig = BigDecimal.new('80.51')
764
+ json = Oj.dump(orig, :mode => :compat, :bigdecimal_as_decimal => false)
765
+ bg = Oj.load(json, :mode => :compat)
766
+ assert_equal(orig.to_s, bg)
767
+ orig = BigDecimal.new('3.14159265358979323846')
768
+ json = Oj.dump(orig, :mode => :compat, :bigdecimal_as_decimal => false)
769
+ bg = Oj.load(json, :mode => :compat)
770
+ assert_equal(orig.to_s, bg)
771
+ end
772
+ def test_bigdecimal_load
773
+ orig = BigDecimal.new('80.51')
774
+ json = Oj.dump(orig, :mode => :compat, :bigdecimal_as_decimal => true)
775
+ bg = Oj.load(json, :mode => :compat, :bigdecimal_load => true)
776
+ assert_equal(BigDecimal, bg.class)
777
+ assert_equal(orig, bg)
778
+ end
779
+ def test_bigdecimal_compat_to_json
780
+ orig = BigDecimal.new('80.51')
781
+ BigDecimal.send(:define_method, :to_json) do
782
+ %{"this is big"}
783
+ end
784
+ json = Oj.dump(orig, :mode => :compat)
785
+ bg = Oj.load(json, :mode => :compat)
786
+ assert_equal("this is big", bg)
787
+ BigDecimal.send(:remove_method, :to_json) # cleanup
788
+ end
789
+ def test_bigdecimal_object
790
+ mode = Oj.default_options[:mode]
791
+ Oj.default_options = {:mode => :object}
792
+ dump_and_load(BigDecimal.new('3.14159265358979323846'), false)
793
+ Oj.default_options = {:mode => mode}
794
+ # Infinity is the same for Float and BigDecimal
795
+ json = Oj.dump(BigDecimal.new('Infinity'), :mode => :object)
796
+ assert_equal('Infinity', json)
797
+ json = Oj.dump(BigDecimal.new('-Infinity'), :mode => :object)
798
+ assert_equal('-Infinity', json)
799
+ end
800
+
801
+ # Date
802
+ def test_date_strict
803
+ begin
804
+ Oj.dump(Date.new(2012, 6, 19), :mode => :strict)
805
+ assert(false)
806
+ rescue Exception
807
+ assert(true)
808
+ end
809
+ end
810
+ def test_date_null
811
+ json = Oj.dump(Date.new(2012, 6, 19), :mode => :null)
812
+ assert_equal('null', json)
813
+ end
814
+ def test_date_compat
815
+ orig = Date.new(2012, 6, 19)
816
+ json = Oj.dump(orig, :mode => :compat)
817
+ x = Oj.load(json, :mode => :compat)
818
+ # Some Rubies implement Date as data and some as a real Object. Either are
819
+ # okay for the test.
820
+ if x.is_a?(String)
821
+ assert_equal(orig.to_s, x)
822
+ else # better be a Hash
823
+ assert_equal({"year" => orig.year, "month" => orig.month, "day" => orig.day, "start" => orig.start}, x)
824
+ end
825
+ end
826
+ def test_date_object
827
+ dump_and_load(Date.new(2012, 6, 19), false)
828
+ end
829
+
830
+ # DateTime
831
+ def test_datetime_strict
832
+ begin
833
+ Oj.dump(DateTime.new(2012, 6, 19, 20, 19, 27), :mode => :strict)
834
+ assert(false)
835
+ rescue Exception
836
+ assert(true)
837
+ end
838
+ end
839
+ def test_datetime_null
840
+ json = Oj.dump(DateTime.new(2012, 6, 19, 20, 19, 27), :mode => :null)
841
+ assert_equal('null', json)
842
+ end
843
+ def test_datetime_compat
844
+ orig = DateTime.new(2012, 6, 19, 20, 19, 27)
845
+ json = Oj.dump(orig, :mode => :compat)
846
+ x = Oj.load(json, :mode => :compat)
847
+ # Some Rubies implement Date as data and some as a real Object. Either are
848
+ # okay for the test.
849
+ assert_equal(orig.to_s, x)
850
+ end
851
+ def test_datetime_object
852
+ dump_and_load(DateTime.new(2012, 6, 19), false)
853
+ end
854
+
855
+ # autodefine Oj::Bag
856
+ def test_bag
857
+ json = %{{
858
+ "^o":"Jem",
859
+ "x":true,
860
+ "y":58 }}
861
+ obj = Oj.load(json, :mode => :object, :auto_define => true)
862
+ assert_equal('Jem', obj.class.name)
863
+ assert_equal(true, obj.x)
864
+ assert_equal(58, obj.y)
865
+ end
866
+
867
+ # Circular
868
+ def test_circular_object
869
+ obj = Jam.new(nil, 58)
870
+ obj.x = obj
871
+ json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
872
+ assert(%{{
873
+ "^o":"Jam",
874
+ "^i":1,
875
+ "x":"^r1",
876
+ "y":58
877
+ }} == json ||
878
+ %{{
879
+ "^o":"Jam",
880
+ "^i":1,
881
+ "y":58,
882
+ "x":"^r1"
883
+ }} == json)
884
+ obj2 = Oj.load(json, :mode => :object, :circular => true)
885
+ assert_equal(obj2.x.__id__, obj2.__id__)
886
+ end
887
+
888
+ def test_circular_hash
889
+ h = { 'a' => 7 }
890
+ h['b'] = h
891
+ json = Oj.dump(h, :mode => :object, :indent => 2, :circular => true)
892
+ ha = Oj.load(json, :mode => :strict)
893
+ assert_equal({'^i' => 1, 'a' => 7, 'b' => '^r1'}, ha)
894
+ Oj.load(json, :mode => :object, :circular => true)
895
+ assert_equal(h['b'].__id__, h.__id__)
896
+ end
897
+
898
+ def test_circular_array
899
+ a = [7]
900
+ a << a
901
+ json = Oj.dump(a, :mode => :object, :indent => 2, :circular => true)
902
+ assert_equal(%{[
903
+ "^i1",
904
+ 7,
905
+ "^r1"
906
+ ]}, json)
907
+ a2 = Oj.load(json, :mode => :object, :circular => true)
908
+ assert_equal(a2[1].__id__, a2.__id__)
909
+ end
910
+
911
+ def test_circular
912
+ h = { 'a' => 7 }
913
+ obj = Jam.new(h, 58)
914
+ obj.x['b'] = obj
915
+ json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
916
+ ha = Oj.load(json, :mode => :strict)
917
+ assert_equal({'^o' => 'Jam', '^i' => 1, 'x' => { '^i' => 2, 'a' => 7, 'b' => '^r1' }, 'y' => 58 }, ha)
918
+ Oj.load(json, :mode => :object, :circular => true)
919
+ assert_equal(obj.x.__id__, h.__id__)
920
+ assert_equal(h['b'].__id__, obj.__id__)
921
+ end
922
+
923
+ # Stream Deeply Nested
924
+ def test_deep_nest
925
+ #unless 'jruby' == RUBY_DESCRIPTION.split(' ')[0]
926
+ begin
927
+ n = 10000
928
+ Oj.strict_load('[' * n + ']' * n)
929
+ rescue Exception => e
930
+ assert(false, e.message)
931
+ end
932
+ end
933
+
934
+ # Stream IO
935
+ def test_io_string
936
+ json = %{{
937
+ "x":true,
938
+ "y":58,
939
+ "z": [1,2,3]
940
+ }
941
+ }
942
+ input = StringIO.new(json)
943
+ obj = Oj.load(input, :mode => :strict)
944
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
945
+ end
946
+
947
+ def test_io_file
948
+ filename = 'open_file_test.json'
949
+ File.open(filename, 'w') { |f| f.write(%{{
950
+ "x":true,
951
+ "y":58,
952
+ "z": [1,2,3]
953
+ }
954
+ }) }
955
+ f = File.new(filename)
956
+ obj = Oj.load(f, :mode => :strict)
957
+ f.close()
958
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
959
+ end
960
+
961
+ # symbol_keys option
962
+ def test_symbol_keys
963
+ json = %{{
964
+ "x":true,
965
+ "y":58,
966
+ "z": [1,2,3]
967
+ }
968
+ }
969
+ obj = Oj.load(json, :mode => :strict, :symbol_keys => true)
970
+ assert_equal({ :x => true, :y => 58, :z => [1, 2, 3]}, obj)
971
+ end
972
+
973
+ # comments
974
+ def test_comment_slash
975
+ json = %{{
976
+ "x":true,//three
977
+ "y":58,
978
+ "z": [1,2,
979
+ 3 // six
980
+ ]}
981
+ }
982
+ obj = Oj.load(json, :mode => :strict)
983
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
984
+ end
985
+
986
+ def test_comment_c
987
+ json = %{{
988
+ "x"/*one*/:/*two*/true,
989
+ "y":58,
990
+ "z": [1,2,3]}
991
+ }
992
+ obj = Oj.load(json, :mode => :strict)
993
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
994
+ end
995
+
996
+ def test_comment
997
+ json = %{{
998
+ "x"/*one*/:/*two*/true,//three
999
+ "y":58/*four*/,
1000
+ "z": [1,2/*five*/,
1001
+ 3 // six
1002
+ ]
1003
+ }
1004
+ }
1005
+ obj = Oj.load(json, :mode => :strict)
1006
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
1007
+ end
1008
+
1009
+ def dump_and_load(obj, trace=false)
1010
+ json = Oj.dump(obj, :indent => 2)
1011
+ puts json if trace
1012
+ loaded = Oj.load(json);
1013
+ assert_equal(obj, loaded)
1014
+ loaded
1015
+ end
1016
+
1017
+ end