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,72 @@
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/testcase'
16
+ require 'test/unit/testsuite'
17
+
18
+ module DTR
19
+ module TestUnit
20
+ module TestRunnerMediatorInjection
21
+ class SuiteWrapper
22
+ def initialize(suite)
23
+ @suite = suite
24
+ end
25
+
26
+ def run(result, &block)
27
+ @suite.run(result, &block)
28
+ WorkerClub.instance.graceful_shutdown
29
+ end
30
+
31
+ def size
32
+ @suite.size
33
+ end
34
+ end
35
+
36
+ def self.included(base)
37
+ base.send(:include, Master)
38
+ base.alias_method_chain :create_result, :thread_safe
39
+ base.alias_method_chain :run_suite, :dtr_injection
40
+ #have to use class_eval for adding it back after removed reject_dtr method
41
+ base.class_eval do
42
+ def self.reject_dtr
43
+ remove_method :run_suite
44
+ alias_method :run_suite, :run_suite_without_dtr_injection
45
+ remove_method :run_suite_without_dtr_injection
46
+
47
+ remove_method :create_result
48
+ alias_method :create_result, :create_result_without_thread_safe
49
+ remove_method :create_result_without_thread_safe
50
+
51
+ (class << self; self; end;).send :remove_method, :reject_dtr
52
+ end
53
+ end
54
+ end
55
+
56
+ def create_result_with_thread_safe
57
+ ThreadSafeTestResult.new(create_result_without_thread_safe)
58
+ end
59
+
60
+ def run_suite_with_dtr_injection
61
+ DTR.logger('dtr_master_process.log')
62
+ # inject testcase&testsuite as late as possible, for it's too easy to be hacked in ruby world
63
+ Test::Unit::TestCase.send(:include, TestUnit::TestCaseInjection)
64
+ Test::Unit::TestSuite.send(:include, TestUnit::TestSuiteInjection)
65
+ @suite = SuiteWrapper.new(@suite.proxy)
66
+ with_dtr_master do
67
+ run_suite_without_dtr_injection
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -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
+ module TestUnit
17
+ class ThreadSafeTestResult
18
+ include DRbUndumped
19
+
20
+ def initialize(rs)
21
+ @mutex = Mutex.new
22
+ @rs = rs
23
+ end
24
+
25
+ def to_s
26
+ @mutex.synchronize do
27
+ @rs.to_s
28
+ end
29
+ end
30
+
31
+ def method_missing(method, *args, &block)
32
+ @mutex.synchronize do
33
+ @rs.send(method, *args, &block)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,72 @@
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 'singleton'
16
+
17
+ module DTR
18
+ module TestUnit
19
+ class WorkerClub
20
+ include Singleton
21
+
22
+ DEFAULT_RUN_TEST_TIMEOUT = 60 #seconds
23
+
24
+ def start_thread(drb_runner, remote_runner)
25
+ thread = Thread.new(drb_runner, remote_runner) do |local, remote|
26
+ local.run_test_on(remote)
27
+ end
28
+ thread[:started_on] = Time.now
29
+ workers.add(thread)
30
+ end
31
+
32
+ # Performs a wait on all the currently running threads and kills any that take
33
+ # too long. It waits by ENV['RUN_TEST_TIMEOUT'] || 60 seconds
34
+ def graceful_shutdown
35
+ while reap_dead_workers("shutdown") > 0
36
+ DTR.info {"Waiting for #{workers.list.length} threads to finish, could take #{timeout} seconds."}
37
+ sleep timeout / 60
38
+ end
39
+ end
40
+
41
+ private
42
+ def timeout
43
+ (ENV['RUN_TEST_TIMEOUT'] || DEFAULT_RUN_TEST_TIMEOUT).to_i
44
+ end
45
+
46
+ def workers
47
+ @workers ||= ThreadGroup.new
48
+ end
49
+
50
+ # Used internally to kill off any worker threads that have taken too long
51
+ # to complete processing. It returns the count of workers still active
52
+ # after the reap is done. It only runs if there are workers to reap.
53
+ def reap_dead_workers(reason='unknown')
54
+ if workers.list.length > 0
55
+ DTR.info {"Reaping #{workers.list.length} threads because of '#{reason}'"}
56
+ error_msg = "#{Time.now}: WorkerClub timed out this thread: #{reason}"
57
+ mark = Time.now
58
+ workers.list.each do |worker|
59
+ worker[:started_on] = Time.now if not worker[:started_on]
60
+
61
+ if mark - worker[:started_on] > timeout
62
+ DTR.info {"Thread #{worker.inspect} is too old, killing."}
63
+ worker.raise(TimeoutError.new(error_msg))
64
+ end
65
+ end
66
+ end
67
+
68
+ return workers.list.length
69
+ end
70
+ end
71
+ end
72
+ 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,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
 
@@ -0,0 +1,86 @@
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
+ end
11
+
12
+ def teardown
13
+ stop_agents
14
+ end
15
+
16
+ def test_run_2_project_should_be_independence
17
+ assert_fork_process_exits_ok do
18
+ $argv_dup = ['an_error_test_case.rb']
19
+
20
+ suite = Test::Unit::TestSuite.new('test_run_2_project_should_be_independence 1')
21
+ suite << AnErrorTestCase.suite
22
+
23
+ @result = runit(suite)
24
+
25
+ assert_false @result.passed?
26
+ assert_equal 1, @result.run_count
27
+ assert_equal 0, @result.failure_count
28
+ assert_equal 1, @result.error_count
29
+ end
30
+
31
+ assert_fork_process_exits_ok do
32
+ Dir.chdir("another_project") do
33
+ $argv_dup = ['passed_test_case.rb']
34
+ require 'passed_test_case'
35
+ suite = Test::Unit::TestSuite.new('test_run_2_project_should_be_independence 2')
36
+ suite << PassedTestCase.suite
37
+
38
+ @result = runit(suite)
39
+
40
+ assert @result.passed?
41
+ assert_equal 1, @result.run_count
42
+ assert_equal 0, @result.failure_count
43
+ assert_equal 0, @result.error_count
44
+ end
45
+ end
46
+ end
47
+
48
+ def test_run_same_project_twice_should_be_independence
49
+ assert_fork_process_exits_ok do
50
+ Dir.chdir("another_project") do
51
+ $argv_dup = ['passed_test_case.rb']
52
+ require 'passed_test_case'
53
+ suite = Test::Unit::TestSuite.new('test_run_same_project_twice_should_be_independence 1')
54
+ suite << PassedTestCase.suite
55
+
56
+ @result = runit(suite)
57
+
58
+ assert @result.passed?
59
+ assert_equal 1, @result.run_count
60
+ assert_equal 0, @result.failure_count
61
+ assert_equal 0, @result.error_count
62
+ end
63
+ end
64
+
65
+ assert_fork_process_exits_ok do
66
+ Dir.chdir("another_project") do
67
+ FileUtils.cp("./../an_error_test_case.rb", '.')
68
+ begin
69
+ $argv_dup = ['an_error_test_case.rb']
70
+ require 'an_error_test_case'
71
+ suite = Test::Unit::TestSuite.new('test_run_same_project_twice_should_be_independence 2')
72
+ suite << AnErrorTestCase.suite
73
+
74
+ @result = runit(suite)
75
+
76
+ assert_false @result.passed?
77
+ assert_equal 1, @result.run_count
78
+ assert_equal 0, @result.failure_count
79
+ assert_equal 1, @result.error_count
80
+ ensure
81
+ FileUtils.rm_f('an_error_test_case.rb')
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,36 @@
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.zip")
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.zip")
22
+ end
23
+ ensure
24
+ FileUtils.rm_rf(testdata_dir + "/dtr_pkg") rescue nil
25
+ end
26
+
27
+ def test_should_not_include_dtr_pkg_dir
28
+ testdata_dir = File.expand_path(File.dirname(__FILE__) + '/../../testdata')
29
+ Dir.chdir(testdata_dir) do
30
+ %x[rake dtr_repackage]
31
+ assert !File.exists?(testdata_dir + "/dtr_pkg/codebase-dump/dtr_pkg")
32
+ end
33
+ ensure
34
+ FileUtils.rm_rf(testdata_dir + "/dtr_pkg") rescue nil
35
+ end
36
+ end
@@ -0,0 +1,331 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ include DTR::AgentHelper
4
+
5
+ class GeneralTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ start_agents
9
+ end
10
+
11
+ def teardown
12
+ stop_agents
13
+ end
14
+
15
+ def test_run_test_passed
16
+ assert_fork_process_exits_ok do
17
+ $argv_dup = ['a_test_case.rb', 'a_test_case2.rb', 'a_file_system_test_case.rb']
18
+ suite = Test::Unit::TestSuite.new('run_test_passed')
19
+ suite << ATestCase.suite
20
+ suite << ATestCase2.suite
21
+ suite << AFileSystemTestCase.suite
22
+ @result = runit(suite)
23
+
24
+ assert @result.passed?
25
+ assert_equal 3, @result.run_count
26
+ assert_equal 0, @result.failure_count
27
+ assert_equal 0, @result.error_count
28
+ end
29
+ end
30
+
31
+ def test_run_test_failed
32
+ assert_fork_process_exits_ok do
33
+ $argv_dup = ['a_test_case.rb', 'a_failed_test_case.rb']
34
+ suite = Test::Unit::TestSuite.new('test_run_test_failed')
35
+ suite << ATestCase.suite
36
+ suite << AFailedTestCase.suite
37
+ @result = runit(suite)
38
+
39
+ assert !@result.passed?
40
+ assert_equal 2, @result.run_count
41
+ assert_equal 1, @result.failure_count
42
+ assert_equal 0, @result.error_count
43
+ end
44
+ end
45
+
46
+ def test_run_test_error
47
+ assert_fork_process_exits_ok do
48
+ $argv_dup = ['a_test_case.rb', 'an_error_test_case.rb']
49
+ suite = Test::Unit::TestSuite.new('test_run_test_error')
50
+ suite << ATestCase.suite
51
+ suite << AnErrorTestCase.suite
52
+
53
+ @result = runit(suite)
54
+
55
+ assert_false @result.passed?
56
+ assert_equal 2, @result.run_count
57
+ assert_equal 0, @result.failure_count
58
+ assert_equal 1, @result.error_count
59
+ end
60
+ end
61
+
62
+ def test_run_suite_should_be_independence
63
+ assert_fork_process_exits_ok do
64
+ $argv_dup = ['an_error_test_case.rb']
65
+ suite = Test::Unit::TestSuite.new('test_run_suite_should_be_independence 1')
66
+ suite << AnErrorTestCase.suite
67
+
68
+ @result = runit(suite)
69
+
70
+ assert_false @result.passed?
71
+ assert_equal 1, @result.run_count
72
+ assert_equal 0, @result.failure_count
73
+ assert_equal 1, @result.error_count
74
+ end
75
+
76
+ assert_fork_process_exits_ok do
77
+ $argv_dup = ['a_test_case.rb']
78
+ suite = Test::Unit::TestSuite.new('test_run_suite_should_be_independence 2')
79
+ suite << ATestCase.suite
80
+
81
+ @result = runit(suite)
82
+
83
+ assert @result.passed?
84
+ assert_equal 1, @result.run_count
85
+ assert_equal 0, @result.failure_count
86
+ assert_equal 0, @result.error_count
87
+ end
88
+ end
89
+
90
+ def test_should_ignore_environment_file_not_exists
91
+ assert_fork_process_exits_ok do
92
+ $argv_dup = ['a_test_case.rb', 'test_file_not_exists.rb']
93
+ suite = Test::Unit::TestSuite.new('test_run_test_file_not_exist')
94
+ suite << ATestCase.suite
95
+
96
+ @result = runit(suite)
97
+
98
+ assert @result.passed?
99
+ assert_equal 1, @result.run_count
100
+ assert_equal 0, @result.failure_count
101
+ assert_equal 0, @result.error_count
102
+ end
103
+ end
104
+
105
+ def test_run_empty_test_suite_and_no_test_files_in_environment
106
+ assert_fork_process_exits_ok do
107
+ $argv_dup = []
108
+ suite = Test::Unit::TestSuite.new('test_run_without_test_files')
109
+
110
+ @result = runit(suite)
111
+
112
+ assert @result.passed?
113
+ assert_equal 0, @result.run_count
114
+ assert_equal 0, @result.failure_count
115
+ assert_equal 0, @result.error_count
116
+ end
117
+ end
118
+
119
+ def test_run_empty_test_suite_should_not_crash_agent
120
+ assert_fork_process_exits_ok do
121
+ $argv_dup = []
122
+ suite = Test::Unit::TestSuite.new('test_run_empty_test_suite_should_not_crash_agent')
123
+
124
+ @result = runit(suite)
125
+
126
+ assert @result.passed?
127
+ assert_equal 0, @result.run_count
128
+ assert_equal 0, @result.failure_count
129
+ assert_equal 0, @result.error_count
130
+ end
131
+
132
+ assert_fork_process_exits_ok do
133
+ $argv_dup = ['a_test_case.rb']
134
+ suite = Test::Unit::TestSuite.new('test_run_empty_test_suite_should_not_crash_agent')
135
+ suite << ATestCase.suite
136
+
137
+ @result = runit(suite)
138
+
139
+ assert @result.passed?
140
+ assert_equal 1, @result.run_count
141
+ assert_equal 0, @result.failure_count
142
+ assert_equal 0, @result.error_count
143
+ end
144
+ end
145
+
146
+ def test_run_empty_test_suite_and_test_files_not_exist_in_environment
147
+ assert_fork_process_exits_ok do
148
+ $argv_dup = ['test_file_not_exists.rb']
149
+ suite = Test::Unit::TestSuite.new('test_run_empty_test_suite_and_test_files_not_exist_in_environment')
150
+
151
+ @result = runit(suite)
152
+
153
+ assert @result.passed?
154
+ assert_equal 0, @result.run_count
155
+ assert_equal 0, @result.failure_count
156
+ assert_equal 0, @result.error_count
157
+ end
158
+ end
159
+
160
+ def test_run_test_specified_by_load_path
161
+ assert_fork_process_exits_ok do
162
+ lib_path = File.expand_path(File.dirname(__FILE__) + '/../../testdata/lib')
163
+ $LOAD_PATH.unshift lib_path
164
+ require 'lib_test_case'
165
+ $argv_dup = ['lib_test_case.rb']
166
+ suite = Test::Unit::TestSuite.new('test_run_test_specified_by_load_path')
167
+ suite << LibTestCase.suite
168
+
169
+ @result = runit(suite)
170
+
171
+ assert @result.passed?
172
+ assert_equal 1, @result.run_count
173
+ assert_equal 0, @result.failure_count
174
+ assert_equal 0, @result.error_count
175
+ end
176
+ end
177
+
178
+ def test_message_of_errors_and_failures_should_include_runner_host_name
179
+ assert_fork_process_exits_ok do
180
+ $argv_dup = ['scenario_test_case.rb']
181
+ suite = Test::Unit::TestSuite.new('test_should_wrapper_errors_by_dtr_remote_exception')
182
+ suite << ScenarioTestCase.suite
183
+
184
+ @result = runit(suite)
185
+
186
+ assert !@result.passed?
187
+ assert_equal 8, @result.run_count
188
+ assert_equal 3, @result.failure_count
189
+ assert_equal 4, @result.error_count
190
+
191
+ @result.errors.each do |e|
192
+ assert e.message.include?("from #{Socket.gethostname}")
193
+ end
194
+ @result.failures.each do |e|
195
+ assert e.message.include?("from #{Socket.gethostname}")
196
+ end
197
+ end
198
+ end
199
+
200
+ def test_setup_agent_env_from_master_process
201
+ assert_fork_process_exits_ok do
202
+ $argv_dup = ['setup_agent_env_test_case.rb']
203
+ suite = Test::Unit::TestSuite.new('setup_agent_env_from_master_process')
204
+ suite << SetupAgentEnvTestCase.suite
205
+ ENV['DTR_AGENT_ENV_SETUP_CMD'] = 'touch /tmp/test_setup_agent_env_from_master_process'
206
+
207
+ @result = runit(suite)
208
+ assert @result.passed?
209
+ assert_equal 1, @result.run_count
210
+ assert_equal 0, @result.failure_count
211
+ assert_equal 0, @result.error_count
212
+ end
213
+ ensure
214
+ File.delete('/tmp/test_setup_agent_env_from_master_process') rescue nil
215
+ end
216
+
217
+ def test_multi_dtr_tasks_should_be_queued_and_processed_one_by_one
218
+ testdata_dir = File.expand_path(File.dirname(__FILE__) + "/../../testdata/")
219
+ process_assertion = Proc.new do |master_dir|
220
+ FileUtils.cp_r testdata_dir, master_dir
221
+ begin
222
+ Dir.chdir(master_dir) do
223
+ $argv_dup = ['a_test_case.rb', 'a_test_case2.rb', 'a_file_system_test_case.rb']
224
+ setup_test_env
225
+ suite = Test::Unit::TestSuite.new('run_test_passed')
226
+ suite << ATestCase.suite
227
+ suite << ATestCase2.suite
228
+ suite << AFileSystemTestCase.suite
229
+ with_agent_helper_group do
230
+ result = runit(suite)
231
+ assert result.passed?
232
+ assert_equal 3, result.run_count
233
+ end
234
+ end
235
+ ensure
236
+ FileUtils.rm_rf master_dir
237
+ end
238
+ end
239
+
240
+ @test_processes = []
241
+ 4.times do |index|
242
+ @test_processes << Process.fork do
243
+ process_assertion.call("#{testdata_dir}_copy#{index}")
244
+ end
245
+ end
246
+
247
+ Process.waitpid @test_processes[0]
248
+ assert_equal 0, $?.exitstatus
249
+ Process.waitpid @test_processes[1]
250
+ assert_equal 0, $?.exitstatus
251
+ Process.waitpid @test_processes[2]
252
+ assert_equal 0, $?.exitstatus
253
+ Process.waitpid @test_processes[3]
254
+ assert_equal 0, $?.exitstatus
255
+ ensure
256
+ @test_processes.each do |pid|
257
+ DTR.kill_process pid
258
+ end
259
+ end
260
+
261
+ def test_run_test_case_hacked_run_method
262
+ assert_fork_process_exits_ok do
263
+ require 'hacked_run_method_test_case'
264
+
265
+ $argv_dup = ['hacked_run_method_test_case.rb']
266
+ suite = Test::Unit::TestSuite.new('run_test_case_hacked_run_method')
267
+ suite << HackedRunMethodTestCase.suite
268
+
269
+ @result = runit(suite)
270
+
271
+ assert @result.passed?
272
+ assert_equal 1, @result.run_count
273
+ assert_equal 0, @result.failure_count
274
+ assert_equal 0, @result.error_count
275
+ end
276
+ end
277
+
278
+ def test_should_not_break_heartbeat_of_master_process_when_run_with_a_test_case_sleep_long_time
279
+ assert_fork_process_exits_ok do
280
+ DTR.configuration.master_heartbeat_interval = 1
281
+ DTR.configuration.follower_listen_heartbeat_timeout = 2
282
+
283
+ require 'sleep_3_secs_test_case'
284
+
285
+ $argv_dup = ['sleep_3_secs_test_case.rb']
286
+ suite = Test::Unit::TestSuite.new('run_test_case_sleep_3_secs')
287
+ suite << Sleep3SecsTestCase.suite
288
+
289
+ @result = runit(suite)
290
+
291
+ assert @result.passed?
292
+ assert_equal 1, @result.run_count
293
+ assert_equal 0, @result.failure_count
294
+ assert_equal 0, @result.error_count
295
+ end
296
+ end
297
+
298
+ def test_should_add_meaningful_error_when_runner_get_a_unknown_test
299
+ assert_fork_process_exits_ok do
300
+ $argv_dup = ['a_failed_test_case.rb']
301
+ suite = Test::Unit::TestSuite.new('should_add_meaningful_error_when_runner_get_a_unknown_test')
302
+ suite << ATestCase.suite
303
+
304
+ @result = runit(suite)
305
+
306
+ assert !@result.passed?
307
+ assert_equal 1, @result.run_count
308
+ assert_equal 0, @result.failure_count
309
+ assert_equal 1, @result.error_count
310
+ assert_equal "DTR::RemoteError: DTR::Agent::UnknownTestError from #{Socket.gethostname}: No such test loaded: ATestCase", @result.errors.first.message
311
+ end
312
+ end
313
+
314
+ def test_run_test_timeout
315
+ assert_fork_process_exits_ok do
316
+ require 'sleep_3_secs_test_case'
317
+ $argv_dup = ['sleep_3_secs_test_case.rb']
318
+ suite = Test::Unit::TestSuite.new('run_test_case_sleep_3_secs')
319
+ suite << Sleep3SecsTestCase.suite
320
+
321
+ ENV['RUN_TEST_TIMEOUT'] = '1'
322
+ @result = runit(suite)
323
+
324
+ assert !@result.passed?
325
+ assert_equal 1, @result.run_count
326
+ assert_equal 0, @result.failure_count
327
+ assert_equal 1, @result.error_count
328
+ assert @result.errors.first.message.include?('Timeout')
329
+ end
330
+ end
331
+ end