jperkins-deep_test 1.2.2
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/CHANGELOG +47 -0
- data/README.rdoc +228 -0
- data/Rakefile +247 -0
- data/bin/deep_test +15 -0
- data/lib/deep_test.rb +91 -0
- data/lib/deep_test/database/mysql_setup_listener.rb +112 -0
- data/lib/deep_test/database/postgresql_setup_listener.rb +116 -0
- data/lib/deep_test/database/setup_listener.rb +125 -0
- data/lib/deep_test/deadlock_detector.rb +7 -0
- data/lib/deep_test/distributed/dispatch_controller.rb +53 -0
- data/lib/deep_test/distributed/drb_client_connection_info.rb +15 -0
- data/lib/deep_test/distributed/filename_resolver.rb +40 -0
- data/lib/deep_test/distributed/master_test_server.rb +52 -0
- data/lib/deep_test/distributed/multi_test_server_proxy.rb +44 -0
- data/lib/deep_test/distributed/null_work_unit.rb +12 -0
- data/lib/deep_test/distributed/remote_worker_client.rb +54 -0
- data/lib/deep_test/distributed/remote_worker_server.rb +82 -0
- data/lib/deep_test/distributed/rsync.rb +37 -0
- data/lib/deep_test/distributed/show_status.rhtml +41 -0
- data/lib/deep_test/distributed/test_server.rb +78 -0
- data/lib/deep_test/distributed/test_server_status.rb +9 -0
- data/lib/deep_test/distributed/test_server_workers.rb +24 -0
- data/lib/deep_test/distributed/throughput_runner.rb +42 -0
- data/lib/deep_test/distributed/throughput_statistics.rb +26 -0
- data/lib/deep_test/distributed/throughput_worker_client.rb +19 -0
- data/lib/deep_test/extensions/drb_extension.rb +34 -0
- data/lib/deep_test/extensions/object_extension.rb +40 -0
- data/lib/deep_test/listener_list.rb +17 -0
- data/lib/deep_test/local_workers.rb +55 -0
- data/lib/deep_test/logger.rb +17 -0
- data/lib/deep_test/marshallable_exception_wrapper.rb +44 -0
- data/lib/deep_test/metrics/gatherer.rb +67 -0
- data/lib/deep_test/metrics/queue_lock_wait_time_measurement.rb +133 -0
- data/lib/deep_test/null_worker_listener.rb +62 -0
- data/lib/deep_test/option.rb +60 -0
- data/lib/deep_test/options.rb +110 -0
- data/lib/deep_test/process_orchestrator.rb +49 -0
- data/lib/deep_test/rake_tasks.rb +11 -0
- data/lib/deep_test/result_reader.rb +36 -0
- data/lib/deep_test/rspec_detector.rb +21 -0
- data/lib/deep_test/server.rb +75 -0
- data/lib/deep_test/spec.rb +13 -0
- data/lib/deep_test/spec/extensions/example_group_methods.rb +64 -0
- data/lib/deep_test/spec/extensions/example_methods.rb +46 -0
- data/lib/deep_test/spec/extensions/options.rb +43 -0
- data/lib/deep_test/spec/extensions/reporter.rb +29 -0
- data/lib/deep_test/spec/extensions/spec_task.rb +20 -0
- data/lib/deep_test/spec/runner.rb +57 -0
- data/lib/deep_test/spec/work_result.rb +33 -0
- data/lib/deep_test/spec/work_unit.rb +59 -0
- data/lib/deep_test/test.rb +10 -0
- data/lib/deep_test/test/extensions/error.rb +14 -0
- data/lib/deep_test/test/runner.rb +24 -0
- data/lib/deep_test/test/supervised_test_suite.rb +49 -0
- data/lib/deep_test/test/work_result.rb +34 -0
- data/lib/deep_test/test/work_unit.rb +40 -0
- data/lib/deep_test/test_task.rb +47 -0
- data/lib/deep_test/ui/console.rb +76 -0
- data/lib/deep_test/ui/null.rb +17 -0
- data/lib/deep_test/warlock.rb +134 -0
- data/lib/deep_test/worker.rb +57 -0
- data/script/internal/run_test_suite.rb +7 -0
- data/script/public/master_test_server.rb +24 -0
- data/script/public/test_server.rb +18 -0
- data/script/public/test_throughput.rb +29 -0
- data/spec/deep_test/option_spec.rb +33 -0
- data/spec/deep_test/options_spec.rb +183 -0
- data/spec/deep_test/spec/extensions/example_group_methods_spec.rb +48 -0
- data/spec/deep_test/spec/extensions/example_methods_spec.rb +61 -0
- data/spec/deep_test/spec/extensions/options_spec.rb +23 -0
- data/spec/deep_test/spec/extensions/reporter_spec.rb +28 -0
- data/spec/deep_test/spec/extensions/spec_task_spec.rb +36 -0
- data/spec/deep_test/spec/runner_spec.rb +106 -0
- data/spec/deep_test/spec/work_result_spec.rb +14 -0
- data/spec/deep_test/spec/work_unit_spec.rb +78 -0
- data/spec/spec_helper.rb +59 -0
- data/spec/thread_worker.rb +25 -0
- data/test/deep_test/database/mysql_setup_listener_test.rb +14 -0
- data/test/deep_test/distributed/dispatch_controller_test.rb +209 -0
- data/test/deep_test/distributed/drb_client_connection_info_test.rb +42 -0
- data/test/deep_test/distributed/filename_resolver_test.rb +52 -0
- data/test/deep_test/distributed/master_test_server_test.rb +32 -0
- data/test/deep_test/distributed/multi_test_server_proxy_test.rb +96 -0
- data/test/deep_test/distributed/remote_worker_client_test.rb +180 -0
- data/test/deep_test/distributed/remote_worker_server_test.rb +99 -0
- data/test/deep_test/distributed/rsync_test.rb +67 -0
- data/test/deep_test/distributed/test_server_test.rb +94 -0
- data/test/deep_test/distributed/test_server_workers_test.rb +26 -0
- data/test/deep_test/distributed/throughput_runner_test.rb +68 -0
- data/test/deep_test/distributed/throughput_worker_client_test.rb +28 -0
- data/test/deep_test/extensions/object_extension_test.rb +37 -0
- data/test/deep_test/listener_list_test.rb +20 -0
- data/test/deep_test/local_workers_test.rb +22 -0
- data/test/deep_test/logger_test.rb +11 -0
- data/test/deep_test/marshallable_exception_wrapper_test.rb +44 -0
- data/test/deep_test/metrics/gatherer_test.rb +66 -0
- data/test/deep_test/process_orchestrator_test.rb +11 -0
- data/test/deep_test/result_reader_test.rb +128 -0
- data/test/deep_test/server_test.rb +58 -0
- data/test/deep_test/test/extensions/error_test.rb +40 -0
- data/test/deep_test/test/runner_test.rb +7 -0
- data/test/deep_test/test/supervised_test_suite_test.rb +79 -0
- data/test/deep_test/test/work_result_test.rb +81 -0
- data/test/deep_test/test/work_unit_test.rb +61 -0
- data/test/deep_test/test_task_test.rb +43 -0
- data/test/deep_test/ui/console_test.rb +9 -0
- data/test/deep_test/warlock_test.rb +38 -0
- data/test/deep_test/worker_test.rb +94 -0
- data/test/failing.rake +11 -0
- data/test/failing.rb +7 -0
- data/test/fake_deadlock_error.rb +12 -0
- data/test/simple_test_blackboard.rb +45 -0
- data/test/simple_test_blackboard_test.rb +33 -0
- data/test/test_factory.rb +74 -0
- data/test/test_helper.rb +15 -0
- data/test/test_task_test.rb +72 -0
- metadata +214 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class DispatchController
|
|
4
|
+
def initialize(options, receivers)
|
|
5
|
+
@options = options
|
|
6
|
+
@receivers = receivers
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def dispatch(method_name, *args)
|
|
10
|
+
dispatch_with_options(method_name, {}, *args)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def dispatch_with_options(method_name, options, *args)
|
|
14
|
+
raise NoDispatchReceiversError if @receivers.empty?
|
|
15
|
+
|
|
16
|
+
@options.ui_instance.dispatch_starting(method_name)
|
|
17
|
+
|
|
18
|
+
threads = @receivers.map do |r|
|
|
19
|
+
Thread.new do
|
|
20
|
+
Thread.current[:receiver] = r
|
|
21
|
+
Timeout.timeout(@options.timeout_in_seconds) do
|
|
22
|
+
r.send method_name, *args
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
results = []
|
|
28
|
+
threads.each do |t|
|
|
29
|
+
begin
|
|
30
|
+
results << t.value
|
|
31
|
+
rescue Timeout::Error
|
|
32
|
+
@receivers.delete t[:receiver]
|
|
33
|
+
DeepTest.logger.error "Timeout dispatching #{method_name} to #{t[:receiver].__drburi}"
|
|
34
|
+
rescue DRb::DRbConnError
|
|
35
|
+
@receivers.delete t[:receiver]
|
|
36
|
+
unless options[:ignore_connection_error]
|
|
37
|
+
DeepTest.logger.error "Connection Refused dispatching #{method_name} to #{t[:receiver].__drburi}"
|
|
38
|
+
end
|
|
39
|
+
rescue Exception => e
|
|
40
|
+
@receivers.delete t[:receiver]
|
|
41
|
+
DeepTest.logger.error "Exception while dispatching #{method_name} to #{t[:receiver].__drburi} #{e.message}"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
results
|
|
46
|
+
ensure
|
|
47
|
+
@options.ui_instance.dispatch_finished(method_name)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class NoDispatchReceiversError < StandardError; end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class DRbClientConnectionInfo
|
|
4
|
+
attr_reader :address
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
info = Thread.current['DRb']
|
|
8
|
+
raise "No DRb client found" unless info && info['client']
|
|
9
|
+
peeraddr = info['client'].peeraddr
|
|
10
|
+
DeepTest.logger.debug("DRbClientConnection info: #{peeraddr.inspect}")
|
|
11
|
+
@address = peeraddr[3]
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class FilenameResolver
|
|
4
|
+
def initialize(base_path)
|
|
5
|
+
@base_path = base_path
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def resolve(filename)
|
|
9
|
+
return resolve("/" + filename) unless filename[0] == ?/
|
|
10
|
+
|
|
11
|
+
return filename.sub(@cached_replaced_path, @base_path) if @cached_replaced_path
|
|
12
|
+
|
|
13
|
+
each_potential_filename(filename) do |potential_filename|
|
|
14
|
+
if File.exist?(potential_filename)
|
|
15
|
+
cache_resolution(filename, potential_filename)
|
|
16
|
+
return potential_filename
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
raise "Filename resolution failed. Cannot resolve #{filename} within #{@base_path}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def cache_resolution(original_filename, resolved_filename)
|
|
24
|
+
@cached_replaced_path = original_filename.sub(
|
|
25
|
+
resolved_filename.sub(@base_path, ""), ""
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def each_potential_filename(filename)
|
|
30
|
+
basename = File.basename(filename)
|
|
31
|
+
dirs = File.dirname(filename).split('/')
|
|
32
|
+
|
|
33
|
+
begin
|
|
34
|
+
dirs.shift
|
|
35
|
+
yield [@base_path, dirs, basename].flatten.join('/')
|
|
36
|
+
end until dirs.empty?
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class MasterTestServer
|
|
4
|
+
include ERB::Util
|
|
5
|
+
|
|
6
|
+
STATUS_PORT = 4020 unless defined?(STATUS_PORT)
|
|
7
|
+
|
|
8
|
+
attr_reader :servers
|
|
9
|
+
|
|
10
|
+
def initialize(servers)
|
|
11
|
+
@servers = servers
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def show_status(req, res)
|
|
15
|
+
template = File.read(File.dirname(__FILE__) + "/show_status.rhtml")
|
|
16
|
+
res.body = ERB.new(template).result(binding)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_server_statuses
|
|
20
|
+
@servers.map do |s|
|
|
21
|
+
status = begin
|
|
22
|
+
s.status
|
|
23
|
+
rescue Exception => e
|
|
24
|
+
e
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
[s.__drburi, status]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.start(uri, server_uris)
|
|
32
|
+
master = start_drb(uri, server_uris)
|
|
33
|
+
start_http(master)
|
|
34
|
+
DeepTest.logger.info "MasterTestServer listening at #{DRb.uri}"
|
|
35
|
+
DRb.thread.join
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.start_drb(uri, server_uris)
|
|
39
|
+
servers = server_uris.map {|server_uri| DRbObject.new_with_uri server_uri}
|
|
40
|
+
master = DeepTest::Distributed::MasterTestServer.new(servers)
|
|
41
|
+
DRb.start_service(uri, master)
|
|
42
|
+
master
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.start_http(master)
|
|
46
|
+
s = WEBrick::HTTPServer.new :Port => STATUS_PORT
|
|
47
|
+
s.mount_proc("/", &master.method(:show_status))
|
|
48
|
+
Thread.new {s.start}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class MultiTestServerProxy
|
|
4
|
+
def initialize(options, slaves)
|
|
5
|
+
DeepTest.logger.debug "MultiTestServerProxy#initialize #{slaves.length} slaves"
|
|
6
|
+
@slave_controller = DispatchController.new(options, slaves)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def spawn_worker_server(options)
|
|
10
|
+
DeepTest.logger.debug "dispatch spawn_worker_server for #{options.origin_hostname}"
|
|
11
|
+
WorkerServerProxy.new options,
|
|
12
|
+
@slave_controller.dispatch(:spawn_worker_server,
|
|
13
|
+
options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def sync(options)
|
|
17
|
+
DeepTest.logger.debug "dispatch sync for #{options.origin_hostname}"
|
|
18
|
+
@slave_controller.dispatch(:sync, options)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class WorkerServerProxy
|
|
22
|
+
def initialize(options, slaves)
|
|
23
|
+
DeepTest.logger.debug "WorkerServerProxy#initialize #{slaves.inspect}"
|
|
24
|
+
@slave_controller = DispatchController.new(options, slaves)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def load_files(files)
|
|
28
|
+
DeepTest.logger.debug "dispatch load_files"
|
|
29
|
+
@slave_controller.dispatch(:load_files, files)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def start_all
|
|
33
|
+
DeepTest.logger.debug "dispatch start_all"
|
|
34
|
+
@slave_controller.dispatch(:start_all)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def stop_all
|
|
38
|
+
DeepTest.logger.debug "dispatch stop_all"
|
|
39
|
+
@slave_controller.dispatch_with_options(:stop_all, :ignore_connection_error => true)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class RemoteWorkerClient
|
|
4
|
+
def initialize(options, test_server, failover_workers)
|
|
5
|
+
@failover_workers = failover_workers
|
|
6
|
+
@options = options
|
|
7
|
+
@test_server = test_server
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def load_files(filelist)
|
|
11
|
+
@options.new_listener_list.before_sync
|
|
12
|
+
|
|
13
|
+
t = Thread.new do
|
|
14
|
+
@test_server.sync(@options)
|
|
15
|
+
@worker_server = @test_server.spawn_worker_server(@options)
|
|
16
|
+
@worker_server.load_files filelist
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
filelist.each {|f| load f}
|
|
20
|
+
|
|
21
|
+
begin
|
|
22
|
+
t.join
|
|
23
|
+
rescue => e
|
|
24
|
+
# The failover here doesn't invoke load_files on the failover_workers
|
|
25
|
+
# because they will be LocalWorkers, which fork from the current
|
|
26
|
+
# process. The fact that we depend in this here is damp...
|
|
27
|
+
#
|
|
28
|
+
fail_over("load_files", e)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def start_all
|
|
33
|
+
@worker_server.start_all
|
|
34
|
+
rescue => e
|
|
35
|
+
raise if failed_over?
|
|
36
|
+
fail_over("start_all", e)
|
|
37
|
+
retry
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def stop_all
|
|
41
|
+
@worker_server.stop_all
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def fail_over(method, exception)
|
|
45
|
+
@options.ui_instance.distributed_failover_to_local(method, exception)
|
|
46
|
+
@worker_server = @failover_workers
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def failed_over?
|
|
50
|
+
@worker_server == @failover_workers
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class RemoteWorkerServer
|
|
4
|
+
include DRb::DRbUndumped
|
|
5
|
+
|
|
6
|
+
MERCY_KILLING_GRACE_PERIOD = 10 * 60 unless defined?(MERCY_KILLING_GRACE_PERIOD)
|
|
7
|
+
|
|
8
|
+
def initialize(base_path, workers)
|
|
9
|
+
@base_path = base_path
|
|
10
|
+
@workers = workers
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def launch_mercy_killer(grace_period)
|
|
14
|
+
Thread.new do
|
|
15
|
+
sleep grace_period
|
|
16
|
+
exit(0) unless workers_started?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def load_files(files)
|
|
21
|
+
Dir.chdir @base_path
|
|
22
|
+
resolver = FilenameResolver.new(@base_path)
|
|
23
|
+
files.each do |file|
|
|
24
|
+
load resolver.resolve(file)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def start_all
|
|
29
|
+
@workers_started = true
|
|
30
|
+
@workers.start_all
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def stop_all
|
|
34
|
+
Thread.new do
|
|
35
|
+
@workers.stop_all
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def workers_started?
|
|
40
|
+
@workers_started
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.warlock
|
|
44
|
+
@warlock ||= DeepTest::Warlock.new
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.running_server_count
|
|
48
|
+
@warlock.demon_count if @warlock
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.stop_all
|
|
52
|
+
@warlock.stop_all if @warlock
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.start(address, base_path, workers, grace_period = MERCY_KILLING_GRACE_PERIOD)
|
|
56
|
+
innie, outie = IO.pipe
|
|
57
|
+
|
|
58
|
+
warlock.start("RemoteWorkerServer") do
|
|
59
|
+
innie.close
|
|
60
|
+
|
|
61
|
+
server = new(base_path, workers)
|
|
62
|
+
|
|
63
|
+
DRb.start_service("drubyall://#{address}:0", server)
|
|
64
|
+
DeepTest.logger.info "RemoteWorkerServer started at #{DRb.uri}"
|
|
65
|
+
|
|
66
|
+
outie.write DRb.uri
|
|
67
|
+
outie.close
|
|
68
|
+
|
|
69
|
+
server.launch_mercy_killer(grace_period)
|
|
70
|
+
|
|
71
|
+
DRb.thread.join
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
outie.close
|
|
75
|
+
uri = innie.gets
|
|
76
|
+
innie.close
|
|
77
|
+
DRbObject.new_with_uri(uri)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module DeepTest
|
|
2
|
+
module Distributed
|
|
3
|
+
class RSync
|
|
4
|
+
def self.sync(connection_info, options, destination)
|
|
5
|
+
command = Args.new(connection_info, options).command(destination)
|
|
6
|
+
DeepTest.logger.debug("rsycing: #{command}")
|
|
7
|
+
successful = system command
|
|
8
|
+
raise "RSync Failed!!" unless successful
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class Args
|
|
12
|
+
def initialize(connection_info, options)
|
|
13
|
+
@connection_info = connection_info
|
|
14
|
+
@options = options
|
|
15
|
+
@sync_options = options.sync_options
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def command(destination)
|
|
19
|
+
# The '/' after source tells rsync to copy the contents
|
|
20
|
+
# of source to destination, rather than the source directory
|
|
21
|
+
# itself
|
|
22
|
+
"rsync -az --delete #{@sync_options[:rsync_options]} #{source_location}/ #{destination}".strip.squeeze(" ")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def source_location
|
|
26
|
+
source = ""
|
|
27
|
+
unless @sync_options[:local]
|
|
28
|
+
source << @sync_options[:username] << '@' if @sync_options[:username]
|
|
29
|
+
source << @connection_info.address
|
|
30
|
+
source << (@sync_options[:daemon] ? '::' : ':')
|
|
31
|
+
end
|
|
32
|
+
source << @sync_options[:source]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<title>DeepTest Test Server Status</title>
|
|
4
|
+
<style>
|
|
5
|
+
.ok {
|
|
6
|
+
background-color: #AAFFAA;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.error {
|
|
10
|
+
background-color: #FFAAAA;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
</style>
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<h1>DeepTest Test Server Status</h1>
|
|
17
|
+
<table>
|
|
18
|
+
<tr>
|
|
19
|
+
<th>Mirror Server</th>
|
|
20
|
+
<th>Bound To</th>
|
|
21
|
+
<th>Workers / Client</th>
|
|
22
|
+
<th>Clients</th>
|
|
23
|
+
</tr>
|
|
24
|
+
<% test_server_statuses.each do |uri, status|
|
|
25
|
+
if Exception === status %>
|
|
26
|
+
<tr class="error">
|
|
27
|
+
<td><%=h uri %></td>
|
|
28
|
+
<td colspan="3"><%=h status.message %></td>
|
|
29
|
+
</tr>
|
|
30
|
+
<% else %>
|
|
31
|
+
<tr class="ok">
|
|
32
|
+
<td><%=h uri %></td>
|
|
33
|
+
<td><%=h status.binding_uri %></td>
|
|
34
|
+
<td><%=h status.number_of_workers %></td>
|
|
35
|
+
<td><%=h status.remote_worker_server_count %></td>
|
|
36
|
+
</tr>
|
|
37
|
+
<% end
|
|
38
|
+
end %>
|
|
39
|
+
</table>
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|