summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/lib/core_assertions.rb764
-rw-r--r--test/lib/envutil.rb367
-rw-r--r--test/lib/find_executable.rb22
-rw-r--r--test/lib/helper.rb4
-rw-r--r--test/psych/helper.rb40
-rw-r--r--test/psych/test_alias_and_anchor.rb12
-rw-r--r--test/psych/test_array.rb6
-rw-r--r--test/psych/test_class.rb4
-rw-r--r--test/psych/test_coder.rb135
-rw-r--r--test/psych/test_date_time.rb4
-rw-r--r--test/psych/test_deprecated.rb4
-rw-r--r--test/psych/test_document.rb2
-rw-r--r--test/psych/test_emitter.rb10
-rw-r--r--test/psych/test_encoding.rb4
-rw-r--r--test/psych/test_exception.rb58
-rw-r--r--test/psych/test_hash.rb18
-rw-r--r--test/psych/test_marshalable.rb12
-rw-r--r--test/psych/test_merge_keys.rb24
-rw-r--r--test/psych/test_numeric.rb1
-rw-r--r--test/psych/test_object.rb4
-rw-r--r--test/psych/test_object_references.rb12
-rw-r--r--test/psych/test_omap.rb4
-rw-r--r--test/psych/test_parser.rb16
-rw-r--r--test/psych/test_psych.rb150
-rw-r--r--test/psych/test_ractor.rb50
-rw-r--r--test/psych/test_safe_load.rb64
-rw-r--r--test/psych/test_scalar_scanner.rb15
-rw-r--r--test/psych/test_serialize_subclasses.rb4
-rw-r--r--test/psych/test_set.rb6
-rw-r--r--test/psych/test_string.rb14
-rw-r--r--test/psych/test_struct.rb6
-rw-r--r--test/psych/test_yaml.rb14
-rw-r--r--test/psych/test_yaml_special_cases.rb6
-rw-r--r--test/psych/test_yamlstore.rb47
-rw-r--r--test/psych/visitors/test_to_ruby.rb4
-rw-r--r--test/psych/visitors/test_yaml_tree.rb13
36 files changed, 1672 insertions, 248 deletions
diff --git a/test/lib/core_assertions.rb b/test/lib/core_assertions.rb
new file mode 100644
index 0000000..ff78c2b
--- /dev/null
+++ b/test/lib/core_assertions.rb
@@ -0,0 +1,764 @@
+# frozen_string_literal: true
+
+module Test
+ module Unit
+ module Assertions
+ def _assertions= n # :nodoc:
+ @_assertions = n
+ end
+
+ def _assertions # :nodoc:
+ @_assertions ||= 0
+ end
+
+ ##
+ # Returns a proc that will output +msg+ along with the default message.
+
+ def message msg = nil, ending = nil, &default
+ proc {
+ msg = msg.call.chomp(".") if Proc === msg
+ custom_message = "#{msg}.\n" unless msg.nil? or msg.to_s.empty?
+ "#{custom_message}#{default.call}#{ending || "."}"
+ }
+ end
+ end
+
+ module CoreAssertions
+ if defined?(MiniTest)
+ require_relative '../../envutil'
+ # for ruby core testing
+ include MiniTest::Assertions
+
+ # Compatibility hack for assert_raise
+ Test::Unit::AssertionFailedError = MiniTest::Assertion
+ else
+ module MiniTest
+ class Assertion < Exception; end
+ class Skip < Assertion; end
+ end
+
+ require 'pp'
+ require_relative 'envutil'
+ include Test::Unit::Assertions
+ end
+
+ def mu_pp(obj) #:nodoc:
+ obj.pretty_inspect.chomp
+ end
+
+ def assert_file
+ AssertFile
+ end
+
+ FailDesc = proc do |status, message = "", out = ""|
+ now = Time.now
+ proc do
+ EnvUtil.failure_description(status, now, message, out)
+ end
+ end
+
+ def assert_in_out_err(args, test_stdin = "", test_stdout = [], test_stderr = [], message = nil,
+ success: nil, **opt)
+ args = Array(args).dup
+ args.insert((Hash === args[0] ? 1 : 0), '--disable=gems')
+ stdout, stderr, status = EnvUtil.invoke_ruby(args, test_stdin, true, true, **opt)
+ desc = FailDesc[status, message, stderr]
+ if block_given?
+ raise "test_stdout ignored, use block only or without block" if test_stdout != []
+ raise "test_stderr ignored, use block only or without block" if test_stderr != []
+ yield(stdout.lines.map {|l| l.chomp }, stderr.lines.map {|l| l.chomp }, status)
+ else
+ all_assertions(desc) do |a|
+ [["stdout", test_stdout, stdout], ["stderr", test_stderr, stderr]].each do |key, exp, act|
+ a.for(key) do
+ if exp.is_a?(Regexp)
+ assert_match(exp, act)
+ elsif exp.all? {|e| String === e}
+ assert_equal(exp, act.lines.map {|l| l.chomp })
+ else
+ assert_pattern_list(exp, act)
+ end
+ end
+ end
+ unless success.nil?
+ a.for("success?") do
+ if success
+ assert_predicate(status, :success?)
+ else
+ assert_not_predicate(status, :success?)
+ end
+ end
+ end
+ end
+ status
+ end
+ end
+
+ if defined?(RubyVM::InstructionSequence)
+ def syntax_check(code, fname, line)
+ code = code.dup.force_encoding(Encoding::UTF_8)
+ RubyVM::InstructionSequence.compile(code, fname, fname, line)
+ :ok
+ ensure
+ raise if SyntaxError === $!
+ end
+ else
+ def syntax_check(code, fname, line)
+ code = code.b
+ code.sub!(/\A(?:\xef\xbb\xbf)?(\s*\#.*$)*(\n)?/n) {
+ "#$&#{"\n" if $1 && !$2}BEGIN{throw tag, :ok}\n"
+ }
+ code = code.force_encoding(Encoding::UTF_8)
+ catch {|tag| eval(code, binding, fname, line - 1)}
+ end
+ end
+
+ def assert_no_memory_leak(args, prepare, code, message=nil, limit: 2.0, rss: false, **opt)
+ # TODO: consider choosing some appropriate limit for MJIT and stop skipping this once it does not randomly fail
+ pend 'assert_no_memory_leak may consider MJIT memory usage as leak' if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+
+ require_relative '../../memory_status'
+ raise MiniTest::Skip, "unsupported platform" unless defined?(Memory::Status)
+
+ token = "\e[7;1m#{$$.to_s}:#{Time.now.strftime('%s.%L')}:#{rand(0x10000).to_s(16)}:\e[m"
+ token_dump = token.dump
+ token_re = Regexp.quote(token)
+ envs = args.shift if Array === args and Hash === args.first
+ args = [
+ "--disable=gems",
+ "-r", File.expand_path("../../../memory_status", __FILE__),
+ *args,
+ "-v", "-",
+ ]
+ if defined? Memory::NO_MEMORY_LEAK_ENVS then
+ envs ||= {}
+ newenvs = envs.merge(Memory::NO_MEMORY_LEAK_ENVS) { |_, _, _| break }
+ envs = newenvs if newenvs
+ end
+ args.unshift(envs) if envs
+ cmd = [
+ 'END {STDERR.puts '"#{token_dump}"'"FINAL=#{Memory::Status.new}"}',
+ prepare,
+ 'STDERR.puts('"#{token_dump}"'"START=#{$initial_status = Memory::Status.new}")',
+ '$initial_size = $initial_status.size',
+ code,
+ 'GC.start',
+ ].join("\n")
+ _, err, status = EnvUtil.invoke_ruby(args, cmd, true, true, **opt)
+ before = err.sub!(/^#{token_re}START=(\{.*\})\n/, '') && Memory::Status.parse($1)
+ after = err.sub!(/^#{token_re}FINAL=(\{.*\})\n/, '') && Memory::Status.parse($1)
+ assert(status.success?, FailDesc[status, message, err])
+ ([:size, (rss && :rss)] & after.members).each do |n|
+ b = before[n]
+ a = after[n]
+ next unless a > 0 and b > 0
+ assert_operator(a.fdiv(b), :<, limit, message(message) {"#{n}: #{b} => #{a}"})
+ end
+ rescue LoadError
+ pend
+ end
+
+ # :call-seq:
+ # assert_nothing_raised( *args, &block )
+ #
+ #If any exceptions are given as arguments, the assertion will
+ #fail if one of those exceptions are raised. Otherwise, the test fails
+ #if any exceptions are raised.
+ #
+ #The final argument may be a failure message.
+ #
+ # assert_nothing_raised RuntimeError do
+ # raise Exception #Assertion passes, Exception is not a RuntimeError
+ # end
+ #
+ # assert_nothing_raised do
+ # raise Exception #Assertion fails
+ # end
+ def assert_nothing_raised(*args)
+ self._assertions += 1
+ if Module === args.last
+ msg = nil
+ else
+ msg = args.pop
+ end
+ begin
+ line = __LINE__; yield
+ rescue MiniTest::Skip
+ raise
+ rescue Exception => e
+ bt = e.backtrace
+ as = e.instance_of?(MiniTest::Assertion)
+ if as
+ ans = /\A#{Regexp.quote(__FILE__)}:#{line}:in /o
+ bt.reject! {|ln| ans =~ ln}
+ end
+ if ((args.empty? && !as) ||
+ args.any? {|a| a.instance_of?(Module) ? e.is_a?(a) : e.class == a })
+ msg = message(msg) {
+ "Exception raised:\n<#{mu_pp(e)}>\n" +
+ "Backtrace:\n" +
+ e.backtrace.map{|frame| " #{frame}"}.join("\n")
+ }
+ raise MiniTest::Assertion, msg.call, bt
+ else
+ raise
+ end
+ end
+ end
+
+ def prepare_syntax_check(code, fname = nil, mesg = nil, verbose: nil)
+ fname ||= caller_locations(2, 1)[0]
+ mesg ||= fname.to_s
+ verbose, $VERBOSE = $VERBOSE, verbose
+ case
+ when Array === fname
+ fname, line = *fname
+ when defined?(fname.path) && defined?(fname.lineno)
+ fname, line = fname.path, fname.lineno
+ else
+ line = 1
+ end
+ yield(code, fname, line, message(mesg) {
+ if code.end_with?("\n")
+ "```\n#{code}```\n"
+ else
+ "```\n#{code}\n```\n""no-newline"
+ end
+ })
+ ensure
+ $VERBOSE = verbose
+ end
+
+ def assert_valid_syntax(code, *args, **opt)
+ prepare_syntax_check(code, *args, **opt) do |src, fname, line, mesg|
+ yield if defined?(yield)
+ assert_nothing_raised(SyntaxError, mesg) do
+ assert_equal(:ok, syntax_check(src, fname, line), mesg)
+ end
+ end
+ end
+
+ def assert_normal_exit(testsrc, message = '', child_env: nil, **opt)
+ assert_valid_syntax(testsrc, caller_locations(1, 1)[0])
+ if child_env
+ child_env = [child_env]
+ else
+ child_env = []
+ end
+ out, _, status = EnvUtil.invoke_ruby(child_env + %W'-W0', testsrc, true, :merge_to_stdout, **opt)
+ assert !status.signaled?, FailDesc[status, message, out]
+ end
+
+ def assert_ruby_status(args, test_stdin="", message=nil, **opt)
+ out, _, status = EnvUtil.invoke_ruby(args, test_stdin, true, :merge_to_stdout, **opt)
+ desc = FailDesc[status, message, out]
+ assert(!status.signaled?, desc)
+ message ||= "ruby exit status is not success:"
+ assert(status.success?, desc)
+ end
+
+ ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV TERM")
+
+ def separated_runner(out = nil)
+ include(*Test::Unit::TestCase.ancestors.select {|c| !c.is_a?(Class) })
+ out = out ? IO.new(out, 'w') : STDOUT
+ at_exit {
+ out.puts [Marshal.dump($!)].pack('m'), "assertions=\#{self._assertions}"
+ }
+ Test::Unit::Runner.class_variable_set(:@@stop_auto_run, true) if defined?(Test::Unit::Runner)
+ end
+
+ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **opt)
+ unless file and line
+ loc, = caller_locations(1,1)
+ file ||= loc.path
+ line ||= loc.lineno
+ end
+ capture_stdout = true
+ unless /mswin|mingw/ =~ RUBY_PLATFORM
+ capture_stdout = false
+ opt[:out] = MiniTest::Unit.output if defined?(MiniTest::Unit)
+ res_p, res_c = IO.pipe
+ opt[:ios] = [res_c]
+ end
+ src = <<eom
+# -*- coding: #{line += __LINE__; src.encoding}; -*-
+BEGIN {
+ require "test/unit";include Test::Unit::Assertions;require #{(__dir__ + "/core_assertions").dump};include Test::Unit::CoreAssertions
+ separated_runner #{res_c&.fileno}
+}
+#{line -= __LINE__; src}
+eom
+ args = args.dup
+ args.insert((Hash === args.first ? 1 : 0), "-w", "--disable=gems", *$:.map {|l| "-I#{l}"})
+ stdout, stderr, status = EnvUtil.invoke_ruby(args, src, capture_stdout, true, **opt)
+ ensure
+ if res_c
+ res_c.close
+ res = res_p.read
+ res_p.close
+ else
+ res = stdout
+ end
+ raise if $!
+ abort = status.coredump? || (status.signaled? && ABORT_SIGNALS.include?(status.termsig))
+ assert(!abort, FailDesc[status, nil, stderr])
+ self._assertions += res[/^assertions=(\d+)/, 1].to_i
+ begin
+ res = Marshal.load(res.unpack1("m"))
+ rescue => marshal_error
+ ignore_stderr = nil
+ res = nil
+ end
+ if res and !(SystemExit === res)
+ if bt = res.backtrace
+ bt.each do |l|
+ l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"}
+ end
+ bt.concat(caller)
+ else
+ res.set_backtrace(caller)
+ end
+ raise res
+ end
+
+ # really is it succeed?
+ unless ignore_stderr
+ # the body of assert_separately must not output anything to detect error
+ assert(stderr.empty?, FailDesc[status, "assert_separately failed with error message", stderr])
+ end
+ assert(status.success?, FailDesc[status, "assert_separately failed", stderr])
+ raise marshal_error if marshal_error
+ end
+
+ # Run Ractor-related test without influencing the main test suite
+ def assert_ractor(src, args: [], require: nil, require_relative: nil, file: nil, line: nil, ignore_stderr: nil, **opt)
+ return unless defined?(Ractor)
+
+ require = "require #{require.inspect}" if require
+ if require_relative
+ dir = File.dirname(caller_locations[0,1][0].absolute_path)
+ full_path = File.expand_path(require_relative, dir)
+ require = "#{require}; require #{full_path.inspect}"
+ end
+
+ assert_separately(args, file, line, <<~RUBY, ignore_stderr: ignore_stderr, **opt)
+ #{require}
+ previous_verbose = $VERBOSE
+ $VERBOSE = nil
+ Ractor.new {} # trigger initial warning
+ $VERBOSE = previous_verbose
+ #{src}
+ RUBY
+ end
+
+ # :call-seq:
+ # assert_throw( tag, failure_message = nil, &block )
+ #
+ #Fails unless the given block throws +tag+, returns the caught
+ #value otherwise.
+ #
+ #An optional failure message may be provided as the final argument.
+ #
+ # tag = Object.new
+ # assert_throw(tag, "#{tag} was not thrown!") do
+ # throw tag
+ # end
+ def assert_throw(tag, msg = nil)
+ ret = catch(tag) do
+ begin
+ yield(tag)
+ rescue UncaughtThrowError => e
+ thrown = e.tag
+ end
+ msg = message(msg) {
+ "Expected #{mu_pp(tag)} to have been thrown"\
+ "#{%Q[, not #{thrown}] if thrown}"
+ }
+ assert(false, msg)
+ end
+ assert(true)
+ ret
+ end
+
+ # :call-seq:
+ # assert_raise( *args, &block )
+ #
+ #Tests if the given block raises an exception. Acceptable exception
+ #types may be given as optional arguments. If the last argument is a
+ #String, it will be used as the error message.
+ #
+ # assert_raise do #Fails, no Exceptions are raised
+ # end
+ #
+ # assert_raise NameError do
+ # puts x #Raises NameError, so assertion succeeds
+ # end
+ def assert_raise(*exp, &b)
+ case exp.last
+ when String, Proc
+ msg = exp.pop
+ end
+
+ begin
+ yield
+ rescue MiniTest::Skip => e
+ return e if exp.include? MiniTest::Skip
+ raise e
+ rescue Exception => e
+ expected = exp.any? { |ex|
+ if ex.instance_of? Module then
+ e.kind_of? ex
+ else
+ e.instance_of? ex
+ end
+ }
+
+ assert expected, proc {
+ flunk(message(msg) {"#{mu_pp(exp)} exception expected, not #{mu_pp(e)}"})
+ }
+
+ return e
+ ensure
+ unless e
+ exp = exp.first if exp.size == 1
+
+ flunk(message(msg) {"#{mu_pp(exp)} expected but nothing was raised"})
+ end
+ end
+ end
+
+ # :call-seq:
+ # assert_raise_with_message(exception, expected, msg = nil, &block)
+ #
+ #Tests if the given block raises an exception with the expected
+ #message.
+ #
+ # assert_raise_with_message(RuntimeError, "foo") do
+ # nil #Fails, no Exceptions are raised
+ # end
+ #
+ # assert_raise_with_message(RuntimeError, "foo") do
+ # raise ArgumentError, "foo" #Fails, different Exception is raised
+ # end
+ #
+ # assert_raise_with_message(RuntimeError, "foo") do
+ # raise "bar" #Fails, RuntimeError is raised but the message differs
+ # end
+ #
+ # assert_raise_with_message(RuntimeError, "foo") do
+ # raise "foo" #Raises RuntimeError with the message, so assertion succeeds
+ # end
+ def assert_raise_with_message(exception, expected, msg = nil, &block)
+ case expected
+ when String
+ assert = :assert_equal
+ when Regexp
+ assert = :assert_match
+ else
+ raise TypeError, "Expected #{expected.inspect} to be a kind of String or Regexp, not #{expected.class}"
+ end
+
+ ex = m = nil
+ EnvUtil.with_default_internal(expected.encoding) do
+ ex = assert_raise(exception, msg || proc {"Exception(#{exception}) with message matches to #{expected.inspect}"}) do
+ yield
+ end
+ m = ex.message
+ end
+ msg = message(msg, "") {"Expected Exception(#{exception}) was raised, but the message doesn't match"}
+
+ if assert == :assert_equal
+ assert_equal(expected, m, msg)
+ else
+ msg = message(msg) { "Expected #{mu_pp expected} to match #{mu_pp m}" }
+ assert expected =~ m, msg
+ block.binding.eval("proc{|_|$~=_}").call($~)
+ end
+ ex
+ end
+
+ MINI_DIR = File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), "minitest") #:nodoc:
+
+ # :call-seq:
+ # assert(test, [failure_message])
+ #
+ #Tests if +test+ is true.
+ #
+ #+msg+ may be a String or a Proc. If +msg+ is a String, it will be used
+ #as the failure message. Otherwise, the result of calling +msg+ will be
+ #used as the message if the assertion fails.
+ #
+ #If no +msg+ is given, a default message will be used.
+ #
+ # assert(false, "This was expected to be true")
+ def assert(test, *msgs)
+ case msg = msgs.first
+ when String, Proc
+ when nil
+ msgs.shift
+ else
+ bt = caller.reject { |s| s.start_with?(MINI_DIR) }
+ raise ArgumentError, "assertion message must be String or Proc, but #{msg.class} was given.", bt
+ end unless msgs.empty?
+ super
+ end
+
+ # :call-seq:
+ # assert_respond_to( object, method, failure_message = nil )
+ #
+ #Tests if the given Object responds to +method+.
+ #
+ #An optional failure message may be provided as the final argument.
+ #
+ # assert_respond_to("hello", :reverse) #Succeeds
+ # assert_respond_to("hello", :does_not_exist) #Fails
+ def assert_respond_to(obj, (meth, *priv), msg = nil)
+ unless priv.empty?
+ msg = message(msg) {
+ "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}#{" privately" if priv[0]}"
+ }
+ return assert obj.respond_to?(meth, *priv), msg
+ end
+ #get rid of overcounting
+ if caller_locations(1, 1)[0].path.start_with?(MINI_DIR)
+ return if obj.respond_to?(meth)
+ end
+ super(obj, meth, msg)
+ end
+
+ # :call-seq:
+ # assert_not_respond_to( object, method, failure_message = nil )
+ #
+ #Tests if the given Object does not respond to +method+.
+ #
+ #An optional failure message may be provided as the final argument.
+ #
+ # assert_not_respond_to("hello", :reverse) #Fails
+ # assert_not_respond_to("hello", :does_not_exist) #Succeeds
+ def assert_not_respond_to(obj, (meth, *priv), msg = nil)
+ unless priv.empty?
+ msg = message(msg) {
+ "Expected #{mu_pp(obj)} (#{obj.class}) to not respond to ##{meth}#{" privately" if priv[0]}"
+ }
+ return assert !obj.respond_to?(meth, *priv), msg
+ end
+ #get rid of overcounting
+ if caller_locations(1, 1)[0].path.start_with?(MINI_DIR)
+ return unless obj.respond_to?(meth)
+ end
+ refute_respond_to(obj, meth, msg)
+ end
+
+ # pattern_list is an array which contains regexp and :*.
+ # :* means any sequence.
+ #
+ # pattern_list is anchored.
+ # Use [:*, regexp, :*] for non-anchored match.
+ def assert_pattern_list(pattern_list, actual, message=nil)
+ rest = actual
+ anchored = true
+ pattern_list.each_with_index {|pattern, i|
+ if pattern == :*
+ anchored = false
+ else
+ if anchored
+ match = /\A#{pattern}/.match(rest)
+ else
+ match = pattern.match(rest)
+ end
+ unless match
+ msg = message(msg) {
+ expect_msg = "Expected #{mu_pp pattern}\n"
+ if /\n[^\n]/ =~ rest
+ actual_mesg = +"to match\n"
+ rest.scan(/.*\n+/) {
+ actual_mesg << ' ' << $&.inspect << "+\n"
+ }
+ actual_mesg.sub!(/\+\n\z/, '')
+ else
+ actual_mesg = "to match " + mu_pp(rest)
+ end
+ actual_mesg << "\nafter #{i} patterns with #{actual.length - rest.length} characters"
+ expect_msg + actual_mesg
+ }
+ assert false, msg
+ end
+ rest = match.post_match
+ anchored = true
+ end
+ }
+ if anchored
+ assert_equal("", rest)
+ end
+ end
+
+ def assert_warning(pat, msg = nil)
+ result = nil
+ stderr = EnvUtil.with_default_internal(pat.encoding) {
+ EnvUtil.verbose_warning {
+ result = yield
+ }
+ }
+ msg = message(msg) {diff pat, stderr}
+ assert(pat === stderr, msg)
+ result
+ end
+
+ def assert_warn(*args)
+ assert_warning(*args) {$VERBOSE = false; yield}
+ end
+
+ def assert_deprecated_warning(mesg = /deprecated/)
+ assert_warning(mesg) do
+ Warning[:deprecated] = true
+ yield
+ end
+ end
+
+ def assert_deprecated_warn(mesg = /deprecated/)
+ assert_warn(mesg) do
+ Warning[:deprecated] = true
+ yield
+ end
+ end
+
+ class << (AssertFile = Struct.new(:failure_message).new)
+ include CoreAssertions
+ def assert_file_predicate(predicate, *args)
+ if /\Anot_/ =~ predicate
+ predicate = $'
+ neg = " not"
+ end
+ result = File.__send__(predicate, *args)
+ result = !result if neg
+ mesg = "Expected file ".dup << args.shift.inspect
+ mesg << "#{neg} to be #{predicate}"
+ mesg << mu_pp(args).sub(/\A\[(.*)\]\z/m, '(\1)') unless args.empty?
+ mesg << " #{failure_message}" if failure_message
+ assert(result, mesg)
+ end
+ alias method_missing assert_file_predicate
+
+ def for(message)
+ clone.tap {|a| a.failure_message = message}
+ end
+ end
+
+ class AllFailures
+ attr_reader :failures
+
+ def initialize
+ @count = 0
+ @failures = {}
+ end
+
+ def for(key)
+ @count += 1
+ yield
+ rescue Exception => e
+ @failures[key] = [@count, e]
+ end
+
+ def foreach(*keys)
+ keys.each do |key|
+ @count += 1
+ begin
+ yield key
+ rescue Exception => e
+ @failures[key] = [@count, e]
+ end
+ end
+ end
+
+ def message
+ i = 0
+ total = @count.to_s
+ fmt = "%#{total.size}d"
+ @failures.map {|k, (n, v)|
+ v = v.message
+ "\n#{i+=1}. [#{fmt%n}/#{total}] Assertion for #{k.inspect}\n#{v.b.gsub(/^/, ' | ').force_encoding(v.encoding)}"
+ }.join("\n")
+ end
+
+ def pass?
+ @failures.empty?
+ end
+ end
+
+ # threads should respond to shift method.
+ # Array can be used.
+ def assert_join_threads(threads, message = nil)
+ errs = []
+ values = []
+ while th = threads.shift
+ begin
+ values << th.value
+ rescue Exception
+ errs << [th, $!]
+ th = nil
+ end
+ end
+ values
+ ensure
+ if th&.alive?
+ th.raise(Timeout::Error.new)
+ th.join rescue errs << [th, $!]
+ end
+ if !errs.empty?
+ msg = "exceptions on #{errs.length} threads:\n" +
+ errs.map {|t, err|
+ "#{t.inspect}:\n" +
+ RUBY_VERSION >= "2.5.0" ? err.full_message(highlight: false, order: :top) : err.message
+ }.join("\n---\n")
+ if message
+ msg = "#{message}\n#{msg}"
+ end
+ raise MiniTest::Assertion, msg
+ end
+ end
+
+ def assert_all_assertions(msg = nil)
+ all = AllFailures.new
+ yield all
+ ensure
+ assert(all.pass?, message(msg) {all.message.chomp(".")})
+ end
+ alias all_assertions assert_all_assertions
+
+ def message(msg = nil, *args, &default) # :nodoc:
+ if Proc === msg
+ super(nil, *args) do
+ ary = [msg.call, (default.call if default)].compact.reject(&:empty?)
+ if 1 < ary.length
+ ary[0...-1] = ary[0...-1].map {|str| str.sub(/(?<!\.)\z/, '.') }
+ end
+ begin
+ ary.join("\n")
+ rescue Encoding::CompatibilityError
+ ary.map(&:b).join("\n")
+ end
+ end
+ else
+ super
+ end
+ end
+
+ def diff(exp, act)
+ require 'pp'
+ q = PP.new(+"")
+ q.guard_inspect_key do
+ q.group(2, "expected: ") do
+ q.pp exp
+ end
+ q.text q.newline
+ q.group(2, "actual: ") do
+ q.pp act
+ end
+ q.flush
+ end
+ q.output
+ end
+ end
+ end
+end
diff --git a/test/lib/envutil.rb b/test/lib/envutil.rb
new file mode 100644
index 0000000..0391b90
--- /dev/null
+++ b/test/lib/envutil.rb
@@ -0,0 +1,367 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: true
+require "open3"
+require "timeout"
+require_relative "find_executable"
+begin
+ require 'rbconfig'
+rescue LoadError
+end
+begin
+ require "rbconfig/sizeof"
+rescue LoadError
+end
+
+module EnvUtil
+ def rubybin
+ if ruby = ENV["RUBY"]
+ return ruby
+ end
+ ruby = "ruby"
+ exeext = RbConfig::CONFIG["EXEEXT"]
+ rubyexe = (ruby + exeext if exeext and !exeext.empty?)
+ 3.times do
+ if File.exist? ruby and File.executable? ruby and !File.directory? ruby
+ return File.expand_path(ruby)
+ end
+ if rubyexe and File.exist? rubyexe and File.executable? rubyexe
+ return File.expand_path(rubyexe)
+ end
+ ruby = File.join("..", ruby)
+ end
+ if defined?(RbConfig.ruby)
+ RbConfig.ruby
+ else
+ "ruby"
+ end
+ end
+ module_function :rubybin
+
+ LANG_ENVS = %w"LANG LC_ALL LC_CTYPE"
+
+ DEFAULT_SIGNALS = Signal.list
+ DEFAULT_SIGNALS.delete("TERM") if /mswin|mingw/ =~ RUBY_PLATFORM
+
+ RUBYLIB = ENV["RUBYLIB"]
+
+ class << self
+ attr_accessor :timeout_scale
+ attr_reader :original_internal_encoding, :original_external_encoding,
+ :original_verbose, :original_warning
+
+ def capture_global_values
+ @original_internal_encoding = Encoding.default_internal
+ @original_external_encoding = Encoding.default_external
+ @original_verbose = $VERBOSE
+ @original_warning = defined?(Warning.[]) ? %i[deprecated experimental].to_h {|i| [i, Warning[i]]} : nil
+ end
+ end
+
+ def apply_timeout_scale(t)
+ if scale = EnvUtil.timeout_scale
+ t * scale
+ else
+ t
+ end
+ end
+ module_function :apply_timeout_scale
+
+ def timeout(sec, klass = nil, message = nil, &blk)
+ return yield(sec) if sec == nil or sec.zero?
+ sec = apply_timeout_scale(sec)
+ Timeout.timeout(sec, klass, message, &blk)
+ end
+ module_function :timeout
+
+ def terminate(pid, signal = :TERM, pgroup = nil, reprieve = 1)
+ reprieve = apply_timeout_scale(reprieve) if reprieve
+
+ signals = Array(signal).select do |sig|
+ DEFAULT_SIGNALS[sig.to_s] or
+ DEFAULT_SIGNALS[Signal.signame(sig)] rescue false
+ end
+ signals |= [:ABRT, :KILL]
+ case pgroup
+ when 0, true
+ pgroup = -pid
+ when nil, false
+ pgroup = pid
+ end
+
+ lldb = true if /darwin/ =~ RUBY_PLATFORM
+
+ while signal = signals.shift
+
+ if lldb and [:ABRT, :KILL].include?(signal)
+ lldb = false
+ # sudo -n: --non-interactive
+ # lldb -p: attach
+ # -o: run command
+ system(*%W[sudo -n lldb -p #{pid} --batch -o bt\ all -o call\ rb_vmdebug_stack_dump_all_threads() -o quit])
+ true
+ end
+
+ begin
+ Process.kill signal, pgroup
+ rescue Errno::EINVAL
+ next
+ rescue Errno::ESRCH
+ break
+ end
+ if signals.empty? or !reprieve
+ Process.wait(pid)
+ else
+ begin
+ Timeout.timeout(reprieve) {Process.wait(pid)}
+ rescue Timeout::Error
+ else
+ break
+ end
+ end
+ end
+ $?
+ end
+ module_function :terminate
+
+ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = false,
+ encoding: nil, timeout: 10, reprieve: 1, timeout_error: Timeout::Error,
+ stdout_filter: nil, stderr_filter: nil, ios: nil,
+ signal: :TERM,
+ rubybin: EnvUtil.rubybin, precommand: nil,
+ **opt)
+ timeout = apply_timeout_scale(timeout)
+
+ in_c, in_p = IO.pipe
+ out_p, out_c = IO.pipe if capture_stdout
+ err_p, err_c = IO.pipe if capture_stderr && capture_stderr != :merge_to_stdout
+ opt[:in] = in_c
+ opt[:out] = out_c if capture_stdout
+ opt[:err] = capture_stderr == :merge_to_stdout ? out_c : err_c if capture_stderr
+ if encoding
+ out_p.set_encoding(encoding) if out_p
+ err_p.set_encoding(encoding) if err_p
+ end
+ ios.each {|i, o = i|opt[i] = o} if ios
+
+ c = "C"
+ child_env = {}
+ LANG_ENVS.each {|lc| child_env[lc] = c}
+ if Array === args and Hash === args.first
+ child_env.update(args.shift)
+ end
+ if RUBYLIB and lib = child_env["RUBYLIB"]
+ child_env["RUBYLIB"] = [lib, RUBYLIB].join(File::PATH_SEPARATOR)
+ end
+ child_env['ASAN_OPTIONS'] = ENV['ASAN_OPTIONS'] if ENV['ASAN_OPTIONS']
+ args = [args] if args.kind_of?(String)
+ pid = spawn(child_env, *precommand, rubybin, *args, opt)
+ in_c.close
+ out_c&.close
+ out_c = nil
+ err_c&.close
+ err_c = nil
+ if block_given?
+ return yield in_p, out_p, err_p, pid
+ else
+ th_stdout = Thread.new { out_p.read } if capture_stdout
+ th_stderr = Thread.new { err_p.read } if capture_stderr && capture_stderr != :merge_to_stdout
+ in_p.write stdin_data.to_str unless stdin_data.empty?
+ in_p.close
+ if (!th_stdout || th_stdout.join(timeout)) && (!th_stderr || th_stderr.join(timeout))
+ timeout_error = nil
+ else
+ status = terminate(pid, signal, opt[:pgroup], reprieve)
+ terminated = Time.now
+ end
+ stdout = th_stdout.value if capture_stdout
+ stderr = th_stderr.value if capture_stderr && capture_stderr != :merge_to_stdout
+ out_p.close if capture_stdout
+ err_p.close if capture_stderr && capture_stderr != :merge_to_stdout
+ status ||= Process.wait2(pid)[1]
+ stdout = stdout_filter.call(stdout) if stdout_filter
+ stderr = stderr_filter.call(stderr) if stderr_filter
+ if timeout_error
+ bt = caller_locations
+ msg = "execution of #{bt.shift.label} expired timeout (#{timeout} sec)"
+ msg = failure_description(status, terminated, msg, [stdout, stderr].join("\n"))
+ raise timeout_error, msg, bt.map(&:to_s)
+ end
+ return stdout, stderr, status
+ end
+ ensure
+ [th_stdout, th_stderr].each do |th|
+ th.kill if th
+ end
+ [in_c, in_p, out_c, out_p, err_c, err_p].each do |io|
+ io&.close
+ end
+ [th_stdout, th_stderr].each do |th|
+ th.join if th
+ end
+ end
+ module_function :invoke_ruby
+
+ def verbose_warning
+ class << (stderr = "".dup)
+ alias write concat
+ def flush; end
+ end
+ stderr, $stderr = $stderr, stderr
+ $VERBOSE = true
+ yield stderr
+ return $stderr
+ ensure
+ stderr, $stderr = $stderr, stderr
+ $VERBOSE = EnvUtil.original_verbose
+ EnvUtil.original_warning&.each {|i, v| Warning[i] = v}
+ end
+ module_function :verbose_warning
+
+ def default_warning
+ $VERBOSE = false
+ yield
+ ensure
+ $VERBOSE = EnvUtil.original_verbose
+ end
+ module_function :default_warning
+
+ def suppress_warning
+ $VERBOSE = nil
+ yield
+ ensure
+ $VERBOSE = EnvUtil.original_verbose
+ end
+ module_function :suppress_warning
+
+ def under_gc_stress(stress = true)
+ stress, GC.stress = GC.stress, stress
+ yield
+ ensure
+ GC.stress = stress
+ end
+ module_function :under_gc_stress
+
+ def with_default_external(enc)
+ suppress_warning { Encoding.default_external = enc }
+ yield
+ ensure
+ suppress_warning { Encoding.default_external = EnvUtil.original_external_encoding }
+ end
+ module_function :with_default_external
+
+ def with_default_internal(enc)
+ suppress_warning { Encoding.default_internal = enc }
+ yield
+ ensure
+ suppress_warning { Encoding.default_internal = EnvUtil.original_internal_encoding }
+ end
+ module_function :with_default_internal
+
+ def labeled_module(name, &block)
+ Module.new do
+ singleton_class.class_eval {
+ define_method(:to_s) {name}
+ alias inspect to_s
+ alias name to_s
+ }
+ class_eval(&block) if block
+ end
+ end
+ module_function :labeled_module
+
+ def labeled_class(name, superclass = Object, &block)
+ Class.new(superclass) do
+ singleton_class.class_eval {
+ define_method(:to_s) {name}
+ alias inspect to_s
+ alias name to_s
+ }
+ class_eval(&block) if block
+ end
+ end
+ module_function :labeled_class
+
+ if /darwin/ =~ RUBY_PLATFORM
+ DIAGNOSTIC_REPORTS_PATH = File.expand_path("~/Library/Logs/DiagnosticReports")
+ DIAGNOSTIC_REPORTS_TIMEFORMAT = '%Y-%m-%d-%H%M%S'
+ @ruby_install_name = RbConfig::CONFIG['RUBY_INSTALL_NAME']
+
+ def self.diagnostic_reports(signame, pid, now)
+ return unless %w[ABRT QUIT SEGV ILL TRAP].include?(signame)
+ cmd = File.basename(rubybin)
+ cmd = @ruby_install_name if "ruby-runner#{RbConfig::CONFIG["EXEEXT"]}" == cmd
+ path = DIAGNOSTIC_REPORTS_PATH
+ timeformat = DIAGNOSTIC_REPORTS_TIMEFORMAT
+ pat = "#{path}/#{cmd}_#{now.strftime(timeformat)}[-_]*.crash"
+ first = true
+ 30.times do
+ first ? (first = false) : sleep(0.1)
+ Dir.glob(pat) do |name|
+ log = File.read(name) rescue next
+ if /\AProcess:\s+#{cmd} \[#{pid}\]$/ =~ log
+ File.unlink(name)
+ File.unlink("#{path}/.#{File.basename(name)}.plist") rescue nil
+ return log
+ end
+ end
+ end
+ nil
+ end
+ else
+ def self.diagnostic_reports(signame, pid, now)
+ end
+ end
+
+ def self.failure_description(status, now, message = "", out = "")
+ pid = status.pid
+ if signo = status.termsig
+ signame = Signal.signame(signo)
+ sigdesc = "signal #{signo}"
+ end
+ log = diagnostic_reports(signame, pid, now)
+ if signame
+ sigdesc = "SIG#{signame} (#{sigdesc})"
+ end
+ if status.coredump?
+ sigdesc = "#{sigdesc} (core dumped)"
+ end
+ full_message = ''.dup
+ message = message.call if Proc === message
+ if message and !message.empty?
+ full_message << message << "\n"
+ end
+ full_message << "pid #{pid}"
+ full_message << " exit #{status.exitstatus}" if status.exited?
+ full_message << " killed by #{sigdesc}" if sigdesc
+ if out and !out.empty?
+ full_message << "\n" << out.b.gsub(/^/, '| ')
+ full_message.sub!(/(?<!\n)\z/, "\n")
+ end
+ if log
+ full_message << "Diagnostic reports:\n" << log.b.gsub(/^/, '| ')
+ end
+ full_message
+ end
+
+ def self.gc_stress_to_class?
+ unless defined?(@gc_stress_to_class)
+ _, _, status = invoke_ruby(["-e""exit GC.respond_to?(:add_stress_to_class)"])
+ @gc_stress_to_class = status.success?
+ end
+ @gc_stress_to_class
+ end
+end
+
+if defined?(RbConfig)
+ module RbConfig
+ @ruby = EnvUtil.rubybin
+ class << self
+ undef ruby if method_defined?(:ruby)
+ attr_reader :ruby
+ end
+ dir = File.dirname(ruby)
+ CONFIG['bindir'] = dir
+ end
+end
+
+EnvUtil.capture_global_values
diff --git a/test/lib/find_executable.rb b/test/lib/find_executable.rb
new file mode 100644
index 0000000..89c6fb8
--- /dev/null
+++ b/test/lib/find_executable.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+require "rbconfig"
+
+module EnvUtil
+ def find_executable(cmd, *args)
+ exts = RbConfig::CONFIG["EXECUTABLE_EXTS"].split | [RbConfig::CONFIG["EXEEXT"]]
+ ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
+ next if path.empty?
+ path = File.join(path, cmd)
+ exts.each do |ext|
+ cmdline = [path + ext, *args]
+ begin
+ return cmdline if yield(IO.popen(cmdline, "r", err: [:child, :out], &:read))
+ rescue
+ next
+ end
+ end
+ end
+ nil
+ end
+ module_function :find_executable
+end
diff --git a/test/lib/helper.rb b/test/lib/helper.rb
new file mode 100644
index 0000000..909f8f9
--- /dev/null
+++ b/test/lib/helper.rb
@@ -0,0 +1,4 @@
+require "test/unit"
+require_relative "core_assertions"
+
+Test::Unit::TestCase.include Test::Unit::CoreAssertions
diff --git a/test/psych/helper.rb b/test/psych/helper.rb
index 9348457..0643139 100644
--- a/test/psych/helper.rb
+++ b/test/psych/helper.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'minitest/autorun'
+require 'test/unit'
require 'stringio'
require 'tempfile'
require 'date'
@@ -7,13 +7,7 @@ require 'date'
require 'psych'
module Psych
- superclass = if defined?(Minitest::Test)
- Minitest::Test
- else
- MiniTest::Unit::TestCase
- end
-
- class TestCase < superclass
+ class TestCase < Test::Unit::TestCase
def self.suppress_warning
verbose, $VERBOSE = $VERBOSE, nil
yield
@@ -47,24 +41,30 @@ module Psych
# Convert between Psych and the object to verify correct parsing and
# emitting
#
- def assert_to_yaml( obj, yaml )
- assert_equal( obj, Psych::load( yaml ) )
+ def assert_to_yaml( obj, yaml, loader = :load )
+ assert_equal( obj, Psych.send(loader, yaml) )
assert_equal( obj, Psych::parse( yaml ).transform )
- assert_equal( obj, Psych::load( obj.to_yaml ) )
+ assert_equal( obj, Psych.send(loader, obj.to_yaml) )
assert_equal( obj, Psych::parse( obj.to_yaml ).transform )
- assert_equal( obj, Psych::load(
+ assert_equal( obj, Psych.send(loader,
obj.to_yaml(
:UseVersion => true, :UseHeader => true, :SortKeys => true
)
))
+ rescue Psych::DisallowedClass, Psych::BadAlias
+ assert_to_yaml obj, yaml, :unsafe_load
end
#
# Test parser only
#
def assert_parse_only( obj, yaml )
- assert_equal( obj, Psych::load( yaml ) )
- assert_equal( obj, Psych::parse( yaml ).transform )
+ begin
+ assert_equal obj, Psych::load( yaml )
+ rescue Psych::DisallowedClass, Psych::BadAlias
+ assert_equal obj, Psych::unsafe_load( yaml )
+ end
+ assert_equal obj, Psych::parse( yaml ).transform
end
def assert_cycle( obj )
@@ -75,9 +75,15 @@ module Psych
assert_nil Psych::load(Psych.dump(obj))
assert_nil Psych::load(obj.to_yaml)
else
- assert_equal(obj, Psych.load(v.tree.yaml))
- assert_equal(obj, Psych::load(Psych.dump(obj)))
- assert_equal(obj, Psych::load(obj.to_yaml))
+ begin
+ assert_equal(obj, Psych.load(v.tree.yaml))
+ assert_equal(obj, Psych::load(Psych.dump(obj)))
+ assert_equal(obj, Psych::load(obj.to_yaml))
+ rescue Psych::DisallowedClass, Psych::BadAlias
+ assert_equal(obj, Psych.unsafe_load(v.tree.yaml))
+ assert_equal(obj, Psych::unsafe_load(Psych.dump(obj)))
+ assert_equal(obj, Psych::unsafe_load(obj.to_yaml))
+ end
end
end
diff --git a/test/psych/test_alias_and_anchor.rb b/test/psych/test_alias_and_anchor.rb
index 91c09df..81ebd66 100644
--- a/test/psych/test_alias_and_anchor.rb
+++ b/test/psych/test_alias_and_anchor.rb
@@ -19,7 +19,7 @@ module Psych
- *id001
- *id001
EOYAML
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each {|el| assert_same(result[0], el) }
end
@@ -33,7 +33,7 @@ EOYAML
- *id001
EOYAML
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each do |el|
assert_same(result[0], el)
assert_equal('test1', el.var1)
@@ -50,7 +50,7 @@ EOYAML
- *id001
- *id001
EOYAML
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each do |el|
assert_same(result[0], el)
assert_equal('test', el.var1)
@@ -62,7 +62,7 @@ EOYAML
original = [o,o,o]
yaml = Psych.dump original
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each {|el| assert_same(result[0], el) }
end
@@ -73,7 +73,7 @@ EOYAML
original = [o,o,o]
yaml = Psych.dump original
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each do |el|
assert_same(result[0], el)
assert_equal('test1', el.var1)
@@ -87,7 +87,7 @@ EOYAML
original = [o,o,o]
yaml = Psych.dump original
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each do |el|
assert_same(result[0], el)
assert_equal('test', el.var1)
diff --git a/test/psych/test_array.rb b/test/psych/test_array.rb
index f2bbdca..28b76da 100644
--- a/test/psych/test_array.rb
+++ b/test/psych/test_array.rb
@@ -24,7 +24,7 @@ module Psych
def test_another_subclass_with_attributes
y = Y.new.tap {|o| o.val = 1}
y << "foo" << "bar"
- y = Psych.load Psych.dump y
+ y = Psych.unsafe_load Psych.dump y
assert_equal %w{foo bar}, y
assert_equal Y, y.class
@@ -42,13 +42,13 @@ module Psych
end
def test_subclass_with_attributes
- y = Psych.load Psych.dump Y.new.tap {|o| o.val = 1}
+ y = Psych.unsafe_load Psych.dump Y.new.tap {|o| o.val = 1}
assert_equal Y, y.class
assert_equal 1, y.val
end
def test_backwards_with_syck
- x = Psych.load "--- !seq:#{X.name} []\n\n"
+ x = Psych.unsafe_load "--- !seq:#{X.name} []\n\n"
assert_equal X, x.class
end
diff --git a/test/psych/test_class.rb b/test/psych/test_class.rb
index 71f7ec3..faa504c 100644
--- a/test/psych/test_class.rb
+++ b/test/psych/test_class.rb
@@ -7,13 +7,13 @@ module Psych
end
def test_cycle_anonymous_class
- assert_raises(::TypeError) do
+ assert_raise(::TypeError) do
assert_cycle(Class.new)
end
end
def test_cycle_anonymous_module
- assert_raises(::TypeError) do
+ assert_raise(::TypeError) do
assert_cycle(Module.new)
end
end
diff --git a/test/psych/test_coder.rb b/test/psych/test_coder.rb
index 5ea8cab..b2be0a4 100644
--- a/test/psych/test_coder.rb
+++ b/test/psych/test_coder.rb
@@ -112,9 +112,19 @@ module Psych
end
end
+ class CustomEncode
+ def initialize(**opts)
+ @opts = opts
+ end
+
+ def encode_with(coder)
+ @opts.each { |k,v| coder.public_send :"#{k}=", v }
+ end
+ end
+
def test_self_referential
x = Referential.new
- copy = Psych.load Psych.dump x
+ copy = Psych.unsafe_load Psych.dump x
assert_equal copy, copy.a
end
@@ -153,23 +163,23 @@ module Psych
end
def test_represent_map
- thing = Psych.load(Psych.dump(RepresentWithMap.new))
+ thing = Psych.unsafe_load(Psych.dump(RepresentWithMap.new))
assert_equal({ "string" => 'a', :symbol => 'b' }, thing.map)
end
def test_represent_sequence
- thing = Psych.load(Psych.dump(RepresentWithSeq.new))
+ thing = Psych.unsafe_load(Psych.dump(RepresentWithSeq.new))
assert_equal %w{ foo bar }, thing.seq
end
def test_represent_with_init
- thing = Psych.load(Psych.dump(RepresentWithInit.new))
+ thing = Psych.unsafe_load(Psych.dump(RepresentWithInit.new))
assert_equal 'bar', thing.str
end
def test_represent!
assert_match(/foo/, Psych.dump(Represent.new))
- assert_instance_of(Represent, Psych.load(Psych.dump(Represent.new)))
+ assert_instance_of(Represent, Psych.unsafe_load(Psych.dump(Represent.new)))
end
def test_scalar_coder
@@ -179,7 +189,7 @@ module Psych
def test_load_dumped_tagging
foo = InitApi.new
- bar = Psych.load(Psych.dump(foo))
+ bar = Psych.unsafe_load(Psych.dump(foo))
assert_equal false, bar.implicit
assert_equal "!ruby/object:Psych::TestCoder::InitApi", bar.tag
assert_equal Psych::Nodes::Mapping::BLOCK, bar.style
@@ -198,10 +208,121 @@ module Psych
def test_dump_init_with
foo = InitApi.new
- bar = Psych.load(Psych.dump(foo))
+ bar = Psych.unsafe_load(Psych.dump(foo))
assert_equal foo.a, bar.a
assert_equal foo.b, bar.b
assert_nil bar.c
end
+
+ def test_coder_style_map_default
+ foo = Psych.dump a: 1, b: 2
+ assert_equal "---\n:a: 1\n:b: 2\n", foo
+ end
+
+ def test_coder_style_map_any
+ foo = Psych.dump CustomEncode.new \
+ map: {a: 1, b: 2},
+ style: Psych::Nodes::Mapping::ANY,
+ tag: nil
+ assert_equal "---\n:a: 1\n:b: 2\n", foo
+ end
+
+ def test_coder_style_map_block
+ foo = Psych.dump CustomEncode.new \
+ map: {a: 1, b: 2},
+ style: Psych::Nodes::Mapping::BLOCK,
+ tag: nil
+ assert_equal "---\n:a: 1\n:b: 2\n", foo
+ end
+
+ def test_coder_style_map_flow
+ foo = Psych.dump CustomEncode.new \
+ map: { a: 1, b: 2 },
+ style: Psych::Nodes::Mapping::FLOW,
+ tag: nil
+ assert_equal "--- {! ':a': 1, ! ':b': 2}\n", foo
+ end
+
+ def test_coder_style_seq_default
+ foo = Psych.dump [ 1, 2, 3 ]
+ assert_equal "---\n- 1\n- 2\n- 3\n", foo
+ end
+
+ def test_coder_style_seq_any
+ foo = Psych.dump CustomEncode.new \
+ seq: [ 1, 2, 3 ],
+ style: Psych::Nodes::Sequence::ANY,
+ tag: nil
+ assert_equal "---\n- 1\n- 2\n- 3\n", foo
+ end
+
+ def test_coder_style_seq_block
+ foo = Psych.dump CustomEncode.new \
+ seq: [ 1, 2, 3 ],
+ style: Psych::Nodes::Sequence::BLOCK,
+ tag: nil
+ assert_equal "---\n- 1\n- 2\n- 3\n", foo
+ end
+
+ def test_coder_style_seq_flow
+ foo = Psych.dump CustomEncode.new \
+ seq: [ 1, 2, 3 ],
+ style: Psych::Nodes::Sequence::FLOW,
+ tag: nil
+ assert_equal "--- [1, 2, 3]\n", foo
+ end
+
+ def test_coder_style_scalar_default
+ foo = Psych.dump 'some scalar'
+ assert_match(/\A--- some scalar\n(?:\.\.\.\n)?\z/, foo)
+ end
+
+ def test_coder_style_scalar_any
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::ANY,
+ tag: nil
+ assert_match(/\A--- some scalar\n(?:\.\.\.\n)?\z/, foo)
+ end
+
+ def test_coder_style_scalar_plain
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::PLAIN,
+ tag: nil
+ assert_match(/\A--- some scalar\n(?:\.\.\.\n)?\z/, foo)
+ end
+
+ def test_coder_style_scalar_single_quoted
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::SINGLE_QUOTED,
+ tag: nil
+ assert_equal "--- ! 'some scalar'\n", foo
+ end
+
+ def test_coder_style_scalar_double_quoted
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::DOUBLE_QUOTED,
+ tag: nil
+ assert_equal %Q'--- ! "some scalar"\n', foo
+ end
+
+ def test_coder_style_scalar_literal
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::LITERAL,
+ tag: nil
+ assert_equal "--- ! |-\n some scalar\n", foo
+ end
+
+ def test_coder_style_scalar_folded
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::FOLDED,
+ tag: nil
+ assert_equal "--- ! >-\n some scalar\n", foo
+ end
end
end
diff --git a/test/psych/test_date_time.rb b/test/psych/test_date_time.rb
index f73f346..6f1e8b5 100644
--- a/test/psych/test_date_time.rb
+++ b/test/psych/test_date_time.rb
@@ -22,7 +22,7 @@ module Psych
def test_timezone_offset
times = [Time.new(2017, 4, 13, 12, 0, 0, "+09:00"),
Time.new(2017, 4, 13, 12, 0, 0, "-05:00")]
- cycled = Psych::load(Psych.dump times)
+ cycled = Psych::unsafe_load(Psych.dump times)
assert_match(/12:00:00 \+0900/, cycled.first.to_s)
assert_match(/12:00:00 -0500/, cycled.last.to_s)
end
@@ -39,7 +39,7 @@ module Psych
def test_datetime_timezone_offset
times = [DateTime.new(2017, 4, 13, 12, 0, 0, "+09:00"),
DateTime.new(2017, 4, 13, 12, 0, 0, "-05:00")]
- cycled = Psych::load(Psych.dump times)
+ cycled = Psych::unsafe_load(Psych.dump times)
assert_match(/12:00:00\+09:00/, cycled.first.to_s)
assert_match(/12:00:00-05:00/, cycled.last.to_s)
end
diff --git a/test/psych/test_deprecated.rb b/test/psych/test_deprecated.rb
index 624f437..af33799 100644
--- a/test/psych/test_deprecated.rb
+++ b/test/psych/test_deprecated.rb
@@ -41,7 +41,7 @@ module Psych
def test_recursive_quick_emit_encode_with
qeew = QuickEmitterEncodeWith.new
hash = { :qe => qeew }
- hash2 = Psych.load Psych.dump hash
+ hash2 = Psych.unsafe_load Psych.dump hash
qe = hash2[:qe]
assert_equal qeew.name, qe.name
@@ -72,7 +72,7 @@ module Psych
# receive the yaml_initialize call.
def test_yaml_initialize_and_init_with
hash = { :yi => YamlInitAndInitWith.new }
- hash2 = Psych.load Psych.dump hash
+ hash2 = Psych.unsafe_load Psych.dump hash
yi = hash2[:yi]
assert_equal 'TGIF!', yi.name
diff --git a/test/psych/test_document.rb b/test/psych/test_document.rb
index a88dd32..cf3b700 100644
--- a/test/psych/test_document.rb
+++ b/test/psych/test_document.rb
@@ -30,7 +30,7 @@ module Psych
end
def test_emit_bad_tag
- assert_raises(RuntimeError) do
+ assert_raise(RuntimeError) do
@doc.tag_directives = [['!']]
@stream.yaml
end
diff --git a/test/psych/test_emitter.rb b/test/psych/test_emitter.rb
index 52d5e9d..506d722 100644
--- a/test/psych/test_emitter.rb
+++ b/test/psych/test_emitter.rb
@@ -40,7 +40,7 @@ module Psych
end
def test_start_stream_arg_error
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@emitter.start_stream 'asdfasdf'
end
end
@@ -56,7 +56,7 @@ module Psych
[[], [nil,nil], false],
[[1,1], [[nil, "tag:TALOS"]], 0],
].each do |args|
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@emitter.start_document(*args)
end
end
@@ -73,7 +73,7 @@ module Psych
['foo', nil, nil, false, true, :foo],
[nil, nil, nil, false, true, 1],
].each do |args|
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@emitter.scalar(*args)
end
end
@@ -83,11 +83,11 @@ module Psych
@emitter.start_stream Psych::Nodes::Stream::UTF8
@emitter.start_document [], [], false
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@emitter.start_sequence(nil, Object.new, true, 1)
end
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@emitter.start_sequence(nil, nil, true, :foo)
end
end
diff --git a/test/psych/test_encoding.rb b/test/psych/test_encoding.rb
index ef66531..e5831c9 100644
--- a/test/psych/test_encoding.rb
+++ b/test/psych/test_encoding.rb
@@ -63,7 +63,7 @@ module Psych
# If the external encoding isn't utf8, utf16le, or utf16be, we cannot
# process the file.
File.open(t.path, 'r', :encoding => 'SHIFT_JIS') do |f|
- assert_raises Psych::SyntaxError do
+ assert_raise Psych::SyntaxError do
Psych.load(f)
end
end
@@ -121,7 +121,7 @@ module Psych
def test_emit_alias
@emitter.start_stream Psych::Parser::UTF8
@emitter.start_document [], [], true
- e = assert_raises(RuntimeError) do
+ e = assert_raise(RuntimeError) do
@emitter.alias 'ドラえもん'.encode('EUC-JP')
end
assert_match(/alias value/, e.message)
diff --git a/test/psych/test_exception.rb b/test/psych/test_exception.rb
index e355c26..c1e69ab 100644
--- a/test/psych/test_exception.rb
+++ b/test/psych/test_exception.rb
@@ -33,42 +33,36 @@ module Psych
def test_backtrace
err = make_ex
- new_err = Psych.load(Psych.dump(err))
+ new_err = Psych.unsafe_load(Psych.dump(err))
assert_equal err.backtrace, new_err.backtrace
end
def test_naming_exception
err = String.xxx rescue $!
- new_err = Psych.load(Psych.dump(err))
+ new_err = Psych.unsafe_load(Psych.dump(err))
assert_equal err.message, new_err.message
end
def test_load_takes_file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.load '--- `'
end
assert_nil ex.file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.load '--- `', filename: 'meow'
end
assert_equal 'meow', ex.file
-
- # deprecated interface
- ex = assert_raises(Psych::SyntaxError) do
- Psych.load '--- `', 'deprecated'
- end
- assert_equal 'deprecated', ex.file
end
def test_psych_parse_stream_takes_file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.parse_stream '--- `'
end
assert_nil ex.file
assert_match '(<unknown>)', ex.message
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.parse_stream '--- `', filename: 'omg!'
end
assert_equal 'omg!', ex.file
@@ -76,22 +70,16 @@ module Psych
end
def test_load_stream_takes_file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.load_stream '--- `'
end
assert_nil ex.file
assert_match '(<unknown>)', ex.message
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.load_stream '--- `', filename: 'omg!'
end
assert_equal 'omg!', ex.file
-
- # deprecated interface
- ex = assert_raises(Psych::SyntaxError) do
- Psych.load_stream '--- `', 'deprecated'
- end
- assert_equal 'deprecated', ex.file
end
def test_parse_file_exception
@@ -99,7 +87,7 @@ module Psych
t.binmode
t.write '--- `'
t.close
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.parse_file t.path
end
assert_equal t.path, ex.file
@@ -111,34 +99,40 @@ module Psych
t.binmode
t.write '--- `'
t.close
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.load_file t.path
end
assert_equal t.path, ex.file
}
end
+ def test_safe_load_file_exception
+ Tempfile.create(['loadfile', 'yml']) {|t|
+ t.binmode
+ t.write '--- `'
+ t.close
+ ex = assert_raise(Psych::SyntaxError) do
+ Psych.safe_load_file t.path
+ end
+ assert_equal t.path, ex.file
+ }
+ end
+
def test_psych_parse_takes_file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.parse '--- `'
end
assert_match '(<unknown>)', ex.message
assert_nil ex.file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.parse '--- `', filename: 'omg!'
end
assert_match 'omg!', ex.message
-
- # deprecated interface
- ex = assert_raises(Psych::SyntaxError) do
- Psych.parse '--- `', 'deprecated'
- end
- assert_match 'deprecated', ex.message
end
def test_attributes
- e = assert_raises(Psych::SyntaxError) {
+ e = assert_raise(Psych::SyntaxError) {
Psych.load '--- `foo'
}
@@ -153,7 +147,7 @@ module Psych
end
def test_convert
- w = Psych.load(Psych.dump(@wups))
+ w = Psych.unsafe_load(Psych.dump(@wups))
assert_equal @wups.message, w.message
assert_equal @wups.backtrace, w.backtrace
assert_equal 1, w.foo
diff --git a/test/psych/test_hash.rb b/test/psych/test_hash.rb
index ba11b82..5374781 100644
--- a/test/psych/test_hash.rb
+++ b/test/psych/test_hash.rb
@@ -39,7 +39,7 @@ module Psych
def test_hash_with_ivar
t1 = HashWithIvar.new
t1[:foo] = :bar
- t2 = Psych.load(Psych.dump(t1))
+ t2 = Psych.unsafe_load(Psych.dump(t1))
assert_equal t1, t2
assert_cycle t1
end
@@ -54,14 +54,14 @@ module Psych
def test_custom_initialized
a = [1,2,3,4,5]
t1 = HashWithCustomInit.new(a)
- t2 = Psych.load(Psych.dump(t1))
+ t2 = Psych.unsafe_load(Psych.dump(t1))
assert_equal t1, t2
assert_cycle t1
end
def test_custom_initialize_no_ivar
t1 = HashWithCustomInitNoIvar.new(nil)
- t2 = Psych.load(Psych.dump(t1))
+ t2 = Psych.unsafe_load(Psych.dump(t1))
assert_equal t1, t2
assert_cycle t1
end
@@ -70,25 +70,25 @@ module Psych
x = X.new
x[:a] = 'b'
x.instance_variable_set :@foo, 'bar'
- dup = Psych.load Psych.dump x
+ dup = Psych.unsafe_load Psych.dump x
assert_cycle x
assert_equal 'bar', dup.instance_variable_get(:@foo)
assert_equal X, dup.class
end
def test_load_with_class_syck_compatibility
- hash = Psych.load "--- !ruby/object:Hash\n:user_id: 7\n:username: Lucas\n"
+ hash = Psych.unsafe_load "--- !ruby/object:Hash\n:user_id: 7\n:username: Lucas\n"
assert_equal({ user_id: 7, username: 'Lucas'}, hash)
end
def test_empty_subclass
assert_match "!ruby/hash:#{X}", Psych.dump(X.new)
- x = Psych.load Psych.dump X.new
+ x = Psych.unsafe_load Psych.dump X.new
assert_equal X, x.class
end
def test_map
- x = Psych.load "--- !map:#{X} { }\n"
+ x = Psych.unsafe_load "--- !map:#{X} { }\n"
assert_equal X, x.class
end
@@ -102,7 +102,7 @@ module Psych
end
def test_ref_append
- hash = Psych.load(<<-eoyml)
+ hash = Psych.unsafe_load(<<-eoyml)
---
foo: &foo
hello: world
@@ -114,7 +114,7 @@ eoyml
def test_key_deduplication
unless String.method_defined?(:-@) && (-("a" * 20)).equal?((-("a" * 20)))
- skip "This Ruby implementation doesn't support string deduplication"
+ pend "This Ruby implementation doesn't support string deduplication"
end
hashes = Psych.load(<<-eoyml)
diff --git a/test/psych/test_marshalable.rb b/test/psych/test_marshalable.rb
index b1f4a83..74ee902 100644
--- a/test/psych/test_marshalable.rb
+++ b/test/psych/test_marshalable.rb
@@ -6,7 +6,7 @@ module Psych
class TestMarshalable < TestCase
def test_objects_defining_marshal_dump_and_marshal_load_can_be_dumped
sd = SimpleDelegator.new(1)
- loaded = Psych.load(Psych.dump(sd))
+ loaded = Psych.unsafe_load(Psych.dump(sd))
assert_instance_of(SimpleDelegator, loaded)
assert_equal(sd, loaded)
@@ -46,7 +46,15 @@ module Psych
def test_init_with_takes_priority_over_marshal_methods
obj = PsychCustomMarshalable.new(1)
- loaded = Psych.load(Psych.dump(obj))
+ loaded = Psych.unsafe_load(Psych.dump(obj))
+
+ assert(PsychCustomMarshalable === loaded)
+ assert_equal(2, loaded.foo)
+ end
+
+ def test_init_symbolize_names
+ obj = PsychCustomMarshalable.new(1)
+ loaded = Psych.unsafe_load(Psych.dump(obj), symbolize_names: true)
assert(PsychCustomMarshalable === loaded)
assert_equal(2, loaded.foo)
diff --git a/test/psych/test_merge_keys.rb b/test/psych/test_merge_keys.rb
index 08ffe58..dcf4f1f 100644
--- a/test/psych/test_merge_keys.rb
+++ b/test/psych/test_merge_keys.rb
@@ -34,7 +34,7 @@ map:
end
def test_explicit_string
- doc = Psych.load <<-eoyml
+ doc = Psych.unsafe_load <<-eoyml
a: &me { hello: world }
b: { !!str '<<': *me }
eoyml
@@ -55,7 +55,7 @@ product:
!ruby/object:#{Product.name}
<<: *foo
eoyml
- hash = Psych.load s
+ hash = Psych.unsafe_load s
assert_equal({"bar" => 10}, hash["foo"])
product = hash["product"]
assert_equal 10, product.bar
@@ -67,7 +67,7 @@ defaults: &defaults
development:
<<: *defaults
eoyml
- assert_equal({'<<' => nil }, Psych.load(yaml)['development'])
+ assert_equal({'<<' => nil }, Psych.unsafe_load(yaml)['development'])
end
def test_merge_array
@@ -77,7 +77,7 @@ foo: &hello
baz:
<<: *hello
eoyml
- assert_equal({'<<' => [1]}, Psych.load(yaml)['baz'])
+ assert_equal({'<<' => [1]}, Psych.unsafe_load(yaml)['baz'])
end
def test_merge_is_not_partial
@@ -89,9 +89,9 @@ foo: &hello
baz:
<<: [*hello, *default]
eoyml
- doc = Psych.load yaml
+ doc = Psych.unsafe_load yaml
refute doc['baz'].key? 'hello'
- assert_equal({'<<' => [[1], {"hello"=>"world"}]}, Psych.load(yaml)['baz'])
+ assert_equal({'<<' => [[1], {"hello"=>"world"}]}, Psych.unsafe_load(yaml)['baz'])
end
def test_merge_seq_nil
@@ -100,7 +100,7 @@ foo: &hello
baz:
<<: [*hello]
eoyml
- assert_equal({'<<' => [nil]}, Psych.load(yaml)['baz'])
+ assert_equal({'<<' => [nil]}, Psych.unsafe_load(yaml)['baz'])
end
def test_bad_seq_merge
@@ -109,7 +109,7 @@ defaults: &defaults [1, 2, 3]
development:
<<: *defaults
eoyml
- assert_equal({'<<' => [1,2,3]}, Psych.load(yaml)['development'])
+ assert_equal({'<<' => [1,2,3]}, Psych.unsafe_load(yaml)['development'])
end
def test_missing_merge_key
@@ -117,7 +117,7 @@ development:
bar:
<< : *foo
eoyml
- exp = assert_raises(Psych::BadAlias) { Psych.load yaml }
+ exp = assert_raise(Psych::BadAlias) { Psych.load yaml }
assert_match 'foo', exp.message
end
@@ -134,7 +134,7 @@ bar:
hash = {
"foo" => { "hello" => "world"},
"bar" => { "hello" => "world", "baz" => "boo" } }
- assert_equal hash, Psych.load(yaml)
+ assert_equal hash, Psych.unsafe_load(yaml)
end
def test_multiple_maps
@@ -159,7 +159,7 @@ bar:
'label' => 'center/big'
}
- assert_equal hash, Psych.load(yaml)[4]
+ assert_equal hash, Psych.unsafe_load(yaml)[4]
end
def test_override
@@ -185,7 +185,7 @@ bar:
'label' => 'center/big'
}
- assert_equal hash, Psych.load(yaml)[4]
+ assert_equal hash, Psych.unsafe_load(yaml)[4]
end
end
end
diff --git a/test/psych/test_numeric.rb b/test/psych/test_numeric.rb
index db99a2a..8c3dcd1 100644
--- a/test/psych/test_numeric.rb
+++ b/test/psych/test_numeric.rb
@@ -33,6 +33,7 @@ module Psych
def test_big_decimal_round_trip
decimal = BigDecimal("12.34")
+ $DEBUG = false
assert_cycle decimal
end
diff --git a/test/psych/test_object.rb b/test/psych/test_object.rb
index f1c6145..0faf6b2 100644
--- a/test/psych/test_object.rb
+++ b/test/psych/test_object.rb
@@ -28,7 +28,7 @@ module Psych
def test_tag_round_trip
tag = Tagged.new
- tag2 = Psych.load(Psych.dump(tag))
+ tag2 = Psych.unsafe_load(Psych.dump(tag))
assert_equal tag.baz, tag2.baz
assert_instance_of(Tagged, tag2)
end
@@ -36,7 +36,7 @@ module Psych
def test_cyclic_references
foo = Foo.new(nil)
foo.parent = foo
- loaded = Psych.load Psych.dump foo
+ loaded = Psych.unsafe_load Psych.dump foo
assert_instance_of(Foo, loaded)
assert_equal loaded, loaded.parent
diff --git a/test/psych/test_object_references.rb b/test/psych/test_object_references.rb
index ca69c7d..269d722 100644
--- a/test/psych/test_object_references.rb
+++ b/test/psych/test_object_references.rb
@@ -34,12 +34,16 @@ module Psych
def assert_reference_trip obj
yml = Psych.dump([obj, obj])
assert_match(/\*-?\d+/, yml)
- data = Psych.load yml
+ begin
+ data = Psych.load yml
+ rescue Psych::DisallowedClass
+ data = Psych.unsafe_load yml
+ end
assert_equal data.first.object_id, data.last.object_id
end
def test_float_references
- data = Psych.load <<-eoyml
+ data = Psych.unsafe_load <<-eoyml
---\s
- &name 1.2
- *name
@@ -49,7 +53,7 @@ module Psych
end
def test_binary_references
- data = Psych.load <<-eoyml
+ data = Psych.unsafe_load <<-eoyml
---
- &name !binary |-
aGVsbG8gd29ybGQh
@@ -60,7 +64,7 @@ module Psych
end
def test_regexp_references
- data = Psych.load <<-eoyml
+ data = Psych.unsafe_load <<-eoyml
---\s
- &name !ruby/regexp /pattern/i
- *name
diff --git a/test/psych/test_omap.rb b/test/psych/test_omap.rb
index 98636de..6de0286 100644
--- a/test/psych/test_omap.rb
+++ b/test/psych/test_omap.rb
@@ -4,7 +4,7 @@ require_relative 'helper'
module Psych
class TestOmap < TestCase
def test_parse_as_map
- o = Psych.load "--- !!omap\na: 1\nb: 2"
+ o = Psych.unsafe_load "--- !!omap\na: 1\nb: 2"
assert_kind_of Psych::Omap, o
assert_equal 1, o['a']
assert_equal 2, o['b']
@@ -14,7 +14,7 @@ module Psych
map = Psych::Omap.new
map['foo'] = 'bar'
map['self'] = map
- assert_equal(map, Psych.load(Psych.dump(map)))
+ assert_equal(map, Psych.unsafe_load(Psych.dump(map)))
end
def test_keys
diff --git a/test/psych/test_parser.rb b/test/psych/test_parser.rb
index e8225da..3604e7c 100644
--- a/test/psych/test_parser.rb
+++ b/test/psych/test_parser.rb
@@ -63,7 +63,7 @@ module Psych
parser = Psych::Parser.new klass.new
2.times {
- assert_raises(RuntimeError, method.to_s) do
+ assert_raise(RuntimeError, method.to_s) do
parser.parse yaml
end
}
@@ -77,7 +77,7 @@ module Psych
end
def test_filename
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
@parser.parse '--- `', 'omg!'
end
assert_match 'omg!', ex.message
@@ -180,7 +180,7 @@ module Psych
def o.external_encoding; nil end
def o.read len; self end
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@parser.parse o
end
end
@@ -193,23 +193,23 @@ module Psych
end
def test_syntax_error
- assert_raises(Psych::SyntaxError) do
+ assert_raise(Psych::SyntaxError) do
@parser.parse("---\n\"foo\"\n\"bar\"\n")
end
end
def test_syntax_error_twice
- assert_raises(Psych::SyntaxError) do
+ assert_raise(Psych::SyntaxError) do
@parser.parse("---\n\"foo\"\n\"bar\"\n")
end
- assert_raises(Psych::SyntaxError) do
+ assert_raise(Psych::SyntaxError) do
@parser.parse("---\n\"foo\"\n\"bar\"\n")
end
end
def test_syntax_error_has_path_for_string
- e = assert_raises(Psych::SyntaxError) do
+ e = assert_raise(Psych::SyntaxError) do
@parser.parse("---\n\"foo\"\n\"bar\"\n")
end
assert_match '(<unknown>):', e.message
@@ -219,7 +219,7 @@ module Psych
io = StringIO.new "---\n\"foo\"\n\"bar\"\n"
def io.path; "hello!"; end
- e = assert_raises(Psych::SyntaxError) do
+ e = assert_raise(Psych::SyntaxError) do
@parser.parse(io)
end
assert_match "(#{io.path}):", e.message
diff --git a/test/psych/test_psych.rb b/test/psych/test_psych.rb
index 55d9f19..1abd69c 100644
--- a/test/psych/test_psych.rb
+++ b/test/psych/test_psych.rb
@@ -16,7 +16,7 @@ class TestPsych < Psych::TestCase
end
def test_line_width_invalid
- assert_raises(ArgumentError) { Psych.dump('x', { :line_width => -2 }) }
+ assert_raise(ArgumentError) { Psych.dump('x', { :line_width => -2 }) }
end
def test_line_width_no_limit
@@ -61,7 +61,7 @@ class TestPsych < Psych::TestCase
end
def test_load_argument_error
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
Psych.load nil
end
end
@@ -75,16 +75,12 @@ class TestPsych < Psych::TestCase
end
def test_parse_raises_on_bad_input
- assert_raises(Psych::SyntaxError) { Psych.parse("--- `") }
- end
-
- def test_parse_with_fallback
- assert_equal 42, Psych.parse("", fallback: 42)
+ assert_raise(Psych::SyntaxError) { Psych.parse("--- `") }
end
def test_non_existing_class_on_deserialize
- e = assert_raises(ArgumentError) do
- Psych.load("--- !ruby/object:NonExistent\nfoo: 1")
+ e = assert_raise(ArgumentError) do
+ Psych.unsafe_load("--- !ruby/object:NonExistent\nfoo: 1")
end
assert_equal 'undefined class/module NonExistent', e.message
end
@@ -125,12 +121,25 @@ class TestPsych < Psych::TestCase
assert_equal %w{ foo bar }, docs
end
+ def test_load_stream_freeze
+ docs = Psych.load_stream("--- foo\n...\n--- bar\n...", freeze: true)
+ assert_equal %w{ foo bar }, docs
+ docs.each do |string|
+ assert_predicate string, :frozen?
+ end
+ end
+
+ def test_load_stream_symbolize_names
+ docs = Psych.load_stream("---\nfoo: bar", symbolize_names: true)
+ assert_equal [{foo: 'bar'}], docs
+ end
+
def test_load_stream_default_fallback
assert_equal [], Psych.load_stream("")
end
def test_load_stream_raises_on_bad_input
- assert_raises(Psych::SyntaxError) { Psych.load_stream("--- `") }
+ assert_raise(Psych::SyntaxError) { Psych.load_stream("--- `") }
end
def test_parse_stream
@@ -162,7 +171,7 @@ class TestPsych < Psych::TestCase
end
def test_parse_stream_raises_on_bad_input
- assert_raises(Psych::SyntaxError) { Psych.parse_stream("--- `") }
+ assert_raise(Psych::SyntaxError) { Psych.parse_stream("--- `") }
end
def test_add_builtin_type
@@ -201,7 +210,7 @@ class TestPsych < Psych::TestCase
def test_load_freeze_deduplication
unless String.method_defined?(:-@) && (-("a" * 20)).equal?((-("a" * 20)))
- skip "This Ruby implementation doesn't support string deduplication"
+ pend "This Ruby implementation doesn't support string deduplication"
end
data = Psych.load("--- ['a']", freeze: true)
@@ -209,28 +218,28 @@ class TestPsych < Psych::TestCase
end
def test_load_default_fallback
- assert_equal false, Psych.load("")
+ assert_equal false, Psych.unsafe_load("")
end
def test_load_with_fallback
- assert_equal 42, Psych.load("", "file", fallback: 42)
+ assert_equal 42, Psych.load("", filename: "file", fallback: 42)
end
def test_load_with_fallback_nil_or_false
- assert_nil Psych.load("", "file", fallback: nil)
- assert_equal false, Psych.load("", "file", fallback: false)
+ assert_nil Psych.load("", filename: "file", fallback: nil)
+ assert_equal false, Psych.load("", filename: "file", fallback: false)
end
def test_load_with_fallback_hash
- assert_equal Hash.new, Psych.load("", "file", fallback: Hash.new)
+ assert_equal Hash.new, Psych.load("", filename: "file", fallback: Hash.new)
end
def test_load_with_fallback_for_nil
- assert_nil Psych.load("--- null", "file", fallback: 42)
+ assert_nil Psych.unsafe_load("--- null", filename: "file", fallback: 42)
end
def test_load_with_fallback_for_false
- assert_equal false, Psych.load("--- false", "file", fallback: 42)
+ assert_equal false, Psych.unsafe_load("--- false", filename: "file", fallback: 42)
end
def test_load_file
@@ -242,9 +251,30 @@ class TestPsych < Psych::TestCase
}
end
+ def test_load_file_freeze
+ Tempfile.create(['yikes', 'yml']) {|t|
+ t.binmode
+ t.write('--- hello world')
+ t.close
+
+ object = Psych.load_file(t.path, freeze: true)
+ assert_predicate object, :frozen?
+ }
+ end
+
+ def test_load_file_symbolize_names
+ Tempfile.create(['yikes', 'yml']) {|t|
+ t.binmode
+ t.write("---\nfoo: bar")
+ t.close
+
+ assert_equal({foo: 'bar'}, Psych.load_file(t.path, symbolize_names: true))
+ }
+ end
+
def test_load_file_default_fallback
Tempfile.create(['empty', 'yml']) {|t|
- assert_equal false, Psych.load_file(t.path)
+ assert_equal false, Psych.unsafe_load_file(t.path)
}
end
@@ -285,6 +315,18 @@ class TestPsych < Psych::TestCase
}
end
+ def test_safe_load_file_with_permitted_classe
+ Tempfile.create(['false', 'yml']) {|t|
+ t.binmode
+ t.write("--- !ruby/range\nbegin: 0\nend: 42\nexcl: false\n")
+ t.close
+ assert_equal 0..42, Psych.safe_load_file(t.path, permitted_classes: [Range])
+ assert_raise(Psych::DisallowedClass) {
+ Psych.safe_load_file(t.path)
+ }
+ }
+ end
+
def test_parse_file
Tempfile.create(['yikes', 'yml']) {|t|
t.binmode
@@ -301,9 +343,9 @@ class TestPsych < Psych::TestCase
end
def test_degenerate_strings
- assert_equal false, Psych.load(' ')
+ assert_equal false, Psych.unsafe_load(' ')
assert_equal false, Psych.parse(' ')
- assert_equal false, Psych.load('')
+ assert_equal false, Psych.unsafe_load('')
assert_equal false, Psych.parse('')
end
@@ -325,17 +367,75 @@ class TestPsych < Psych::TestCase
yaml = <<-eoyml
foo:
bar: baz
+ 1: 2
hoge:
- fuga: piyo
eoyml
result = Psych.load(yaml)
- assert_equal result, { "foo" => { "bar" => "baz"}, "hoge" => [{ "fuga" => "piyo" }] }
+ assert_equal result, { "foo" => { "bar" => "baz", 1 => 2 }, "hoge" => [{ "fuga" => "piyo" }] }
result = Psych.load(yaml, symbolize_names: true)
- assert_equal result, { foo: { bar: "baz" }, hoge: [{ fuga: "piyo" }] }
+ assert_equal result, { foo: { bar: "baz", 1 => 2 }, hoge: [{ fuga: "piyo" }] }
result = Psych.safe_load(yaml, symbolize_names: true)
- assert_equal result, { foo: { bar: "baz" }, hoge: [{ fuga: "piyo" }] }
+ assert_equal result, { foo: { bar: "baz", 1 => 2 }, hoge: [{ fuga: "piyo" }] }
+ end
+
+ def test_safe_dump_defaults
+ yaml = <<-eoyml
+---
+array:
+- 1
+float: 13.12
+booleans:
+- true
+- false
+eoyml
+
+ payload = Psych.safe_dump({
+ "array" => [1],
+ "float" => 13.12,
+ "booleans" => [true, false],
+ })
+ assert_equal yaml, payload
+ end
+
+ def test_safe_dump_unpermitted_class
+ error = assert_raise Psych::DisallowedClass do
+ Psych.safe_dump(Object.new)
+ end
+ assert_equal "Tried to dump unspecified class: Object", error.message
+
+ hash_subclass = Class.new(Hash)
+ error = assert_raise Psych::DisallowedClass do
+ Psych.safe_dump(hash_subclass.new)
+ end
+ assert_equal "Tried to dump unspecified class: #{hash_subclass.inspect}", error.message
end
+
+ def test_safe_dump_extra_permitted_classes
+ assert_equal "--- !ruby/object {}\n", Psych.safe_dump(Object.new, permitted_classes: [Object])
+ end
+
+ def test_safe_dump_symbols
+ error = assert_raise Psych::DisallowedClass do
+ Psych.safe_dump(:foo, permitted_classes: [Symbol])
+ end
+ assert_equal "Tried to dump unspecified class: Symbol(:foo)", error.message
+
+ assert_match(/\A--- :foo\n(?:\.\.\.\n)?\z/, Psych.safe_dump(:foo, permitted_classes: [Symbol], permitted_symbols: [:foo]))
+ end
+
+ def test_safe_dump_aliases
+ x = []
+ x << x
+ error = assert_raise Psych::BadAlias do
+ Psych.safe_dump(x)
+ end
+ assert_equal "Tried to dump an aliased object", error.message
+
+ assert_equal "--- &1\n" + "- *1\n", Psych.safe_dump(x, aliases: true)
+ end
+
end
diff --git a/test/psych/test_ractor.rb b/test/psych/test_ractor.rb
new file mode 100644
index 0000000..1b0d810
--- /dev/null
+++ b/test/psych/test_ractor.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+require_relative 'helper'
+
+class TestPsychRactor < Test::Unit::TestCase
+ def test_ractor_round_trip
+ assert_ractor(<<~RUBY, require_relative: 'helper')
+ obj = {foo: [42]}
+ obj2 = Ractor.new(obj) do |obj|
+ Psych.unsafe_load(Psych.dump(obj))
+ end.take
+ assert_equal obj, obj2
+ RUBY
+ end
+
+ def test_not_shareable
+ # There's no point in making these frozen / shareable
+ # and the C-ext disregards begin frozen
+ assert_ractor(<<~RUBY, require_relative: 'helper')
+ parser = Psych::Parser.new
+ emitter = Psych::Emitter.new(nil)
+ assert_raise(Ractor::Error) { Ractor.make_shareable(parser) }
+ assert_raise(Ractor::Error) { Ractor.make_shareable(emitter) }
+ RUBY
+ end
+
+ def test_ractor_config
+ # Config is ractor-local
+ # Test is to make sure it works, even though usage is probably very low.
+ # The methods are not documented and might be deprecated one day
+ assert_ractor(<<~RUBY, require_relative: 'helper')
+ r = Ractor.new do
+ Psych.add_builtin_type 'omap' do |type, val|
+ val * 2
+ end
+ Psych.load('--- !!omap hello')
+ end.take
+ assert_equal 'hellohello', r
+ assert_equal 'hello', Psych.load('--- !!omap hello')
+ RUBY
+ end
+
+ def test_ractor_constants
+ assert_ractor(<<~RUBY, require_relative: 'helper')
+ r = Ractor.new do
+ Psych.libyaml_version.join('.') == Psych::LIBYAML_VERSION
+ end.take
+ assert_equal true, r
+ RUBY
+ end
+end if defined?(Ractor)
diff --git a/test/psych/test_safe_load.rb b/test/psych/test_safe_load.rb
index e397271..b52d604 100644
--- a/test/psych/test_safe_load.rb
+++ b/test/psych/test_safe_load.rb
@@ -22,7 +22,7 @@ module Psych
def test_no_recursion
x = []
x << x
- assert_raises(Psych::BadAlias) do
+ assert_raise(Psych::BadAlias) do
Psych.safe_load Psych.dump(x)
end
end
@@ -31,13 +31,11 @@ module Psych
x = []
x << x
assert_equal(x, Psych.safe_load(Psych.dump(x), permitted_classes: [], permitted_symbols: [], aliases: true))
- # deprecated interface
- assert_equal(x, Psych.safe_load(Psych.dump(x), [], [], true))
end
def test_permitted_symbol
yml = Psych.dump :foo
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load yml
end
assert_equal(
@@ -48,55 +46,36 @@ module Psych
permitted_symbols: [:foo]
)
)
-
- # deprecated interface
- assert_equal(:foo, Psych.safe_load(yml, [Symbol], [:foo]))
end
def test_symbol
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
assert_safe_cycle :foo
end
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load '--- !ruby/symbol foo', permitted_classes: []
end
- # deprecated interface
- assert_raises(Psych::DisallowedClass) do
- Psych.safe_load '--- !ruby/symbol foo', []
- end
-
assert_safe_cycle :foo, permitted_classes: [Symbol]
assert_safe_cycle :foo, permitted_classes: %w{ Symbol }
assert_equal :foo, Psych.safe_load('--- !ruby/symbol foo', permitted_classes: [Symbol])
-
- # deprecated interface
- assert_equal :foo, Psych.safe_load('--- !ruby/symbol foo', [Symbol])
end
def test_foo
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load '--- !ruby/object:Foo {}', permitted_classes: [Foo]
end
- # deprecated interface
- assert_raises(Psych::DisallowedClass) do
- Psych.safe_load '--- !ruby/object:Foo {}', [Foo]
- end
-
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
assert_safe_cycle Foo.new
end
assert_kind_of(Foo, Psych.safe_load(Psych.dump(Foo.new), permitted_classes: [Foo]))
-
- # deprecated interface
- assert_kind_of(Foo, Psych.safe_load(Psych.dump(Foo.new), [Foo]))
end
X = Struct.new(:x)
def test_struct_depends_on_sym
assert_safe_cycle(X.new, permitted_classes: [X, Symbol])
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
cycle X.new, permitted_classes: [X]
end
end
@@ -107,14 +86,14 @@ module Psych
foo: bar
eoyml
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load(<<-eoyml, permitted_classes: [Struct])
--- !ruby/struct
foo: bar
eoyml
end
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load(<<-eoyml, permitted_classes: [Symbol])
--- !ruby/struct
foo: bar
@@ -122,27 +101,6 @@ module Psych
end
end
- def test_deprecated_anon_struct
- assert Psych.safe_load(<<-eoyml, [Struct, Symbol])
---- !ruby/struct
- foo: bar
- eoyml
-
- assert_raises(Psych::DisallowedClass) do
- Psych.safe_load(<<-eoyml, [Struct])
---- !ruby/struct
- foo: bar
- eoyml
- end
-
- assert_raises(Psych::DisallowedClass) do
- Psych.safe_load(<<-eoyml, [Symbol])
---- !ruby/struct
- foo: bar
- eoyml
- end
- end
-
def test_safe_load_default_fallback
assert_nil Psych.safe_load("")
end
@@ -152,15 +110,13 @@ module Psych
end
def test_safe_load_raises_on_bad_input
- assert_raises(Psych::SyntaxError) { Psych.safe_load("--- `") }
+ assert_raise(Psych::SyntaxError) { Psych.safe_load("--- `") }
end
private
def cycle object, permitted_classes: []
Psych.safe_load(Psych.dump(object), permitted_classes: permitted_classes)
- # deprecated interface test
- Psych.safe_load(Psych.dump(object), permitted_classes)
end
def assert_safe_cycle object, permitted_classes: []
diff --git a/test/psych/test_scalar_scanner.rb b/test/psych/test_scalar_scanner.rb
index ec67a33..cac8b8f 100644
--- a/test/psych/test_scalar_scanner.rb
+++ b/test/psych/test_scalar_scanner.rb
@@ -115,7 +115,15 @@ module Psych
end
def test_scan_strings_starting_with_underscores
- assert_equal "_100", ss.tokenize('_100')
+ assert_equal '_100', ss.tokenize('_100')
+ end
+
+ def test_scan_strings_starting_with_number
+ assert_equal '450D', ss.tokenize('450D')
+ end
+
+ def test_scan_strings_ending_with_underscores
+ assert_equal '100_', ss.tokenize('100_')
end
def test_scan_int_commas_and_underscores
@@ -124,7 +132,10 @@ module Psych
assert_equal 123_456_789, ss.tokenize('123_456_789')
assert_equal 123_456_789, ss.tokenize('123,456,789')
assert_equal 123_456_789, ss.tokenize('1_2,3,4_5,6_789')
- assert_equal 123_456_789, ss.tokenize('1_2,3,4_5,6_789_')
+
+ assert_equal 1, ss.tokenize('1')
+ assert_equal 1, ss.tokenize('+1')
+ assert_equal -1, ss.tokenize('-1')
assert_equal 0b010101010, ss.tokenize('0b010101010')
assert_equal 0b010101010, ss.tokenize('0b0,1_0,1_,0,1_01,0')
diff --git a/test/psych/test_serialize_subclasses.rb b/test/psych/test_serialize_subclasses.rb
index 8e1d0d3..344c79b 100644
--- a/test/psych/test_serialize_subclasses.rb
+++ b/test/psych/test_serialize_subclasses.rb
@@ -17,7 +17,7 @@ module Psych
def test_some_object
so = SomeObject.new('foo', [1,2,3])
- assert_equal so, Psych.load(Psych.dump(so))
+ assert_equal so, Psych.unsafe_load(Psych.dump(so))
end
class StructSubclass < Struct.new(:foo)
@@ -33,7 +33,7 @@ module Psych
def test_struct_subclass
so = StructSubclass.new('foo', [1,2,3])
- assert_equal so, Psych.load(Psych.dump(so))
+ assert_equal so, Psych.unsafe_load(Psych.dump(so))
end
end
end
diff --git a/test/psych/test_set.rb b/test/psych/test_set.rb
index 5690957..87944d8 100644
--- a/test/psych/test_set.rb
+++ b/test/psych/test_set.rb
@@ -21,7 +21,7 @@ module Psych
###
# FIXME: Syck should also support !!set as shorthand
def test_load_from_yaml
- loaded = Psych.load(<<-eoyml)
+ loaded = Psych.unsafe_load(<<-eoyml)
--- !set
foo: bar
bar: baz
@@ -30,11 +30,11 @@ bar: baz
end
def test_loaded_class
- assert_instance_of(Psych::Set, Psych.load(Psych.dump(@set)))
+ assert_instance_of(Psych::Set, Psych.unsafe_load(Psych.dump(@set)))
end
def test_set_shorthand
- loaded = Psych.load(<<-eoyml)
+ loaded = Psych.unsafe_load(<<-eoyml)
--- !!set
foo: bar
bar: baz
diff --git a/test/psych/test_string.rb b/test/psych/test_string.rb
index 973f38b..20ab79c 100644
--- a/test/psych/test_string.rb
+++ b/test/psych/test_string.rb
@@ -104,7 +104,7 @@ module Psych
end
def test_string_subclass_with_anchor
- y = Psych.load <<-eoyml
+ y = Psych.unsafe_load <<-eoyml
---
body:
string: &70121654388580 !ruby/string
@@ -116,7 +116,7 @@ body:
end
def test_self_referential_string
- y = Psych.load <<-eoyml
+ y = Psych.unsafe_load <<-eoyml
---
string: &70121654388580 !ruby/string
str: ! 'foo'
@@ -129,32 +129,32 @@ string: &70121654388580 !ruby/string
end
def test_another_subclass_with_attributes
- y = Psych.load Psych.dump Y.new("foo").tap {|o| o.val = 1}
+ y = Psych.unsafe_load Psych.dump Y.new("foo").tap {|o| o.val = 1}
assert_equal "foo", y
assert_equal Y, y.class
assert_equal 1, y.val
end
def test_backwards_with_syck
- x = Psych.load "--- !str:#{X.name} foo\n\n"
+ x = Psych.unsafe_load "--- !str:#{X.name} foo\n\n"
assert_equal X, x.class
assert_equal 'foo', x
end
def test_empty_subclass
assert_match "!ruby/string:#{X}", Psych.dump(X.new)
- x = Psych.load Psych.dump X.new
+ x = Psych.unsafe_load Psych.dump X.new
assert_equal X, x.class
end
def test_empty_character_subclass
assert_match "!ruby/string:#{Z}", Psych.dump(Z.new)
- x = Psych.load Psych.dump Z.new
+ x = Psych.unsafe_load Psych.dump Z.new
assert_equal Z, x.class
end
def test_subclass_with_attributes
- y = Psych.load Psych.dump Y.new.tap {|o| o.val = 1}
+ y = Psych.unsafe_load Psych.dump Y.new.tap {|o| o.val = 1}
assert_equal Y, y.class
assert_equal 1, y.val
end
diff --git a/test/psych/test_struct.rb b/test/psych/test_struct.rb
index 721df44..1479798 100644
--- a/test/psych/test_struct.rb
+++ b/test/psych/test_struct.rb
@@ -22,7 +22,7 @@ module Psych
ss = StructSubclass.new(nil, 'foo')
ss.foo = ss
- loaded = Psych.load(Psych.dump(ss))
+ loaded = Psych.unsafe_load(Psych.dump(ss))
assert_instance_of(StructSubclass, loaded.foo)
assert_equal(ss, loaded)
@@ -30,14 +30,14 @@ module Psych
def test_roundtrip
thing = PsychStructWithIvar.new('bar')
- struct = Psych.load(Psych.dump(thing))
+ struct = Psych.unsafe_load(Psych.dump(thing))
assert_equal 'hello', struct.bar
assert_equal 'bar', struct.foo
end
def test_load
- obj = Psych.load(<<-eoyml)
+ obj = Psych.unsafe_load(<<-eoyml)
--- !ruby/struct:PsychStructWithIvar
:foo: bar
:@bar: hello
diff --git a/test/psych/test_yaml.rb b/test/psych/test_yaml.rb
index 84cbe26..e12b976 100644
--- a/test/psych/test_yaml.rb
+++ b/test/psych/test_yaml.rb
@@ -17,7 +17,7 @@ class Psych_Unit_Tests < Psych::TestCase
end
def test_y_method
- assert_raises(NoMethodError) do
+ assert_raise(NoMethodError) do
OpenStruct.new.y 1
end
end
@@ -573,7 +573,7 @@ EOY
end
def test_spec_root_mapping
- y = Psych::load( <<EOY
+ y = Psych::unsafe_load( <<EOY
# This stream is an example of a top-level mapping.
invoice : 34843
date : 2001-01-23
@@ -1077,7 +1077,7 @@ EOY
# Read Psych dumped by the ruby 1.8.3.
assert_to_yaml( Rational(1, 2), "!ruby/object:Rational 1/2\n" )
- assert_raises( ArgumentError ) { Psych.load("!ruby/object:Rational INVALID/RATIONAL\n") }
+ assert_raise( ArgumentError ) { Psych.unsafe_load("!ruby/object:Rational INVALID/RATIONAL\n") }
end
def test_ruby_complex
@@ -1089,7 +1089,7 @@ EOY
# Read Psych dumped by the ruby 1.8.3.
assert_to_yaml( Complex(3, 4), "!ruby/object:Complex 3+4i\n" )
- assert_raises( ArgumentError ) { Psych.load("!ruby/object:Complex INVALID+COMPLEXi\n") }
+ assert_raise( ArgumentError ) { Psych.unsafe_load("!ruby/object:Complex INVALID+COMPLEXi\n") }
end
def test_emitting_indicators
@@ -1209,7 +1209,7 @@ EOY
def test_circular_references
a = []; a[0] = a; a[1] = a
inspect_str = "[[...], [...]]"
- assert_equal( inspect_str, Psych::load(Psych.dump(a)).inspect )
+ assert_equal( inspect_str, Psych::unsafe_load(Psych.dump(a)).inspect )
end
#
@@ -1264,11 +1264,11 @@ EOY
end
def test_date_out_of_range
- Psych::load('1900-01-01T00:00:00+00:00')
+ Psych::unsafe_load('1900-01-01T00:00:00+00:00')
end
def test_normal_exit
- Psych.load("2000-01-01 00:00:00.#{"0"*1000} +00:00\n")
+ Psych.unsafe_load("2000-01-01 00:00:00.#{"0"*1000} +00:00\n")
# '[ruby-core:13735]'
end
diff --git a/test/psych/test_yaml_special_cases.rb b/test/psych/test_yaml_special_cases.rb
index 4501704..205457b 100644
--- a/test/psych/test_yaml_special_cases.rb
+++ b/test/psych/test_yaml_special_cases.rb
@@ -13,7 +13,7 @@ module Psych
def test_empty_string
s = ""
- assert_equal false, Psych.load(s)
+ assert_equal false, Psych.unsafe_load(s)
assert_equal [], Psych.load_stream(s)
assert_equal false, Psych.parse(s)
assert_equal [], Psych.parse_stream(s).transform
@@ -58,8 +58,8 @@ module Psych
def test_NaN
s = ".NaN"
- assert Float::NAN, Psych.load(s).nan?
- assert [Float::NAN], Psych.load_stream(s).first.nan?
+ assert Psych.load(s).nan?
+ assert Psych.load_stream(s).first.nan?
assert Psych.parse(s).transform.nan?
assert Psych.parse_stream(s).transform.first.nan?
assert Psych.safe_load(s).nan?
diff --git a/test/psych/test_yamlstore.rb b/test/psych/test_yamlstore.rb
index d1e927c..1a1be37 100644
--- a/test/psych/test_yamlstore.rb
+++ b/test/psych/test_yamlstore.rb
@@ -4,7 +4,22 @@ require 'yaml/store'
require 'tmpdir'
module Psych
- Psych::Store = YAML::Store unless defined?(Psych::Store)
+ class YAML::Store
+ alias :old_load :load
+
+ def load(content)
+ table = YAML.load(content, fallback: false)
+ if table == false
+ {}
+ else
+ table
+ end
+ end
+ end
+
+ unless defined?(Psych::Store)
+ Psych::Store = YAML::Store
+ end
class YAMLStoreTest < TestCase
def setup
@@ -24,61 +39,61 @@ module Psych
def test_opening_new_file_in_readonly_mode_should_result_in_empty_values
@yamlstore.transaction(true) do
- assert_nil @yamlstore[:foo]
- assert_nil @yamlstore[:bar]
+ assert_nil @yamlstore["foo"]
+ assert_nil @yamlstore["bar"]
end
end
def test_opening_new_file_in_readwrite_mode_should_result_in_empty_values
@yamlstore.transaction do
- assert_nil @yamlstore[:foo]
- assert_nil @yamlstore[:bar]
+ assert_nil @yamlstore["foo"]
+ assert_nil @yamlstore["bar"]
end
end
def test_data_should_be_loaded_correctly_when_in_readonly_mode
@yamlstore.transaction do
- @yamlstore[:foo] = "bar"
+ @yamlstore["foo"] = "bar"
end
@yamlstore.transaction(true) do
- assert_equal "bar", @yamlstore[:foo]
+ assert_equal "bar", @yamlstore["foo"]
end
end
def test_data_should_be_loaded_correctly_when_in_readwrite_mode
@yamlstore.transaction do
- @yamlstore[:foo] = "bar"
+ @yamlstore["foo"] = "bar"
end
@yamlstore.transaction do
- assert_equal "bar", @yamlstore[:foo]
+ assert_equal "bar", @yamlstore["foo"]
end
end
def test_changes_after_commit_are_discarded
@yamlstore.transaction do
- @yamlstore[:foo] = "bar"
+ @yamlstore["foo"] = "bar"
@yamlstore.commit
- @yamlstore[:foo] = "baz"
+ @yamlstore["foo"] = "baz"
end
@yamlstore.transaction(true) do
- assert_equal "bar", @yamlstore[:foo]
+ assert_equal "bar", @yamlstore["foo"]
end
end
def test_changes_are_not_written_on_abort
@yamlstore.transaction do
- @yamlstore[:foo] = "bar"
+ @yamlstore["foo"] = "bar"
@yamlstore.abort
end
@yamlstore.transaction(true) do
- assert_nil @yamlstore[:foo]
+ assert_nil @yamlstore["foo"]
end
end
def test_writing_inside_readonly_transaction_raises_error
- assert_raises(PStore::Error) do
+ assert_raise(PStore::Error) do
@yamlstore.transaction(true) do
- @yamlstore[:foo] = "bar"
+ @yamlstore["foo"] = "bar"
end
end
end
diff --git a/test/psych/visitors/test_to_ruby.rb b/test/psych/visitors/test_to_ruby.rb
index e1a0056..3d4608b 100644
--- a/test/psych/visitors/test_to_ruby.rb
+++ b/test/psych/visitors/test_to_ruby.rb
@@ -20,13 +20,13 @@ module Psych
end
def test_tz_00_00_loads_without_error
- assert Psych.load('1900-01-01T00:00:00+00:00')
+ assert Psych.unsafe_load('1900-01-01T00:00:00+00:00')
end
def test_legacy_struct
Struct.send(:remove_const, :AWESOME) if Struct.const_defined?(:AWESOME)
foo = Struct.new('AWESOME', :bar)
- assert_equal foo.new('baz'), Psych.load(<<-eoyml)
+ assert_equal foo.new('baz'), Psych.unsafe_load(<<-eoyml)
!ruby/struct:AWESOME
bar: baz
eoyml
diff --git a/test/psych/visitors/test_yaml_tree.rb b/test/psych/visitors/test_yaml_tree.rb
index 69885ee..4c48670 100644
--- a/test/psych/visitors/test_yaml_tree.rb
+++ b/test/psych/visitors/test_yaml_tree.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
require 'psych/helper'
+require 'delegate'
module Psych
module Visitors
@@ -62,19 +63,19 @@ module Psych
def test_struct_anon
s = Struct.new(:foo).new('bar')
- obj = Psych.load(Psych.dump(s))
+ obj = Psych.unsafe_load(Psych.dump(s))
assert_equal s.foo, obj.foo
end
def test_override_method
s = Struct.new(:method).new('override')
- obj = Psych.load(Psych.dump(s))
+ obj = Psych.unsafe_load(Psych.dump(s))
assert_equal s.method, obj.method
end
def test_exception
ex = Exception.new 'foo'
- loaded = Psych.load(Psych.dump(ex))
+ loaded = Psych.unsafe_load(Psych.dump(ex))
assert_equal ex.message, loaded.message
assert_equal ex.class, loaded.class
@@ -88,7 +89,7 @@ module Psych
def test_time
t = Time.now
- assert_equal t, Psych.load(Psych.dump(t))
+ assert_equal t, Psych.unsafe_load(Psych.dump(t))
end
def test_date
@@ -127,11 +128,11 @@ module Psych
end
def test_anon_class
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@v.accept Class.new
end
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
Psych.dump(Class.new)
end
end