summaryrefslogtreecommitdiff
path: root/tool/test/testunit
diff options
context:
space:
mode:
Diffstat (limited to 'tool/test/testunit')
-rw-r--r--tool/test/testunit/metametameta.rb70
-rw-r--r--tool/test/testunit/test4test_hideskip.rb8
-rw-r--r--tool/test/testunit/test4test_load_failure.rb1
-rw-r--r--tool/test/testunit/test4test_sorting.rb2
-rw-r--r--tool/test/testunit/test4test_timeout.rb15
-rw-r--r--tool/test/testunit/test_assertion.rb26
-rw-r--r--tool/test/testunit/test_hideskip.rb8
-rw-r--r--tool/test/testunit/test_launchable.rb69
-rw-r--r--tool/test/testunit/test_load_failure.rb23
-rw-r--r--tool/test/testunit/test_minitest_unit.rb1488
-rw-r--r--tool/test/testunit/test_parallel.rb58
-rw-r--r--tool/test/testunit/test_redefinition.rb13
-rw-r--r--tool/test/testunit/test_sorting.rb59
-rw-r--r--tool/test/testunit/test_timeout.rb10
-rw-r--r--tool/test/testunit/tests_for_parallel/slow_helper.rb8
-rw-r--r--tool/test/testunit/tests_for_parallel/test4test_hungup.rb15
-rw-r--r--tool/test/testunit/tests_for_parallel/test4test_slow_0.rb5
-rw-r--r--tool/test/testunit/tests_for_parallel/test4test_slow_1.rb5
18 files changed, 1845 insertions, 38 deletions
diff --git a/tool/test/testunit/metametameta.rb b/tool/test/testunit/metametameta.rb
new file mode 100644
index 0000000000..e494038939
--- /dev/null
+++ b/tool/test/testunit/metametameta.rb
@@ -0,0 +1,70 @@
+# encoding: utf-8
+# frozen_string_literal: false
+
+require 'tempfile'
+require 'stringio'
+
+class Test::Unit::TestCase
+ def clean s
+ s.gsub(/^ {6}/, '')
+ end
+end
+
+class MetaMetaMetaTestCase < Test::Unit::TestCase
+ def assert_report expected, flags = %w[--seed 42]
+ header = clean <<-EOM
+ Run options: #{flags.map { |s| s =~ /\|/ ? s.inspect : s }.join " "}
+
+ # Running tests:
+
+ EOM
+
+ with_output do
+ @tu.run flags
+ end
+
+ output = @output.string.dup
+ output.sub!(/Finished tests in .*/, "Finished tests in 0.00")
+ output.sub!(/Loaded suite .*/, 'Loaded suite blah')
+
+ output.gsub!(/ = \d+.\d\d s = /, ' = 0.00 s = ')
+ output.gsub!(/0x[A-Fa-f0-9]+/, '0xXXX')
+
+ if windows? then
+ output.gsub!(/\[(?:[A-Za-z]:)?[^\]:]+:\d+\]/, '[FILE:LINE]')
+ output.gsub!(/^(\s+)(?:[A-Za-z]:)?[^:]+:\d+:in/, '\1FILE:LINE:in')
+ else
+ output.gsub!(/\[[^\]:]+:\d+\]/, '[FILE:LINE]')
+ output.gsub!(/^(\s+)[^:]+:\d+:in/, '\1FILE:LINE:in')
+ end
+
+ assert_equal header + expected, output
+ end
+
+ def setup
+ super
+ srand 42
+ Test::Unit::TestCase.reset
+ @tu = Test::Unit::Runner.new
+
+ Test::Unit::Runner.runner = nil # protect the outer runner from the inner tests
+ end
+
+ def teardown
+ super
+ end
+
+ def with_output
+ synchronize do
+ begin
+ save = Test::Unit::Runner.output
+ @output = StringIO.new("")
+ Test::Unit::Runner.output = @output
+
+ yield
+ ensure
+ Test::Unit::Runner.output = save
+ end
+ end
+ end
+end
diff --git a/tool/test/testunit/test4test_hideskip.rb b/tool/test/testunit/test4test_hideskip.rb
index 410bffc13c..14f79a5743 100644
--- a/tool/test/testunit/test4test_hideskip.rb
+++ b/tool/test/testunit/test4test_hideskip.rb
@@ -4,7 +4,11 @@ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
require 'test/unit'
class TestForTestHideSkip < Test::Unit::TestCase
- def test_skip
- skip "do nothing"
+ def test_omit
+ omit "do nothing"
+ end
+
+ def test_pend
+ pend "do nothing"
end
end
diff --git a/tool/test/testunit/test4test_load_failure.rb b/tool/test/testunit/test4test_load_failure.rb
new file mode 100644
index 0000000000..e1570c2542
--- /dev/null
+++ b/tool/test/testunit/test4test_load_failure.rb
@@ -0,0 +1 @@
+raise LoadError, "no-such-library"
diff --git a/tool/test/testunit/test4test_sorting.rb b/tool/test/testunit/test4test_sorting.rb
index 698c875b79..f5a6866425 100644
--- a/tool/test/testunit/test4test_sorting.rb
+++ b/tool/test/testunit/test4test_sorting.rb
@@ -5,7 +5,7 @@ require 'test/unit'
class TestForTestHideSkip < Test::Unit::TestCase
def test_c
- skip "do nothing"
+ omit "do nothing"
end
def test_b
diff --git a/tool/test/testunit/test4test_timeout.rb b/tool/test/testunit/test4test_timeout.rb
new file mode 100644
index 0000000000..3225f66398
--- /dev/null
+++ b/tool/test/testunit/test4test_timeout.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
+
+require 'test/unit'
+require 'timeout'
+
+class TestForTestTimeout < Test::Unit::TestCase
+ 10.times do |i|
+ define_method("test_timeout_#{i}") do
+ Timeout.timeout(0.001) do
+ sleep
+ end
+ end
+ end
+end
diff --git a/tool/test/testunit/test_assertion.rb b/tool/test/testunit/test_assertion.rb
index 0c7c4882b8..709b495572 100644
--- a/tool/test/testunit/test_assertion.rb
+++ b/tool/test/testunit/test_assertion.rb
@@ -22,8 +22,32 @@ class TestAssertion < Test::Unit::TestCase
end
def test_assert_raise
- assert_raise(MiniTest::Assertion) do
+ assert_raise(Test::Unit::AssertionFailedError) do
return_in_assert_raise
end
end
+
+ def test_assert_pattern_list
+ assert_pattern_list([/foo?/], "foo")
+ assert_not_pattern_list([/foo?/], "afoo")
+ assert_not_pattern_list([/foo?/], "foo?")
+ assert_pattern_list([:*, /foo?/, :*], "foo")
+ assert_pattern_list([:*, /foo?/], "afoo")
+ assert_not_pattern_list([:*, /foo?/], "afoo?")
+ assert_pattern_list([/foo?/, :*], "foo?")
+
+ assert_not_pattern_list(["foo?"], "foo")
+ assert_not_pattern_list(["foo?"], "afoo")
+ assert_pattern_list(["foo?"], "foo?")
+ assert_not_pattern_list([:*, "foo?", :*], "foo")
+ assert_not_pattern_list([:*, "foo?"], "afoo")
+ assert_pattern_list([:*, "foo?"], "afoo?")
+ assert_pattern_list(["foo?", :*], "foo?")
+ end
+
+ def assert_not_pattern_list(pattern_list, actual, message=nil)
+ assert_raise(Test::Unit::AssertionFailedError) do
+ assert_pattern_list(pattern_list, actual, message)
+ end
+ end
end
diff --git a/tool/test/testunit/test_hideskip.rb b/tool/test/testunit/test_hideskip.rb
index e90be5da32..0c4c9b40f2 100644
--- a/tool/test/testunit/test_hideskip.rb
+++ b/tool/test/testunit/test_hideskip.rb
@@ -4,16 +4,16 @@ require 'test/unit'
class TestHideSkip < Test::Unit::TestCase
def test_hideskip
assert_not_match(/^ *1\) Skipped/, hideskip)
- assert_match(/^ *1\) Skipped/, hideskip("--show-skip"))
+ assert_match(/^ *1\) Skipped.*^ *2\) Skipped/m, hideskip("--show-skip"))
output = hideskip("--hide-skip")
- output.gsub!(/Successful MJIT finish\n/, '') if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
- assert_match(/assertions\/s.\n+1 tests, 0 assertions, 0 failures, 0 errors, 1 skips/, output)
+ output.gsub!(/Successful RJIT finish\n/, '') if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ assert_match(/assertions\/s.\n+2 tests, 0 assertions, 0 failures, 0 errors, 2 skips/, output)
end
private
def hideskip(*args)
- IO.popen([*@options[:ruby], "#{File.dirname(__FILE__)}/test4test_hideskip.rb",
+ IO.popen([*@__runner_options__[:ruby], "#{File.dirname(__FILE__)}/test4test_hideskip.rb",
"--verbose", *args], err: [:child, :out]) {|f|
f.read
}
diff --git a/tool/test/testunit/test_launchable.rb b/tool/test/testunit/test_launchable.rb
new file mode 100644
index 0000000000..70c371e212
--- /dev/null
+++ b/tool/test/testunit/test_launchable.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'tempfile'
+require 'json'
+
+class TestLaunchable < Test::Unit::TestCase
+ def test_json_stream_writer
+ Tempfile.create(['launchable-test-', '.json']) do |f|
+ json_stream_writer = Test::Unit::LaunchableOption::JsonStreamWriter.new(f.path)
+ json_stream_writer.write_array('testCases')
+ json_stream_writer.write_object(
+ {
+ testPath: "file=test/test_a.rb#class=class1#testcase=testcase899",
+ duration: 42,
+ status: "TEST_FAILED",
+ stdout: nil,
+ stderr: nil,
+ createdAt: "2021-10-05T12:34:00",
+ data: {
+ lineNumber: 1
+ }
+ }
+ )
+ json_stream_writer.write_object(
+ {
+ testPath: "file=test/test_a.rb#class=class1#testcase=testcase899",
+ duration: 45,
+ status: "TEST_PASSED",
+ stdout: "This is stdout",
+ stderr: "This is stderr",
+ createdAt: "2021-10-05T12:36:00",
+ data: {
+ lineNumber: 10
+ }
+ }
+ )
+ json_stream_writer.close()
+ expected = <<JSON
+{
+ "testCases": [
+ {
+ "testPath": "file=test/test_a.rb#class=class1#testcase=testcase899",
+ "duration": 42,
+ "status": "TEST_FAILED",
+ "stdout": null,
+ "stderr": null,
+ "createdAt": "2021-10-05T12:34:00",
+ "data": {
+ "lineNumber": 1
+ }
+ },
+ {
+ "testPath": "file=test/test_a.rb#class=class1#testcase=testcase899",
+ "duration": 45,
+ "status": "TEST_PASSED",
+ "stdout": "This is stdout",
+ "stderr": "This is stderr",
+ "createdAt": "2021-10-05T12:36:00",
+ "data": {
+ "lineNumber": 10
+ }
+ }
+ ]
+}
+JSON
+ assert_equal(expected, f.read)
+ end
+ end
+end
diff --git a/tool/test/testunit/test_load_failure.rb b/tool/test/testunit/test_load_failure.rb
new file mode 100644
index 0000000000..8defa9e39a
--- /dev/null
+++ b/tool/test/testunit/test_load_failure.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+require 'test/unit'
+
+class TestLoadFailure < Test::Unit::TestCase
+ def test_load_failure
+ assert_not_predicate(load_failure, :success?)
+ end
+
+ def test_load_failure_parallel
+ assert_not_predicate(load_failure("-j2"), :success?)
+ end
+
+ private
+
+ def load_failure(*args)
+ IO.popen([*@__runner_options__[:ruby], "#{__dir__}/../runner.rb",
+ "#{__dir__}/test4test_load_failure.rb",
+ "--verbose", *args], err: [:child, :out]) {|f|
+ assert_include(f.read, "test4test_load_failure.rb")
+ }
+ $?
+ end
+end
diff --git a/tool/test/testunit/test_minitest_unit.rb b/tool/test/testunit/test_minitest_unit.rb
new file mode 100644
index 0000000000..84b6cf688c
--- /dev/null
+++ b/tool/test/testunit/test_minitest_unit.rb
@@ -0,0 +1,1488 @@
+# encoding: utf-8
+# frozen_string_literal: false
+
+require 'pathname'
+require_relative 'metametameta'
+
+module MyModule; end
+class AnError < StandardError; include MyModule; end
+class ImmutableString < String; def inspect; super.freeze; end; end
+
+class TestMiniTestUnit < MetaMetaMetaTestCase
+ pwd = Pathname.new File.expand_path Dir.pwd
+ basedir = Pathname.new(File.expand_path "lib/test")
+ basedir = basedir.relative_path_from(pwd).to_s
+ MINITEST_BASE_DIR = basedir[/\A\./] ? basedir : "./#{basedir}"
+ BT_MIDDLE = ["#{MINITEST_BASE_DIR}/test.rb:161:in `each'",
+ "#{MINITEST_BASE_DIR}/test.rb:158:in `each'",
+ "#{MINITEST_BASE_DIR}/test.rb:139:in `run'",
+ "#{MINITEST_BASE_DIR}/test.rb:106:in `run'"]
+
+ def test_class_puke_with_assertion_failed
+ exception = Test::Unit::AssertionFailedError.new "Oh no!"
+ exception.set_backtrace ["unhappy"]
+ assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception)
+ assert_equal 1, @tu.failures
+ assert_match(/^Failure.*Oh no!/m, @tu.report.first)
+ assert_match("SomeClass#method_name [unhappy]", @tu.report.first)
+ end
+
+ def test_class_puke_with_assertion_failed_and_long_backtrace
+ bt = (["test/test_some_class.rb:615:in `method_name'",
+ "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raise'",
+ "test/test_some_class.rb:615:in `each'",
+ "test/test_some_class.rb:614:in `test_method_name'",
+ "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+ BT_MIDDLE +
+ ["#{MINITEST_BASE_DIR}/test.rb:29"])
+ bt = util_expand_bt bt
+
+ ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first
+
+ exception = Test::Unit::AssertionFailedError.new "Oh no!"
+ exception.set_backtrace bt
+ assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception)
+ assert_equal 1, @tu.failures
+ assert_match(/^Failure.*Oh no!/m, @tu.report.first)
+ assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first)
+ end
+
+ def test_class_puke_with_assertion_failed_and_user_defined_assertions
+ bt = (["lib/test/my/util.rb:16:in `another_method_name'",
+ "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raise'",
+ "lib/test/my/util.rb:15:in `block in assert_something'",
+ "lib/test/my/util.rb:14:in `each'",
+ "lib/test/my/util.rb:14:in `assert_something'",
+ "test/test_some_class.rb:615:in `each'",
+ "test/test_some_class.rb:614:in `test_method_name'",
+ "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+ BT_MIDDLE +
+ ["#{MINITEST_BASE_DIR}/test.rb:29"])
+ bt = util_expand_bt bt
+
+ ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first
+
+ exception = Test::Unit::AssertionFailedError.new "Oh no!"
+ exception.set_backtrace bt
+ assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception)
+ assert_equal 1, @tu.failures
+ assert_match(/^Failure.*Oh no!/m, @tu.report.first)
+ assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first)
+ end
+
+ def test_class_puke_with_failure_and_flunk_in_backtrace
+ exception = begin
+ Test::Unit::TestCase.new('fake tc').flunk
+ rescue Test::Unit::AssertionFailedError => failure
+ failure
+ end
+ assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception)
+ refute @tu.report.any?{|line| line =~ /in .flunk/}
+ end
+
+ def test_class_puke_with_flunk_and_user_defined_assertions
+ bt = (["lib/test/my/util.rb:16:in `flunk'",
+ "#{MINITEST_BASE_DIR}/unit.rb:140:in `assert_raise'",
+ "lib/test/my/util.rb:15:in `block in assert_something'",
+ "lib/test/my/util.rb:14:in `each'",
+ "lib/test/my/util.rb:14:in `assert_something'",
+ "test/test_some_class.rb:615:in `each'",
+ "test/test_some_class.rb:614:in `test_method_name'",
+ "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+ BT_MIDDLE +
+ ["#{MINITEST_BASE_DIR}/test.rb:29"])
+ bt = util_expand_bt bt
+
+ ex_location = util_expand_bt(["test/test_some_class.rb:615"]).first
+
+ exception = Test::Unit::AssertionFailedError.new "Oh no!"
+ exception.set_backtrace bt
+ assert_equal 'F', @tu.puke('TestSomeClass', 'test_method_name', exception)
+ assert_equal 1, @tu.failures
+ assert_match(/^Failure.*Oh no!/m, @tu.report.first)
+ assert_match("TestSomeClass#test_method_name [#{ex_location}]", @tu.report.first)
+ end
+
+ def test_class_puke_with_non_failure_exception
+ exception = Exception.new("Oh no again!")
+ assert_equal 'E', @tu.puke('SomeClass', 'method_name', exception)
+ assert_equal 1, @tu.errors
+ assert_match(/^Exception.*Oh no again!/m, @tu.report.first)
+ end
+
+ def test_filter_backtrace
+ # this is a semi-lame mix of relative paths.
+ # I cheated by making the autotest parts not have ./
+ bt = (["lib/autotest.rb:571:in `add_exception'",
+ "test/test_autotest.rb:62:in `test_add_exception'",
+ "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+ BT_MIDDLE +
+ ["#{MINITEST_BASE_DIR}/test.rb:29",
+ "test/test_autotest.rb:422"])
+ bt = util_expand_bt bt
+
+ ex = ["lib/autotest.rb:571:in `add_exception'",
+ "test/test_autotest.rb:62:in `test_add_exception'"]
+ ex = util_expand_bt ex
+
+ fu = Test::filter_backtrace(bt)
+
+ assert_equal ex, fu
+ end
+
+ def test_filter_backtrace_all_unit
+ bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+ BT_MIDDLE +
+ ["#{MINITEST_BASE_DIR}/test.rb:29"])
+ ex = bt.clone
+ fu = Test::filter_backtrace(bt)
+ assert_equal ex, fu
+ end
+
+ def test_filter_backtrace_unit_starts
+ bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+ BT_MIDDLE +
+ ["#{MINITEST_BASE_DIR}/mini/test.rb:29",
+ "-e:1"])
+
+ bt = util_expand_bt bt
+
+ ex = ["-e:1"]
+ fu = Test::filter_backtrace bt
+ assert_equal ex, fu
+ end
+
+ def test_default_runner_is_minitest_unit
+ assert_instance_of Test::Unit::Runner, Test::Unit::Runner.runner
+ end
+
+
+ def test_passed_eh_teardown_good
+ test_class = Class.new Test::Unit::TestCase do
+ def teardown; assert true; end
+ def test_omg; assert true; end
+ end
+
+ test = test_class.new :test_omg
+ test.run @tu
+ assert test.passed?
+ end
+
+ def test_passed_eh_teardown_skipped
+ test_class = Class.new Test::Unit::TestCase do
+ def teardown; assert true; end
+ def test_omg; omit "bork"; end
+ end
+
+ test = test_class.new :test_omg
+ test.run @tu
+ assert test.passed?
+ end
+
+ def test_passed_eh_teardown_flunked
+ test_class = Class.new Test::Unit::TestCase do
+ def teardown; flunk; end
+ def test_omg; assert true; end
+ end
+
+ test = test_class.new :test_omg
+ test.run @tu
+ refute test.passed?
+ end
+
+ def util_expand_bt bt
+ bt.map { |f| (f =~ /^\./) ? File.expand_path(f) : f }
+ end
+end
+
+class TestMiniTestUnitInherited < MetaMetaMetaTestCase
+ def with_overridden_include
+ Class.class_eval do
+ def inherited_with_hacks klass
+ throw :inherited_hook
+ end
+
+ alias inherited_without_hacks inherited
+ alias inherited inherited_with_hacks
+ alias IGNORE_ME! inherited # 1.8 bug. god I love venture bros
+ end
+
+ yield
+ ensure
+ Class.class_eval do
+ alias inherited inherited_without_hacks
+
+ undef_method :inherited_with_hacks
+ undef_method :inherited_without_hacks
+ end
+
+ refute_respond_to Class, :inherited_with_hacks
+ refute_respond_to Class, :inherited_without_hacks
+ end
+
+ def test_inherited_hook_plays_nice_with_others
+ with_overridden_include do
+ assert_throws :inherited_hook do
+ Class.new Test::Unit::TestCase
+ end
+ end
+ end
+end
+
+class TestMiniTestRunner < MetaMetaMetaTestCase
+ # do not parallelize this suite... it just can't handle it.
+
+ def test_class_test_suites
+ @assertion_count = 0
+
+ tc = Class.new(Test::Unit::TestCase)
+
+ assert_equal 2, Test::Unit::TestCase.test_suites.size
+ assert_equal [tc, Test::Unit::TestCase], Test::Unit::TestCase.test_suites.sort_by {|ts| ts.name.to_s}
+ end
+
+ def assert_filtering name, expected, a = false
+ args = %W[--name #{name} --seed 42]
+
+ alpha = Class.new Test::Unit::TestCase do
+ define_method :test_something do
+ assert a
+ end
+ end
+ Object.const_set(:Alpha, alpha)
+
+ beta = Class.new Test::Unit::TestCase do
+ define_method :test_something do
+ assert true
+ end
+ end
+ Object.const_set(:Beta, beta)
+
+ assert_report expected, args
+ ensure
+ Object.send :remove_const, :Alpha
+ Object.send :remove_const, :Beta
+ end
+
+ def test_run_with_other_runner
+ pend "We don't imagine to replace the default runner with ruby/ruby test suite."
+ Test::Unit::Runner.runner = Class.new Test::Unit::Runner do
+ def _run_suite suite, type
+ suite.before_suite # Run once before each suite
+ super suite, type
+ end
+ end.new
+
+ Class.new Test::Unit::TestCase do
+ def self.name; "wacky!" end
+
+ def self.before_suite
+ Test::Unit::Runner.output.puts "Running #{self.name} tests"
+ @@foo = 1
+ end
+
+ def test_something
+ assert_equal 1, @@foo
+ end
+
+ def test_something_else
+ assert_equal 1, @@foo
+ end
+ end
+
+ expected = clean <<-EOM
+ Running wacky! tests
+ ..
+
+ Finished tests in 0.00
+
+ 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips
+ EOM
+
+ assert_report expected
+ end
+
+ require 'monitor'
+
+ class Latch
+ def initialize count = 1
+ @count = count
+ @lock = Monitor.new
+ @cv = @lock.new_cond
+ end
+
+ def release
+ @lock.synchronize do
+ @count -= 1 if @count > 0
+ @cv.broadcast if @count == 0
+ end
+ end
+
+ def await
+ @lock.synchronize { @cv.wait_while { @count > 0 } }
+ end
+ end
+end
+
+class TestMiniTestUnitOrder < MetaMetaMetaTestCase
+ # do not parallelize this suite... it just can't handle it.
+
+ def test_before_setup
+ pend "Surpressing the raise message when running with tests"
+
+ call_order = []
+ Class.new Test::Unit::TestCase do
+ define_method :setup do
+ super()
+ call_order << :setup
+ end
+
+ define_method :before_setup do
+ call_order << :before_setup
+ end
+
+ def test_omg; assert true; end
+ end
+
+ with_output do
+ @tu.run %w[--seed 42]
+ end
+
+ expected = [:before_setup, :setup]
+ assert_equal expected, call_order
+ end
+
+ def test_after_teardown
+ pend "Surpressing the result message of this tests"
+
+ call_order = []
+ Class.new Test::Unit::TestCase do
+ define_method :teardown do
+ super()
+ call_order << :teardown
+ end
+
+ define_method :after_teardown do
+ call_order << :after_teardown
+ end
+
+ def test_omg; assert true; end
+ end
+
+ with_output do
+ @tu.run %w[--seed 42]
+ end
+
+ expected = [:teardown, :after_teardown]
+ assert_equal expected, call_order
+ end
+
+ def test_all_teardowns_are_guaranteed_to_run
+ pend "Surpressing the raise message when running with tests"
+
+ call_order = []
+ Class.new Test::Unit::TestCase do
+ define_method :after_teardown do
+ super()
+ call_order << :after_teardown
+ raise
+ end
+
+ define_method :teardown do
+ super()
+ call_order << :teardown
+ raise
+ end
+
+ define_method :before_teardown do
+ super()
+ call_order << :before_teardown
+ raise
+ end
+
+ def test_omg; assert true; end
+ end
+
+ with_output do
+ @tu.run %w[--seed 42]
+ end
+
+ expected = [:before_teardown, :teardown, :after_teardown]
+ assert_equal expected, call_order
+ end
+
+ def test_setup_and_teardown_survive_inheritance
+ pend "Surpressing the result message of this tests"
+
+ call_order = []
+
+ parent = Class.new Test::Unit::TestCase do
+ define_method :setup do
+ call_order << :setup_method
+ end
+
+ define_method :teardown do
+ call_order << :teardown_method
+ end
+
+ define_method :test_something do
+ call_order << :test
+ end
+ end
+
+ _ = Class.new parent
+
+ with_output do
+ @tu.run %w[--seed 42]
+ end
+
+ # Once for the parent class, once for the child
+ expected = [:setup_method, :test, :teardown_method] * 2
+
+ assert_equal expected, call_order
+ end
+end
+
+class TestMiniTestUnitTestCase < Test::Unit::TestCase
+ # do not call parallelize_me! - teardown accesses @tc._assertions
+ # which is not threadsafe. Nearly every method in here is an
+ # assertion test so it isn't worth splitting it out further.
+
+ def setup
+ super
+
+ Test::Unit::TestCase.reset
+
+ @tc = Test::Unit::TestCase.new 'fake tc'
+ @zomg = "zomg ponies!"
+ @assertion_count = 1
+ end
+
+ def teardown
+ assert_equal(@assertion_count, @tc._assertions,
+ "expected #{@assertion_count} assertions to be fired during the test, not #{@tc._assertions}") if @tc.passed?
+ end
+
+ def non_verbose
+ orig_verbose = $VERBOSE
+ $VERBOSE = false
+
+ yield
+ ensure
+ $VERBOSE = orig_verbose
+ end
+
+ def test_assert
+ @assertion_count = 2
+
+ @tc.assert_equal true, @tc.assert(true), "returns true on success"
+ end
+
+ def test_assert__triggered
+ util_assert_triggered "Failed assertion, no message given." do
+ @tc.assert false
+ end
+ end
+
+ def test_assert__triggered_message
+ util_assert_triggered @zomg do
+ @tc.assert false, @zomg
+ end
+ end
+
+ def test_assert_empty
+ @assertion_count = 2
+
+ @tc.assert_empty []
+ end
+
+ def test_assert_empty_triggered
+ @assertion_count = 2
+
+ util_assert_triggered "Expected [1] to be empty." do
+ @tc.assert_empty [1]
+ end
+ end
+
+ def test_assert_equal
+ @tc.assert_equal 1, 1
+ end
+
+ def test_assert_equal_different_collection_array_hex_invisible
+ object1 = Object.new
+ object2 = Object.new
+ msg = "<[#{object1.inspect}]> expected but was
+ <[#{object2.inspect}]>.".gsub(/^ +/, "")
+ util_assert_triggered msg do
+ @tc.assert_equal [object1], [object2]
+ end
+ end
+
+ def test_assert_equal_different_collection_hash_hex_invisible
+ h1, h2 = {}, {}
+ h1[1] = Object.new
+ h2[1] = Object.new
+ msg = "<#{h1.inspect}> expected but was
+ <#{h2.inspect}>.".gsub(/^ +/, "")
+
+ util_assert_triggered msg do
+ @tc.assert_equal h1, h2
+ end
+ end
+
+ def test_assert_equal_different_diff_deactivated
+ without_diff do
+ util_assert_triggered util_msg("haha" * 10, "blah" * 10) do
+ o1 = "haha" * 10
+ o2 = "blah" * 10
+
+ @tc.assert_equal o1, o2
+ end
+ end
+ end
+
+ def test_assert_equal_different_hex
+ c = Class.new do
+ def initialize s; @name = s; end
+ end
+
+ o1 = c.new "a"
+ o2 = c.new "b"
+ msg = "<#{o1.inspect}> expected but was
+ <#{o2.inspect}>.".gsub(/^ +/, "")
+
+ util_assert_triggered msg do
+ @tc.assert_equal o1, o2
+ end
+ end
+
+ def test_assert_equal_different_hex_invisible
+ o1 = Object.new
+ o2 = Object.new
+
+ msg = "<#{o1.inspect}> expected but was
+ <#{o2.inspect}>.".gsub(/^ +/, "")
+
+ util_assert_triggered msg do
+ @tc.assert_equal o1, o2
+ end
+ end
+
+ def test_assert_equal_different_long
+ msg = "<\"hahahahahahahahahahahahahahahahahahahaha\"> expected but was
+ <\"blahblahblahblahblahblahblahblahblahblah\">.".gsub(/^ +/, "")
+
+ util_assert_triggered msg do
+ o1 = "haha" * 10
+ o2 = "blah" * 10
+
+ @tc.assert_equal o1, o2
+ end
+ end
+
+ def test_assert_equal_different_long_invisible
+ msg = "<\"blahblahblahblahblahblahblahblahblahblah\"> (UTF-8) expected but was
+ <\"blahblahblahblahblahblahblahblahblahblah\"> (UTF-8).".gsub(/^ +/, "")
+
+ util_assert_triggered msg do
+ o1 = "blah" * 10
+ o2 = "blah" * 10
+ def o1.== o
+ false
+ end
+ @tc.assert_equal o1, o2
+ end
+ end
+
+ def test_assert_equal_different_long_msg
+ msg = "message.
+ <\"hahahahahahahahahahahahahahahahahahahaha\"> expected but was
+ <\"blahblahblahblahblahblahblahblahblahblah\">.".gsub(/^ +/, "")
+
+ util_assert_triggered msg do
+ o1 = "haha" * 10
+ o2 = "blah" * 10
+ @tc.assert_equal o1, o2, "message"
+ end
+ end
+
+ def test_assert_equal_different_short
+ util_assert_triggered util_msg(1, 2) do
+ @tc.assert_equal 1, 2
+ end
+ end
+
+ def test_assert_equal_different_short_msg
+ util_assert_triggered util_msg(1, 2, "message") do
+ @tc.assert_equal 1, 2, "message"
+ end
+ end
+
+ def test_assert_equal_different_short_multiline
+ msg = "<\"a\\n\" + \"b\"> expected but was\n<\"a\\n\" + \"c\">."
+ util_assert_triggered msg do
+ @tc.assert_equal "a\nb", "a\nc"
+ end
+ end
+
+ def test_assert_equal_different_escaped_newline
+ msg = "<\"xxx\\n\" + \"a\\\\nb\"> expected but was\n<\"xxx\\n\" + \"a\\\\nc\">."
+ util_assert_triggered msg do
+ @tc.assert_equal "xxx\na\\nb", "xxx\na\\nc"
+ end
+ end
+
+ def test_assert_in_delta
+ @tc.assert_in_delta 0.0, 1.0 / 1000, 0.1
+ end
+
+ def test_delta_consistency
+ @tc.assert_in_delta 0, 1, 1
+
+ util_assert_triggered "Expected |0 - 1| (1) to not be <= 1." do
+ @tc.refute_in_delta 0, 1, 1
+ end
+ end
+
+ def test_assert_in_delta_triggered
+ x = "1.0e-06"
+ util_assert_triggered "Expected |0.0 - 0.001| (0.001) to be <= #{x}." do
+ @tc.assert_in_delta 0.0, 1.0 / 1000, 0.000001
+ end
+ end
+
+ def test_assert_in_epsilon
+ @assertion_count = 10
+
+ @tc.assert_in_epsilon 10000, 9991
+ @tc.assert_in_epsilon 9991, 10000
+ @tc.assert_in_epsilon 1.0, 1.001
+ @tc.assert_in_epsilon 1.001, 1.0
+
+ @tc.assert_in_epsilon 10000, 9999.1, 0.0001
+ @tc.assert_in_epsilon 9999.1, 10000, 0.0001
+ @tc.assert_in_epsilon 1.0, 1.0001, 0.0001
+ @tc.assert_in_epsilon 1.0001, 1.0, 0.0001
+
+ @tc.assert_in_epsilon(-1, -1)
+ @tc.assert_in_epsilon(-10000, -9991)
+ end
+
+ def test_epsilon_consistency
+ @tc.assert_in_epsilon 1.0, 1.001
+
+ msg = "Expected |1.0 - 1.001| (0.000999xxx) to not be <= 0.001."
+ util_assert_triggered msg do
+ @tc.refute_in_epsilon 1.0, 1.001
+ end
+ end
+
+ def test_assert_in_epsilon_triggered
+ util_assert_triggered 'Expected |10000 - 9990| (10) to be <= 9.99.' do
+ @tc.assert_in_epsilon 10000, 9990
+ end
+ end
+
+ def test_assert_in_epsilon_triggered_negative_case
+ x = "0.100000xxx"
+ y = "0.1"
+ util_assert_triggered "Expected |-1.1 - -1| (#{x}) to be <= #{y}." do
+ @tc.assert_in_epsilon(-1.1, -1, 0.1)
+ end
+ end
+
+ def test_assert_includes
+ @assertion_count = 2
+
+ @tc.assert_includes [true], true
+ end
+
+ def test_assert_includes_triggered
+ @assertion_count = 3
+
+ e = @tc.assert_raise Test::Unit::AssertionFailedError do
+ @tc.assert_includes [true], false
+ end
+
+ expected = "Expected [true] to include false."
+ assert_equal expected, e.message
+ end
+
+ def test_assert_instance_of
+ @tc.assert_instance_of String, "blah"
+ end
+
+ def test_assert_instance_of_triggered
+ util_assert_triggered 'Expected "blah" to be an instance of Array, not String.' do
+ @tc.assert_instance_of Array, "blah"
+ end
+ end
+
+ def test_assert_kind_of
+ @tc.assert_kind_of String, "blah"
+ end
+
+ def test_assert_kind_of_triggered
+ util_assert_triggered 'Expected "blah" to be a kind of Array, not String.' do
+ @tc.assert_kind_of Array, "blah"
+ end
+ end
+
+ def test_assert_match
+ @assertion_count = 2
+ @tc.assert_match(/\w+/, "blah blah blah")
+ end
+
+ def test_assert_match_matcher_object
+ @assertion_count = 2
+
+ pattern = Object.new
+ def pattern.=~(other) true end
+
+ @tc.assert_match pattern, 5
+ end
+
+ def test_assert_match_matchee_to_str
+ @assertion_count = 2
+
+ obj = Object.new
+ def obj.to_str; "blah" end
+
+ @tc.assert_match "blah", obj
+ end
+
+ def test_assert_match_object_triggered
+ @assertion_count = 2
+
+ pattern = Object.new
+ def pattern.=~(other) false end
+ def pattern.inspect; "[Object]" end
+
+ util_assert_triggered 'Expected [Object] to match 5.' do
+ @tc.assert_match pattern, 5
+ end
+ end
+
+ def test_assert_match_triggered
+ @assertion_count = 2
+ util_assert_triggered 'Expected /\d+/ to match "blah blah blah".' do
+ @tc.assert_match(/\d+/, "blah blah blah")
+ end
+ end
+
+ def test_assert_nil
+ @tc.assert_nil nil
+ end
+
+ def test_assert_nil_triggered
+ util_assert_triggered 'Expected 42 to be nil.' do
+ @tc.assert_nil 42
+ end
+ end
+
+ def test_assert_operator
+ @tc.assert_operator 2, :>, 1
+ end
+
+ def test_assert_operator_bad_object
+ bad = Object.new
+ def bad.==(other) true end
+
+ @tc.assert_operator bad, :equal?, bad
+ end
+
+ def test_assert_operator_triggered
+ util_assert_triggered "Expected 2 to be < 1." do
+ @tc.assert_operator 2, :<, 1
+ end
+ end
+
+ def test_assert_output_both
+ @assertion_count = 2
+
+ @tc.assert_output "yay", "blah" do
+ print "yay"
+ $stderr.print "blah"
+ end
+ end
+
+ def test_assert_output_both_regexps
+ @assertion_count = 4
+
+ @tc.assert_output(/y.y/, /bl.h/) do
+ print "yay"
+ $stderr.print "blah"
+ end
+ end
+
+ def test_assert_output_err
+ @tc.assert_output nil, "blah" do
+ $stderr.print "blah"
+ end
+ end
+
+ def test_assert_output_neither
+ @assertion_count = 0
+
+ @tc.assert_output do
+ # do nothing
+ end
+ end
+
+ def test_assert_output_out
+ @tc.assert_output "blah" do
+ print "blah"
+ end
+ end
+
+ def test_assert_output_triggered_both
+ util_assert_triggered util_msg("blah", "blah blah", "In stderr") do
+ @tc.assert_output "yay", "blah" do
+ print "boo"
+ $stderr.print "blah blah"
+ end
+ end
+ end
+
+ def test_assert_output_triggered_err
+ util_assert_triggered util_msg("blah", "blah blah", "In stderr") do
+ @tc.assert_output nil, "blah" do
+ $stderr.print "blah blah"
+ end
+ end
+ end
+
+ def test_assert_output_triggered_out
+ util_assert_triggered util_msg("blah", "blah blah", "In stdout") do
+ @tc.assert_output "blah" do
+ print "blah blah"
+ end
+ end
+ end
+
+ def test_assert_predicate
+ @tc.assert_predicate "", :empty?
+ end
+
+ def test_assert_predicate_triggered
+ util_assert_triggered 'Expected "blah" to be empty?.' do
+ @tc.assert_predicate "blah", :empty?
+ end
+ end
+
+ def test_assert_raise
+ @tc.assert_raise RuntimeError do
+ raise "blah"
+ end
+ end
+
+ def test_assert_raise_module
+ @tc.assert_raise MyModule do
+ raise AnError
+ end
+ end
+
+ ##
+ # *sigh* This is quite an odd scenario, but it is from real (albeit
+ # ugly) test code in ruby-core:
+ #
+ # https://github.com/ruby/ruby/commit/6bab4ea9917dc05cd2c94aead2e96eb7df7d4be1
+
+ def test_assert_raise_skip
+ @assertion_count = 0
+
+ util_assert_triggered "skipped", Test::Unit::PendedError do
+ @tc.assert_raise ArgumentError do
+ begin
+ raise "blah"
+ rescue
+ omit "skipped"
+ end
+ end
+ end
+ end
+
+ def test_assert_raise_triggered_different
+ e = assert_raise Test::Unit::AssertionFailedError do
+ @tc.assert_raise RuntimeError do
+ raise SyntaxError, "icky"
+ end
+ end
+
+ expected = clean <<-EOM.chomp
+ [RuntimeError] exception expected, not #<SyntaxError: icky>.
+ EOM
+
+ actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE')
+ actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION >= '1.9.0'
+
+ assert_equal expected, actual
+ end
+
+ def test_assert_raise_triggered_different_msg
+ e = assert_raise Test::Unit::AssertionFailedError do
+ @tc.assert_raise RuntimeError, "XXX" do
+ raise SyntaxError, "icky"
+ end
+ end
+
+ expected = clean <<-EOM
+ XXX.
+ [RuntimeError] exception expected, not #<SyntaxError: icky>.
+ EOM
+
+ actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE')
+ actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION >= '1.9.0'
+
+ assert_equal expected.chomp, actual
+ end
+
+ def test_assert_raise_triggered_none
+ e = assert_raise Test::Unit::AssertionFailedError do
+ @tc.assert_raise Test::Unit::AssertionFailedError do
+ # do nothing
+ end
+ end
+
+ expected = "Test::Unit::AssertionFailedError expected but nothing was raised."
+
+ assert_equal expected, e.message
+ end
+
+ def test_assert_raise_triggered_none_msg
+ e = assert_raise Test::Unit::AssertionFailedError do
+ @tc.assert_raise Test::Unit::AssertionFailedError, "XXX" do
+ # do nothing
+ end
+ end
+
+ expected = "XXX.\nTest::Unit::AssertionFailedError expected but nothing was raised."
+
+ assert_equal expected, e.message
+ end
+
+ def test_assert_raise_triggered_subclass
+ e = assert_raise Test::Unit::AssertionFailedError do
+ @tc.assert_raise StandardError do
+ raise AnError
+ end
+ end
+
+ expected = clean <<-EOM.chomp
+ [StandardError] exception expected, not #<AnError: AnError>.
+ EOM
+
+ actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE')
+ actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION >= '1.9.0'
+
+ assert_equal expected, actual
+ end
+
+ def test_assert_respond_to
+ @tc.assert_respond_to "blah", :empty?
+ end
+
+ def test_assert_respond_to_triggered
+ util_assert_triggered 'Expected "blah" (String) to respond to #rawr!.' do
+ @tc.assert_respond_to "blah", :rawr!
+ end
+ end
+
+ def test_assert_same
+ @assertion_count = 3
+
+ o = "blah"
+ @tc.assert_same 1, 1
+ @tc.assert_same :blah, :blah
+ @tc.assert_same o, o
+ end
+
+ def test_assert_same_triggered
+ @assertion_count = 2
+
+ util_assert_triggered 'Expected 2 (oid=N) to be the same as 1 (oid=N).' do
+ @tc.assert_same 1, 2
+ end
+
+ s1 = "blah"
+ s2 = "blah"
+
+ util_assert_triggered 'Expected "blah" (oid=N) to be the same as "blah" (oid=N).' do
+ @tc.assert_same s1, s2
+ end
+ end
+
+ def test_assert_send
+ @tc.assert_send [1, :<, 2]
+ end
+
+ def test_assert_send_bad
+ util_assert_triggered "Expected 1.>(2) to return true." do
+ @tc.assert_send [1, :>, 2]
+ end
+ end
+
+ def test_assert_silent
+ @assertion_count = 2
+
+ @tc.assert_silent do
+ # do nothing
+ end
+ end
+
+ def test_assert_silent_triggered_err
+ util_assert_triggered util_msg("", "blah blah", "In stderr") do
+ @tc.assert_silent do
+ $stderr.print "blah blah"
+ end
+ end
+ end
+
+ def test_assert_silent_triggered_out
+ @assertion_count = 2
+
+ util_assert_triggered util_msg("", "blah blah", "In stdout") do
+ @tc.assert_silent do
+ print "blah blah"
+ end
+ end
+ end
+
+ def test_assert_throws
+ @tc.assert_throws :blah do
+ throw :blah
+ end
+ end
+
+ def test_assert_throws_different
+ util_assert_triggered 'Expected :blah to have been thrown, not :not_blah.' do
+ @tc.assert_throws :blah do
+ throw :not_blah
+ end
+ end
+ end
+
+ def test_assert_throws_unthrown
+ util_assert_triggered 'Expected :blah to have been thrown.' do
+ @tc.assert_throws :blah do
+ # do nothing
+ end
+ end
+ end
+
+ def test_capture_output
+ @assertion_count = 0
+
+ non_verbose do
+ out, err = capture_output do
+ puts 'hi'
+ $stderr.puts 'bye!'
+ end
+
+ assert_equal "hi\n", out
+ assert_equal "bye!\n", err
+ end
+ end
+
+ def test_flunk
+ util_assert_triggered 'Epic Fail!' do
+ @tc.flunk
+ end
+ end
+
+ def test_flunk_message
+ util_assert_triggered @zomg do
+ @tc.flunk @zomg
+ end
+ end
+
+ def test_message
+ @assertion_count = 0
+
+ assert_equal "blah2.", @tc.message { "blah2" }.call
+ assert_equal "blah2.", @tc.message("") { "blah2" }.call
+ assert_equal "blah1.\nblah2.", @tc.message(:blah1) { "blah2" }.call
+ assert_equal "blah1.\nblah2.", @tc.message("blah1") { "blah2" }.call
+
+ message = proc { "blah1" }
+ assert_equal "blah1.\nblah2.", @tc.message(message) { "blah2" }.call
+
+ message = @tc.message { "blah1" }
+ assert_equal "blah1.\nblah2.", @tc.message(message) { "blah2" }.call
+ end
+
+ def test_message_message
+ util_assert_triggered "whoops.\n<1> expected but was\n<2>." do
+ @tc.assert_equal 1, 2, message { "whoops" }
+ end
+ end
+
+ def test_message_lambda
+ util_assert_triggered "whoops.\n<1> expected but was\n<2>." do
+ @tc.assert_equal 1, 2, lambda { "whoops" }
+ end
+ end
+
+ def test_message_deferred
+ @assertion_count, var = 0, nil
+
+ msg = message { var = "blah" }
+
+ assert_nil var
+
+ msg.call
+
+ assert_equal "blah", var
+ end
+
+ def test_pass
+ @tc.pass
+ end
+
+ def test_prints
+ printer = Class.new { extend Test::Unit::CoreAssertions }
+ @tc.assert_equal '"test"', printer.mu_pp(ImmutableString.new 'test')
+ end
+
+ def test_refute
+ @assertion_count = 2
+
+ @tc.assert_equal false, @tc.refute(false), "returns false on success"
+ end
+
+ def test_refute_empty
+ @assertion_count = 2
+
+ @tc.refute_empty [1]
+ end
+
+ def test_refute_empty_triggered
+ @assertion_count = 2
+
+ util_assert_triggered "Expected [] to not be empty." do
+ @tc.refute_empty []
+ end
+ end
+
+ def test_refute_equal
+ @tc.refute_equal "blah", "yay"
+ end
+
+ def test_refute_equal_triggered
+ util_assert_triggered 'Expected "blah" to not be equal to "blah".' do
+ @tc.refute_equal "blah", "blah"
+ end
+ end
+
+ def test_refute_in_delta
+ @tc.refute_in_delta 0.0, 1.0 / 1000, 0.000001
+ end
+
+ def test_refute_in_delta_triggered
+ x = "0.1"
+ util_assert_triggered "Expected |0.0 - 0.001| (0.001) to not be <= #{x}." do
+ @tc.refute_in_delta 0.0, 1.0 / 1000, 0.1
+ end
+ end
+
+ def test_refute_in_epsilon
+ @tc.refute_in_epsilon 10000, 9990-1
+ end
+
+ def test_refute_in_epsilon_triggered
+ util_assert_triggered 'Expected |10000 - 9990| (10) to not be <= 10.0.' do
+ @tc.refute_in_epsilon 10000, 9990
+ fail
+ end
+ end
+
+ def test_refute_includes
+ @assertion_count = 2
+
+ @tc.refute_includes [true], false
+ end
+
+ def test_refute_includes_triggered
+ @assertion_count = 3
+
+ e = @tc.assert_raise Test::Unit::AssertionFailedError do
+ @tc.refute_includes [true], true
+ end
+
+ expected = "Expected [true] to not include true."
+ assert_equal expected, e.message
+ end
+
+ def test_refute_instance_of
+ @tc.refute_instance_of Array, "blah"
+ end
+
+ def test_refute_instance_of_triggered
+ util_assert_triggered 'Expected "blah" to not be an instance of String.' do
+ @tc.refute_instance_of String, "blah"
+ end
+ end
+
+ def test_refute_kind_of
+ @tc.refute_kind_of Array, "blah"
+ end
+
+ def test_refute_kind_of_triggered
+ util_assert_triggered 'Expected "blah" to not be a kind of String.' do
+ @tc.refute_kind_of String, "blah"
+ end
+ end
+
+ def test_refute_match
+ @assertion_count = 2
+ @tc.refute_match(/\d+/, "blah blah blah")
+ end
+
+ def test_refute_match_matcher_object
+ @assertion_count = 2
+ non_verbose do
+ obj = Object.new
+ def obj.=~(other); false; end
+ @tc.refute_match obj, 5
+ end
+ end
+
+ def test_refute_match_object_triggered
+ @assertion_count = 2
+
+ pattern = Object.new
+ def pattern.=~(other) true end
+ def pattern.inspect; "[Object]" end
+
+ util_assert_triggered 'Expected [Object] to not match 5.' do
+ @tc.refute_match pattern, 5
+ end
+ end
+
+ def test_refute_match_triggered
+ @assertion_count = 2
+ util_assert_triggered 'Expected /\w+/ to not match "blah blah blah".' do
+ @tc.refute_match(/\w+/, "blah blah blah")
+ end
+ end
+
+ def test_refute_nil
+ @tc.refute_nil 42
+ end
+
+ def test_refute_nil_triggered
+ util_assert_triggered 'Expected nil to not be nil.' do
+ @tc.refute_nil nil
+ end
+ end
+
+ def test_refute_predicate
+ @tc.refute_predicate "42", :empty?
+ end
+
+ def test_refute_predicate_triggered
+ util_assert_triggered 'Expected "" to not be empty?.' do
+ @tc.refute_predicate "", :empty?
+ end
+ end
+
+ def test_refute_operator
+ @tc.refute_operator 2, :<, 1
+ end
+
+ def test_refute_operator_bad_object
+ bad = Object.new
+ def bad.==(other) true end
+
+ @tc.refute_operator true, :equal?, bad
+ end
+
+ def test_refute_operator_triggered
+ util_assert_triggered "Expected 2 to not be > 1." do
+ @tc.refute_operator 2, :>, 1
+ end
+ end
+
+ def test_refute_respond_to
+ @tc.refute_respond_to "blah", :rawr!
+ end
+
+ def test_refute_respond_to_triggered
+ util_assert_triggered 'Expected "blah" to not respond to empty?.' do
+ @tc.refute_respond_to "blah", :empty?
+ end
+ end
+
+ def test_refute_same
+ @tc.refute_same 1, 2
+ end
+
+ def test_refute_same_triggered
+ util_assert_triggered 'Expected 1 (oid=N) to not be the same as 1 (oid=N).' do
+ @tc.refute_same 1, 1
+ end
+ end
+
+ def test_omit
+ @assertion_count = 0
+
+ util_assert_triggered "haha!", Test::Unit::PendedError do
+ @tc.omit "haha!"
+ end
+ end
+
+ def test_pend
+ @assertion_count = 0
+
+ util_assert_triggered "haha!", Test::Unit::PendedError do
+ @tc.pend "haha!"
+ end
+ end
+
+ def test_test_methods
+ @assertion_count = 0
+
+ sample_test_case = Class.new Test::Unit::TestCase do
+ def test_test1; assert "does not matter" end
+ def test_test2; assert "does not matter" end
+ def test_test3; assert "does not matter" end
+ end
+
+ expected = %i(test_test1 test_test2 test_test3)
+ assert_equal expected, sample_test_case.test_methods.sort
+ end
+
+ def assert_triggered expected, klass = Test::Unit::AssertionFailedError
+ e = assert_raise klass do
+ yield
+ end
+
+ msg = e.message.sub(/(---Backtrace---).*/m, '\1')
+ msg.gsub!(/\(oid=[-0-9]+\)/, '(oid=N)')
+ msg.gsub!(/(\d\.\d{6})\d+/, '\1xxx') # normalize: ruby version, impl, platform
+
+ assert_equal expected, msg
+ end
+ alias util_assert_triggered assert_triggered
+
+ def util_msg exp, act, msg = nil
+ s = "<#{exp.inspect}> expected but was\n<#{act.inspect}>."
+ s = "#{msg}.\n#{s}" if msg
+ s
+ end
+
+ def without_diff
+ old_diff = Test::Unit::Assertions.diff
+ Test::Unit::Assertions.diff = nil
+
+ yield
+ ensure
+ Test::Unit::Assertions.diff = old_diff
+ end
+end
+
+class TestMiniTestGuard < Test::Unit::TestCase
+ def test_mri_eh
+ assert self.class.mri? "ruby blah"
+ assert self.mri? "ruby blah"
+ end
+
+ def test_jruby_eh
+ assert self.class.jruby? "java"
+ assert self.jruby? "java"
+ end
+
+ def test_windows_eh
+ assert self.class.windows? "mswin"
+ assert self.windows? "mswin"
+ end
+end
+
+class TestMiniTestUnitRecording < MetaMetaMetaTestCase
+ # do not parallelize this suite... it just can't handle it.
+
+ def assert_run_record(*expected, &block)
+ pend "Test::Unit::Runner#run was changed about recoding feature. We should fix it."
+ def @tu.record suite, method, assertions, time, error
+ recording[method] << error
+ end
+
+ def @tu.recording
+ @recording ||= Hash.new { |h,k| h[k] = [] }
+ end
+
+ Test::Unit::Runner.runner = @tu
+
+ Class.new Test::Unit::TestCase, &block
+
+ with_output do
+ @tu.run
+ end
+
+ recorded = @tu.recording.fetch("test_method").map(&:class)
+
+ assert_equal expected, recorded
+ end
+
+ def test_record_passing
+ assert_run_record NilClass do
+ def test_method
+ assert true
+ end
+ end
+ end
+
+ def test_record_failing
+ assert_run_record Test::Unit::AssertionFailedError do
+ def test_method
+ assert false
+ end
+ end
+ end
+
+ def test_record_error
+ assert_run_record RuntimeError do
+ def test_method
+ raise "unhandled exception"
+ end
+ end
+ end
+
+ def test_record_error_teardown
+ assert_run_record NilClass, RuntimeError do
+ def test_method
+ assert true
+ end
+
+ def teardown
+ raise "unhandled exception"
+ end
+ end
+ end
+
+ def test_record_error_in_test_and_teardown
+ assert_run_record AnError, RuntimeError do
+ def test_method
+ raise AnError
+ end
+
+ def teardown
+ raise "unhandled exception"
+ end
+ end
+ end
+
+ def test_record_skip
+ assert_run_record Test::Unit::PendedError do
+ def test_method
+ omit "not yet"
+ end
+ end
+
+ assert_run_record Test::Unit::PendedError do
+ def test_method
+ pend "not yet"
+ end
+ end
+ end
+end
diff --git a/tool/test/testunit/test_parallel.rb b/tool/test/testunit/test_parallel.rb
index fa87ca53ab..6882fd6c5f 100644
--- a/tool/test/testunit/test_parallel.rb
+++ b/tool/test/testunit/test_parallel.rb
@@ -3,17 +3,17 @@ require 'test/unit'
require 'timeout'
module TestParallel
- PARALLEL_RB = "#{File.dirname(__FILE__)}/../../lib/test/unit/parallel.rb"
- TESTS = "#{File.dirname(__FILE__)}/tests_for_parallel"
+ PARALLEL_RB = "#{__dir__}/../../lib/test/unit/parallel.rb"
+ TESTS = "#{__dir__}/tests_for_parallel"
# use large timeout for --jit-wait
- TIMEOUT = EnvUtil.apply_timeout_scale(defined?(RubyVM::JIT) && RubyVM::JIT.enabled? ? 100 : 30)
+ TIMEOUT = EnvUtil.apply_timeout_scale(defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? ? 100 : 30)
class TestParallelWorker < Test::Unit::TestCase
def setup
i, @worker_in = IO.pipe
@worker_out, o = IO.pipe
- @worker_pid = spawn(*@options[:ruby], PARALLEL_RB,
- "--ruby", @options[:ruby].join(" "),
+ @worker_pid = spawn(*@__runner_options__[:ruby], PARALLEL_RB,
+ "--ruby", @__runner_options__[:ruby].join(" "),
"-j", "t1", "-v", out: o, in: i)
[i,o].each(&:close)
end
@@ -49,6 +49,7 @@ module TestParallel
assert_match(/^ready/,@worker_out.gets)
@worker_in.puts "run #{TESTS}/ptest_first.rb test"
assert_match(/^okay/,@worker_out.gets)
+ assert_match(/^start/,@worker_out.gets)
assert_match(/^record/,@worker_out.gets)
assert_match(/^p/,@worker_out.gets)
assert_match(/^done/,@worker_out.gets)
@@ -61,9 +62,11 @@ module TestParallel
assert_match(/^ready/,@worker_out.gets)
@worker_in.puts "run #{TESTS}/ptest_second.rb test"
assert_match(/^okay/,@worker_out.gets)
+ assert_match(/^start/,@worker_out.gets)
assert_match(/^record/,@worker_out.gets)
assert_match(/^p/,@worker_out.gets)
assert_match(/^done/,@worker_out.gets)
+ assert_match(/^start/,@worker_out.gets)
assert_match(/^record/,@worker_out.gets)
assert_match(/^p/,@worker_out.gets)
assert_match(/^done/,@worker_out.gets)
@@ -76,15 +79,18 @@ module TestParallel
assert_match(/^ready/,@worker_out.gets)
@worker_in.puts "run #{TESTS}/ptest_first.rb test"
assert_match(/^okay/,@worker_out.gets)
+ assert_match(/^start/,@worker_out.gets)
assert_match(/^record/,@worker_out.gets)
assert_match(/^p/,@worker_out.gets)
assert_match(/^done/,@worker_out.gets)
assert_match(/^ready/,@worker_out.gets)
@worker_in.puts "run #{TESTS}/ptest_second.rb test"
assert_match(/^okay/,@worker_out.gets)
+ assert_match(/^start/,@worker_out.gets)
assert_match(/^record/,@worker_out.gets)
assert_match(/^p/,@worker_out.gets)
assert_match(/^done/,@worker_out.gets)
+ assert_match(/^start/,@worker_out.gets)
assert_match(/^record/,@worker_out.gets)
assert_match(/^p/,@worker_out.gets)
assert_match(/^done/,@worker_out.gets)
@@ -99,7 +105,7 @@ module TestParallel
break if /^p (.+?)$/ =~ buf
end
assert_not_nil($1, "'p' was not found")
- assert_match(/TestA#test_nothing_test = \d+\.\d+ s = \.\n/, $1.chomp.unpack("m")[0])
+ assert_match(/TestA#test_nothing_test = \d+\.\d+ s = \.\n/, $1.chomp.unpack1("m"))
end
end
@@ -111,16 +117,18 @@ module TestParallel
end
assert_not_nil($1, "'done' was not found")
- result = Marshal.load($1.chomp.unpack("m")[0])
+ result = Marshal.load($1.chomp.unpack1("m"))
assert_equal(5, result[0])
- assert_equal(17, result[1])
+ pend "TODO: result[1] returns 17. We should investigate it" do # TODO: misusage of pend (pend doens't use given block)
+ assert_equal(12, result[1])
+ end
assert_kind_of(Array,result[2])
assert_kind_of(Array,result[3])
assert_kind_of(Array,result[4])
assert_kind_of(Array,result[2][1])
- assert_kind_of(MiniTest::Assertion,result[2][0][2])
- assert_kind_of(MiniTest::Skip,result[2][1][2])
- assert_kind_of(MiniTest::Skip,result[2][2][2])
+ assert_kind_of(Test::Unit::AssertionFailedError,result[2][0][2])
+ assert_kind_of(Test::Unit::PendedError,result[2][1][2])
+ assert_kind_of(Test::Unit::PendedError,result[2][2][2])
assert_kind_of(Exception, result[2][3][2])
assert_equal(result[5], "TestE")
end
@@ -135,11 +143,11 @@ module TestParallel
end
class TestParallel < Test::Unit::TestCase
- def spawn_runner(*opt_args)
+ def spawn_runner(*opt_args, jobs: "t1")
@test_out, o = IO.pipe
- @test_pid = spawn(*@options[:ruby], TESTS+"/runner.rb",
- "--ruby", @options[:ruby].join(" "),
- "-j","t1",*opt_args, out: o, err: o)
+ @test_pid = spawn(*@__runner_options__[:ruby], TESTS+"/runner.rb",
+ "--ruby", @__runner_options__[:ruby].join(" "),
+ "-j", jobs, *opt_args, out: o, err: o)
o.close
end
@@ -158,11 +166,7 @@ module TestParallel
end
def test_ignore_jzero
- @test_out, o = IO.pipe
- @test_pid = spawn(*@options[:ruby], TESTS+"/runner.rb",
- "--ruby", @options[:ruby].join(" "),
- "-j","0", out: File::NULL, err: o)
- o.close
+ spawn_runner(jobs: "0")
Timeout.timeout(TIMEOUT) {
assert_match(/Error: parameter of -j option should be greater than 0/,@test_out.read)
}
@@ -200,5 +204,19 @@ module TestParallel
assert(buf.scan(/^\[\s*\d+\/\d+\]\s*(\d+?)=/).flatten.uniq.size > 1,
message("retried tests should run in different processes") {buf})
end
+
+ def test_hungup
+ spawn_runner "--worker-timeout=1", "test4test_hungup.rb"
+ buf = Timeout.timeout(TIMEOUT) {@test_out.read}
+ assert_match(/^Retrying hung up testcases\.+$/, buf)
+ assert_match(/^2 tests,.* 0 failures,/, buf)
+ end
+
+ def test_retry_workers
+ spawn_runner "--worker-timeout=1", "test4test_slow_0.rb", "test4test_slow_1.rb", jobs: "2"
+ buf = Timeout.timeout(TIMEOUT) {@test_out.read}
+ assert_match(/^Retrying hung up testcases\.+$/, buf)
+ assert_match(/^2 tests,.* 0 failures,/, buf)
+ end
end
end
diff --git a/tool/test/testunit/test_redefinition.rb b/tool/test/testunit/test_redefinition.rb
index 9129e55489..b4f5cabd4f 100644
--- a/tool/test/testunit/test_redefinition.rb
+++ b/tool/test/testunit/test_redefinition.rb
@@ -3,14 +3,9 @@ require 'test/unit'
class TestRedefinition < Test::Unit::TestCase
def test_redefinition
- assert_match(/^test\/unit warning: method TestForTestRedefinition#test_redefinition is redefined$/,
- redefinition)
- end
-
- def redefinition(*args)
- IO.popen([*@options[:ruby], "#{File.dirname(__FILE__)}/test4test_redefinition.rb", *args],
- err: [:child, :out]) {|f|
- f.read
- }
+ message = %r[test/unit: method TestForTestRedefinition#test_redefinition is redefined$]
+ assert_raise_with_message(Test::Unit::AssertionFailedError, message) do
+ require_relative("test4test_redefinition.rb")
+ end
end
end
diff --git a/tool/test/testunit/test_sorting.rb b/tool/test/testunit/test_sorting.rb
index f9de3ec154..3e5d7bfdcc 100644
--- a/tool/test/testunit/test_sorting.rb
+++ b/tool/test/testunit/test_sorting.rb
@@ -10,9 +10,66 @@ class TestTestUnitSorting < Test::Unit::TestCase
end
def sorting(*args)
- IO.popen([*@options[:ruby], "#{File.dirname(__FILE__)}/test4test_sorting.rb",
+ IO.popen([*@__runner_options__[:ruby], "#{File.dirname(__FILE__)}/test4test_sorting.rb",
"--verbose", *args], err: [:child, :out]) {|f|
f.read
}
end
+
+ Item = Struct.new(:name)
+ SEED = 0x50975eed
+
+ def make_test_list
+ (1..16).map {"test_%.3x" % rand(0x1000)}.freeze
+ end
+
+ def test_sort_alpha
+ sorter = Test::Unit::Order::Types[:alpha].new(SEED)
+ assert_kind_of(Test::Unit::Order::Types[:sorted], sorter)
+
+ list = make_test_list
+ sorted = list.sort
+ 16.times do
+ assert_equal(sorted, sorter.sort_by_string(list))
+ end
+
+ list = list.map {|s| Item.new(s)}.freeze
+ sorted = list.sort_by(&:name)
+ 16.times do
+ assert_equal(sorted, sorter.sort_by_name(list))
+ end
+ end
+
+ def test_sort_nosort
+ sorter = Test::Unit::Order::Types[:nosort].new(SEED)
+
+ list = make_test_list
+ 16.times do
+ assert_equal(list, sorter.sort_by_string(list))
+ end
+
+ list = list.map {|s| Item.new(s)}.freeze
+ 16.times do
+ assert_equal(list, sorter.sort_by_name(list))
+ end
+ end
+
+ def test_sort_random
+ type = Test::Unit::Order::Types[:random]
+ sorter = type.new(SEED)
+
+ list = make_test_list
+ sorted = type.new(SEED).sort_by_string(list).freeze
+ 16.times do
+ assert_equal(sorted, sorter.sort_by_string(list))
+ end
+ assert_not_equal(sorted, type.new(SEED+1).sort_by_string(list))
+
+ list = list.map {|s| Item.new(s)}.freeze
+ sorted = sorted.map {|s| Item.new(s)}.freeze
+ 16.times do
+ assert_equal(sorted, sorter.sort_by_name(list))
+ end
+ assert_not_equal(sorted, type.new(SEED+1).sort_by_name(list))
+ end
end
diff --git a/tool/test/testunit/test_timeout.rb b/tool/test/testunit/test_timeout.rb
new file mode 100644
index 0000000000..452f5e1a7e
--- /dev/null
+++ b/tool/test/testunit/test_timeout.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: false
+require 'test/unit'
+
+class TestTiemout < Test::Unit::TestCase
+ def test_timeout
+ cmd = [*@__runner_options__[:ruby], "#{File.dirname(__FILE__)}/test4test_timeout.rb"]
+ result = IO.popen(cmd, err: [:child, :out], &:read)
+ assert_not_match(/^T{10}$/, result)
+ end
+end
diff --git a/tool/test/testunit/tests_for_parallel/slow_helper.rb b/tool/test/testunit/tests_for_parallel/slow_helper.rb
new file mode 100644
index 0000000000..38067c1f47
--- /dev/null
+++ b/tool/test/testunit/tests_for_parallel/slow_helper.rb
@@ -0,0 +1,8 @@
+require 'test/unit'
+
+module TestSlowTimeout
+ def test_slow
+ sleep_for = EnvUtil.apply_timeout_scale((ENV['sec'] || 3).to_i)
+ sleep sleep_for if on_parallel_worker?
+ end
+end
diff --git a/tool/test/testunit/tests_for_parallel/test4test_hungup.rb b/tool/test/testunit/tests_for_parallel/test4test_hungup.rb
new file mode 100644
index 0000000000..65a75f7c4d
--- /dev/null
+++ b/tool/test/testunit/tests_for_parallel/test4test_hungup.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+require_relative '../../../lib/test/unit'
+
+class TestHung < Test::Unit::TestCase
+ def test_success_at_worker
+ assert true
+ end
+
+ def test_hungup_at_worker
+ if on_parallel_worker?
+ sleep 10
+ end
+ assert true
+ end
+end
diff --git a/tool/test/testunit/tests_for_parallel/test4test_slow_0.rb b/tool/test/testunit/tests_for_parallel/test4test_slow_0.rb
new file mode 100644
index 0000000000..a749b0e1d3
--- /dev/null
+++ b/tool/test/testunit/tests_for_parallel/test4test_slow_0.rb
@@ -0,0 +1,5 @@
+require_relative 'slow_helper'
+
+class TestSlowV0 < Test::Unit::TestCase
+ include TestSlowTimeout
+end
diff --git a/tool/test/testunit/tests_for_parallel/test4test_slow_1.rb b/tool/test/testunit/tests_for_parallel/test4test_slow_1.rb
new file mode 100644
index 0000000000..924a3b11fa
--- /dev/null
+++ b/tool/test/testunit/tests_for_parallel/test4test_slow_1.rb
@@ -0,0 +1,5 @@
+require_relative 'slow_helper'
+
+class TestSlowV1 < Test::Unit::TestCase
+ include TestSlowTimeout
+end