Class: Toaster::TestRunner
- Inherits:
-
Object
- Object
- Toaster::TestRunner
- Defined in:
- lib/toaster/test/test_runner.rb
Class Attribute Summary collapse
-
.delay_between_tests ⇒ Object
Returns the value of attribute delay_between_tests.
-
.last_start_time ⇒ Object
Returns the value of attribute last_start_time.
-
.semaphore ⇒ Object
Returns the value of attribute semaphore.
-
.signal ⇒ Object
Returns the value of attribute signal.
-
.singleton ⇒ Object
Returns the value of attribute singleton.
Class Method Summary collapse
- .ensure_automation_exists_in_db(automation_name, recipes, test_suite, destroy_container = true, print_output = false) ⇒ Object
-
.execute_test(test_case, destroy_container = true, print_output = false, num_attempts = 2) ⇒ Object
execute the provided test case.
-
.instance ⇒ Object
singleton pattern.
Instance Method Summary collapse
- #execute_test_case(test_case, do_wait_until_finished = true) ⇒ Object
- #execute_tests(test_cases, do_wait_until_finished = true) ⇒ Object
- #schedule_test_case(test_case) ⇒ Object
- #schedule_tests(test_suite, test_case_uuids) ⇒ Object
- #start ⇒ Object
- #stop ⇒ Object
Class Attribute Details
.delay_between_tests ⇒ Object
Returns the value of attribute delay_between_tests.
29 30 31 |
# File 'lib/toaster/test/test_runner.rb', line 29 def delay_between_tests @delay_between_tests end |
.last_start_time ⇒ Object
Returns the value of attribute last_start_time.
29 30 31 |
# File 'lib/toaster/test/test_runner.rb', line 29 def last_start_time @last_start_time end |
.semaphore ⇒ Object
Returns the value of attribute semaphore.
29 30 31 |
# File 'lib/toaster/test/test_runner.rb', line 29 def semaphore @semaphore end |
.signal ⇒ Object
Returns the value of attribute signal.
29 30 31 |
# File 'lib/toaster/test/test_runner.rb', line 29 def signal @signal end |
.singleton ⇒ Object
Returns the value of attribute singleton.
29 30 31 |
# File 'lib/toaster/test/test_runner.rb', line 29 def singleton @singleton end |
Class Method Details
.ensure_automation_exists_in_db(automation_name, recipes, test_suite, destroy_container = true, print_output = false) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/toaster/test/test_runner.rb', line 101 def self.ensure_automation_exists_in_db(automation_name, recipes, test_suite, destroy_container=true, print_output=false) chef_node_name = ChefUtil.extract_node_name(automation_name) # prepare run list (add toaster::testing recipe definitions) actual_run_list = ChefUtil.prepare_run_list(chef_node_name, recipes) reduced_run_list = ChefUtil.get_reduced_run_list(actual_run_list) automation = Automation.find_by_cookbook_and_runlist(automation_name, reduced_run_list) return automation if !automation.nil? # if we don't have a matching automation in the DB yet, execute an initial run.. c = TestCase.new(test_suite) test_suite.test_cases << c puts "INFO: Executing initial automation run; test case '#{c.uuid}'" automation_run = execute_test(c, destroy_container, print_output) puts "DEBUG: Finished execution of initial automation run; test case '#{c.uuid}': #{automation_run}" return nil if !automation_run return automation_run.automation end |
.execute_test(test_case, destroy_container = true, print_output = false, num_attempts = 2) ⇒ Object
execute the provided test case
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/toaster/test/test_runner.rb', line 124 def self.execute_test(test_case, destroy_container=true, print_output=false, num_attempts=2) test_suite = nil test_id = nil recipes = nil automation = nil self.semaphore.synchronize do test_suite = test_case.test_suite automation = test_suite.automation test_id = test_suite.uuid recipes = automation.recipes end sleep_time = 0 self.semaphore.synchronize do time = TimeStamp.now() diff = time - self.last_start_time if diff < self.delay_between_tests.to_f sleep_time = self.delay_between_tests.to_f - diff end self.last_start_time = time + sleep_time end # sleep a bit, and then this test is ready to go... sleep(sleep_time) time_now = TimeStamp.now() test_case.start_time = time_now # start test case execution automation_run = nil error_output = nil while num_attempts > 0 begin automation_run = nil if automation.is_chef? # generate automation attributes which represent this test case chef_node_attrs = test_case.create_chef_node_attrs() # set cookbook if necessary automation.cookbook = automation.get_short_name if !automation.cookbook # now run test! automation_run = TestRunner.do_execute_test_chef(automation.cookbook, automation.script, recipes, chef_node_attrs, test_suite.lxc_prototype, test_id, destroy_container, print_output) else raise "Unknown automation language/type: '#{automation.language}'" end automation_run.success = true test_case.test_suite().test_cases << test_case if !test_case.test_suite().test_cases().include?(test_case) test_case.automation_run = automation_run num_attempts = 0 rescue Object => ex error_output = ex num_attempts -= 1 puts "WARN: cannot run test case '#{test_case.uuid}' (remaining attempts: #{num_attempts}): #{ex}" puts "#{ex.backtrace.join("\n")}" end end if !automation_run machine_id = Util.get_machine_id() automation = test_case.test_suite.automation automation_run = AutomationRun.new( :automation => automation, :machine_id => machine_id, :user => test_case.test_suite.user ) puts "WARN: Test case '#{test_case.uuid}' failed entirely, storing " + "an empty automation run '#{test_case.automation_run}' with success=false." automation_run.success = false automation_run.end_time = TimeStamp.now automation_run.error_details = "Test case '#{test_case.uuid}' failed " + "(no automation run created by test runner). Output:\n#{error_output}" automation_run.save test_case.automation_run = automation_run end test_case.end_time = TimeStamp.now().to_i test_case.save return automation_run end |
.instance ⇒ Object
singleton pattern
92 93 94 95 96 97 98 99 |
# File 'lib/toaster/test/test_runner.rb', line 92 def self.instance self.semaphore.synchronize do if !self.singleton self.singleton = TestRunner.new() end end return singleton end |
Instance Method Details
#execute_test_case(test_case, do_wait_until_finished = true) ⇒ Object
75 76 77 |
# File 'lib/toaster/test/test_runner.rb', line 75 def execute_test_case(test_case, do_wait_until_finished=true) execute_tests(test_case, do_wait_until_finished) end |
#execute_tests(test_cases, do_wait_until_finished = true) ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/toaster/test/test_runner.rb', line 78 def execute_tests(test_cases, do_wait_until_finished=true) test_cases = [test_cases] if !test_cases.kind_of?(Array) test_cases.each do |test| puts "INFO: Pushing test case to queue: #{test.uuid}" @request_queue.push(test) end if do_wait_until_finished puts "INFO: Waiting until #{test_cases.size} test cases are finished." wait_until_finished(test_cases) end end |
#schedule_test_case(test_case) ⇒ Object
72 73 74 |
# File 'lib/toaster/test/test_runner.rb', line 72 def schedule_test_case(test_case) execute_test_case(test_case, false) end |
#schedule_tests(test_suite, test_case_uuids) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/toaster/test/test_runner.rb', line 59 def schedule_tests(test_suite, test_case_uuids) test_cases = [] test_case_uuids.each do |tc| if !tc.kind_of?(TestCase) tc = TestCase.find(:uuid => tc)[0] end test_cases << tc end test_cases.each do |tc| schedule_test_case(tc) end end |
#start ⇒ Object
51 52 53 |
# File 'lib/toaster/test/test_runner.rb', line 51 def start() start_worker_threads() end |
#stop ⇒ Object
55 56 57 |
# File 'lib/toaster/test/test_runner.rb', line 55 def stop() stop_threads() end |