oj 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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