mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
265 lines
7.8 KiB
Ruby
Executable File
265 lines
7.8 KiB
Ruby
Executable File
# frozen_string_literal: true
|
|
|
|
require_relative 'test_helper'
|
|
|
|
class JSONCoderTest < Test::Unit::TestCase
|
|
def test_json_coder_with_proc
|
|
coder = JSON::Coder.new do |object|
|
|
"[Object object]"
|
|
end
|
|
assert_equal %(["[Object object]"]), coder.dump([Object.new])
|
|
end
|
|
|
|
def test_json_coder_with_as_json_option
|
|
callback = ->(object, is_key) { 42 }
|
|
[callback, callback.method(:call)].each do |as_json|
|
|
coder = JSON::Coder.new(as_json: as_json)
|
|
assert_equal '[42]', coder.dump([Object.new])
|
|
end
|
|
end
|
|
|
|
def test_json_coder_block_overrides_as_json_option
|
|
coder = JSON::Coder.new(as_json: ->(object) { 1 }) { 2 }
|
|
assert_equal '[2]', coder.dump([Object.new])
|
|
end
|
|
|
|
def test_json_coder_as_json_invalid_type
|
|
assert_raise(TypeError) { JSON::Coder.new(as_json: 'x') }
|
|
end
|
|
|
|
def test_json_coder_rejects_disabling_strict_mode
|
|
[false, nil].each do |strict|
|
|
error = assert_raise(ArgumentError) { JSON::Coder.new(strict: strict) }
|
|
assert_equal 'JSON::Coder requires strict mode', error.message
|
|
end
|
|
assert_raise(JSON::GeneratorError) { JSON::Coder.new.dump(Object.new) }
|
|
assert_raise(JSON::GeneratorError) { JSON::Coder.new(strict: true).dump(Object.new) }
|
|
end
|
|
|
|
def test_json_coder_with_proc_with_unsupported_value
|
|
coder = JSON::Coder.new do |object, is_key|
|
|
assert_equal false, is_key
|
|
Object.new
|
|
end
|
|
assert_raise(JSON::GeneratorError) { coder.dump([Object.new]) }
|
|
end
|
|
|
|
def test_json_coder_with_proc_returning_symbol
|
|
coder = JSON::Coder.new { _1 }
|
|
assert_equal %({"sym":"sym"}), coder.dump({ sym: :sym })
|
|
end
|
|
|
|
def test_json_coder_hash_key
|
|
obj = Object.new
|
|
coder = JSON::Coder.new do |obj, is_key|
|
|
assert_equal true, is_key
|
|
obj.to_s
|
|
end
|
|
assert_equal %({#{obj.to_s.inspect}:1}), coder.dump({ obj => 1 })
|
|
|
|
coder = JSON::Coder.new { 42 }
|
|
error = assert_raise JSON::GeneratorError do
|
|
coder.dump({ obj => 1 })
|
|
end
|
|
assert_equal "Integer not allowed as object key in JSON", error.message
|
|
end
|
|
|
|
def test_json_coder_rfc8785_converted_keys
|
|
time = Time.utc(1999)
|
|
calls = []
|
|
coder = JSON::Coder.new(rfc8785: true) do |object, is_key|
|
|
calls << [object, is_key]
|
|
object.year.to_s
|
|
end
|
|
input = { time => 1, '1999!' => 2, Time.utc(2000) => 3 }
|
|
assert_equal '{"1999":1,"1999!":2,"2000":3}', coder.dump(input)
|
|
assert_equal [[time, true], [Time.utc(2000), true]], calls
|
|
assert_equal [time, '1999!', Time.utc(2000)], input.keys
|
|
end
|
|
|
|
def test_json_coder_rfc8785_converted_key_validation
|
|
object = Object.new
|
|
coder = JSON::Coder.new(rfc8785: true) { 42 }
|
|
error = assert_raise(JSON::GeneratorError) { coder.dump(object => 1) }
|
|
assert_equal 'Integer not allowed as object key in JSON', error.message
|
|
assert_equal 42, error.invalid_object
|
|
|
|
coder = JSON::Coder.new(rfc8785: true) { :a }
|
|
assert_equal '{"a":1,"b":2}', coder.dump('b' => 2, object => 1)
|
|
|
|
invalid = "\xFF"
|
|
calls = 0
|
|
coder = JSON::Coder.new(rfc8785: true) { calls += 1; invalid }
|
|
error = assert_raise(JSON::GeneratorError) { coder.dump(object => 1) }
|
|
assert_same invalid, error.invalid_object
|
|
assert_equal 1, calls
|
|
end
|
|
|
|
def test_json_coder_rfc8785_converted_key_collision
|
|
coder = JSON::Coder.new(rfc8785: true) { 'a' }
|
|
assert_raise(JSON::GeneratorError) { coder.dump(Object.new => 1, 'a' => 2) }
|
|
assert_raise(JSON::GeneratorError) { coder.dump(Object.new => 1, Object.new => 2) }
|
|
assert_raise(JSON::GeneratorError) { coder.dump(Object.new => 1, :a => 2) }
|
|
end
|
|
|
|
def test_json_coder_rfc8785_invalid_encoding_key
|
|
calls = []
|
|
coder = JSON::Coder.new(rfc8785: true) do |object, is_key|
|
|
calls << [object, is_key]
|
|
'a'
|
|
end
|
|
assert_equal '{"a":1,"b":2}', coder.dump('b' => 2, "\xFF" => 1)
|
|
assert_equal [["\xFF", true]], calls
|
|
end
|
|
|
|
def test_json_coder_options
|
|
coder = JSON::Coder.new(array_nl: "\n") do |object|
|
|
42
|
|
end
|
|
|
|
assert_equal "[\n42\n]", coder.dump([Object.new])
|
|
end
|
|
|
|
def test_json_coder_load
|
|
coder = JSON::Coder.new
|
|
assert_equal [1,2,3], coder.load("[1,2,3]")
|
|
end
|
|
|
|
def test_json_coder_load_options
|
|
coder = JSON::Coder.new(symbolize_names: true)
|
|
assert_equal({a: 1}, coder.load('{"a":1}'))
|
|
end
|
|
|
|
def test_json_coder_load_with_on_load_method
|
|
on_load = ->(value) { Integer === value ? value + 1 : value }.method(:call)
|
|
coder = JSON::Coder.new(on_load: on_load)
|
|
assert_equal [2], coder.load('[1]')
|
|
end
|
|
|
|
def test_json_coder_on_load_invalid_type
|
|
assert_raise(TypeError) { JSON::Coder.new(on_load: 'x') }
|
|
end
|
|
|
|
def test_json_coder_dump_NaN_or_Infinity
|
|
coder = JSON::Coder.new { |o| o.inspect }
|
|
assert_equal "NaN", coder.load(coder.dump(Float::NAN))
|
|
assert_equal "Infinity", coder.load(coder.dump(Float::INFINITY))
|
|
assert_equal "-Infinity", coder.load(coder.dump(-Float::INFINITY))
|
|
end
|
|
|
|
def test_json_coder_dump_NaN_or_Infinity_loop
|
|
coder = JSON::Coder.new { |o| o.itself }
|
|
error = assert_raise JSON::GeneratorError do
|
|
coder.dump(Float::NAN)
|
|
end
|
|
assert_include error.message, "NaN not allowed in JSON"
|
|
end
|
|
|
|
def test_json_coder_string_invalid_encoding
|
|
calls = 0
|
|
coder = JSON::Coder.new do |object, is_key|
|
|
calls += 1
|
|
object
|
|
end
|
|
|
|
error = assert_raise JSON::GeneratorError do
|
|
coder.dump("\xFF")
|
|
end
|
|
assert_equal "source sequence is illegal/malformed utf-8", error.message
|
|
assert_equal 1, calls
|
|
|
|
error = assert_raise JSON::GeneratorError do
|
|
coder.dump({ "\xFF" => 1 })
|
|
end
|
|
assert_equal "source sequence is illegal/malformed utf-8", error.message
|
|
assert_equal 2, calls
|
|
|
|
calls = 0
|
|
coder = JSON::Coder.new do |object, is_key|
|
|
calls += 1
|
|
object.dup
|
|
end
|
|
|
|
error = assert_raise JSON::GeneratorError do
|
|
coder.dump("\xFF")
|
|
end
|
|
assert_equal "source sequence is illegal/malformed utf-8", error.message
|
|
assert_equal 1, calls
|
|
|
|
error = assert_raise JSON::GeneratorError do
|
|
coder.dump({ "\xFF" => 1 })
|
|
end
|
|
assert_equal "source sequence is illegal/malformed utf-8", error.message
|
|
assert_equal 2, calls
|
|
|
|
calls = 0
|
|
coder = JSON::Coder.new do |object, is_key|
|
|
calls += 1
|
|
object.bytes
|
|
end
|
|
|
|
assert_equal "[255]", coder.dump("\xFF")
|
|
assert_equal 1, calls
|
|
|
|
error = assert_raise JSON::GeneratorError do
|
|
coder.dump({ "\xFF" => 1 })
|
|
end
|
|
assert_equal "Array not allowed as object key in JSON", error.message
|
|
assert_equal 2, calls
|
|
|
|
calls = 0
|
|
coder = JSON::Coder.new do |object, is_key|
|
|
calls += 1
|
|
[object].pack("m")
|
|
end
|
|
|
|
assert_equal '"/w==\\n"', coder.dump("\xFF")
|
|
assert_equal 1, calls
|
|
|
|
assert_equal '{"/w==\\n":1}', coder.dump({ "\xFF" => 1 })
|
|
assert_equal 2, calls
|
|
end
|
|
|
|
def test_json_coder_symbol_invalid_encoding
|
|
symbol = "\xFF".b.to_sym
|
|
|
|
calls = 0
|
|
coder = JSON::Coder.new do |object, is_key|
|
|
calls += 1
|
|
object.bytes
|
|
end
|
|
|
|
assert_equal "[[255]]", coder.dump([symbol])
|
|
assert_equal 1, calls
|
|
|
|
coder = JSON::Coder.new { |object, is_key| nil }
|
|
assert_equal "[null]", coder.dump([symbol])
|
|
|
|
coder = JSON::Coder.new { |object, is_key| Object.new }
|
|
assert_raise(JSON::GeneratorError) { coder.dump([symbol]) }
|
|
|
|
if RUBY_ENGINE == "ruby"
|
|
coder = JSON::Coder.new { |object, is_key| symbol }
|
|
error = assert_raise JSON::GeneratorError do
|
|
coder.dump([symbol])
|
|
end
|
|
assert_equal "source sequence is illegal/malformed utf-8", error.message
|
|
end
|
|
end
|
|
|
|
def test_depth
|
|
coder = JSON::Coder.new(object_nl: "\n", array_nl: "\n", space: " ", indent: " ", depth: 1)
|
|
assert_equal %({\n "foo": 42\n }), coder.dump(foo: 42)
|
|
end
|
|
|
|
def test_nesting_recovery
|
|
coder = JSON::Coder.new
|
|
ary = []
|
|
ary << ary
|
|
assert_raise JSON::NestingError do
|
|
coder.dump(ary)
|
|
end
|
|
assert_equal '{"a":1}', coder.dump({ a: 1 })
|
|
end
|
|
end
|