oj 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +17 -23
  3. data/README.md +74 -425
  4. data/ext/oj/buf.h +103 -0
  5. data/ext/oj/cache8.c +4 -0
  6. data/ext/oj/circarray.c +68 -0
  7. data/ext/oj/circarray.h +23 -0
  8. data/ext/oj/code.c +227 -0
  9. data/ext/oj/code.h +40 -0
  10. data/ext/oj/compat.c +243 -0
  11. data/ext/oj/custom.c +1097 -0
  12. data/ext/oj/dump.c +766 -1534
  13. data/ext/oj/dump.h +92 -0
  14. data/ext/oj/dump_compat.c +937 -0
  15. data/ext/oj/dump_leaf.c +254 -0
  16. data/ext/oj/dump_object.c +810 -0
  17. data/ext/oj/dump_rails.c +329 -0
  18. data/ext/oj/dump_strict.c +416 -0
  19. data/ext/oj/encode.h +51 -0
  20. data/ext/oj/err.c +57 -0
  21. data/ext/oj/err.h +70 -0
  22. data/ext/oj/extconf.rb +17 -7
  23. data/ext/oj/fast.c +213 -180
  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 +817 -0
  28. data/ext/oj/mimic_rails.c +806 -0
  29. data/ext/oj/mimic_rails.h +17 -0
  30. data/ext/oj/object.c +752 -0
  31. data/ext/oj/odd.c +230 -0
  32. data/ext/oj/odd.h +44 -0
  33. data/ext/oj/oj.c +1288 -929
  34. data/ext/oj/oj.h +240 -69
  35. data/ext/oj/parse.c +1014 -0
  36. data/ext/oj/parse.h +92 -0
  37. data/ext/oj/reader.c +223 -0
  38. data/ext/oj/reader.h +151 -0
  39. data/ext/oj/resolve.c +127 -0
  40. data/ext/oj/{cache.h → resolve.h} +6 -13
  41. data/ext/oj/rxclass.c +133 -0
  42. data/ext/oj/rxclass.h +27 -0
  43. data/ext/oj/saj.c +77 -175
  44. data/ext/oj/scp.c +224 -0
  45. data/ext/oj/sparse.c +911 -0
  46. data/ext/oj/stream_writer.c +301 -0
  47. data/ext/oj/strict.c +162 -0
  48. data/ext/oj/string_writer.c +480 -0
  49. data/ext/oj/val_stack.c +98 -0
  50. data/ext/oj/val_stack.h +188 -0
  51. data/lib/oj/active_support_helper.rb +41 -0
  52. data/lib/oj/bag.rb +6 -10
  53. data/lib/oj/easy_hash.rb +52 -0
  54. data/lib/oj/json.rb +172 -0
  55. data/lib/oj/mimic.rb +260 -5
  56. data/lib/oj/saj.rb +13 -10
  57. data/lib/oj/schandler.rb +142 -0
  58. data/lib/oj/state.rb +131 -0
  59. data/lib/oj/version.rb +1 -1
  60. data/lib/oj.rb +11 -23
  61. data/pages/Advanced.md +22 -0
  62. data/pages/Compatibility.md +25 -0
  63. data/pages/Custom.md +23 -0
  64. data/pages/Encoding.md +65 -0
  65. data/pages/JsonGem.md +79 -0
  66. data/pages/Modes.md +140 -0
  67. data/pages/Options.md +250 -0
  68. data/pages/Rails.md +60 -0
  69. data/pages/Security.md +20 -0
  70. data/test/_test_active.rb +76 -0
  71. data/test/_test_active_mimic.rb +96 -0
  72. data/test/_test_mimic_rails.rb +126 -0
  73. data/test/activesupport4/decoding_test.rb +105 -0
  74. data/test/activesupport4/encoding_test.rb +531 -0
  75. data/test/activesupport4/test_helper.rb +41 -0
  76. data/test/activesupport5/decoding_test.rb +125 -0
  77. data/test/activesupport5/encoding_test.rb +483 -0
  78. data/test/activesupport5/encoding_test_cases.rb +90 -0
  79. data/test/activesupport5/test_helper.rb +50 -0
  80. data/test/activesupport5/time_zone_test_helpers.rb +24 -0
  81. data/test/helper.rb +27 -0
  82. data/test/isolated/shared.rb +310 -0
  83. data/test/isolated/test_mimic_after.rb +13 -0
  84. data/test/isolated/test_mimic_alone.rb +12 -0
  85. data/test/isolated/test_mimic_as_json.rb +45 -0
  86. data/test/isolated/test_mimic_before.rb +13 -0
  87. data/test/isolated/test_mimic_define.rb +28 -0
  88. data/test/isolated/test_mimic_rails_after.rb +22 -0
  89. data/test/isolated/test_mimic_rails_before.rb +21 -0
  90. data/test/isolated/test_mimic_redefine.rb +15 -0
  91. data/test/json_gem/json_addition_test.rb +216 -0
  92. data/test/json_gem/json_common_interface_test.rb +143 -0
  93. data/test/json_gem/json_encoding_test.rb +109 -0
  94. data/test/json_gem/json_ext_parser_test.rb +20 -0
  95. data/test/json_gem/json_fixtures_test.rb +35 -0
  96. data/test/json_gem/json_generator_test.rb +383 -0
  97. data/test/json_gem/json_generic_object_test.rb +90 -0
  98. data/test/json_gem/json_parser_test.rb +470 -0
  99. data/test/json_gem/json_string_matching_test.rb +42 -0
  100. data/test/json_gem/test_helper.rb +18 -0
  101. data/test/perf_compat.rb +130 -0
  102. data/test/perf_fast.rb +9 -9
  103. data/test/perf_file.rb +64 -0
  104. data/test/{perf_obj.rb → perf_object.rb} +24 -10
  105. data/test/perf_scp.rb +151 -0
  106. data/test/perf_strict.rb +32 -113
  107. data/test/sample.rb +2 -3
  108. data/test/test_compat.rb +474 -0
  109. data/test/test_custom.rb +355 -0
  110. data/test/test_debian.rb +53 -0
  111. data/test/test_fast.rb +66 -16
  112. data/test/test_file.rb +237 -0
  113. data/test/test_gc.rb +49 -0
  114. data/test/test_hash.rb +29 -0
  115. data/test/test_null.rb +376 -0
  116. data/test/test_object.rb +1010 -0
  117. data/test/test_saj.rb +16 -16
  118. data/test/test_scp.rb +417 -0
  119. data/test/test_strict.rb +410 -0
  120. data/test/test_various.rb +815 -0
  121. data/test/test_writer.rb +308 -0
  122. data/test/tests.rb +9 -902
  123. data/test/tests_mimic.rb +14 -0
  124. data/test/tests_mimic_addition.rb +7 -0
  125. metadata +253 -38
  126. data/ext/oj/cache.c +0 -148
  127. data/ext/oj/foo.rb +0 -6
  128. data/ext/oj/load.c +0 -1049
  129. data/test/a.rb +0 -38
  130. data/test/perf1.rb +0 -64
  131. data/test/perf2.rb +0 -76
  132. data/test/perf_obj_old.rb +0 -213
  133. data/test/test_mimic.rb +0 -208
data/test/test_saj.rb CHANGED
@@ -1,18 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: UTF-8
3
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
4
+ $: << File.dirname(__FILE__)
7
5
 
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'
6
+ require 'helper'
16
7
 
17
8
  $json = %{{
18
9
  "array": [
@@ -62,7 +53,16 @@ class AllSaj < Oj::Saj
62
53
 
63
54
  end # AllSaj
64
55
 
65
- class SajTest < ::Test::Unit::TestCase
56
+ class SajTest < Minitest::Test
57
+
58
+ def setup
59
+ @default_options = Oj.default_options
60
+ end
61
+
62
+ def teardown
63
+ Oj.default_options = @default_options
64
+ end
65
+
66
66
  def test_nil
67
67
  handler = AllSaj.new()
68
68
  json = %{null}
@@ -177,10 +177,10 @@ class SajTest < ::Test::Unit::TestCase
177
177
  handler = AllSaj.new()
178
178
  json = %{12345xyz}
179
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:716]", 1, 6]], handler.calls)
180
+ assert_equal([:add_value, 12345, nil], handler.calls.first)
181
+ type, message, line, column = handler.calls.last
182
+ assert_equal([:error, 1, 6], [type, line, column])
183
+ assert_match(%r{invalid format, extra characters at line 1, column 6 \[(?:[a-z\.]+/)*saj\.c:\d+\]}, message)
182
184
  end
183
185
 
184
186
  end
185
-
186
-
data/test/test_scp.rb ADDED
@@ -0,0 +1,417 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+
6
+ require 'helper'
7
+ require 'socket'
8
+ require 'stringio'
9
+
10
+ $json = %{{
11
+ "array": [
12
+ {
13
+ "num" : 3,
14
+ "string": "message",
15
+ "hash" : {
16
+ "h2" : {
17
+ "a" : [ 1, 2, 3 ]
18
+ }
19
+ }
20
+ }
21
+ ],
22
+ "boolean" : true
23
+ }}
24
+
25
+ class NoHandler < Oj::ScHandler
26
+ def initialize()
27
+ end
28
+ end
29
+
30
+ class AllHandler < Oj::ScHandler
31
+ attr_accessor :calls
32
+
33
+ def initialize()
34
+ @calls = []
35
+ end
36
+
37
+ def hash_start()
38
+ @calls << [:hash_start]
39
+ {}
40
+ end
41
+
42
+ def hash_end()
43
+ @calls << [:hash_end]
44
+ end
45
+
46
+ def hash_key(key)
47
+ @calls << [:hash_key, key]
48
+ return 'too' if 'two' == key
49
+ return :symbol if 'symbol' == key
50
+ key
51
+ end
52
+
53
+ def array_start()
54
+ @calls << [:array_start]
55
+ []
56
+ end
57
+
58
+ def array_end()
59
+ @calls << [:array_end]
60
+ end
61
+
62
+ def add_value(value)
63
+ @calls << [:add_value, value]
64
+ end
65
+
66
+ def hash_set(h, key, value)
67
+ @calls << [:hash_set, key, value]
68
+ end
69
+
70
+ def array_append(a, value)
71
+ @calls << [:array_append, value]
72
+ end
73
+
74
+ end # AllHandler
75
+
76
+ class Closer < AllHandler
77
+ attr_accessor :io
78
+ def initialize(io)
79
+ super()
80
+ @io = io
81
+ end
82
+
83
+ def hash_start()
84
+ @calls << [:hash_start]
85
+ @io.close
86
+ {}
87
+ end
88
+
89
+ def hash_set(h, key, value)
90
+ @calls << [:hash_set, key, value]
91
+ @io.close
92
+ end
93
+
94
+ end # Closer
95
+
96
+ class ScpTest < Minitest::Test
97
+
98
+ def setup
99
+ @default_options = Oj.default_options
100
+ end
101
+
102
+ def teardown
103
+ Oj.default_options = @default_options
104
+ end
105
+
106
+ def test_nil
107
+ handler = AllHandler.new()
108
+ json = %{null}
109
+ Oj.sc_parse(handler, json)
110
+ assert_equal([[:add_value, nil]], handler.calls)
111
+ end
112
+
113
+ def test_true
114
+ handler = AllHandler.new()
115
+ json = %{true}
116
+ Oj.sc_parse(handler, json)
117
+ assert_equal([[:add_value, true]], handler.calls)
118
+ end
119
+
120
+ def test_false
121
+ handler = AllHandler.new()
122
+ json = %{false}
123
+ Oj.sc_parse(handler, json)
124
+ assert_equal([[:add_value, false]], handler.calls)
125
+ end
126
+
127
+ def test_string
128
+ handler = AllHandler.new()
129
+ json = %{"a string"}
130
+ Oj.sc_parse(handler, json)
131
+ assert_equal([[:add_value, 'a string']], handler.calls)
132
+ end
133
+
134
+ def test_fixnum
135
+ handler = AllHandler.new()
136
+ json = %{12345}
137
+ Oj.sc_parse(handler, json)
138
+ assert_equal([[:add_value, 12345]], handler.calls)
139
+ end
140
+
141
+ def test_float
142
+ handler = AllHandler.new()
143
+ json = %{12345.6789}
144
+ Oj.sc_parse(handler, json)
145
+ assert_equal([[:add_value, 12345.6789]], handler.calls)
146
+ end
147
+
148
+ def test_float_exp
149
+ handler = AllHandler.new()
150
+ json = %{12345.6789e7}
151
+ Oj.sc_parse(handler, json)
152
+ assert_equal(1, handler.calls.size)
153
+ assert_equal(:add_value, handler.calls[0][0])
154
+ assert_equal((12345.6789e7 * 10000).to_i, (handler.calls[0][1] * 10000).to_i)
155
+ end
156
+
157
+ def test_array_empty
158
+ handler = AllHandler.new()
159
+ json = %{[]}
160
+ Oj.sc_parse(handler, json)
161
+ assert_equal([[:array_start],
162
+ [:array_end],
163
+ [:add_value, []]], handler.calls)
164
+ end
165
+
166
+ def test_array
167
+ handler = AllHandler.new()
168
+ json = %{[true,false]}
169
+ Oj.sc_parse(handler, json)
170
+ assert_equal([[:array_start],
171
+ [:array_append, true],
172
+ [:array_append, false],
173
+ [:array_end],
174
+ [:add_value, []]], handler.calls)
175
+ end
176
+
177
+ def test_hash_empty
178
+ handler = AllHandler.new()
179
+ json = %{{}}
180
+ Oj.sc_parse(handler, json)
181
+ assert_equal([[:hash_start],
182
+ [:hash_end],
183
+ [:add_value, {}]], handler.calls)
184
+ end
185
+
186
+ def test_hash
187
+ handler = AllHandler.new()
188
+ json = %{{"one":true,"two":false}}
189
+ Oj.sc_parse(handler, json)
190
+ assert_equal([[:hash_start],
191
+ [:hash_key, 'one'],
192
+ [:hash_set, 'one', true],
193
+ [:hash_key, 'two'],
194
+ [:hash_set, 'too', false],
195
+ [:hash_end],
196
+ [:add_value, {}]], handler.calls)
197
+ end
198
+
199
+ def test_hash_sym
200
+ handler = AllHandler.new()
201
+ json = %{{"one":true,"two":false}}
202
+ Oj.sc_parse(handler, json, :symbol_keys => true)
203
+ assert_equal([[:hash_start],
204
+ [:hash_key, 'one'],
205
+ [:hash_set, 'one', true],
206
+ [:hash_key, 'two'],
207
+ [:hash_set, 'too', false],
208
+ [:hash_end],
209
+ [:add_value, {}]], handler.calls)
210
+ end
211
+
212
+ def test_symbol_hash_key_without_symbol_keys
213
+ handler = AllHandler.new()
214
+ json = %{{"one":true,"symbol":false}}
215
+ Oj.sc_parse(handler, json)
216
+ assert_equal([[:hash_start],
217
+ [:hash_key, 'one'],
218
+ [:hash_set, 'one', true],
219
+ [:hash_key, 'symbol'],
220
+ [:hash_set, :symbol, false],
221
+ [:hash_end],
222
+ [:add_value, {}]], handler.calls)
223
+ end
224
+
225
+ def test_full
226
+ handler = AllHandler.new()
227
+ Oj.sc_parse(handler, $json)
228
+ assert_equal([[:hash_start],
229
+ [:hash_key, 'array'],
230
+ [:array_start],
231
+ [:hash_start],
232
+ [:hash_key, 'num'],
233
+ [:hash_set, "num", 3],
234
+ [:hash_key, 'string'],
235
+ [:hash_set, "string", "message"],
236
+ [:hash_key, 'hash'],
237
+ [:hash_start],
238
+ [:hash_key, 'h2'],
239
+ [:hash_start],
240
+ [:hash_key, 'a'],
241
+ [:array_start],
242
+ [:array_append, 1],
243
+ [:array_append, 2],
244
+ [:array_append, 3],
245
+ [:array_end],
246
+ [:hash_set, "a", []],
247
+ [:hash_end],
248
+ [:hash_set, "h2", {}],
249
+ [:hash_end],
250
+ [:hash_set, "hash", {}],
251
+ [:hash_end],
252
+ [:array_append, {}],
253
+ [:array_end],
254
+ [:hash_set, "array", []],
255
+ [:hash_key, 'boolean'],
256
+ [:hash_set, "boolean", true],
257
+ [:hash_end],
258
+ [:add_value, {}]], handler.calls)
259
+ end
260
+
261
+ def test_double
262
+ handler = AllHandler.new()
263
+ json = %{{"one":true,"two":false}{"three":true,"four":false}}
264
+ Oj.sc_parse(handler, json)
265
+ assert_equal([[:hash_start],
266
+ [:hash_key, 'one'],
267
+ [:hash_set, 'one', true],
268
+ [:hash_key, 'two'],
269
+ [:hash_set, 'too', false],
270
+ [:hash_end],
271
+ [:add_value, {}],
272
+ [:hash_start],
273
+ [:hash_key, 'three'],
274
+ [:hash_set, 'three', true],
275
+ [:hash_key, 'four'],
276
+ [:hash_set, 'four', false],
277
+ [:hash_end],
278
+ [:add_value, {}]], handler.calls)
279
+ end
280
+
281
+ def test_double_io
282
+ handler = AllHandler.new()
283
+ json = %{{"one":true,"two":false}{"three":true,"four":false}}
284
+ Oj.sc_parse(handler, StringIO.new(json))
285
+ assert_equal([[:hash_start],
286
+ [:hash_key, 'one'],
287
+ [:hash_set, 'one', true],
288
+ [:hash_key, 'two'],
289
+ [:hash_set, 'too', false],
290
+ [:hash_end],
291
+ [:add_value, {}],
292
+ [:hash_start],
293
+ [:hash_key, 'three'],
294
+ [:hash_set, 'three', true],
295
+ [:hash_key, 'four'],
296
+ [:hash_set, 'four', false],
297
+ [:hash_end],
298
+ [:add_value, {}]], handler.calls)
299
+ end
300
+
301
+ def test_none
302
+ handler = NoHandler.new()
303
+ Oj.sc_parse(handler, $json)
304
+ end
305
+
306
+ def test_fixnum_bad
307
+ handler = AllHandler.new()
308
+ json = %{12345xyz}
309
+ assert_raises Oj::ParseError do
310
+ Oj.sc_parse(handler, json)
311
+ end
312
+ end
313
+
314
+ def test_null_string
315
+ handler = AllHandler.new()
316
+ json = %{"\0"}
317
+ assert_raises Oj::ParseError do
318
+ Oj.sc_parse(handler, json)
319
+ end
320
+ end
321
+
322
+ def test_pipe
323
+ handler = AllHandler.new()
324
+ json = %{{"one":true,"two":false}}
325
+ IO.pipe do |read_io, write_io|
326
+ if fork
327
+ write_io.close
328
+ Oj.sc_parse(handler, read_io) {|v| p v}
329
+ read_io.close
330
+ assert_equal([[:hash_start],
331
+ [:hash_key, 'one'],
332
+ [:hash_set, 'one', true],
333
+ [:hash_key, 'two'],
334
+ [:hash_set, 'too', false],
335
+ [:hash_end],
336
+ [:add_value, {}]], handler.calls)
337
+ else
338
+ read_io.close
339
+ write_io.write json
340
+ write_io.close
341
+ Process.exit(0)
342
+ end
343
+ end
344
+ end
345
+
346
+ def test_pipe_close
347
+ json = %{{"one":true,"two":false}}
348
+ IO.pipe do |read_io, write_io|
349
+ if fork
350
+ write_io.close
351
+ handler = Closer.new(read_io)
352
+ err = nil
353
+ begin
354
+ Oj.sc_parse(handler, read_io)
355
+ read_io.close
356
+ rescue Exception => e
357
+ err = e.class.to_s
358
+ end
359
+ assert_equal("IOError", err)
360
+ assert_equal([[:hash_start],
361
+ [:hash_key, 'one'],
362
+ [:hash_set, 'one', true]], handler.calls)
363
+ else
364
+ read_io.close
365
+ write_io.write json[0..11]
366
+ sleep(0.1)
367
+ begin
368
+ write_io.write json[12..-1]
369
+ rescue Exception => e
370
+ # ignore, should fail to write
371
+ end
372
+ write_io.close
373
+ Process.exit(0)
374
+ end
375
+ end
376
+ end
377
+
378
+ def test_socket_close
379
+ json = %{{"one":true,"two":false}}
380
+ begin
381
+ server = TCPServer.new(8080)
382
+ rescue
383
+ # Not able to open a socket to run the test. Might be Travis.
384
+ return
385
+ end
386
+ Thread.start(json) do |j|
387
+ c = server.accept()
388
+ c.puts json[0..11]
389
+ 10.times {
390
+ break if c.closed?
391
+ sleep(0.1)
392
+ }
393
+ unless c.closed?
394
+ c.puts json[12..-1]
395
+ c.close
396
+ end
397
+ end
398
+ begin
399
+ sock = TCPSocket.new('localhost', 8080)
400
+ rescue
401
+ # Not able to open a socket to run the test. Might be Travis.
402
+ return
403
+ end
404
+ handler = Closer.new(sock)
405
+ err = nil
406
+ begin
407
+ Oj.sc_parse(handler, sock)
408
+ rescue Exception => e
409
+ err = e.class.to_s
410
+ end
411
+ assert_equal("IOError", err)
412
+ assert_equal([[:hash_start],
413
+ [:hash_key, 'one'],
414
+ [:hash_set, 'one', true]], handler.calls)
415
+ end
416
+
417
+ end