hydra 0.18.0 → 0.19.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/.gitignore +1 -0
- data/VERSION +1 -1
- data/hydra.gemspec +14 -11
- data/lib/hydra.rb +1 -0
- data/lib/hydra/master.rb +31 -29
- data/lib/hydra/runner.rb +1 -1
- data/lib/hydra/ssh.rb +1 -0
- data/lib/hydra/sync.rb +99 -0
- data/lib/hydra/tasks.rb +83 -19
- data/test/sync_test.rb +113 -0
- metadata +15 -12
data/.gitignore
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.19.0
|
data/hydra.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{hydra}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.19.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Nick Gauthier"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-06-07}
|
13
13
|
s.description = %q{Spread your tests over multiple machines to test your code faster.}
|
14
14
|
s.email = %q{nick@smartlogicsolutions.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -51,6 +51,7 @@ Gem::Specification.new do |s|
|
|
51
51
|
"lib/hydra/spec/hydra_formatter.rb",
|
52
52
|
"lib/hydra/ssh.rb",
|
53
53
|
"lib/hydra/stdio.rb",
|
54
|
+
"lib/hydra/sync.rb",
|
54
55
|
"lib/hydra/tasks.rb",
|
55
56
|
"lib/hydra/trace.rb",
|
56
57
|
"lib/hydra/worker.rb",
|
@@ -73,6 +74,7 @@ Gem::Specification.new do |s|
|
|
73
74
|
"test/pipe_test.rb",
|
74
75
|
"test/runner_test.rb",
|
75
76
|
"test/ssh_test.rb",
|
77
|
+
"test/sync_test.rb",
|
76
78
|
"test/test_helper.rb",
|
77
79
|
"test/worker_test.rb"
|
78
80
|
]
|
@@ -83,20 +85,21 @@ Gem::Specification.new do |s|
|
|
83
85
|
s.summary = %q{Distributed testing toolkit}
|
84
86
|
s.test_files = [
|
85
87
|
"test/pipe_test.rb",
|
88
|
+
"test/test_helper.rb",
|
86
89
|
"test/ssh_test.rb",
|
90
|
+
"test/message_test.rb",
|
91
|
+
"test/master_test.rb",
|
92
|
+
"test/fixtures/write_file.rb",
|
93
|
+
"test/fixtures/slow.rb",
|
94
|
+
"test/fixtures/write_file_with_pending_spec.rb",
|
95
|
+
"test/fixtures/write_file_spec.rb",
|
96
|
+
"test/fixtures/features/step_definitions.rb",
|
97
|
+
"test/fixtures/hello_world.rb",
|
87
98
|
"test/fixtures/write_file_alternate_spec.rb",
|
88
99
|
"test/fixtures/sync_test.rb",
|
89
|
-
"test/fixtures/hello_world.rb",
|
90
|
-
"test/fixtures/features/step_definitions.rb",
|
91
100
|
"test/fixtures/assert_true.rb",
|
92
|
-
"test/fixtures/slow.rb",
|
93
|
-
"test/fixtures/write_file_spec.rb",
|
94
|
-
"test/fixtures/write_file_with_pending_spec.rb",
|
95
|
-
"test/fixtures/write_file.rb",
|
96
|
-
"test/message_test.rb",
|
97
|
-
"test/test_helper.rb",
|
98
|
-
"test/master_test.rb",
|
99
101
|
"test/runner_test.rb",
|
102
|
+
"test/sync_test.rb",
|
100
103
|
"test/worker_test.rb"
|
101
104
|
]
|
102
105
|
|
data/lib/hydra.rb
CHANGED
data/lib/hydra/master.rb
CHANGED
@@ -1,15 +1,20 @@
|
|
1
1
|
require 'hydra/hash'
|
2
2
|
require 'open3'
|
3
3
|
require 'tmpdir'
|
4
|
+
require 'erb'
|
4
5
|
require 'yaml'
|
6
|
+
|
5
7
|
module Hydra #:nodoc:
|
6
8
|
# Hydra class responsible for delegate work down to workers.
|
7
9
|
#
|
8
10
|
# The Master is run once for any given testing session.
|
11
|
+
class YmlLoadError < StandardError; end
|
12
|
+
|
9
13
|
class Master
|
10
14
|
include Hydra::Messages::Master
|
11
15
|
include Open3
|
12
16
|
traceable('MASTER')
|
17
|
+
|
13
18
|
# Create a new Master
|
14
19
|
#
|
15
20
|
# Options:
|
@@ -28,10 +33,29 @@ module Hydra #:nodoc:
|
|
28
33
|
# * :autosort
|
29
34
|
# * Set to false to disable automatic sorting by historical run-time per file
|
30
35
|
def initialize(opts = { })
|
36
|
+
trap("SIGINT") do
|
37
|
+
puts "Testing halted by user. Untested files:"
|
38
|
+
puts @incomplete_files.join("\n")
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
|
31
42
|
opts.stringify_keys!
|
32
43
|
config_file = opts.delete('config') { nil }
|
33
44
|
if config_file
|
34
|
-
|
45
|
+
|
46
|
+
begin
|
47
|
+
config_erb = ERB.new(IO.read(config_file)).result(binding)
|
48
|
+
rescue Exception => e
|
49
|
+
raise(YmlLoadError,"config file was found, but could not be parsed with ERB.\n#{$!.inspect}")
|
50
|
+
end
|
51
|
+
|
52
|
+
begin
|
53
|
+
config_yml = YAML::load(config_erb)
|
54
|
+
rescue StandardError => e
|
55
|
+
raise(YmlLoadError,"config file was found, but could not be parsed.\n#{$!.inspect}")
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.merge!(config_yml.stringify_keys!)
|
35
59
|
end
|
36
60
|
@files = Array(opts.fetch('files') { nil })
|
37
61
|
raise "No files, nothing to do" if @files.empty?
|
@@ -47,6 +71,7 @@ module Hydra #:nodoc:
|
|
47
71
|
@verbose = opts.fetch('verbose') { false }
|
48
72
|
@autosort = opts.fetch('autosort') { true }
|
49
73
|
@sync = opts.fetch('sync') { nil }
|
74
|
+
@environment = opts.fetch('environment') { 'test' }
|
50
75
|
|
51
76
|
if @autosort
|
52
77
|
sort_files_from_report
|
@@ -134,39 +159,16 @@ module Hydra #:nodoc:
|
|
134
159
|
end
|
135
160
|
|
136
161
|
def boot_ssh_worker(worker)
|
162
|
+
sync = Sync.new(worker, @sync, @verbose)
|
163
|
+
|
137
164
|
runners = worker.fetch('runners') { raise "You must specify the number of runners" }
|
138
|
-
connect = worker.fetch('connect') { raise "You must specify an SSH connection target" }
|
139
|
-
ssh_opts = worker.fetch('ssh_opts') { "" }
|
140
|
-
directory = worker.fetch('directory') { raise "You must specify a remote directory" }
|
141
165
|
command = worker.fetch('command') {
|
142
|
-
"ruby -e \"require 'rubygems'; require 'hydra'; Hydra::Worker.new(:io => Hydra::Stdio.new, :runners => #{runners}, :verbose => #{@verbose});\""
|
166
|
+
"RAILS_ENV=#{@environment} ruby -e \"require 'rubygems'; require 'hydra'; Hydra::Worker.new(:io => Hydra::Stdio.new, :runners => #{runners}, :verbose => #{@verbose});\""
|
143
167
|
}
|
144
168
|
|
145
|
-
if @sync
|
146
|
-
@sync.stringify_keys!
|
147
|
-
trace "Synchronizing with #{connect}\n\t#{@sync.inspect}"
|
148
|
-
local_dir = @sync.fetch('directory') {
|
149
|
-
raise "You must specify a synchronization directory"
|
150
|
-
}
|
151
|
-
exclude_paths = @sync.fetch('exclude') { [] }
|
152
|
-
exclude_opts = exclude_paths.inject(''){|memo, path| memo += "--exclude=#{path} "}
|
153
|
-
|
154
|
-
rsync_command = [
|
155
|
-
'rsync',
|
156
|
-
'-avz',
|
157
|
-
'--delete',
|
158
|
-
exclude_opts,
|
159
|
-
File.expand_path(local_dir)+'/',
|
160
|
-
"-e \"ssh #{ssh_opts}\"",
|
161
|
-
"#{connect}:#{directory}"
|
162
|
-
].join(" ")
|
163
|
-
trace rsync_command
|
164
|
-
trace `#{rsync_command}`
|
165
|
-
end
|
166
|
-
|
167
169
|
trace "Booting SSH worker"
|
168
|
-
ssh = Hydra::SSH.new("#{ssh_opts} #{connect}",
|
169
|
-
return { :io => ssh, :idle => false, :type => :ssh }
|
170
|
+
ssh = Hydra::SSH.new("#{sync.ssh_opts} #{sync.connect}", sync.remote_dir, command)
|
171
|
+
return { :io => ssh, :idle => false, :type => :ssh, :connect => sync.connect }
|
170
172
|
end
|
171
173
|
|
172
174
|
def shutdown_all_workers
|
data/lib/hydra/runner.rb
CHANGED
@@ -180,7 +180,7 @@ module Hydra #:nodoc:
|
|
180
180
|
def run_javascript_file(file)
|
181
181
|
errors = []
|
182
182
|
require 'v8'
|
183
|
-
V8::Context.
|
183
|
+
V8::Context.new do |context|
|
184
184
|
context.load(File.expand_path(File.join(File.dirname(__FILE__), 'js', 'lint.js')))
|
185
185
|
context['input'] = lambda{
|
186
186
|
File.read(file)
|
data/lib/hydra/ssh.rb
CHANGED
@@ -27,6 +27,7 @@ module Hydra #:nodoc:
|
|
27
27
|
# list all the files.
|
28
28
|
def initialize(connection_options, directory, command)
|
29
29
|
@writer, @reader, @error = popen3("ssh -tt #{connection_options}")
|
30
|
+
@writer.write("mkdir -p #{directory}\n")
|
30
31
|
@writer.write("cd #{directory}\n")
|
31
32
|
@writer.write(command+"\n")
|
32
33
|
end
|
data/lib/hydra/sync.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
module Hydra #:nodoc:
|
3
|
+
# Hydra class responsible for delegate work down to workers.
|
4
|
+
#
|
5
|
+
# The Sync is run once for each remote worker.
|
6
|
+
class Sync
|
7
|
+
traceable('SYNC')
|
8
|
+
self.class.traceable('SYNC MANY')
|
9
|
+
|
10
|
+
attr_reader :connect, :ssh_opts, :remote_dir
|
11
|
+
|
12
|
+
# Create a new Sync instance to rsync source from the local machine to a remote worker
|
13
|
+
#
|
14
|
+
# Arguments:
|
15
|
+
# * :worker_opts
|
16
|
+
# * A hash of the configuration options for a worker.
|
17
|
+
# * :sync
|
18
|
+
# * A hash of settings specifically for copying the source directory to be tested
|
19
|
+
# to the remote worked
|
20
|
+
# * :verbose
|
21
|
+
# * Set to true to see lots of Hydra output (for debugging)
|
22
|
+
def initialize(worker_opts, sync_opts, verbose = false)
|
23
|
+
worker_opts ||= {}
|
24
|
+
worker_opts.stringify_keys!
|
25
|
+
@verbose = verbose
|
26
|
+
@connect = worker_opts.fetch('connect') { raise "You must specify an SSH connection target" }
|
27
|
+
@ssh_opts = worker_opts.fetch('ssh_opts') { "" }
|
28
|
+
@remote_dir = worker_opts.fetch('directory') { raise "You must specify a remote directory" }
|
29
|
+
|
30
|
+
return unless sync_opts
|
31
|
+
sync_opts.stringify_keys!
|
32
|
+
@local_dir = sync_opts.fetch('directory') { raise "You must specify a synchronization directory" }
|
33
|
+
@exclude_paths = sync_opts.fetch('exclude') { [] }
|
34
|
+
|
35
|
+
trace "Initialized"
|
36
|
+
trace " Worker: (#{worker_opts.inspect})"
|
37
|
+
trace " Sync: (#{sync_opts.inspect})"
|
38
|
+
|
39
|
+
sync
|
40
|
+
end
|
41
|
+
|
42
|
+
def sync
|
43
|
+
#trace "Synchronizing with #{connect}\n\t#{sync_opts.inspect}"
|
44
|
+
exclude_opts = @exclude_paths.inject(''){|memo, path| memo += "--exclude=#{path} "}
|
45
|
+
|
46
|
+
rsync_command = [
|
47
|
+
'rsync',
|
48
|
+
'-avz',
|
49
|
+
'--delete',
|
50
|
+
exclude_opts,
|
51
|
+
File.expand_path(@local_dir)+'/',
|
52
|
+
"-e \"ssh #{@ssh_opts}\"",
|
53
|
+
"#{@connect}:#{@remote_dir}"
|
54
|
+
].join(" ")
|
55
|
+
trace rsync_command
|
56
|
+
trace `#{rsync_command}`
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.sync_many opts
|
60
|
+
opts.stringify_keys!
|
61
|
+
config_file = opts.delete('config') { nil }
|
62
|
+
if config_file
|
63
|
+
opts.merge!(YAML.load_file(config_file).stringify_keys!)
|
64
|
+
end
|
65
|
+
@verbose = opts.fetch('verbose') { false }
|
66
|
+
@sync = opts.fetch('sync') { {} }
|
67
|
+
|
68
|
+
workers_opts = opts.fetch('workers') { [] }
|
69
|
+
@remote_worker_opts = []
|
70
|
+
workers_opts.each do |worker_opts|
|
71
|
+
worker_opts.stringify_keys!
|
72
|
+
if worker_opts['type'].to_s == 'ssh'
|
73
|
+
@remote_worker_opts << worker_opts
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
trace "Initialized"
|
78
|
+
trace " Sync: (#{@sync.inspect})"
|
79
|
+
trace " Workers: (#{@remote_worker_opts.inspect})"
|
80
|
+
|
81
|
+
Thread.abort_on_exception = true
|
82
|
+
trace "Processing workers"
|
83
|
+
@listeners = []
|
84
|
+
@remote_worker_opts.each do |worker_opts|
|
85
|
+
@listeners << Thread.new do
|
86
|
+
begin
|
87
|
+
trace "Syncing #{worker_opts.inspect}"
|
88
|
+
Sync.new worker_opts, @sync, @verbose
|
89
|
+
rescue
|
90
|
+
trace "Syncing failed [#{worker_opts.inspect}]"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
@listeners.each{|l| l.join}
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
data/lib/hydra/tasks.rb
CHANGED
@@ -177,6 +177,43 @@ module Hydra #:nodoc:
|
|
177
177
|
end
|
178
178
|
end
|
179
179
|
|
180
|
+
# Define a sync task that uses hydra to rsync the source tree under test to remote workers.
|
181
|
+
#
|
182
|
+
# This task is very useful to run before a remote db:reset task to make sure the db/schema.rb
|
183
|
+
# file is up to date on the remote workers.
|
184
|
+
#
|
185
|
+
# Hydra::SyncTask.new('hydra:sync') do |t|
|
186
|
+
# t.verbose = false # optionally set to true for lots of debug messages
|
187
|
+
# end
|
188
|
+
class SyncTask < Hydra::Task
|
189
|
+
|
190
|
+
# Create a new SyncTestTask
|
191
|
+
def initialize(name = :sync)
|
192
|
+
@name = name
|
193
|
+
@verbose = false
|
194
|
+
|
195
|
+
yield self if block_given?
|
196
|
+
|
197
|
+
@config = find_config_file
|
198
|
+
|
199
|
+
@opts = {
|
200
|
+
:verbose => @verbose
|
201
|
+
}
|
202
|
+
@opts.merge!(:config => @config) if @config
|
203
|
+
|
204
|
+
define
|
205
|
+
end
|
206
|
+
|
207
|
+
private
|
208
|
+
# Create the rake task defined by this HydraSyncTask
|
209
|
+
def define
|
210
|
+
desc "Hydra Tests" + (@name == :hydra ? "" : " for #{@name}")
|
211
|
+
task @name do
|
212
|
+
Hydra::Sync.sync_many(@opts)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
180
217
|
# Setup a task that will be run across all remote workers
|
181
218
|
# Hydra::RemoteTask.new('db:reset')
|
182
219
|
#
|
@@ -202,32 +239,59 @@ module Hydra #:nodoc:
|
|
202
239
|
desc "Run #{@name} remotely on all workers"
|
203
240
|
task "hydra:remote:#{@name}" do
|
204
241
|
config = YAML.load_file(@config)
|
242
|
+
environment = config.fetch('environment') { 'test' }
|
205
243
|
workers = config.fetch('workers') { [] }
|
206
244
|
workers = workers.select{|w| w['type'] == 'ssh'}
|
245
|
+
|
246
|
+
$stdout.write "==== Hydra Running #{@name} ====\n"
|
247
|
+
Thread.abort_on_exception = true
|
248
|
+
@listeners = []
|
249
|
+
@results = {}
|
207
250
|
workers.each do |worker|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
ignoring = true
|
218
|
-
while line = reader.gets
|
219
|
-
line.chomp!
|
220
|
-
if line =~ /echo END HYDRA$/
|
221
|
-
ignoring = true
|
222
|
-
end
|
223
|
-
$stdout.write "#{line}\n" unless ignoring
|
224
|
-
if line == 'BEGIN HYDRA'
|
225
|
-
ignoring = false
|
251
|
+
@listeners << Thread.new do
|
252
|
+
begin
|
253
|
+
@results[worker] = if run_task(worker, environment)
|
254
|
+
"==== #{@name} passed on #{worker['connect']} ====\n"
|
255
|
+
else
|
256
|
+
"==== #{@name} failed on #{worker['connect']} ====\nPlease see above for more details.\n"
|
257
|
+
end
|
258
|
+
rescue
|
259
|
+
@results[worker] = "==== #{@name} failed for #{worker['connect']} ====\n#{$!.inspect}\n#{$!.backtrace.join("\n")}"
|
226
260
|
end
|
227
261
|
end
|
228
|
-
|
262
|
+
end
|
263
|
+
@listeners.each{|l| l.join}
|
264
|
+
$stdout.write "\n==== Hydra Running #{@name} COMPLETE ====\n\n"
|
265
|
+
$stdout.write @results.values.join("\n")
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def run_task worker, environment
|
270
|
+
$stdout.write "==== Hydra Running #{@name} on #{worker['connect']} ====\n"
|
271
|
+
ssh_opts = worker.fetch('ssh_opts') { '' }
|
272
|
+
writer, reader, error = popen3("ssh -tt #{ssh_opts} #{worker['connect']} ")
|
273
|
+
writer.write("cd #{worker['directory']}\n")
|
274
|
+
writer.write "echo BEGIN HYDRA\n"
|
275
|
+
writer.write("RAILS_ENV=#{environment} rake #{@name}\n")
|
276
|
+
writer.write "echo END HYDRA\n"
|
277
|
+
writer.write("exit\n")
|
278
|
+
writer.close
|
279
|
+
ignoring = true
|
280
|
+
passed = true
|
281
|
+
while line = reader.gets
|
282
|
+
line.chomp!
|
283
|
+
if line =~ /^rake aborted!$/
|
284
|
+
passed = false
|
285
|
+
end
|
286
|
+
if line =~ /echo END HYDRA$/
|
287
|
+
ignoring = true
|
288
|
+
end
|
289
|
+
$stdout.write "#{worker['connect']}: #{line}\n" unless ignoring
|
290
|
+
if line == 'BEGIN HYDRA'
|
291
|
+
ignoring = false
|
229
292
|
end
|
230
293
|
end
|
294
|
+
passed
|
231
295
|
end
|
232
296
|
end
|
233
297
|
|
data/test/sync_test.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class SyncTest < Test::Unit::TestCase
|
4
|
+
context "with a file to test and a destination to verify" do
|
5
|
+
setup do
|
6
|
+
# avoid having other tests interfering with us
|
7
|
+
sleep(0.2)
|
8
|
+
#FileUtils.rm_f(target_file)
|
9
|
+
end
|
10
|
+
|
11
|
+
teardown do
|
12
|
+
#FileUtils.rm_f(target_file)
|
13
|
+
end
|
14
|
+
|
15
|
+
should "synchronize a test file over ssh with rsync" do
|
16
|
+
local = File.join(Dir.tmpdir, 'hydra', 'local')
|
17
|
+
remote = File.join(Dir.tmpdir, 'hydra', 'remote')
|
18
|
+
sync_test = File.join(File.dirname(__FILE__), 'fixtures', 'sync_test.rb')
|
19
|
+
[local, remote].each{|f| FileUtils.rm_rf f; FileUtils.mkdir_p f}
|
20
|
+
|
21
|
+
# setup the folders:
|
22
|
+
# local:
|
23
|
+
# - test_a
|
24
|
+
# - test_c
|
25
|
+
# remote:
|
26
|
+
# - test_b
|
27
|
+
#
|
28
|
+
# add test_c to exludes
|
29
|
+
FileUtils.cp(sync_test, File.join(local, 'test_a.rb'))
|
30
|
+
FileUtils.cp(sync_test, File.join(local, 'test_c.rb'))
|
31
|
+
FileUtils.cp(sync_test, File.join(remote, 'test_b.rb'))
|
32
|
+
|
33
|
+
# ensure a is not on remote
|
34
|
+
assert !File.exists?(File.join(remote, 'test_a.rb')), "A should not be on remote"
|
35
|
+
# ensure c is not on remote
|
36
|
+
assert !File.exists?(File.join(remote, 'test_c.rb')), "C should not be on remote"
|
37
|
+
# ensure b is on remote
|
38
|
+
assert File.exists?(File.join(remote, 'test_b.rb')), "B should be on remote"
|
39
|
+
|
40
|
+
Hydra::Sync.new(
|
41
|
+
{
|
42
|
+
:type => :ssh,
|
43
|
+
:connect => 'localhost',
|
44
|
+
:directory => remote,
|
45
|
+
:runners => 1
|
46
|
+
},
|
47
|
+
{
|
48
|
+
:directory => local,
|
49
|
+
:exclude => ['test_c.rb']
|
50
|
+
}
|
51
|
+
)
|
52
|
+
# ensure a is copied
|
53
|
+
assert File.exists?(File.join(remote, 'test_a.rb')), "A was not copied"
|
54
|
+
# ensure c is not copied
|
55
|
+
assert !File.exists?(File.join(remote, 'test_c.rb')), "C was copied, should be excluded"
|
56
|
+
# ensure b is deleted
|
57
|
+
assert !File.exists?(File.join(remote, 'test_b.rb')), "B was not deleted"
|
58
|
+
end
|
59
|
+
|
60
|
+
should "synchronize a test file over ssh with rsync to multiple workers" do
|
61
|
+
local = File.join(Dir.tmpdir, 'hydra', 'local')
|
62
|
+
remote_a = File.join(Dir.tmpdir, 'hydra', 'remote_a')
|
63
|
+
remote_b = File.join(Dir.tmpdir, 'hydra', 'remote_b')
|
64
|
+
sync_test = File.join(File.dirname(__FILE__), 'fixtures', 'sync_test.rb')
|
65
|
+
[local, remote_a, remote_b].each{|f| FileUtils.rm_rf f; FileUtils.mkdir_p f}
|
66
|
+
|
67
|
+
# setup the folders:
|
68
|
+
# local:
|
69
|
+
# - test_a
|
70
|
+
# remote_a:
|
71
|
+
# - test_b
|
72
|
+
# remote_b:
|
73
|
+
# - test_c
|
74
|
+
#
|
75
|
+
# add test_c to exludes
|
76
|
+
FileUtils.cp(sync_test, File.join(local, 'test_a.rb'))
|
77
|
+
FileUtils.cp(sync_test, File.join(remote_a, 'test_b.rb'))
|
78
|
+
FileUtils.cp(sync_test, File.join(remote_b, 'test_c.rb'))
|
79
|
+
|
80
|
+
# ensure a is not on remotes
|
81
|
+
assert !File.exists?(File.join(remote_a, 'test_a.rb')), "A should not be on remote_a"
|
82
|
+
assert !File.exists?(File.join(remote_b, 'test_a.rb')), "A should not be on remote_b"
|
83
|
+
# ensure b is on remote_a
|
84
|
+
assert File.exists?(File.join(remote_a, 'test_b.rb')), "B should be on remote_a"
|
85
|
+
# ensure c is on remote_b
|
86
|
+
assert File.exists?(File.join(remote_b, 'test_c.rb')), "C should be on remote_b"
|
87
|
+
|
88
|
+
Hydra::Sync.sync_many(
|
89
|
+
:workers => [{
|
90
|
+
:type => :ssh,
|
91
|
+
:connect => 'localhost',
|
92
|
+
:directory => remote_a,
|
93
|
+
:runners => 1
|
94
|
+
},
|
95
|
+
{
|
96
|
+
:type => :ssh,
|
97
|
+
:connect => 'localhost',
|
98
|
+
:directory => remote_b,
|
99
|
+
:runners => 1
|
100
|
+
}],
|
101
|
+
:sync => {
|
102
|
+
:directory => local
|
103
|
+
}
|
104
|
+
)
|
105
|
+
# ensure a is copied to both remotes
|
106
|
+
assert File.exists?(File.join(remote_a, 'test_a.rb')), "A was not copied to remote_a"
|
107
|
+
assert File.exists?(File.join(remote_b, 'test_a.rb')), "A was not copied to remote_b"
|
108
|
+
# ensure b and c are deleted from remotes
|
109
|
+
assert !File.exists?(File.join(remote_a, 'test_b.rb')), "B was not deleted from remote_a"
|
110
|
+
assert !File.exists?(File.join(remote_b, 'test_c.rb')), "C was not deleted from remote_b"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 19
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.19.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Nick Gauthier
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-06-07 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -103,6 +103,7 @@ files:
|
|
103
103
|
- lib/hydra/spec/hydra_formatter.rb
|
104
104
|
- lib/hydra/ssh.rb
|
105
105
|
- lib/hydra/stdio.rb
|
106
|
+
- lib/hydra/sync.rb
|
106
107
|
- lib/hydra/tasks.rb
|
107
108
|
- lib/hydra/trace.rb
|
108
109
|
- lib/hydra/worker.rb
|
@@ -125,6 +126,7 @@ files:
|
|
125
126
|
- test/pipe_test.rb
|
126
127
|
- test/runner_test.rb
|
127
128
|
- test/ssh_test.rb
|
129
|
+
- test/sync_test.rb
|
128
130
|
- test/test_helper.rb
|
129
131
|
- test/worker_test.rb
|
130
132
|
has_rdoc: true
|
@@ -159,18 +161,19 @@ specification_version: 3
|
|
159
161
|
summary: Distributed testing toolkit
|
160
162
|
test_files:
|
161
163
|
- test/pipe_test.rb
|
164
|
+
- test/test_helper.rb
|
162
165
|
- test/ssh_test.rb
|
166
|
+
- test/message_test.rb
|
167
|
+
- test/master_test.rb
|
168
|
+
- test/fixtures/write_file.rb
|
169
|
+
- test/fixtures/slow.rb
|
170
|
+
- test/fixtures/write_file_with_pending_spec.rb
|
171
|
+
- test/fixtures/write_file_spec.rb
|
172
|
+
- test/fixtures/features/step_definitions.rb
|
173
|
+
- test/fixtures/hello_world.rb
|
163
174
|
- test/fixtures/write_file_alternate_spec.rb
|
164
175
|
- test/fixtures/sync_test.rb
|
165
|
-
- test/fixtures/hello_world.rb
|
166
|
-
- test/fixtures/features/step_definitions.rb
|
167
176
|
- test/fixtures/assert_true.rb
|
168
|
-
- test/fixtures/slow.rb
|
169
|
-
- test/fixtures/write_file_spec.rb
|
170
|
-
- test/fixtures/write_file_with_pending_spec.rb
|
171
|
-
- test/fixtures/write_file.rb
|
172
|
-
- test/message_test.rb
|
173
|
-
- test/test_helper.rb
|
174
|
-
- test/master_test.rb
|
175
177
|
- test/runner_test.rb
|
178
|
+
- test/sync_test.rb
|
176
179
|
- test/worker_test.rb
|