oj 2.18.5 → 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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +33 -226
  3. data/ext/oj/circarray.c +0 -25
  4. data/ext/oj/circarray.h +0 -25
  5. data/ext/oj/code.c +227 -0
  6. data/ext/oj/code.h +40 -0
  7. data/ext/oj/compat.c +126 -38
  8. data/ext/oj/custom.c +1097 -0
  9. data/ext/oj/dump.c +658 -2376
  10. data/ext/oj/dump.h +92 -0
  11. data/ext/oj/dump_compat.c +937 -0
  12. data/ext/oj/dump_leaf.c +254 -0
  13. data/ext/oj/dump_object.c +810 -0
  14. data/ext/oj/dump_rails.c +329 -0
  15. data/ext/oj/dump_strict.c +416 -0
  16. data/ext/oj/err.c +0 -25
  17. data/ext/oj/err.h +8 -2
  18. data/ext/oj/fast.c +24 -24
  19. data/ext/oj/mimic_json.c +817 -0
  20. data/ext/oj/mimic_rails.c +806 -0
  21. data/ext/oj/mimic_rails.h +17 -0
  22. data/ext/oj/object.c +18 -72
  23. data/ext/oj/odd.c +0 -25
  24. data/ext/oj/odd.h +2 -27
  25. data/ext/oj/oj.c +655 -1503
  26. data/ext/oj/oj.h +93 -40
  27. data/ext/oj/parse.c +99 -46
  28. data/ext/oj/parse.h +12 -26
  29. data/ext/oj/reader.c +1 -25
  30. data/ext/oj/reader.h +3 -25
  31. data/ext/oj/resolve.c +9 -11
  32. data/ext/oj/resolve.h +2 -2
  33. data/ext/oj/rxclass.c +133 -0
  34. data/ext/oj/rxclass.h +27 -0
  35. data/ext/oj/saj.c +4 -25
  36. data/ext/oj/scp.c +3 -25
  37. data/ext/oj/sparse.c +89 -13
  38. data/ext/oj/stream_writer.c +301 -0
  39. data/ext/oj/strict.c +4 -27
  40. data/ext/oj/string_writer.c +480 -0
  41. data/ext/oj/val_stack.h +6 -2
  42. data/lib/oj.rb +1 -23
  43. data/lib/oj/easy_hash.rb +12 -4
  44. data/lib/oj/json.rb +172 -0
  45. data/lib/oj/mimic.rb +123 -18
  46. data/lib/oj/state.rb +131 -0
  47. data/lib/oj/version.rb +1 -1
  48. data/pages/Advanced.md +22 -0
  49. data/pages/Compatibility.md +25 -0
  50. data/pages/Custom.md +23 -0
  51. data/pages/Encoding.md +65 -0
  52. data/pages/JsonGem.md +79 -0
  53. data/pages/Modes.md +140 -0
  54. data/pages/Options.md +250 -0
  55. data/pages/Rails.md +60 -0
  56. data/pages/Security.md +20 -0
  57. data/test/activesupport4/decoding_test.rb +105 -0
  58. data/test/activesupport4/encoding_test.rb +531 -0
  59. data/test/activesupport4/test_helper.rb +41 -0
  60. data/test/activesupport5/decoding_test.rb +125 -0
  61. data/test/activesupport5/encoding_test.rb +483 -0
  62. data/test/activesupport5/encoding_test_cases.rb +90 -0
  63. data/test/activesupport5/test_helper.rb +50 -0
  64. data/test/activesupport5/time_zone_test_helpers.rb +24 -0
  65. data/test/json_gem/json_addition_test.rb +216 -0
  66. data/test/json_gem/json_common_interface_test.rb +143 -0
  67. data/test/json_gem/json_encoding_test.rb +109 -0
  68. data/test/json_gem/json_ext_parser_test.rb +20 -0
  69. data/test/json_gem/json_fixtures_test.rb +35 -0
  70. data/test/json_gem/json_generator_test.rb +383 -0
  71. data/test/json_gem/json_generic_object_test.rb +90 -0
  72. data/test/json_gem/json_parser_test.rb +470 -0
  73. data/test/json_gem/json_string_matching_test.rb +42 -0
  74. data/test/json_gem/test_helper.rb +18 -0
  75. data/test/perf_compat.rb +30 -28
  76. data/test/perf_object.rb +1 -1
  77. data/test/perf_strict.rb +18 -1
  78. data/test/sample.rb +0 -1
  79. data/test/test_compat.rb +169 -93
  80. data/test/test_custom.rb +355 -0
  81. data/test/test_file.rb +0 -8
  82. data/test/test_null.rb +376 -0
  83. data/test/test_object.rb +268 -3
  84. data/test/test_scp.rb +22 -1
  85. data/test/test_strict.rb +160 -4
  86. data/test/test_various.rb +52 -620
  87. data/test/tests.rb +14 -0
  88. data/test/tests_mimic.rb +14 -0
  89. data/test/tests_mimic_addition.rb +7 -0
  90. metadata +89 -47
  91. data/test/activesupport_datetime_test.rb +0 -23
  92. data/test/bug.rb +0 -51
  93. data/test/bug2.rb +0 -10
  94. data/test/bug3.rb +0 -46
  95. data/test/bug_fast.rb +0 -32
  96. data/test/bug_load.rb +0 -24
  97. data/test/crash.rb +0 -111
  98. data/test/curl/curl_oj.rb +0 -46
  99. data/test/curl/get_oj.rb +0 -24
  100. data/test/curl/just_curl.rb +0 -31
  101. data/test/curl/just_oj.rb +0 -51
  102. data/test/example.rb +0 -11
  103. data/test/foo.rb +0 -24
  104. data/test/io.rb +0 -48
  105. data/test/isolated/test_mimic_rails_datetime.rb +0 -27
  106. data/test/mod.rb +0 -16
  107. data/test/rails.rb +0 -50
  108. data/test/russian.rb +0 -18
  109. data/test/struct.rb +0 -29
  110. data/test/test_serializer.rb +0 -59
  111. data/test/write_timebars.rb +0 -31
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ #frozen_string_literal: false
5
+
6
+ require 'json_gem/test_helper'
7
+
8
+ class JSONEncodingTest < Test::Unit::TestCase
9
+ include Test::Unit::TestCaseOmissionSupport
10
+ include Test::Unit::TestCasePendingSupport
11
+
12
+ def setup
13
+ @utf_8 = '"© ≠ €!"'
14
+ @ascii_8bit = @utf_8.dup.force_encoding('ascii-8bit')
15
+ @parsed = "© ≠ €!"
16
+ @generated = '"\u00a9 \u2260 \u20ac!"'
17
+ if String.method_defined?(:encode)
18
+ @utf_16_data = @parsed.encode('utf-16be', 'utf-8')
19
+ @utf_16be = @utf_8.encode('utf-16be', 'utf-8')
20
+ @utf_16le = @utf_8.encode('utf-16le', 'utf-8')
21
+ @utf_32be = @utf_8.encode('utf-32be', 'utf-8')
22
+ @utf_32le = @utf_8.encode('utf-32le', 'utf-8')
23
+ else
24
+ require 'iconv'
25
+ @utf_16_data, = Iconv.iconv('utf-16be', 'utf-8', @parsed)
26
+ @utf_16be, = Iconv.iconv('utf-16be', 'utf-8', @utf_8)
27
+ @utf_16le, = Iconv.iconv('utf-16le', 'utf-8', @utf_8)
28
+ @utf_32be, = Iconv.iconv('utf-32be', 'utf-8', @utf_8)
29
+ @utf_32le, = Iconv.iconv('utf-32le', 'utf-8', @utf_8)
30
+ end
31
+ end
32
+
33
+ def test_parse
34
+ assert_equal @parsed, JSON.parse(@ascii_8bit)
35
+ assert_equal @parsed, JSON.parse(@utf_8)
36
+ assert_equal @parsed, JSON.parse(@utf_16be)
37
+ assert_equal @parsed, JSON.parse(@utf_16le)
38
+ assert_equal @parsed, JSON.parse(@utf_32be)
39
+ assert_equal @parsed, JSON.parse(@utf_32le)
40
+ end
41
+
42
+ def test_generate
43
+ assert_equal @generated, JSON.generate(@parsed, :ascii_only => true)
44
+ assert_equal @generated, JSON.generate(@utf_16_data, :ascii_only => true)
45
+ end
46
+
47
+ def test_unicode
48
+ assert_equal '""', ''.to_json
49
+ assert_equal '"\\b"', "\b".to_json
50
+ assert_equal '"\u0001"', 0x1.chr.to_json
51
+ assert_equal '"\u001f"', 0x1f.chr.to_json
52
+ assert_equal '" "', ' '.to_json
53
+ assert_equal "\"#{0x7f.chr}\"", 0x7f.chr.to_json
54
+ utf8 = [ "© ≠ €! \01" ]
55
+ json = '["© ≠ €! \u0001"]'
56
+ assert_equal json, utf8.to_json(:ascii_only => false)
57
+ assert_equal utf8, JSON.parse(json)
58
+ json = '["\u00a9 \u2260 \u20ac! \u0001"]'
59
+ assert_equal json, utf8.to_json(:ascii_only => true)
60
+ assert_equal utf8, JSON.parse(json)
61
+ utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
62
+ json = "[\"\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212\"]"
63
+ assert_equal utf8, JSON.parse(json)
64
+ assert_equal json, utf8.to_json(:ascii_only => false)
65
+ utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
66
+ assert_equal utf8, JSON.parse(json)
67
+ json = "[\"\\u3042\\u3044\\u3046\\u3048\\u304a\"]"
68
+ assert_equal json, utf8.to_json(:ascii_only => true)
69
+ assert_equal utf8, JSON.parse(json)
70
+ utf8 = ['საქართველო']
71
+ json = '["საქართველო"]'
72
+ assert_equal json, utf8.to_json(:ascii_only => false)
73
+ json = "[\"\\u10e1\\u10d0\\u10e5\\u10d0\\u10e0\\u10d7\\u10d5\\u10d4\\u10da\\u10dd\"]"
74
+ assert_equal json, utf8.to_json(:ascii_only => true)
75
+ assert_equal utf8, JSON.parse(json)
76
+ assert_equal '["Ã"]', JSON.generate(["Ã"], :ascii_only => false)
77
+ assert_equal '["\\u00c3"]', JSON.generate(["Ã"], :ascii_only => true)
78
+ assert_equal ["€"], JSON.parse('["\u20ac"]')
79
+ utf8 = ["\xf0\xa0\x80\x81"]
80
+ json = "[\"\xf0\xa0\x80\x81\"]"
81
+ assert_equal json, JSON.generate(utf8, :ascii_only => false)
82
+ assert_equal utf8, JSON.parse(json)
83
+ json = '["\ud840\udc01"]'
84
+ assert_equal json, JSON.generate(utf8, :ascii_only => true)
85
+ assert_equal utf8, JSON.parse(json)
86
+ end
87
+
88
+ def test_chars
89
+ (0..0x7f).each do |i|
90
+ json = '["\u%04x"]' % i
91
+ if RUBY_VERSION >= "1.9."
92
+ i = i.chr
93
+ end
94
+ assert_equal i, JSON.parse(json).first[0]
95
+ if i == ?\b
96
+ generated = JSON.generate(["" << i])
97
+ assert '["\b"]' == generated || '["\10"]' == generated
98
+ elsif [?\n, ?\r, ?\t, ?\f].include?(i)
99
+ assert_equal '[' << ('' << i).dump << ']', JSON.generate(["" << i])
100
+ elsif i.chr < 0x20.chr
101
+ assert_equal json, JSON.generate(["" << i])
102
+ end
103
+ end
104
+ assert_raise(JSON::GeneratorError) do
105
+ JSON.generate(["\x80"], :ascii_only => true)
106
+ end
107
+ assert_equal "\302\200", JSON.parse('["\u0080"]').first
108
+ end
109
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ #frozen_string_literal: false
5
+ require 'json_gem/test_helper'
6
+
7
+ class JSONExtParserTest < Test::Unit::TestCase
8
+ include Test::Unit::TestCaseOmissionSupport
9
+
10
+ if defined?(JSON::Ext::Parser)
11
+ def test_allocate
12
+ parser = JSON::Ext::Parser.new("{}")
13
+ assert_raise(TypeError, '[ruby-core:35079]') do
14
+ parser.__send__(:initialize, "{}")
15
+ end
16
+ parser = JSON::Ext::Parser.allocate
17
+ assert_raise(TypeError, '[ruby-core:35079]') { parser.source }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ #frozen_string_literal: false
5
+ require 'json_gem/test_helper'
6
+
7
+ class JSONFixturesTest < Test::Unit::TestCase
8
+ def setup
9
+ fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}.json')
10
+ passed, failed = Dir[fixtures].partition { |f| f['pass'] }
11
+ @passed = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
12
+ @failed = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
13
+ end
14
+
15
+ def test_passing
16
+ for name, source in @passed
17
+ begin
18
+ assert JSON.parse(source),
19
+ "Did not pass for fixture '#{name}': #{source.inspect}"
20
+ rescue => e
21
+ warn "\nCaught #{e.class}(#{e}) for fixture '#{name}': #{source.inspect}\n#{e.backtrace * "\n"}"
22
+ raise e
23
+ end
24
+ end
25
+ end
26
+
27
+ def test_failing
28
+ for name, source in @failed
29
+ assert_raise(JSON::ParserError, JSON::NestingError,
30
+ "Did not fail for fixture '#{name}': #{source.inspect}") do
31
+ JSON.parse(source)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,383 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ # frozen_string_literal: false
5
+
6
+ require 'json_gem/test_helper'
7
+
8
+ class JSONGeneratorTest < Test::Unit::TestCase
9
+ include Test::Unit::TestCaseOmissionSupport
10
+ include Test::Unit::TestCasePendingSupport
11
+
12
+ def setup
13
+ @hash = {
14
+ 'a' => 2,
15
+ 'b' => 3.141,
16
+ 'c' => 'c',
17
+ 'd' => [ 1, "b", 3.14 ],
18
+ 'e' => { 'foo' => 'bar' },
19
+ 'g' => "\"\0\037",
20
+ 'h' => 1000.0,
21
+ 'i' => 0.001
22
+ }
23
+ @json2 = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},' +
24
+ '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
25
+ @json3 = <<'EOT'.chomp
26
+ {
27
+ "a": 2,
28
+ "b": 3.141,
29
+ "c": "c",
30
+ "d": [
31
+ 1,
32
+ "b",
33
+ 3.14
34
+ ],
35
+ "e": {
36
+ "foo": "bar"
37
+ },
38
+ "g": "\"\u0000\u001f",
39
+ "h": 1000.0,
40
+ "i": 0.001
41
+ }
42
+ EOT
43
+ end
44
+
45
+ def test_generate
46
+ json = JSON.generate(@hash)
47
+ assert_equal(JSON.parse(@json2), JSON.parse(json))
48
+ json = JSON[@hash]
49
+ assert_equal(JSON.parse(@json2), JSON.parse(json))
50
+ parsed_json = JSON.parse(json)
51
+ assert_equal(@hash, parsed_json)
52
+ json = JSON.generate({1=>2})
53
+ assert_equal('{"1":2}', json)
54
+ parsed_json = JSON.parse(json)
55
+ assert_equal({"1"=>2}, parsed_json)
56
+ assert_equal '666', JSON.generate(666)
57
+ end
58
+
59
+ def test_generate_pretty
60
+ json = JSON.pretty_generate(@hash)
61
+ # hashes aren't (insertion) ordered on every ruby implementation
62
+ assert_equal(@json3, json)
63
+ assert_equal(JSON.parse(@json3), JSON.parse(json))
64
+ parsed_json = JSON.parse(json)
65
+ assert_equal(@hash, parsed_json)
66
+ json = JSON.pretty_generate({1=>2})
67
+ assert_equal(<<'EOT'.chomp, json)
68
+ {
69
+ "1": 2
70
+ }
71
+ EOT
72
+ parsed_json = JSON.parse(json)
73
+ assert_equal({"1"=>2}, parsed_json)
74
+ assert_equal '666', JSON.pretty_generate(666)
75
+ end
76
+
77
+ def test_generate_custom
78
+ state = JSON::State.new(:space_before => " ", :space => " ", :indent => "<i>", :object_nl => "\n", :array_nl => "<a_nl>")
79
+ json = JSON.generate({1=>{2=>3,4=>[5,6]}}, state)
80
+ assert_equal(<<'EOT'.chomp, json)
81
+ {
82
+ <i>"1" : {
83
+ <i><i>"2" : 3,
84
+ <i><i>"4" : [<a_nl><i><i><i>5,<a_nl><i><i><i>6<a_nl><i><i>]
85
+ <i>}
86
+ }
87
+ EOT
88
+ end
89
+
90
+ def test_fast_generate
91
+ json = JSON.fast_generate(@hash)
92
+ assert_equal(JSON.parse(@json2), JSON.parse(json))
93
+ parsed_json = JSON.parse(json)
94
+ assert_equal(@hash, parsed_json)
95
+ json = JSON.fast_generate({1=>2})
96
+ assert_equal('{"1":2}', json)
97
+ parsed_json = JSON.parse(json)
98
+ assert_equal({"1"=>2}, parsed_json)
99
+ assert_equal '666', JSON.fast_generate(666)
100
+ end
101
+
102
+ def test_own_state
103
+ state = JSON::State.new
104
+ json = JSON.generate(@hash, state)
105
+ assert_equal(JSON.parse(@json2), JSON.parse(json))
106
+ parsed_json = JSON.parse(json)
107
+ assert_equal(@hash, parsed_json)
108
+ json = JSON.generate({1=>2}, state)
109
+ assert_equal('{"1":2}', json)
110
+ parsed_json = JSON.parse(json)
111
+ assert_equal({"1"=>2}, parsed_json)
112
+ assert_equal '666', JSON.generate(666, state)
113
+ end
114
+
115
+ # TBD Implement JSON.state to return state class.
116
+ # set state attibutes from defaults
117
+ # implement methods
118
+ # circular should use circular in defaults or maybe always set to true, allow changes with [:check_circular]=
119
+ def test_states
120
+ json = JSON.generate({1=>2}, nil)
121
+ assert_equal('{"1":2}', json)
122
+ s = JSON.state.new
123
+ assert s.check_circular?
124
+ assert s[:check_circular?]
125
+ h = { 1=>2 }
126
+ h[3] = h
127
+ assert_raise(JSON::NestingError) { JSON.generate(h) }
128
+ assert_raise(JSON::NestingError) { JSON.generate(h, s) }
129
+ s = JSON.state.new
130
+ a = [ 1, 2 ]
131
+ a << a
132
+ assert_raise(JSON::NestingError) { JSON.generate(a, s) }
133
+ assert s.check_circular?
134
+ assert s[:check_circular?]
135
+ end
136
+
137
+ def test_pretty_state
138
+ state = JSON::PRETTY_STATE_PROTOTYPE.dup
139
+ assert_equal({
140
+ :allow_nan => false,
141
+ :array_nl => "\n",
142
+ :ascii_only => false,
143
+ :buffer_initial_length => 1024,
144
+ :depth => 0,
145
+ :indent => " ",
146
+ :max_nesting => 100,
147
+ :object_nl => "\n",
148
+ :space => " ",
149
+ :space_before => "",
150
+ }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
151
+ end
152
+
153
+ def test_safe_state
154
+ state = JSON::SAFE_STATE_PROTOTYPE.dup
155
+ assert_equal({
156
+ :allow_nan => false,
157
+ :array_nl => "",
158
+ :ascii_only => false,
159
+ :buffer_initial_length => 1024,
160
+ :depth => 0,
161
+ :indent => "",
162
+ :max_nesting => 100,
163
+ :object_nl => "",
164
+ :space => "",
165
+ :space_before => "",
166
+ }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
167
+ end
168
+
169
+ def test_fast_state
170
+ state = JSON::FAST_STATE_PROTOTYPE.dup
171
+ assert_equal({
172
+ :allow_nan => false,
173
+ :array_nl => "",
174
+ :ascii_only => false,
175
+ :buffer_initial_length => 1024,
176
+ :depth => 0,
177
+ :indent => "",
178
+ :max_nesting => 0,
179
+ :object_nl => "",
180
+ :space => "",
181
+ :space_before => "",
182
+ }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
183
+ end
184
+
185
+ def test_allow_nan
186
+ assert_raise(JSON::GeneratorError) { JSON.generate([JSON::NaN]) }
187
+ assert_equal '[NaN]', JSON.generate([JSON::NaN], :allow_nan => true)
188
+ assert_raise(JSON::GeneratorError) { JSON.fast_generate([JSON::NaN]) }
189
+ assert_raise(JSON::GeneratorError) { JSON.pretty_generate([JSON::NaN]) }
190
+ assert_equal "[\n NaN\n]", JSON.pretty_generate([JSON::NaN], :allow_nan => true)
191
+ assert_raise(JSON::GeneratorError) { JSON.generate([JSON::Infinity]) }
192
+ assert_equal '[Infinity]', JSON.generate([JSON::Infinity], :allow_nan => true)
193
+ assert_raise(JSON::GeneratorError) { JSON.fast_generate([JSON::Infinity]) }
194
+ assert_raise(JSON::GeneratorError) { JSON.pretty_generate([JSON::Infinity]) }
195
+ assert_equal "[\n Infinity\n]", JSON.pretty_generate([JSON::Infinity], :allow_nan => true)
196
+ assert_raise(JSON::GeneratorError) { JSON.generate([JSON::MinusInfinity]) }
197
+ assert_equal '[-Infinity]', JSON.generate([JSON::MinusInfinity], :allow_nan => true)
198
+ assert_raise(JSON::GeneratorError) { JSON.fast_generate([JSON::MinusInfinity]) }
199
+ assert_raise(JSON::GeneratorError) { JSON.pretty_generate([JSON::MinusInfinity]) }
200
+ assert_equal "[\n -Infinity\n]", JSON.pretty_generate([JSON::MinusInfinity], :allow_nan => true)
201
+ end
202
+
203
+ def test_depth
204
+ ary = []; ary << ary
205
+ assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
206
+ assert_raise(JSON::NestingError) { JSON.generate(ary) }
207
+ assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
208
+ assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
209
+ assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) }
210
+ assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
211
+ s = JSON.state.new
212
+ assert_equal 0, s.depth
213
+ assert_raise(JSON::NestingError) { ary.to_json(s) }
214
+ assert_equal 100, s.depth
215
+ end
216
+
217
+ def test_buffer_initial_length
218
+ s = JSON.state.new
219
+ assert_equal 1024, s.buffer_initial_length
220
+ s.buffer_initial_length = 0
221
+ assert_equal 1024, s.buffer_initial_length
222
+ s.buffer_initial_length = -1
223
+ assert_equal 1024, s.buffer_initial_length
224
+ s.buffer_initial_length = 128
225
+ assert_equal 128, s.buffer_initial_length
226
+ end
227
+
228
+ def test_gc
229
+ if respond_to?(:assert_in_out_err)
230
+ assert_in_out_err(%w[-rjson --disable-gems], <<-EOS, [], [])
231
+ bignum_too_long_to_embed_as_string = 1234567890123456789012345
232
+ expect = bignum_too_long_to_embed_as_string.to_s
233
+ GC.stress = true
234
+
235
+ 10.times do |i|
236
+ tmp = bignum_too_long_to_embed_as_string.to_json
237
+ raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect
238
+ end
239
+ EOS
240
+ end
241
+ end if GC.respond_to?(:stress=)
242
+
243
+ def test_configure_using_configure_and_merge
244
+ numbered_state = {
245
+ :indent => "1",
246
+ :space => '2',
247
+ :space_before => '3',
248
+ :object_nl => '4',
249
+ :array_nl => '5'
250
+ }
251
+ state1 = JSON.state.new
252
+ state1.merge(numbered_state)
253
+ assert_equal '1', state1.indent
254
+ assert_equal '2', state1.space
255
+ assert_equal '3', state1.space_before
256
+ assert_equal '4', state1.object_nl
257
+ assert_equal '5', state1.array_nl
258
+ state2 = JSON.state.new
259
+ state2.configure(numbered_state)
260
+ assert_equal '1', state2.indent
261
+ assert_equal '2', state2.space
262
+ assert_equal '3', state2.space_before
263
+ assert_equal '4', state2.object_nl
264
+ assert_equal '5', state2.array_nl
265
+ end
266
+
267
+ def test_configure_hash_conversion
268
+ state = JSON.state.new
269
+ state.configure(:indent => '1')
270
+ assert_equal '1', state.indent
271
+ state = JSON.state.new
272
+ foo = 'foo'
273
+ assert_raise(TypeError) do
274
+ state.configure(foo)
275
+ end
276
+ def foo.to_h
277
+ { :indent => '2' }
278
+ end
279
+ state.configure(foo)
280
+ assert_equal '2', state.indent
281
+ end
282
+
283
+ if defined?(JSON::Ext::Generator)
284
+ def test_broken_bignum # [ruby-core:38867]
285
+ pid = fork do
286
+ x = 1 << 64
287
+ x.class.class_eval do
288
+ def to_s
289
+ end
290
+ end
291
+ begin
292
+ j = JSON::Ext::Generator::State.new.generate(x)
293
+ exit 1
294
+ rescue TypeError
295
+ exit 0
296
+ end
297
+ end
298
+ _, status = Process.waitpid2(pid)
299
+ assert status.success?
300
+ rescue NotImplementedError
301
+ # forking to avoid modifying core class of a parent process and
302
+ # introducing race conditions of tests are run in parallel
303
+ end
304
+ end
305
+
306
+ def test_hash_likeness_set_symbol
307
+ state = JSON.state.new
308
+ assert_equal nil, state[:foo]
309
+ assert_equal nil.class, state[:foo].class
310
+ assert_equal nil, state['foo']
311
+ state[:foo] = :bar
312
+ assert_equal :bar, state[:foo]
313
+ assert_equal :bar, state['foo']
314
+ state_hash = state.to_hash
315
+ assert_kind_of Hash, state_hash
316
+ assert_equal :bar, state_hash[:foo]
317
+ end
318
+
319
+ def test_hash_likeness_set_string
320
+ state = JSON.state.new
321
+ assert_equal nil, state[:foo]
322
+ assert_equal nil, state['foo']
323
+ state['foo'] = :bar
324
+ assert_equal :bar, state[:foo]
325
+ assert_equal :bar, state['foo']
326
+ state_hash = state.to_hash
327
+ assert_kind_of Hash, state_hash
328
+ assert_equal :bar, state_hash[:foo]
329
+ end
330
+
331
+ def test_json_generate
332
+ assert_raise JSON::GeneratorError do
333
+ assert_equal true, JSON.generate(["\xea"])
334
+ end
335
+ end
336
+
337
+ def test_nesting
338
+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
339
+ too_deep_ary = eval too_deep
340
+ assert_raise(JSON::NestingError) { JSON.generate too_deep_ary }
341
+ assert_raise(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 100 }
342
+ ok = JSON.generate too_deep_ary, :max_nesting => 101
343
+ assert_equal too_deep, ok
344
+ ok = JSON.generate too_deep_ary, :max_nesting => nil
345
+ assert_equal too_deep, ok
346
+ ok = JSON.generate too_deep_ary, :max_nesting => false
347
+ assert_equal too_deep, ok
348
+ ok = JSON.generate too_deep_ary, :max_nesting => 0
349
+ assert_equal too_deep, ok
350
+ end
351
+
352
+ def test_backslash
353
+ data = [ '\\.(?i:gif|jpe?g|png)$' ]
354
+ json = '["\\\\.(?i:gif|jpe?g|png)$"]'
355
+ assert_equal json, JSON.generate(data)
356
+ #
357
+ data = [ '\\"' ]
358
+ json = '["\\\\\""]'
359
+ assert_equal json, JSON.generate(data)
360
+ #
361
+ data = [ '/' ]
362
+ json = '["/"]'
363
+ assert_equal json, JSON.generate(data)
364
+ #
365
+ data = ['"']
366
+ json = '["\""]'
367
+ assert_equal json, JSON.generate(data)
368
+ #
369
+ data = ["'"]
370
+ json = '["\\\'"]'
371
+ assert_equal '["\'"]', JSON.generate(data)
372
+ end
373
+
374
+ def test_string_subclass
375
+ s = Class.new(String) do
376
+ def to_s; self; end
377
+ undef to_json
378
+ end
379
+ assert_nothing_raised(SystemStackError) do
380
+ assert_equal '["foo"]', JSON.generate([s.new('foo')])
381
+ end
382
+ end
383
+ end