#!/usr/bin/env ruby # encoding: UTF-8 require 'tins/xt' require 'tins/lines_file' include Tins::GO require 'utils' include Utils require '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, test-unit or cucumber) -c start probe as a client -l start probe as a server -p PORT listen on/connect to local port PORT -h display this help Version is #{File.basename($0)} #{Utils::VERSION}. EOT exit 1 end def cmd(*args) puts args * ' ' system(*args) or exit $?.exitstatus end def find_cmd(*cmds) cmds.map { |c| `which #{c}`.full?(:chomp) }.compact.first or raise fail "no #{cmds * '|'} command found" end def zeus? !`which zeus`.empty? && test(?S, '.zeus.sock') end singleton_class.class_eval do memoize_function :zeus? end def start_server Thread.abort_on_exception = $DEBUG zeus? and puts "Found a zeus socket file, I'll try to use it for running tests." begin DRb.start_service DRbObject.new_with_uri($uri).shutdown rescue DRb::DRbConnError end Utils::ProbeServer.new($uri).start end def connect_server Utils::ProbeServer::Job.colorize = true puts "Connecting probe server on #{$uri.inspect}." DRb.start_service probe_server = DRbObject.new_with_uri($uri) if $opt['c'] opts = $opt.subhash('n', 't').each_with_object([]) { |(k, v), a| v.full? and a.concat [ "-#{k}", v ] } probe_server.enqueue opts + $args exit end 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}" case when $opt['l'] start_server exit when $opt['c'] connect_server end $args.empty? and fail "require filename or filename:linenumber as arguments" puts "Running tests in #{$args.inspect}" case ($opt['t'] || $config.probe.test_framework).to_sym when :rspec if zeus? rspec = %w[-S zeus rspec -f Utils::LineFormatter ] else rspec = [ find_cmd('rspec', 'spec') ] << '-f' << 'Utils::LineFormatter' end 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' if zeus? testrb = %w[-S zeus testrb] else testrb = find_cmd('testrb') end if testname = $opt['n'] cmd 'ruby', '-I', $config.probe.include_dirs_argument, *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, *testrb, sl.filename, *testrunner_args end end end when :cucumber cucumber = find_cmd('cucumber') if linenumber = $opt['n'] cmd 'ruby', cucumber, '-r', $config.probe.include_dirs_argument, '-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', cucumber, '-r', $config.probe.include_dirs_argument, *($args + testrunner_args) end end