add a simple runner for autospec

This commit is contained in:
Sam 2013-10-24 10:06:05 +11:00
parent 666264879c
commit 1357f16563
4 changed files with 176 additions and 91 deletions

View File

@ -0,0 +1,22 @@
module Autospec
class BaseRunner
def run(args, specs)
end
def abort
end
def reload
end
def running?
true
end
def start
end
def stop
end
end
end

View File

@ -2,6 +2,9 @@ require "drb/drb"
require "thread"
require "fileutils"
require "autospec/reload_css"
require "autospec/base_runner"
require "autospec/simple_runner"
require "autospec/spork_runner"
module Autospec; end
@ -48,19 +51,19 @@ class Autospec::Runner
end
def run(opts = {})
if already_running?(pid_file)
puts "autospec appears to be running, it is possible the pid file is old"
puts "if you are sure it is not running, delete #{pid_file}"
return
end
write_pid_file(pid_file, Process.pid)
start_spork
Signal.trap("HUP") {stop_spork; exit }
Signal.trap("SIGINT") {stop_spork; exit }
puts "Forced polling (slower) - inotify does not work on network filesystems, use local filesystem to avoid" if opts[:force_polling]
if ENV["SPORK"] == 0
@runner = Autospec::SimpleRunner.new
else
@runner = Autospec::SporkRunner.new
end
@runner.start
Signal.trap("HUP") {@runner.stop; exit }
Signal.trap("SIGINT") {@runner.stop; exit }
options = {filter: /^app|^spec|^lib/, relative_paths: true}
if opts[:force_polling]
@ -79,22 +82,14 @@ class Autospec::Runner
@signal.signal
end
spork_running = true
Thread.new do
Process.wait(@spork_pid)
spork_running = false
end
while spork_running
while @runner.running?
process_queue
end
puts "Spork has been terminated, exiting"
rescue => e
puts e
puts e.backtrace
stop_spork
@runner.stop
end
def process_queue
@ -168,15 +163,13 @@ class Autospec::Runner
def process_change(files)
return unless files.length > 0
specs = []
hit = false
files.each do |file|
RELOAD_MATCHERS.each do |k|
if k.match(file)
spork_service.abort
stop_spork
sleep 1
start_spork
@runner.reload
return
end
end
@ -213,7 +206,7 @@ class Autospec::Runner
end
return
else
spork_service.abort
@runner.abort
end
@mutex.synchronize do
@ -305,72 +298,9 @@ class Autospec::Runner
"-r", "#{File.dirname(__FILE__)}/formatter.rb",
"-f", "Autospec::Formatter"].flatten
spork_service.run(args,$stderr,$stdout)
end
def spork_pid_file
Rails.root + "tmp/pids/spork.pid"
end
def pid_file
Rails.root + "tmp/pids/autospec.pid"
end
def already_running?(pid_file)
if File.exists? pid_file
pid = File.read(pid_file).to_i
Process.getpgid(pid) rescue nil
end
end
def write_pid_file(file,pid)
FileUtils.mkdir_p(Rails.root + "tmp/pids")
File.open(file,'w') do |f|
f.write(pid)
end
end
def spork_running?
spork_service.port rescue nil
end
def spork_service
unless @drb_listener_running
begin
DRb.start_service("druby://127.0.0.1:0")
rescue SocketError, Errno::EADDRNOTAVAIL
DRb.start_service("druby://:0")
end
@drb_listener_running = true
end
@spork_service ||= DRbObject.new_with_uri("druby://127.0.0.1:8989")
end
def stop_spork
pid = File.read(spork_pid_file).to_i
Process.kill("SIGTERM",pid)
end
def start_spork
if already_running?(spork_pid_file)
puts "Killing old orphan spork instance"
stop_spork
sleep 1
end
@spork_pid = Process.spawn({'RAILS_ENV' => 'test'}, "bundle exec spork")
write_pid_file(spork_pid_file, @spork_pid)
running = false
while !running
running = spork_running?
sleep 0.1
end
@runner.run(args, specs)
end
end

View File

@ -0,0 +1,26 @@
module Autospec
class SimpleRunner < BaseRunner
def abort
if @pid
Process.kill("SIGINT", @pid) rescue nil
while(Process.getpgid(@pid) rescue nil)
sleep 0.001
end
@pid = nil
end
end
def run(args, spec)
self.abort
puts "Running: " << spec
@pid = Process.spawn({"RAILS_ENV" => "test"}, "bundle exec rspec " << args.join(" "))
pid, status = Process.wait2(@pid)
status
end
def stop
self.abort
end
end
end

View File

@ -0,0 +1,107 @@
module Autospec
class SporkRunner < BaseRunner
def start
if already_running?(pid_file)
puts "autospec appears to be running, it is possible the pid file is old"
puts "if you are sure it is not running, delete #{pid_file}"
return
end
write_pid_file(pid_file, Process.pid)
start_spork
@spork_running = true
end
def running?
@monitor_thread ||=
Thread.new do
Process.wait(@spork_pid)
@spork_running = false
end
@spork_running
end
def stop
stop_spork
end
def run(args,specs)
spork_service.run(args,$stderr,$stdout)
end
def abort
spork_service.abort
end
def reload
stop_spork
sleep 1
start_spork
end
private
def spork_pid_file
Rails.root + "tmp/pids/spork.pid"
end
def pid_file
Rails.root + "tmp/pids/autospec.pid"
end
def already_running?(pid_file)
if File.exists? pid_file
pid = File.read(pid_file).to_i
Process.getpgid(pid) rescue nil
end
end
def write_pid_file(file,pid)
FileUtils.mkdir_p(Rails.root + "tmp/pids")
File.open(file,'w') do |f|
f.write(pid)
end
end
def spork_running?
spork_service.port rescue nil
end
def spork_service
unless @drb_listener_running
begin
DRb.start_service("druby://127.0.0.1:0")
rescue SocketError, Errno::EADDRNOTAVAIL
DRb.start_service("druby://:0")
end
@drb_listener_running = true
end
@spork_service ||= DRbObject.new_with_uri("druby://127.0.0.1:8989")
end
def stop_spork
pid = File.read(spork_pid_file).to_i
Process.kill("SIGTERM",pid)
end
def start_spork
if already_running?(spork_pid_file)
puts "Killing old orphan spork instance"
stop_spork
sleep 1
end
@spork_pid = Process.spawn({'RAILS_ENV' => 'test'}, "bundle exec spork")
write_pid_file(spork_pid_file, @spork_pid)
running = false
while !running
running = spork_running?
sleep 0.01
end
end
end
end