Skip to content

Commit

Permalink
remote_job_runner became job_runner. Moved all job running behaviour …
Browse files Browse the repository at this point in the history
…into job. Hooks are run before jobs

git-svn-id: http://rspec-ext.rubyforge.org/svn/distributed/branches/multi_transport@37 b9fc4567-813f-4f01-94b2-355dee807878
  • Loading branch information
bcotton committed Feb 5, 2008
1 parent e27849f commit 228ecca
Show file tree
Hide file tree
Showing 24 changed files with 474 additions and 421 deletions.
6 changes: 3 additions & 3 deletions Manifest.txt
Expand Up @@ -3,7 +3,7 @@ License.txt
Manifest.txt
README.txt
Rakefile
bin/remote_job_runner
bin/job_runner
examples/slooow_examples.rb
lib/spec/distributed.rb
lib/spec/distributed/example_group_value_holder.rb
Expand All @@ -12,11 +12,11 @@ lib/spec/distributed/hooks.rb
lib/spec/distributed/hooks/spec_path_hook.rb
lib/spec/distributed/hooks/svn_update_hooks.rb
lib/spec/distributed/job.rb
lib/spec/distributed/job_runner.rb
lib/spec/distributed/job_runner_option_parser.rb
lib/spec/distributed/marshaled_delegate.rb
lib/spec/distributed/master_example_group_runner.rb
lib/spec/distributed/recording_reporter.rb
lib/spec/distributed/remote_job_runner.rb
lib/spec/distributed/remote_job_runner_option_parser.rb
lib/spec/distributed/slave_example_group_runner.rb
lib/spec/distributed/transport_manager.rb
Expand All @@ -33,11 +33,11 @@ spec/spec/distributed/example_group_value_holder_spec.rb
spec/spec/distributed/example_value_holder_spec.rb
spec/spec/distributed/hooks_spec.rb
spec/spec/distributed/job_runner_option_parser_spec.rb
spec/spec/distributed/job_runner_spec.rb
spec/spec/distributed/job_spec.rb
spec/spec/distributed/marshaled_delegate_spec.rb
spec/spec/distributed/master_example_group_runner_spec.rb
spec/spec/distributed/recording_formatter_spec.rb
spec/spec/distributed/remote_job_runner_spec.rb
spec/spec/distributed/slave_example_group_runner_spec.rb
spec/spec/distributed/transport_manager_spec.rb
spec/spec/distributed/transports/rinda/rinda_connection_spec.rb
Expand Down
2 changes: 1 addition & 1 deletion bin/remote_job_runner → bin/job_runner
Expand Up @@ -3,5 +3,5 @@ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))

require 'spec/distributed'
options = ::Spec::Distributed::JobRunnerOptionParser.parse(ARGV, STDERR, STDOUT)
exit ::Spec::Distributed::RemoteJobRunner.new(options).run
exit ::Spec::Distributed::JobRunner.new(options).run

2 changes: 1 addition & 1 deletion lib/spec/distributed.rb
Expand Up @@ -29,7 +29,7 @@ def describe_with_nested_example_group_spec_path(*args, &example_group_block)
require 'spec/distributed/recording_reporter'
require 'spec/distributed/job_runner_option_parser'
require 'spec/distributed/remote_job_runner_option_parser'
require 'spec/distributed/remote_job_runner'
require 'spec/distributed/job_runner'
require 'spec/distributed/job'
require 'spec/distributed/transport_manager'
require 'spec/distributed/transports'
Expand Down
6 changes: 4 additions & 2 deletions lib/spec/distributed/example_group_value_holder.rb
Expand Up @@ -2,13 +2,15 @@ module Spec
module Distributed
class ExampleGroupValueHolder
def initialize(example_group)
@object_id = example_group.description_options[:remote_example_group_object_id]
@object_id = example_group.description_options[:example_group_object_id]
end

def value
rspec_options.example_groups.find do |eg|
value = rspec_options.example_groups.find do |eg|
eg.object_id == @object_id
end
debugger if value.nil?
value
end
end
end
Expand Down
13 changes: 12 additions & 1 deletion lib/spec/distributed/hooks/svn_update_hooks.rb
Expand Up @@ -12,11 +12,15 @@ def update_wc(svn_rev, patch)
end

def apply_changeset(diff)
puts diff
IO.popen("patch -p0", "w+") do |patch|
patch.puts diff
patch.close_write
patch.readlines
end
File.open("last_patch.txt", "w") do |f|
f << diff
end
end

def local_diff
Expand All @@ -33,6 +37,13 @@ def local_revision
end

def revert
if File.exists?('last_patch.txt')
`egrep '^Index:' last_patch.txt`.split(/\n/).each do |line|
file = line.match(/\AIndex: (.*)/)[1]
FileUtils.rm_rf file.strip
end
FileUtils.rm 'last_patch.txt'
end
`svn revert -R .`
end

Expand Down Expand Up @@ -62,7 +73,7 @@ module MasterHooks
# make sure your new files are 'svn add'ed
module DetectSvnRev
Spec::Distributed::Hooks.add_master_hook do |job|
job.add_library 'spec/distributed/hooks/svn_update_hooks'
job.add_hook_library 'spec/distributed/hooks/svn_update_hooks'

svn = UpdateSvn.new
job.master_svn_rev = svn.local_revision
Expand Down
111 changes: 72 additions & 39 deletions lib/spec/distributed/job.rb
@@ -1,16 +1,11 @@
require 'tempfile'
require 'systemu'

module Spec
module Distributed

# Stuff we're going to want:
# - in process or out
# - path to spec file
# - Load path
# - CWD
# - enviroment variables
# - return path
# - DRb location of formatters IO?

# OpenStruct is a bug waiting to happen...
# btw, don't add instance variables, OpenStruct has it's own
# marshal_dump etc
class Job < OpenStruct
class << self
def create_job(example_group, options, return_path)
Expand All @@ -29,6 +24,7 @@ def strip_line_number(spec_path)
spec_path.gsub(/:\d+.*\Z/, "")
end

# push this into File
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/20586
def rel_path(a, b)
# Should work in in win and *nix
Expand Down Expand Up @@ -56,49 +52,86 @@ def rel_path(a, b)
parent = ".." + sep
(parent * a.size) + b.join(sep)
end

# path transformation
# The master may want to set a path transformation in a few scenarios:
# A. The master wants the slave to load the spec from the master's
# directory, most likely over network. The master will
# specify a transformation resulting in:
# /absolute/path/to/where/the/specs/are ->
# /network/path/to/where/the/specs/are
# This is a substitution of s/absolute/network/ where the
# rest of the path remains the same. e.g. If a user's home
# directory were exported over NFS, then the master would transform
# the spec_path from /Users/john/project/spec ->
# /net/johns_machine/Users/john/project/spec
#
# B. The master wants the slave to load libraries relative to
# some known CWD, therefore wants the slave to run in a
# specific CWD.
# B1. The master wants the slave to run in a known CWD.
# B1.1 This may be the CWD the remote_runner was started in (because
# those starting the master/slave know this)
# B1.2 or some other CWD that the master suggests (e.g. run in
# branch dir vs. the trunk)
#
# B2. The master wants the slave to run in a CWD that is on
# the masters machine, thus the path would be would be
# similar to A.
#
# How to deal with win/unix path transformations?
end

def initialize(args={})
super
self.libraries ||= []
self.hook_libraries ||= []
self.environment ||= {}

add_library("spec/distributed")
end

def add_library(library_path)
self.libraries << library_path
end

def add_hook_library(library_path)
self.hook_libraries << library_path
end

def add_environment(key, value)
environment[key] = value
end

def command_line
command_string = "spec"
libraries.each do |lib|
command_string << " --require '#{lib}'"
end
command_string << " --runner Spec::Distributed::SlaveExampleGroupRunner:#{temp_filename}"
# TODO: escape the EG descriptions for quote chars
command_string << " -e \"#{example_group_description}\""
command_string << " #{spec_path}"
command_string
end

def run
begin
run_hooks
setup_environment
setup_temp_filename
fork_command
collect_reporter
rescue Exception => e
self.fatal_failure = true
self.exception = e
end
ensure
temp_file.delete if temp_file
self.temp_file = nil
end

def run_hooks
hook_libraries.each { |lib| require lib }
Hooks.run_slave_hooks(self)
end

def setup_environment
if example_group_object_id
add_environment('REMOTE_EXAMPLE_GROUP_OBJECT_ID', example_group_object_id)
end
end

def setup_temp_filename
self.temp_file = Tempfile.new('job')
self.temp_filename = temp_file.path
end

def fork_command
self.status, self.stdout, self.stderr = systemu command_line, 'env' => environment
end

def collect_reporter
if File.stat(temp_file.path).size > 0
temp_file.open
self.reporter = Marshal.load(temp_file)
else
self.fatal_failure = true
end
end

end
end
end
46 changes: 46 additions & 0 deletions lib/spec/distributed/job_runner.rb
@@ -0,0 +1,46 @@
module Spec
module Distributed
class JobRunner
def initialize(options)
@options = options
end

def run
prepare
begin
next_job
run_job
publish_result
end while keep_running?
end

def prepare
#transport_manager.start_local_server_if_required_or_somesuch
transport_manager.connect(true)
end

def next_job
@job = transport_manager.next_job
end

def run_job
@job.run # options?
end

def publish_result
Marshal.dump(@job) # safety check for now. Don't need any
# remote references
transport_manager.publish_result(@job)
end

def keep_running?
true
end

protected
def transport_manager
@options.transport_manager
end
end
end
end
26 changes: 24 additions & 2 deletions lib/spec/distributed/job_runner_option_parser.rb
Expand Up @@ -14,11 +14,33 @@ def valid?
end

def transport_type_valid?
transport_type && transport_manager
end

def transport_manager
@transport_manager ||= create_transport_manager
end

protected
def create_transport_manager
begin
TransportManager.manager_for(transport_type)
type, options = parse_transport_manager_options
@transport_manager = TransportManager.manager_for(type).new(options)
rescue NoSuchTransportException => e
false
nil
end
end

def parse_transport_manager_options
start = transport_type.index(':')
if start
type = transport_type[0...start]
options = start ? transport_type[start +1..-1] : ""
else
type = transport_type
options = ""
end
return type, options
end
end

Expand Down
6 changes: 3 additions & 3 deletions lib/spec/distributed/master_example_group_runner.rb
Expand Up @@ -71,14 +71,14 @@ def report_jobs_with_exceptions
if jobs_with_exceptions.length > 0
puts "The following jobs had fatal failures: "
jobs_with_exceptions.each do |job|
e = job.slave_exception
e = job.exception
if e
puts "#{job.spec_path} -e '#{job.example_group_description}'"
puts "#{e}"
puts e.backtrace
end
puts job.slave_status
puts job.slave_stout
puts job.status
puts job.stout
puts job.stderr
puts
end
Expand Down

0 comments on commit 228ecca

Please sign in to comment.