summaryrefslogtreecommitdiff
path: root/test/json/json_parser_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/json/json_parser_test.rb')
-rw-r--r--test/json/json_parser_test.rb135
1 files changed, 116 insertions, 19 deletions
diff --git a/test/json/json_parser_test.rb b/test/json/json_parser_test.rb
index 6455d2971a..292ca1a670 100644
--- a/test/json/json_parser_test.rb
+++ b/test/json/json_parser_test.rb
@@ -128,6 +128,18 @@ class JSONParserTest < Test::Unit::TestCase
assert_equal(1.0/0, parse('Infinity', :allow_nan => true))
assert_raise(ParserError) { parse('-Infinity') }
assert_equal(-1.0/0, parse('-Infinity', :allow_nan => true))
+ capture_output { assert_equal(Float::INFINITY, parse("23456789012E666")) }
+ end
+
+ def test_parse_bignum
+ bignum = Integer('1234567890' * 10)
+ assert_equal(bignum, JSON.parse(bignum.to_s))
+ assert_equal(bignum.to_f, JSON.parse(bignum.to_s + ".0"))
+
+ bignum = Integer('1234567890' * 50)
+ assert_equal(bignum, JSON.parse(bignum.to_s))
+ bignum_float = EnvUtil.suppress_warning { bignum.to_f }
+ assert_equal(bignum_float, EnvUtil.suppress_warning { JSON.parse(bignum.to_s + ".0") })
end
def test_parse_bigdecimals
@@ -157,6 +169,37 @@ class JSONParserTest < Test::Unit::TestCase
end
end
+ def test_parse_control_chars_in_string
+ 0.upto(31) do |ord|
+ assert_raise JSON::ParserError do
+ parse(%("#{ord.chr}"))
+ end
+ end
+ end
+
+ def test_parse_allowed_control_chars_in_string
+ 0.upto(31) do |ord|
+ assert_equal ord.chr, parse(%("#{ord.chr}"), allow_control_characters: true)
+ end
+ end
+
+ def test_parse_control_char_and_backslash
+ backslash_and_control_char = "\\\t"
+ assert_raise JSON::ParserError do
+ JSON.parse(%("#{'a' * 30}#{backslash_and_control_char}"), allow_control_characters: true, allow_invalid_escape: false)
+ end
+
+ JSON.parse(%("#{'a' * 30}#{backslash_and_control_char}"), allow_control_characters: true, allow_invalid_escape: true)
+ end
+
+ def test_parse_invalid_escape
+ assert_raise JSON::ParserError do
+ parse(%("fo\\o"))
+ end
+
+ assert_equal "foo", parse(%("fo\\o"), allow_invalid_escape: true)
+ end
+
def test_parse_arrays
assert_equal([1,2,3], parse('[1,2,3]'))
assert_equal([1.2,2,3], parse('[1.2,2,3]'))
@@ -318,6 +361,20 @@ class JSONParserTest < Test::Unit::TestCase
assert_raise(JSON::ParserError) { parse('"\u111___"') }
end
+ def test_unicode_followed_by_newline
+ # Ref: https://github.com/ruby/json/issues/912
+ assert_equal "🌌\n".bytes, JSON.parse('"\ud83c\udf0c\n"').bytes
+ assert_equal "🌌\n", JSON.parse('"\ud83c\udf0c\n"')
+ assert_predicate JSON.parse('"\ud83c\udf0c\n"'), :valid_encoding?
+ end
+
+ def test_invalid_surogates
+ assert_raise(JSON::ParserError) { parse('"\\uD800"') }
+ assert_raise(JSON::ParserError) { parse('"\\uD800_________________"') }
+ assert_raise(JSON::ParserError) { parse('"\\uD800\\u0041"') }
+ assert_raise(JSON::ParserError) { parse('"\\uD800\\u004') }
+ end
+
def test_parse_big_integers
json1 = JSON(orig = (1 << 31) - 1)
assert_equal orig, parse(json1)
@@ -331,6 +388,18 @@ class JSONParserTest < Test::Unit::TestCase
assert_equal orig, parse(json5)
end
+ def test_parse_escaped_key
+ doc = {
+ "test\r1" => 1,
+ "entries" => [
+ "test\t2" => 2,
+ "test\n3" => 3,
+ ]
+ }
+
+ assert_equal doc, parse(JSON.generate(doc))
+ end
+
def test_parse_duplicate_key
expected = {"a" => 2}
expected_sym = {a: 2}
@@ -346,7 +415,7 @@ class JSONParserTest < Test::Unit::TestCase
assert_equal expected_sym, parse('{"a": 1, "a": 2}', symbolize_names: true)
end
- if RUBY_ENGINE == 'RUBY_ENGINE'
+ if RUBY_ENGINE == 'ruby'
assert_deprecated_warning(/#{File.basename(__FILE__)}\:#{__LINE__ + 1}/) do
assert_equal expected, parse('{"a": 1, "a": 2}')
end
@@ -365,6 +434,13 @@ class JSONParserTest < Test::Unit::TestCase
end
end
+ def test_parse_duplicate_key_escape
+ error = assert_raise(ParserError) do
+ JSON.parse('{"%s%s%s%s":1,"%s%s%s%s":2}', allow_duplicate_key: false)
+ end
+ assert_match "%s%s%s%s", error.message
+ end
+
def test_some_wrong_inputs
assert_raise(ParserError) { parse('[] bla') }
assert_raise(ParserError) { parse('[] 1') }
@@ -396,10 +472,8 @@ class JSONParserTest < Test::Unit::TestCase
assert_predicate parse('[]', :freeze => true), :frozen?
assert_predicate parse('"foo"', :freeze => true), :frozen?
- if string_deduplication_available?
- assert_same(-'foo', parse('"foo"', :freeze => true))
- assert_same(-'foo', parse('{"foo": 1}', :freeze => true).keys.first)
- end
+ assert_same(-'foo', parse('"foo"', :freeze => true))
+ assert_same(-'foo', parse('{"foo": 1}', :freeze => true).keys.first)
end
def test_parse_comments
@@ -471,24 +545,28 @@ class JSONParserTest < Test::Unit::TestCase
end
def test_backslash
+ assert_raise(JSON::ParserError) do
+ JSON.parse('"\\')
+ end
+
data = [ '\\.(?i:gif|jpe?g|png)$' ]
json = '["\\\\.(?i:gif|jpe?g|png)$"]'
assert_equal data, parse(json)
- #
+
data = [ '\\"' ]
json = '["\\\\\""]'
assert_equal data, parse(json)
- #
+
json = '["/"]'
data = [ '/' ]
assert_equal data, parse(json)
- #
+
json = '["\""]'
data = ['"']
assert_equal data, parse(json)
- #
- json = '["\\\'"]'
- data = ["'"]
+
+ json = '["\\/"]'
+ data = ["/"]
assert_equal data, parse(json)
json = '["\/"]'
@@ -636,6 +714,7 @@ class JSONParserTest < Test::Unit::TestCase
def test_parse_array_custom_non_array_derived_class
res = parse('[1,2]', :array_class => SubArrayWrapper)
assert_equal([1,2], res.data)
+ assert_equal(1, res[0])
assert_equal(SubArrayWrapper, res.class)
assert res.shifted?
end
@@ -697,6 +776,7 @@ class JSONParserTest < Test::Unit::TestCase
def test_parse_object_custom_non_hash_derived_class
res = parse('{"foo":"bar"}', :object_class => SubOpenStruct)
assert_equal "bar", res.foo
+ assert_equal "bar", res[:foo]
assert_equal(SubOpenStruct, res.class)
assert res.item_set?
end
@@ -791,18 +871,35 @@ class JSONParserTest < Test::Unit::TestCase
end
end
- private
+ def test_parse_whitespace_after_newline
+ assert_equal [], JSON.parse("[\n#{' ' * (8 + 8 + 4 + 3)}]")
+ end
- def string_deduplication_available?
- r1 = rand.to_s
- r2 = r1.dup
- begin
- (-r1).equal?(-r2)
- rescue NoMethodError
- false # No String#-@
+ def test_frozen
+ parser_config = JSON::Parser::Config.new({}).freeze
+ assert_raise FrozenError do
+ parser_config.send(:initialize, {})
end
end
+ def test_mutating_source_string_during_parsing
+ expected = ([1] * 100) + [2.3] + ([1] * 100)
+ source = JSON.generate(expected)
+ expected.delete_at(100)
+
+ fake_decimal_class = Class.new
+ fake_decimal_class.define_method(:initialize) do |number|
+ source.tr!('1', '0')
+ number.to_f
+ end
+
+ actual = JSON.parse(source, decimal_class: fake_decimal_class)
+ actual.delete_at(100)
+ assert_equal expected, actual
+ end
+
+ private
+
def assert_equal_float(expected, actual, delta = 1e-2)
Array === expected and expected = expected.first
Array === actual and actual = actual.first