summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2019-06-29 19:43:47 +0900
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2019-07-02 07:59:54 +0900
commitc3c0e3f5c9444c197779cb242de46dfffda79dec (patch)
tree03866471345f8c9baa68d548340199408aa51405 /test
parent142617c8e1cad65fa483c5beb78ab40a99626a87 (diff)
Move to tool/lib from test/lib.
Diffstat (limited to 'test')
-rw-r--r--test/colors3
-rw-r--r--test/lib/-test-/integer.rb14
-rw-r--r--test/lib/envutil.rb311
-rw-r--r--test/lib/find_executable.rb22
-rw-r--r--test/lib/iseq_loader_checker.rb75
-rw-r--r--test/lib/jit_support.rb68
-rw-r--r--test/lib/leakchecker.rb240
-rw-r--r--test/lib/memory_status.rb149
-rw-r--r--test/lib/minitest/README.txt457
-rw-r--r--test/lib/minitest/autorun.rb14
-rw-r--r--test/lib/minitest/benchmark.rb418
-rw-r--r--test/lib/minitest/mock.rb196
-rw-r--r--test/lib/minitest/unit.rb1420
-rw-r--r--test/lib/profile_test_all.rb91
-rw-r--r--test/lib/test/unit.rb1175
-rw-r--r--test/lib/test/unit/assertions.rb984
-rw-r--r--test/lib/test/unit/parallel.rb208
-rw-r--r--test/lib/test/unit/testcase.rb36
-rw-r--r--test/lib/tracepointchecker.rb126
-rw-r--r--test/lib/with_different_ofs.rb22
-rw-r--r--test/lib/zombie_hunter.rb10
-rw-r--r--test/runner.rb13
22 files changed, 7 insertions, 6045 deletions
diff --git a/test/colors b/test/colors
deleted file mode 100644
index a65c326ade4..00000000000
--- a/test/colors
+++ /dev/null
@@ -1,3 +0,0 @@
-pass=36;7
-fail=31;1;7
-skip=33;1
diff --git a/test/lib/-test-/integer.rb b/test/lib/-test-/integer.rb
deleted file mode 100644
index a224148f24e..00000000000
--- a/test/lib/-test-/integer.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require 'test/unit'
-require '-test-/integer.so'
-
-module Test::Unit::Assertions
- def assert_fixnum(v, msg=nil)
- assert_instance_of(Integer, v, msg)
- assert_predicate(v, :fixnum?, msg)
- end
-
- def assert_bignum(v, msg=nil)
- assert_instance_of(Integer, v, msg)
- assert_predicate(v, :bignum?, msg)
- end
-end
diff --git a/test/lib/envutil.rb b/test/lib/envutil.rb
deleted file mode 100644
index b4eb63da90b..00000000000
--- a/test/lib/envutil.rb
+++ /dev/null
@@ -1,311 +0,0 @@
-# -*- 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
-
- def capture_global_values
- @original_internal_encoding = Encoding.default_internal
- @original_external_encoding = Encoding.default_external
- @original_verbose = $VERBOSE
- 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
- while signal = signals.shift
- 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
- 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,
- 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
- 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
- args = [args] if args.kind_of?(String)
- pid = spawn(child_env, *precommand, rubybin, *args, **opt)
- in_c.close
- out_c.close if capture_stdout
- err_c.close if capture_stderr && capture_stderr != :merge_to_stdout
- 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)
- 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 = Test::Unit::Assertions::FailDesc[status, 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
-
- alias rubyexec invoke_ruby
- class << self
- alias rubyexec invoke_ruby
- end
-
- 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
- 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}
- 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}
- 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.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
- Gem::ConfigMap[:bindir] = dir if defined?(Gem::ConfigMap)
- end
-end
-
-EnvUtil.capture_global_values
diff --git a/test/lib/find_executable.rb b/test/lib/find_executable.rb
deleted file mode 100644
index 89c6fb8f3b7..00000000000
--- a/test/lib/find_executable.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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/iseq_loader_checker.rb b/test/lib/iseq_loader_checker.rb
deleted file mode 100644
index 1a1a694834d..00000000000
--- a/test/lib/iseq_loader_checker.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-# frozen_string_literal: true
-
-begin
- require '-test-/iseq_load/iseq_load'
-rescue LoadError
-end
-require 'tempfile'
-
-class RubyVM::InstructionSequence
- def disasm_if_possible
- begin
- self.disasm
- rescue Encoding::CompatibilityError, EncodingError, SecurityError
- nil
- end
- end
-
- def self.compare_dump_and_load i1, dumper, loader
- dump = dumper.call(i1)
- return i1 unless dump
- i2 = loader.call(dump)
-
- # compare disassembled result
- d1 = i1.disasm_if_possible
- d2 = i2.disasm_if_possible
-
- if d1 != d2
- STDERR.puts "expected:"
- STDERR.puts d1
- STDERR.puts "actual:"
- STDERR.puts d2
-
- t1 = Tempfile.new("expected"); t1.puts d1; t1.close
- t2 = Tempfile.new("actual"); t2.puts d2; t2.close
- system("diff -u #{t1.path} #{t2.path}") # use diff if available
- exit(1)
- end
- i2
- end
-
- CHECK_TO_A = ENV['RUBY_ISEQ_DUMP_DEBUG'] == 'to_a'
- CHECK_TO_BINARY = ENV['RUBY_ISEQ_DUMP_DEBUG'] == 'to_binary'
-
- def self.translate i1
- # check to_a/load_iseq
- compare_dump_and_load(i1,
- proc{|iseq|
- ary = iseq.to_a
- ary[9] == :top ? ary : nil
- },
- proc{|ary|
- RubyVM::InstructionSequence.iseq_load(ary)
- }) if CHECK_TO_A && defined?(RubyVM::InstructionSequence.iseq_load)
-
- # check to_binary
- i2_bin = compare_dump_and_load(i1,
- proc{|iseq|
- begin
- iseq.to_binary
- rescue RuntimeError # not a toplevel
- # STDERR.puts [:failed, $!, iseq].inspect
- nil
- end
- },
- proc{|bin|
- iseq = RubyVM::InstructionSequence.load_from_binary(bin)
- # STDERR.puts iseq.inspect
- iseq
- }) if CHECK_TO_BINARY
- # return value
- i2_bin if CHECK_TO_BINARY
- end if CHECK_TO_A || CHECK_TO_BINARY
-end
-
-#require_relative 'x'; exit(1)
diff --git a/test/lib/jit_support.rb b/test/lib/jit_support.rb
deleted file mode 100644
index c1624cc3b2b..00000000000
--- a/test/lib/jit_support.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-require 'rbconfig'
-
-module JITSupport
- JIT_TIMEOUT = 600 # 10min for each...
- JIT_SUCCESS_PREFIX = 'JIT success \(\d+\.\dms\)'
- UNSUPPORTED_COMPILERS = [
- %r[\Aicc\b],
- %r[\A/opt/developerstudio\d+\.\d+/bin/cc\z],
- ]
-
- module_function
- # Run Ruby script with --jit-wait (Synchronous JIT compilation).
- # Returns [stdout, stderr]
- def eval_with_jit(env = nil, script, **opts)
- stdout, stderr = nil, nil
- # retry 3 times while cc1 error happens.
- 3.times do |i|
- stdout, stderr, status = eval_with_jit_without_retry(env, script, **opts)
- assert_equal(true, status.success?, "Failed to run script with JIT:\n#{code_block(script)}\nstdout:\n#{code_block(stdout)}\nstderr:\n#{code_block(stderr)}")
- break unless retried_stderr?(stderr)
- end
- [stdout, stderr]
- end
-
- def eval_with_jit_without_retry(env = nil, script, verbose: 0, min_calls: 5, save_temps: false, max_cache: 1000, wait: true, timeout: JIT_TIMEOUT)
- args = [
- '--disable-gems', "--jit-verbose=#{verbose}",
- "--jit-min-calls=#{min_calls}", "--jit-max-cache=#{max_cache}",
- ]
- args << '--jit-wait' if wait
- args << '--jit-save-temps' if save_temps
- args << '-e' << script
- base_env = { 'MJIT_SEARCH_BUILD_DIR' => 'true' } # workaround to skip requiring `make install` for `make test-all`
- if preloadenv = RbConfig::CONFIG['PRELOADENV'] and !preloadenv.empty?
- so = "mjit_build_dir.#{RbConfig::CONFIG['SOEXT']}"
- base_env[preloadenv] = File.realpath(so) rescue nil
- end
- args.unshift(env ? base_env.merge!(env) : base_env)
- EnvUtil.invoke_ruby(args,
- '', true, true, timeout: timeout,
- )
- end
-
- def supported?
- return @supported if defined?(@supported)
- @supported = UNSUPPORTED_COMPILERS.all? do |regexp|
- !regexp.match?(RbConfig::CONFIG['CC'])
- end
- end
-
- def remove_mjit_logs(stderr)
- if RubyVM::MJIT.enabled? # utility for -DFORCE_MJIT_ENABLE
- stderr.gsub(/^MJIT warning: Skipped to compile unsupported instruction: \w+\n/m, '')
- else
- stderr
- end
- end
-
- def code_block(code)
- %Q["""\n#{code}\n"""\n\n]
- end
-
- # We're retrying cc1 not found error on gcc, which should be solved in the future but ignored for now.
- def retried_stderr?(stderr)
- RbConfig::CONFIG['CC'].start_with?('gcc') &&
- stderr.include?("error trying to exec 'cc1': execvp: No such file or directory")
- end
-end
diff --git a/test/lib/leakchecker.rb b/test/lib/leakchecker.rb
deleted file mode 100644
index af9200bf77a..00000000000
--- a/test/lib/leakchecker.rb
+++ /dev/null
@@ -1,240 +0,0 @@
-# frozen_string_literal: true
-class LeakChecker
- def initialize
- @fd_info = find_fds
- @tempfile_info = find_tempfiles
- @thread_info = find_threads
- @env_info = find_env
- @encoding_info = find_encodings
- @old_verbose = $VERBOSE
- end
-
- def check(test_name)
- leaks = [
- check_fd_leak(test_name),
- check_thread_leak(test_name),
- check_tempfile_leak(test_name),
- check_env(test_name),
- check_encodings(test_name),
- check_safe(test_name),
- check_verbose(test_name),
- ]
- GC.start if leaks.any?
- end
-
- def check_safe test_name
- puts "#{test_name}: $SAFE == #{$SAFE}" unless $SAFE == 0
- end
-
- def check_verbose test_name
- puts "#{test_name}: $VERBOSE == #{$VERBOSE}" unless @old_verbose == $VERBOSE
- end
-
- def find_fds
- if IO.respond_to?(:console) and (m = IO.method(:console)).arity.nonzero?
- m[:close]
- end
- fd_dir = "/proc/self/fd"
- if File.directory?(fd_dir)
- fds = Dir.open(fd_dir) {|d|
- a = d.grep(/\A\d+\z/, &:to_i)
- if d.respond_to? :fileno
- a -= [d.fileno]
- end
- a
- }
- fds.sort
- else
- []
- end
- end
-
- def check_fd_leak(test_name)
- leaked = false
- live1 = @fd_info
- live2 = find_fds
- fd_closed = live1 - live2
- if !fd_closed.empty?
- fd_closed.each {|fd|
- puts "Closed file descriptor: #{test_name}: #{fd}"
- }
- end
- fd_leaked = live2 - live1
- if !fd_leaked.empty?
- leaked = true
- h = {}
- ObjectSpace.each_object(IO) {|io|
- inspect = io.inspect
- begin
- autoclose = io.autoclose?
- fd = io.fileno
- rescue IOError # closed IO object
- next
- end
- (h[fd] ||= []) << [io, autoclose, inspect]
- }
- fd_leaked.each {|fd|
- str = ''.dup
- if h[fd]
- str << ' :'
- h[fd].map {|io, autoclose, inspect|
- s = ' ' + inspect
- s << "(not-autoclose)" if !autoclose
- s
- }.sort.each {|s|
- str << s
- }
- end
- puts "Leaked file descriptor: #{test_name}: #{fd}#{str}"
- }
- #system("lsof -p #$$") if !fd_leaked.empty?
- h.each {|fd, list|
- next if list.length <= 1
- if 1 < list.count {|io, autoclose, inspect| autoclose }
- str = list.map {|io, autoclose, inspect| " #{inspect}" + (autoclose ? "(autoclose)" : "") }.sort.join
- puts "Multiple autoclose IO object for a file descriptor:#{str}"
- end
- }
- end
- @fd_info = live2
- return leaked
- end
-
- def extend_tempfile_counter
- return if defined? LeakChecker::TempfileCounter
- m = Module.new {
- @count = 0
- class << self
- attr_accessor :count
- end
-
- def new(data)
- LeakChecker::TempfileCounter.count += 1
- super(data)
- end
- }
- LeakChecker.const_set(:TempfileCounter, m)
-
- class << Tempfile::Remover
- prepend LeakChecker::TempfileCounter
- end
- end
-
- def find_tempfiles(prev_count=-1)
- return [prev_count, []] unless defined? Tempfile
- extend_tempfile_counter
- count = TempfileCounter.count
- if prev_count == count
- [prev_count, []]
- else
- tempfiles = ObjectSpace.each_object(Tempfile).find_all {|t|
- t.instance_variable_defined?(:@tmpfile) and t.path
- }
- [count, tempfiles]
- end
- end
-
- def check_tempfile_leak(test_name)
- return false unless defined? Tempfile
- count1, initial_tempfiles = @tempfile_info
- count2, current_tempfiles = find_tempfiles(count1)
- leaked = false
- tempfiles_leaked = current_tempfiles - initial_tempfiles
- if !tempfiles_leaked.empty?
- leaked = true
- list = tempfiles_leaked.map {|t| t.inspect }.sort
- list.each {|str|
- puts "Leaked tempfile: #{test_name}: #{str}"
- }
- tempfiles_leaked.each {|t| t.close! }
- end
- @tempfile_info = [count2, initial_tempfiles]
- return leaked
- end
-
- def find_threads
- Thread.list.find_all {|t|
- t != Thread.current && t.alive?
- }
- end
-
- def check_thread_leak(test_name)
- live1 = @thread_info
- live2 = find_threads
- thread_finished = live1 - live2
- leaked = false
- if !thread_finished.empty?
- list = thread_finished.map {|t| t.inspect }.sort
- list.each {|str|
- puts "Finished thread: #{test_name}: #{str}"
- }
- end
- thread_leaked = live2 - live1
- if !thread_leaked.empty?
- leaked = true
- list = thread_leaked.map {|t| t.inspect }.sort
- list.each {|str|
- puts "Leaked thread: #{test_name}: #{str}"
- }
- end
- @thread_info = live2
- return leaked
- end
-
- def find_env
- ENV.to_h
- end
-
- def check_env(test_name)
- old_env = @env_info
- new_env = ENV.to_h
- return false if old_env == new_env
- (old_env.keys | new_env.keys).sort.each {|k|
- if old_env.has_key?(k)
- if new_env.has_key?(k)
- if old_env[k] != new_env[k]
- puts "Environment variable changed: #{test_name} : #{k.inspect} changed : #{old_env[k].inspect} -> #{new_env[k].inspect}"
- end
- else
- puts "Environment variable changed: #{test_name} : #{k.inspect} deleted"
- end
- else
- if new_env.has_key?(k)
- puts "Environment variable changed: #{test_name} : #{k.inspect} added"
- else
- flunk "unreachable"
- end
- end
- }
- @env_info = new_env
- return true
- end
-
- def find_encodings
- [Encoding.default_internal, Encoding.default_external]
- end
-
- def check_encodings(test_name)
- old_internal, old_external = @encoding_info
- new_internal, new_external = find_encodings
- leaked = false
- if new_internal != old_internal
- leaked = true
- puts "Encoding.default_internal changed: #{test_name} : #{old_internal.inspect} to #{new_internal.inspect}"
- end
- if new_external != old_external
- leaked = true
- puts "Encoding.default_external changed: #{test_name} : #{old_external.inspect} to #{new_external.inspect}"
- end
- @encoding_info = [new_internal, new_external]
- return leaked
- end
-
- def puts(*a)
- output = MiniTest::Unit.output
- if defined?(output.set_encoding)
- output.set_encoding(nil, nil)
- end
- output.puts(*a)
- end
-end
diff --git a/test/lib/memory_status.rb b/test/lib/memory_status.rb
deleted file mode 100644
index ad002b2dda5..00000000000
--- a/test/lib/memory_status.rb
+++ /dev/null
@@ -1,149 +0,0 @@
-# frozen_string_literal: true
-begin
- require '-test-/memory_status.so'
-rescue LoadError
-end
-
-module Memory
- keys = []
-
- case
- when File.exist?(procfile = "/proc/self/status") && (pat = /^Vm(\w+):\s+(\d+)/) =~ (data = File.binread(procfile))
- PROC_FILE = procfile
- VM_PAT = pat
- def self.read_status
- IO.foreach(PROC_FILE, encoding: Encoding::ASCII_8BIT) do |l|
- yield($1.downcase.intern, $2.to_i * 1024) if VM_PAT =~ l
- end
- end
-
- data.scan(pat) {|k, v| keys << k.downcase.intern}
-
- when /mswin|mingw/ =~ RUBY_PLATFORM
- require 'fiddle/import'
- require 'fiddle/types'
-
- module Win32
- extend Fiddle::Importer
- dlload "kernel32.dll", "psapi.dll"
- include Fiddle::Win32Types
- typealias "SIZE_T", "size_t"
-
- PROCESS_MEMORY_COUNTERS = struct [
- "DWORD cb",
- "DWORD PageFaultCount",
- "SIZE_T PeakWorkingSetSize",
- "SIZE_T WorkingSetSize",
- "SIZE_T QuotaPeakPagedPoolUsage",
- "SIZE_T QuotaPagedPoolUsage",
- "SIZE_T QuotaPeakNonPagedPoolUsage",
- "SIZE_T QuotaNonPagedPoolUsage",
- "SIZE_T PagefileUsage",
- "SIZE_T PeakPagefileUsage",
- ]
-
- typealias "PPROCESS_MEMORY_COUNTERS", "PROCESS_MEMORY_COUNTERS*"
-
- extern "HANDLE GetCurrentProcess()", :stdcall
- extern "BOOL GetProcessMemoryInfo(HANDLE, PPROCESS_MEMORY_COUNTERS, DWORD)", :stdcall
-
- module_function
- def memory_info
- size = PROCESS_MEMORY_COUNTERS.size
- data = PROCESS_MEMORY_COUNTERS.malloc
- data.cb = size
- data if GetProcessMemoryInfo(GetCurrentProcess(), data, size)
- end
- end
-
- keys << :peak << :size
- def self.read_status
- if info = Win32.memory_info
- yield :peak, info.PeakPagefileUsage
- yield :size, info.PagefileUsage
- end
- end
- when (require_relative 'find_executable'
- pat = /^\s*(\d+)\s+(\d+)$/
- pscmd = EnvUtil.find_executable("ps", "-ovsz=", "-orss=", "-p", $$.to_s) {|out| pat =~ out})
- pscmd.pop
- PAT = pat
- PSCMD = pscmd
-
- keys << :size << :rss
- def self.read_status
- if PAT =~ IO.popen(PSCMD + [$$.to_s], "r", err: [:child, :out], &:read)
- yield :size, $1.to_i*1024
- yield :rss, $2.to_i*1024
- end
- end
- else
- def self.read_status
- raise NotImplementedError, "unsupported platform"
- end
- end
-
- if !keys.empty?
- Status = Struct.new(*keys)
- end
-end unless defined?(Memory::Status)
-
-if defined?(Memory::Status)
- class Memory::Status
- def _update
- Memory.read_status do |key, val|
- self[key] = val
- end
- end unless method_defined?(:_update)
-
- Header = members.map {|k| k.to_s.upcase.rjust(6)}.join('')
- Format = "%6d"
-
- def initialize
- _update
- end
-
- def to_s
- status = each_pair.map {|n,v|
- "#{n}:#{v}"
- }
- "{#{status.join(",")}}"
- end
-
- def self.parse(str)
- status = allocate
- str.scan(/(?:\A\{|\G,)(#{members.join('|')}):(\d+)(?=,|\}\z)/) do
- status[$1] = $2.to_i
- end
- status
- end
- end
-
- # On some platforms (e.g. Solaris), libc malloc does not return
- # freed memory to OS because of efficiency, and linking with extra
- # malloc library is needed to detect memory leaks.
- #
- case RUBY_PLATFORM
- when /solaris2\.(?:9|[1-9][0-9])/i # Solaris 9, 10, 11,...
- bits = [nil].pack('p').size == 8 ? 64 : 32
- if ENV['LD_PRELOAD'].to_s.empty? &&
- ENV["LD_PRELOAD_#{bits}"].to_s.empty? &&
- (ENV['UMEM_OPTIONS'].to_s.empty? ||
- ENV['UMEM_OPTIONS'] == 'backend=mmap') then
- envs = {
- 'LD_PRELOAD' => 'libumem.so',
- 'UMEM_OPTIONS' => 'backend=mmap'
- }
- args = [
- envs,
- "--disable=gems",
- "-v", "-",
- ]
- _, err, status = EnvUtil.invoke_ruby(args, "exit(0)", true, true)
- if status.exitstatus == 0 && err.to_s.empty? then
- Memory::NO_MEMORY_LEAK_ENVS = envs
- end
- end
- end #case RUBY_PLATFORM
-
-end
diff --git a/test/lib/minitest/README.txt b/test/lib/minitest/README.txt
deleted file mode 100644
index 368cc3aa4eb..00000000000
--- a/test/lib/minitest/README.txt
+++ /dev/null
@@ -1,457 +0,0 @@
-= minitest/{unit,spec,mock,benchmark}
-
-home :: https://github.com/seattlerb/minitest
-rdoc :: http://docs.seattlerb.org/minitest
-vim :: https://github.com/sunaku/vim-ruby-minitest
-
-== DESCRIPTION:
-
-minitest provides a complete suite of testing facilities supporting
-TDD, BDD, mocking, and benchmarking.
-
- "I had a class with Jim Weirich on testing last week and we were
- allowed to choose our testing frameworks. Kirk Haines and I were
- paired up and we cracked open the code for a few test
- frameworks...
-
- I MUST say that minitest is *very* readable / understandable
- compared to the 'other two' options we looked at. Nicely done and
- thank you for helping us keep our mental sanity."
-
- -- Wayne E. Seguin
-
-minitest/unit is a small and incredibly fast unit testing framework.
-It provides a rich set of assertions to make your tests clean and
-readable.
-
-minitest/spec is a functionally complete spec engine. It hooks onto
-minitest/unit and seamlessly bridges test assertions over to spec
-expectations.
-
-minitest/benchmark is an awesome way to assert the performance of your
-algorithms in a repeatable manner. Now you can assert that your newb
-co-worker doesn't replace your linear algorithm with an exponential
-one!
-
-minitest/mock by Steven Baker, is a beautifully tiny mock (and stub)
-object framework.
-
-minitest/pride shows pride in testing and adds coloring to your test
-output. I guess it is an example of how to write IO pipes too. :P
-
-minitest/unit is meant to have a clean implementation for language
-implementors that need a minimal set of methods to bootstrap a working
-test suite. For example, there is no magic involved for test-case
-discovery.
-
- "Again, I can't praise enough the idea of a testing/specing
- framework that I can actually read in full in one sitting!"
-
- -- Piotr Szotkowski
-
-Comparing to rspec:
-
- rspec is a testing DSL. minitest is ruby.
-
- -- Adam Hawkins, "Bow Before MiniTest"
-
-minitest doesn't reinvent anything that ruby already provides, like:
-classes, modules, inheritance, methods. This means you only have to
-learn ruby to use minitest and all of your regular OO practices like
-extract-method refactorings still apply.
-
-== FEATURES/PROBLEMS:
-
-* minitest/autorun - the easy and explicit way to run all your tests.
-* minitest/unit - a very fast, simple, and clean test system.
-* minitest/spec - a very fast, simple, and clean spec system.
-* minitest/mock - a simple and clean mock/stub system.
-* minitest/benchmark - an awesome way to assert your algorithm's performance.
-* minitest/pride - show your pride in testing!
-* Incredibly small and fast runner, but no bells and whistles.
-
-== RATIONALE:
-
-See design_rationale.rb to see how specs and tests work in minitest.
-
-== SYNOPSIS:
-
-Given that you'd like to test the following class:
-
- class Meme
- def i_can_has_cheezburger?
- "OHAI!"
- end
-
- def will_it_blend?
- "YES!"
- end
- end
-
-=== Unit tests
-
- require 'minitest/autorun'
-
- class TestMeme < MiniTest::Unit::TestCase
- def setup
- @meme = Meme.new
- end
-
- def test_that_kitty_can_eat
- assert_equal "OHAI!", @meme.i_can_has_cheezburger?
- end
-
- def test_that_it_will_not_blend
- refute_match /^no/i, @meme.will_it_blend?
- end
-
- def test_that_will_be_skipped
- skip "test this later"
- end
- end
-
-=== Specs
-
- require 'minitest/autorun'
-
- describe Meme do
- before do
- @meme = Meme.new
- end
-
- describe "when asked about cheeseburgers" do
- it "must respond positively" do
- @meme.i_can_has_cheezburger?.must_equal "OHAI!"
- end
- end
-
- describe "when asked about blending possibilities" do
- it "won't say no" do
- @meme.will_it_blend?.wont_match /^no/i
- end
- end
- end
-
-For matchers support check out:
-
-https://github.com/zenspider/minitest-matchers
-
-=== Benchmarks
-
-Add benchmarks to your regular unit tests. If the unit tests fail, the
-benchmarks won't run.
-
- # optionally run benchmarks, good for CI-only work!
- require 'minitest/benchmark' if ENV["BENCH"]
-
- class TestMeme < MiniTest::Unit::TestCase
- # Override self.bench_range or default range is [1, 10, 100, 1_000, 10_000]
- def bench_my_algorithm
- assert_performance_linear 0.9999 do |n| # n is a range value
- @obj.my_algorithm(n)
- end
- end
- end
-
-Or add them to your specs. If you make benchmarks optional, you'll
-need to wrap your benchmarks in a conditional since the methods won't
-be defined.
-
- describe Meme do
- if ENV["BENCH"] then
- bench_performance_linear "my_algorithm", 0.9999 do |n|
- 100.times do
- @obj.my_algorithm(n)
- end
- end
- end
- end
-
-outputs something like:
-
- # Running benchmarks:
-
- TestBlah 100 1000 10000
- bench_my_algorithm 0.006167 0.079279 0.786993
- bench_other_algorithm 0.061679 0.792797 7.869932
-
-Output is tab-delimited to make it easy to paste into a spreadsheet.
-
-=== Mocks
-
- class MemeAsker
- def initialize(meme)
- @meme = meme
- end
-
- def ask(question)
- method = question.tr(" ","_") + "?"
- @meme.__send__(method)
- end
- end
-
- require 'minitest/autorun'
-
- describe MemeAsker do
- before do
- @meme = MiniTest::Mock.new
- @meme_asker = MemeAsker.new @meme
- end
-
- describe "#ask" do
- describe "when passed an unpunctuated question" do
- it "should invoke the appropriate predicate method on the meme" do
- @meme.expect :will_it_blend?, :return_value
- @meme_asker.ask "will it blend"
- @meme.verify
- end
- end
- end
- end
-
-=== Stubs
-
- def test_stale_eh
- obj_under_test = Something.new
-
- refute obj_under_test.stale?
-
- Time.stub :now, Time.at(0) do # stub goes away once the block is done
- assert obj_under_test.stale?
- end
- end
-
-A note on stubbing: In order to stub a method, the method must
-actually exist prior to stubbing. Use a singleton method to create a
-new non-existing method:
-
- def obj_under_test.fake_method
- ...
- end
-
-=== Customizable Test Runner Types:
-
-MiniTest::Unit.runner=(runner) provides an easy way of creating custom
-test runners for specialized needs. Justin Weiss provides the
-following real-world example to create an alternative to regular
-fixture loading:
-
- class MiniTestWithHooks::Unit < MiniTest::Unit
- def before_suites
- end
-
- def after_suites
- end
-
- def _run_suites(suites, type)
- begin
- before_suites
- super(suites, type)
- ensure
- after_suites
- end
- end
-
- def _run_suite(suite, type)
- begin
- suite.before_suite
- super(suite, type)
- ensure
- suite.after_suite
- end
- end
- end
-
- module MiniTestWithTransactions
- class Unit < MiniTestWithHooks::Unit
- include TestSetupHelper
-
- def before_suites
- super
- setup_nested_transactions
- # load any data we want available for all tests
- end
-
- def after_suites
- teardown_nested_transactions
- super
- end
- end
- end
-
- MiniTest::Unit.runner = MiniTestWithTransactions::Unit.new
-
-== FAQ
-
-=== How to test SimpleDelegates?
-
-The following implementation and test:
-
- class Worker < SimpleDelegator
- def work
- end
- end
-
- describe Worker do
- before do
- @worker = Worker.new(Object.new)
- end
-
- it "must respond to work" do
- @worker.must_respond_to :work
- end
- end
-
-outputs a failure:
-
- 1) Failure:
- Worker#test_0001_must respond to work [bug11.rb:16]:
- Expected #<Object:0x007f9e7184f0a0> (Object) to respond to #work.
-
-Worker is a SimpleDelegate which in 1.9+ is a subclass of BasicObject.
-Expectations are put on Object (one level down) so the Worker
-(SimpleDelegate) hits `method_missing` and delegates down to the
-`Object.new` instance. That object doesn't respond to work so the test
-fails.
-
-You can bypass `SimpleDelegate#method_missing` by extending the worker
-with `MiniTest::Expectations`. You can either do that in your setup at
-the instance level, like:
-
- before do
- @worker = Worker.new(Object.new)
- @worker.extend MiniTest::Expectations
- end
-
-or you can extend the Worker class (within the test file!), like:
-
- class Worker
- include ::MiniTest::Expectations
- end
-
-== Known Extensions:
-
-capybara_minitest_spec :: Bridge between Capybara RSpec matchers and MiniTest::Spec expectations (e.g. page.must_have_content('Title')).
-minispec-metadata :: Metadata for describe/it blocks
- (e.g. `it 'requires JS driver', js: true do`)
-minitest-ansi :: Colorize minitest output with ANSI colors.
-minitest-around :: Around block for minitest. An alternative to setup/teardown dance.
-minitest-capistrano :: Assertions and expectations for testing Capistrano recipes
-minitest-capybara :: Capybara matchers support for minitest unit and spec
-minitest-chef-handler :: Run Minitest suites as Chef report handlers
-minitest-ci :: CI reporter plugin for MiniTest.
-minitest-colorize :: Colorize MiniTest output and show failing tests instantly.
-minitest-context :: Defines contexts for code reuse in MiniTest
- specs that share common expectations.
-minitest-debugger :: Wraps assert so failed assertions drop into
- the ruby debugger.
-minitest-display :: Patches MiniTest to allow for an easily configurable output.
-minitest-emoji :: Print out emoji for your test passes, fails, and skips.
-minitest-english :: Semantically symmetric aliases for assertions and expectations.
-minitest-excludes :: Clean API for excluding certain tests you
- don't want to run under certain conditions.
-minitest-firemock :: Makes your MiniTest mocks more resilient.
-minitest-great_expectations :: Generally useful additions to minitest's assertions and expectations
-minitest-growl :: Test notifier for minitest via growl.
-minitest-implicit-subject :: Implicit declaration of the test subject.
-minitest-instrument :: Instrument ActiveSupport::Notifications when
- test method is executed
-minitest-instrument-db :: Store information about speed of test
- execution provided by minitest-instrument in database
-minitest-libnotify :: Test notifier for minitest via libnotify.
-minitest-macruby :: Provides extensions to minitest for macruby UI testing.
-minitest-matchers :: Adds support for RSpec-style matchers to minitest.
-minitest-metadata :: Annotate tests with metadata (key-value).
-minitest-mongoid :: Mongoid assertion matchers for MiniTest
-minitest-must_not :: Provides must_not as an alias for wont in MiniTest
-minitest-nc :: Test notifier for minitest via Mountain Lion's Notification Center
-minitest-predicates :: Adds support for .predicate? methods
-minitest-rails :: MiniTest integration for Rails 3.x
-minitest-rails-capybara :: Capybara integration for MiniTest::Rails
-minitest-reporters :: Create customizable MiniTest output formats
-minitest-should_syntax :: RSpec-style +x.should == y+ assertions for MiniTest
-minitest-shouldify :: Adding all manner of shoulds to MiniTest (bad idea)
-minitest-spec-context :: Provides rspec-ish context method to MiniTest::Spec
-minitest-spec-magic :: Minitest::Spec extensions for Rails and beyond
-minitest-spec-rails :: Drop in MiniTest::Spec superclass for ActiveSupport::TestCase.
-minitest-stub-const :: Stub constants for the duration of a block
-minitest-tags :: add tags for minitest
-minitest-wscolor :: Yet another test colorizer.
-minitest_owrapper :: Get tests results as a TestResult object.
-minitest_should :: Shoulda style syntax for minitest test::unit.
-minitest_tu_shim :: minitest_tu_shim bridges between test/unit and minitest.
-mongoid-minitest :: MiniTest matchers for Mongoid.
-pry-rescue :: A pry plugin w/ minitest support. See pry-rescue/minitest.rb.
-
-== Unknown Extensions:
-
-Authors... Please send me a pull request with a description of your minitest extension.
-
-* assay-minitest
-* detroit-minitest
-* em-minitest-spec
-* flexmock-minitest
-* guard-minitest
-* guard-minitest-decisiv
-* minitest-activemodel
-* minitest-ar-assertions
-* minitest-capybara-unit
-* minitest-colorer
-* minitest-deluxe
-* minitest-extra-assertions
-* minitest-rails-shoulda
-* minitest-spec
-* minitest-spec-should
-* minitest-sugar
-* minitest_should
-* mongoid-minitest
-* spork-minitest
-
-== REQUIREMENTS:
-
-* Ruby 1.8, maybe even 1.6 or lower. No magic is involved.
-
-== INSTALL:
-
- sudo gem install minitest
-
-On 1.9, you already have it. To get newer candy you can still install
-the gem, but you'll need to activate the gem explicitly to use it:
-
- require 'rubygems'
- gem 'minitest' # ensures you're using the gem, and not the built in MT
- require 'minitest/autorun'
-
- # ... usual testing stuffs ...
-
-DO NOTE: There is a serious problem with the way that ruby 1.9/2.0
-packages their own gems. They install a gem specification file, but
-don't install the gem contents in the gem path. This messes up
-Gem.find_files and many other things (gem which, gem contents, etc).
-
-Just install minitest as a gem for real and you'll be happier.
-
-== LICENSE:
-
-(The MIT License)
-
-Copyright (c) Ryan Davis, seattle.rb
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-'Software'), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/test/lib/minitest/autorun.rb b/test/lib/minitest/autorun.rb
deleted file mode 100644
index 844096623c0..00000000000
--- a/test/lib/minitest/autorun.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# encoding: utf-8
-# frozen_string_literal: true
-
-begin
- require 'rubygems'
- gem 'minitest'
-rescue Gem::LoadError
- # do nothing
-end
-
-require 'minitest/unit'
-require 'minitest/mock'
-
-MiniTest::Unit.autorun
diff --git a/test/lib/minitest/benchmark.rb b/test/lib/minitest/benchmark.rb
deleted file mode 100644
index b3f2bc28b30..00000000000
--- a/test/lib/minitest/benchmark.rb
+++ /dev/null
@@ -1,418 +0,0 @@
-# encoding: utf-8
-# frozen_string_literal: true
-
-require 'minitest/unit'
-
-class MiniTest::Unit # :nodoc:
- def run_benchmarks # :nodoc:
- _run_anything :benchmark
- end
-
- def benchmark_suite_header suite # :nodoc:
- "\n#{suite}\t#{suite.bench_range.join("\t")}"
- end
-
- class TestCase
- ##
- # Returns a set of ranges stepped exponentially from +min+ to
- # +max+ by powers of +base+. Eg:
- #
- # bench_exp(2, 16, 2) # => [2, 4, 8, 16]
-
- def self.bench_exp min, max, base = 10
- min = (Math.log10(min) / Math.log10(base)).to_i
- max = (Math.log10(max) / Math.log10(base)).to_i
-
- (min..max).map { |m| base ** m }.to_a
- end
-
- ##
- # Returns a set of ranges stepped linearly from +min+ to +max+ by
- # +step+. Eg:
- #
- # bench_linear(20, 40, 10) # => [20, 30, 40]
-
- def self.bench_linear min, max, step = 10
- (min..max).step(step).to_a
- rescue LocalJumpError # 1.8.6
- r = []; (min..max).step(step) { |n| r << n }; r
- end
-
- ##
- # Returns the benchmark methods (methods that start with bench_)
- # for that class.
-
- def self.benchmark_methods # :nodoc:
- public_instance_methods(true).grep(/^bench_/).map { |m| m.to_s }.sort
- end
-
- ##
- # Returns all test suites that have benchmark methods.
-
- def self.benchmark_suites
- TestCase.test_suites.reject { |s| s.benchmark_methods.empty? }
- end
-
- ##
- # Specifies the ranges used for benchmarking for that class.
- # Defaults to exponential growth from 1 to 10k by powers of 10.
- # Override if you need different ranges for your benchmarks.
- #
- # See also: ::bench_exp and ::bench_linear.
-
- def self.bench_range
- bench_exp 1, 10_000
- end
-
- ##
- # Runs the given +work+, gathering the times of each run. Range
- # and times are then passed to a given +validation+ proc. Outputs
- # the benchmark name and times in tab-separated format, making it
- # easy to paste into a spreadsheet for graphing or further
- # analysis.
- #
- # Ranges are specified by ::bench_range.
- #
- # Eg:
- #
- # def bench_algorithm
- # validation = proc { |x, y| ... }
- # assert_performance validation do |n|
- # @obj.algorithm(n)
- # end
- # end
-
- def assert_performance validation, &work
- range = self.class.bench_range
-
- io.print "#{__name__}"
-
- times = []
-
- range.each do |x|
- GC.start
- t0 = Time.now
- instance_exec(x, &work)
- t = Time.now - t0
-
- io.print "\t%9.6f" % t
- times << t
- end
- io.puts
-
- validation[range, times]
- end
-
- ##
- # Runs the given +work+ and asserts that the times gathered fit to
- # match a constant rate (eg, linear slope == 0) within a given
- # +threshold+. Note: because we're testing for a slope of 0, R^2
- # is not a good determining factor for the fit, so the threshold
- # is applied against the slope itself. As such, you probably want
- # to tighten it from the default.
- #
- # See http://www.graphpad.com/curvefit/goodness_of_fit.htm for
- # more details.
- #
- # Fit is calculated by #fit_linear.
- #
- # Ranges are specified by ::bench_range.
- #
- # Eg:
- #
- # def bench_algorithm
- # assert_performance_constant 0.9999 do |n|
- # @obj.algorithm(n)
- # end
- # end
-
- def assert_performance_constant threshold = 0.99, &work
- validation = proc do |range, times|
- a, b, rr = fit_linear range, times
- assert_in_delta 0, b, 1 - threshold
- [a, b, rr]
- end
-
- assert_performance validation, &work
- end
-
- ##
- # Runs the given +work+ and asserts that the times gathered fit to
- # match a exponential curve within a given error +threshold+.
- #
- # Fit is calculated by #fit_exponential.
- #
- # Ranges are specified by ::bench_range.
- #
- # Eg:
- #
- # def bench_algorithm
- # assert_performance_exponential 0.9999 do |n|
- # @obj.algorithm(n)
- # end
- # end
-
- def assert_performance_exponential threshold = 0.99, &work
- assert_performance validation_for_fit(:exponential, threshold), &work
- end
-
- ##
- # Runs the given +work+ and asserts that the times gathered fit to
- # match a logarithmic curve within a given error +threshold+.
- #
- # Fit is calculated by #fit_logarithmic.
- #
- # Ranges are specified by ::bench_range.
- #
- # Eg:
- #
- # def bench_algorithm
- # assert_performance_logarithmic 0.9999 do |n|
- # @obj.algorithm(n)
- # end
- # end
-
- def assert_performance_logarithmic threshold = 0.99, &work
- assert_performance validation_for_fit(:logarithmic, threshold), &work
- end
-
- ##
- # Runs the given +work+ and asserts that the times gathered fit to
- # match a straight line within a given error +threshold+.
- #
- # Fit is calculated by #fit_linear.
- #
- # Ranges are specified by ::bench_range.
- #
- # Eg:
- #
- # def bench_algorithm
- # assert_performance_linear 0.9999 do |n|
- # @obj.algorithm(n)
- # end
- # end
-
- def assert_performance_linear threshold = 0.99, &work
- assert_performance validation_for_fit(:linear, threshold), &work
- end
-
- ##
- # Runs the given +work+ and asserts that the times gathered curve
- # fit to match a power curve within a given error +threshold+.
- #
- # Fit is calculated by #fit_power.
- #
- # Ranges are specified by ::bench_range.
- #
- # Eg:
- #
- # def bench_algorithm
- # assert_performance_power 0.9999 do |x|
- # @obj.algorithm
- # end
- # end
-
- def assert_performance_power threshold = 0.99, &work
- assert_performance validation_for_fit(:power, threshold), &work
- end
-
- ##
- # Takes an array of x/y pairs and calculates the general R^2 value.
- #
- # See: http://en.wikipedia.org/wiki/Coefficient_of_determination
-
- def fit_error xys
- y_bar = sigma(xys) { |x, y| y } / xys.size.to_f
- ss_tot = sigma(xys) { |x, y| (y - y_bar) ** 2 }
- ss_err = sigma(xys) { |x, y| (yield(x) - y) ** 2 }
-
- 1 - (ss_err / ss_tot)
- end
-
- ##
- # To fit a functional form: y = ae^(bx).
- #
- # Takes x and y values and returns [a, b, r^2].
- #
- # See: http://mathworld.wolfram.com/LeastSquaresFittingExponential.html
-
- def fit_exponential xs, ys
- n = xs.size
- xys = xs.zip(ys)
- sxlny = sigma(xys) { |x,y| x * Math.log(y) }
- slny = sigma(xys) { |x,y| Math.log(y) }
- sx2 = sigma(xys) { |x,y| x * x }
- sx = sigma xs
-
- c = n * sx2 - sx ** 2
- a = (slny * sx2 - sx * sxlny) / c
- b = ( n * sxlny - sx * slny ) / c
-
- return Math.exp(a), b, fit_error(xys) { |x| Math.exp(a + b * x) }
- end
-
- ##
- # To fit a functional form: y = a + b*ln(x).
- #
- # Takes x and y values and returns [a, b, r^2].
- #
- # See: http://mathworld.wolfram.com/LeastSquaresFittingLogarithmic.html
-
- def fit_logarithmic xs, ys
- n = xs.size
- xys = xs.zip(ys)
- slnx2 = sigma(xys) { |x,y| Math.log(x) ** 2 }
- slnx = sigma(xys) { |x,y| Math.log(x) }
- sylnx = sigma(xys) { |x,y| y * Math.log(x) }
- sy = sigma(xys) { |x,y| y }
-
- c = n * slnx2 - slnx ** 2
- b = ( n * sylnx - sy * slnx ) / c
- a = (sy - b * slnx) / n
-
- return a, b, fit_error(xys) { |x| a + b * Math.log(x) }
- end
-
-
- ##
- # Fits the functional form: a + bx.
- #
- # Takes x and y values and returns [a, b, r^2].
- #
- # See: http://mathworld.wolfram.com/LeastSquaresFitting.html
-
- def fit_linear xs, ys
- n = xs.size
- xys = xs.zip(ys)
- sx = sigma xs
- sy = sigma ys
- sx2 = sigma(xs) { |x| x ** 2 }
- sxy = sigma(xys) { |x,y| x * y }
-
- c = n * sx2 - sx**2
- a = (sy * sx2 - sx * sxy) / c
- b = ( n * sxy - sx * sy ) / c
-
- return a, b, fit_error(xys) { |x| a + b * x }
- end
-
- ##
- # To fit a functional form: y = ax^b.
- #
- # Takes x and y values and returns [a, b, r^2].
- #
- # See: http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html
-
- def fit_power xs, ys
- n = xs.size
- xys = xs.zip(ys)
- slnxlny = sigma(xys) { |x, y| Math.log(x) * Math.log(y) }
- slnx = sigma(xs) { |x | Math.log(x) }
- slny = sigma(ys) { | y| Math.log(y) }
- slnx2 = sigma(xs) { |x | Math.log(x) ** 2 }
-
- b = (n * slnxlny - slnx * slny) / (n * slnx2 - slnx ** 2);
- a = (slny - b * slnx) / n
-
- return Math.exp(a), b, fit_error(xys) { |x| (Math.exp(a) * (x ** b)) }
- end
-
- ##
- # Enumerates over +enum+ mapping +block+ if given, returning the
- # sum of the result. Eg:
- #
- # sigma([1, 2, 3]) # => 1 + 2 + 3 => 7
- # sigma([1, 2, 3]) { |n| n ** 2 } # => 1 + 4 + 9 => 14
-
- def sigma enum, &block
- enum = enum.map(&block) if block
- enum.inject { |sum, n| sum + n }
- end
-
- ##
- # Returns a proc that calls the specified fit method and asserts
- # that the error is within a tolerable threshold.
-
- def validation_for_fit msg, threshold
- proc do |range, times|
- a, b, rr = send "fit_#{msg}", range, times
- assert_operator rr, :>=, threshold
- [a, b, rr]
- end
- end
- end
-end
-
-class MiniTest::Spec
- ##
- # This is used to define a new benchmark method. You usually don't
- # use this directly and is intended for those needing to write new
- # performance curve fits (eg: you need a specific polynomial fit).
- #
- # See ::bench_performance_linear for an example of how to use this.
-
- def self.bench name, &block
- define_method "bench_#{name.gsub(/\W+/, '_')}", &block
- end
-
- ##
- # Specifies the ranges used for benchmarking for that class.
- #
- # bench_range do
- # bench_exp(2, 16, 2)
- # end
- #
- # See Unit::TestCase.bench_range for more details.
-
- def self.bench_range &block
- return super unless block
-
- meta = (class << self; self; end)
- meta.send :define_method, "bench_range", &block
- end
-
- ##
- # Create a benchmark that verifies that the performance is linear.
- #
- # describe "my class" do
- # bench_performance_linear "fast_algorithm", 0.9999 do |n|
- # @obj.fast_algorithm(n)
- # end
- # end
-
- def self.bench_performance_linear name, threshold = 0.99, &work
- bench name do
- assert_performance_linear threshold, &work
- end
- end
-
- ##
- # Create a benchmark that verifies that the performance is constant.
- #
- # describe "my class" do
- # bench_performance_constant "zoom_algorithm!" do |n|
- # @obj.zoom_algorithm!(n)
- # end
- # end
-
- def self.bench_performance_constant name, threshold = 0.99, &work
- bench name do
- assert_performance_constant threshold, &work
- end
- end
-
- ##
- # Create a benchmark that verifies that the performance is exponential.
- #
- # describe "my class" do
- # bench_performance_exponential "algorithm" do |n|
- # @obj.algorithm(n)
- # end
- # end
-
- def self.bench_performance_exponential name, threshold = 0.99, &work
- bench name do
- assert_performance_exponential threshold, &work
- end
- end
-end
diff --git a/test/lib/minitest/mock.rb b/test/lib/minitest/mock.rb
deleted file mode 100644
index 224b06cb89f..00000000000
--- a/test/lib/minitest/mock.rb
+++ /dev/null
@@ -1,196 +0,0 @@
-# encoding: utf-8
-# frozen_string_literal: true
-
-class MockExpectationError < StandardError; end # :nodoc:
-
-##
-# A simple and clean mock object framework.
-
-module MiniTest # :nodoc:
-
- ##
- # All mock objects are an instance of Mock
-
- class Mock
- alias :__respond_to? :respond_to?
-
- skip_methods = %w(object_id respond_to_missing? inspect === to_s)
-
- instance_methods.each do |m|
- undef_method m unless skip_methods.include?(m.to_s) || m =~ /^__/
- end
-
- def initialize # :nodoc:
- @expected_calls = Hash.new { |calls, name| calls[name] = [] }
- @actual_calls = Hash.new { |calls, name| calls[name] = [] }
- end
-
- ##
- # Expect that method +name+ is called, optionally with +args+ or a
- # +blk+, and returns +retval+.
- #
- # @mock.expect(:meaning_of_life, 42)
- # @mock.meaning_of_life # => 42
- #
- # @mock.expect(:do_something_with, true, [some_obj, true])
- # @mock.do_something_with(some_obj, true) # => true
- #
- # @mock.expect(:do_something_else, true) do |a1, a2|
- # a1 == "buggs" && a2 == :bunny
- # end
- #
- # +args+ is compared to the expected args using case equality (ie, the
- # '===' operator), allowing for less specific expectations.
- #
- # @mock.expect(:uses_any_string, true, [String])
- # @mock.uses_any_string("foo") # => true
- # @mock.verify # => true
- #
- # @mock.expect(:uses_one_string, true, ["foo"]
- # @mock.uses_one_string("bar") # => true
- # @mock.verify # => raises MockExpectationError
-
- def expect(name, retval, args=[], &blk)
- if block_given?
- raise ArgumentError, "args ignored when block given" unless args.empty?
- @expected_calls[name] << { :retval => retval, :block => blk }
- else
- raise ArgumentError, "args must be an array" unless Array === args
- @expected_calls[name] << { :retval => retval, :args => args }
- end
- self
- end
-
- def __call name, data # :nodoc:
- case data
- when Hash then
- "#{name}(#{data[:args].inspect[1..-2]}) => #{data[:retval].inspect}"
- else
- data.map { |d| __call name, d }.join ", "
- end
- end
-
- ##
- # Verify that all methods were called as expected. Raises
- # +MockExpectationError+ if the mock object was not called as
- # expected.
-
- def verify
- @expected_calls.each do |name, calls|
- calls.each do |expected|
- msg1 = "expected #{__call name, expected}"
- msg2 = "#{msg1}, got [#{__call name, @actual_calls[name]}]"
-
- raise MockExpectationError, msg2 if
- @actual_calls.has_key?(name) and
- not @actual_calls[name].include?(expected)
-
- raise MockExpectationError, msg1 unless
- @actual_calls.has_key?(name) and
- @actual_calls[name].include?(expected)
- end
- end
- true
- end
-
- def method_missing(sym, *args) # :nodoc:
- unless @expected_calls.has_key?(sym) then
- raise NoMethodError, "unmocked method %p, expected one of %p" %
- [sym, @expected_calls.keys.sort_by(&:to_s)]
- end
-
- index = @actual_calls[sym].length
- expected_call = @expected_calls[sym][index]
-
- unless expected_call then
- raise MockExpectationError, "No more expects available for %p: %p" %
- [sym, args]
- end
-
- expected_args, retval, val_block =
- expected_call.values_at(:args, :retval, :block)
-
- if val_block then
- raise MockExpectationError, "mocked method %p failed block w/ %p" %
- [sym, args] unless val_block.call(args)
-
- # keep "verify" happy
- @actual_calls[sym] << expected_call
- return retval
- end
-
- if expected_args.size != args.size then
- raise ArgumentError, "mocked method %p expects %d arguments, got %d" %
- [sym, expected_args.size, args.size]
- end
-
- fully_matched = expected_args.zip(args).all? { |mod, a|
- mod === a or mod == a
- }
-
- unless fully_matched then
- raise MockExpectationError, "mocked method %p called with unexpected arguments %p" %
- [sym, args]
- end
-
- @actual_calls[sym] << {
- :retval => retval,
- :args => expected_args.zip(args).map { |mod, a| mod === a ? mod : a }
- }
-
- retval
- end
-
- def respond_to?(sym, include_private = false) # :nodoc:
- return true if @expected_calls.has_key?(sym.to_sym)
- return __respond_to?(sym, include_private)
- end
- end
-end
-
-class Object # :nodoc:
-
- ##
- # Add a temporary stubbed method replacing +name+ for the duration
- # of the +block+. If +val_or_callable+ responds to #call, then it
- # returns the result of calling it, otherwise returns the value
- # as-is. Cleans up the stub at the end of the +block+. The method
- # +name+ must exist before stubbing.
- #
- # def test_stale_eh
- # obj_under_test = Something.new
- # refute obj_under_test.stale?
- #
- # Time.stub :now, Time.at(0) do
- # assert obj_under_test.stale?
- # end
- # end
-
- def stub name, val_or_callable, &block
- new_name = "__minitest_stub__#{name}"
-
- metaclass = class << self; self; end
-
- if respond_to? name and not methods.map(&:to_s).include? name.to_s then
- metaclass.send :define_method, name do |*args|
- super(*args)
- end
- end
-
- metaclass.send :alias_method, new_name, name
-
- metaclass.send :define_method, name do |*args|
- if val_or_callable.respond_to? :call then
- val_or_callable.call(*args)
- else
- val_or_callable
- end
- end
-
- yield self
- ensure
- metaclass.send :undef_method, name
- metaclass.send :alias_method, name, new_name
- metaclass.send :undef_method, new_name
- end
-end
diff --git a/test/lib/minitest/unit.rb b/test/lib/minitest/unit.rb
deleted file mode 100644
index d922a5fc412..00000000000
--- a/test/lib/minitest/unit.rb
+++ /dev/null
@@ -1,1420 +0,0 @@
-# encoding: utf-8
-# frozen_string_literal: true
-
-require "optparse"
-require "rbconfig"
-require "leakchecker"
-
-##
-# Minimal (mostly drop-in) replacement for test-unit.
-#
-# :include: README.txt
-
-module MiniTest
-
- def self.const_missing name # :nodoc:
- case name
- when :MINI_DIR then
- msg = "MiniTest::MINI_DIR was removed. Don't violate other's internals."
- warn "WAR\NING: #{msg}"
- warn "WAR\NING: Used by #{caller.first}."
- const_set :MINI_DIR, "bad value"
- else
- super
- end
- end
-
- ##
- # Assertion base class
-
- class Assertion < Exception; end
-
- ##
- # Assertion raised when skipping a test
-
- class Skip < Assertion; end
-
- class << self
- ##
- # Filter object for backtraces.
-
- attr_accessor :backtrace_filter
- end
-
- class BacktraceFilter # :nodoc:
- def filter bt
- return ["No backtrace"] unless bt
-
- new_bt = []
-
- unless $DEBUG then
- bt.each do |line|
- break if line =~ /lib\/minitest/
- new_bt << line
- end
-
- new_bt = bt.reject { |line| line =~ /lib\/minitest/ } if new_bt.empty?
- new_bt = bt.dup if new_bt.empty?
- else
- new_bt = bt.dup
- end
-
- new_bt
- end
- end
-
- self.backtrace_filter = BacktraceFilter.new
-
- def self.filter_backtrace bt # :nodoc:
- backtrace_filter.filter bt
- end
-
- ##
- # MiniTest Assertions. All assertion methods accept a +msg+ which is
- # printed if the assertion fails.
-
- module Assertions
- ##
- # Returns the diff command to use in #diff. Tries to intelligently
- # figure out what diff to use.
-
- def self.diff
- unless defined? @diff
- exe = RbConfig::CONFIG['EXEEXT']
- @diff = %W"gdiff#{exe} diff#{exe}".find do |diff|
- if system(diff, "-u", __FILE__, __FILE__)
- break "#{diff} -u"
- end
- end
- end
-
- @diff
- end
-
- ##
- # Set the diff command to use in #diff.
-
- def self.diff= o
- @diff = o
- end
-
- ##
- # Returns a diff between +exp+ and +act+. If there is no known
- # diff command or if it doesn't make sense to diff the output
- # (single line, short output), then it simply returns a basic
- # comparison between the two.
-
- def diff exp, act
- require "tempfile"
-
- expect = mu_pp_for_diff exp
- butwas = mu_pp_for_diff act
- result = nil
-
- need_to_diff =
- MiniTest::Assertions.diff &&
- (expect.include?("\n") ||
- butwas.include?("\n") ||
- expect.size > 30 ||
- butwas.size > 30 ||
- expect == butwas)
-
- return "Expected: #{mu_pp exp}\n Actual: #{mu_pp act}" unless
- need_to_diff
-
- tempfile_a = nil
- tempfile_b = nil
-
- Tempfile.open("expect") do |a|
- tempfile_a = a
- a.puts expect
- a.flush
-
- Tempfile.open("butwas") do |b|
- tempfile_b = b
- b.puts butwas
- b.flush
-
- result = `#{MiniTest::Assertions.diff} #{a.path} #{b.path}`
- result.sub!(/^\-\-\- .+/, "--- expected")
- result.sub!(/^\+\+\+ .+/, "+++ actual")
-
- if result.empty? then
- klass = exp.class
- result = [
- "No visible difference in the #{klass}#inspect output.\n",
- "You should look at the implementation of #== on ",
- "#{klass} or its members.\n",
- expect,
- ].join
- end
- end
- end
-
- result
- ensure
- tempfile_a.close! if tempfile_a
- tempfile_b.close! if tempfile_b
- end
-
- ##
- # This returns a human-readable version of +obj+. By default
- # #inspect is called. You can override this to use #pretty_print
- # if you want.
-
- def mu_pp obj
- s = obj.inspect
- s = s.encode Encoding.default_external if defined? Encoding
- s
- end
-
- ##
- # This returns a diff-able human-readable version of +obj+. This
- # differs from the regular mu_pp because it expands escaped
- # newlines and makes hex-values generic (like object_ids). This
- # uses mu_pp to do the first pass and then cleans it up.
-
- def mu_pp_for_diff obj
- mu_pp(obj).gsub(/(?<!\\)(?:\\\\)*\K\\n/, "\n").gsub(/:0x[a-fA-F0-9]{4,}/m, ':0xXXXXXX')
- end
-
- def _assertions= n # :nodoc:
- @_assertions = n
- end
-
- def _assertions # :nodoc:
- @_assertions ||= 0
- end
-
- ##
- # Fails unless +test+ is a true value.
-
- def assert test, msg = nil
- msg ||= "Failed assertion, no message given."
- self._assertions += 1
- unless test then
- msg = msg.call if Proc === msg
- raise MiniTest::Assertion, msg
- end
- true
- end
-
- ##
- # Fails unless +obj+ is empty.
-
- def assert_empty obj, msg = nil
- msg = message(msg) { "Expected #{mu_pp(obj)} to be empty" }
- assert_respond_to obj, :empty?
- assert obj.empty?, msg
- end
-
- ##
- # Fails unless <tt>exp == act</tt> printing the difference between
- # the two, if possible.
- #
- # If there is no visible difference but the assertion fails, you
- # should suspect that your #== is buggy, or your inspect output is
- # missing crucial details.
- #
- # For floats use assert_in_delta.
- #
- # See also: MiniTest::Assertions.diff
-
- def assert_equal exp, act, msg = nil
- msg = message(msg, "") { diff exp, act }
- assert exp == act, msg
- end
-
- ##
- # For comparing Floats. Fails unless +exp+ and +act+ are within +delta+
- # of each other.
- #
- # assert_in_delta Math::PI, (22.0 / 7.0), 0.01
-
- def assert_in_delta exp, act, delta = 0.001, msg = nil
- n = (exp - act).abs
- msg = message(msg) {
- "Expected |#{exp} - #{act}| (#{n}) to be <= #{delta}"
- }
- assert delta >= n, msg
- end
-
- ##
- # For comparing Floats. Fails unless +exp+ and +act+ have a relative
- # error less than +epsilon+.
-
- def assert_in_epsilon a, b, epsilon = 0.001, msg = nil
- assert_in_delta a, b, [a.abs, b.abs].min * epsilon, msg
- end
-
- ##
- # Fails unless +collection+ includes +obj+.
-
- def assert_includes collection, obj, msg = nil
- msg = message(msg) {
- "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}"
- }
- assert_respond_to collection, :include?
- assert collection.include?(obj), msg
- end
-
- ##
- # Fails unless +obj+ is an instance of +cls+.
-
- def assert_instance_of cls, obj, msg = nil
- msg = message(msg) {
- "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}"
- }
-
- assert obj.instance_of?(cls), msg
- end
-
- ##
- # Fails unless +obj+ is a kind of +cls+.
-
- def assert_kind_of cls, obj, msg = nil # TODO: merge with instance_of
- msg = message(msg) {
- "Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" }
-
- assert obj.kind_of?(cls), msg
- end
-
- ##
- # Fails unless +matcher+ <tt>=~</tt> +obj+.
-
- def assert_match matcher, obj, msg = nil
- msg = message(msg) { "Expected #{mu_pp matcher} to match #{mu_pp obj}" }
- assert_respond_to matcher, :"=~"
- matcher = Regexp.new Regexp.escape matcher if String === matcher
- assert matcher =~ obj, msg
- end
-
- ##
- # Fails unless +obj+ is nil
-
- def assert_nil obj, msg = nil
- msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" }
- assert obj.nil?, msg
- end
-
- ##
- # For testing with binary operators.
- #
- # assert_operator 5, :<=, 4
-
- def assert_operator o1, op, o2 = (predicate = true; nil), msg = nil
- return assert_predicate o1, op, msg if predicate
- msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" }
- assert o1.__send__(op, o2), msg
- end
-
- ##
- # Fails if stdout or stderr do not output the expected results.
- # Pass in nil if you don't care about that streams output. Pass in
- # "" if you require it to be silent. Pass in a regexp if you want
- # to pattern match.
- #
- # NOTE: this uses #capture_io, not #capture_subprocess_io.
- #
- # See also: #assert_silent
-
- def assert_output stdout = nil, stderr = nil
- out, err = capture_io do
- yield
- end
-
- err_msg = Regexp === stderr ? :assert_match : :assert_equal if stderr
- out_msg = Regexp === stdout ? :assert_match : :assert_equal if stdout
-
- y = send err_msg, stderr, err, "In stderr" if err_msg
- x = send out_msg, stdout, out, "In stdout" if out_msg
-
- (!stdout || x) && (!stderr || y)
- end
-
- ##
- # For testing with predicates.
- #
- # assert_predicate str, :empty?
- #
- # This is really meant for specs and is front-ended by assert_operator:
- #
- # str.must_be :empty?
-
- def assert_predicate o1, op, msg = nil
- msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op}" }
- assert o1.__send__(op), msg
- end
-
- ##
- # Fails unless the block raises one of +exp+. Returns the
- # exception matched so you can check the message, attributes, etc.
-
- def assert_raises *exp
- msg = "#{exp.pop}.\n" if String === exp.last
-
- 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 {
- exception_details(e, "#{msg}#{mu_pp(exp)} exception expected, not")
- }
-
- return e
- end
-
- exp = exp.first if exp.size == 1
-
- flunk "#{msg}#{mu_pp(exp)} expected but nothing was raised."
- end
-
- ##
- # Fails unless +obj+ responds to +meth+.
-
- def assert_respond_to obj, meth, msg = nil
- msg = message(msg) {
- "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}"
- }
- assert obj.respond_to?(meth), msg
- end
-
- ##
- # Fails unless +exp+ and +act+ are #equal?
-
- def assert_same exp, act, msg = nil
- msg = message(msg) {
- data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
- "Expected %s (oid=%d) to be the same as %s (oid=%d)" % data
- }
- assert exp.equal?(act), msg
- end
-
- ##
- # +send_ary+ is a receiver, message and arguments.
- #
- # Fails unless the call returns a true value
- # TODO: I should prolly remove this from specs
-
- def assert_send send_ary, m = nil
- recv, msg, *args = send_ary
- m = message(m) {
- "Expected #{mu_pp(recv)}.#{msg}(*#{mu_pp(args)}) to return true" }
- assert recv.__send__(msg, *args), m
- end
-
- ##
- # Fails if the block outputs anything to stderr or stdout.
- #
- # See also: #assert_output
-
- def assert_silent
- assert_output "", "" do
- yield
- end
- end
-
- ##
- # Fails unless the block throws +sym+
-
- def assert_throws sym, msg = nil
- default = "Expected #{mu_pp(sym)} to have been thrown"
- caught = true
- catch(sym) do
- begin
- yield
- rescue ThreadError => e # wtf?!? 1.8 + threads == suck
- default += ", not \:#{e.message[/uncaught throw \`(\w+?)\'/, 1]}"
- rescue ArgumentError => e # 1.9 exception
- default += ", not #{e.message.split(/ /).last}"
- rescue NameError => e # 1.8 exception
- default += ", not #{e.name.inspect}"
- end
- caught = false
- end
-
- assert caught, message(msg) { default }
- end
-
- ##
- # Captures $stdout and $stderr into strings:
- #
- # out, err = capture_io do
- # puts "Some info"
- # warn "You did a bad thing"
- # end
- #
- # assert_match %r%info%, out
- # assert_match %r%bad%, err
- #
- # NOTE: For efficiency, this method uses StringIO and does not
- # capture IO for subprocesses. Use #capture_subprocess_io for
- # that.
-
- def capture_io
- require 'stringio'
-
- captured_stdout, captured_stderr = StringIO.new, StringIO.new
-
- synchronize do
- orig_stdout, orig_stderr = $stdout, $stderr
- $stdout, $stderr = captured_stdout, captured_stderr
-
- begin
- yield
- ensure
- $stdout = orig_stdout
- $stderr = orig_stderr
- end
- end
-
- return captured_stdout.string, captured_stderr.string
- end
-
- ##
- # Captures $stdout and $stderr into strings, using Tempfile to
- # ensure that subprocess IO is captured as well.
- #
- # out, err = capture_subprocess_io do
- # system "echo Some info"
- # system "echo You did a bad thing 1>&2"
- # end
- #
- # assert_match %r%info%, out
- # assert_match %r%bad%, err
- #
- # NOTE: This method is approximately 10x slower than #capture_io so
- # only use it when you need to test the output of a subprocess.
-
- def capture_subprocess_io
- require 'tempfile'
-
- captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err")
-
- synchronize do
- orig_stdout, orig_stderr = $stdout.dup, $stderr.dup
- $stdout.reopen captured_stdout
- $stderr.reopen captured_stderr
-
- begin
- yield
-
- $stdout.rewind
- $stderr.rewind
-
- [captured_stdout.read, captured_stderr.read]
- ensure
- $stdout.reopen orig_stdout
- $stderr.reopen orig_stderr
- orig_stdout.close
- orig_stderr.close
- captured_stdout.close!
- captured_stderr.close!
- end
- end
- end
-
- ##
- # Returns details for exception +e+
-
- def exception_details e, msg
- [
- "#{msg}",
- "Class: <#{e.class}>",
- "Message: <#{e.message.inspect}>",
- "---Backtrace---",
- "#{MiniTest::filter_backtrace(e.backtrace).join("\n")}",
- "---------------",
- ].join "\n"
- end
-
- ##
- # Fails with +msg+
-
- def flunk msg = nil
- msg ||= "Epic Fail!"
- assert false, msg
- end
-
- ##
- # Returns a proc that will output +msg+ along with the default message.
-
- def message msg = nil, ending = ".", &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
-
- ##
- # used for counting assertions
-
- def pass msg = nil
- assert true
- end
-
- ##
- # Fails if +test+ is a true value
-
- def refute test, msg = nil
- msg ||= "Failed refutation, no message given"
- not assert(! test, msg)
- end
-
- ##
- # Fails if +obj+ is empty.
-
- def refute_empty obj, msg = nil
- msg = message(msg) { "Expected #{mu_pp(obj)} to not be empty" }
- assert_respond_to obj, :empty?
- refute obj.empty?, msg
- end
-
- ##
- # Fails if <tt>exp == act</tt>.
- #
- # For floats use refute_in_delta.
-
- def refute_equal exp, act, msg = nil
- msg = message(msg) {
- "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}"
- }
- refute exp == act, msg
- end
-
- ##
- # For comparing Floats. Fails if +exp+ is within +delta+ of +act+.
- #
- # refute_in_delta Math::PI, (22.0 / 7.0)
-
- def refute_in_delta exp, act, delta = 0.001, msg = nil
- n = (exp - act).abs
- msg = message(msg) {
- "Expected |#{exp} - #{act}| (#{n}) to not be <= #{delta}"
- }
- refute delta >= n, msg
- end
-
- ##
- # For comparing Floats. Fails if +exp+ and +act+ have a relative error
- # less than +epsilon+.
-
- def refute_in_epsilon a, b, epsilon = 0.001, msg = nil
- refute_in_delta a, b, a * epsilon, msg
- end
-
- ##
- # Fails if +collection+ includes +obj+.
-
- def refute_includes collection, obj, msg = nil
- msg = message(msg) {
- "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}"
- }
- assert_respond_to collection, :include?
- refute collection.include?(obj), msg
- end
-
- ##
- # Fails if +obj+ is an instance of +cls+.
-
- def refute_instance_of cls, obj, msg = nil
- msg = message(msg) {
- "Expected #{mu_pp(obj)} to not be an instance of #{cls}"
- }
- refute obj.instance_of?(cls), msg
- end
-
- ##
- # Fails if +obj+ is a kind of +cls+.
-
- def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of
- msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" }
- refute obj.kind_of?(cls), msg
- end
-
- ##
- # Fails if +matcher+ <tt>=~</tt> +obj+.
-
- def refute_match matcher, obj, msg = nil
- msg = message(msg) {"Expected #{mu_pp matcher} to not match #{mu_pp obj}"}
- assert_respond_to matcher, :"=~"
- matcher = Regexp.new Regexp.escape matcher if String === matcher
- refute matcher =~ obj, msg
- end
-
- ##
- # Fails if +obj+ is nil.
-
- def refute_nil obj, msg = nil
- msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" }
- refute obj.nil?, msg
- end
-
- ##
- # Fails if +o1+ is not +op+ +o2+. Eg:
- #
- # refute_operator 1, :>, 2 #=> pass
- # refute_operator 1, :<, 2 #=> fail
-
- def refute_operator o1, op, o2 = (predicate = true; nil), msg = nil
- return refute_predicate o1, op, msg if predicate
- msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}"}
- refute o1.__send__(op, o2), msg
- end
-
- ##
- # For testing with predicates.
- #
- # refute_predicate str, :empty?
- #
- # This is really meant for specs and is front-ended by refute_operator:
- #
- # str.wont_be :empty?
-
- def refute_predicate o1, op, msg = nil
- msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op}" }
- refute o1.__send__(op), msg
- end
-
- ##
- # Fails if +obj+ responds to the message +meth+.
-
- def refute_respond_to obj, meth, msg = nil
- msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" }
-
- refute obj.respond_to?(meth), msg
- end
-
- ##
- # Fails if +exp+ is the same (by object identity) as +act+.
-
- def refute_same exp, act, msg = nil
- msg = message(msg) {
- data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
- "Expected %s (oid=%d) to not be the same as %s (oid=%d)" % data
- }
- refute exp.equal?(act), msg
- end
-
- ##
- # Skips the current test. Gets listed at the end of the run but
- # doesn't cause a failure exit code.
-
- def skip msg = nil, bt = caller
- msg ||= "Skipped, no message given"
- @skip = true
- raise MiniTest::Skip, msg, bt
- end
-
- ##
- # Was this testcase skipped? Meant for #teardown.
-
- def skipped?
- defined?(@skip) and @skip
- end
-
- ##
- # Takes a block and wraps it with the runner's shared mutex.
-
- def synchronize
- Minitest::Unit.runner.synchronize do
- yield
- end
- end
- end
-
- class Unit # :nodoc:
- VERSION = "4.7.5" # :nodoc:
-
- attr_accessor :report, :failures, :errors, :skips # :nodoc:
- attr_accessor :assertion_count # :nodoc:
- attr_writer :test_count # :nodoc:
- attr_accessor :start_time # :nodoc:
- attr_accessor :help # :nodoc:
- attr_accessor :verbose # :nodoc:
- attr_writer :options # :nodoc:
-
- ##
- # :attr:
- #
- # if true, installs an "INFO" signal handler (only available to BSD and
- # OS X users) which prints diagnostic information about the test run.
- #
- # This is auto-detected by default but may be overridden by custom
- # runners.
-
- attr_accessor :info_signal
-
- ##
- # Lazy accessor for options.
-
- def options
- @options ||= {}
- end
-
- @@installed_at_exit ||= false
- @@out = $stdout
- @@after_tests = []
-
- ##
- # A simple hook allowing you to run a block of code after _all_ of
- # the tests are done. Eg:
- #
- # MiniTest::Unit.after_tests { p $debugging_info }
-
- def self.after_tests &block
- @@after_tests << block
- end
-
- ##
- # Registers MiniTest::Unit to run tests at process exit
-
- def self.autorun
- at_exit {
- # don't run if there was a non-exit exception
- next if $! and not $!.kind_of? SystemExit
-
- # the order here is important. The at_exit handler must be
- # installed before anyone else gets a chance to install their
- # own, that way we can be assured that our exit will be last
- # to run (at_exit stacks).
- exit_code = nil
-
- at_exit {
- @@after_tests.reverse_each(&:call)
- exit false if exit_code && exit_code != 0
- }
-
- exit_code = MiniTest::Unit.new.run ARGV
- } unless @@installed_at_exit
- @@installed_at_exit = true
- end
-
- ##
- # Returns the stream to use for output.
-
- def self.output
- @@out
- end
-
- ##
- # Sets MiniTest::Unit to write output to +stream+. $stdout is the default
- # output
-
- def self.output= stream
- @@out = stream
- end
-
- ##
- # Tells MiniTest::Unit to delegate to +runner+, an instance of a
- # MiniTest::Unit subclass, when MiniTest::Unit#run is called.
-
- def self.runner= runner
- @@runner = runner
- end
-
- ##
- # Returns the MiniTest::Unit subclass instance that will be used
- # to run the tests. A MiniTest::Unit instance is the default
- # runner.
-
- def self.runner
- @@runner ||= self.new
- end
-
- ##
- # Return all plugins' run methods (methods that start with "run_").
-
- def self.plugins
- @@plugins ||= (["run_tests"] +
- public_instance_methods(false).
- grep(/^run_/).map { |s| s.to_s }).uniq
- end
-
- ##
- # Return the IO for output.
-
- def output
- self.class.output
- end
-
- def puts *a # :nodoc:
- output.puts(*a)
- end
-
- def print *a # :nodoc:
- output.print(*a)
- end
-
- def test_count # :nodoc:
- @test_count ||= 0
- end
-
- ##
- # Runner for a given +type+ (eg, test vs bench).
-
- def _run_anything type
- suites = TestCase.send "#{type}_suites"
- return if suites.empty?
-
- puts
- puts "# Running #{type}s:"
- puts
-
- @test_count, @assertion_count = 0, 0
- test_count = assertion_count = 0
- sync = output.respond_to? :"sync=" # stupid emacs
- old_sync, output.sync = output.sync, true if sync
-
- count = 0
- begin
- start = Time.now
-
- results = _run_suites suites, type
-
- @test_count = results.inject(0) { |sum, (tc, _)| sum + tc }
- @assertion_count = results.inject(0) { |sum, (_, ac)| sum + ac }
- test_count += @test_count
- assertion_count += @assertion_count
- t = Time.now - start
- count += 1
- unless @repeat_count
- puts
- puts
- end
- puts "Finished%s %ss in %.6fs, %.4f tests/s, %.4f assertions/s.\n" %
- [(@repeat_count ? "(#{count}/#{@repeat_count}) " : ""), type,
- t, @test_count.fdiv(t), @assertion_count.fdiv(t)]
- end while @repeat_count && count < @repeat_count &&
- report.empty? && failures.zero? && errors.zero?
-
- output.sync = old_sync if sync
-
- report.each_with_index do |msg, i|
- puts "\n%3d) %s" % [i + 1, msg]
- end
-
- puts
- @test_count = test_count
- @assertion_count = assertion_count
-
- status
- end
-
- ##
- # Runs all the +suites+ for a given +type+.
- #
-
- def _run_suites suites, type
- suites.map { |suite| _run_suite suite, type }
- end
-
- ##
- # Run a single +suite+ for a given +type+.
-
- def _run_suite suite, type
- header = "#{type}_suite_header"
- puts send(header, suite) if respond_to? header
-
- filter = options[:filter] || '/./'
- filter = Regexp.new $1 if filter =~ /\/(.*)\//
-
- all_test_methods = suite.send "#{type}_methods"
-
- filtered_test_methods = all_test_methods.find_all { |m|
- filter === m || filter === "#{suite}##{m}"
- }
-
- leakchecker = LeakChecker.new
-
- assertions = filtered_test_methods.map { |method|
- inst = suite.new method
- inst._assertions = 0
-
- print "#{suite}##{method} = " if @verbose
-
- start_time = Time.now if @verbose
- result = inst.run self
-
- print "%.2f s = " % (Time.now - start_time) if @verbose
- print result
- puts if @verbose
- $stdout.flush
-
- unless defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # compiler process is wrongly considered as leak
- leakchecker.check("#{inst.class}\##{inst.__name__}")
- end
-
- inst._assertions
- }
-
- return assertions.size, assertions.inject(0) { |sum, n| sum + n }
- end
-
- ##
- # Record the result of a single test. Makes it very easy to gather
- # information. Eg:
- #
- # class StatisticsRecorder < MiniTest::Unit
- # def record suite, method, assertions, time, error
- # # ... record the results somewhere ...
- # end
- # end
- #
- # MiniTest::Unit.runner = StatisticsRecorder.new
- #
- # NOTE: record might be sent more than once per test. It will be
- # sent once with the results from the test itself. If there is a
- # failure or error in teardown, it will be sent again with the
- # error or failure.
-
- def record suite, method, assertions, time, error
- end
-
- def location e # :nodoc:
- last_before_assertion = ""
- e.backtrace.reverse_each do |s|
- break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
- last_before_assertion = s
- end
- last_before_assertion.sub(/:in .*$/, '')
- end
-
- ##
- # Writes status for failed test +meth+ in +klass+ which finished with
- # exception +e+
-
- def puke klass, meth, e
- e = case e
- when MiniTest::Skip then
- @skips += 1
- return "S" unless @verbose
- "Skipped:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n"
- when MiniTest::Assertion then
- @failures += 1
- "Failure:\n#{klass}##{meth} [#{location e}]:\n#{e.message}\n"
- else
- @errors += 1
- bt = MiniTest::filter_backtrace(e.backtrace).join "\n "
- "Error:\n#{klass}##{meth}:\n#{e.class}: #{e.message.b}\n #{bt}\n"
- end
- @report << e
- e[0, 1]
- end
-
- def initialize # :nodoc:
- @report = []
- @errors = @failures = @skips = 0
- @verbose = false
- @mutex = Thread::Mutex.new
- @info_signal = Signal.list['INFO']
- @repeat_count = nil
- end
-
- def synchronize # :nodoc:
- if @mutex then
- @mutex.synchronize { yield }
- else
- yield
- end
- end
-
- def process_args args = [] # :nodoc:
- options = {}
- orig_args = args.dup
-
- OptionParser.new do |opts|
- opts.banner = 'minitest options:'
- opts.version = MiniTest::Unit::VERSION
-
- opts.on '-h', '--help', 'Display this help.' do
- puts opts
- exit
- end
-
- opts.on '-s', '--seed SEED', Integer, "Sets random seed" do |m|
- options[:seed] = m.to_i
- end
-
- opts.on '-v', '--verbose', "Verbose. Show progress processing files." do
- options[:verbose] = true
- end
-
- opts.on '-n', '--name PATTERN', "Filter test names on pattern (e.g. /foo/)" do |a|
- options[:filter] = a
- end
-
- opts.parse! args
- orig_args -= args
- end
-
- unless options[:seed] then
- srand
- options[:seed] = srand % 0xFFFF
- orig_args << "--seed" << options[:seed].to_s
- end
-
- srand options[:seed]
-
- self.verbose = options[:verbose]
- @help = orig_args.map { |s| s =~ /[\s|&<>$()]/ ? s.inspect : s }.join " "
-
- options
- end
-
- ##
- # Begins the full test run. Delegates to +runner+'s #_run method.
-
- def run args = []
- self.class.runner._run(args)
- end
-
- ##
- # Top level driver, controls all output and filtering.
-
- def _run args = []
- args = process_args args # ARGH!! blame test/unit process_args
- self.options.merge! args
-
- puts "Run options: #{help}"
-
- self.class.plugins.each do |plugin|
- send plugin
- break unless report.empty?
- end
-
- return failures + errors if self.test_count > 0 # or return nil...
- rescue Interrupt
- abort 'Interrupted'
- end
-
- ##
- # Runs test suites matching +filter+.
-
- def run_tests
- _run_anything :test
- end
-
- ##
- # Writes status to +io+
-
- def status io = self.output
- format = "%d tests, %d assertions, %d failures, %d errors, %d skips"
- io.puts format % [test_count, assertion_count, failures, errors, skips]
- end
-
- ##
- # Provides a simple set of guards that you can use in your tests
- # to skip execution if it is not applicable. These methods are
- # mixed into TestCase as both instance and class methods so you
- # can use them inside or outside of the test methods.
- #
- # def test_something_for_mri
- # skip "bug 1234" if jruby?
- # # ...
- # end
- #
- # if windows? then
- # # ... lots of test methods ...
- # end
-
- module Guard
-
- ##
- # Is this running on jruby?
-
- def jruby? platform = RUBY_PLATFORM
- "java" == platform
- end
-
- ##
- # Is this running on mri?
-
- def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
- "maglev" == platform
- end
-
- module_function :maglev?
-
- ##
- # Is this running on mri?
-
- def mri? platform = RUBY_DESCRIPTION
- /^ruby/ =~ platform
- end
-
- ##
- # Is this running on rubinius?
-
- def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
- "rbx" == platform
- end
-
- ##
- # Is this running on windows?
-
- def windows? platform = RUBY_PLATFORM
- /mswin|mingw/ =~ platform
- end
-
- ##
- # Is this running on mingw?
-
- def mingw? platform = RUBY_PLATFORM
- /mingw/ =~ platform
- end
-
- end
-
- ##
- # Provides before/after hooks for setup and teardown. These are
- # meant for library writers, NOT for regular test authors. See
- # #before_setup for an example.
-
- module LifecycleHooks
- ##
- # Runs before every test, after setup. This hook is meant for
- # libraries to extend minitest. It is not meant to be used by
- # test developers.
- #
- # See #before_setup for an example.
-
- def after_setup; end
-
- ##
- # Runs before every test, before setup. This hook is meant for
- # libraries to extend minitest. It is not meant to be used by
- # test developers.
- #
- # As a simplistic example:
- #
- # module MyMinitestPlugin
- # def before_setup
- # super
- # # ... stuff to do before setup is run
- # end
- #
- # def after_setup
- # # ... stuff to do after setup is run
- # super
- # end
- #
- # def before_teardown
- # super
- # # ... stuff to do before teardown is run
- # end
- #
- # def after_teardown
- # # ... stuff to do after teardown is run
- # super
- # end
- # end
- #
- # class MiniTest::Unit::TestCase
- # include MyMinitestPlugin
- # end
-
- def before_setup; end
-
- ##
- # Runs after every test, before teardown. This hook is meant for
- # libraries to extend minitest. It is not meant to be used by
- # test developers.
- #
- # See #before_setup for an example.
-
- def before_teardown; end
-
- ##
- # Runs after every test, after teardown. This hook is meant for
- # libraries to extend minitest. It is not meant to be used by
- # test developers.
- #
- # See #before_setup for an example.
-
- def after_teardown; end
- end
-
- ##
- # Subclass TestCase to create your own tests. Typically you'll want a
- # TestCase subclass per implementation class.
- #
- # See MiniTest::Assertions
-
- class TestCase
- include LifecycleHooks
- include Guard
- extend Guard
-
- attr_reader :__name__ # :nodoc:
-
- PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException,
- Interrupt, SystemExit] # :nodoc:
-
- ##
- # Runs the tests reporting the status to +runner+
-
- def run runner
- trap "INFO" do
- runner.report.each_with_index do |msg, i|
- warn "\n%3d) %s" % [i + 1, msg]
- end
- warn ''
- time = runner.start_time ? Time.now - runner.start_time : 0
- warn "Current Test: %s#%s %.2fs" % [self.class, self.__name__, time]
- runner.status $stderr
- end if runner.info_signal
-
- start_time = Time.now
-
- result = ""
- begin
- @passed = nil
- self.before_setup
- self.setup
- self.after_setup
- self.run_test self.__name__
- result = "." unless io?
- time = Time.now - start_time
- runner.record self.class, self.__name__, self._assertions, time, nil
- @passed = true
- rescue *PASSTHROUGH_EXCEPTIONS
- raise
- rescue Exception => e
- @passed = Skip === e
- time = Time.now - start_time
- runner.record self.class, self.__name__, self._assertions, time, e
- result = runner.puke self.class, self.__name__, e
- ensure
- %w{ before_teardown teardown after_teardown }.each do |hook|
- begin
- self.send hook
- rescue *PASSTHROUGH_EXCEPTIONS
- raise
- rescue Exception => e
- @passed = false
- runner.record self.class, self.__name__, self._assertions, time, e
- result = runner.puke self.class, self.__name__, e
- end
- end
- trap 'INFO', 'DEFAULT' if runner.info_signal
- end
- result
- end
-
- alias :run_test :__send__
-
- def initialize name # :nodoc:
- @__name__ = name
- @__io__ = nil
- @passed = nil
- @@current = self # FIX: make thread local
- end
-
- def self.current # :nodoc:
- @@current # FIX: make thread local
- end
-
- ##
- # Return the output IO object
-
- def io
- @__io__ = true
- MiniTest::Unit.output
- end
-
- ##
- # Have we hooked up the IO yet?
-
- def io?
- @__io__
- end
-
- def self.reset # :nodoc:
- @@test_suites = {}
- end
-
- reset
-
- ##
- # Make diffs for this TestCase use #pretty_inspect so that diff
- # in assert_equal can be more details. NOTE: this is much slower
- # than the regular inspect but much more usable for complex
- # objects.
-
- def self.make_my_diffs_pretty!
- require 'pp'
-
- define_method :mu_pp do |o|
- o.pretty_inspect
- end
- end
-
- def self.inherited klass # :nodoc:
- @@test_suites[klass] = true
- super
- end
-
- def self.test_order # :nodoc:
- :random
- end
-
- def self.test_suites # :nodoc:
- @@test_suites.keys.sort_by { |ts| ts.name.to_s }
- end
-
- def self.test_methods # :nodoc:
- methods = public_instance_methods(true).grep(/^test/).map { |m| m.to_s }
-
- case self.test_order
- when :parallel
- max = methods.size
- ParallelEach.new methods.sort.sort_by { rand max }
- when :random then
- max = methods.size
- methods.sort.sort_by { rand max }
- when :alpha, :sorted then
- methods.sort
- else
- raise "Unknown test_order: #{self.test_order.inspect}"
- end
- end
-
- ##
- # Returns true if the test passed.
-
- def passed?
- @passed
- end
-
- ##
- # Runs before every test. Use this to set up before each test
- # run.
-
- def setup; end
-
- ##
- # Runs after every test. Use this to clean up after each test
- # run.
-
- def teardown; end
-
- include MiniTest::Assertions
- end # class TestCase
- end # class Unit
-
- Test = Unit::TestCase
-end # module MiniTest
-
-Minitest = MiniTest # :nodoc: because ugh... I typo this all the time
diff --git a/test/lib/profile_test_all.rb b/test/lib/profile_test_all.rb
deleted file mode 100644
index 2c360d76ddc..00000000000
--- a/test/lib/profile_test_all.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-#
-# purpose:
-# Profile memory usage of each tests.
-#
-# usage:
-# RUBY_TEST_ALL_PROFILE=[file] make test-all
-#
-# output:
-# [file] specified by RUBY_TEST_ALL_PROFILE
-# If [file] is 'true', then it is ./test_all_profile
-#
-# collected information:
-# - ObjectSpace.memsize_of_all
-# - GC.stat
-# - /proc/meminfo (some fields, if exists)
-# - /proc/self/status (some fields, if exists)
-# - /proc/self/statm (if exists)
-#
-
-require 'objspace'
-
-class MiniTest::Unit::TestCase
- alias orig_run run
-
- file = ENV['RUBY_TEST_ALL_PROFILE']
- file = 'test-all-profile-result' if file == 'true'
- TEST_ALL_PROFILE_OUT = open(file, 'w')
- TEST_ALL_PROFILE_GC_STAT_HASH = {}
- TEST_ALL_PROFILE_BANNER = ['name']
- TEST_ALL_PROFILE_PROCS = []
-
- def self.add *name, &b
- TEST_ALL_PROFILE_BANNER.concat name
- TEST_ALL_PROFILE_PROCS << b
- end
-
- add 'failed?' do |result, tc|
- result << (tc.passed? ? 0 : 1)
- end
-
- add 'memsize_of_all' do |result, *|
- result << ObjectSpace.memsize_of_all
- end
-
- add(*GC.stat.keys) do |result, *|
- GC.stat(TEST_ALL_PROFILE_GC_STAT_HASH)
- result.concat TEST_ALL_PROFILE_GC_STAT_HASH.values
- end
-
- def self.add_proc_meminfo file, fields
- return unless FileTest.exist?(file)
- regexp = /(#{fields.join("|")}):\s*(\d+) kB/
- # check = {}; fields.each{|e| check[e] = true}
- add(*fields) do |result, *|
- text = File.read(file)
- text.scan(regexp){
- # check.delete $1
- result << $2
- ''
- }
- # raise check.inspect unless check.empty?
- end
- end
-
- add_proc_meminfo '/proc/meminfo', %w(MemTotal MemFree)
- add_proc_meminfo '/proc/self/status', %w(VmPeak VmSize VmHWM VmRSS)
-
- if FileTest.exist?('/proc/self/statm')
- add 'size', 'resident', 'share', 'text', 'lib', 'data', 'dt' do |result, *|
- result.concat File.read('/proc/self/statm').split(/\s+/)
- end
- end
-
- def memprofile_test_all_result_result
- result = ["#{self.class}\##{self.__name__.to_s.gsub(/\s+/, '')}"]
- TEST_ALL_PROFILE_PROCS.each{|proc|
- proc.call(result, self)
- }
- result.join("\t")
- end
-
- def run runner
- result = orig_run(runner)
- TEST_ALL_PROFILE_OUT.puts memprofile_test_all_result_result
- TEST_ALL_PROFILE_OUT.flush
- result
- end
-
- TEST_ALL_PROFILE_OUT.puts TEST_ALL_PROFILE_BANNER.join("\t")
-end
diff --git a/test/lib/test/unit.rb b/test/lib/test/unit.rb
deleted file mode 100644
index 3df6774d61f..00000000000
--- a/test/lib/test/unit.rb
+++ /dev/null
@@ -1,1175 +0,0 @@
-# frozen_string_literal: true
-begin
- gem 'minitest', '< 5.0.0' if defined? Gem
-rescue Gem::LoadError
-end
-require 'minitest/unit'
-require 'test/unit/assertions'
-require_relative '../envutil'
-require_relative '../../../tool/colorize'
-require 'test/unit/testcase'
-require 'optparse'
-
-# See Test::Unit
-module Test
- ##
- # Test::Unit is an implementation of the xUnit testing framework for Ruby.
- #
- # If you are writing new test code, please use MiniTest instead of Test::Unit.
- #
- # Test::Unit has been left in the standard library to support legacy test
- # suites.
- module Unit
- TEST_UNIT_IMPLEMENTATION = 'test/unit compatibility layer using minitest' # :nodoc:
-
- module RunCount # :nodoc: all
- @@run_count = 0
-
- def self.have_run?
- @@run_count.nonzero?
- end
-
- def run(*)
- @@run_count += 1
- super
- end
-
- def run_once
- return if have_run?
- return if $! # don't run if there was an exception
- yield
- end
- module_function :run_once
- end
-
- module Options # :nodoc: all
- def initialize(*, &block)
- @init_hook = block
- @options = nil
- super(&nil)
- end
-
- def option_parser
- @option_parser ||= OptionParser.new
- end
-
- def process_args(args = [])
- return @options if @options
- orig_args = args.dup
- options = {}
- opts = option_parser
- setup_options(opts, options)
- opts.parse!(args)
- orig_args -= args
- args = @init_hook.call(args, options) if @init_hook
- non_options(args, options)
- @run_options = orig_args
- @help = orig_args.map { |s| s =~ /[\s|&<>$()]/ ? s.inspect : s }.join " "
- @options = options
- end
-
- private
- def setup_options(opts, options)
- opts.separator 'minitest options:'
- opts.version = MiniTest::Unit::VERSION
-
- opts.on '-h', '--help', 'Display this help.' do
- puts opts
- exit
- end
-
- opts.on '-s', '--seed SEED', Integer, "Sets random seed" do |m|
- options[:seed] = m
- end
-
- opts.on '-v', '--verbose', "Verbose. Show progress processing files." do
- options[:verbose] = true
- self.verbose = options[:verbose]
- end
-
- opts.on '-n', '--name PATTERN', "Filter test method names on pattern: /REGEXP/, !/REGEXP/ or STRING" do |a|
- (options[:filter] ||= []) << a
- end
-
- opts.on '--test-order=random|alpha|sorted', [:random, :alpha, :sorted] do |a|
- MiniTest::Unit::TestCase.test_order = a
- end
- end
-
- def non_options(files, options)
- filter = options[:filter]
- if filter
- pos_pat = /\A\/(.*)\/\z/
- neg_pat = /\A!\/(.*)\/\z/
- negative, positive = filter.partition {|s| neg_pat =~ s}
- if positive.empty?
- filter = nil
- elsif negative.empty? and positive.size == 1 and pos_pat !~ positive[0]
- filter = positive[0]
- else
- filter = Regexp.union(*positive.map! {|s| Regexp.new(s[pos_pat, 1] || "\\A#{Regexp.quote(s)}\\z")})
- end
- unless negative.empty?
- negative = Regexp.union(*negative.map! {|s| Regexp.new(s[neg_pat, 1])})
- filter = /\A(?=.*#{filter})(?!.*#{negative})/
- end
- if Regexp === filter
- # bypass conversion in minitest
- def filter.=~(other) # :nodoc:
- super unless Regexp === other
- end
- end
- options[:filter] = filter
- end
- true
- end
- end
-
- module Parallel # :nodoc: all
- def process_args(args = [])
- return @options if @options
- options = super
- if @options[:parallel]
- @files = args
- end
- options
- end
-
- def non_options(files, options)
- @jobserver = nil
- makeflags = ENV.delete("MAKEFLAGS")
- if !options[:parallel] and
- /(?:\A|\s)--jobserver-(?:auth|fds)=(\d+),(\d+)/ =~ makeflags
- begin
- r = IO.for_fd($1.to_i(10), "rb", autoclose: false)
- w = IO.for_fd($2.to_i(10), "wb", autoclose: false)
- rescue
- r.close if r
- nil
- else
- r.close_on_exec = true
- w.close_on_exec = true
- @jobserver = [r, w]
- options[:parallel] ||= 1
- end
- end
- super
- end
-
- def status(*args)
- result = super
- raise @interrupt if @interrupt
- result
- end
-
- private
- def setup_options(opts, options)
- super
-
- opts.separator "parallel test options:"
-
- options[:retry] = true
-
- opts.on '-j N', '--jobs N', /\A(t)?(\d+)\z/, "Allow run tests with N jobs at once" do |_, t, a|
- options[:testing] = true & t # For testing
- options[:parallel] = a.to_i
- end
-
- opts.on '--separate', "Restart job process after one testcase has done" do
- options[:parallel] ||= 1
- options[:separate] = true
- end
-
- opts.on '--retry', "Retry running testcase when --jobs specified" do
- options[:retry] = true
- end
-
- opts.on '--no-retry', "Disable --retry" do
- options[:retry] = false
- end
-
- opts.on '--ruby VAL', "Path to ruby which is used at -j option" do |a|
- options[:ruby] = a.split(/ /).reject(&:empty?)
- end
- end
-
- class Worker
- def self.launch(ruby,args=[])
- scale = EnvUtil.timeout_scale
- io = IO.popen([*ruby, "-W1",
- "#{File.dirname(__FILE__)}/unit/parallel.rb",
- *("--timeout-scale=#{scale}" if scale),
- *args], "rb+")
- new(io, io.pid, :waiting)
- end
-
- attr_reader :quit_called
-
- def initialize(io, pid, status)
- @io = io
- @pid = pid
- @status = status
- @file = nil
- @real_file = nil
- @loadpath = []
- @hooks = {}
- @quit_called = false
- end
-
- def puts(*args)
- @io.puts(*args)
- end
-
- def run(task,type)
- @file = File.basename(task, ".rb")
- @real_file = task
- begin
- puts "loadpath #{[Marshal.dump($:-@loadpath)].pack("m0")}"
- @loadpath = $:.dup
- puts "run #{task} #{type}"
- @status = :prepare
- rescue Errno::EPIPE
- died
- rescue IOError
- raise unless /stream closed|closed stream/ =~ $!.message
- died
- end
- end
-
- def hook(id,&block)
- @hooks[id] ||= []
- @hooks[id] << block
- self
- end
-
- def read
- res = (@status == :quit) ? @io.read : @io.gets
- res && res.chomp
- end
-
- def close
- @io.close unless @io.closed?
- self
- rescue IOError
- end
-
- def quit
- return if @io.closed?
- @quit_called = true
- @io.puts "quit"
- rescue Errno::EPIPE => e
- warn "#{@pid}:#{@status.to_s.ljust(7)}:#{@file}: #{e.message}"
- end
-
- def kill
- Process.kill(:KILL, @pid)
- rescue Errno::ESRCH
- end
-
- def died(*additional)
- @status = :quit
- @io.close
- status = $?
- if status and status.signaled?
- additional[0] ||= SignalException.new(status.termsig)
- end
-
- call_hook(:dead,*additional)
- end
-
- def to_s
- if @file and @status != :ready
- "#{@pid}=#{@file}"
- else
- "#{@pid}:#{@status.to_s.ljust(7)}"
- end
- end
-
- attr_reader :io, :pid
- attr_accessor :status, :file, :real_file, :loadpath
-
- private
-
- def call_hook(id,*additional)
- @hooks[id] ||= []
- @hooks[id].each{|hook| hook[self,additional] }
- self
- end
-
- end
-
- def flush_job_tokens
- if @jobserver
- r, w = @jobserver.shift(2)
- @jobserver = nil
- w << @job_tokens.slice!(0..-1)
- r.close
- w.close
- end
- end
-
- def after_worker_down(worker, e=nil, c=false)
- return unless @options[:parallel]
- return if @interrupt
- flush_job_tokens
- warn e if e
- real_file = worker.real_file and warn "running file: #{real_file}"
- @need_quit = true
- warn ""
- warn "Some worker was crashed. It seems ruby interpreter's bug"
- warn "or, a bug of test/unit/parallel.rb. try again without -j"
- warn "option."
- warn ""
- STDERR.flush
- exit c
- end
-
- def after_worker_quit(worker)
- return unless @options[:parallel]
- return if @interrupt
- worker.close
- if @jobserver and (token = @job_tokens.slice!(0))
- @jobserver[1] << token
- end
- @workers.delete(worker)
- @dead_workers << worker
- @ios = @workers.map(&:io)
- end
-
- def launch_worker
- begin
- worker = Worker.launch(@options[:ruby], @run_options)
- rescue => e
- abort "ERROR: Failed to launch job process - #{e.class}: #{e.message}"
- end
- worker.hook(:dead) do |w,info|
- after_worker_quit w
- after_worker_down w, *info if !info.empty? && !worker.quit_called
- end
- @workers << worker
- @ios << worker.io
- @workers_hash[worker.io] = worker
- worker
- end
-
- def delete_worker(worker)
- @workers_hash.delete worker.io
- @workers.delete worker
- @ios.delete worker.io
- end
-
- def quit_workers
- return if @workers.empty?
- @workers.reject! do |worker|
- begin
- Timeout.timeout(1) do
- worker.quit
- end
- rescue Errno::EPIPE
- rescue Timeout::Error
- end
- worker.close
- end
-
- return if @workers.empty?
- begin
- Timeout.timeout(0.2 * @workers.size) do
- Process.waitall
- end
- rescue Timeout::Error
- @workers.each do |worker|
- worker.kill
- end
- @worker.clear
- end
- end
-
- FakeClass = Struct.new(:name)
- def fake_class(name)
- (@fake_classes ||= {})[name] ||= FakeClass.new(name)
- end
-
- def deal(io, type, result, rep, shutting_down = false)
- worker = @workers_hash[io]
- cmd = worker.read
- cmd.sub!(/\A\.+/, '') if cmd # read may return nil
- case cmd
- when ''
- # just only dots, ignore
- when /^okay$/
- worker.status = :running
- when /^ready(!)?$/
- bang = $1
- worker.status = :ready
-
- unless task = @tasks.shift
- worker.quit
- return nil
- end
- if @options[:separate] and not bang
- worker.quit
- worker = launch_worker
- end
- worker.run(task, type)
- @test_count += 1
-
- jobs_status(worker)
- when /^done (.+?)$/
- begin
- r = Marshal.load($1.unpack("m")[0])
- rescue
- print "unknown object: #{$1.unpack("m")[0].dump}"
- return true
- end
- result << r[0..1] unless r[0..1] == [nil,nil]
- rep << {file: worker.real_file, report: r[2], result: r[3], testcase: r[5]}
- $:.push(*r[4]).uniq!
- jobs_status(worker) if @options[:job_status] == :replace
- return true
- when /^record (.+?)$/
- begin
- r = Marshal.load($1.unpack("m")[0])
- rescue => e
- print "unknown record: #{e.message} #{$1.unpack("m")[0].dump}"
- return true
- end
- record(fake_class(r[0]), *r[1..-1])
- when /^p (.+?)$/
- del_jobs_status
- print $1.unpack("m")[0]
- jobs_status(worker) if @options[:job_status] == :replace
- when /^after (.+?)$/
- @warnings << Marshal.load($1.unpack("m")[0])
- when /^bye (.+?)$/
- after_worker_down worker, Marshal.load($1.unpack("m")[0])
- when /^bye$/, nil
- if shutting_down || worker.quit_called
- after_worker_quit worker
- else
- after_worker_down worker
- end
- else
- print "unknown command: #{cmd.dump}\n"
- end
- return false
- end
-
- def _run_parallel suites, type, result
- if @options[:parallel] < 1
- warn "Error: parameter of -j option should be greater than 0."
- return
- end
-
- # Require needed thing for parallel running
- require 'timeout'
- @tasks = @files.dup # Array of filenames.
- @need_quit = false
- @dead_workers = [] # Array of dead workers.
- @warnings = []
- @total_tests = @tasks.size.to_s(10)
- rep = [] # FIXME: more good naming
-
- @workers = [] # Array of workers.
- @workers_hash = {} # out-IO => worker
- @ios = [] # Array of worker IOs
- @job_tokens = String.new(encoding: Encoding::ASCII_8BIT) if @jobserver
- begin
- [@tasks.size, @options[:parallel]].min.times {launch_worker}
-
- while _io = IO.select(@ios)[0]
- break if _io.any? do |io|
- @need_quit or
- (deal(io, type, result, rep).nil? and
- !@workers.any? {|x| [:running, :prepare].include? x.status})
- end
- if @jobserver and @job_tokens and !@tasks.empty? and !@workers.any? {|x| x.status == :ready}
- t = @jobserver[0].read_nonblock([@tasks.size, @options[:parallel]].min, exception: false)
- if String === t
- @job_tokens << t
- t.size.times {launch_worker}
- end
- end
- end
- rescue Interrupt => ex
- @interrupt = ex
- return result
- ensure
- if @interrupt
- @ios.select!{|x| @workers_hash[x].status == :running }
- while !@ios.empty? && (__io = IO.select(@ios,[],[],10))
- __io[0].reject! {|io| deal(io, type, result, rep, true)}
- end
- end
-
- quit_workers
- flush_job_tokens
-
- unless @interrupt || !@options[:retry] || @need_quit
- parallel = @options[:parallel]
- @options[:parallel] = false
- suites, rep = rep.partition {|r| r[:testcase] && r[:file] && r[:report].any? {|e| !e[2].is_a?(MiniTest::Skip)}}
- suites.map {|r| r[:file]}.uniq.each {|file| require file}
- suites.map! {|r| eval("::"+r[:testcase])}
- del_status_line or puts
- unless suites.empty?
- puts "\n""Retrying..."
- _run_suites(suites, type)
- end
- @options[:parallel] = parallel
- end
- unless @options[:retry]
- del_status_line or puts
- end
- unless rep.empty?
- rep.each do |r|
- r[:report].each do |f|
- puke(*f) if f
- end
- end
- if @options[:retry]
- @errors += rep.map{|x| x[:result][0] }.inject(:+)
- @failures += rep.map{|x| x[:result][1] }.inject(:+)
- @skips += rep.map{|x| x[:result][2] }.inject(:+)
- end
- end
- unless @warnings.empty?
- warn ""
- @warnings.uniq! {|w| w[1].message}
- @warnings.each do |w|
- warn "#{w[0]}: #{w[1].message} (#{w[1].class})"
- end
- warn ""
- end
- end
- end
-
- def _run_suites suites, type
- _prepare_run(suites, type)
- @interrupt = nil
- result = []
- GC.start
- if @options[:parallel]
- _run_parallel suites, type, result
- else
- suites.each {|suite|
- begin
- result << _run_suite(suite, type)
- rescue Interrupt => e
- @interrupt = e
- break
- end
- }
- end
- del_status_line
- result
- end
- end
-
- module Skipping # :nodoc: all
- def failed(s)
- super if !s or @options[:hide_skip]
- end
-
- private
- def setup_options(opts, options)
- super
-
- opts.separator "skipping options:"
-
- options[:hide_skip] = true
-
- opts.on '-q', '--hide-skip', 'Hide skipped tests' do
- options[:hide_skip] = true
- end
-
- opts.on '--show-skip', 'Show skipped tests' do
- options[:hide_skip] = false
- end
- end
-
- def _run_suites(suites, type)
- result = super
- report.reject!{|r| r.start_with? "Skipped:" } if @options[:hide_skip]
- report.sort_by!{|r| r.start_with?("Skipped:") ? 0 : \
- (r.start_with?("Failure:") ? 1 : 2) }
- failed(nil)
- result
- end
- end
-
- module Statistics
- def update_list(list, rec, max)
- if i = list.empty? ? 0 : list.bsearch_index {|*a| yield(*a)}
- list[i, 0] = [rec]
- list[max..-1] = [] if list.size >= max
- end
- end
-
- def record(suite, method, assertions, time, error)
- if @options.values_at(:longest, :most_asserted).any?
- @tops ||= {}
- rec = [suite.name, method, assertions, time, error]
- if max = @options[:longest]
- update_list(@tops[:longest] ||= [], rec, max) {|_,_,_,t,_|t<time}
- end
- if max = @options[:most_asserted]
- update_list(@tops[:most_asserted] ||= [], rec, max) {|_,_,a,_,_|a<assertions}
- end
- end
- # (((@record ||= {})[suite] ||= {})[method]) = [assertions, time, error]
- super
- end
-
- def run(*args)
- result = super
- if @tops ||= nil
- @tops.each do |t, list|
- if list
- puts "#{t.to_s.tr('_', ' ')} tests:"
- list.each {|suite, method, assertions, time, error|
- printf "%5.2fsec(%d): %s#%s\n", time, assertions, suite, method
- }
- end
- end
- end
- result
- end
-
- private
- def setup_options(opts, options)
- super
- opts.separator "statistics options:"
- opts.on '--longest=N', Integer, 'Show longest N tests' do |n|
- options[:longest] = n
- end
- opts.on '--most-asserted=N', Integer, 'Show most asserted N tests' do |n|
- options[:most_asserted] = n
- end
- end
- end
-
- module StatusLine # :nodoc: all
- def terminal_width
- unless @terminal_width ||= nil
- begin
- require 'io/console'
- width = $stdout.winsize[1]
- rescue LoadError, NoMethodError, Errno::ENOTTY, Errno::EBADF, Errno::EINVAL
- width = ENV["COLUMNS"].to_i.nonzero? || 80
- end
- width -= 1 if /mswin|mingw/ =~ RUBY_PLATFORM
- @terminal_width = width
- end
- @terminal_width
- end
-
- def del_status_line(flush = true)
- @status_line_size ||= 0
- if @options[:job_status] == :replace
- $stdout.print "\r"+" "*@status_line_size+"\r"
- else
- $stdout.puts if @status_line_size > 0
- end
- $stdout.flush if flush
- @status_line_size = 0
- end
-
- def add_status(line)
- @status_line_size ||= 0
- if @options[:job_status] == :replace
- line = line[0...(terminal_width-@status_line_size)]
- end
- print line
- @status_line_size += line.size
- end
-
- def jobs_status(worker)
- return if !@options[:job_status] or @options[:verbose]
- if @options[:job_status] == :replace
- status_line = @workers.map(&:to_s).join(" ")
- else
- status_line = worker.to_s
- end
- update_status(status_line) or (puts; nil)
- end
-
- def del_jobs_status
- return unless @options[:job_status] == :replace && @status_line_size.nonzero?
- del_status_line
- end
-
- def output
- (@output ||= nil) || super
- end
-
- def _prepare_run(suites, type)
- options[:job_status] ||= :replace if @tty && !@verbose
- case options[:color]
- when :always
- color = true
- when :auto, nil
- color = true if @tty || @options[:job_status] == :replace
- else
- color = false
- end
- @colorize = Colorize.new(color, colors_file: File.join(__dir__, "../../colors"))
- if color or @options[:job_status] == :replace
- @verbose = !options[:parallel]
- end
- @output = Output.new(self) unless @options[:testing]
- filter = options[:filter]
- type = "#{type}_methods"
- total = if filter
- suites.inject(0) {|n, suite| n + suite.send(type).grep(filter).size}
- else
- suites.inject(0) {|n, suite| n + suite.send(type).size}
- end
- @test_count = 0
- @total_tests = total.to_s(10)
- end
-
- def new_test(s)
- @test_count += 1
- update_status(s)
- end
-
- def update_status(s)
- count = @test_count.to_s(10).rjust(@total_tests.size)
- del_status_line(false)
- add_status(@colorize.pass("[#{count}/#{@total_tests}]"))
- add_status(" #{s}")
- $stdout.print "\r" if @options[:job_status] == :replace and !@verbose
- $stdout.flush
- end
-
- def _print(s); $stdout.print(s); end
- def succeed; del_status_line; end
-
- def failed(s)
- return if s and @options[:job_status] != :replace
- sep = "\n"
- @report_count ||= 0
- report.each do |msg|
- if msg.start_with? "Skipped:"
- if @options[:hide_skip]
- del_status_line
- next
- end
- color = :skip
- else
- color = :fail
- end
- first, msg = msg.split(/$/, 2)
- first = sprintf("%3d) %s", @report_count += 1, first)
- $stdout.print(sep, @colorize.decorate(first, color), msg, "\n")
- sep = nil
- end
- report.clear
- end
-
- def initialize
- super
- @tty = $stdout.tty?
- end
-
- def run(*args)
- result = super
- puts "\nruby -v: #{RUBY_DESCRIPTION}"
- result
- end
-
- private
- def setup_options(opts, options)
- super
-
- opts.separator "status line options:"
-
- options[:job_status] = nil
-
- opts.on '--jobs-status [TYPE]', [:normal, :replace, :none],
- "Show status of jobs every file; Disabled when --jobs isn't specified." do |type|
- options[:job_status] = (type || :normal if type != :none)
- end
-
- opts.on '--color[=WHEN]',
- [:always, :never, :auto],
- "colorize the output. WHEN defaults to 'always'", "or can be 'never' or 'auto'." do |c|
- options[:color] = c || :always
- end
-
- opts.on '--tty[=WHEN]',
- [:yes, :no],
- "force to output tty control. WHEN defaults to 'yes'", "or can be 'no'." do |c|
- @tty = c != :no
- end
- end
-
- class Output < Struct.new(:runner) # :nodoc: all
- def puts(*a) $stdout.puts(*a) unless a.empty? end
- def respond_to_missing?(*a) $stdout.respond_to?(*a) end
- def method_missing(*a, &b) $stdout.__send__(*a, &b) end
-
- def print(s)
- case s
- when /\A(.*\#.*) = \z/
- runner.new_test($1)
- when /\A(.* s) = \z/
- runner.add_status(" = #$1")
- when /\A\.+\z/
- runner.succeed
- when /\A[EFS]\z/
- runner.failed(s)
- else
- $stdout.print(s)
- end
- end
- end
- end
-
- module LoadPathOption # :nodoc: all
- def non_options(files, options)
- begin
- require "rbconfig"
- rescue LoadError
- warn "#{caller(1, 1)[0]}: warning: Parallel running disabled because can't get path to ruby; run specify with --ruby argument"
- options[:parallel] = nil
- else
- options[:ruby] ||= [RbConfig.ruby]
- end
-
- super
- end
-
- def setup_options(parser, options)
- super
- parser.separator "load path options:"
- parser.on '-Idirectory', 'Add library load path' do |dirs|
- dirs.split(':').each { |d| $LOAD_PATH.unshift d }
- end
- end
- end
-
- module GlobOption # :nodoc: all
- @@testfile_prefix = "test"
- @@testfile_suffix = "test"
-
- def setup_options(parser, options)
- super
- parser.separator "globbing options:"
- parser.on '-b', '--basedir=DIR', 'Base directory of test suites.' do |dir|
- options[:base_directory] = dir
- end
- parser.on '-x', '--exclude REGEXP', 'Exclude test files on pattern.' do |pattern|
- (options[:reject] ||= []) << pattern
- end
- end
-
- def non_options(files, options)
- paths = [options.delete(:base_directory), nil].uniq
- if reject = options.delete(:reject)
- reject_pat = Regexp.union(reject.map {|r| %r"#{r}"})
- end
- files.map! {|f|
- f = f.tr(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
- ((paths if /\A\.\.?(?:\z|\/)/ !~ f) || [nil]).any? do |prefix|
- if prefix
- path = f.empty? ? prefix : "#{prefix}/#{f}"
- else
- next if f.empty?
- path = f
- end
- if f.end_with?(File::SEPARATOR) or !f.include?(File::SEPARATOR) or File.directory?(path)
- match = (Dir["#{path}/**/#{@@testfile_prefix}_*.rb"] + Dir["#{path}/**/*_#{@@testfile_suffix}.rb"]).uniq
- else
- match = Dir[path]
- end
- if !match.empty?
- if reject
- match.reject! {|n|
- n = n[(prefix.length+1)..-1] if prefix
- reject_pat =~ n
- }
- end
- break match
- elsif !reject or reject_pat !~ f and File.exist? path
- break path
- end
- end or
- raise ArgumentError, "file not found: #{f}"
- }
- files.flatten!
- super(files, options)
- end
- end
-
- module GCStressOption # :nodoc: all
- def setup_options(parser, options)
- super
- parser.separator "GC options:"
- parser.on '--[no-]gc-stress', 'Set GC.stress as true' do |flag|
- options[:gc_stress] = flag
- end
- end
-
- def non_options(files, options)
- if options.delete(:gc_stress)
- MiniTest::Unit::TestCase.class_eval do
- oldrun = instance_method(:run)
- define_method(:run) do |runner|
- begin
- gc_stress, GC.stress = GC.stress, true
- oldrun.bind(self).call(runner)
- ensure
- GC.stress = gc_stress
- end
- end
- end
- end
- super
- end
- end
-
- module RequireFiles # :nodoc: all
- def non_options(files, options)
- return false if !super
- errors = {}
- result = false
- files.each {|f|
- d = File.dirname(path = File.realpath(f))
- unless $:.include? d
- $: << d
- end
- begin
- require path unless options[:parallel]
- result = true
- rescue LoadError
- next if errors[$!.message]
- errors[$!.message] = true
- puts "#{f}: #{$!}"
- end
- }
- result
- end
- end
-
- module RepeatOption # :nodoc: all
- def setup_options(parser, options)
- super
- options[:repeat_count] = nil
- parser.separator "repeat options:"
- parser.on '--repeat-count=NUM', "Number of times to repeat", Integer do |n|
- options[:repeat_count] = n
- end
- end
-
- def _run_anything(type)
- @repeat_count = @options[:repeat_count]
- super
- end
- end
-
- module ExcludesOption # :nodoc: all
- class ExcludedMethods < Struct.new(:excludes)
- def exclude(name, reason)
- excludes[name] = reason
- end
-
- def exclude_from(klass)
- excludes = self.excludes
- pattern = excludes.keys.grep(Regexp).tap {|k|
- break (Regexp.new(k.join('|')) unless k.empty?)
- }
- klass.class_eval do
- public_instance_methods(false).each do |method|
- if excludes[method] or (pattern and pattern =~ method)
- remove_method(method)
- end
- end
- public_instance_methods(true).each do |method|
- if excludes[method] or (pattern and pattern =~ method)
- undef_method(method)
- end
- end
- end
- end
-
- def self.load(dirs, name)
- return unless dirs and name
- instance = nil
- dirs.each do |dir|
- path = File.join(dir, name.gsub(/::/, '/') + ".rb")
- begin
- src = File.read(path)
- rescue Errno::ENOENT
- nil
- else
- instance ||= new({})
- instance.instance_eval(src, path)
- end
- end
- instance
- end
- end
-
- def setup_options(parser, options)
- super
- if excludes = ENV["EXCLUDES"]
- excludes = excludes.split(File::PATH_SEPARATOR)
- end
- options[:excludes] = excludes || []
- parser.separator "excludes options:"
- parser.on '-X', '--excludes-dir DIRECTORY', "Directory name of exclude files" do |d|
- options[:excludes].concat d.split(File::PATH_SEPARATOR)
- end
- end
-
- def _run_suite(suite, type)
- if ex = ExcludedMethods.load(@options[:excludes], suite.name)
- ex.exclude_from(suite)
- end
- super
- end
- end
-
- module TimeoutOption
- def setup_options(parser, options)
- super
- parser.separator "timeout options:"
- parser.on '--timeout-scale NUM', '--subprocess-timeout-scale NUM', "Scale timeout", Float do |scale|
- raise OptionParser::InvalidArgument, "timeout scale must be positive" unless scale > 0
- options[:timeout_scale] = scale
- end
- end
-
- def non_options(files, options)
- if scale = options[:timeout_scale] or
- (scale = ENV["RUBY_TEST_TIMEOUT_SCALE"] || ENV["RUBY_TEST_SUBPROCESS_TIMEOUT_SCALE"] and
- (scale = scale.to_f) > 0)
- EnvUtil.timeout_scale = scale
- end
- super
- end
- end
-
- class Runner < MiniTest::Unit # :nodoc: all
- include Test::Unit::Options
- include Test::Unit::StatusLine
- include Test::Unit::Parallel
- include Test::Unit::Statistics
- include Test::Unit::Skipping
- include Test::Unit::GlobOption
- include Test::Unit::RepeatOption
- include Test::Unit::LoadPathOption
- include Test::Unit::GCStressOption
- include Test::Unit::ExcludesOption
- include Test::Unit::TimeoutOption
- include Test::Unit::RunCount
-
- class << self; undef autorun; end
-
- @@stop_auto_run = false
- def self.autorun
- at_exit {
- Test::Unit::RunCount.run_once {
- exit(Test::Unit::Runner.new.run(ARGV) || true)
- } unless @@stop_auto_run
- } unless @@installed_at_exit
- @@installed_at_exit = true
- end
-
- alias mini_run_suite _run_suite
-
- # Overriding of MiniTest::Unit#puke
- def puke klass, meth, e
- # TODO:
- # this overriding is for minitest feature that skip messages are
- # hidden when not verbose (-v), note this is temporally.
- n = report.size
- rep = super
- if MiniTest::Skip === e and /no message given\z/ =~ e.message
- report.slice!(n..-1)
- rep = "."
- end
- rep
- end
- end
-
- class AutoRunner # :nodoc: all
- class Runner < Test::Unit::Runner
- include Test::Unit::RequireFiles
- end
-
- attr_accessor :to_run, :options
-
- def initialize(force_standalone = false, default_dir = nil, argv = ARGV)
- @force_standalone = force_standalone
- @runner = Runner.new do |files, options|
- options[:base_directory] ||= default_dir
- files << default_dir if files.empty? and default_dir
- @to_run = files
- yield self if block_given?
- files
- end
- Runner.runner = @runner
- @options = @runner.option_parser
- if @force_standalone
- @options.banner.sub!(/\[options\]/, '\& tests...')
- end
- @argv = argv
- end
-
- def process_args(*args)
- @runner.process_args(*args)
- !@to_run.empty?
- end
-
- def run
- if @force_standalone and not process_args(@argv)
- abort @options.banner
- end
- @runner.run(@argv) || true
- end
-
- def self.run(*args)
- new(*args).run
- end
- end
-
- class ProxyError < StandardError # :nodoc: all
- def initialize(ex)
- @message = ex.message
- @backtrace = ex.backtrace
- end
-
- attr_accessor :message, :backtrace
- end
- end
-end
-
-module MiniTest # :nodoc: all
- class Unit
- end
-end
-
-class MiniTest::Unit::TestCase # :nodoc: all
- test_order = self.test_order
- class << self
- attr_writer :test_order
- undef test_order
- end
- def self.test_order
- defined?(@test_order) ? @test_order : superclass.test_order
- end
- self.test_order = test_order
- undef run_test
- RUN_TEST_TRACE = "#{__FILE__}:#{__LINE__+3}:in `run_test'".freeze
- def run_test(name)
- progname, $0 = $0, "#{$0}: #{self.class}##{name}"
- self.__send__(name)
- ensure
- $@.delete(RUN_TEST_TRACE) if $@
- $0 = progname
- end
-end
-
-Test::Unit::Runner.autorun
diff --git a/test/lib/test/unit/assertions.rb b/test/lib/test/unit/assertions.rb
deleted file mode 100644
index 169a3dcc7e0..00000000000
--- a/test/lib/test/unit/assertions.rb
+++ /dev/null
@@ -1,984 +0,0 @@
-# frozen_string_literal: true
-require 'minitest/unit'
-require 'pp'
-
-module Test
- module Unit
- module Assertions
- include MiniTest::Assertions
-
- def mu_pp(obj) #:nodoc:
- obj.pretty_inspect.chomp
- 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_block( failure_message = nil )
- #
- #Tests the result of the given block. If the block does not return true,
- #the assertion will fail. The optional +failure_message+ argument is the same as in
- #Assertions#assert.
- #
- # assert_block do
- # [1, 2, 3].any? { |num| num < 1 }
- # end
- def assert_block(*msgs)
- assert yield, *msgs
- 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 {
- exception_details(e, message(msg) {"#{mu_pp(exp)} exception expected, not"}.call)
- }
-
- 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
-
- def assert_raises(*exp, &b)
- raise NoMethodError, "use assert_raise", caller
- 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
-
- # :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)}>" }
- raise MiniTest::Assertion, msg.call, bt
- else
- raise
- end
- end
- end
-
- # :call-seq:
- # assert_nothing_thrown( failure_message = nil, &block )
- #
- #Fails if the given block uses a call to Kernel#throw, and
- #returns the result of the block otherwise.
- #
- #An optional failure message may be provided as the final argument.
- #
- # assert_nothing_thrown "Something was thrown!" do
- # throw :problem?
- # end
- def assert_nothing_thrown(msg=nil)
- begin
- ret = yield
- rescue ArgumentError => error
- raise error if /\Auncaught throw (.+)\z/m !~ error.message
- msg = message(msg) { "<#{$1}> was thrown when nothing was expected" }
- flunk(msg)
- end
- assert(true, "Expected nothing to be thrown")
- ret
- 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_equal( expected, actual, failure_message = nil )
- #
- #Tests if +expected+ is equal to +actual+.
- #
- #An optional failure message may be provided as the final argument.
- def assert_equal(exp, act, msg = nil)
- msg = message(msg) {
- exp_str = mu_pp(exp)
- act_str = mu_pp(act)
- exp_comment = ''
- act_comment = ''
- if exp_str == act_str
- if (exp.is_a?(String) && act.is_a?(String)) ||
- (exp.is_a?(Regexp) && act.is_a?(Regexp))
- exp_comment = " (#{exp.encoding})"
- act_comment = " (#{act.encoding})"
- elsif exp.is_a?(Float) && act.is_a?(Float)
- exp_str = "%\#.#{Float::DIG+2}g" % exp
- act_str = "%\#.#{Float::DIG+2}g" % act
- elsif exp.is_a?(Time) && act.is_a?(Time)
- if exp.subsec * 1000_000_000 == exp.nsec
- exp_comment = " (#{exp.nsec}[ns])"
- else
- exp_comment = " (subsec=#{exp.subsec})"
- end
- if act.subsec * 1000_000_000 == act.nsec
- act_comment = " (#{act.nsec}[ns])"
- else
- act_comment = " (subsec=#{act.subsec})"
- end
- elsif exp.class != act.class
- # a subclass of Range, for example.
- exp_comment = " (#{exp.class})"
- act_comment = " (#{act.class})"
- end
- elsif !Encoding.compatible?(exp_str, act_str)
- if exp.is_a?(String) && act.is_a?(String)
- exp_str = exp.dump
- act_str = act.dump
- exp_comment = " (#{exp.encoding})"
- act_comment = " (#{act.encoding})"
- else
- exp_str = exp_str.dump
- act_str = act_str.dump
- end
- end
- "<#{exp_str}>#{exp_comment} expected but was\n<#{act_str}>#{act_comment}"
- }
- assert(exp == act, msg)
- end
-
- # :call-seq:
- # assert_not_nil( expression, failure_message = nil )
- #
- #Tests if +expression+ is not nil.
- #
- #An optional failure message may be provided as the final argument.
- def assert_not_nil(exp, msg=nil)
- msg = message(msg) { "<#{mu_pp(exp)}> expected to not be nil" }
- assert(!exp.nil?, msg)
- end
-
- # :call-seq:
- # assert_not_equal( expected, actual, failure_message = nil )
- #
- #Tests if +expected+ is not equal to +actual+.
- #
- #An optional failure message may be provided as the final argument.
- def assert_not_equal(exp, act, msg=nil)
- msg = message(msg) { "<#{mu_pp(exp)}> expected to be != to\n<#{mu_pp(act)}>" }
- assert(exp != act, msg)
- end
-
- # :call-seq:
- # assert_no_match( regexp, string, failure_message = nil )
- #
- #Tests if the given Regexp does not match a given String.
- #
- #An optional failure message may be provided as the final argument.
- def assert_no_match(regexp, string, msg=nil)
- assert_instance_of(Regexp, regexp, "The first argument to assert_no_match should be a Regexp.")
- self._assertions -= 1
- msg = message(msg) { "<#{mu_pp(regexp)}> expected to not match\n<#{mu_pp(string)}>" }
- assert(regexp !~ string, msg)
- end
-
- # :call-seq:
- # assert_not_same( expected, actual, failure_message = nil )
- #
- #Tests if +expected+ is not the same object as +actual+.
- #This test uses Object#equal? to test equality.
- #
- #An optional failure message may be provided as the final argument.
- #
- # assert_not_same("x", "x") #Succeeds
- def assert_not_same(expected, actual, message="")
- msg = message(msg) { build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__) }
-<?>
-with id <?> expected to not be equal\\? to
-<?>
-with id <?>.
-EOT
- assert(!actual.equal?(expected), msg)
- 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
-
- # :call-seq:
- # assert_send( +send_array+, failure_message = nil )
- #
- # Passes if the method send returns a true value.
- #
- # +send_array+ is composed of:
- # * A receiver
- # * A method
- # * Arguments to the method
- #
- # Example:
- # assert_send(["Hello world", :include?, "Hello"]) # -> pass
- # assert_send(["Hello world", :include?, "Goodbye"]) # -> fail
- def assert_send send_ary, m = nil
- recv, msg, *args = send_ary
- m = message(m) {
- if args.empty?
- argsstr = ""
- else
- (argsstr = mu_pp(args)).sub!(/\A\[(.*)\]\z/m, '(\1)')
- end
- "Expected #{mu_pp(recv)}.#{msg}#{argsstr} to return true"
- }
- assert recv.__send__(msg, *args), m
- end
-
- # :call-seq:
- # assert_not_send( +send_array+, failure_message = nil )
- #
- # Passes if the method send doesn't return a true value.
- #
- # +send_array+ is composed of:
- # * A receiver
- # * A method
- # * Arguments to the method
- #
- # Example:
- # assert_not_send([[1, 2], :member?, 1]) # -> fail
- # assert_not_send([[1, 2], :member?, 4]) # -> pass
- def assert_not_send send_ary, m = nil
- recv, msg, *args = send_ary
- m = message(m) {
- if args.empty?
- argsstr = ""
- else
- (argsstr = mu_pp(args)).sub!(/\A\[(.*)\]\z/m, '(\1)')
- end
- "Expected #{mu_pp(recv)}.#{msg}#{argsstr} to return false"
- }
- assert !recv.__send__(msg, *args), m
- end
-
- ms = instance_methods(true).map {|sym| sym.to_s }
- ms.grep(/\Arefute_/) do |m|
- mname = ('assert_not_'.dup << m.to_s[/.*?_(.*)/, 1])
- alias_method(mname, m) unless ms.include? mname
- end
- alias assert_include assert_includes
- alias assert_not_include assert_not_includes
-
- def assert_all?(obj, m = nil, &blk)
- failed = []
- obj.each do |*a, &b|
- unless blk.call(*a, &b)
- failed << (a.size > 1 ? a : a[0])
- end
- end
- assert(failed.empty?, message(m) {failed.pretty_inspect})
- end
-
- def assert_not_all?(obj, m = nil, &blk)
- failed = []
- obj.each do |*a, &b|
- if blk.call(*a, &b)
- failed << (a.size > 1 ? a : a[0])
- end
- end
- assert(failed.empty?, message(m) {failed.pretty_inspect})
- end
-
- # compatibility with test-unit
- alias pend skip
-
- 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
- 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 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_syntax_error(code, error, *args)
- prepare_syntax_check(code, *args) do |src, fname, line, mesg|
- yield if defined?(yield)
- e = assert_raise(SyntaxError, mesg) do
- syntax_check(src, fname, line)
- end
- assert_match(error, e.message, mesg)
- e
- 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
-
- FailDesc = proc do |status, message = "", out = ""|
- pid = status.pid
- now = Time.now
- faildesc = proc do
- if signo = status.termsig
- signame = Signal.signame(signo)
- sigdesc = "signal #{signo}"
- end
- log = EnvUtil.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
- faildesc
- 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)
- if signo = status.termsig
- EnvUtil.diagnostic_reports(Signal.signame(signo), status.pid, Time.now)
- end
- 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(message) 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
-
- 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 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
- src = <<eom
-# -*- coding: #{line += __LINE__; src.encoding}; -*-
- require #{__dir__.dump};include Test::Unit::Assertions
- END {
- puts [Marshal.dump($!)].pack('m'), "assertions=\#{self._assertions}"
- }
-#{line -= __LINE__; src}
- class Test::Unit::Runner
- @@stop_auto_run = true
- end
-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, true, true, **opt)
- abort = status.coredump? || (status.signaled? && ABORT_SIGNALS.include?(status.termsig))
- assert(!abort, FailDesc[status, nil, stderr])
- self._assertions += stdout[/^assertions=(\d+)/, 1].to_i
- begin
- res = Marshal.load(stdout.unpack("m")[0])
- rescue => marshal_error
- ignore_stderr = nil
- end
- if 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 unless SystemExit === 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
-
- 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_no_warning(pat, msg = nil)
- result = nil
- stderr = EnvUtil.verbose_warning {
- EnvUtil.with_default_internal(pat.encoding) {
- result = yield
- }
- }
- msg = message(msg) {diff pat, stderr}
- refute(pat === stderr, msg)
- result
- 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
- skip 'assert_no_memory_leak may consider MJIT memory usage as leak' if defined?(RubyVM::MJIT) && RubyVM::MJIT.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
- skip
- end
-
- # kernel resolution can limit the minimum time we can measure
- # [ruby-core:81540]
- MIN_HZ = MiniTest::Unit::TestCase.windows? ? 67 : 100
- MIN_MEASURABLE = 1.0 / MIN_HZ
-
- def assert_cpu_usage_low(msg = nil, pct: 0.05, wait: 1.0, stop: nil)
- require 'benchmark'
-
- wait = EnvUtil.apply_timeout_scale(wait)
- if wait < 0.1 # TIME_QUANTUM_USEC in thread_pthread.c
- warn "test #{msg || 'assert_cpu_usage_low'} too short to be accurate"
- end
- tms = Benchmark.measure(msg || '') do
- if stop
- th = Thread.start {sleep wait; stop.call}
- yield
- th.join
- else
- begin
- Timeout.timeout(wait) {yield}
- rescue Timeout::Error
- end
- end
- end
-
- max = pct * tms.real
- min_measurable = MIN_MEASURABLE
- min_measurable *= 1.30 # add a little (30%) to account for misc. overheads
- if max < min_measurable
- max = min_measurable
- end
-
- assert_operator tms.total, :<=, max, msg
- end
-
- def assert_is_minus_zero(f)
- assert(1.0/f == -Float::INFINITY, "#{f} is not -0.0")
- end
-
- def assert_file
- AssertFile
- 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
-
- # 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" +
- err.full_message(highlight: false, order: :top)
- }.join("\n---\n")
- if message
- msg = "#{message}\n#{msg}"
- end
- raise MiniTest::Assertion, msg
- end
- end
-
- class << (AssertFile = Struct.new(:failure_message).new)
- include Assertions
- 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
-
- 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 assert_all_assertions_foreach(msg = nil, *keys, &block)
- all = AllFailures.new
- all.foreach(*keys, &block)
- ensure
- assert(all.pass?, message(msg) {all.message.chomp(".")})
- end
- alias all_assertions_foreach assert_all_assertions_foreach
-
- def build_message(head, template=nil, *arguments) #:nodoc:
- template &&= template.chomp
- template.gsub(/\G((?:[^\\]|\\.)*?)(\\)?\?/) { $1 + ($2 ? "?" : mu_pp(arguments.shift)) }
- end
-
- 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
- end
- end
-end
diff --git a/test/lib/test/unit/parallel.rb b/test/lib/test/unit/parallel.rb
deleted file mode 100644
index d851326acab..00000000000
--- a/test/lib/test/unit/parallel.rb
+++ /dev/null
@@ -1,208 +0,0 @@
-# frozen_string_literal: true
-$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../.."
-require 'test/unit'
-
-module Test
- module Unit
- class Worker < Runner # :nodoc:
- class << self
- undef autorun
- end
-
- alias orig_run_suite mini_run_suite
- undef _run_suite
- undef _run_suites
- undef run
-
- def increment_io(orig) # :nodoc:
- *rest, io = 32.times.inject([orig.dup]){|ios, | ios << ios.last.dup }
- rest.each(&:close)
- io
- end
-
- def _run_suites(suites, type) # :nodoc:
- suites.map do |suite|
- _run_suite(suite, type)
- end
- end
-
- def _run_suite(suite, type) # :nodoc:
- @partial_report = []
- orig_testout = MiniTest::Unit.output
- i,o = IO.pipe
-
- MiniTest::Unit.output = o
- orig_stdin, orig_stdout = $stdin, $stdout
-
- th = Thread.new do
- begin
- while buf = (self.verbose ? i.gets : i.readpartial(1024))
- _report "p", buf
- end
- rescue IOError
- rescue Errno::EPIPE
- end
- end
-
- e, f, s = @errors, @failures, @skips
-
- begin
- result = orig_run_suite(suite, type)
- rescue Interrupt
- @need_exit = true
- result = [nil,nil]
- end
-
- MiniTest::Unit.output = orig_testout
- $stdin = orig_stdin
- $stdout = orig_stdout
-
- o.close
- begin
- th.join
- rescue IOError
- raise unless /stream closed|closed stream/ =~ $!.message
- end
- i.close
-
- result << @partial_report
- @partial_report = nil
- result << [@errors-e,@failures-f,@skips-s]
- result << ($: - @old_loadpath)
- result << suite.name
-
- begin
- _report "done", Marshal.dump(result)
- rescue Errno::EPIPE; end
- return result
- ensure
- MiniTest::Unit.output = orig_stdout
- $stdin = orig_stdin if orig_stdin
- $stdout = orig_stdout if orig_stdout
- o.close if o && !o.closed?
- i.close if i && !i.closed?
- end
-
- def run(args = []) # :nodoc:
- process_args args
- @@stop_auto_run = true
- @opts = @options.dup
- @need_exit = false
-
- @old_loadpath = []
- begin
- begin
- @stdout = increment_io(STDOUT)
- @stdin = increment_io(STDIN)
- rescue
- exit 2
- end
- exit 2 unless @stdout && @stdin
-
- @stdout.sync = true
- _report "ready!"
- while buf = @stdin.gets
- case buf.chomp
- when /^loadpath (.+?)$/
- @old_loadpath = $:.dup
- $:.push(*Marshal.load($1.unpack("m")[0].force_encoding("ASCII-8BIT"))).uniq!
- when /^run (.+?) (.+?)$/
- _report "okay"
-
- @options = @opts.dup
- suites = MiniTest::Unit::TestCase.test_suites
-
- begin
- require File.realpath($1)
- rescue LoadError
- _report "after", Marshal.dump([$1, ProxyError.new($!)])
- _report "ready"
- next
- end
- _run_suites MiniTest::Unit::TestCase.test_suites-suites, $2.to_sym
-
- if @need_exit
- begin
- _report "bye"
- rescue Errno::EPIPE; end
- exit
- else
- _report "ready"
- end
- when /^quit$/
- begin
- _report "bye"
- rescue Errno::EPIPE; end
- exit
- end
- end
- rescue Errno::EPIPE
- rescue Exception => e
- begin
- trace = e.backtrace || ['unknown method']
- err = ["#{trace.shift}: #{e.message} (#{e.class})"] + trace.map{|t| t.prepend("\t") }
-
- _report "bye", Marshal.dump(err.join("\n"))
- rescue Errno::EPIPE;end
- exit
- ensure
- @stdin.close if @stdin
- @stdout.close if @stdout
- end
- end
-
- def _report(res, *args) # :nodoc:
- @stdout.write(args.empty? ? "#{res}\n" : "#{res} #{args.pack("m0")}\n")
- end
-
- def puke(klass, meth, e) # :nodoc:
- if e.is_a?(MiniTest::Skip)
- new_e = MiniTest::Skip.new(e.message)
- new_e.set_backtrace(e.backtrace)
- e = new_e
- end
- @partial_report << [klass.name, meth, e.is_a?(MiniTest::Assertion) ? e : ProxyError.new(e)]
- super
- end
-
- def record(suite, method, assertions, time, error) # :nodoc:
- case error
- when nil
- when MiniTest::Assertion, MiniTest::Skip
- case error.cause
- when nil, MiniTest::Assertion, MiniTest::Skip
- else
- bt = error.backtrace
- error = error.class.new(error.message)
- error.set_backtrace(bt)
- end
- else
- error = ProxyError.new(error)
- end
- _report "record", Marshal.dump([suite.name, method, assertions, time, error])
- super
- end
- end
- end
-end
-
-if $0 == __FILE__
- module Test
- module Unit
- class TestCase < MiniTest::Unit::TestCase # :nodoc: all
- undef on_parallel_worker?
- def on_parallel_worker?
- true
- end
- end
- end
- end
- require 'rubygems'
- module Gem # :nodoc:
- end
- class Gem::TestCase < MiniTest::Unit::TestCase # :nodoc:
- @@project_dir = File.expand_path('../../../../..', __FILE__)
- end
-
- Test::Unit::Worker.new.run(ARGV)
-end
diff --git a/test/lib/test/unit/testcase.rb b/test/lib/test/unit/testcase.rb
deleted file mode 100644
index 58cfbcab99e..00000000000
--- a/test/lib/test/unit/testcase.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit/assertions'
-
-module Test
- module Unit
- # remove silly TestCase class
- remove_const(:TestCase) if defined?(self::TestCase)
-
- class TestCase < MiniTest::Unit::TestCase # :nodoc: all
- include Assertions
-
- def on_parallel_worker?
- false
- end
-
- def run runner
- @options = runner.options
- super runner
- end
-
- def self.test_order
- :sorted
- end
-
- def self.method_added(name)
- super
- return unless name.to_s.start_with?("test_")
- @test_methods ||= {}
- if @test_methods[name]
- warn "test/unit warning: method #{ self }##{ name } is redefined"
- end
- @test_methods[name] = true
- end
- end
- end
-end
diff --git a/test/lib/tracepointchecker.rb b/test/lib/tracepointchecker.rb
deleted file mode 100644
index 47822ecef54..00000000000
--- a/test/lib/tracepointchecker.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# frozen_string_literal: true
-module TracePointChecker
- STATE = {
- count: 0,
- running: false,
- }
-
- module ZombieTraceHunter
- def tracepoint_capture_stat_get
- TracePoint.stat.map{|k, (activated, deleted)|
- deleted = 0 unless @tracepoint_captured_singlethread
- [k, activated, deleted]
- }
- end
-
- def before_setup
- @tracepoint_captured_singlethread = (Thread.list.size == 1)
- @tracepoint_captured_stat = tracepoint_capture_stat_get()
- super
- end
-
- def after_teardown
- super
-
- # detect zombie traces.
- assert_equal(
- @tracepoint_captured_stat,
- tracepoint_capture_stat_get(),
- "The number of active/deleted trace events was changed"
- )
- # puts "TracePoint - deleted: #{deleted}" if deleted > 0
-
- TracePointChecker.check if STATE[:running]
- end
- end
-
- MAIN_THREAD = Thread.current
- TRACES = []
-
- def self.prefix event
- case event
- when :call, :return
- :n
- when :c_call, :c_return
- :c
- when :b_call, :b_return
- :b
- end
- end
-
- def self.clear_call_stack
- Thread.current[:call_stack] = []
- end
-
- def self.call_stack
- stack = Thread.current[:call_stack]
- stack = clear_call_stack unless stack
- stack
- end
-
- def self.verbose_out label, method
- puts label => call_stack, :count => STATE[:count], :method => method
- end
-
- def self.method_label tp
- "#{prefix(tp.event)}##{tp.method_id}"
- end
-
- def self.start verbose: false, stop_at_failure: false
- call_events = %i(a_call)
- return_events = %i(a_return)
- clear_call_stack
-
- STATE[:running] = true
-
- TRACES << TracePoint.new(*call_events){|tp|
- next if Thread.current != MAIN_THREAD
-
- method = method_label(tp)
- call_stack.push method
- STATE[:count] += 1
-
- verbose_out :psuh, method if verbose
- }
-
- TRACES << TracePoint.new(*return_events){|tp|
- next if Thread.current != MAIN_THREAD
- STATE[:count] += 1
-
- method = "#{prefix(tp.event)}##{tp.method_id}"
- verbose_out :pop1, method if verbose
-
- stored_method = call_stack.pop
- next if stored_method.nil?
-
- verbose_out :pop2, method if verbose
-
- if stored_method != method
- stop if stop_at_failure
- RubyVM::SDR() if defined? RubyVM::SDR()
- call_stack.clear
- raise "#{stored_method} is expected, but #{method} (count: #{STATE[:count]})"
- end
- }
-
- TRACES.each{|trace| trace.enable}
- end
-
- def self.stop
- STATE[:running] = true
- TRACES.each{|trace| trace.disable}
- TRACES.clear
- end
-
- def self.check
- TRACES.each{|trace|
- raise "trace #{trace} should not be deactivated" unless trace.enabled?
- }
- end
-end if defined?(TracePoint.stat)
-
-class ::Test::Unit::TestCase
- include TracePointChecker::ZombieTraceHunter
-end if defined?(TracePointChecker)
-
-# TracePointChecker.start verbose: false
diff --git a/test/lib/with_different_ofs.rb b/test/lib/with_different_ofs.rb
deleted file mode 100644
index 559ed6a1d12..00000000000
--- a/test/lib/with_different_ofs.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-module DifferentOFS
- module WithDifferentOFS
- def setup
- super
- verbose, $VERBOSE = $VERBOSE, nil
- @ofs, $, = $,, "-"
- $VERBOSE = verbose
- end
- def teardown
- verbose, $VERBOSE = $VERBOSE, nil
- $, = @ofs
- $VERBOSE = verbose
- super
- end
- end
-
- def self.extended(klass)
- super(klass)
- klass.const_set(:DifferentOFS, Class.new(klass).class_eval {include WithDifferentOFS}).name
- end
-end
diff --git a/test/lib/zombie_hunter.rb b/test/lib/zombie_hunter.rb
deleted file mode 100644
index 33bc4679412..00000000000
--- a/test/lib/zombie_hunter.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-module ZombieHunter
- def after_teardown
- super
- assert_empty(Process.waitall)
- end
-end
-
-Test::Unit::TestCase.include ZombieHunter
diff --git a/test/runner.rb b/test/runner.rb
index d8b44644f74..263df1d930b 100644
--- a/test/runner.rb
+++ b/test/runner.rb
@@ -3,7 +3,8 @@ require 'rbconfig'
src_testdir = File.dirname(File.realpath(__FILE__))
$LOAD_PATH << src_testdir
-$LOAD_PATH.unshift "#{src_testdir}/lib"
+tool_dir = File.join src_testdir, "..", "tool"
+$LOAD_PATH.unshift "#{tool_dir}/lib"
# Get bundled gems on load path
Dir.glob("#{src_testdir}/../gems/*/*.gemspec")
@@ -20,13 +21,13 @@ end
ENV["GEM_SKIP"] = ENV["GEM_HOME"] = ENV["GEM_PATH"] = "".freeze
-require_relative 'lib/profile_test_all' if ENV.has_key?('RUBY_TEST_ALL_PROFILE')
-require_relative 'lib/tracepointchecker'
-require_relative 'lib/zombie_hunter'
-require_relative 'lib/iseq_loader_checker'
+require_relative "#{tool_dir}/lib/profile_test_all" if ENV.has_key?('RUBY_TEST_ALL_PROFILE')
+require_relative "#{tool_dir}/lib/tracepointchecker"
+require_relative "#{tool_dir}/lib/zombie_hunter"
+require_relative "#{tool_dir}/lib/iseq_loader_checker"
if ENV['COVERAGE']
- require_relative "../tool/test-coverage.rb"
+ require_relative "#{tool_dir}/lib/test-coverage.rb"
end
begin