brynary-testjour 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -44,4 +44,5 @@ For now, just pull down the code from the GitHub repo:
44
44
 
45
45
  === Authors
46
46
 
47
- - Maintained by Bryan Helmkamp (http://brynary.com/)
47
+ - Maintained by Bryan Helmkamp (http://brynary.com/)
48
+ - Thanks to Weplay (http://weplay.com) for sponsoring development and supporting open sourcing it from the start
@@ -6,11 +6,15 @@ Thread.abort_on_exception = true
6
6
  module Testjour
7
7
  SERVICE = "_testjour._tcp"
8
8
 
9
- class Bonjour
9
+ module Bonjour
10
10
 
11
11
  class Server
12
12
  attr_reader :name, :host, :port
13
13
 
14
+ def self.from_dnssd(reply, rr)
15
+ new(reply.name, rr.target, rr.port)
16
+ end
17
+
14
18
  def initialize(name, host, port)
15
19
  @name = name
16
20
  @host = host
@@ -24,24 +28,57 @@ module Testjour
24
28
  def uri
25
29
  "druby://" + @host.gsub(/\.$/, "") + ":" + @port.to_s
26
30
  end
31
+
32
+ def status_line
33
+ " %-12s %s %s" % [name, colored_status, "#{host}:#{port}"]
34
+ end
35
+
36
+ protected
37
+
38
+ def colored_status
39
+ formatted_status = ("%-12s" % status)
40
+ return formatted_status unless defined?(Testjour::Colorer)
41
+
42
+ case formatted_status.strip
43
+ when "available"
44
+ Testjour::Colorer.green(formatted_status)
45
+ else
46
+ Testjour::Colorer.yellow(formatted_status)
47
+ end
48
+ end
49
+
50
+ def status
51
+ drb_object.status
52
+ end
53
+
54
+ def drb_object
55
+ @drb_object ||= DRbObject.new(nil, uri)
56
+ end
27
57
  end
28
58
 
29
- def self.list
30
- hosts = []
59
+ def bonjour_servers
60
+ return @bonjour_servers if !@bonjour_servers.nil?
61
+
62
+ @bonjour_servers = []
31
63
 
32
64
  service = DNSSD.browse(SERVICE) do |reply|
33
65
  DNSSD.resolve(reply.name, reply.type, reply.domain) do |rr|
34
- server = Server.new(reply.name, rr.target, rr.port)
35
- hosts << server unless hosts.any? { |h| h == server }
66
+ found_bonjour_server(Server.from_dnssd(reply, rr))
36
67
  end
37
68
  end
38
69
 
39
70
  sleep 3
40
71
  service.stop
41
- return hosts
72
+ return @bonjour_servers
73
+ end
74
+
75
+ def found_bonjour_server(server)
76
+ unless @bonjour_servers.any? { |h| h == server }
77
+ @bonjour_servers << server
78
+ end
42
79
  end
43
80
 
44
- def self.serve(port)
81
+ def bonjour_serve(port)
45
82
  name = ENV['USER']
46
83
 
47
84
  tr = DNSSD::TextRecord.new
data/lib/testjour/cli.rb CHANGED
@@ -33,19 +33,15 @@ module Testjour
33
33
  self.commands = []
34
34
 
35
35
  def execute
36
- begin
37
- raise NoCommandGiven if ARGV.empty?
38
- raise UnknownCommand.new(command_name) unless command_klass
39
-
40
- args = ARGV.dup
41
- args.shift # Remove subcommand name
42
-
43
- command_klass.new(self, args).run
44
- rescue NoCommandGiven, UnknownCommand
45
- $stderr.puts "ERROR: #{$!.message}"
46
- $stderr.puts usage
47
- exit 1
48
- end
36
+ raise NoCommandGiven if ARGV.empty?
37
+ raise UnknownCommand.new(command_name) unless command_klass
38
+
39
+ args = ARGV.dup
40
+ args.shift # Remove subcommand name
41
+
42
+ command_klass.new(self, args).run
43
+ rescue NoCommandGiven, UnknownCommand
44
+ exit_with_usage
49
45
  end
50
46
 
51
47
  def command_klass
@@ -58,6 +54,12 @@ module Testjour
58
54
  ARGV.first
59
55
  end
60
56
 
57
+ def exit_with_usage
58
+ $stderr.puts "ERROR: #{$!.message}"
59
+ $stderr.puts usage
60
+ exit 1
61
+ end
62
+
61
63
  def usage
62
64
  message = []
63
65
  message << "usage: testjour <SUBCOMMAND> [OPTIONS] [ARGS...]"
@@ -65,13 +67,16 @@ module Testjour
65
67
  message << "Type 'testjour version' to get this program's version."
66
68
  message << ""
67
69
  message << "Available subcommands are:"
68
-
69
- self.class.commands.sort_by { |c| c.command }.each do |command_klass|
70
- message << " " + command_klass.command
71
- end
72
-
70
+ message += command_listing
73
71
  message.map { |line| line.chomp }.join("\n")
74
72
  end
73
+
74
+ def command_listing
75
+ self.class.commands.sort_by { |c| c.command }.map do |command_klass|
76
+ " " + command_klass.command
77
+ end
78
+ end
79
+
75
80
  end
76
81
 
77
82
  end
@@ -10,6 +10,10 @@ module Testjour
10
10
  self.name.downcase
11
11
  end
12
12
 
13
+ def self.inherited(command_class)
14
+ Parser.register_command command_class
15
+ end
16
+
13
17
  def self.options
14
18
  {}
15
19
  end
@@ -14,7 +14,6 @@ module Testjour
14
14
  end
15
15
  end
16
16
 
17
- Parser.register_command HelpCommand
18
17
  end
19
18
  end
20
19
 
@@ -6,6 +6,8 @@ module Testjour
6
6
  module CLI
7
7
 
8
8
  class List < BaseCommand
9
+ include Bonjour
10
+
9
11
  def self.command
10
12
  "list"
11
13
  end
@@ -19,17 +21,13 @@ module Testjour
19
21
  end
20
22
 
21
23
  def run
22
- available_servers = Testjour::Bonjour.list
23
-
24
- if available_servers.any?
24
+ if bonjour_servers.any?
25
25
  puts
26
26
  puts "Testjour servers:"
27
27
  puts
28
28
 
29
- available_servers.each do |server|
30
- slave_server = DRbObject.new(nil, server.uri)
31
- status = colorize_status(slave_server.status)
32
- puts " %-12s %s %s" % [server.name, status, "#{server.host}:#{server.port}"]
29
+ bonjour_servers.each do |server|
30
+ puts server.status_line
33
31
  end
34
32
  else
35
33
  puts
@@ -37,21 +35,8 @@ module Testjour
37
35
  end
38
36
  end
39
37
 
40
- def colorize_status(status)
41
- formatted_status = ("%-12s" % status)
42
- return formatted_status unless defined?(Testjour::Colorer)
43
-
44
- case formatted_status.strip
45
- when "available"
46
- Testjour::Colorer.green(formatted_status)
47
- else
48
- Testjour::Colorer.yellow(formatted_status)
49
- end
50
- end
51
-
52
38
  end
53
39
 
54
- Parser.register_command List
55
40
  end
56
41
  end
57
42
 
@@ -24,33 +24,38 @@ module Testjour
24
24
  ARGV.clear # Don't pass along args to RSpec
25
25
  Testjour.load_cucumber
26
26
 
27
- ENV["RAILS_ENV"] = "test"
28
- require File.expand_path("config/environment")
29
-
30
27
  Testjour::MysqlDatabaseSetup.with_new_database do
31
28
  Cucumber::CLI.executor.formatters = Testjour::DRbFormatter.new(queue_server)
32
29
  require_files
33
-
34
- begin
35
- loop do
36
- begin
37
- run_file(queue_server.take_work)
38
- rescue Testjour::QueueServer::NoWorkUnitsAvailableError
39
- # If no work, ignore and keep looping
40
- end
30
+ work
31
+ end
32
+ end
33
+
34
+ def work
35
+ begin
36
+ loop do
37
+ begin
38
+ run_file(queue_server.take_work)
39
+ rescue Testjour::QueueServer::NoWorkUnitsAvailableError
40
+ # If no work, ignore and keep looping
41
41
  end
42
- rescue DRb::DRbConnError
43
- Testjour.logger.debug "DRb connection error. (This is normal.) Exiting runner."
44
42
  end
43
+ rescue DRb::DRbConnError
44
+ Testjour.logger.debug "DRb connection error. (This is normal.) Exiting runner."
45
45
  end
46
46
  end
47
47
 
48
48
  def require_files
49
49
  cli = Cucumber::CLI.new
50
- cli.parse_options!(@non_options)
50
+ Testjour.logger.debug "Cucumber options: #{options_for_cucumber.inspect}"
51
+ cli.parse_options!(options_for_cucumber)
51
52
  cli.send(:require_files)
52
53
  end
53
54
 
55
+ def options_for_cucumber
56
+ @non_options
57
+ end
58
+
54
59
  def run_file(file)
55
60
  Testjour.logger.debug "Running feature file: #{file}"
56
61
  features = feature_parser.parse_feature(File.expand_path(file))
@@ -77,7 +82,5 @@ module Testjour
77
82
  end
78
83
 
79
84
  end
80
-
81
- Parser.register_command LocalRun
82
85
  end
83
86
  end
@@ -3,11 +3,15 @@ require "drb"
3
3
  require "testjour/commands/base_command"
4
4
  require "testjour/queue_server"
5
5
  require "testjour/bonjour"
6
+ require "testjour/run_command"
6
7
 
7
8
  module Testjour
8
9
  module CLI
9
10
 
10
11
  class Run < BaseCommand
12
+ include RunCommand
13
+ include Bonjour
14
+
11
15
  def self.command
12
16
  "run"
13
17
  end
@@ -63,16 +67,11 @@ module Testjour
63
67
  end
64
68
 
65
69
  def slave_servers_to_use
66
- # require "rubygems"; require "ruby-debug"; Debugger.start; debugger
67
- @slave_servers_to_use ||= available_servers.select do |potential_server|
70
+ @slave_servers_to_use ||= bonjour_servers.select do |potential_server|
68
71
  !servers_specified? || specified_servers_include?(potential_server)
69
72
  end
70
73
  end
71
74
 
72
- def available_servers
73
- @available_servers ||= Testjour::Bonjour.list
74
- end
75
-
76
75
  def request_build_from(server)
77
76
  slave_server = DRbObject.new(nil, server.uri)
78
77
  result = slave_server.run(testjour_uri, @non_options)
@@ -98,22 +97,8 @@ module Testjour
98
97
  end
99
98
 
100
99
  def start_local_runner
101
- pid_queue = Queue.new
102
-
103
- Thread.new do
104
- Thread.current.abort_on_exception = true
105
- cmd = command_for_local_run
106
- Testjour.logger.debug "Starting local:run with command: #{cmd}"
107
- status, stdout, stderr = systemu(cmd) { |pid| pid_queue << pid }
108
- Testjour.logger.warn stderr if stderr.strip.size > 0
109
- end
110
-
111
- pid = pid_queue.pop
112
-
100
+ run_command(command_for_local_run)
113
101
  @found_server += 1
114
- Testjour.logger.info "Started local:run on PID #{pid}"
115
-
116
- pid
117
102
  end
118
103
 
119
104
  def command_for_local_run
@@ -159,7 +144,6 @@ module Testjour
159
144
  end
160
145
  end
161
146
  end
162
-
163
- Parser.register_command Run
147
+
164
148
  end
165
149
  end
@@ -1,88 +1,19 @@
1
- require "drb"
2
- require "uri"
3
-
4
- require "testjour/commands/base_command"
1
+ require "testjour/commands/local_run"
5
2
  require "testjour/rsync"
6
- require "testjour/queue_server"
7
- require "testjour/cucumber_extensions/drb_formatter"
8
- require "testjour/mysql"
9
3
 
10
4
  module Testjour
11
5
  module CLI
12
6
 
13
- class SlaveRun < BaseCommand
7
+ class SlaveRun < LocalRun
14
8
  def self.command
15
9
  "slave:run"
16
10
  end
17
-
18
- def initialize(parser, args)
19
- Testjour.logger.debug "Runner command #{self.class}..."
20
- super
21
- @queue = @non_options.first
22
- end
23
11
 
24
12
  def run
25
- retryable :tries => 2, :on => RsyncFailed do
26
- Testjour::Rsync.copy_to_current_directory_from(@queue)
27
- end
28
-
29
- ARGV.clear # Don't pass along args to RSpec
30
- Testjour.load_cucumber
31
-
32
- ENV["RAILS_ENV"] = "test"
33
- require File.expand_path("config/environment")
34
-
35
- Testjour::MysqlDatabaseSetup.with_new_database do
36
- Cucumber::CLI.executor.formatters = Testjour::DRbFormatter.new(queue_server)
37
- require_files
38
-
39
- begin
40
- loop do
41
- begin
42
- run_file(queue_server.take_work)
43
- rescue Testjour::QueueServer::NoWorkUnitsAvailableError
44
- # If no work, ignore and keep looping
45
- end
46
- end
47
- rescue DRb::DRbConnError
48
- Testjour.logger.debug "DRb connection error. (This is normal.) Exiting runner."
49
- end
50
- end
51
- end
52
-
53
- def require_files
54
- cli = Cucumber::CLI.new
55
- cli.parse_options!(@non_options)
56
- cli.send(:require_files)
57
- end
58
-
59
- def run_file(file)
60
- Testjour.logger.debug "Running feature file: #{file}"
61
- features = feature_parser.parse_feature(File.expand_path(file))
62
- Cucumber::CLI.executor.visit_features(features)
63
- end
64
-
65
- def queue_server
66
- @queue_server ||= begin
67
- DRb.start_service
68
- DRbObject.new(nil, drb_uri)
69
- end
70
- end
71
-
72
- def drb_uri
73
- uri = URI.parse(@queue)
74
- uri.scheme = "druby"
75
- uri.path = ""
76
- uri.user = nil
77
- uri.to_s
78
- end
79
-
80
- def feature_parser
81
- @feature_parser ||= Cucumber::TreetopParser::FeatureParser.new
13
+ Testjour::Rsync.copy_to_current_directory_from(@queue)
14
+ super
82
15
  end
83
-
84
16
  end
85
17
 
86
- Parser.register_command SlaveRun
87
18
  end
88
19
  end
@@ -10,6 +10,8 @@ module Testjour
10
10
  module CLI
11
11
 
12
12
  class SlaveStart < BaseCommand
13
+ include Bonjour
14
+
13
15
  class StopServer < Exception
14
16
  end
15
17
 
@@ -24,7 +26,15 @@ module Testjour
24
26
 
25
27
  def run
26
28
  verify_not_a_git_repo
27
-
29
+ daemonize
30
+ Testjour.setup_logger
31
+ bonjour_serve(Testjour::SlaveServer.start)
32
+ DRb.thread.join
33
+ rescue StopServer
34
+ exit 0
35
+ end
36
+
37
+ def daemonize
28
38
  original_working_directory = File.expand_path(".")
29
39
 
30
40
  pid_file = PidFile.new("./testjour_slave.pid")
@@ -37,12 +47,6 @@ module Testjour
37
47
 
38
48
  Dir.chdir(original_working_directory)
39
49
  pid_file.write
40
-
41
- Testjour.setup_logger
42
- Testjour::Bonjour.serve(Testjour::SlaveServer.start)
43
- DRb.thread.join
44
- rescue StopServer
45
- exit 0
46
50
  end
47
51
 
48
52
  def verify_not_a_git_repo
@@ -60,6 +64,5 @@ module Testjour
60
64
 
61
65
  end
62
66
 
63
- Parser.register_command SlaveStart
64
67
  end
65
68
  end
@@ -15,11 +15,9 @@ module Testjour
15
15
  end
16
16
 
17
17
  def run
18
- pid_file = PidFile.new("./testjour_slave.pid")
19
- pid_file.send_signal("TERM")
18
+ PidFile.term("./testjour_slave.pid")
20
19
  end
21
20
  end
22
21
 
23
- Parser.register_command SlaveStop
24
22
  end
25
23
  end
@@ -19,13 +19,10 @@ module Testjour
19
19
  end
20
20
 
21
21
  def run
22
- retryable :tries => 2, :on => RsyncFailed do
23
- Testjour::Rsync.copy_to_current_directory_from(@queue)
24
- end
22
+ Testjour::Rsync.copy_to_current_directory_from(@queue)
25
23
  end
26
24
 
27
25
  end
28
26
 
29
- Parser.register_command SlaveWarm
30
27
  end
31
28
  end
@@ -13,6 +13,5 @@ module Testjour
13
13
  end
14
14
  end
15
15
 
16
- Parser.register_command VersionCommand
17
16
  end
18
17
  end
@@ -7,6 +7,8 @@ module Testjour
7
7
  module CLI
8
8
 
9
9
  class Warm < BaseCommand
10
+ include Bonjour
11
+
10
12
  def self.command
11
13
  "warm"
12
14
  end
@@ -20,8 +22,8 @@ module Testjour
20
22
  end
21
23
 
22
24
  def run
23
- if available_servers.any?
24
- available_servers.each do |server|
25
+ if bonjour_servers.any?
26
+ bonjour_servers.each do |server|
25
27
  request_warm_from(server)
26
28
  end
27
29
 
@@ -32,10 +34,6 @@ module Testjour
32
34
  end
33
35
  end
34
36
 
35
- def available_servers
36
- @available_servers ||= Testjour::Bonjour.list
37
- end
38
-
39
37
  def request_warm_from(server)
40
38
  slave_server = DRbObject.new(nil, server.uri)
41
39
  result = slave_server.warm(testjour_uri)
@@ -68,6 +66,5 @@ module Testjour
68
66
  end
69
67
  end
70
68
 
71
- Parser.register_command Warm
72
69
  end
73
70
  end
@@ -11,79 +11,97 @@ module Testjour
11
11
  attr_accessor :queue
12
12
  end
13
13
 
14
- def initialize(queue_server, step_mother)
15
- @queue_server = queue_server
16
- @step_count = 0
17
- @passed = 0
18
- @skipped = 0
19
- @pending = 0
20
- @result_uris = []
21
- @errors = []
22
- end
23
-
24
- def wait_for_results
25
- progress_bar = ProgressBar.new("0 slaves", step_count)
14
+ class ResultsFormatter
15
+ def initialize(step_count)
16
+ @passed = 0
17
+ @skipped = 0
18
+ @pending = 0
19
+ @result_uris = []
20
+ @errors = []
21
+ @progress_bar = ProgressBar.new("0 slaves", step_count)
22
+ end
26
23
 
27
- step_count.times do
28
- log_result(*@queue_server.take_result)
24
+ def result(uri, dot, message, backtrace)
25
+ @result_uris << uri
26
+ @result_uris.uniq!
27
+
28
+ log_result(uri, dot, message, backtrace)
29
29
 
30
+ @progress_bar.colorer = colorer
31
+ @progress_bar.title = title
32
+ @progress_bar.inc
33
+ end
34
+
35
+ def log_result(uri, dot, message, backtrace)
36
+ case dot
37
+ when "."
38
+ @passed += 1
39
+ when "F"
40
+ @errors << [message, backtrace]
41
+
42
+ erase_current_line
43
+ print Testjour::Colorer.failed("#{@errors.size}) ")
44
+ puts Testjour::Colorer.failed(message)
45
+ puts backtrace
46
+ puts
47
+ when "P"
48
+ @pending += 1
49
+ when "_"
50
+ @skipped += 1
51
+ end
52
+ end
53
+
54
+ def colorer
30
55
  if failed?
31
- progress_bar.colorer = Testjour::Colorer.method(:failed).to_proc
32
- progress_bar.title = "#{@result_uris.size} slaves, #{@errors.size} failures"
56
+ Testjour::Colorer.method(:failed).to_proc
33
57
  else
34
- progress_bar.colorer = Testjour::Colorer.method(:passed).to_proc
35
- progress_bar.title = "#{@result_uris.size} slaves"
58
+ Testjour::Colorer.method(:passed).to_proc
59
+ end
60
+ end
61
+
62
+ def title
63
+ if failed?
64
+ "#{@result_uris.size} slaves, #{@errors.size} failures"
65
+ else
66
+ "#{@result_uris.size} slaves"
36
67
  end
37
-
38
- progress_bar.inc
39
68
  end
40
69
 
41
- progress_bar.finish
70
+ def erase_current_line
71
+ print "\e[K"
72
+ end
42
73
 
43
- print_summary
44
- print_errors
45
- end
46
-
47
- def failed?
48
- @errors.any?
49
- end
50
-
51
-
52
- def log_result(uri, dot, message, backtrace)
53
- @result_uris << uri
54
- @result_uris.uniq!
74
+ def print_summary
75
+ puts
76
+ puts
77
+ puts Colorer.passed("#{@passed} steps passed") unless @passed.zero?
78
+ puts Colorer.failed("#{@errors.size} steps failed") unless @errors.empty?
79
+ puts Colorer.skipped("#{@skipped} steps skipped") unless @skipped.zero?
80
+ puts Colorer.pending("#{@pending} steps pending") unless @pending.zero?
81
+ puts
82
+ end
55
83
 
56
- case dot
57
- when "."
58
- @passed += 1
59
- when "F"
60
- @errors << [message, backtrace]
61
- when "P"
62
- @pending += 1
63
- when "_"
64
- @skipped += 1
84
+ def finish
85
+ @progress_bar.finish
86
+ print_summary
87
+ end
88
+
89
+ def failed?
90
+ @errors.any?
65
91
  end
66
92
  end
67
-
68
- def print_summary
69
- puts
70
- puts
71
- puts Colorer.passed("#{@passed} steps passed") unless @passed.zero?
72
- puts Colorer.failed("#{@errors.size} steps failed") unless @errors.empty?
73
- puts Colorer.skipped("#{@skipped} steps skipped") unless @skipped.zero?
74
- puts Colorer.pending("#{@pending} steps pending") unless @pending.zero?
75
- puts
93
+
94
+ def initialize(queue_server, step_mother)
95
+ @queue_server = queue_server
96
+ @step_count = 0
76
97
  end
77
98
 
78
- def print_errors
79
- @errors.each_with_index do |error, i|
80
- message, backtrace = error
81
-
82
- puts
83
- puts Colorer.failed("#{i+1})")
84
- puts Colorer.failed(message)
85
- puts Colorer.failed(backtrace)
99
+ def wait_for_results
100
+ results_formatter = ResultsFormatter.new(@step_count)
101
+ step_count.times do
102
+ results_formatter.result(*@queue_server.take_result)
86
103
  end
104
+ results_formatter.finish
87
105
  end
88
106
 
89
107
  def visit_feature(feature)
@@ -1,3 +1,5 @@
1
+ RAILS_ROOT = File.expand_path(".") unless defined?(RAILS_ROOT)
2
+
1
3
  module Testjour
2
4
 
3
5
  # Stolen from deep-test
@@ -21,9 +23,18 @@ module Testjour
21
23
  }
22
24
 
23
25
  def self.with_new_database
26
+ ENV["RAILS_ENV"] ||= "test"
27
+ require File.expand_path("./vendor/rails/railties/lib/initializer")
28
+ Rails::Initializer.run(:set_load_path)
29
+
30
+ require "active_record"
31
+ require "active_record/connection_adapters/mysql_adapter"
32
+
24
33
  mysql = self.new
25
34
  mysql.create_database
26
35
 
36
+ ENV["TESTJOUR_DB"] = mysql.runner_database_name
37
+
27
38
  at_exit do
28
39
  mysql.drop_database
29
40
  end
@@ -33,7 +44,7 @@ module Testjour
33
44
 
34
45
  yield
35
46
  end
36
-
47
+
37
48
  def grant_privileges(connection)
38
49
  sql = %{grant all on #{runner_database_name}.*
39
50
  to %s@'localhost' identified by %s;} % [
@@ -1,6 +1,10 @@
1
1
  module Testjour
2
2
 
3
3
  class PidFile
4
+
5
+ def self.term(path)
6
+ new(path).send_signal("TERM")
7
+ end
4
8
 
5
9
  def initialize(path)
6
10
  @path = File.expand_path(path)
@@ -8,22 +8,46 @@ module Testjour
8
8
  class Rsync
9
9
 
10
10
  def self.copy_to_current_directory_from(source_uri)
11
- destination_dir = File.expand_path(".")
12
- uri = URI.parse(source_uri)
13
-
14
- command = "rsync -az --delete --exclude=.git --exclude=*.log --exclude=*.pid #{uri.user}@#{uri.host}:#{uri.path}/ #{destination_dir}"
15
-
16
- Testjour.logger.info "Rsyncing: #{command}"
17
- start_time = Time.now
18
- successful = system command
19
-
20
- if successful
21
- time = Time.now - start_time
22
- Testjour.logger.debug("Rsync finished in %.2fs" % time)
23
- else
24
- raise RsyncFailed.new
11
+ new(source_uri).copy_with_retry
12
+ end
13
+
14
+ def initialize(source_uri)
15
+ @source_uri = source_uri
16
+ end
17
+
18
+ def copy_with_retry
19
+ retryable :tries => 2, :on => RsyncFailed do
20
+ Testjour.logger.info "Rsyncing: #{command}"
21
+ copy
22
+ Testjour.logger.debug("Rsync finished in %.2fs" % elapsed_time)
23
+ raise RsyncFailed.new unless successful?
25
24
  end
26
25
  end
27
26
 
27
+ def copy
28
+ @start_time = Time.now
29
+ @successful = system(command)
30
+ end
31
+
32
+ def elapsed_time
33
+ Time.now - @start_time
34
+ end
35
+
36
+ def successful?
37
+ @successful
38
+ end
39
+
40
+ def command
41
+ "rsync -az --delete --exclude=.git --exclude=*.log --exclude=*.pid #{uri.user}@#{uri.host}:#{uri.path}/ #{destination_dir}"
42
+ end
43
+
44
+ def destination_dir
45
+ File.expand_path(".")
46
+ end
47
+
48
+ def uri
49
+ URI.parse(@source_uri)
50
+ end
51
+
28
52
  end
29
53
  end
@@ -0,0 +1,21 @@
1
+ require "systemu"
2
+
3
+ module Testjour
4
+ module RunCommand
5
+
6
+ def run_command(cmd)
7
+ pid_queue = Queue.new
8
+
9
+ Thread.new do
10
+ Thread.current.abort_on_exception = true
11
+ status, stdout, stderr = systemu(cmd) { |pid| pid_queue << pid }
12
+ Testjour.logger.warn stderr if stderr.strip.size > 0
13
+ end
14
+
15
+ pid = pid_queue.pop
16
+ Testjour.logger.info "Started on PID #{pid}: #{cmd}"
17
+ pid
18
+ end
19
+
20
+ end
21
+ end
@@ -2,12 +2,14 @@ require "thread"
2
2
  require "drb"
3
3
  require "uri"
4
4
  require "timeout"
5
- require "systemu"
5
+
6
+ require "testjour/run_command"
6
7
 
7
8
  module Testjour
8
9
 
9
10
  class SlaveServer
10
-
11
+ include RunCommand
12
+
11
13
  def self.start
12
14
  server = self.new
13
15
  DRb.start_service(nil, server)
@@ -28,22 +30,8 @@ module Testjour
28
30
  Testjour.logger.info "Not running because pid exists: #{@pid}"
29
31
  return false
30
32
  end
31
-
32
- pid_queue = Queue.new
33
- @pid = nil
34
-
35
- Thread.new do
36
- Thread.current.abort_on_exception = true
37
- cmd = command_to_warm_for(queue_server_url)
38
- Testjour.logger.debug "Starting warm with command: #{cmd}"
39
- status, stdout, stderr = systemu(cmd) { |pid| pid_queue << pid }
40
- Testjour.logger.warn stderr if stderr.strip.size > 0
41
- end
42
-
43
- @pid = pid_queue.pop
44
-
45
- Testjour.logger.info "Warming from server #{queue_server_url} on PID #{@pid}"
46
-
33
+
34
+ @pid = run_command(command_to_warm_for(queue_server_url))
47
35
  return @pid
48
36
  end
49
37
 
@@ -53,21 +41,7 @@ module Testjour
53
41
  return false
54
42
  end
55
43
 
56
- pid_queue = Queue.new
57
- @pid = nil
58
-
59
- Thread.new do
60
- Thread.current.abort_on_exception = true
61
- cmd = command_to_run_for(queue_server_url, cucumber_options)
62
- Testjour.logger.debug "Starting runner with command: #{cmd}"
63
- status, stdout, stderr = systemu(cmd) { |pid| pid_queue << pid }
64
- Testjour.logger.warn stderr if stderr.strip.size > 0
65
- end
66
-
67
- @pid = pid_queue.pop
68
-
69
- Testjour.logger.info "Running tests from queue #{queue_server_url} on PID #{@pid}"
70
-
44
+ @pid = run_command(command_to_run_for(queue_server_url, cucumber_options))
71
45
  return @pid
72
46
  end
73
47
 
data/lib/testjour.rb CHANGED
@@ -31,7 +31,7 @@ module Kernel
31
31
  end
32
32
 
33
33
  module Testjour
34
- VERSION = '0.1.0'
34
+ VERSION = '0.2.0'
35
35
 
36
36
  class << self
37
37
  attr_accessor :step_mother
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brynary-testjour
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Helmkamp
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-09 00:00:00 -08:00
12
+ date: 2008-12-11 00:00:00 -08:00
13
13
  default_executable: testjour
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -69,6 +69,7 @@ files:
69
69
  - lib/testjour/progressbar.rb
70
70
  - lib/testjour/queue_server.rb
71
71
  - lib/testjour/rsync.rb
72
+ - lib/testjour/run_command.rb
72
73
  - lib/testjour/slave_server.rb
73
74
  - lib/testjour.rb
74
75
  - vendor/authprogs