Skip to content

Commit

Permalink
Added integration spec and JRuby support.
Browse files Browse the repository at this point in the history
  • Loading branch information
dblock committed Jan 15, 2013
1 parent f5f9b40 commit f769dd8
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 68 deletions.
9 changes: 8 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
source "http://rubygems.org"

gem "guard", "~> 1.1"
gem "posix-spawn"

platforms :ruby do
gem "posix-spawn"
end

group :development, :test do
gem "rake"
Expand All @@ -13,6 +16,10 @@ group :development, :test do
gem "mocha"
end

group :test do
gem "rack"
end

require "rbconfig"

if RbConfig::CONFIG["target_os"] =~ /darwin/i
Expand Down
5 changes: 4 additions & 1 deletion guard-rack.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Gem::Specification.new do |s|

s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Daniel Doubrovkine"]
s.date = "2012-12-19"
s.date = "2013-01-15"
s.email = "dblock@dblock.org"
s.extra_rdoc_files = [
"LICENSE.md",
Expand All @@ -33,6 +33,7 @@ Gem::Specification.new do |s|

if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<guard>, ["~> 1.1"])
s.add_runtime_dependency(%q<posix-spawn>, [">= 0"]) if RUBY_PLATFORM == 'ruby'
s.add_runtime_dependency(%q<rb-fsevent>, [">= 0.3.9"])
s.add_runtime_dependency(%q<growl>, ["~> 1.0.3"])
s.add_development_dependency(%q<rake>, [">= 0"])
Expand All @@ -44,6 +45,7 @@ Gem::Specification.new do |s|
s.add_development_dependency(%q<mocha>, [">= 0"])
else
s.add_dependency(%q<guard>, ["~> 1.1"])
s.add_dependency(%q<posix-spawn>, [">= 0"]) if RUBY_PLATFORM == 'ruby'
s.add_dependency(%q<rb-fsevent>, [">= 0.3.9"])
s.add_dependency(%q<growl>, ["~> 1.0.3"])
s.add_dependency(%q<rake>, [">= 0"])
Expand All @@ -56,6 +58,7 @@ Gem::Specification.new do |s|
end
else
s.add_dependency(%q<guard>, ["~> 1.1"])
s.add_dependency(%q<posix-spawn>, [">= 0"]) if RUBY_PLATFORM == 'ruby'
s.add_dependency(%q<rb-fsevent>, [">= 0.3.9"])
s.add_dependency(%q<growl>, ["~> 1.0.3"])
s.add_dependency(%q<rake>, [">= 0"])
Expand Down
119 changes: 63 additions & 56 deletions lib/guard/rack/runner.rb
Original file line number Diff line number Diff line change
@@ -1,41 +1,22 @@
require 'fileutils'
require 'timeout'
require 'posix/spawn'

module Guard
class RackRunner

begin
require 'posix/spawn'
include POSIX::Spawn
rescue LoadError => e
# JRuby and possibly others
end

attr_reader :options, :pid

def initialize(options)
@options = options
end

def kill(pid, force = false)
result = -1

UI.debug("Trying to kill Rack (PID #{pid})...")
if !force
Process.kill("INT", pid)
begin
Timeout.timeout(options[:timeout]) do
_, status = Process.wait2(pid)
result = status.exitstatus
UI.debug("Killed Rack (Exit status: #{result})")
end
rescue Timeout::Error
UI.debug("Couldn't kill Rack with INT, switching to TERM")
force = true
end
end

if force
Process.kill("TERM", pid)
end

result
end

def start
kill_unmanaged_pid! if options[:force_run]
@pid = run_rack_command!
Expand All @@ -48,7 +29,7 @@ def stop

exitstatus = kill(@pid)
@pid = nil
if exitstatus != 0
if exitstatus && exitstatus != 0
UI.info "Rackup exited with non-zero exit status (#{exitstatus}) whilst trying to stop."
return false
end
Expand All @@ -60,42 +41,68 @@ def restart
stop and start
end

def build_rack_command
command = %w{rackup}
command.push(
options[:config],
'--env', options[:environment].to_s,
'--port', options[:port].to_s
)
private

command << '--daemonize' if options[:daemon]
command << '--debug' if options[:debugger]
command.push("--server", options[:server].to_s) if options[:server]
def build_rack_command
command = %w{rackup}
command.push(
options[:config],
'--env', options[:environment].to_s,
'--port', options[:port].to_s
)

command
end
command << '--daemonize' if options[:daemon]
command << '--debug' if options[:debugger]
command.push("--server", options[:server].to_s) if options[:server]

private
command
end

def run_rack_command!
command = build_rack_command
UI.debug("Running Rack with command: #{command.inspect}")
POSIX::Spawn.spawn(*command)
end
def kill(pid, force = false)
result = -1

UI.debug("Trying to kill Rack (PID #{pid})...")
if !force
Process.kill("INT", pid)
begin
Timeout.timeout(options[:timeout]) do
_, status = Process.wait2(pid)
result = status.exitstatus
UI.debug("Killed Rack (Exit status: #{result})")
end
rescue Timeout::Error
UI.debug("Couldn't kill Rack with INT, switching to TERM")
force = true
end
end

def kill_unmanaged_pid!
if pid = unmanaged_pid
kill(pid, true)
if force
Process.kill("TERM", pid)
end

result
end

def run_rack_command!
command = build_rack_command
UI.debug("Running Rack with command: #{command.inspect}")
spawn(*command)
end
end

def unmanaged_pid
%x{lsof -n -i TCP:#{options[:port]}}.each_line { |line|
if line["*:#{options[:port]} "]
return line.split("\s")[1].to_i
def kill_unmanaged_pid!
if pid = unmanaged_pid
kill(pid, true)
end
}
nil
end
end

def unmanaged_pid
%x{lsof -n -i TCP:#{options[:port]}}.each_line { |line|
if line["*:#{options[:port]} "]
return line.split("\s")[1].to_i
end
}
nil
end

end
end
11 changes: 11 additions & 0 deletions spec/lib/guard/integration.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class HelloWorld
def call(env)
return [
200,
{'Content-Type' => 'text/html'},
["Hello world!"]
]
end
end

run HelloWorld.new
22 changes: 22 additions & 0 deletions spec/lib/guard/integration_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require 'spec_helper'
require 'guard/rack/runner'

describe "Integration" do
let(:runner) { Guard::RackRunner.new(options) }
let(:options) { { :environment => 'development', :port => 3000, :config => 'spec/lib/guard/integration.ru' } }

describe '#start' do
context 'run' do
it "should run" do
runner.start.should be_true
pid = runner.pid
pid.should_not be_nil
Process.getpgid(pid).should > 0
runner.stop
expect {
Process.getpgid(pid)
}.to raise_error Errno::ESRCH
end
end
end
end
18 changes: 9 additions & 9 deletions spec/lib/guard/runner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
let(:pid) { 1234 }

before do
POSIX::Spawn.stubs(:spawn).returns(pid)
runner.stubs(:spawn).returns(pid)
runner.start
end

Expand All @@ -37,31 +37,31 @@
describe '#build_rack_command' do
context 'no daemon' do
it "should not have a daemon switch" do
runner.build_rack_command.should_not include('--daemonize')
runner.send(:build_rack_command).should_not include('--daemonize')
end
end

context 'daemon' do
let(:options) { default_options.merge(:daemon => true) }

it "should have a daemon switch" do
runner.build_rack_command.should include('--daemonize')
runner.send(:build_rack_command).should include('--daemonize')
end
end

context 'debugger' do
let(:options) { default_options.merge(:debugger => true) }

it "should have a debugger switch" do
runner.build_rack_command.should include('--debug')
runner.send(:build_rack_command).should include('--debug')
end
end

context "server" do
let(:options) { default_options.merge(:server => "thin") }

it "should honour server switch" do
command = runner.build_rack_command
command = runner.send(:build_rack_command)
index = command.index('--server')
index.should be >= 0
command[index + 1].should == 'thin'
Expand All @@ -71,15 +71,15 @@
context "config file" do
context "default" do
it "should default to config.ru" do
runner.build_rack_command.should include('config.ru')
runner.send(:build_rack_command).should include('config.ru')
end
end

context "custom" do
let(:options) { default_options.merge(:config => 'config2.ru') }
it "should honour config option" do
options = default_options.merge(:config => 'config2.ru')
runner.build_rack_command.should include('config2.ru')
runner.send(:build_rack_command).should include('config2.ru')
end
end
end
Expand All @@ -91,7 +91,7 @@
let(:kill_expectation) { Process.expects(:kill).with("TERM", unmanaged_pid) }

before do
POSIX::Spawn.expects(:spawn).once.returns(pid)
runner.expects(:spawn).once.returns(pid)
runner.stubs(:unmanaged_pid).returns(unmanaged_pid)
end

Expand Down Expand Up @@ -127,7 +127,7 @@
let(:wait_stub) { Process.stubs(:wait2) }

before do
POSIX::Spawn.stubs(:spawn).returns(pid)
runner.stubs(:spawn).returns(pid)
runner.start

Process.expects(:kill).with('INT', pid)
Expand Down
2 changes: 1 addition & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
$LOAD_PATH.unshift(File.dirname(__FILE__))

require 'guard-rack'
require 'mocha'
require 'mocha_standalone'

RSpec.configure do |c|
c.mock_with :mocha
Expand Down

0 comments on commit f769dd8

Please sign in to comment.