In Files

  • test/unit/parallel.rb

Test::Unit::Worker

Public Instance Methods

_report(res, *args) click to toggle source
 
               # File test/unit/parallel.rb, line 152
def _report(res, *args)
  res = "#{res} #{args.pack("m0")}" unless args.empty?
  @stdout.puts(res)
end
            
_run_suite(suite, type) click to toggle source
 
               # File test/unit/parallel.rb, line 27
def _run_suite(suite, type)
  @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.read(5))
        _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"].include? $!.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
  $stdout = orig_stdout
  o.close if o && !o.closed?
  i.close if i && !i.closed?
end
            
_run_suites(suites, type) click to toggle source
 
               # File test/unit/parallel.rb, line 21
def _run_suites(suites, type)
  suites.map do |suite|
    _run_suite(suite, type)
  end
end
            
increment_io(orig) click to toggle source
 
               # File test/unit/parallel.rb, line 15
def increment_io(orig)
  *rest, io = 32.times.inject([orig.dup]){|ios, | ios << ios.last.dup }
  rest.each(&:close)
  io
end
            
puke(klass, meth, e) click to toggle source
 
               # File test/unit/parallel.rb, line 157
def puke(klass, meth, e)
  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
            
run(args = []) click to toggle source
 
               # File test/unit/parallel.rb, line 84
def run(args = [])
  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 $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
      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