diff --git a/ChangeLog b/ChangeLog index eeee758766..c248989485 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Wed Feb 23 23:07:38 2011 Shota Fukumori (sora_h) + + * test/testunit/test_parallel.rb, test/testunit/parallel/*: + Test for r30939. + * lib/test/unit.rb: For test. + * lib/test/parallel.rb: For test. + * lib/test/unit/testcase.rb: For test. + + Wed Feb 23 22:05:13 2011 Tanaka Akira * ext/openssl/ossl_engine.c: parenthesize macro arguments. diff --git a/lib/test/unit.rb b/lib/test/unit.rb index 1272153c7b..6c4cecc442 100644 --- a/lib/test/unit.rb +++ b/lib/test/unit.rb @@ -87,7 +87,12 @@ module Test end opts.on '-j N', '--jobs N', "Allow run tests with N jobs at once" do |a| - options[:parallel] = a.to_i + if /^t/ =~ a + options[:testing] = true # For testing + options[:parallel] = a[1..-1].to_i + else + options[:parallel] = a.to_i + end end opts.on '--no-retry', "Don't retry running testcase when --jobs specified" do diff --git a/lib/test/unit/parallel.rb b/lib/test/unit/parallel.rb index acfdc84bb4..ae1bf2961c 100644 --- a/lib/test/unit/parallel.rb +++ b/lib/test/unit/parallel.rb @@ -10,6 +10,7 @@ module Test alias orig_run_suite _run_suite undef _run_suite undef _run_suites + undef run def _run_suites suites, type suites.map do |suite| @@ -42,13 +43,12 @@ module Test MiniTest::Unit.output = orig_stdout o.close - i.close - begin th.join rescue IOError raise unless ["stream closed","closed stream"].include? $!.message end + i.close result << (report - r) result << [@errors-e,@failures-f,@skips-s] diff --git a/test/testunit/test_parallel.rb b/test/testunit/test_parallel.rb new file mode 100644 index 0000000000..2f2b2520db --- /dev/null +++ b/test/testunit/test_parallel.rb @@ -0,0 +1,177 @@ +require 'test/unit' +require 'timeout' + +module TestParallel + PARALLEL_RB = "#{File.dirname(__FILE__)}/../../lib/test/unit/parallel.rb" + TESTS = "#{File.dirname(__FILE__)}/tests_for_parallel" + + + class TestParallelWorker < Test::Unit::TestCase + def setup + i, @worker_in = IO.pipe + @worker_out, o = IO.pipe + @worker_pid = spawn(*@options[:ruby].split(/ /), PARALLEL_RB, + "-j", "t1", "-v", out: o, in: i) + [i,o].each(&:close) + end + + def teardown + begin + @worker_in.puts "quit" + timeout(2) do + Process.waitpid(@worker_pid) + end + rescue IOError, Errno::EPIPE, Timeout::Error + Process.kill(:KILL, @worker_pid) + end + end + + def test_run + timeout(10) do + assert_match(/^ready/,@worker_out.gets) + @worker_in.puts "run #{TESTS}/test_first.rb ptest" + assert_match(/^okay/,@worker_out.gets) + assert_match(/^p/,@worker_out.gets) + assert_match(/^done/,@worker_out.gets) + assert_match(/^done/,@worker_out.gets) + assert_match(/^ready/,@worker_out.gets) + end + end + + def test_run_multiple_testcase_in_one_file + timeout(10) do + assert_match(/^ready/,@worker_out.gets) + @worker_in.puts "run #{TESTS}/test_second.rb ptest" + assert_match(/^okay/,@worker_out.gets) + assert_match(/^p/,@worker_out.gets) + assert_match(/^done/,@worker_out.gets) + assert_match(/^p/,@worker_out.gets) + assert_match(/^done/,@worker_out.gets) + assert_match(/^done/,@worker_out.gets) + assert_match(/^ready/,@worker_out.gets) + end + end + + def test_accept_run_command_multiple_times + timeout(10) do + assert_match(/^ready/,@worker_out.gets) + @worker_in.puts "run #{TESTS}/test_first.rb ptest" + assert_match(/^okay/,@worker_out.gets) + assert_match(/^p/,@worker_out.gets) + assert_match(/^done/,@worker_out.gets) + assert_match(/^done/,@worker_out.gets) + assert_match(/^ready/,@worker_out.gets) + @worker_in.puts "run #{TESTS}/test_second.rb ptest" + assert_match(/^okay/,@worker_out.gets) + assert_match(/^p/,@worker_out.gets) + assert_match(/^done/,@worker_out.gets) + assert_match(/^p/,@worker_out.gets) + assert_match(/^done/,@worker_out.gets) + assert_match(/^ready/,@worker_out.gets) + end + end + + def test_p + timeout(10) do + @worker_in.puts "run #{TESTS}/test_first.rb ptest" + while buf = @worker_out.gets + break if /^p (.+?)$/ =~ buf + end + assert_match(/TestA#ptest_nothing_test = \d+\.\d+ s = \.\n/, $1.chomp.unpack("m")[0]) + end + end + + def test_done + timeout(10) do + @worker_in.puts "run #{TESTS}/test_forth.rb ptest" + i = 0 + while buf = @worker_out.gets + if /^done (.+?)$/ =~ buf + i += 1 + break if i == 2 # Break at 2nd "done" + end + end + + result = Marshal.load($1.chomp.unpack("m")[0]) + + assert_equal(result[0],3) + assert_equal(result[1],2) + assert_kind_of(Array,result[2]) + assert_kind_of(Array,result[3]) + assert_kind_of(Array,result[4]) + assert_match(/Skipped:$/,result[2][0]) + assert_match(/Failure:$/,result[2][1]) + assert_equal(result[5], "TestE") + end + end + + def test_quit + timeout(10) do + @worker_in.puts "quit" + assert_match(/^bye$/m,@worker_out.read) + end + end + + def test_quit_in_test + timeout(10) do + @worker_in.puts "run #{TESTS}/test_third.rb ptest" + @worker_in.puts "quit" + assert_match(/^ready\nokay\nbye/m,@worker_out.read) + end + end + end + + class TestParallel < Test::Unit::TestCase + def spawn_runner(*opt_args) + @test_out, o = IO.pipe + @test_pid = spawn(*@options[:ruby].split(/ /), TESTS+"/runner.rb", + "-j","t2","-x","sleeping",*opt_args, out: o) + o.close + end + + def teardown + begin + if @test_pid + timeout(2) do + Process.waitpid(@test_pid) + end + end + rescue Timeout::Error + Process.kill(:KILL, @test_pid) if @test_pid + ensure + @test_out.close if @test_out + end + end + + #def test_childs + #end + + def test_should_run_all_without_any_leaks + spawn_runner + buf = timeout(10){@test_out.read} + assert_match(/^\.+SF\.+F\.*$/,buf) + end + + def test_should_retry_failed_on_workers + spawn_runner + buf = timeout(10){@test_out.read} + assert_match(/^Retrying\.+$/,buf) + assert_match(/^\.*SF\.*$/,buf) + end + + def test_no_retry_option + spawn_runner "--no-retry" + buf = timeout(10){@test_out.read} + refute_match(/^Retrying\.+$/,buf) + assert_match(/^ +\d+\) Failure:\nptest_fail_at_worker\(TestD\)/,buf) + end + + def test_jobs_status + spawn_runner "--jobs-status" + buf = timeout(10){@test_out.read} + assert_match(/\d+:(ready|prepare|running) */,buf) + assert_match(/test_(first|second|third|forth) */,buf) + end + + end +end diff --git a/test/testunit/tests_for_parallel/misc.rb b/test/testunit/tests_for_parallel/misc.rb new file mode 100644 index 0000000000..c0fa31d798 --- /dev/null +++ b/test/testunit/tests_for_parallel/misc.rb @@ -0,0 +1,31 @@ +module Test + module Unit + class Worker + def run_tests + _run_anything :ptest + end + end + class Runner + def run_tests + _run_anything :ptest + end + end + end +end +module MiniTest + class Unit + class << TestCase + alias ptest_suites test_suites + def ptest_methods;[];end + end + end +end + +class TestCaseForParallelTest < Test::Unit::TestCase + class << self + undef ptest_methods + def ptest_methods + public_instance_methods(true).grep(/^ptest/).map { |m| m.to_s } + end + end +end diff --git a/test/testunit/tests_for_parallel/runner.rb b/test/testunit/tests_for_parallel/runner.rb new file mode 100644 index 0000000000..88413effc5 --- /dev/null +++ b/test/testunit/tests_for_parallel/runner.rb @@ -0,0 +1,7 @@ +require 'rbconfig' +require 'test/unit' +require_relative 'misc' + +src_testdir = File.dirname(File.expand_path(__FILE__)) + +exit Test::Unit::AutoRunner.run(true, src_testdir) diff --git a/test/testunit/tests_for_parallel/test_first.rb b/test/testunit/tests_for_parallel/test_first.rb new file mode 100644 index 0000000000..93fcd67e8e --- /dev/null +++ b/test/testunit/tests_for_parallel/test_first.rb @@ -0,0 +1,8 @@ +require 'test/unit' +require_relative "misc.rb" + +class TestA < TestCaseForParallelTest + def ptest_nothing_test + end +end + diff --git a/test/testunit/tests_for_parallel/test_forth.rb b/test/testunit/tests_for_parallel/test_forth.rb new file mode 100644 index 0000000000..fb8bfe067f --- /dev/null +++ b/test/testunit/tests_for_parallel/test_forth.rb @@ -0,0 +1,17 @@ +require 'test/unit' +require_relative "misc.rb" + +class TestE < TestCaseForParallelTest + def ptest_not_fail + assert_equal(1,1) + end + + def ptest_always_skip + skip + end + + def ptest_always_fail + assert_equal(0,1) + end +end + diff --git a/test/testunit/tests_for_parallel/test_second.rb b/test/testunit/tests_for_parallel/test_second.rb new file mode 100644 index 0000000000..fbc24a8793 --- /dev/null +++ b/test/testunit/tests_for_parallel/test_second.rb @@ -0,0 +1,12 @@ +require 'test/unit' +require_relative "misc.rb" + +class TestB < TestCaseForParallelTest + def ptest_nothing + end +end + +class TestC < TestCaseForParallelTest + def ptest_nothing + end +end diff --git a/test/testunit/tests_for_parallel/test_third.rb b/test/testunit/tests_for_parallel/test_third.rb new file mode 100644 index 0000000000..6393130933 --- /dev/null +++ b/test/testunit/tests_for_parallel/test_third.rb @@ -0,0 +1,14 @@ +require 'test/unit' +require_relative "misc.rb" + +class TestD < TestCaseForParallelTest + def ptest_sleeping + sleep 2 + end + + def ptest_fail_at_worker + if MiniTest::Unit.output != STDOUT + assert_equal(0,1) + end + end +end