summaryrefslogtreecommitdiff
path: root/lib/test/unit/parallel.rb
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-11-06 11:57:02 -0800
committerAnas Nashif <anas.nashif@intel.com>2012-11-06 11:57:02 -0800
commit3b35de2a90e26b99e2a6d4f61dc56d6ce7ded748 (patch)
treef66334a0ad8cf59590dd682d95d6244e8b454853 /lib/test/unit/parallel.rb
downloadruby-3b35de2a90e26b99e2a6d4f61dc56d6ce7ded748.tar.gz
ruby-3b35de2a90e26b99e2a6d4f61dc56d6ce7ded748.tar.bz2
ruby-3b35de2a90e26b99e2a6d4f61dc56d6ce7ded748.zip
Imported Upstream version 1.9.3.p194upstream/1.9.3.p194
Diffstat (limited to 'lib/test/unit/parallel.rb')
-rw-r--r--lib/test/unit/parallel.rb157
1 files changed, 157 insertions, 0 deletions
diff --git a/lib/test/unit/parallel.rb b/lib/test/unit/parallel.rb
new file mode 100644
index 0000000..7a7c73d
--- /dev/null
+++ b/lib/test/unit/parallel.rb
@@ -0,0 +1,157 @@
+require 'test/unit'
+
+module Test
+ module Unit
+ class Worker < Runner
+ class << self
+ undef autorun
+ end
+
+ alias orig_run_suite _run_suite
+ undef _run_suite
+ undef _run_suites
+ undef run
+
+ def increment_io(orig)
+ *rest, io = 32.times.inject([orig.dup]){|ios, | ios << ios.last.dup }
+ rest.each(&:close)
+ io
+ end
+
+ def _run_suites(suites, type)
+ suites.map do |suite|
+ _run_suite(suite, type)
+ end
+ end
+
+ def _run_suite(suite, type)
+ r = report.dup
+ 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.read(5))
+ @stdout.puts "p #{[buf].pack("m").gsub("\n","")}"
+ 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"].include? $!.message
+ end
+ i.close
+
+ result << (report - r)
+ result << [@errors-e,@failures-f,@skips-s]
+ result << ($: - @old_loadpath)
+ result << suite.name
+
+ begin
+ @stdout.puts "done #{[Marshal.dump(result)].pack("m").gsub("\n","")}"
+ rescue Errno::EPIPE; end
+ return result
+ ensure
+ MiniTest::Unit.output = orig_stdout
+ $stdin = orig_stdin
+ $stdout = orig_stdout
+ o.close if o && !o.closed?
+ i.close if i && !i.closed?
+ end
+
+ def run(args = [])
+ process_args args
+ @@stop_auto_run = true
+ @opts = @options.dup
+ @need_exit = false
+
+ @old_loadpath = []
+ begin
+ @stdout = increment_io(STDOUT)
+ @stdin = increment_io(STDIN)
+ @stdout.sync = true
+ @stdout.puts "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 (.+?) (.+?)$/
+ @stdout.puts "okay"
+
+ @options = @opts.dup
+ suites = MiniTest::Unit::TestCase.test_suites
+
+ begin
+ require $1
+ rescue LoadError
+ @stdout.puts "after #{[Marshal.dump([$1, $!])].pack("m").gsub("\n","")}"
+ @stdout.puts "ready"
+ next
+ end
+ _run_suites MiniTest::Unit::TestCase.test_suites-suites, $2.to_sym
+
+ if @need_exit
+ begin
+ @stdout.puts "bye"
+ rescue Errno::EPIPE; end
+ exit
+ else
+ @stdout.puts "ready"
+ end
+ when /^quit$/
+ begin
+ @stdout.puts "bye"
+ rescue Errno::EPIPE; end
+ exit
+ end
+ end
+ rescue Errno::EPIPE
+ rescue Exception => e
+ begin
+ @stdout.puts "bye #{[Marshal.dump(e)].pack("m").gsub("\n","")}"
+ rescue Errno::EPIPE;end
+ exit
+ ensure
+ @stdin.close
+ @stdout.close
+ end
+ end
+ end
+ end
+end
+
+if $0 == __FILE__
+ module Test
+ module Unit
+ class TestCase < MiniTest::Unit::TestCase
+ def on_parallel_worker?
+ true
+ end
+ end
+ end
+ end
+
+ Test::Unit::Worker.new.run(ARGV)
+end