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,35 @@
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 'oj'
16
+ require 'json'
17
+
18
+ class MimicAfter < ::Test::Unit::TestCase
19
+
20
+ def test0_mimic_json
21
+ assert(!defined?(JSON).nil?)
22
+ Oj.mimic_JSON
23
+ end
24
+
25
+ # dump
26
+ def test_dump_string
27
+ Oj.default_options= {:indent => 2} # JSON this will not change anything
28
+ json = JSON.dump([1, true, nil])
29
+ assert_equal(%{[
30
+ 1,
31
+ true,
32
+ null]}, json)
33
+ end
34
+
35
+ end # MimicAfter
@@ -0,0 +1,390 @@
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
+ class Jeez
23
+ attr_accessor :x, :y
24
+
25
+ def initialize(x, y)
26
+ @x = x
27
+ @y = y
28
+ end
29
+
30
+ def eql?(o)
31
+ self.class == o.class && @x == o.x && @y == o.y
32
+ end
33
+ alias == eql?
34
+
35
+ def to_json(*a)
36
+ %{{"json_class":"#{self.class}","x":#{@x},"y":#{@y}}}
37
+ end
38
+
39
+ def self.json_create(h)
40
+ self.new(h['x'], h['y'])
41
+ end
42
+ end # Jeez
43
+
44
+ module One
45
+ module Two
46
+ module Three
47
+ class Deep
48
+
49
+ def initialize()
50
+ end
51
+
52
+ def eql?(o)
53
+ self.class == o.class
54
+ end
55
+ alias == eql?
56
+
57
+ def to_hash()
58
+ {'json_class' => "#{self.class.name}"}
59
+ end
60
+
61
+ def to_json(*a)
62
+ %{{"json_class":"#{self.class.name}"}}
63
+ end
64
+
65
+ def self.json_create(h)
66
+ self.new()
67
+ end
68
+ end # Deep
69
+ end # Three
70
+ end # Two
71
+ end # One
72
+
73
+ class Stuck < Struct.new(:a, :b)
74
+ end
75
+
76
+ def hash_eql(h1, h2)
77
+ return false if h1.size != h2.size
78
+ h1.keys.each do |k|
79
+ return false unless h1[k] == h2[k]
80
+ end
81
+ true
82
+ end
83
+
84
+ class ObjectJuice < ::Test::Unit::TestCase
85
+
86
+ def test_nil
87
+ dump_and_load(nil, false)
88
+ end
89
+
90
+ def test_true
91
+ dump_and_load(true, false)
92
+ end
93
+
94
+ def test_false
95
+ dump_and_load(false, false)
96
+ end
97
+
98
+ def test_fixnum
99
+ dump_and_load(0, false)
100
+ dump_and_load(12345, false)
101
+ dump_and_load(-54321, false)
102
+ dump_and_load(1, false)
103
+ end
104
+
105
+ def test_float
106
+ dump_and_load(0.0, false)
107
+ dump_and_load(12345.6789, false)
108
+ dump_and_load(70.35, false)
109
+ dump_and_load(-54321.012, false)
110
+ dump_and_load(2.48e16, false)
111
+ dump_and_load(2.48e100 * 1.0e10, false)
112
+ dump_and_load(-2.48e100 * 1.0e10, false)
113
+ end
114
+
115
+ def test_string
116
+ dump_and_load('', false)
117
+ dump_and_load('abc', false)
118
+ dump_and_load("abc\ndef", false)
119
+ dump_and_load("a\u0041", false)
120
+ end
121
+
122
+ def test_symbol
123
+ dump_and_load(:abc, false)
124
+ dump_and_load(":abc", false)
125
+ end
126
+
127
+ def test_encode
128
+ opts = Oj.default_options
129
+ Oj.default_options = { :ascii_only => false }
130
+ unless 'jruby' == $ruby
131
+ dump_and_load("ぴーたー", false)
132
+ end
133
+ Oj.default_options = { :ascii_only => true }
134
+ json = Oj.dump("ぴーたー")
135
+ assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json)
136
+ unless 'jruby' == $ruby
137
+ dump_and_load("ぴーたー", false)
138
+ end
139
+ Oj.default_options = opts
140
+ end
141
+
142
+ def test_unicode
143
+ # hits the 3 normal ranges and one extended surrogate pair
144
+ json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e"}
145
+ obj = Oj.load(json)
146
+ json2 = Oj.dump(obj, :ascii_only => true)
147
+ assert_equal(json, json2)
148
+ end
149
+
150
+ def test_array
151
+ dump_and_load([], false)
152
+ dump_and_load([true, false], false)
153
+ dump_and_load(['a', 1, nil], false)
154
+ dump_and_load([[nil]], false)
155
+ dump_and_load([[nil], 58], false)
156
+ end
157
+
158
+ def test_array_deep
159
+ dump_and_load([1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20]]]]]]]]]]]]]]]]]]]], false)
160
+ end
161
+
162
+ # Hash
163
+ def test_hash
164
+ dump_and_load({}, false)
165
+ dump_and_load({ 'true' => true, 'false' => false}, false)
166
+ dump_and_load({ 'true' => true, 'array' => [], 'hash' => { }}, false)
167
+ end
168
+
169
+ def test_hash_deep
170
+ dump_and_load({'1' => {
171
+ '2' => {
172
+ '3' => {
173
+ '4' => {
174
+ '5' => {
175
+ '6' => {
176
+ '7' => {
177
+ '8' => {
178
+ '9' => {
179
+ '10' => {
180
+ '11' => {
181
+ '12' => {
182
+ '13' => {
183
+ '14' => {
184
+ '15' => {
185
+ '16' => {
186
+ '17' => {
187
+ '18' => {
188
+ '19' => {
189
+ '20' => {}}}}}}}}}}}}}}}}}}}}}, false)
190
+ end
191
+
192
+ def test_hash_escaped_key
193
+ json = %{{"a\nb":true,"c\td":false}}
194
+ obj = Oj.object_load(json)
195
+ assert_equal({"a\nb" => true, "c\td" => false}, obj)
196
+ end
197
+
198
+ def test_bignum_object
199
+ dump_and_load(7 ** 55, false)
200
+ end
201
+
202
+ # BigDecimal
203
+ def test_bigdecimal_object
204
+ dump_and_load(BigDecimal.new('3.14159265358979323846'), false)
205
+ end
206
+
207
+ def test_bigdecimal_load
208
+ orig = BigDecimal.new('80.51')
209
+ json = Oj.dump(orig, :mode => :object, :bigdecimal_as_decimal => true)
210
+ bg = Oj.load(json, :mode => :object, :bigdecimal_load => true)
211
+ assert_equal(BigDecimal, bg.class)
212
+ assert_equal(orig, bg)
213
+ end
214
+
215
+ # Stream IO
216
+ def test_io_string
217
+ json = %{{
218
+ "x":true,
219
+ "y":58,
220
+ "z": [1,2,3]
221
+ }
222
+ }
223
+ input = StringIO.new(json)
224
+ obj = Oj.object_load(input)
225
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
226
+ end
227
+
228
+ def test_io_file
229
+ filename = 'open_file_test.json'
230
+ File.open(filename, 'w') { |f| f.write(%{{
231
+ "x":true,
232
+ "y":58,
233
+ "z": [1,2,3]
234
+ }
235
+ }) }
236
+ f = File.new(filename)
237
+ obj = Oj.object_load(f)
238
+ f.close()
239
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
240
+ end
241
+
242
+ # symbol_keys option
243
+ def test_symbol_keys
244
+ json = %{{
245
+ "x":true,
246
+ "y":58,
247
+ "z": [1,2,3]
248
+ }
249
+ }
250
+ obj = Oj.object_load(json, :symbol_keys => true)
251
+ assert_equal({ :x => true, :y => 58, :z => [1, 2, 3]}, obj)
252
+ end
253
+
254
+ # comments
255
+ def test_comment_slash
256
+ json = %{{
257
+ "x":true,//three
258
+ "y":58,
259
+ "z": [1,2,
260
+ 3 // six
261
+ ]}
262
+ }
263
+ obj = Oj.object_load(json)
264
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
265
+ end
266
+
267
+ def test_comment_c
268
+ json = %{{
269
+ "x"/*one*/:/*two*/true,
270
+ "y":58,
271
+ "z": [1,2,3]}
272
+ }
273
+ obj = Oj.object_load(json)
274
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
275
+ end
276
+
277
+ def test_comment
278
+ json = %{{
279
+ "x"/*one*/:/*two*/true,//three
280
+ "y":58/*four*/,
281
+ "z": [1,2/*five*/,
282
+ 3 // six
283
+ ]
284
+ }
285
+ }
286
+ obj = Oj.object_load(json)
287
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
288
+ end
289
+
290
+ def test_json_module_object
291
+ obj = One::Two::Three::Deep.new()
292
+ dump_and_load(obj, false)
293
+ end
294
+
295
+ def test_time
296
+ t = Time.now()
297
+ dump_and_load(t, false)
298
+ end
299
+
300
+ def test_time_early
301
+ t = Time.xmlschema("1954-01-05T00:00:00.123456")
302
+ dump_and_load(t, false)
303
+ end
304
+
305
+ def test_json_object
306
+ obj = Jeez.new(true, 58)
307
+ dump_and_load(obj, false)
308
+ end
309
+
310
+ def test_json_object_create_deep
311
+ obj = One::Two::Three::Deep.new()
312
+ dump_and_load(obj, false)
313
+ end
314
+
315
+ def test_json_object_bad
316
+ json = %{{"^o":"Junk","x":true}}
317
+ begin
318
+ Oj.object_load(json)
319
+ rescue Exception => e
320
+ assert_equal("Oj::ParseError", e.class().name)
321
+ return
322
+ end
323
+ assert(false, "*** expected an exception")
324
+ end
325
+
326
+ def test_json_struct
327
+ unless 'jruby' == RUBY_DESCRIPTION.split(' ')[0]
328
+ obj = Stuck.new(false, 7)
329
+ dump_and_load(obj, false)
330
+ end
331
+ end
332
+
333
+ def test_json_non_str_hash
334
+ obj = { 59 => "young", false => true }
335
+ dump_and_load(obj, false)
336
+ end
337
+
338
+ def test_mixed_hash_object
339
+ json = Oj.dump({ 1 => true, 'nil' => nil, :sim => 4 })
340
+ h = Oj.object_load(json)
341
+ assert_equal({ 1 => true, 'nil' => nil, :sim => 4 }, h)
342
+ end
343
+
344
+ def test_circular_hash
345
+ h = { 'a' => 7 }
346
+ h['b'] = h
347
+ json = Oj.dump(h, :mode => :object, :indent => 2, :circular => true)
348
+ h2 = Oj.object_load(json, :circular => true)
349
+ assert_equal(h2['b'].__id__, h2.__id__)
350
+ end
351
+
352
+ def test_circular_array
353
+ a = [7]
354
+ a << a
355
+ json = Oj.dump(a, :mode => :object, :indent => 2, :circular => true)
356
+ a2 = Oj.object_load(json, :circular => true)
357
+ assert_equal(a2[1].__id__, a2.__id__)
358
+ end
359
+
360
+ def test_circular_object
361
+ obj = Jeez.new(nil, 58)
362
+ obj.x = obj
363
+ json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
364
+ obj2 = Oj.object_load(json, :circular => true)
365
+ assert_equal(obj2.x.__id__, obj2.__id__)
366
+ end
367
+
368
+ def test_circular
369
+ h = { 'a' => 7 }
370
+ obj = Jeez.new(h, 58)
371
+ obj.x['b'] = obj
372
+ json = Oj.dump(obj, :mode => :object, :indent => 2, :circular => true)
373
+ Oj.object_load(json, :circular => true)
374
+ assert_equal(obj.x.__id__, h.__id__)
375
+ assert_equal(h['b'].__id__, obj.__id__)
376
+ end
377
+
378
+ def test_odd_date
379
+ dump_and_load(Date.new(2012, 6, 19), false)
380
+ end
381
+
382
+ def dump_and_load(obj, trace=false)
383
+ json = Oj.dump(obj, :indent => 2, :mode => :object)
384
+ puts json if trace
385
+ loaded = Oj.object_load(json);
386
+ assert_equal(obj, loaded)
387
+ loaded
388
+ end
389
+
390
+ end
@@ -0,0 +1,184 @@
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 'oj'
15
+ require 'pp'
16
+
17
+ $json = %{{
18
+ "array": [
19
+ {
20
+ "num" : 3,
21
+ "string": "message",
22
+ "hash" : {
23
+ "h2" : {
24
+ "a" : [ 1, 2, 3 ]
25
+ }
26
+ }
27
+ }
28
+ ],
29
+ "boolean" : true
30
+ }}
31
+
32
+ class AllSaj < Oj::Saj
33
+ attr_accessor :calls
34
+
35
+ def initialize()
36
+ @calls = []
37
+ end
38
+
39
+ def hash_start(key)
40
+ @calls << [:hash_start, key]
41
+ end
42
+
43
+ def hash_end(key)
44
+ @calls << [:hash_end, key]
45
+ end
46
+
47
+ def array_start(key)
48
+ @calls << [:array_start, key]
49
+ end
50
+
51
+ def array_end(key)
52
+ @calls << [:array_end, key]
53
+ end
54
+
55
+ def add_value(value, key)
56
+ @calls << [:add_value, value, key]
57
+ end
58
+
59
+ def error(message, line, column)
60
+ @calls << [:error, message, line, column]
61
+ end
62
+
63
+ end # AllSaj
64
+
65
+ class SajTest < ::Test::Unit::TestCase
66
+ def test_nil
67
+ handler = AllSaj.new()
68
+ json = %{null}
69
+ Oj.saj_parse(handler, json)
70
+ assert_equal([[:add_value, nil, nil]], handler.calls)
71
+ end
72
+
73
+ def test_true
74
+ handler = AllSaj.new()
75
+ json = %{true}
76
+ Oj.saj_parse(handler, json)
77
+ assert_equal([[:add_value, true, nil]], handler.calls)
78
+ end
79
+
80
+ def test_false
81
+ handler = AllSaj.new()
82
+ json = %{false}
83
+ Oj.saj_parse(handler, json)
84
+ assert_equal([[:add_value, false, nil]], handler.calls)
85
+ end
86
+
87
+ def test_string
88
+ handler = AllSaj.new()
89
+ json = %{"a string"}
90
+ Oj.saj_parse(handler, json)
91
+ assert_equal([[:add_value, 'a string', nil]], handler.calls)
92
+ end
93
+
94
+ def test_fixnum
95
+ handler = AllSaj.new()
96
+ json = %{12345}
97
+ Oj.saj_parse(handler, json)
98
+ assert_equal([[:add_value, 12345, nil]], handler.calls)
99
+ end
100
+
101
+ def test_float
102
+ handler = AllSaj.new()
103
+ json = %{12345.6789}
104
+ Oj.saj_parse(handler, json)
105
+ assert_equal([[:add_value, 12345.6789, nil]], handler.calls)
106
+ end
107
+
108
+ def test_float_exp
109
+ handler = AllSaj.new()
110
+ json = %{12345.6789e7}
111
+ Oj.saj_parse(handler, json)
112
+ assert_equal(1, handler.calls.size)
113
+ assert_equal(:add_value, handler.calls[0][0])
114
+ assert_equal((12345.6789e7 * 10000).to_i, (handler.calls[0][1] * 10000).to_i)
115
+ end
116
+
117
+ def test_array_empty
118
+ handler = AllSaj.new()
119
+ json = %{[]}
120
+ Oj.saj_parse(handler, json)
121
+ assert_equal([[:array_start, nil],
122
+ [:array_end, nil]], handler.calls)
123
+ end
124
+
125
+ def test_array
126
+ handler = AllSaj.new()
127
+ json = %{[true,false]}
128
+ Oj.saj_parse(handler, json)
129
+ assert_equal([[:array_start, nil],
130
+ [:add_value, true, nil],
131
+ [:add_value, false, nil],
132
+ [:array_end, nil]], handler.calls)
133
+ end
134
+
135
+ def test_hash_empty
136
+ handler = AllSaj.new()
137
+ json = %{{}}
138
+ Oj.saj_parse(handler, json)
139
+ assert_equal([[:hash_start, nil],
140
+ [:hash_end, nil]], handler.calls)
141
+ end
142
+
143
+ def test_hash
144
+ handler = AllSaj.new()
145
+ json = %{{"one":true,"two":false}}
146
+ Oj.saj_parse(handler, json)
147
+ assert_equal([[:hash_start, nil],
148
+ [:add_value, true, 'one'],
149
+ [:add_value, false, 'two'],
150
+ [:hash_end, nil]], handler.calls)
151
+ end
152
+
153
+ def test_full
154
+ handler = AllSaj.new()
155
+ Oj.saj_parse(handler, $json)
156
+ assert_equal([[:hash_start, nil],
157
+ [:array_start, 'array'],
158
+ [:hash_start, nil],
159
+ [:add_value, 3, 'num'],
160
+ [:add_value, 'message', 'string'],
161
+ [:hash_start, 'hash'],
162
+ [:hash_start, 'h2'],
163
+ [:array_start, 'a'],
164
+ [:add_value, 1, nil],
165
+ [:add_value, 2, nil],
166
+ [:add_value, 3, nil],
167
+ [:array_end, 'a'],
168
+ [:hash_end, 'h2'],
169
+ [:hash_end, 'hash'],
170
+ [:hash_end, nil],
171
+ [:array_end, 'array'],
172
+ [:add_value, true, 'boolean'],
173
+ [:hash_end, nil]], handler.calls)
174
+ end
175
+
176
+ def test_fixnum_bad
177
+ handler = AllSaj.new()
178
+ json = %{12345xyz}
179
+ Oj.saj_parse(handler, json)
180
+ assert_equal([[:add_value, 12345, nil],
181
+ [:error, "invalid format, extra characters at line 1, column 6 [saj.c:711]", 1, 6]], handler.calls)
182
+ end
183
+
184
+ end