#!/usr/bin/env ruby # encoding: UTF-8 require 'tins/xt' require 'tins/lines_file' include Tins::GO require 'utils' include Utils require 'drb/drb' def usage puts <<-EOT Usage: #{File.basename($0)} [OPTS] FILENAME[:LINENO] [FILENAME] Options are -n TESTNAME run the test TESTNAME in file FILENAME -t FRAMEWORK use test framework FRAMEWORK (rspec or test-unit) -h display this help Version is #{File.basename($0)} #{Utils::VERSION}. EOT exit 1 end def cmd(*args) puts args * ' ' system(*args) end def find_cmd(*cmds) cmds.map { |c| `which #{c}`.full?(:chomp) }.compact.first or raise fail "no #{cmds * '|'} command found" end $config = Utils::Config::ConfigFile.new $config.configure_from_paths testrunner_args = [] if i = ARGV.index('--') testrunner_args.concat ARGV[(i + 1)..-1] args = ARGV[0...i] else args = ARGV.dup end $opt = go 'lcp:t:n:h', args $opt['h'] and usage uri = "druby://localhost:#{$opt['p'] || 6623}" if $opt['l'] Thread.abort_on_exception = false class ProbeServer def initialize @jobs = Queue.new Thread.new { loop } end def run(job) @jobs << job end private def run_job(job) fork do exec $0, *job end Process.wait end def loop while job = @jobs.pop run_job job end end end puts "Starting probe server listening to #{uri.inspect}." DRb.start_service(uri, ProbeServer.new) begin DRb.thread.join rescue Interrupt warn " *** Interrupted ***" exit end end args.empty? and fail "require filename or filename:linenumber as arguments" if $opt['c'] puts "Connecting probe server on #{uri.inspect}." DRb.start_service probe_server = DRbObject.new_with_uri(uri) opts = $opt.subhash('n', 't').map { |k, v| v.full? { "-#{k} #{v.inspect}" } }.compact probe_server.run opts + args exit end puts "Running tests in #{args.inspect}" case ($opt['t'] || $config.probe.test_framework).to_sym when :rspec rspec = find_cmd('rspec', 'spec') if linenumber = $opt['n'] cmd 'ruby', '-I', $config.probe.include_dirs_argument, rspec, '-l', linenumber, *(args + testrunner_args) else args = args.map do |a| if Utils::Editor::FILE_LINENUMBER_REGEXP =~ a $~.captures * ':' else a end end cmd 'ruby', '-I', $config.probe.include_dirs_argument, rspec, *(args + testrunner_args) end when :'test-unit' testrb = find_cmd('testrb') if testname = $opt['n'] cmd 'ruby', '-I', $config.probe.include_dirs_argument, '-S', testrb, '-n', testname, *(args + testrunner_args) else for filename in args sl = filename.source_location if sl.linenumber lf = Tins::LinesFile.for_filename(*sl) if testname = lf.match_backward(/def\s+(\S+?)(?:\(|\s*$)/).full?(:first) cmd 'ruby', '-I', $config.probe.include_dirs_argument, testrb, '-n', testname, sl.filename, *testrunner_args else warn "no test found before line #{sl.linenumber}" end else cmd 'ruby', '-I', $config.probe.include_dirs_argument, '-S', testrb, sl.filename, *testrunner_args end end end end