xli-dtr 0.0.4 → 0.0.5

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 (78) hide show
  1. data/README +6 -115
  2. data/Rakefile +22 -154
  3. data/TODO +16 -1
  4. data/bin/dtr +22 -61
  5. data/dtr.gemspec +7 -6
  6. data/lib/dtr/agent/brain.rb +66 -0
  7. data/lib/dtr/agent/herald.rb +50 -0
  8. data/lib/dtr/agent/runner.rb +100 -0
  9. data/lib/dtr/agent/sync_codebase.rb +44 -0
  10. data/lib/dtr/agent/sync_logger.rb +40 -0
  11. data/lib/dtr/agent/test_unit.rb +42 -0
  12. data/lib/dtr/agent/worker.rb +92 -0
  13. data/lib/dtr/agent/working_env_ext.rb +45 -0
  14. data/lib/dtr/agent.rb +37 -0
  15. data/lib/dtr/master.rb +40 -0
  16. data/lib/dtr/monitor.rb +37 -0
  17. data/lib/dtr/raketasks.rb +74 -13
  18. data/lib/dtr/shared/adapter.rb +112 -0
  19. data/lib/dtr/shared/configuration.rb +76 -0
  20. data/lib/dtr/shared/message_decorator.rb +28 -0
  21. data/lib/dtr/shared/ruby_ext.rb +153 -0
  22. data/lib/dtr/shared/service/agent.rb +33 -0
  23. data/lib/dtr/shared/service/file.rb +28 -0
  24. data/lib/dtr/shared/service/rinda.rb +40 -0
  25. data/lib/dtr/shared/service/runner.rb +33 -0
  26. data/lib/dtr/shared/service/working_env.rb +28 -0
  27. data/lib/dtr/shared/service.rb +19 -0
  28. data/lib/dtr/shared/sync_codebase/codebase.rb +32 -0
  29. data/lib/dtr/shared/sync_codebase/master_ext.rb +52 -0
  30. data/lib/dtr/shared/sync_codebase/package.rb +39 -0
  31. data/lib/dtr/shared/sync_codebase/sync_service.rb +41 -0
  32. data/lib/dtr/shared/sync_codebase.rb +18 -0
  33. data/lib/dtr/shared/sync_logger.rb +72 -0
  34. data/lib/dtr/shared/utils/cmd.rb +30 -0
  35. data/lib/dtr/shared/utils/env_store.rb +60 -0
  36. data/lib/dtr/shared/utils/logger.rb +71 -0
  37. data/lib/dtr/shared/utils.rb +17 -0
  38. data/lib/dtr/shared/working_env.rb +38 -0
  39. data/lib/dtr/shared.rb +24 -0
  40. data/lib/dtr/test_unit/drb_test_runner.rb +57 -0
  41. data/lib/dtr/test_unit/injection.rb +30 -0
  42. data/lib/dtr/test_unit/test_case_injection.rb +37 -0
  43. data/lib/dtr/test_unit/testrunnermediator_injection.rb +72 -0
  44. data/lib/dtr/test_unit/thread_safe_test_result.rb +40 -0
  45. data/lib/dtr/test_unit/worker_club.rb +72 -0
  46. data/lib/dtr/test_unit.rb +8 -275
  47. data/lib/dtr/test_unit_injection.rb +0 -1
  48. data/lib/dtr.rb +23 -81
  49. data/test/acceptance/agent_working_env_test.rb +92 -0
  50. data/test/acceptance/dtr_package_task_test.rb +26 -0
  51. data/test/acceptance/general_test.rb +275 -0
  52. data/test/acceptance/sync_codebase_test.rb +67 -0
  53. data/test/acceptance/sync_logger_test.rb +41 -0
  54. data/test/agent_helper.rb +39 -0
  55. data/test/logger_stub.rb +30 -0
  56. data/test/test_helper.rb +43 -0
  57. data/test/unit/adapter_test.rb +107 -0
  58. data/test/unit/test_unit_test.rb +47 -0
  59. data/test/unit/working_env_test.rb +71 -0
  60. data/testdata/Rakefile +15 -0
  61. data/testdata/a_failed_test_case.rb +8 -0
  62. data/testdata/a_file_system_test_case.rb +8 -0
  63. data/testdata/a_test_case.rb +13 -0
  64. data/testdata/a_test_case2.rb +6 -0
  65. data/testdata/an_error_test_case.rb +9 -0
  66. data/testdata/another_project/Rakefile +6 -0
  67. data/testdata/another_project/passed_test_case.rb +7 -0
  68. data/testdata/is_required_by_a_test.rb +9 -0
  69. data/testdata/lib/lib_test_case.rb +7 -0
  70. data/testdata/package_task_test_rakefile +8 -0
  71. data/testdata/scenario_test_case.rb +34 -0
  72. data/testdata/setup_agent_env_test_case.rb +9 -0
  73. data/testdata/should_not_sync_codebase_and_setup_working_dir_when_agent_is_in_same_dir_with_master_process/Rakefile +6 -0
  74. data/testdata/should_not_sync_codebase_and_setup_working_dir_when_agent_is_in_same_dir_with_master_process/verify_dir_pwd_test_case.rb +10 -0
  75. metadata +72 -18
  76. data/lib/dtr/base.rb +0 -172
  77. data/lib/dtr/runner.rb +0 -270
  78. data/lib/dtr/service_provider.rb +0 -160
data/lib/dtr/test_unit.rb CHANGED
@@ -12,278 +12,11 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'dtr/base'
16
- require 'dtr/service_provider'
17
- require 'test/unit/testcase'
18
- require 'test/unit/util/observable'
19
- require 'monitor'
20
- require 'drb'
21
- require 'timeout'
22
-
23
- DTROPTIONS = {} unless defined?(DTROPTIONS)
24
- DTROPTIONS[:log_file] = 'dtr_master_process.log' unless DTROPTIONS[:log_file]
25
-
26
- module DTR
27
- def reject
28
- return unless Test::Unit::TestSuite.method_defined?(:dtr_injected?)
29
- Test::Unit::TestCase.send(:include, Rejection)
30
- Test::Unit::TestSuite.send(:include, Rejection)
31
- end
32
-
33
- def inject
34
- return if Test::Unit::TestSuite.method_defined?(:dtr_injected?)
35
- Test::Unit::TestCase.send(:include, TestCaseInjection)
36
- Test::Unit::TestSuite.send(:include, TestSuiteInjection)
37
- end
38
-
39
- def service_provider
40
- $dtr_service_provider ||= DTR::ServiceProvider.new
41
- end
42
-
43
- module_function :reject, :inject, :service_provider
44
-
45
- class Counter
46
-
47
- def initialize
48
- extend MonitorMixin
49
- @start_count, @finish_count = 0, 0
50
- @complete_cond = new_cond
51
- end
52
-
53
- def add_start_count
54
- synchronize do
55
- @start_count += 1
56
- end
57
- end
58
-
59
- def add_finish_count
60
- synchronize do
61
- @finish_count += 1
62
- @complete_cond.signal
63
- end
64
- end
65
-
66
- def to_s
67
- synchronize do
68
- status
69
- end
70
- end
71
-
72
- def wait_until_complete
73
- synchronize do
74
- @complete_cond.wait_until {complete?}
75
- end
76
- end
77
-
78
- private
79
- def complete?
80
- DTR.info{ "Counter status: #{status}" }
81
- @finish_count >= @start_count
82
- end
83
-
84
- def status
85
- "finish_count => #{@finish_count}, start_count => #{@start_count}"
86
- end
87
- end
88
-
89
- class ThreadSafeTestResult
90
- include Test::Unit::Util::Observable
91
- include DRbUndumped
92
-
93
- def initialize(rs)
94
- extend MonitorMixin
95
- @rs = rs
96
- @channels = @rs.send(:channels).dup
97
- @rs.send(:channels).clear
98
- end
99
-
100
- def add_run
101
- synchronize do
102
- @rs.add_run
103
- end
104
- notify_listeners(Test::Unit::TestResult::CHANGED, self)
105
- end
106
-
107
- def add_failure(failure)
108
- synchronize do
109
- @rs.add_failure(failure)
110
- end
111
- notify_listeners(Test::Unit::TestResult::FAULT, failure)
112
- notify_listeners(Test::Unit::TestResult::CHANGED, self)
113
- end
114
-
115
- def add_error(error)
116
- synchronize do
117
- @rs.add_error(error)
118
- end
119
- notify_listeners(Test::Unit::TestResult::FAULT, error)
120
- notify_listeners(Test::Unit::TestResult::CHANGED, self)
121
- end
122
-
123
- def add_assertion
124
- synchronize do
125
- @rs.add_assertion
126
- end
127
- notify_listeners(Test::Unit::TestResult::CHANGED, self)
128
- end
129
-
130
- def to_s
131
- synchronize do
132
- @rs.to_s
133
- end
134
- end
135
-
136
- def passed?
137
- synchronize do
138
- @rs.passed?
139
- end
140
- end
141
-
142
- def failure_count
143
- synchronize do
144
- @rs.failure_count
145
- end
146
- end
147
-
148
- def error_count
149
- synchronize do
150
- @rs.error_count
151
- end
152
- end
153
- end
154
-
155
- class DRbTestRunner
156
-
157
- # because some test case will rewrite TestCase#run to ignore some tests, which
158
- # makes TestResult#run_count different with TestSuite#size, so we need to count
159
- # by ourselves.(for example: ActionController::IntegrationTest)
160
- class << self
161
- def counter
162
- @counter ||= Counter.new
163
- end
164
- end
165
-
166
- RUN_TEST_FINISHED = "::DRbTestRunner::RUN_TEST_FINISHED"
167
- DEFAULT_RUN_TEST_TIMEOUT = 60 #seconds
168
-
169
- def initialize(test, result, &progress_block)
170
- @test = test
171
- @result = result
172
- @progress_block = progress_block
173
-
174
- DRbTestRunner.counter.add_start_count
175
- end
176
-
177
- def run
178
- if runner = lookup_runner
179
- run_test_on(runner)
180
- else
181
- self.run
182
- end
183
- end
184
-
185
- def run_test_on(runner)
186
- Thread.start do
187
- begin
188
- Timeout.timeout(ENV['RUN_TEST_TIMEOUT'] || DEFAULT_RUN_TEST_TIMEOUT) do
189
- runner.run(@test, @result, &@progress_block)
190
- end
191
- @progress_block.call(RUN_TEST_FINISHED, @test.name)
192
- rescue Timeout::Error => e
193
- DTR.info {"Run test timeout(#{ENV['RUN_TEST_TIMEOUT'] || DEFAULT_RUN_TEST_TIMEOUT}), reboot runner"}
194
- runner.reboot rescue nil
195
- DTR.info {"rerun test: #{@test.name}"}
196
- self.run
197
- rescue DRb::DRbConnError => e
198
- DTR.info {"DRb::DRbConnError(#{e.message}), rerun test: #{@test.name}"}
199
- self.run
200
- rescue Exception => e
201
- DTR.info{ "#{test.name}, rescue an exception: #{e.message}, add error into result." }
202
- @result.add_error(Test::Unit::Error.new(@test.name, e))
203
- @result.add_run
204
- @progress_block.call(Test::Unit::TestCase::FINISHED, @test.name)
205
- @progress_block.call(RUN_TEST_FINISHED, @test.name)
206
- end
207
- end
208
- end
209
-
210
- def lookup_runner
211
- runner = DTR.service_provider.lookup_runner
212
- begin
213
- DTR.debug {"#{runner.name}.env ==?: #{WorkingEnv.current[:identifier] == runner.identifier}"}
214
- return runner if runner.identifier == WorkingEnv.current[:identifier]
215
- runner.shutdown
216
- rescue DRb::DRbConnError => e
217
- DTR.debug {"DRb::DRbConnError(#{e.message})"}
218
- end
219
- nil
220
- end
221
- end
222
-
223
- module TestCaseInjection
224
-
225
- def self.included(base)
226
- base.class_eval do
227
- alias_method :__run__, :run
228
-
229
- def run(result, &progress_block)
230
- DTR.debug {"start of run TestCase(#{name})"}
231
- DRbTestRunner.new(self, result, &progress_block).run
232
- DTR.debug {"end of run TestCase(#{name})"}
233
- end
234
- end
235
- end
236
- end
237
-
238
- module TestSuiteInjection
239
- def self.included(base)
240
- base.class_eval do
241
- def dtr_injected?
242
- true
243
- end
244
-
245
- alias_method :__run__, :run
246
-
247
- def run(result, &progress_block)
248
- DTR.info { "start of run suite(#{name}), size: #{size};"}
249
-
250
- if result.kind_of?(ThreadSafeTestResult)
251
- __run__(result, &progress_block)
252
- else
253
- if defined?(ActiveRecord::Base)
254
- ActiveRecord::Base.clear_active_connections! rescue nil
255
- end
256
-
257
- DTR.service_provider.setup_working_env WorkingEnv.refresh
258
-
259
- puts 'Refreshed dtr working environment, looking for runner service...' unless ENV['DTR_ENV'] == 'test'
260
- DTR.info {"Master process started at #{Time.now}"}
261
- result = ThreadSafeTestResult.new(result)
262
- __run__(result) do |channel, value|
263
- DTR.debug { "=> channel: #{channel}, value: #{value}" }
264
- progress_block.call(channel, value)
265
- if channel == DTR::DRbTestRunner::RUN_TEST_FINISHED
266
- DRbTestRunner.counter.add_finish_count
267
- end
268
- end
269
- DRbTestRunner.counter.wait_until_complete
270
- DTR.debug { "==> teardown" }
271
- DTR.service_provider.teardown_working_env
272
- end
273
- DTR.info { "end of run suite(#{name}), test result status: #{result}, counter status: #{DRbTestRunner.counter}"}
274
- end
275
- end
276
- end
277
- end
278
-
279
- module Rejection
280
- def self.included(base)
281
- base.class_eval do
282
- remove_method :dtr_injected? if base.method_defined?(:dtr_injected?)
283
- remove_method :run
284
- alias_method :run, :__run__
285
- remove_method :__run__
286
- end
287
- end
288
- end
289
- end
15
+ require 'dtr/master'
16
+
17
+ require 'dtr/test_unit/worker_club'
18
+ require 'dtr/test_unit/thread_safe_test_result'
19
+ require 'dtr/test_unit/drb_test_runner'
20
+ require 'dtr/test_unit/test_case_injection'
21
+ require 'dtr/test_unit/testrunnermediator_injection'
22
+ require 'dtr/test_unit/injection'
@@ -12,7 +12,6 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'dtr/service_provider'
16
15
  require 'dtr/test_unit'
17
16
  $argv_dup = ARGV.dup.delete_if{|f| f.include?('dtr/test_unit_injection')}
18
17
 
data/lib/dtr.rb CHANGED
@@ -12,100 +12,42 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- DTRVERSION="0.0.4"
16
- DTROPTIONS = {} unless defined?(DTROPTIONS)
17
-
18
- require 'fileutils'
15
+ DTRVERSION="0.0.5"
16
+ DTR_AGENT_OPTIONS = {:runners => [], :agent_env_setup_cmd => nil}
19
17
 
20
18
  module DTR
21
19
 
22
- def start_server
23
- require 'dtr/service_provider'
24
- ServiceProvider.new.start
25
- end
26
-
27
- def start_runners
28
- launch_runners(DTROPTIONS[:names], DTROPTIONS[:setup])
20
+ def start_agent
21
+ launch_agent(DTR_AGENT_OPTIONS[:runners], DTR_AGENT_OPTIONS[:agent_env_setup_cmd])
29
22
  end
30
-
31
- def launch_runners(names, setup=nil)
32
- require 'dtr/runner'
23
+
24
+ def launch_agent(names, setup=nil)
25
+ require 'dtr/agent'
33
26
  names = names || "DTR(#{Time.now})"
34
- DTR::RunnerAgent.start(names, setup)
27
+ DTR::Agent.start(names, setup)
35
28
  end
36
-
29
+
37
30
  def lib_path
38
31
  File.expand_path(File.dirname(__FILE__))
39
32
  end
40
-
33
+
41
34
  def broadcast_list=(list)
42
- require 'dtr/service_provider'
43
- ServiceProvider.broadcast_list = list
35
+ require 'dtr/shared'
36
+ DTR.configuration.broadcast_list = list
37
+ DTR.configuration.save
44
38
  end
45
-
39
+
46
40
  def port=(port)
47
- require 'dtr/service_provider'
48
- ServiceProvider.port = port
41
+ require 'dtr/shared'
42
+ DTR.configuration.rinda_server_port = port
43
+ DTR.configuration.save
49
44
  end
50
-
51
- def runners
52
- require 'dtr/service_provider'
53
- ServiceProvider.new.runners
54
- end
55
-
45
+
56
46
  def monitor
57
- require 'dtr/service_provider'
58
- DTROPTIONS[:log_file] = 'dtr_monitor.log'
59
- ServiceProvider.new.monitor
47
+ require 'dtr/monitor'
48
+ DTR.logger('dtr_monitor.log')
49
+ Monitor.new.start
60
50
  end
61
-
62
- def stop_runners_daemon_mode
63
- with_daemon_gem do
64
- Daemons.run_proc "dtr_runners", :ARGV => ['stop']
65
- end
66
- end
67
-
68
- def start_runners_daemon_mode
69
- with_daemon_gem do
70
- FileUtils.rm_rf('dtr_runners.output')
71
- pwd = Dir.pwd
72
- Daemons.run_proc "dtr_runners", :ARGV => ['start'], :backtrace => true do
73
- Dir.chdir(pwd) do
74
- start_runners
75
- end
76
- end
77
- end
78
- end
79
-
80
- def start_server_daemon_mode
81
- with_daemon_gem do
82
- Daemons.run_proc "dtr_server", :ARGV => ['start'] do
83
- start_server
84
- end
85
- end
86
- sleep(2)
87
- end
88
-
89
- def stop_server_daemon_mode
90
- with_daemon_gem do
91
- Daemons.run_proc "dtr_server", :ARGV => ['stop']
92
- end
93
- end
94
-
95
- def with_daemon_gem
96
- require "rubygems"
97
- begin
98
- require "daemons"
99
- rescue LoadError
100
- raise "The daemons gem must be installed"
101
- end
102
- yield
103
- end
104
-
105
- def clean_server
106
- require 'dtr/service_provider'
107
- ServiceProvider.new.clear_workspace
108
- end
109
-
110
- module_function :start_server, :start_runners, :launch_runners, :lib_path, :broadcast_list=, :runners, :with_daemon_gem, :start_runners_daemon_mode, :stop_runners_daemon_mode, :start_server_daemon_mode, :stop_server_daemon_mode, :monitor, :port=, :clean_server
51
+
52
+ module_function :start_agent, :launch_agent, :lib_path, :broadcast_list=, :monitor, :port=
111
53
  end
@@ -0,0 +1,92 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ include DTR::AgentHelper
4
+
5
+ class AgentWorkingEnvTest < Test::Unit::TestCase
6
+ include DTR::Service::WorkingEnv
7
+ def setup
8
+ #start_agents first for test files loaded would be copied into sub processes
9
+ start_agents
10
+ DTR.inject
11
+ end
12
+
13
+ def teardown
14
+ DTR.reject
15
+ stop_agents
16
+ $argv_dup = nil
17
+ end
18
+
19
+ def test_run_2_project_should_be_independence
20
+ Dir.chdir(File.expand_path(File.dirname(__FILE__) + "/../../testdata/")) do
21
+ $argv_dup = ['an_error_test_case.rb']
22
+ require 'an_error_test_case'
23
+
24
+ suite = Test::Unit::TestSuite.new('test_run_2_project_should_be_independence 1')
25
+ suite << AnErrorTestCase.suite
26
+
27
+ assert_fork_process_exits_ok do
28
+ @result = runit(suite)
29
+
30
+ assert_false @result.passed?
31
+ assert_equal 1, @result.run_count
32
+ assert_equal 0, @result.failure_count
33
+ assert_equal 1, @result.error_count
34
+ end
35
+ end
36
+
37
+ Dir.chdir(File.expand_path(File.dirname(__FILE__) + "/../../testdata/another_project")) do
38
+ $argv_dup = ['passed_test_case.rb']
39
+ require 'passed_test_case'
40
+ suite = Test::Unit::TestSuite.new('test_run_2_project_should_be_independence 2')
41
+ suite << PassedTestCase.suite
42
+
43
+ assert_fork_process_exits_ok do
44
+ @result = runit(suite)
45
+
46
+ assert @result.passed?
47
+ assert_equal 1, @result.run_count
48
+ assert_equal 0, @result.failure_count
49
+ assert_equal 0, @result.error_count
50
+ end
51
+ end
52
+ end
53
+
54
+ def test_run_same_project_twice_should_be_independence
55
+ Dir.chdir(File.expand_path(File.dirname(__FILE__) + "/../../testdata/another_project")) do
56
+ $argv_dup = ['passed_test_case.rb']
57
+ require 'passed_test_case'
58
+ suite = Test::Unit::TestSuite.new('test_run_same_project_twice_should_be_independence 1')
59
+ suite << PassedTestCase.suite
60
+
61
+ assert_fork_process_exits_ok do
62
+ @result = runit(suite)
63
+
64
+ assert @result.passed?
65
+ assert_equal 1, @result.run_count
66
+ assert_equal 0, @result.failure_count
67
+ assert_equal 0, @result.error_count
68
+ end
69
+ end
70
+
71
+ Dir.chdir(File.expand_path(File.dirname(__FILE__) + "/../../testdata/another_project")) do
72
+ FileUtils.cp("./../an_error_test_case.rb", '.')
73
+ begin
74
+ $argv_dup = ['an_error_test_case.rb']
75
+ require 'an_error_test_case'
76
+ suite = Test::Unit::TestSuite.new('test_run_same_project_twice_should_be_independence 2')
77
+ suite << AnErrorTestCase.suite
78
+
79
+ assert_fork_process_exits_ok do
80
+ @result = runit(suite)
81
+
82
+ assert_false @result.passed?
83
+ assert_equal 1, @result.run_count
84
+ assert_equal 0, @result.failure_count
85
+ assert_equal 1, @result.error_count
86
+ end
87
+ ensure
88
+ FileUtils.rm_f('an_error_test_case.rb')
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ require 'fileutils'
3
+
4
+ class DTRPackageTaskTest < Test::Unit::TestCase
5
+ def test_package
6
+ testdata_dir = File.expand_path(File.dirname(__FILE__) + '/../../testdata')
7
+ Dir.chdir(testdata_dir) do
8
+ %x[rake --rakefile package_task_test_rakefile dtr_package]
9
+ assert File.exists?(testdata_dir + "/dtr_pkg/codebase-dump/a_test_case2.rb")
10
+ assert File.exists?(testdata_dir + "/dtr_pkg/codebase-dump/lib/lib_test_case.rb")
11
+ assert File.exists?(testdata_dir + "/dtr_pkg/codebase-dump/is_required_by_a_test.rb")
12
+
13
+ assert File.exists?(testdata_dir + "/dtr_pkg/codebase-dump.tar.bz2")
14
+
15
+ %x[rake --rakefile package_task_test_rakefile dtr_clobber_package]
16
+
17
+ assert !File.exists?(testdata_dir + "/dtr_pkg/codebase-dump/a_test_case2.rb")
18
+ assert !File.exists?(testdata_dir + "/dtr_pkg/codebase-dump/lib/lib_test_case.rb")
19
+ assert !File.exists?(testdata_dir + "/dtr_pkg/codebase-dump/is_required_by_a_test.rb")
20
+
21
+ assert !File.exists?(testdata_dir + "/dtr_pkg/codebase-dump.tar.bz2")
22
+ end
23
+ ensure
24
+ FileUtils.rm_rf(testdata_dir + "/dtr_pkg") rescue nil
25
+ end
26
+ end