json 2.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of json might be problematic. Click here for more details.

Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +23 -0
  4. data/CHANGES.md +391 -0
  5. data/Gemfile +14 -0
  6. data/README-json-jruby.md +33 -0
  7. data/README.md +409 -0
  8. data/Rakefile +408 -0
  9. data/VERSION +1 -0
  10. data/diagrams/.keep +0 -0
  11. data/ext/json/ext/fbuffer/fbuffer.h +187 -0
  12. data/ext/json/ext/generator/depend +1 -0
  13. data/ext/json/ext/generator/extconf.rb +4 -0
  14. data/ext/json/ext/generator/generator.c +1444 -0
  15. data/ext/json/ext/generator/generator.h +171 -0
  16. data/ext/json/ext/parser/depend +1 -0
  17. data/ext/json/ext/parser/extconf.rb +6 -0
  18. data/ext/json/ext/parser/parser.c +2131 -0
  19. data/ext/json/ext/parser/parser.h +91 -0
  20. data/ext/json/ext/parser/parser.rl +891 -0
  21. data/ext/json/extconf.rb +2 -0
  22. data/install.rb +23 -0
  23. data/java/src/json/ext/ByteListTranscoder.java +166 -0
  24. data/java/src/json/ext/Generator.java +443 -0
  25. data/java/src/json/ext/GeneratorMethods.java +231 -0
  26. data/java/src/json/ext/GeneratorService.java +42 -0
  27. data/java/src/json/ext/GeneratorState.java +490 -0
  28. data/java/src/json/ext/OptionsReader.java +113 -0
  29. data/java/src/json/ext/Parser.java +2362 -0
  30. data/java/src/json/ext/Parser.rl +893 -0
  31. data/java/src/json/ext/ParserService.java +34 -0
  32. data/java/src/json/ext/RuntimeInfo.java +116 -0
  33. data/java/src/json/ext/StringDecoder.java +166 -0
  34. data/java/src/json/ext/StringEncoder.java +111 -0
  35. data/java/src/json/ext/Utils.java +88 -0
  36. data/json-java.gemspec +38 -0
  37. data/json.gemspec +0 -0
  38. data/json_pure.gemspec +38 -0
  39. data/lib/json.rb +63 -0
  40. data/lib/json/add/bigdecimal.rb +29 -0
  41. data/lib/json/add/complex.rb +29 -0
  42. data/lib/json/add/core.rb +12 -0
  43. data/lib/json/add/date.rb +34 -0
  44. data/lib/json/add/date_time.rb +50 -0
  45. data/lib/json/add/exception.rb +31 -0
  46. data/lib/json/add/ostruct.rb +31 -0
  47. data/lib/json/add/range.rb +29 -0
  48. data/lib/json/add/rational.rb +28 -0
  49. data/lib/json/add/regexp.rb +30 -0
  50. data/lib/json/add/set.rb +29 -0
  51. data/lib/json/add/struct.rb +30 -0
  52. data/lib/json/add/symbol.rb +25 -0
  53. data/lib/json/add/time.rb +38 -0
  54. data/lib/json/common.rb +456 -0
  55. data/lib/json/ext.rb +15 -0
  56. data/lib/json/ext/.keep +0 -0
  57. data/lib/json/generic_object.rb +71 -0
  58. data/lib/json/pure.rb +15 -0
  59. data/lib/json/pure/generator.rb +458 -0
  60. data/lib/json/pure/parser.rb +311 -0
  61. data/lib/json/version.rb +9 -0
  62. data/references/rfc7159.txt +899 -0
  63. data/tests/fixtures/fail10.json +1 -0
  64. data/tests/fixtures/fail11.json +1 -0
  65. data/tests/fixtures/fail12.json +1 -0
  66. data/tests/fixtures/fail13.json +1 -0
  67. data/tests/fixtures/fail14.json +1 -0
  68. data/tests/fixtures/fail18.json +1 -0
  69. data/tests/fixtures/fail19.json +1 -0
  70. data/tests/fixtures/fail2.json +1 -0
  71. data/tests/fixtures/fail20.json +1 -0
  72. data/tests/fixtures/fail21.json +1 -0
  73. data/tests/fixtures/fail22.json +1 -0
  74. data/tests/fixtures/fail23.json +1 -0
  75. data/tests/fixtures/fail24.json +1 -0
  76. data/tests/fixtures/fail25.json +1 -0
  77. data/tests/fixtures/fail27.json +2 -0
  78. data/tests/fixtures/fail28.json +2 -0
  79. data/tests/fixtures/fail3.json +1 -0
  80. data/tests/fixtures/fail4.json +1 -0
  81. data/tests/fixtures/fail5.json +1 -0
  82. data/tests/fixtures/fail6.json +1 -0
  83. data/tests/fixtures/fail7.json +1 -0
  84. data/tests/fixtures/fail8.json +1 -0
  85. data/tests/fixtures/fail9.json +1 -0
  86. data/tests/fixtures/obsolete_fail1.json +1 -0
  87. data/tests/fixtures/pass1.json +56 -0
  88. data/tests/fixtures/pass15.json +1 -0
  89. data/tests/fixtures/pass16.json +1 -0
  90. data/tests/fixtures/pass17.json +1 -0
  91. data/tests/fixtures/pass2.json +1 -0
  92. data/tests/fixtures/pass26.json +1 -0
  93. data/tests/fixtures/pass3.json +6 -0
  94. data/tests/json_addition_test.rb +203 -0
  95. data/tests/json_common_interface_test.rb +126 -0
  96. data/tests/json_encoding_test.rb +107 -0
  97. data/tests/json_ext_parser_test.rb +15 -0
  98. data/tests/json_fixtures_test.rb +32 -0
  99. data/tests/json_generator_test.rb +377 -0
  100. data/tests/json_generic_object_test.rb +82 -0
  101. data/tests/json_parser_test.rb +472 -0
  102. data/tests/json_string_matching_test.rb +38 -0
  103. data/tests/test_helper.rb +17 -0
  104. data/tools/diff.sh +18 -0
  105. data/tools/fuzz.rb +131 -0
  106. data/tools/server.rb +62 -0
  107. metadata +185 -0
@@ -0,0 +1,107 @@
1
+ # encoding: utf-8
2
+ #frozen_string_literal: false
3
+ require 'test_helper'
4
+
5
+ class JSONEncodingTest < Test::Unit::TestCase
6
+ include JSON
7
+
8
+ def setup
9
+ @utf_8 = '"© ≠ €!"'
10
+ @ascii_8bit = @utf_8.dup.force_encoding('ascii-8bit')
11
+ @parsed = "© ≠ €!"
12
+ @generated = '"\u00a9 \u2260 \u20ac!"'
13
+ if String.method_defined?(:encode)
14
+ @utf_16_data = @parsed.encode('utf-16be', 'utf-8')
15
+ @utf_16be = @utf_8.encode('utf-16be', 'utf-8')
16
+ @utf_16le = @utf_8.encode('utf-16le', 'utf-8')
17
+ @utf_32be = @utf_8.encode('utf-32be', 'utf-8')
18
+ @utf_32le = @utf_8.encode('utf-32le', 'utf-8')
19
+ else
20
+ require 'iconv'
21
+ @utf_16_data, = Iconv.iconv('utf-16be', 'utf-8', @parsed)
22
+ @utf_16be, = Iconv.iconv('utf-16be', 'utf-8', @utf_8)
23
+ @utf_16le, = Iconv.iconv('utf-16le', 'utf-8', @utf_8)
24
+ @utf_32be, = Iconv.iconv('utf-32be', 'utf-8', @utf_8)
25
+ @utf_32le, = Iconv.iconv('utf-32le', 'utf-8', @utf_8)
26
+ end
27
+ end
28
+
29
+ def test_parse
30
+ assert_equal @parsed, JSON.parse(@ascii_8bit)
31
+ assert_equal @parsed, JSON.parse(@utf_8)
32
+ assert_equal @parsed, JSON.parse(@utf_16be)
33
+ assert_equal @parsed, JSON.parse(@utf_16le)
34
+ assert_equal @parsed, JSON.parse(@utf_32be)
35
+ assert_equal @parsed, JSON.parse(@utf_32le)
36
+ end
37
+
38
+ def test_generate
39
+ assert_equal @generated, JSON.generate(@parsed, :ascii_only => true)
40
+ assert_equal @generated, JSON.generate(@utf_16_data, :ascii_only => true)
41
+ end
42
+
43
+ def test_unicode
44
+ assert_equal '""', ''.to_json
45
+ assert_equal '"\\b"', "\b".to_json
46
+ assert_equal '"\u0001"', 0x1.chr.to_json
47
+ assert_equal '"\u001f"', 0x1f.chr.to_json
48
+ assert_equal '" "', ' '.to_json
49
+ assert_equal "\"#{0x7f.chr}\"", 0x7f.chr.to_json
50
+ utf8 = [ "© ≠ €! \01" ]
51
+ json = '["© ≠ €! \u0001"]'
52
+ assert_equal json, utf8.to_json(:ascii_only => false)
53
+ assert_equal utf8, parse(json)
54
+ json = '["\u00a9 \u2260 \u20ac! \u0001"]'
55
+ assert_equal json, utf8.to_json(:ascii_only => true)
56
+ assert_equal utf8, parse(json)
57
+ utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
58
+ json = "[\"\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212\"]"
59
+ assert_equal utf8, parse(json)
60
+ assert_equal json, utf8.to_json(:ascii_only => false)
61
+ utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
62
+ assert_equal utf8, parse(json)
63
+ json = "[\"\\u3042\\u3044\\u3046\\u3048\\u304a\"]"
64
+ assert_equal json, utf8.to_json(:ascii_only => true)
65
+ assert_equal utf8, parse(json)
66
+ utf8 = ['საქართველო']
67
+ json = '["საქართველო"]'
68
+ assert_equal json, utf8.to_json(:ascii_only => false)
69
+ json = "[\"\\u10e1\\u10d0\\u10e5\\u10d0\\u10e0\\u10d7\\u10d5\\u10d4\\u10da\\u10dd\"]"
70
+ assert_equal json, utf8.to_json(:ascii_only => true)
71
+ assert_equal utf8, parse(json)
72
+ assert_equal '["Ã"]', generate(["Ã"], :ascii_only => false)
73
+ assert_equal '["\\u00c3"]', generate(["Ã"], :ascii_only => true)
74
+ assert_equal ["€"], parse('["\u20ac"]')
75
+ utf8 = ["\xf0\xa0\x80\x81"]
76
+ json = "[\"\xf0\xa0\x80\x81\"]"
77
+ assert_equal json, generate(utf8, :ascii_only => false)
78
+ assert_equal utf8, parse(json)
79
+ json = '["\ud840\udc01"]'
80
+ assert_equal json, generate(utf8, :ascii_only => true)
81
+ assert_equal utf8, parse(json)
82
+ assert_raise(JSON::ParserError) { parse('"\u"') }
83
+ assert_raise(JSON::ParserError) { parse('"\ud800"') }
84
+ end
85
+
86
+ def test_chars
87
+ (0..0x7f).each do |i|
88
+ json = '["\u%04x"]' % i
89
+ if RUBY_VERSION >= "1.9."
90
+ i = i.chr
91
+ end
92
+ assert_equal i, parse(json).first[0]
93
+ if i == ?\b
94
+ generated = generate(["" << i])
95
+ assert '["\b"]' == generated || '["\10"]' == generated
96
+ elsif [?\n, ?\r, ?\t, ?\f].include?(i)
97
+ assert_equal '[' << ('' << i).dump << ']', generate(["" << i])
98
+ elsif i.chr < 0x20.chr
99
+ assert_equal json, generate(["" << i])
100
+ end
101
+ end
102
+ assert_raise(JSON::GeneratorError) do
103
+ generate(["\x80"], :ascii_only => true)
104
+ end
105
+ assert_equal "\302\200", parse('["\u0080"]').first
106
+ end
107
+ end
@@ -0,0 +1,15 @@
1
+ #frozen_string_literal: false
2
+ require 'test_helper'
3
+
4
+ class JSONExtParserTest < Test::Unit::TestCase
5
+ if defined?(JSON::Ext::Parser)
6
+ def test_allocate
7
+ parser = JSON::Ext::Parser.new("{}")
8
+ assert_raise(TypeError, '[ruby-core:35079]') do
9
+ parser.__send__(:initialize, "{}")
10
+ end
11
+ parser = JSON::Ext::Parser.allocate
12
+ assert_raise(TypeError, '[ruby-core:35079]') { parser.source }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,32 @@
1
+ #frozen_string_literal: false
2
+ require 'test_helper'
3
+
4
+ class JSONFixturesTest < Test::Unit::TestCase
5
+ def setup
6
+ fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}.json')
7
+ passed, failed = Dir[fixtures].partition { |f| f['pass'] }
8
+ @passed = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
9
+ @failed = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
10
+ end
11
+
12
+ def test_passing
13
+ for name, source in @passed
14
+ begin
15
+ assert JSON.parse(source),
16
+ "Did not pass for fixture '#{name}': #{source.inspect}"
17
+ rescue => e
18
+ warn "\nCaught #{e.class}(#{e}) for fixture '#{name}': #{source.inspect}\n#{e.backtrace * "\n"}"
19
+ raise e
20
+ end
21
+ end
22
+ end
23
+
24
+ def test_failing
25
+ for name, source in @failed
26
+ assert_raise(JSON::ParserError, JSON::NestingError,
27
+ "Did not fail for fixture '#{name}': #{source.inspect}") do
28
+ JSON.parse(source)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,377 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+ # frozen_string_literal: false
4
+
5
+ require 'test_helper'
6
+
7
+ class JSONGeneratorTest < Test::Unit::TestCase
8
+ include JSON
9
+
10
+ def setup
11
+ @hash = {
12
+ 'a' => 2,
13
+ 'b' => 3.141,
14
+ 'c' => 'c',
15
+ 'd' => [ 1, "b", 3.14 ],
16
+ 'e' => { 'foo' => 'bar' },
17
+ 'g' => "\"\0\037",
18
+ 'h' => 1000.0,
19
+ 'i' => 0.001
20
+ }
21
+ @json2 = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},' +
22
+ '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
23
+ @json3 = <<'EOT'.chomp
24
+ {
25
+ "a": 2,
26
+ "b": 3.141,
27
+ "c": "c",
28
+ "d": [
29
+ 1,
30
+ "b",
31
+ 3.14
32
+ ],
33
+ "e": {
34
+ "foo": "bar"
35
+ },
36
+ "g": "\"\u0000\u001f",
37
+ "h": 1000.0,
38
+ "i": 0.001
39
+ }
40
+ EOT
41
+ end
42
+
43
+ def test_generate
44
+ json = generate(@hash)
45
+ assert_equal(parse(@json2), parse(json))
46
+ json = JSON[@hash]
47
+ assert_equal(parse(@json2), parse(json))
48
+ parsed_json = parse(json)
49
+ assert_equal(@hash, parsed_json)
50
+ json = generate({1=>2})
51
+ assert_equal('{"1":2}', json)
52
+ parsed_json = parse(json)
53
+ assert_equal({"1"=>2}, parsed_json)
54
+ assert_equal '666', generate(666)
55
+ end
56
+
57
+ def test_generate_pretty
58
+ json = pretty_generate(@hash)
59
+ # hashes aren't (insertion) ordered on every ruby implementation
60
+ # assert_equal(@json3, json)
61
+ assert_equal(parse(@json3), parse(json))
62
+ parsed_json = parse(json)
63
+ assert_equal(@hash, parsed_json)
64
+ json = pretty_generate({1=>2})
65
+ assert_equal(<<'EOT'.chomp, json)
66
+ {
67
+ "1": 2
68
+ }
69
+ EOT
70
+ parsed_json = parse(json)
71
+ assert_equal({"1"=>2}, parsed_json)
72
+ assert_equal '666', pretty_generate(666)
73
+ end
74
+
75
+ def test_generate_custom
76
+ state = State.new(:space_before => " ", :space => " ", :indent => "<i>", :object_nl => "\n", :array_nl => "<a_nl>")
77
+ json = generate({1=>{2=>3,4=>[5,6]}}, state)
78
+ assert_equal(<<'EOT'.chomp, json)
79
+ {
80
+ <i>"1" : {
81
+ <i><i>"2" : 3,
82
+ <i><i>"4" : [<a_nl><i><i><i>5,<a_nl><i><i><i>6<a_nl><i><i>]
83
+ <i>}
84
+ }
85
+ EOT
86
+ end
87
+
88
+ def test_fast_generate
89
+ json = fast_generate(@hash)
90
+ assert_equal(parse(@json2), parse(json))
91
+ parsed_json = parse(json)
92
+ assert_equal(@hash, parsed_json)
93
+ json = fast_generate({1=>2})
94
+ assert_equal('{"1":2}', json)
95
+ parsed_json = parse(json)
96
+ assert_equal({"1"=>2}, parsed_json)
97
+ assert_equal '666', fast_generate(666)
98
+ end
99
+
100
+ def test_own_state
101
+ state = State.new
102
+ json = generate(@hash, state)
103
+ assert_equal(parse(@json2), parse(json))
104
+ parsed_json = parse(json)
105
+ assert_equal(@hash, parsed_json)
106
+ json = generate({1=>2}, state)
107
+ assert_equal('{"1":2}', json)
108
+ parsed_json = parse(json)
109
+ assert_equal({"1"=>2}, parsed_json)
110
+ assert_equal '666', generate(666, state)
111
+ end
112
+
113
+ def test_states
114
+ json = generate({1=>2}, nil)
115
+ assert_equal('{"1":2}', json)
116
+ s = JSON.state.new
117
+ assert s.check_circular?
118
+ assert s[:check_circular?]
119
+ h = { 1=>2 }
120
+ h[3] = h
121
+ assert_raise(JSON::NestingError) { generate(h) }
122
+ assert_raise(JSON::NestingError) { generate(h, s) }
123
+ s = JSON.state.new
124
+ a = [ 1, 2 ]
125
+ a << a
126
+ assert_raise(JSON::NestingError) { generate(a, s) }
127
+ assert s.check_circular?
128
+ assert s[:check_circular?]
129
+ end
130
+
131
+ def test_pretty_state
132
+ state = PRETTY_STATE_PROTOTYPE.dup
133
+ assert_equal({
134
+ :allow_nan => false,
135
+ :array_nl => "\n",
136
+ :ascii_only => false,
137
+ :buffer_initial_length => 1024,
138
+ :depth => 0,
139
+ :indent => " ",
140
+ :max_nesting => 100,
141
+ :object_nl => "\n",
142
+ :space => " ",
143
+ :space_before => "",
144
+ }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
145
+ end
146
+
147
+ def test_safe_state
148
+ state = SAFE_STATE_PROTOTYPE.dup
149
+ assert_equal({
150
+ :allow_nan => false,
151
+ :array_nl => "",
152
+ :ascii_only => false,
153
+ :buffer_initial_length => 1024,
154
+ :depth => 0,
155
+ :indent => "",
156
+ :max_nesting => 100,
157
+ :object_nl => "",
158
+ :space => "",
159
+ :space_before => "",
160
+ }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
161
+ end
162
+
163
+ def test_fast_state
164
+ state = FAST_STATE_PROTOTYPE.dup
165
+ assert_equal({
166
+ :allow_nan => false,
167
+ :array_nl => "",
168
+ :ascii_only => false,
169
+ :buffer_initial_length => 1024,
170
+ :depth => 0,
171
+ :indent => "",
172
+ :max_nesting => 0,
173
+ :object_nl => "",
174
+ :space => "",
175
+ :space_before => "",
176
+ }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s })
177
+ end
178
+
179
+ def test_allow_nan
180
+ assert_raise(GeneratorError) { generate([JSON::NaN]) }
181
+ assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
182
+ assert_raise(GeneratorError) { fast_generate([JSON::NaN]) }
183
+ assert_raise(GeneratorError) { pretty_generate([JSON::NaN]) }
184
+ assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
185
+ assert_raise(GeneratorError) { generate([JSON::Infinity]) }
186
+ assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
187
+ assert_raise(GeneratorError) { fast_generate([JSON::Infinity]) }
188
+ assert_raise(GeneratorError) { pretty_generate([JSON::Infinity]) }
189
+ assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
190
+ assert_raise(GeneratorError) { generate([JSON::MinusInfinity]) }
191
+ assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
192
+ assert_raise(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
193
+ assert_raise(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
194
+ assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
195
+ end
196
+
197
+ def test_depth
198
+ ary = []; ary << ary
199
+ assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
200
+ assert_raise(JSON::NestingError) { generate(ary) }
201
+ assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
202
+ assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
203
+ assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) }
204
+ assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
205
+ s = JSON.state.new
206
+ assert_equal 0, s.depth
207
+ assert_raise(JSON::NestingError) { ary.to_json(s) }
208
+ assert_equal 100, s.depth
209
+ end
210
+
211
+ def test_buffer_initial_length
212
+ s = JSON.state.new
213
+ assert_equal 1024, s.buffer_initial_length
214
+ s.buffer_initial_length = 0
215
+ assert_equal 1024, s.buffer_initial_length
216
+ s.buffer_initial_length = -1
217
+ assert_equal 1024, s.buffer_initial_length
218
+ s.buffer_initial_length = 128
219
+ assert_equal 128, s.buffer_initial_length
220
+ end
221
+
222
+ def test_gc
223
+ if respond_to?(:assert_in_out_err)
224
+ assert_in_out_err(%w[-rjson --disable-gems], <<-EOS, [], [])
225
+ bignum_too_long_to_embed_as_string = 1234567890123456789012345
226
+ expect = bignum_too_long_to_embed_as_string.to_s
227
+ GC.stress = true
228
+
229
+ 10.times do |i|
230
+ tmp = bignum_too_long_to_embed_as_string.to_json
231
+ raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect
232
+ end
233
+ EOS
234
+ end
235
+ end if GC.respond_to?(:stress=)
236
+
237
+ def test_configure_using_configure_and_merge
238
+ numbered_state = {
239
+ :indent => "1",
240
+ :space => '2',
241
+ :space_before => '3',
242
+ :object_nl => '4',
243
+ :array_nl => '5'
244
+ }
245
+ state1 = JSON.state.new
246
+ state1.merge(numbered_state)
247
+ assert_equal '1', state1.indent
248
+ assert_equal '2', state1.space
249
+ assert_equal '3', state1.space_before
250
+ assert_equal '4', state1.object_nl
251
+ assert_equal '5', state1.array_nl
252
+ state2 = JSON.state.new
253
+ state2.configure(numbered_state)
254
+ assert_equal '1', state2.indent
255
+ assert_equal '2', state2.space
256
+ assert_equal '3', state2.space_before
257
+ assert_equal '4', state2.object_nl
258
+ assert_equal '5', state2.array_nl
259
+ end
260
+
261
+ def test_configure_hash_conversion
262
+ state = JSON.state.new
263
+ state.configure(:indent => '1')
264
+ assert_equal '1', state.indent
265
+ state = JSON.state.new
266
+ foo = 'foo'
267
+ assert_raise(TypeError) do
268
+ state.configure(foo)
269
+ end
270
+ def foo.to_h
271
+ { :indent => '2' }
272
+ end
273
+ state.configure(foo)
274
+ assert_equal '2', state.indent
275
+ end
276
+
277
+ if defined?(JSON::Ext::Generator)
278
+ def test_broken_bignum # [ruby-core:38867]
279
+ pid = fork do
280
+ x = 1 << 64
281
+ x.class.class_eval do
282
+ def to_s
283
+ end
284
+ end
285
+ begin
286
+ JSON::Ext::Generator::State.new.generate(x)
287
+ exit 1
288
+ rescue TypeError
289
+ exit 0
290
+ end
291
+ end
292
+ _, status = Process.waitpid2(pid)
293
+ assert status.success?
294
+ rescue NotImplementedError
295
+ # forking to avoid modifying core class of a parent process and
296
+ # introducing race conditions of tests are run in parallel
297
+ end
298
+ end
299
+
300
+ def test_hash_likeness_set_symbol
301
+ state = JSON.state.new
302
+ assert_equal nil, state[:foo]
303
+ assert_equal nil.class, state[:foo].class
304
+ assert_equal nil, state['foo']
305
+ state[:foo] = :bar
306
+ assert_equal :bar, state[:foo]
307
+ assert_equal :bar, state['foo']
308
+ state_hash = state.to_hash
309
+ assert_kind_of Hash, state_hash
310
+ assert_equal :bar, state_hash[:foo]
311
+ end
312
+
313
+ def test_hash_likeness_set_string
314
+ state = JSON.state.new
315
+ assert_equal nil, state[:foo]
316
+ assert_equal nil, state['foo']
317
+ state['foo'] = :bar
318
+ assert_equal :bar, state[:foo]
319
+ assert_equal :bar, state['foo']
320
+ state_hash = state.to_hash
321
+ assert_kind_of Hash, state_hash
322
+ assert_equal :bar, state_hash[:foo]
323
+ end
324
+
325
+ def test_json_generate
326
+ assert_raise JSON::GeneratorError do
327
+ assert_equal true, generate(["\xea"])
328
+ end
329
+ end
330
+
331
+ def test_nesting
332
+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
333
+ too_deep_ary = eval too_deep
334
+ assert_raise(JSON::NestingError) { generate too_deep_ary }
335
+ assert_raise(JSON::NestingError) { generate too_deep_ary, :max_nesting => 100 }
336
+ ok = generate too_deep_ary, :max_nesting => 101
337
+ assert_equal too_deep, ok
338
+ ok = generate too_deep_ary, :max_nesting => nil
339
+ assert_equal too_deep, ok
340
+ ok = generate too_deep_ary, :max_nesting => false
341
+ assert_equal too_deep, ok
342
+ ok = generate too_deep_ary, :max_nesting => 0
343
+ assert_equal too_deep, ok
344
+ end
345
+
346
+ def test_backslash
347
+ data = [ '\\.(?i:gif|jpe?g|png)$' ]
348
+ json = '["\\\\.(?i:gif|jpe?g|png)$"]'
349
+ assert_equal json, generate(data)
350
+ #
351
+ data = [ '\\"' ]
352
+ json = '["\\\\\""]'
353
+ assert_equal json, generate(data)
354
+ #
355
+ data = [ '/' ]
356
+ json = '["/"]'
357
+ assert_equal json, generate(data)
358
+ #
359
+ data = ['"']
360
+ json = '["\""]'
361
+ assert_equal json, generate(data)
362
+ #
363
+ data = ["'"]
364
+ json = '["\\\'"]'
365
+ assert_equal '["\'"]', generate(data)
366
+ end
367
+
368
+ def test_string_subclass
369
+ s = Class.new(String) do
370
+ def to_s; self; end
371
+ undef to_json
372
+ end
373
+ assert_nothing_raised(SystemStackError) do
374
+ assert_equal '["foo"]', JSON.generate([s.new('foo')])
375
+ end
376
+ end
377
+ end