1#!/usr/bin/python 2# 3# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7"""Unit tests for site_utils/deduping_scheduler.py.""" 8 9import mox 10import unittest 11 12# driver must be imported first due to circular imports in base_event and task 13import driver # pylint: disable-msg=W0611 14import deduping_scheduler 15 16import common 17from autotest_lib.client.common_lib import error 18from autotest_lib.client.common_lib import priorities 19from autotest_lib.server import frontend, site_utils 20from autotest_lib.server.cros.dynamic_suite import reporting 21 22 23class DedupingSchedulerTest(mox.MoxTestBase): 24 """Unit tests for DedupingScheduler 25 26 @var _BUILD: fake build 27 @var _BOARD: fake board to reimage 28 @var _SUITE: fake suite name 29 @var _POOL: fake machine pool name 30 """ 31 32 _BUILD = 'build' 33 _BUILDS = {'cros-version': 'build'} 34 _BOARD = 'board' 35 _SUITE = 'suite' 36 _POOL = 'pool' 37 _NUM = 2 38 _PRIORITY = priorities.Priority.POSTBUILD 39 _TIMEOUT = 24 40 41 42 def setUp(self): 43 super(DedupingSchedulerTest, self).setUp() 44 self.afe = self.mox.CreateMock(frontend.AFE) 45 self.scheduler = deduping_scheduler.DedupingScheduler(afe=self.afe) 46 self.mox.StubOutWithMock(site_utils, 'check_lab_status') 47 48 49 def _SetupLabStatus(self, build, message=None): 50 """Set up to mock one call to `site_utils.check_lab_status()`. 51 52 @param build The build to expect to be passed to 53 `check_lab_status()`. 54 @param message `None` if the mocked call should return that 55 the lab status is up. Otherwise, a string for 56 the exception message. 57 58 """ 59 if message is None: 60 site_utils.check_lab_status(build) 61 else: 62 site_utils.check_lab_status(build).AndRaise( 63 site_utils.TestLabException(message)) 64 65 66 def testScheduleSuite(self): 67 """Test a successful de-dup and suite schedule.""" 68 # Lab is UP! 69 self._SetupLabStatus(self._BUILD) 70 # A similar suite has not already been scheduled. 71 self.afe.get_jobs(name__startswith=self._BUILD, 72 name__endswith='control.'+self._SUITE, 73 created_on__gte=mox.IgnoreArg()).AndReturn([]) 74 # Expect an attempt to schedule; allow it to succeed. 75 self.afe.run('create_suite_job', 76 name=self._SUITE, 77 board=self._BOARD, 78 builds=self._BUILDS, 79 check_hosts=False, 80 pool=self._POOL, 81 num=self._NUM, 82 priority=self._PRIORITY, 83 test_source_build=None, 84 timeout=self._TIMEOUT, 85 file_bugs=False, 86 wait_for_results=False, 87 job_retry=False).AndReturn(7) 88 self.mox.ReplayAll() 89 self.assertTrue(self.scheduler.ScheduleSuite(self._SUITE, 90 self._BOARD, 91 self._BUILD, 92 self._POOL, 93 self._NUM, 94 self._PRIORITY, 95 self._TIMEOUT)) 96 97 98 def testShouldNotScheduleSuite(self): 99 """Test a successful de-dup and avoiding scheduling the suite.""" 100 # Lab is UP! 101 self._SetupLabStatus(self._BUILD) 102 # A similar suite has already been scheduled. 103 self.afe.get_jobs( 104 name__startswith=self._BUILD, 105 name__endswith='control.'+self._SUITE, 106 created_on__gte=mox.IgnoreArg()).AndReturn(['42']) 107 self.mox.ReplayAll() 108 self.assertFalse(self.scheduler.ScheduleSuite(self._SUITE, 109 self._BOARD, 110 self._BUILD, 111 self._POOL, 112 None, 113 self._PRIORITY, 114 self._TIMEOUT)) 115 116 117 def testShouldNotScheduleSuiteLabClosed(self): 118 """Test that we don't schedule when the lab is closed.""" 119 # Lab is down. :-( 120 self._SetupLabStatus(self._BUILD, 'Lab closed due to sheep.') 121 self.mox.ReplayAll() 122 self.assertFalse(self.scheduler.ScheduleSuite(self._SUITE, 123 self._BOARD, 124 self._BUILD, 125 self._POOL, 126 None, 127 self._PRIORITY, 128 self._TIMEOUT)) 129 130 131 def testForceScheduleSuite(self): 132 """Test a successful de-dup, but force scheduling the suite.""" 133 # Expect an attempt to schedule; allow it to succeed. 134 self.afe.run('create_suite_job', 135 name=self._SUITE, 136 board=self._BOARD, 137 builds=self._BUILDS, 138 check_hosts=False, 139 num=None, 140 pool=self._POOL, 141 priority=self._PRIORITY, 142 test_source_build=None, 143 timeout=self._TIMEOUT, 144 file_bugs=False, 145 wait_for_results=False, 146 job_retry=False).AndReturn(7) 147 self.mox.ReplayAll() 148 self.assertTrue(self.scheduler.ScheduleSuite(self._SUITE, 149 self._BOARD, 150 self._BUILD, 151 self._POOL, 152 None, 153 self._PRIORITY, 154 self._TIMEOUT, 155 force=True)) 156 157 158 def testShouldScheduleSuiteExplodes(self): 159 """Test a failure to de-dup.""" 160 # Lab is UP! 161 self._SetupLabStatus(self._BUILD) 162 # Barf while checking for similar suites. 163 self.afe.get_jobs( 164 name__startswith=self._BUILD, 165 name__endswith='control.'+self._SUITE, 166 created_on__gte=mox.IgnoreArg()).AndRaise(Exception()) 167 self.mox.ReplayAll() 168 self.assertRaises(deduping_scheduler.DedupException, 169 self.scheduler.ScheduleSuite, 170 self._SUITE, 171 self._BOARD, 172 self._BUILD, 173 self._POOL, 174 self._NUM, 175 self._PRIORITY, 176 self._TIMEOUT) 177 178 179 def testScheduleFail(self): 180 """Test a successful de-dup and failure to schedule the suite.""" 181 # Lab is UP! 182 self._SetupLabStatus(self._BUILD) 183 # A similar suite has not already been scheduled. 184 self.afe.get_jobs(name__startswith=self._BUILD, 185 name__endswith='control.'+self._SUITE, 186 created_on__gte=mox.IgnoreArg()).AndReturn([]) 187 # Expect an attempt to create a job for the suite; fail it. 188 self.afe.run('create_suite_job', 189 name=self._SUITE, 190 board=self._BOARD, 191 builds=self._BUILDS, 192 check_hosts=False, 193 num=None, 194 pool=None, 195 priority=self._PRIORITY, 196 test_source_build=None, 197 timeout=self._TIMEOUT, 198 file_bugs=False, 199 wait_for_results=False).AndReturn(None) 200 self.mox.ReplayAll() 201 self.assertRaises(deduping_scheduler.ScheduleException, 202 self.scheduler.ScheduleSuite, 203 self._SUITE, 204 self._BOARD, 205 self._BUILD, 206 None, 207 None, 208 self._PRIORITY, 209 self._TIMEOUT) 210 211 212 def testScheduleExplodes(self): 213 """Test a successful de-dup and barf while scheduling the suite.""" 214 # Lab is UP! 215 self._SetupLabStatus(self._BUILD) 216 # A similar suite has not already been scheduled. 217 self.afe.get_jobs(name__startswith=self._BUILD, 218 name__endswith='control.'+self._SUITE, 219 created_on__gte=mox.IgnoreArg()).AndReturn([]) 220 # Expect an attempt to create a job for the suite; barf on it. 221 self.afe.run('create_suite_job', 222 name=self._SUITE, 223 board=self._BOARD, 224 builds=self._BUILDS, 225 check_hosts=False, 226 num=None, 227 pool=None, 228 priority=self._PRIORITY, 229 test_source_build=None, 230 timeout=self._TIMEOUT, 231 file_bugs=False, 232 wait_for_results=False).AndRaise(Exception()) 233 self.mox.ReplayAll() 234 self.assertRaises(deduping_scheduler.ScheduleException, 235 self.scheduler.ScheduleSuite, 236 self._SUITE, 237 self._BOARD, 238 self._BUILD, 239 None, 240 None, 241 self._PRIORITY, 242 self._TIMEOUT) 243 244 245 def _SetupScheduleSuiteMocks(self, mock_bug_id): 246 """Setup mocks needed for SuiteSchedulerBug testing. 247 248 @param mock_bug_id: An integer representing a bug id that should be 249 returned by Reporter._create_bug_report 250 None if _create_bug_report is supposed to 251 fail. 252 """ 253 self.mox.StubOutWithMock(reporting.Reporter, '__init__') 254 self.mox.StubOutWithMock(reporting.Reporter, '_create_bug_report') 255 self.mox.StubOutWithMock(reporting.Reporter, '_check_tracker') 256 self.mox.StubOutWithMock(reporting.Reporter, 'find_issue_by_marker') 257 self.mox.StubOutWithMock(site_utils, 'get_sheriffs') 258 self.scheduler._file_bug = True 259 # Lab is UP! 260 self._SetupLabStatus(self._BUILD) 261 # A similar suite has not already been scheduled. 262 self.afe.get_jobs(name__startswith=self._BUILD, 263 name__endswith='control.'+self._SUITE, 264 created_on__gte=mox.IgnoreArg()).AndReturn([]) 265 message = 'Control file not found.' 266 exception = error.ControlFileNotFound(message) 267 site_utils.get_sheriffs(lab_only=True).AndReturn(['deputy1', 'deputy2']) 268 self.afe.run('create_suite_job', 269 name=self._SUITE, 270 board=self._BOARD, 271 builds=self._BUILDS, 272 check_hosts=False, 273 pool=self._POOL, 274 num=self._NUM, 275 priority=self._PRIORITY, 276 test_source_build=None, 277 timeout=self._TIMEOUT, 278 file_bugs=False, 279 wait_for_results=False, 280 job_retry=False).AndRaise(exception) 281 reporting.Reporter.__init__() 282 reporting.Reporter._check_tracker().AndReturn(True) 283 reporting.Reporter.find_issue_by_marker(mox.IgnoreArg()).AndReturn(None) 284 reporting.Reporter._create_bug_report( 285 mox.IgnoreArg(), {}, []).AndReturn(mock_bug_id) 286 287 288 def testScheduleReportsBugSuccess(self): 289 """Test that the scheduler file a bug.""" 290 self._SetupScheduleSuiteMocks(1158) 291 self.mox.ReplayAll() 292 self.assertFalse(self.scheduler.ScheduleSuite( 293 self._SUITE, self._BOARD, self._BUILD, self._POOL, 294 self._NUM, self._PRIORITY, self._TIMEOUT)) 295 self.mox.VerifyAll() 296 297 298 def testScheduleReportsBugFalse(self): 299 """Test that the scheduler failed to file a bug.""" 300 self._SetupScheduleSuiteMocks(None) 301 self.mox.ReplayAll() 302 self.assertRaises( 303 deduping_scheduler.ScheduleException, 304 self.scheduler.ScheduleSuite, 305 self._SUITE, self._BOARD, self._BUILD, self._POOL, 306 self._NUM, self._PRIORITY, self._TIMEOUT) 307 self.mox.VerifyAll() 308 309 310if __name__ == '__main__': 311 unittest.main() 312