dtr 0.0.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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