deep_test_pre 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.
Files changed (98) hide show
  1. data/CHANGELOG +47 -0
  2. data/README.rdoc +199 -0
  3. data/Rakefile +137 -0
  4. data/lib/deep_test.rb +78 -0
  5. data/lib/deep_test/agent.rb +108 -0
  6. data/lib/deep_test/central_command.rb +165 -0
  7. data/lib/deep_test/cpu_info.rb +22 -0
  8. data/lib/deep_test/database/mysql_setup_listener.rb +112 -0
  9. data/lib/deep_test/database/setup_listener.rb +116 -0
  10. data/lib/deep_test/deadlock_detector.rb +7 -0
  11. data/lib/deep_test/demon.rb +25 -0
  12. data/lib/deep_test/distributed/beachhead.rb +104 -0
  13. data/lib/deep_test/distributed/dispatch_controller.rb +60 -0
  14. data/lib/deep_test/distributed/establish_beachhead.rb +19 -0
  15. data/lib/deep_test/distributed/filename_resolver.rb +40 -0
  16. data/lib/deep_test/distributed/landing_fleet.rb +30 -0
  17. data/lib/deep_test/distributed/landing_ship.rb +60 -0
  18. data/lib/deep_test/distributed/remote_deployment.rb +56 -0
  19. data/lib/deep_test/distributed/rsync.rb +50 -0
  20. data/lib/deep_test/distributed/shell_environment.rb +50 -0
  21. data/lib/deep_test/distributed/ssh_client_connection_info.rb +14 -0
  22. data/lib/deep_test/extensions/object_extension.rb +40 -0
  23. data/lib/deep_test/failure_message.rb +19 -0
  24. data/lib/deep_test/lib_root.rb +4 -0
  25. data/lib/deep_test/listener_list.rb +17 -0
  26. data/lib/deep_test/local_deployment.rb +46 -0
  27. data/lib/deep_test/logger.rb +32 -0
  28. data/lib/deep_test/main.rb +41 -0
  29. data/lib/deep_test/marshallable_exception_wrapper.rb +44 -0
  30. data/lib/deep_test/metrics/data.rb +34 -0
  31. data/lib/deep_test/metrics/measurement.rb +39 -0
  32. data/lib/deep_test/null_listener.rb +62 -0
  33. data/lib/deep_test/options.rb +113 -0
  34. data/lib/deep_test/proxy_io.rb +77 -0
  35. data/lib/deep_test/rake_tasks.rb +13 -0
  36. data/lib/deep_test/result_reader.rb +40 -0
  37. data/lib/deep_test/rspec_detector.rb +21 -0
  38. data/lib/deep_test/spec.rb +17 -0
  39. data/lib/deep_test/spec/extensions/example_group_methods.rb +64 -0
  40. data/lib/deep_test/spec/extensions/example_methods.rb +52 -0
  41. data/lib/deep_test/spec/extensions/options.rb +43 -0
  42. data/lib/deep_test/spec/extensions/spec_task.rb +21 -0
  43. data/lib/deep_test/spec/runner.rb +72 -0
  44. data/lib/deep_test/spec/work_result.rb +35 -0
  45. data/lib/deep_test/spec/work_unit.rb +59 -0
  46. data/lib/deep_test/test.rb +10 -0
  47. data/lib/deep_test/test/extensions/error.rb +14 -0
  48. data/lib/deep_test/test/run_test_suite.rb +5 -0
  49. data/lib/deep_test/test/runner.rb +24 -0
  50. data/lib/deep_test/test/supervised_test_suite.rb +48 -0
  51. data/lib/deep_test/test/work_result.rb +35 -0
  52. data/lib/deep_test/test/work_unit.rb +40 -0
  53. data/lib/deep_test/test_task.rb +47 -0
  54. data/lib/deep_test/ui/console.rb +74 -0
  55. data/lib/deep_test/ui/null.rb +17 -0
  56. data/lib/deep_test/warlock.rb +146 -0
  57. data/lib/telegraph.rb +29 -0
  58. data/lib/telegraph/ack_sequence.rb +14 -0
  59. data/lib/telegraph/logging.rb +20 -0
  60. data/lib/telegraph/message.rb +39 -0
  61. data/lib/telegraph/operator.rb +47 -0
  62. data/lib/telegraph/switchboard.rb +57 -0
  63. data/lib/telegraph/wire.rb +73 -0
  64. data/test/deep_test/agent_test.rb +175 -0
  65. data/test/deep_test/central_command_test.rb +147 -0
  66. data/test/deep_test/cpu_info_test.rb +33 -0
  67. data/test/deep_test/database/mysql_setup_listener_test.rb +18 -0
  68. data/test/deep_test/demon_test.rb +23 -0
  69. data/test/deep_test/distributed/beachhead_test.rb +67 -0
  70. data/test/deep_test/distributed/dispatch_controller_test.rb +162 -0
  71. data/test/deep_test/distributed/filename_resolver_test.rb +56 -0
  72. data/test/deep_test/distributed/landing_fleet_test.rb +55 -0
  73. data/test/deep_test/distributed/landing_ship_test.rb +48 -0
  74. data/test/deep_test/distributed/remote_deployment_test.rb +134 -0
  75. data/test/deep_test/distributed/rsync_test.rb +47 -0
  76. data/test/deep_test/distributed/shell_environment_test.rb +108 -0
  77. data/test/deep_test/distributed/ssh_client_connection_info_test.rb +34 -0
  78. data/test/deep_test/extensions/object_extension_test.rb +37 -0
  79. data/test/deep_test/listener_list_test.rb +22 -0
  80. data/test/deep_test/local_deployment_test.rb +19 -0
  81. data/test/deep_test/logger_test.rb +38 -0
  82. data/test/deep_test/main_test.rb +12 -0
  83. data/test/deep_test/marshallable_exception_wrapper_test.rb +46 -0
  84. data/test/deep_test/metrics/data_test.rb +22 -0
  85. data/test/deep_test/metrics/measurement_test.rb +18 -0
  86. data/test/deep_test/proxy_io_test.rb +104 -0
  87. data/test/deep_test/result_reader_test.rb +128 -0
  88. data/test/deep_test/test/extensions/error_test.rb +42 -0
  89. data/test/deep_test/test/runner_test.rb +11 -0
  90. data/test/deep_test/test/supervised_test_suite_test.rb +107 -0
  91. data/test/deep_test/test/work_result_test.rb +85 -0
  92. data/test/deep_test/test/work_unit_test.rb +63 -0
  93. data/test/deep_test/test_task_test.rb +15 -0
  94. data/test/deep_test/ui/console_test.rb +13 -0
  95. data/test/deep_test/warlock_test.rb +40 -0
  96. data/test/test_helper.rb +30 -0
  97. data/test/test_task_test.rb +75 -0
  98. metadata +156 -0
@@ -0,0 +1,162 @@
1
+ require File.dirname(__FILE__) + "/../../test_helper"
2
+
3
+ module DeepTest
4
+ module Distributed
5
+ unit_tests do
6
+ test "dispatch invokes each receiver once" do
7
+ receiver_1, receiver_2 = mock, mock
8
+
9
+ controller = DispatchController.new(
10
+ Options.new({:ui => "UI::Null"}),
11
+ [receiver_1, receiver_2]
12
+ )
13
+
14
+ receiver_1.expects(:a_method).with(:args)
15
+ receiver_2.expects(:a_method).with(:args)
16
+
17
+ controller.dispatch(:a_method, :args)
18
+ end
19
+
20
+ test "dispatch returns array of all results" do
21
+ receiver_1, receiver_2 = mock, mock
22
+
23
+ controller = DispatchController.new(
24
+ Options.new({:ui => "UI::Null"}),
25
+ [receiver_1, receiver_2]
26
+ )
27
+
28
+ receiver_1.expects(:a_method).returns(:result_1)
29
+ receiver_2.expects(:a_method).returns(:result_2)
30
+
31
+ results = controller.dispatch(:a_method)
32
+ assert_equal 2, results.size
33
+ assert_equal [:result_1, :result_2].to_set, results.to_set
34
+ end
35
+
36
+ test "dispatch calls all receivers in parallel" do
37
+ options = Options.new({:ui => "UI::Null"})
38
+ waiter = Waiter.new(tracker = Tracker.new)
39
+
40
+ Timeout.timeout(1) do
41
+ DispatchController.new(options,[tracker, waiter]).
42
+ dispatch(:tracked_method)
43
+ end
44
+
45
+ waiter = Waiter.new(tracker = Tracker.new)
46
+
47
+ Timeout.timeout(1) do
48
+ DispatchController.new(options,[waiter, tracker]).
49
+ dispatch(:tracked_method)
50
+ end
51
+ end
52
+
53
+ test "receiver is dropped when any exception occurs" do
54
+ receiver = mock
55
+ receiver.expects(:method_call).raises(Exception)
56
+
57
+ controller = DispatchController.new(
58
+ Options.new({:ui => "UI::Null"}),
59
+ [receiver]
60
+ )
61
+
62
+ controller.dispatch(:method_call)
63
+ assert_raises(NoDispatchReceiversError) {controller.dispatch(:another_call)}
64
+ end
65
+
66
+ test "error is printed with backtrace when it occurrs" do
67
+ e = Exception.new("message")
68
+ e.set_backtrace %w[file1:1 file2:2]
69
+ receiver = mock
70
+ receiver.expects(:method_call).raises(e)
71
+
72
+ controller = DispatchController.new(
73
+ Options.new({:ui => "UI::Null"}),
74
+ [receiver]
75
+ )
76
+
77
+ Timewarp.freeze("2009-09-22 12:01:33") do
78
+ controller.dispatch(:method_call)
79
+ assert_equal <<-end_log, DeepTest.logger.logged_output
80
+ [DeepTest@#{Socket.gethostname}] 2009-09-22 12:01:33 Exception while dispatching method_call to #{receiver.inspect}:
81
+ [DeepTest@#{Socket.gethostname}] 2009-09-22 12:01:33 Exception: message
82
+ [DeepTest@#{Socket.gethostname}] 2009-09-22 12:01:33 file1:1
83
+ [DeepTest@#{Socket.gethostname}] 2009-09-22 12:01:33 file2:2
84
+ end_log
85
+ end
86
+ end
87
+
88
+ test "dispatch calls notifies ui of start and stop of dispatch" do
89
+ options = Options.new({:ui => "UI::Null"})
90
+ controller = DispatchController.new(
91
+ options, [stub_everything]
92
+ )
93
+
94
+ options.ui_instance.expects(:dispatch_starting).with(:method_name)
95
+ options.ui_instance.expects(:dispatch_finished).with(:method_name)
96
+
97
+ controller.dispatch(:method_name)
98
+ end
99
+
100
+ test "dispatch calls notifies ui dispatch end in case of an error" do
101
+ options = Options.new({:ui => "UI::Null"})
102
+ controller = DispatchController.new(
103
+ options, [receiver = mock]
104
+ )
105
+ receiver.expects(:method_name).raises("An Error")
106
+
107
+ options.ui_instance.expects(:dispatch_starting).with(:method_name)
108
+ options.ui_instance.expects(:dispatch_finished).with(:method_name)
109
+
110
+ begin
111
+ controller.dispatch(:method_name)
112
+ rescue RuntimeError => e
113
+ raise unless e.message == "An Error"
114
+ end
115
+ end
116
+
117
+ test "error is raised if dispatch to no receivers in attempted" do
118
+ options = Options.new({:ui => "UI::Null"})
119
+ controller = DispatchController.new(
120
+ options, []
121
+ )
122
+
123
+ assert_raises(NoDispatchReceiversError) do
124
+ controller.dispatch(:any_method)
125
+ end
126
+ end
127
+
128
+ class Tracker
129
+ def initialize
130
+ @mutex = Mutex.new
131
+ @condvar = ConditionVariable.new
132
+ end
133
+
134
+ def tracked_method
135
+ @mutex.synchronize do
136
+ @tracked_method_called = true
137
+ @condvar.broadcast
138
+ end
139
+ end
140
+
141
+ def wait_for_tracked_method
142
+ @mutex.synchronize do
143
+ loop do
144
+ return if @tracked_method_called
145
+ @condvar.wait(@mutex)
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ class Waiter
152
+ def initialize(tracker)
153
+ @tracker = tracker
154
+ end
155
+
156
+ def tracked_method
157
+ @tracker.wait_for_tracked_method
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + "/../../test_helper"
2
+
3
+ module DeepTest
4
+ module Distributed
5
+ unit_tests do
6
+ test "should strip off directories until file exists in base path" do
7
+ resolver = FilenameResolver.new("base_path")
8
+
9
+ File.expects(:exist?).with("base_path/a/b/c/d.rb").returns(false)
10
+ File.expects(:exist?).with("base_path/b/c/d.rb").returns(false)
11
+ File.expects(:exist?).with("base_path/c/d.rb").returns(true)
12
+
13
+ assert_equal "base_path/c/d.rb", resolver.resolve("/a/b/c/d.rb")
14
+ end
15
+
16
+ test "should resolve relative names starting at first element" do
17
+ resolver = FilenameResolver.new("base_path")
18
+
19
+ File.expects(:exist?).with("base_path/a/b/c/d.rb").returns(true)
20
+
21
+ assert_equal "base_path/a/b/c/d.rb", resolver.resolve("a/b/c/d.rb")
22
+ end
23
+
24
+ test "should resolve relative names the same each time" do
25
+ resolver = FilenameResolver.new("base_path")
26
+
27
+ File.expects(:exist?).with("base_path/a/b/c/d.rb").returns(true)
28
+
29
+ assert_equal "base_path/a/b/c/d.rb", resolver.resolve("a/b/c/d.rb")
30
+ assert_equal "base_path/a/b/c/d.rb", resolver.resolve("a/b/c/d.rb")
31
+ end
32
+
33
+ test "should raise exception if filename can't be resolved" do
34
+ resolver = FilenameResolver.new("base_path")
35
+
36
+ File.expects(:exist?).with("base_path/a/b/c/d.rb").returns(false)
37
+ File.expects(:exist?).with("base_path/b/c/d.rb").returns(false)
38
+ File.expects(:exist?).with("base_path/c/d.rb").returns(false)
39
+ File.expects(:exist?).with("base_path/d.rb").returns(false)
40
+
41
+ assert_raises(RuntimeError) { resolver.resolve("/a/b/c/d.rb") }
42
+ end
43
+
44
+ test "should remember how many directories to strip off after first resolution" do
45
+ resolver = FilenameResolver.new("base_path")
46
+
47
+ File.expects(:exist?).with("base_path/a/b/c/d.rb").returns(false)
48
+ File.expects(:exist?).with("base_path/b/c/d.rb").returns(true)
49
+
50
+ resolver.resolve("/a/b/c/d.rb")
51
+
52
+ assert_equal "base_path/x/y/z.rb", resolver.resolve("/a/x/y/z.rb")
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,55 @@
1
+ require File.dirname(__FILE__) + "/../../test_helper"
2
+
3
+ module DeepTest
4
+ module Distributed
5
+ unit_tests do
6
+ test "push_code is invoked on all servers" do
7
+ server_1, server_2 = mock, mock
8
+ options = Options.new({:ui => "UI::Null"})
9
+
10
+ fleet = LandingFleet.new(options, [server_1, server_2])
11
+
12
+ server_1.expects(:push_code).with(options)
13
+ server_2.expects(:push_code).with(options)
14
+
15
+ fleet.push_code(options)
16
+ end
17
+
18
+ test "establish_beachhead is invoked on all server" do
19
+ server_1, server_2 = mock, mock
20
+ options = Options.new({:ui => "UI::Null"})
21
+
22
+ fleet = LandingFleet.new(options, [server_1, server_2])
23
+
24
+ server_1.expects(:establish_beachhead).with(options)
25
+ server_2.expects(:establish_beachhead).with(options)
26
+
27
+ fleet.establish_beachhead(options)
28
+ end
29
+
30
+ test "load_files is invoked on all server" do
31
+ server_1, server_2 = mock, mock
32
+ options = Options.new({:ui => "UI::Null"})
33
+
34
+ fleet = LandingFleet.new(options, [server_1, server_2])
35
+
36
+ server_1.expects(:load_files).with(['a'])
37
+ server_2.expects(:load_files).with(['a'])
38
+
39
+ fleet.load_files(['a'])
40
+ end
41
+
42
+ test "deploy_agents is invoked on all server" do
43
+ server_1, server_2 = mock, mock
44
+ options = Options.new({:ui => "UI::Null"})
45
+
46
+ fleet = LandingFleet.new(options, [server_1, server_2])
47
+
48
+ server_1.expects(:deploy_agents)
49
+ server_2.expects(:deploy_agents)
50
+
51
+ fleet.deploy_agents
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,48 @@
1
+ require File.dirname(__FILE__) + "/../../test_helper"
2
+
3
+ module DeepTest
4
+ module Distributed
5
+ unit_tests do
6
+ test "generates a local working copy path based on host and source of request" do
7
+ Socket.stubs(:gethostname).returns("myhost")
8
+ Telegraph::Wire.stubs(:connect).returns :wire
9
+ landing_ship = LandingShip.new(:address => "host")
10
+ options = Options.new(:sync_options => {:source => "/my/local/dir"})
11
+ RSync.expects(:push).with("host", options.sync_options, "/tmp/myhost_my_local_dir")
12
+ landing_ship.push_code(options)
13
+ end
14
+
15
+ test "establish_beachhead launches beachhead process on remote machine" do
16
+ Socket.stubs(:gethostname).returns("myhost")
17
+ Telegraph::Wire.stubs(:connect).returns :wire
18
+ landing_ship = LandingShip.new(:address => "remote_host")
19
+ options = Options.new(:sync_options => {:source => "/my/local/dir"})
20
+
21
+ landing_ship.expects(:`).with(
22
+ "ssh -4 remote_host " +
23
+ "'#{ShellEnvironment.like_login} && cd /tmp/myhost_my_local_dir && " +
24
+ "OPTIONS=#{options.to_command_line} " +
25
+ "ruby lib/deep_test/distributed/establish_beachhead.rb' 2>&1"
26
+ ).returns("blah blah\nBeachhead port: 9999\nblah")
27
+
28
+ landing_ship.establish_beachhead(options)
29
+ end
30
+
31
+ test "establish_beachhead launches beachhead process on remote machine with usernames specified in sync_options" do
32
+ Socket.stubs(:gethostname).returns("myhost")
33
+ Telegraph::Wire.stubs(:connect).returns :wire
34
+ landing_ship = LandingShip.new(:address => "remote_host")
35
+ options = Options.new(:sync_options => {:username => "me", :source => "/my/local/dir"})
36
+
37
+ landing_ship.expects(:`).with(
38
+ "ssh -4 remote_host -l me " +
39
+ "'#{ShellEnvironment.like_login} && cd /tmp/myhost_my_local_dir && " +
40
+ "OPTIONS=#{options.to_command_line} " +
41
+ "ruby lib/deep_test/distributed/establish_beachhead.rb' 2>&1"
42
+ ).returns("blah blah\nBeachhead port: 9999\nblah")
43
+
44
+ landing_ship.establish_beachhead(options)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,134 @@
1
+ require File.dirname(__FILE__) + "/../../test_helper"
2
+
3
+ module DeepTest
4
+ module Distributed
5
+ unit_tests do
6
+ test "load_files broadcasts before_sync" do
7
+ class FakeListener; end
8
+ deployment = RemoteDeployment.new(
9
+ options = Options.new(:listener => FakeListener,
10
+ :sync_options => {:source => "/tmp"}),
11
+ landing_ship = stub_everything,
12
+ failover_deployment = mock
13
+ )
14
+ FakeListener.any_instance.expects(:before_sync)
15
+ deployment.expects(:load)
16
+ deployment.load_files ["filelist"]
17
+
18
+ end
19
+
20
+ test "load_files pushes code to remote machines" do
21
+ deployment = RemoteDeployment.new(
22
+ options = Options.new(:sync_options => {:source => "/tmp"}),
23
+ landing_ship = stub_everything,
24
+ failover_deployment = mock
25
+ )
26
+
27
+ landing_ship.expects(:push_code).with(options)
28
+ deployment.expects(:load)
29
+ deployment.load_files ["filelist"]
30
+ end
31
+
32
+ test "load_files loads files locally" do
33
+ beachhead = stub_everything
34
+ deployment = RemoteDeployment.new(
35
+ Options.new(:sync_options => {:source => "/tmp"}),
36
+ landing_ship = stub_everything,
37
+ failover_deployment = mock
38
+ )
39
+
40
+ deployment.expects(:load).with("filelist")
41
+ deployment.load_files ["filelist"]
42
+ end
43
+
44
+ test "deploy_agents starts agents on agent server" do
45
+ deployment = RemoteDeployment.new(
46
+ options = Options.new(:sync_options => {:source => "/tmp"}),
47
+ landing_ship = stub_everything,
48
+ failover_deployment = mock
49
+ )
50
+
51
+ landing_ship.expects(:establish_beachhead).with(options)
52
+ deployment.expects(:load)
53
+ deployment.load_files ["filelist"]
54
+
55
+ landing_ship.expects(:deploy_agents)
56
+ deployment.deploy_agents
57
+ end
58
+
59
+ test "exception in deploy_agents causes failover to failover_deployment" do
60
+ deployment = RemoteDeployment.new(
61
+ options = Options.new(:sync_options => {:source => "/tmp"}, :ui => UI::Null),
62
+ landing_ship = stub_everything,
63
+ failover_deployment = mock
64
+ )
65
+
66
+ landing_ship.expects(:establish_beachhead).with(options)
67
+ landing_ship.expects(:load_files)
68
+ deployment.expects(:load)
69
+ deployment.load_files ["filelist"]
70
+
71
+ landing_ship.expects(:deploy_agents).raises("An Error")
72
+
73
+ failover_deployment.expects(:deploy_agents)
74
+ deployment.deploy_agents
75
+ end
76
+
77
+ test "exception in push_code causes failover to failover_deployment" do
78
+ deployment = RemoteDeployment.new(
79
+ options = Options.new(:sync_options => {:source => "/tmp"}, :ui => UI::Null),
80
+ landing_ship = mock,
81
+ failover_deployment = mock
82
+ )
83
+
84
+ landing_ship.expects(:push_code).raises("An Error")
85
+
86
+ deployment.expects(:load)
87
+ deployment.load_files ["filelist"]
88
+
89
+ failover_deployment.expects(:deploy_agents)
90
+ deployment.deploy_agents
91
+ end
92
+
93
+ test "exception in load_files causes failover to failover_deployment" do
94
+ deployment = RemoteDeployment.new(
95
+ options = Options.new(:sync_options => {:source => "/tmp"}, :ui => UI::Null),
96
+ landing_ship = mock,
97
+ failover_deployment = mock
98
+ )
99
+
100
+ landing_ship.expects(:push_code)
101
+ landing_ship.expects(:establish_beachhead)
102
+ landing_ship.expects(:load_files).raises("An Error")
103
+
104
+ deployment.expects(:load)
105
+ deployment.load_files ["filelist"]
106
+
107
+ failover_deployment.expects(:deploy_agents)
108
+ deployment.deploy_agents
109
+ end
110
+
111
+ test "exception from deploy_agents of failover_deployment is raised" do
112
+ deployment = RemoteDeployment.new(
113
+ options = Options.new(:sync_options => {:source => "/tmp"}, :ui => UI::Null),
114
+ landing_ship = stub_everything,
115
+ failover_deployment = mock
116
+ )
117
+
118
+ landing_ship.expects(:establish_beachhead).with(options)
119
+ landing_ship.expects(:load_files).raises("An Error")
120
+ deployment.expects(:load)
121
+ deployment.load_files ["filelist"]
122
+
123
+ failover_deployment.expects(:deploy_agents).raises("Failover Error").then.returns(nil)
124
+
125
+ begin
126
+ deployment.deploy_agents
127
+ flunk
128
+ rescue RuntimeError => e
129
+ assert_equal "Failover Error", e.message
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end