oj 3.8.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 (156) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +104 -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 +1191 -0
  13. data/ext/oj/dump.c +1252 -0
  14. data/ext/oj/dump.h +96 -0
  15. data/ext/oj/dump_compat.c +977 -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 +878 -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 +1704 -0
  32. data/ext/oj/oj.h +385 -0
  33. data/ext/oj/parse.c +1086 -0
  34. data/ext/oj/parse.h +111 -0
  35. data/ext/oj/rails.c +1493 -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 +534 -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 +155 -0
  73. data/pages/Options.md +283 -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/bar.rb +25 -0
  90. data/test/files.rb +29 -0
  91. data/test/foo.rb +167 -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/perf.rb +107 -0
  113. data/test/perf_compat.rb +130 -0
  114. data/test/perf_fast.rb +164 -0
  115. data/test/perf_file.rb +64 -0
  116. data/test/perf_object.rb +138 -0
  117. data/test/perf_saj.rb +109 -0
  118. data/test/perf_scp.rb +151 -0
  119. data/test/perf_simple.rb +287 -0
  120. data/test/perf_strict.rb +145 -0
  121. data/test/perf_wab.rb +131 -0
  122. data/test/sample.rb +54 -0
  123. data/test/sample/change.rb +14 -0
  124. data/test/sample/dir.rb +19 -0
  125. data/test/sample/doc.rb +36 -0
  126. data/test/sample/file.rb +48 -0
  127. data/test/sample/group.rb +16 -0
  128. data/test/sample/hasprops.rb +16 -0
  129. data/test/sample/layer.rb +12 -0
  130. data/test/sample/line.rb +20 -0
  131. data/test/sample/oval.rb +10 -0
  132. data/test/sample/rect.rb +10 -0
  133. data/test/sample/shape.rb +35 -0
  134. data/test/sample/text.rb +20 -0
  135. data/test/sample_json.rb +37 -0
  136. data/test/test_compat.rb +509 -0
  137. data/test/test_custom.rb +503 -0
  138. data/test/test_debian.rb +53 -0
  139. data/test/test_fast.rb +470 -0
  140. data/test/test_file.rb +239 -0
  141. data/test/test_gc.rb +49 -0
  142. data/test/test_hash.rb +29 -0
  143. data/test/test_integer_range.rb +73 -0
  144. data/test/test_null.rb +376 -0
  145. data/test/test_object.rb +1018 -0
  146. data/test/test_saj.rb +186 -0
  147. data/test/test_scp.rb +433 -0
  148. data/test/test_strict.rb +410 -0
  149. data/test/test_various.rb +741 -0
  150. data/test/test_wab.rb +307 -0
  151. data/test/test_writer.rb +380 -0
  152. data/test/tests.rb +24 -0
  153. data/test/tests_mimic.rb +14 -0
  154. data/test/tests_mimic_addition.rb +7 -0
  155. data/test/zoo.rb +13 -0
  156. metadata +359 -0
@@ -0,0 +1,239 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+
6
+ require 'helper'
7
+
8
+ class FileJuice < Minitest::Test
9
+ class Jam
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
+ end# Jam
23
+
24
+ class Jeez < Jam
25
+ def initialize(x, y)
26
+ super
27
+ end
28
+
29
+ def to_json()
30
+ %{{"json_class":"#{self.class}","x":#{@x},"y":#{@y}}}
31
+ end
32
+
33
+ def self.json_create(h)
34
+ self.new(h['x'], h['y'])
35
+ end
36
+ end# Jeez
37
+
38
+ class Orange < Jam
39
+ def initialize(x, y)
40
+ super
41
+ end
42
+
43
+ def as_json()
44
+ { :json_class => self.class,
45
+ :x => @x,
46
+ :y => @y }
47
+ end
48
+
49
+ def self.json_create(h)
50
+ self.new(h['x'], h['y'])
51
+ end
52
+ end
53
+
54
+ def setup
55
+ @default_options = Oj.default_options
56
+ end
57
+
58
+ def teardown
59
+ Oj.default_options = @default_options
60
+ end
61
+
62
+ def test_nil
63
+ dump_and_load(nil, false)
64
+ end
65
+
66
+ def test_true
67
+ dump_and_load(true, false)
68
+ end
69
+
70
+ def test_false
71
+ dump_and_load(false, false)
72
+ end
73
+
74
+ def test_fixnum
75
+ dump_and_load(0, false)
76
+ dump_and_load(12345, false)
77
+ dump_and_load(-54321, false)
78
+ dump_and_load(1, false)
79
+ end
80
+
81
+ def test_float
82
+ mode = Oj.default_options()[:mode]
83
+ Oj.default_options = {:mode => :object}
84
+ dump_and_load(0.0, false)
85
+ dump_and_load(12345.6789, false)
86
+ dump_and_load(70.35, false)
87
+ dump_and_load(-54321.012, false)
88
+ dump_and_load(1.7775, false)
89
+ dump_and_load(2.5024, false)
90
+ dump_and_load(2.48e16, false)
91
+ dump_and_load(2.48e100 * 1.0e10, false)
92
+ dump_and_load(-2.48e100 * 1.0e10, false)
93
+ dump_and_load(1/0.0, false)
94
+ Oj.default_options = {:mode => mode}
95
+ end
96
+
97
+ def test_string
98
+ dump_and_load('', false)
99
+ dump_and_load('abc', false)
100
+ dump_and_load("abc\ndef", false)
101
+ dump_and_load("a\u0041", false)
102
+ assert_equal("a\u0000a", dump_and_load("a\u0000a", false))
103
+ end
104
+
105
+ def test_string_object
106
+ dump_and_load('abc', false)
107
+ dump_and_load(':abc', false)
108
+ end
109
+
110
+ def test_array
111
+ dump_and_load([], false)
112
+ dump_and_load([true, false], false)
113
+ dump_and_load(['a', 1, nil], false)
114
+ dump_and_load([[nil]], false)
115
+ dump_and_load([[nil], 58], false)
116
+ end
117
+
118
+ # Symbol
119
+ def test_symbol_object
120
+ Oj.default_options = { :mode => :object }
121
+ #dump_and_load(''.to_sym, false)
122
+ dump_and_load(:abc, false)
123
+ dump_and_load(':xyz'.to_sym, false)
124
+ end
125
+
126
+ # Time
127
+ def test_time_object
128
+ t = Time.now()
129
+ Oj.default_options = { :mode => :object, :time_format => :unix_zone }
130
+ dump_and_load(t, false)
131
+ end
132
+ def test_time_object_early
133
+ # Windows does not support dates before 1970.
134
+ return if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
135
+ t = Time.xmlschema("1954-01-05T00:00:00.123456")
136
+ Oj.default_options = { :mode => :object, :time_format => :unix_zone }
137
+ dump_and_load(t, false)
138
+ end
139
+
140
+ # Hash
141
+ def test_hash
142
+ Oj.default_options = { :mode => :strict }
143
+ dump_and_load({}, false)
144
+ dump_and_load({ 'true' => true, 'false' => false}, false)
145
+ dump_and_load({ 'true' => true, 'array' => [], 'hash' => { }}, false)
146
+ end
147
+
148
+ # Object with to_json()
149
+ def test_json_object_compat
150
+ Oj.default_options = { :mode => :compat, :use_to_json => true, :create_additions => true }
151
+ obj = Jeez.new(true, 58)
152
+ json = Oj.dump(obj, :indent => 2)
153
+ assert(%{{"json_class":"FileJuice::Jeez","x":true,"y":58}
154
+ } == json ||
155
+ %{{"json_class":"FileJuice::Jeez","y":58,"x":true}
156
+ } == json)
157
+ dump_and_load(obj, false)
158
+ Oj.default_options = { :mode => :compat, :use_to_json => false }
159
+ end
160
+
161
+ # Range
162
+ def test_range_object
163
+ Oj.default_options = { :mode => :object }
164
+ json = Oj.dump(1..7, :mode => :object, :indent => 0)
165
+ if 'rubinius' == $ruby
166
+ assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
167
+ elsif 'jruby' == $ruby
168
+ assert(%{{"^O":"Range","begin":1,"end":7,"exclude_end?":false}} == json)
169
+ else
170
+ assert_equal(%{{"^u":["Range",1,7,false]}}, json)
171
+ end
172
+ dump_and_load(1..7, false)
173
+ dump_and_load(1..1, false)
174
+ dump_and_load(1...7, false)
175
+ end
176
+
177
+ # BigNum
178
+ def test_bignum_object
179
+ Oj.default_options = { :mode => :compat }
180
+ dump_and_load(7 ** 55, false)
181
+ end
182
+
183
+ # BigDecimal
184
+ def test_bigdecimal_strict
185
+ mode = Oj.default_options[:mode]
186
+ Oj.default_options = {:mode => :strict}
187
+ dump_and_load(BigDecimal('3.14159265358979323846'), false)
188
+ Oj.default_options = {:mode => mode}
189
+ end
190
+
191
+ def test_bigdecimal_null
192
+ mode = Oj.default_options[:mode]
193
+ Oj.default_options = {:mode => :null}
194
+ dump_and_load(BigDecimal('3.14159265358979323846'), false)
195
+ Oj.default_options = {:mode => mode}
196
+ end
197
+
198
+ def test_bigdecimal_object
199
+ Oj.default_options = {:mode => :object}
200
+ dump_and_load(BigDecimal('3.14159265358979323846'), false)
201
+ end
202
+
203
+ # Date
204
+ def test_date_object
205
+ Oj.default_options = { :mode => :object }
206
+ dump_and_load(Date.new(2012, 6, 19), false)
207
+ end
208
+
209
+ # DateTime
210
+ def test_datetime_object
211
+ Oj.default_options = { :mode => :object }
212
+ dump_and_load(DateTime.new(2012, 6, 19), false)
213
+ end
214
+
215
+ def dump_and_load(obj, trace=false)
216
+ filename = File.join(File.dirname(__FILE__), 'file_test.json')
217
+ File.open(filename, "w") { |f|
218
+ Oj.to_stream(f, obj, :indent => 2)
219
+ }
220
+ puts "\n*** file: '#{File.read(filename)}'" if trace
221
+ loaded = Oj.load_file(filename)
222
+ if obj.is_a?(Time) && loaded.is_a?(Time)
223
+ assert_equal(obj.tv_sec, loaded.tv_sec)
224
+ if obj.respond_to?(:tv_nsec)
225
+ assert_equal(obj.tv_nsec, loaded.tv_nsec)
226
+ else
227
+ assert_equal(obj.tv_usec, loaded.tv_usec)
228
+ end
229
+ assert_equal(obj.utc?, loaded.utc?)
230
+ assert_equal(obj.utc_offset, loaded.utc_offset)
231
+ elsif obj.nil?
232
+ assert_nil(loaded)
233
+ else
234
+ assert_equal(obj, loaded)
235
+ end
236
+ loaded
237
+ end
238
+
239
+ end
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+
6
+ require 'helper'
7
+
8
+ class GCTest < Minitest::Test
9
+ class Goo
10
+ attr_accessor :x, :child
11
+
12
+ def initialize(x, child)
13
+ @x = x
14
+ @child = child
15
+ end
16
+
17
+ def to_hash()
18
+ { 'json_class' => "#{self.class}", 'x' => x, 'child' => child }
19
+ end
20
+
21
+ def self.json_create(h)
22
+ GC.start
23
+ self.new(h['x'], h['child'])
24
+ end
25
+ end # Goo
26
+
27
+ def setup
28
+ @default_options = Oj.default_options
29
+ end
30
+
31
+ def teardown
32
+ Oj.default_options = @default_options
33
+ end
34
+
35
+ # if no crash then the GC marking is working
36
+ def test_parse_compat_gc
37
+ g = Goo.new(0, nil)
38
+ 100.times { |i| g = Goo.new(i, g) }
39
+ json = Oj.dump(g, :mode => :compat)
40
+ Oj.compat_load(json)
41
+ end
42
+
43
+ def test_parse_object_gc
44
+ g = Goo.new(0, nil)
45
+ 100.times { |i| g = Goo.new(i, g) }
46
+ json = Oj.dump(g, :mode => :object)
47
+ Oj.object_load(json)
48
+ end
49
+ end
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+
6
+ require 'helper'
7
+
8
+ class Hashi < Minitest::Test
9
+
10
+ module TestModule
11
+ end
12
+
13
+ def test_dump
14
+ h = Oj::EasyHash.new()
15
+ h['abc'] = 3
16
+ out = Oj.dump(h, :mode => :compat)
17
+ assert_equal(%|{"abc":3}|, out)
18
+ end
19
+
20
+ def test_load
21
+ obj = Oj.load(%|{"abc":3}|, :mode => :compat, :hash_class => Oj::EasyHash)
22
+
23
+ assert_equal(Oj::EasyHash, obj.class)
24
+ assert_equal(3, obj['abc'])
25
+ assert_equal(3, obj[:abc])
26
+ assert_equal(3, obj.abc())
27
+ end
28
+
29
+ end # HashTest
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
6
+ %w(lib ext).each do |dir|
7
+ $: << File.join($oj_dir, dir)
8
+ end
9
+
10
+ require 'minitest'
11
+ require 'minitest/autorun'
12
+ require 'oj'
13
+
14
+ class IntegerRangeTest < Minitest::Test
15
+ def setup
16
+ @default_options = Oj.default_options
17
+ # in null mode other options other than the number formats are not used.
18
+ Oj.default_options = { :mode => :null }
19
+ end
20
+
21
+ def teardown
22
+ Oj.default_options = @default_options
23
+ end
24
+
25
+ def test_range
26
+ test = {s: 0, s2: -1, s3: 1, u: -2, u2: 2, u3: 9007199254740993}
27
+ exp = '{"s":0,"s2":-1,"s3":1,"u":"-2","u2":"2","u3":"9007199254740993"}'
28
+ assert_equal(exp, Oj.dump(test, integer_range: (-1..1)))
29
+ end
30
+
31
+ def test_bignum
32
+ test = {u: -10000000000000000000, u2: 10000000000000000000}
33
+ exp = '{"u":"-10000000000000000000","u2":"10000000000000000000"}'
34
+ assert_equal(exp, Oj.dump(test, integer_range: (-1..1)))
35
+ end
36
+
37
+ def test_valid_modes
38
+ test = {safe: 0, unsafe: 9007199254740993}
39
+ exp = '{"safe":0,"unsafe":"9007199254740993"}'
40
+
41
+ [:strict, :null, :compat, :rails, :custom].each do |mode|
42
+ assert_equal(exp, Oj.dump(test, mode: mode, integer_range: (-1..1)), "Invalid mode #{mode}")
43
+ end
44
+
45
+ exp = '{":safe":0,":unsafe":"9007199254740993"}'
46
+ [:object].each do |mode|
47
+ assert_equal(exp, Oj.dump(test, mode: mode, integer_range: (-1..1)), "Invalid mode #{mode}")
48
+ end
49
+ end
50
+
51
+ def test_modes_without_opt
52
+ test = {safe:0, unsafe: 10000000000000000000}
53
+ exp = '{"safe":0,"unsafe":10000000000000000000}'
54
+
55
+ [:strict, :null, :compat, :rails, :custom].each do |mode|
56
+ assert_equal(exp, Oj.dump(test, mode: mode), "Invalid mode #{mode}")
57
+ end
58
+
59
+ exp = '{":safe":0,":unsafe":10000000000000000000}'
60
+ [:object].each do |mode|
61
+ assert_equal(exp, Oj.dump(test, mode: mode), "Invalid mode #{mode}")
62
+ end
63
+ end
64
+
65
+ def test_accept_nil_and_false
66
+ test = {safe:0, unsafe: 10000000000000000000}
67
+ exp = '{"safe":0,"unsafe":10000000000000000000}'
68
+
69
+ assert_equal(exp, Oj.dump(test, integer_range: nil))
70
+ assert_equal(exp, Oj.dump(test, integer_range: false))
71
+ end
72
+ end
73
+
@@ -0,0 +1,376 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ $: << File.dirname(__FILE__)
5
+ $oj_dir = File.dirname(File.expand_path(File.dirname(__FILE__)))
6
+ %w(lib ext).each do |dir|
7
+ $: << File.join($oj_dir, dir)
8
+ end
9
+
10
+ require 'minitest'
11
+ require 'minitest/autorun'
12
+ require 'stringio'
13
+ require 'date'
14
+ require 'bigdecimal'
15
+ require 'oj'
16
+
17
+ class NullJuice < Minitest::Test
18
+
19
+ module TestModule
20
+ end
21
+
22
+ class Jeez
23
+ attr_accessor :x, :y
24
+
25
+ def initialize(x, y)
26
+ @x = x
27
+ @y = y
28
+ end
29
+ end
30
+
31
+ def setup
32
+ @default_options = Oj.default_options
33
+ # in null mode other options other than the number formats are not used.
34
+ Oj.default_options = { :mode => :null }
35
+ end
36
+
37
+ def teardown
38
+ Oj.default_options = @default_options
39
+ end
40
+
41
+ def test_nil
42
+ dump_and_load(nil, false)
43
+ end
44
+
45
+ def test_true
46
+ dump_and_load(true, false)
47
+ end
48
+
49
+ def test_false
50
+ dump_and_load(false, false)
51
+ end
52
+
53
+ def test_fixnum
54
+ dump_and_load(0, false)
55
+ dump_and_load(12345, false)
56
+ dump_and_load(-54321, false)
57
+ dump_and_load(1, false)
58
+ end
59
+
60
+ def test_float
61
+ dump_and_load(0.0, false)
62
+ dump_and_load(12345.6789, false)
63
+ dump_and_load(70.35, false)
64
+ dump_and_load(-54321.012, false)
65
+ dump_and_load(1.7775, false)
66
+ dump_and_load(2.5024, false)
67
+ dump_and_load(2.48e16, false)
68
+ dump_and_load(2.48e100 * 1.0e10, false)
69
+ dump_and_load(-2.48e100 * 1.0e10, false)
70
+ end
71
+
72
+ def test_nan_dump
73
+ assert_equal('null', Oj.dump(0/0.0, :nan => :null))
74
+ assert_equal('3.3e14159265358979323846', Oj.dump(0/0.0, :nan => :huge))
75
+ begin
76
+ Oj.dump(0/0.0, :nan => :word)
77
+ rescue Exception
78
+ assert(true)
79
+ return
80
+ end
81
+ assert(false, "*** expected an exception")
82
+ end
83
+
84
+ def test_infinity_dump
85
+ assert_equal('null', Oj.dump(1/0.0, :nan => :null))
86
+ assert_equal('3.0e14159265358979323846', Oj.dump(1/0.0, :nan => :huge))
87
+ begin
88
+ Oj.dump(1/0.0, :nan => :word)
89
+ rescue Exception
90
+ assert(true)
91
+ return
92
+ end
93
+ assert(false, "*** expected an exception")
94
+ end
95
+
96
+ def test_neg_infinity_dump
97
+ assert_equal('null', Oj.dump(-1/0.0, :nan => :null))
98
+ assert_equal('-3.0e14159265358979323846', Oj.dump(-1/0.0, :nan => :huge))
99
+ begin
100
+ Oj.dump(-1/0.0, :nan => :word)
101
+ rescue Exception
102
+ assert(true)
103
+ return
104
+ end
105
+ assert(false, "*** expected an exception")
106
+ end
107
+
108
+ def test_string
109
+ dump_and_load('', false)
110
+ dump_and_load('abc', false)
111
+ dump_and_load("abc\ndef", false)
112
+ dump_and_load("a\u0041", false)
113
+ end
114
+
115
+ def test_encode
116
+ opts = Oj.default_options
117
+ Oj.default_options = { :ascii_only => false }
118
+ unless 'jruby' == $ruby
119
+ dump_and_load("ぴーたー", false)
120
+ end
121
+ Oj.default_options = { :ascii_only => true }
122
+ json = Oj.dump("ぴーたー")
123
+ assert_equal(%{"\\u3074\\u30fc\\u305f\\u30fc"}, json)
124
+ unless 'jruby' == $ruby
125
+ dump_and_load("ぴーたー", false)
126
+ end
127
+ Oj.default_options = opts
128
+ end
129
+
130
+ def test_unicode
131
+ # hits the 3 normal ranges and one extended surrogate pair
132
+ json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e"}
133
+ obj = Oj.load(json)
134
+ json2 = Oj.dump(obj, :ascii_only => true)
135
+ assert_equal(json, json2)
136
+ end
137
+
138
+ def test_unicode_long
139
+ # tests buffer overflow
140
+ json = %{"\\u019f\\u05e9\\u3074\\ud834\\udd1e #{'x' * 2000}"}
141
+ obj = Oj.load(json)
142
+ json2 = Oj.dump(obj, :ascii_only => true)
143
+ assert_equal(json, json2)
144
+ end
145
+
146
+ def test_array
147
+ dump_and_load([], false)
148
+ dump_and_load([true, false], false)
149
+ dump_and_load(['a', 1, nil], false)
150
+ dump_and_load([[nil]], false)
151
+ dump_and_load([[nil], 58], false)
152
+ end
153
+
154
+ def test_array_deep
155
+ dump_and_load([1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20]]]]]]]]]]]]]]]]]]]], false)
156
+ end
157
+
158
+ # Hash
159
+ def test_hash
160
+ dump_and_load({}, false)
161
+ dump_and_load({ 'true' => true, 'false' => false}, false)
162
+ dump_and_load({ 'true' => true, 'array' => [], 'hash' => { }}, false)
163
+ end
164
+
165
+ def test_hash_deep
166
+ dump_and_load({'1' => {
167
+ '2' => {
168
+ '3' => {
169
+ '4' => {
170
+ '5' => {
171
+ '6' => {
172
+ '7' => {
173
+ '8' => {
174
+ '9' => {
175
+ '10' => {
176
+ '11' => {
177
+ '12' => {
178
+ '13' => {
179
+ '14' => {
180
+ '15' => {
181
+ '16' => {
182
+ '17' => {
183
+ '18' => {
184
+ '19' => {
185
+ '20' => {}}}}}}}}}}}}}}}}}}}}}, false)
186
+ end
187
+
188
+ def test_hash_escaped_key
189
+ json = %{{"a\nb":true,"c\td":false}}
190
+ obj = Oj.strict_load(json)
191
+ assert_equal({"a\nb" => true, "c\td" => false}, obj)
192
+ end
193
+
194
+ def test_non_str_hash
195
+ begin
196
+ Oj.dump({ 1 => true, 0 => false })
197
+ rescue Exception
198
+ assert(true)
199
+ return
200
+ end
201
+ assert(false, "*** expected an exception")
202
+ end
203
+
204
+ def test_bignum_object
205
+ dump_and_load(7 ** 55, false)
206
+ end
207
+
208
+ # BigDecimal
209
+ def test_bigdecimal_strict
210
+ Oj.default_options = { :bigdecimal_load => true}
211
+ dump_and_load(BigDecimal('3.14159265358979323846'), false)
212
+ end
213
+
214
+ def test_bigdecimal_load
215
+ orig = BigDecimal('80.51')
216
+ json = Oj.dump(orig, :mode => :strict, :bigdecimal_as_decimal => true)
217
+ bg = Oj.load(json, :mode => :strict, :bigdecimal_load => true)
218
+ assert_equal(BigDecimal, bg.class)
219
+ assert_equal(orig, bg)
220
+ end
221
+
222
+ def test_json_object
223
+ obj = Jeez.new(true, 58)
224
+ json = Oj.dump(obj)
225
+ assert_equal('null', json)
226
+ end
227
+
228
+ def test_range
229
+ json = Oj.dump(1..7)
230
+ assert_equal('null', json)
231
+ end
232
+
233
+ # Stream IO
234
+ def test_io_string
235
+ json = %{{
236
+ "x":true,
237
+ "y":58,
238
+ "z": [1,2,3]
239
+ }
240
+ }
241
+ input = StringIO.new(json)
242
+ obj = Oj.strict_load(input)
243
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
244
+ end
245
+
246
+ def test_io_file
247
+ filename = File.join(File.dirname(__FILE__), 'open_file_test.json')
248
+ File.open(filename, 'w') { |f| f.write(%{{
249
+ "x":true,
250
+ "y":58,
251
+ "z": [1,2,3]
252
+ }
253
+ }) }
254
+ f = File.new(filename)
255
+ obj = Oj.strict_load(f)
256
+ f.close()
257
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
258
+ end
259
+
260
+ def test_symbol
261
+ json = Oj.dump(:abc)
262
+ assert_equal('"abc"', json)
263
+ end
264
+
265
+ def test_time
266
+ t = Time.local(2012, 1, 5, 23, 58, 7)
267
+ json = Oj.dump(t)
268
+ assert_equal('null', json)
269
+ end
270
+
271
+ def test_class
272
+ json = Oj.dump(NullJuice)
273
+ assert_equal('null', json)
274
+ end
275
+
276
+ def test_module
277
+ json = Oj.dump(TestModule)
278
+ assert_equal('null', json)
279
+ end
280
+
281
+ # symbol_keys option
282
+ def test_symbol_keys
283
+ json = %{{
284
+ "x":true,
285
+ "y":58,
286
+ "z": [1,2,3]
287
+ }
288
+ }
289
+ obj = Oj.strict_load(json, :symbol_keys => true)
290
+ assert_equal({ :x => true, :y => 58, :z => [1, 2, 3]}, obj)
291
+ end
292
+
293
+ def test_symbol_keys_safe
294
+ json = %{{
295
+ "x":true,
296
+ "y":58,
297
+ "z": [1,2,3]
298
+ }
299
+ }
300
+ obj = Oj.safe_load(json)
301
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
302
+ end
303
+
304
+ # comments
305
+ def test_comment_slash
306
+ json = %{{
307
+ "x":true,//three
308
+ "y":58,
309
+ "z": [1,2,
310
+ 3 // six
311
+ ]}
312
+ }
313
+ obj = Oj.strict_load(json)
314
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
315
+ end
316
+
317
+ def test_comment_c
318
+ json = %{{
319
+ "x"/*one*/:/*two*/true,
320
+ "y":58,
321
+ "z": [1,2,3]}
322
+ }
323
+ obj = Oj.strict_load(json)
324
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
325
+ end
326
+
327
+ def test_comment
328
+ json = %{{
329
+ "x"/*one*/:/*two*/true,//three
330
+ "y":58/*four*/,
331
+ "z": [1,2/*five*/,
332
+ 3 // six
333
+ ]
334
+ }
335
+ }
336
+ obj = Oj.strict_load(json)
337
+ assert_equal({ 'x' => true, 'y' => 58, 'z' => [1, 2, 3]}, obj)
338
+ end
339
+
340
+ def test_double
341
+ json = %{{ "x": 1}{ "y": 2}}
342
+ results = []
343
+ Oj.load(json, :mode => :strict) { |x| results << x }
344
+
345
+ assert_equal([{ 'x' => 1 }, { 'y' => 2 }], results)
346
+ end
347
+
348
+ def test_circular_hash
349
+ h = { 'a' => 7 }
350
+ h['b'] = h
351
+ json = Oj.dump(h, :indent => 2, :circular => true, :mode => :null)
352
+ assert_equal(%|{
353
+ "a":7,
354
+ "b":null
355
+ }
356
+ |, json)
357
+ end
358
+
359
+ def test_omit_nil
360
+ json = Oj.dump({'x' => {'a' => 1, 'b' => nil }, 'y' => nil}, :omit_nil => true)
361
+ assert_equal(%|{"x":{"a":1}}|, json)
362
+ end
363
+
364
+ def dump_and_load(obj, trace=false)
365
+ json = Oj.dump(obj, :indent => 2)
366
+ puts json if trace
367
+ loaded = Oj.strict_load(json);
368
+ if obj.nil?
369
+ assert_nil(loaded)
370
+ else
371
+ assert_equal(obj, loaded)
372
+ end
373
+ loaded
374
+ end
375
+
376
+ end