1require 'test/unit' 2require 'timeout' 3 4module TestParallel 5 PARALLEL_RB = "#{File.dirname(__FILE__)}/../../lib/test/unit/parallel.rb" 6 TESTS = "#{File.dirname(__FILE__)}/tests_for_parallel" 7 8 9 class TestParallelWorker < Test::Unit::TestCase 10 def setup 11 i, @worker_in = IO.pipe 12 @worker_out, o = IO.pipe 13 @worker_pid = spawn(*@options[:ruby], PARALLEL_RB, 14 "--ruby", @options[:ruby].join(" "), 15 "-j", "t1", "-v", out: o, in: i) 16 [i,o].each(&:close) 17 end 18 19 def teardown 20 if @worker_pid && @worker_in 21 begin 22 begin 23 @worker_in.puts "quit" 24 rescue IOError, Errno::EPIPE 25 end 26 timeout(2) do 27 Process.waitpid(@worker_pid) 28 end 29 rescue Timeout::Error 30 begin 31 Process.kill(:KILL, @worker_pid) 32 rescue Errno::ESRCH 33 end 34 end 35 end 36 end 37 38 def test_run 39 timeout(10) do 40 assert_match(/^ready/,@worker_out.gets) 41 @worker_in.puts "run #{TESTS}/ptest_first.rb test" 42 assert_match(/^okay/,@worker_out.gets) 43 assert_match(/^p/,@worker_out.gets) 44 assert_match(/^done/,@worker_out.gets) 45 assert_match(/^ready/,@worker_out.gets) 46 end 47 end 48 49 def test_run_multiple_testcase_in_one_file 50 timeout(10) do 51 assert_match(/^ready/,@worker_out.gets) 52 @worker_in.puts "run #{TESTS}/ptest_second.rb test" 53 assert_match(/^okay/,@worker_out.gets) 54 assert_match(/^p/,@worker_out.gets) 55 assert_match(/^done/,@worker_out.gets) 56 assert_match(/^p/,@worker_out.gets) 57 assert_match(/^done/,@worker_out.gets) 58 assert_match(/^ready/,@worker_out.gets) 59 end 60 end 61 62 def test_accept_run_command_multiple_times 63 timeout(10) do 64 assert_match(/^ready/,@worker_out.gets) 65 @worker_in.puts "run #{TESTS}/ptest_first.rb test" 66 assert_match(/^okay/,@worker_out.gets) 67 assert_match(/^p/,@worker_out.gets) 68 assert_match(/^done/,@worker_out.gets) 69 assert_match(/^ready/,@worker_out.gets) 70 @worker_in.puts "run #{TESTS}/ptest_second.rb test" 71 assert_match(/^okay/,@worker_out.gets) 72 assert_match(/^p/,@worker_out.gets) 73 assert_match(/^done/,@worker_out.gets) 74 assert_match(/^p/,@worker_out.gets) 75 assert_match(/^done/,@worker_out.gets) 76 assert_match(/^ready/,@worker_out.gets) 77 end 78 end 79 80 def test_p 81 timeout(10) do 82 @worker_in.puts "run #{TESTS}/ptest_first.rb test" 83 while buf = @worker_out.gets 84 break if /^p (.+?)$/ =~ buf 85 end 86 assert_match(/TestA#test_nothing_test = \d+\.\d+ s = \.\n/, $1.chomp.unpack("m")[0]) 87 end 88 end 89 90 def test_done 91 timeout(10) do 92 @worker_in.puts "run #{TESTS}/ptest_forth.rb test" 93 i = 0 94 6.times { @worker_out.gets } 95 buf = @worker_out.gets 96 assert_match(/^done (.+?)$/, buf) 97 98 /^done (.+?)$/ =~ buf 99 100 result = Marshal.load($1.chomp.unpack("m")[0]) 101 102 assert_equal(4, result[0]) 103 assert_equal(2, result[1]) 104 assert_kind_of(Array,result[2]) 105 assert_kind_of(Array,result[3]) 106 assert_kind_of(Array,result[4]) 107 assert_kind_of(Array,result[2][1]) 108 assert_kind_of(MiniTest::Assertion,result[2][0][2]) 109 assert_kind_of(MiniTest::Skip,result[2][1][2]) 110 assert_kind_of(Exception, result[2][2][2]) 111 assert_equal(result[5], "TestE") 112 end 113 end 114 115 def test_quit 116 timeout(10) do 117 @worker_in.puts "quit" 118 assert_match(/^bye$/m,@worker_out.read) 119 end 120 end 121 end 122 123 class TestParallel < Test::Unit::TestCase 124 def spawn_runner(*opt_args) 125 @test_out, o = IO.pipe 126 @test_pid = spawn(*@options[:ruby], TESTS+"/runner.rb", 127 "--ruby", @options[:ruby].join(" "), 128 "-j","t1",*opt_args, out: o, err: o) 129 o.close 130 end 131 132 def teardown 133 begin 134 if @test_pid 135 timeout(2) do 136 Process.waitpid(@test_pid) 137 end 138 end 139 rescue Timeout::Error 140 Process.kill(:KILL, @test_pid) if @test_pid 141 ensure 142 @test_out.close if @test_out 143 end 144 end 145 146 def test_ignore_jzero 147 @test_out, o = IO.pipe 148 @test_pid = spawn(*@options[:ruby], TESTS+"/runner.rb", 149 "--ruby", @options[:ruby].join(" "), 150 "-j","0", out: File::NULL, err: o) 151 o.close 152 timeout(10) { 153 assert_match(/Error: parameter of -j option should be greater than 0/,@test_out.read) 154 } 155 end 156 157 def test_should_run_all_without_any_leaks 158 spawn_runner 159 buf = timeout(10){@test_out.read} 160 assert_match(/^[SFE\.]{8}$/,buf) 161 end 162 163 def test_should_retry_failed_on_workers 164 spawn_runner 165 buf = timeout(10){@test_out.read} 166 assert_match(/^Retrying\.+$/,buf) 167 end 168 169 def test_no_retry_option 170 spawn_runner "--no-retry" 171 buf = timeout(10){@test_out.read} 172 refute_match(/^Retrying\.+$/,buf) 173 assert_match(/^ +\d+\) Failure:\ntest_fail_at_worker\(TestD\)/,buf) 174 end 175 176 def test_jobs_status 177 spawn_runner "--jobs-status" 178 buf = timeout(10){@test_out.read} 179 assert_match(/\d+=ptest_(first|second|third|forth) */,buf) 180 end 181 182 def test_separate 183 # this test depends to --jobs-status 184 spawn_runner "--jobs-status", "--separate" 185 buf = timeout(10){@test_out.read} 186 assert(buf.scan(/(\d+?)[:=]/).flatten.uniq.size > 1) 187 end 188 end 189end 190