oj 2.18.5 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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