dtr 0.0.4 → 1.0.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 (93) hide show
  1. data/CHANGES +7 -0
  2. data/LICENSE.txt +203 -0
  3. data/README.rdoc +208 -0
  4. data/Rakefile +64 -205
  5. data/TODO +8 -2
  6. data/bin/dtr +27 -60
  7. data/dtr.gemspec +8 -11
  8. data/lib/dtr.rb +5 -94
  9. data/lib/dtr/agent.rb +38 -0
  10. data/lib/dtr/agent/brain.rb +57 -0
  11. data/lib/dtr/agent/herald.rb +60 -0
  12. data/lib/dtr/agent/runner.rb +87 -0
  13. data/lib/dtr/agent/sync_codebase.rb +44 -0
  14. data/lib/dtr/agent/sync_logger.rb +70 -0
  15. data/lib/dtr/agent/test_case.rb +53 -0
  16. data/lib/dtr/agent/test_unit.rb +40 -0
  17. data/lib/dtr/agent/worker.rb +89 -0
  18. data/lib/dtr/agent/working_env_ext.rb +47 -0
  19. data/lib/dtr/facade.rb +65 -0
  20. data/lib/dtr/master.rb +40 -0
  21. data/lib/dtr/monitor.rb +95 -0
  22. data/lib/dtr/raketasks.rb +155 -22
  23. data/lib/dtr/shared.rb +24 -0
  24. data/lib/dtr/shared/adapter.rb +115 -0
  25. data/lib/dtr/shared/configuration.rb +104 -0
  26. data/lib/dtr/shared/message_decorator.rb +28 -0
  27. data/lib/dtr/shared/ruby_ext.rb +129 -0
  28. data/lib/dtr/shared/service.rb +19 -0
  29. data/lib/dtr/shared/service/agent.rb +37 -0
  30. data/lib/dtr/shared/service/file.rb +28 -0
  31. data/lib/dtr/shared/service/rinda.rb +48 -0
  32. data/lib/dtr/shared/service/runner.rb +34 -0
  33. data/lib/dtr/shared/service/working_env.rb +28 -0
  34. data/lib/dtr/shared/sync_codebase.rb +18 -0
  35. data/lib/dtr/shared/sync_codebase/copiable_package.rb +40 -0
  36. data/lib/dtr/shared/sync_codebase/master_ext.rb +40 -0
  37. data/lib/dtr/shared/sync_codebase/package.rb +53 -0
  38. data/lib/dtr/shared/sync_codebase/sync_service.rb +36 -0
  39. data/lib/dtr/shared/sync_logger.rb +64 -0
  40. data/lib/dtr/shared/utils.rb +17 -0
  41. data/lib/dtr/shared/utils/cmd.rb +30 -0
  42. data/lib/dtr/shared/utils/env_store.rb +60 -0
  43. data/lib/dtr/shared/utils/logger.rb +87 -0
  44. data/lib/dtr/shared/working_env.rb +38 -0
  45. data/lib/dtr/test_unit.rb +9 -275
  46. data/lib/dtr/test_unit/drb_test_runner.rb +48 -0
  47. data/lib/dtr/test_unit/injection.rb +29 -0
  48. data/lib/dtr/test_unit/test_case_injection.rb +37 -0
  49. data/lib/dtr/test_unit/test_suite_injection.rb +24 -0
  50. data/lib/dtr/test_unit/testrunnermediator_injection.rb +72 -0
  51. data/lib/dtr/test_unit/thread_safe_test_result.rb +38 -0
  52. data/lib/dtr/test_unit/worker_club.rb +72 -0
  53. data/lib/dtr/test_unit_injection.rb +1 -2
  54. data/test/acceptance/agent_working_env_test.rb +86 -0
  55. data/test/acceptance/dtr_package_task_test.rb +36 -0
  56. data/test/acceptance/general_test.rb +331 -0
  57. data/test/acceptance/raketasks_test.rb +23 -0
  58. data/test/acceptance/sync_codebase_test.rb +66 -0
  59. data/test/acceptance/sync_logger_test.rb +32 -0
  60. data/test/agent_helper.rb +37 -0
  61. data/test/logger_stub.rb +34 -0
  62. data/test/test_helper.rb +71 -0
  63. data/test/unit/adapter_test.rb +149 -0
  64. data/test/unit/configuration_test.rb +44 -0
  65. data/test/unit/facade_test.rb +41 -0
  66. data/test/unit/logger_test.rb +72 -0
  67. data/test/unit/test_unit_test.rb +26 -0
  68. data/test/unit/working_env_test.rb +71 -0
  69. data/testdata/Rakefile +11 -0
  70. data/testdata/a_failed_test_case.rb +8 -0
  71. data/testdata/a_file_system_test_case.rb +8 -0
  72. data/testdata/a_test_case.rb +13 -0
  73. data/testdata/a_test_case2.rb +6 -0
  74. data/testdata/an_error_test_case.rb +9 -0
  75. data/testdata/another_project/Rakefile +6 -0
  76. data/testdata/another_project/passed_test_case.rb +7 -0
  77. data/testdata/hacked_run_method_test_case.rb +15 -0
  78. data/testdata/is_required_by_a_test.rb +9 -0
  79. data/testdata/lib/lib_test_case.rb +7 -0
  80. data/testdata/package_task_test_rakefile +8 -0
  81. data/testdata/raketasks/Rakefile +7 -0
  82. data/testdata/raketasks/success_test_case.rb +6 -0
  83. data/testdata/scenario_test_case.rb +34 -0
  84. data/testdata/setup_agent_env_test_case.rb +9 -0
  85. data/testdata/sleep_3_secs_test_case.rb +9 -0
  86. data/testdata/verify_dir_pwd/Rakefile +6 -0
  87. data/testdata/verify_dir_pwd/verify_dir_pwd_test_case.rb +10 -0
  88. metadata +101 -34
  89. data/README +0 -291
  90. data/install.rb +0 -88
  91. data/lib/dtr/base.rb +0 -172
  92. data/lib/dtr/runner.rb +0 -270
  93. data/lib/dtr/service_provider.rb +0 -160
@@ -0,0 +1,38 @@
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module DTR
16
+ class WorkingEnv
17
+ def initialize
18
+ files = (defined?($argv_dup) && $argv_dup ? $argv_dup : []).dup
19
+ @env = {:libs => $LOAD_PATH.dup, :files => files, :created_at => Time.now.to_s, :dtr_master_env => ENV['DTR_MASTER_ENV'], :agent_env_setup_cmd => ENV['DTR_AGENT_ENV_SETUP_CMD'], :identifier => "#{Time.now.to_s}:#{rand}:#{object_id}", :host => Socket.gethostname, :pwd => Dir.pwd}
20
+ end
21
+
22
+ def [](key)
23
+ @env[key]
24
+ end
25
+
26
+ def []=(key, value)
27
+ @env[key] = value
28
+ end
29
+
30
+ def to_s
31
+ @env.inspect
32
+ end
33
+
34
+ def ==(obj)
35
+ obj && obj[:identifier] == self[:identifier]
36
+ end
37
+ end
38
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2008 Li Xiao
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -12,278 +12,12 @@
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'
15
+ require 'dtr/master'
22
16
 
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
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/test_suite_injection'
22
+ require 'dtr/test_unit/testrunnermediator_injection'
23
+ require 'dtr/test_unit/injection'
@@ -0,0 +1,48 @@
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module DTR
16
+ module TestUnit
17
+ class DRbTestRunner
18
+ include Service::Runner
19
+
20
+ def initialize(test, result, &progress_block)
21
+ @test = test
22
+ @result = result
23
+ @progress_block = progress_block
24
+ end
25
+
26
+ def run
27
+ if runner = lookup_runner
28
+ WorkerClub.instance.start_thread(self, runner)
29
+ else
30
+ self.run
31
+ end
32
+ end
33
+
34
+ def run_test_on(runner)
35
+ runner.run(@test, @result, &@progress_block)
36
+ rescue DRb::DRbConnError => e
37
+ DTR.info {"#{cause.class.name}(#{cause.message}), rerun test: #{@test.name}"}
38
+ DTR.debug { cause.backtrace.join("\n") }
39
+ self.run
40
+ rescue Exception => e
41
+ DTR.info{ "#{@test.name}, rescue an exception: #{e.message}, add error into result." }
42
+ @result.add_error(Test::Unit::Error.new(@test.name, e))
43
+ @result.add_run
44
+ @progress_block.call(Test::Unit::TestCase::FINISHED, @test.name)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'test/unit/ui/testrunnermediator'
16
+
17
+ module DTR
18
+ def reject
19
+ return unless Test::Unit::UI::TestRunnerMediator.respond_to?(:reject_dtr)
20
+ Test::Unit::UI::TestRunnerMediator.reject_dtr
21
+ end
22
+
23
+ def inject
24
+ return if Test::Unit::UI::TestRunnerMediator.respond_to?(:reject_dtr)
25
+ Test::Unit::UI::TestRunnerMediator.send(:include, TestUnit::TestRunnerMediatorInjection)
26
+ end
27
+
28
+ module_function :reject, :inject
29
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module DTR
16
+ module TestUnit
17
+ module TestCaseInjection
18
+ class Proxy
19
+ def initialize(test)
20
+ @test = test
21
+ end
22
+
23
+ def run(result, &progress_block)
24
+ DRbTestRunner.new(@test, result, &progress_block).run
25
+ end
26
+
27
+ def size
28
+ @test.size
29
+ end
30
+ end
31
+
32
+ def proxy
33
+ Proxy.new(self)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,24 @@
1
+ # Copyright (c) 2007-2008 Li Xiao <iam@li-xiao.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module DTR
16
+ module TestUnit
17
+ module TestSuiteInjection
18
+ def proxy
19
+ @tests.collect! {|t| t.proxy}
20
+ self
21
+ end
22
+ end
23
+ end
24
+ end