Home | History | Annotate | Download | only in suite_scheduler
      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/task.py."""
      8 
      9 import mox, unittest
     10 
     11 # driver must be imported first due to circular imports in base_event and task
     12 import driver  # pylint: disable-msg=W0611
     13 import deduping_scheduler, forgiving_config_parser, task, build_event
     14 
     15 
     16 class TaskTestBase(mox.MoxTestBase):
     17     """Common code for Task test classes
     18 
     19     @var _BUILD: fake build.
     20     @var _BOARD: fake board to reimage.
     21     @var _BRANCH: fake branch to run tests on.
     22     @var _BRANCH_SPEC: fake branch specification for Tasks.
     23     @var _MAP: fake branch:build map.
     24     @var _POOL: fake pool of machines to test on.
     25     @var _SUITE: fake suite name.
     26     @var _TASK_NAME: fake name for tasks in config.
     27     """
     28 
     29     _BUILD = 'build'
     30     _BOARD = 'board1'
     31     _BRANCH = '20'
     32     _BRANCH_SPEC = '>=R' + _BRANCH
     33     _BRANCH_SPEC_EQUAL = '==R' + _BRANCH
     34     _BRANCH_SPEC_LTE = '<=R' + _BRANCH
     35     _MAP = {_BRANCH: [_BUILD]}
     36     _NUM = 2
     37     _POOL = 'fake_pool'
     38     _SUITE = 'suite'
     39     _TASK_NAME = 'fake_task_name'
     40     _PRIORITY = build_event.BuildEvent.PRIORITY
     41     _TIMEOUT = build_event.BuildEvent.TIMEOUT
     42     _FILE_BUGS=False
     43 
     44 
     45     def setUp(self):
     46         super(TaskTestBase, self).setUp()
     47         self.sched = self.mox.CreateMock(deduping_scheduler.DedupingScheduler)
     48 
     49 
     50 class TaskCreateTest(TaskTestBase):
     51     """Unit tests for Task.CreateFromConfigSection().
     52 
     53     @var _EVENT_KEY: fake event-to-run-on keyword for tasks in config.
     54     """
     55 
     56     _EVENT_KEY = 'new_build'
     57 
     58 
     59     def setUp(self):
     60         super(TaskCreateTest, self).setUp()
     61         self.config = forgiving_config_parser.ForgivingConfigParser()
     62         self.config.add_section(self._TASK_NAME)
     63         self.config.set(self._TASK_NAME, 'suite', self._SUITE)
     64         self.config.set(self._TASK_NAME, 'branch_specs', self._BRANCH_SPEC)
     65         self.config.set(self._TASK_NAME, 'run_on', self._EVENT_KEY)
     66         self.config.set(self._TASK_NAME, 'pool', self._POOL)
     67         self.config.set(self._TASK_NAME, 'num', '%d' % self._NUM)
     68         self.config.set(self._TASK_NAME, 'boards', self._BOARD)
     69 
     70 
     71     def testCreateFromConfig(self):
     72         """Ensure a Task can be built from a correct config."""
     73         keyword, new_task = task.Task.CreateFromConfigSection(self.config,
     74                                                               self._TASK_NAME)
     75         self.assertEquals(keyword, self._EVENT_KEY)
     76         self.assertEquals(new_task, task.Task(self._TASK_NAME, self._SUITE,
     77                                               [self._BRANCH_SPEC], self._POOL,
     78                                               self._NUM, self._BOARD,
     79                                               self._PRIORITY, self._TIMEOUT))
     80         self.assertTrue(new_task._FitsSpec(self._BRANCH))
     81         self.assertFalse(new_task._FitsSpec('12'))
     82 
     83 
     84     def testCreateFromConfigEqualBranch(self):
     85         """Ensure a Task can be built from a correct config with support of
     86         branch_specs: ==RXX."""
     87         # Modify the branch_specs setting in self.config.
     88         self.config.set(self._TASK_NAME, 'branch_specs',
     89                         self._BRANCH_SPEC_EQUAL)
     90         keyword, new_task = task.Task.CreateFromConfigSection(self.config,
     91                                                               self._TASK_NAME)
     92         self.assertEquals(keyword, self._EVENT_KEY)
     93         self.assertEquals(new_task, task.Task(self._TASK_NAME, self._SUITE,
     94                                               [self._BRANCH_SPEC_EQUAL],
     95                                               self._POOL, self._NUM,
     96                                               self._BOARD, self._PRIORITY,
     97                                               self._TIMEOUT))
     98         self.assertTrue(new_task._FitsSpec(self._BRANCH))
     99         self.assertFalse(new_task._FitsSpec('12'))
    100         self.assertFalse(new_task._FitsSpec('21'))
    101         # Reset the branch_specs setting in self.config to >=R.
    102         self.config.set(self._TASK_NAME, 'branch_specs', self._BRANCH_SPEC)
    103 
    104 
    105     def testCreateFromConfigLessThanOrEqualBranch(self):
    106         """Ensure a Task can be built from a correct config with support of
    107         branch_specs: <=RXX."""
    108         # Modify the branch_specs setting in self.config.
    109         self.config.set(self._TASK_NAME, 'branch_specs',
    110                         self._BRANCH_SPEC_LTE)
    111         keyword, new_task = task.Task.CreateFromConfigSection(self.config,
    112                                                               self._TASK_NAME)
    113         self.assertEquals(keyword, self._EVENT_KEY)
    114         self.assertEquals(new_task, task.Task(self._TASK_NAME, self._SUITE,
    115                                               [self._BRANCH_SPEC_LTE],
    116                                               self._POOL, self._NUM,
    117                                               self._BOARD, self._PRIORITY,
    118                                               self._TIMEOUT))
    119         self.assertTrue(new_task._FitsSpec(self._BRANCH))
    120         self.assertTrue(new_task._FitsSpec('12'))
    121         self.assertFalse(new_task._FitsSpec('21'))
    122         # Reset the branch_specs setting in self.config to >=R.
    123         self.config.set(self._TASK_NAME, 'branch_specs', self._BRANCH_SPEC)
    124 
    125 
    126     def testCreateFromConfigNoBranch(self):
    127         """Ensure a Task can be built from a correct config with no branch."""
    128         self.config.remove_option(self._TASK_NAME, 'branch_specs')
    129         keyword, new_task = task.Task.CreateFromConfigSection(self.config,
    130                                                               self._TASK_NAME)
    131         self.assertEquals(keyword, self._EVENT_KEY)
    132         self.assertEquals(new_task, task.Task(self._TASK_NAME, self._SUITE,
    133                                               [], self._POOL, self._NUM,
    134                                               self._BOARD, self._PRIORITY,
    135                                               self._TIMEOUT))
    136         self.assertTrue(new_task._FitsSpec(self._BRANCH))
    137 
    138 
    139     def testCreateFromConfigMultibranch(self):
    140         """Ensure a Task can be built from a correct config with >1 branches."""
    141         specs = ['factory', self._BRANCH_SPEC]
    142         self.config.set(self._TASK_NAME, 'branch_specs', ','.join(specs))
    143         keyword, new_task = task.Task.CreateFromConfigSection(self.config,
    144                                                               self._TASK_NAME)
    145         self.assertEquals(keyword, self._EVENT_KEY)
    146         self.assertEquals(new_task, task.Task(self._TASK_NAME, self._SUITE,
    147                                               specs, self._POOL, self._NUM,
    148                                               self._BOARD, self._PRIORITY,
    149                                               self._TIMEOUT))
    150         for spec in [specs[0], self._BRANCH]:
    151             self.assertTrue(new_task._FitsSpec(spec))
    152 
    153 
    154     def testCreateFromConfigNoNum(self):
    155         """Ensure a Task can be built from a correct config with no num."""
    156         self.config.remove_option(self._TASK_NAME, 'num')
    157         keyword, new_task = task.Task.CreateFromConfigSection(self.config,
    158                                                               self._TASK_NAME)
    159         self.assertEquals(keyword, self._EVENT_KEY)
    160         self.assertEquals(new_task, task.Task(self._TASK_NAME, self._SUITE,
    161                                               [self._BRANCH_SPEC], self._POOL,
    162                                               boards=self._BOARD))
    163         self.assertTrue(new_task._FitsSpec(self._BRANCH))
    164         self.assertFalse(new_task._FitsSpec('12'))
    165 
    166 
    167     def testCreateFromNoSuiteConfig(self):
    168         """Ensure we require a suite in Task config."""
    169         self.config.remove_option(self._TASK_NAME, 'suite')
    170         self.assertRaises(task.MalformedConfigEntry,
    171                           task.Task.CreateFromConfigSection,
    172                           self.config,
    173                           self._TASK_NAME)
    174 
    175 
    176     def testCreateFromNoKeywordConfig(self):
    177         """Ensure we require a run_on event in Task config."""
    178         self.config.remove_option(self._TASK_NAME, 'run_on')
    179         self.assertRaises(task.MalformedConfigEntry,
    180                           task.Task.CreateFromConfigSection,
    181                           self.config,
    182                           self._TASK_NAME)
    183 
    184 
    185     def testCreateFromNonexistentConfig(self):
    186         """Ensure we fail gracefully if we pass in a bad section name."""
    187         self.assertRaises(task.MalformedConfigEntry,
    188                           task.Task.CreateFromConfigSection,
    189                           self.config,
    190                           'not_a_thing')
    191 
    192 
    193     def testFileBugsNoConfigValue(self):
    194         """Ensure not setting file bugs in a config leads to file_bugs=False."""
    195         keyword, new_task = task.Task.CreateFromConfigSection(self.config,
    196                                                               self._TASK_NAME)
    197         self.assertFalse(new_task._file_bugs)
    198 
    199 
    200 class TaskTest(TaskTestBase):
    201     """Unit tests for Task."""
    202 
    203 
    204     def setUp(self):
    205         super(TaskTest, self).setUp()
    206         self.task = task.Task(self._TASK_NAME, self._SUITE, [self._BRANCH_SPEC],
    207                               None, None, self._BOARD, self._PRIORITY,
    208                               self._TIMEOUT)
    209 
    210 
    211     def testRun(self):
    212         """Test running a recurring task."""
    213         self.sched.ScheduleSuite(self._SUITE, self._BOARD, self._BUILD,
    214                                  None, None, self._PRIORITY, self._TIMEOUT,
    215                                  False, file_bugs=self._FILE_BUGS,
    216                                  firmware_rw_build=None,
    217                                  test_source_build=None,
    218                                  job_retry=False).AndReturn(True)
    219         self.mox.ReplayAll()
    220         self.assertTrue(self.task.Run(self.sched, self._MAP, self._BOARD))
    221 
    222 
    223     def testRunCustomSharding(self):
    224         """Test running a recurring task with non-default sharding."""
    225         expected_sharding = 2
    226         mytask = task.Task(self._TASK_NAME, self._SUITE, [self._BRANCH_SPEC],
    227                            num=expected_sharding)
    228         self.sched.ScheduleSuite(self._SUITE, self._BOARD, self._BUILD,
    229                                  None, expected_sharding, None, None,
    230                                  False, file_bugs=self._FILE_BUGS,
    231                                  firmware_rw_build=None,
    232                                  test_source_build=None,
    233                                  job_retry=False).AndReturn(True)
    234         self.mox.ReplayAll()
    235         self.assertTrue(mytask.Run(self.sched, self._MAP, self._BOARD))
    236 
    237 
    238     def testRunDuplicate(self):
    239         """Test running a task that schedules a duplicate suite task."""
    240         self.sched.ScheduleSuite(self._SUITE, self._BOARD, self._BUILD,
    241                                  None, None, self._PRIORITY, self._TIMEOUT,
    242                                  False, file_bugs=self._FILE_BUGS,
    243                                  firmware_rw_build=None,
    244                                  test_source_build=None,
    245                                  job_retry=False).AndReturn(True)
    246         self.mox.ReplayAll()
    247         self.assertTrue(self.task.Run(self.sched, self._MAP, self._BOARD))
    248 
    249 
    250     def testRunUnrunnablePool(self):
    251         """Test running a task that cannot run on this pool."""
    252         self.sched.CheckHostsExist(
    253                 multiple_labels=mox.IgnoreArg()).AndReturn(None)
    254         self.mox.ReplayAll()
    255         t = task.Task(self._TASK_NAME, self._SUITE,
    256                       [self._BRANCH_SPEC], "BadPool")
    257         self.assertTrue(not t.AvailableHosts(self.sched, self._BOARD))
    258 
    259 
    260     def testRunUnrunnableBoard(self):
    261         """Test running a task that cannot run on this board."""
    262         self.mox.ReplayAll()
    263         t = task.Task(self._TASK_NAME, self._SUITE,
    264                       [self._BRANCH_SPEC], self._POOL, boards="BadBoard")
    265         self.assertTrue(not t.AvailableHosts(self.sched, self._BOARD))
    266 
    267 
    268     def testNoRunBranchMismatch(self):
    269         """Test running a recurring task with no matching builds."""
    270         t = task.Task(self._TASK_NAME, self._SUITE, task.BARE_BRANCHES)
    271         self.mox.ReplayAll()
    272         self.assertTrue(t.Run(self.sched, self._MAP, self._BOARD))
    273 
    274 
    275     def testNoRunBareBranchMismatch(self):
    276         """Test running a recurring task with no matching builds (factory)."""
    277         self.mox.ReplayAll()
    278         self.assertTrue(
    279             self.task.Run(self.sched, {'factory': 'build2'}, self._BOARD))
    280 
    281 
    282     def testRunNoSpec(self):
    283         """Test running a recurring task with default branch specs."""
    284         t = task.Task(self._TASK_NAME, self._SUITE, [])
    285         self.sched.ScheduleSuite(self._SUITE, self._BOARD, self._BUILD,
    286                                  None, None, None, None,
    287                                  False, file_bugs=self._FILE_BUGS,
    288                                  firmware_rw_build=None,
    289                                  test_source_build=None,
    290                                  job_retry=False).AndReturn(True)
    291         self.mox.ReplayAll()
    292         self.assertTrue(t.Run(self.sched, self._MAP, self._BOARD))
    293 
    294 
    295     def testRunExplodes(self):
    296         """Test a failure to schedule while running task."""
    297         # Barf while scheduling.
    298         self.sched.ScheduleSuite(
    299             self._SUITE, self._BOARD, self._BUILD, None, None, self._PRIORITY,
    300             self._TIMEOUT, False, file_bugs=self._FILE_BUGS,
    301             firmware_rw_build=None, test_source_build=None,
    302             job_retry=False).AndRaise(
    303                     deduping_scheduler.ScheduleException('Simulated Failure'))
    304         self.mox.ReplayAll()
    305         self.assertTrue(self.task.Run(self.sched, self._MAP, self._BOARD))
    306 
    307 
    308     def testForceRun(self):
    309         """Test force running a recurring task."""
    310         self.sched.ScheduleSuite(self._SUITE, self._BOARD, self._BUILD,
    311                                  None, None, self._PRIORITY, self._TIMEOUT,
    312                                  True, file_bugs=self._FILE_BUGS,
    313                                  firmware_rw_build=None,
    314                                  test_source_build=None,
    315                                  job_retry=False).AndReturn(True)
    316         self.mox.ReplayAll()
    317         self.assertTrue(self.task.Run(self.sched, self._MAP, self._BOARD, True))
    318 
    319 
    320     def testHash(self):
    321         """Test hash function for Task classes."""
    322         same_task = task.Task(self._TASK_NAME, self._SUITE, [self._BRANCH_SPEC],
    323                               boards=self._BOARD)
    324         other_task = task.Task(self._TASK_NAME, self._SUITE,
    325                                [self._BRANCH_SPEC, '>=RX1'], 'pool')
    326         self.assertEquals(hash(self.task), hash(same_task))
    327         self.assertNotEquals(hash(self.task), hash(other_task))
    328 
    329 
    330 class OneShotTaskTest(TaskTestBase):
    331     """Unit tests for OneShotTask."""
    332 
    333 
    334     def setUp(self):
    335         super(OneShotTaskTest, self).setUp()
    336         self.task = task.OneShotTask(self._TASK_NAME, self._SUITE,
    337                                      [self._BRANCH_SPEC])
    338 
    339 
    340     def testRun(self):
    341         """Test running a one-shot task."""
    342         self.sched.ScheduleSuite(self._SUITE, self._BOARD, self._BUILD,
    343                                  None, None, None, None, False,
    344                                  file_bugs=self._FILE_BUGS,
    345                                  firmware_rw_build=None,
    346                                  test_source_build=None,
    347                                  job_retry=False).AndReturn(True)
    348         self.mox.ReplayAll()
    349         self.assertFalse(self.task.Run(self.sched, self._MAP, self._BOARD))
    350 
    351 
    352     def testRunDuplicate(self):
    353         """Test running a one-shot task that schedules a dup suite task."""
    354         self.sched.ScheduleSuite(self._SUITE, self._BOARD, self._BUILD,
    355                                  None, None, None, None, False,
    356                                  file_bugs=self._FILE_BUGS,
    357                                  firmware_rw_build=None,
    358                                  test_source_build=None,
    359                                  job_retry=False).AndReturn(False)
    360         self.mox.ReplayAll()
    361         self.assertFalse(self.task.Run(self.sched, self._MAP, self._BOARD))
    362 
    363 
    364     def testRunExplodes(self):
    365         """Test a failure to schedule while running one-shot task."""
    366         # Barf while scheduling.
    367         self.sched.ScheduleSuite(
    368             self._SUITE, self._BOARD, self._BUILD, None, None,
    369             None, None, False, file_bugs=self._FILE_BUGS,
    370             firmware_rw_build=None, test_source_build=None,
    371             job_retry=False).AndRaise(
    372                 deduping_scheduler.ScheduleException('Simulated Failure'))
    373         self.mox.ReplayAll()
    374         self.assertFalse(self.task.Run(self.sched, self._MAP, self._BOARD))
    375 
    376 
    377     def testForceRun(self):
    378         """Test force running a one-shot task."""
    379         self.sched.ScheduleSuite(self._SUITE, self._BOARD, self._BUILD,
    380                                  None, None, None, None, True,
    381                                  file_bugs=self._FILE_BUGS,
    382                                  firmware_rw_build=None,
    383                                  test_source_build=None,
    384                                  job_retry=False).AndReturn(True)
    385         self.mox.ReplayAll()
    386         self.assertFalse(self.task.Run(self.sched, self._MAP, self._BOARD,
    387                                        force=True))
    388 
    389 
    390     def testFileBugs(self):
    391         """Test that file_bugs is passed from the task to ScheduleSuite."""
    392         self.sched.ScheduleSuite(self._SUITE, self._BOARD, self._BUILD,
    393                                  None, None, None, None, True,
    394                                  file_bugs=True, firmware_rw_build=None,
    395                                  test_source_build=None,
    396                                  job_retry=False).AndReturn(True)
    397         self.mox.ReplayAll()
    398         self.task._file_bugs = True
    399         self.assertFalse(self.task.Run(self.sched, self._MAP, self._BOARD,
    400                                        force=True))
    401 
    402 
    403 if __name__ == '__main__':
    404     unittest.main()
    405