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/manifest_versions.py."""
      8 
      9 # Turn off "access to protected member of class"
     10 # pylint: disable=W0212
     11 
     12 import datetime
     13 import os
     14 import re
     15 import time
     16 import unittest
     17 
     18 import mox
     19 
     20 import common
     21 from autotest_lib.client.common_lib import error
     22 from autotest_lib.client.common_lib import utils
     23 from autotest_lib.site_utils.suite_scheduler import manifest_versions
     24 
     25 
     26 class ManifestVersionsTest(mox.MoxTestBase):
     27     """Unit tests for ManifestVersions.
     28 
     29     @var _BRANCHES: canned branches that should parse out of the below.
     30     @var _MANIFESTS_STRING: canned (string) list of manifest file paths.
     31     """
     32 
     33     _BRANCHES = [('release', '18'), ('release', '19'), ('release', '20'),
     34                  ('factory', '20'), ('firmware', '20')]
     35     _MANIFESTS_STRING = """
     36 build-name/x86-alex-release-group/pass/20/2057.0.9.xml
     37 
     38 
     39 build-name/x86-alex-release-group/pass/20/2057.0.10.xml
     40 
     41 
     42 build-name/x86-alex-release-group/pass/20/2054.0.0.xml
     43 
     44 
     45 build-name/x86-alex-release/pass/18/1660.103.0.xml
     46 
     47 
     48 build-name/x86-alex-release-group/pass/20/2051.0.0.xml
     49 
     50 
     51 build-name/x86-alex-firmware/pass/20/2048.1.1.xml
     52 
     53 
     54 build-name/x86-alex-release/pass/19/2046.3.0.xml
     55 
     56 
     57 build-name/x86-alex-release-group/pass/20/2050.0.0.xml
     58 
     59 
     60 build-name/x86-alex-release-group/pass/20/2048.0.0.xml
     61 
     62 
     63 build-name/x86-alex-factory/pass/20/2048.1.0.xml
     64 """
     65 
     66 
     67     def setUp(self):
     68         """Initialization for unit tests."""
     69         super(ManifestVersionsTest, self).setUp()
     70         self.mv = manifest_versions.ManifestVersions()
     71 
     72 
     73     def testInitialize(self):
     74         """Ensure we can initialize a ManifestVersions."""
     75         self.mox.StubOutWithMock(self.mv, '_Clone')
     76         self.mox.StubOutWithMock(time, 'sleep')
     77         self.mv._Clone()
     78         self.mox.ReplayAll()
     79         self.mv.Initialize()
     80 
     81 
     82     def testInitializeRetry(self):
     83         """Ensure we retry _Clone() the correct number of times."""
     84         self.mox.StubOutWithMock(self.mv, '_Clone')
     85         self.mox.StubOutWithMock(time, 'sleep')
     86         for i in range(0, self.mv._CLONE_MAX_RETRIES):
     87             self.mv._Clone().AndRaise(
     88                 error.CmdError('retried git clone failure',
     89                                utils.CmdResult()))
     90             time.sleep(self.mv._CLONE_RETRY_SECONDS)
     91         self.mv._Clone()
     92         self.mox.ReplayAll()
     93         self.mv.Initialize()
     94 
     95 
     96     def testInitializeFail(self):
     97         """Ensure we fail after too many _Clone() retries."""
     98         self.mox.StubOutWithMock(self.mv, '_Clone')
     99         self.mox.StubOutWithMock(time, 'sleep')
    100         for i in range(0, self.mv._CLONE_MAX_RETRIES):
    101             self.mv._Clone().AndRaise(
    102                 error.CmdError('retried git clone failure',
    103                                utils.CmdResult()))
    104             time.sleep(self.mv._CLONE_RETRY_SECONDS)
    105         self.mv._Clone().AndRaise(
    106             error.CmdError('final git clone failure',
    107                            utils.CmdResult()))
    108         self.mox.ReplayAll()
    109         self.assertRaises(manifest_versions.CloneException,
    110                           self.mv.Initialize)
    111 
    112 
    113     def testGlobs(self):
    114         """Ensure that we expand globs correctly."""
    115         desired_paths = ['one/path', 'two/path', 'three/path']
    116         tempdir = self.mv._tempdir.name
    117         for path in desired_paths:
    118             os.makedirs(os.path.join(tempdir, path))
    119         for path in self.mv._ExpandGlobMinusPrefix(tempdir, '*/path'):
    120             self.assertTrue(path in desired_paths)
    121 
    122 
    123     def _ExpectGlob(self, to_return):
    124         self.mox.StubOutWithMock(self.mv, '_ExpandGlobMinusPrefix')
    125         self.mv._ExpandGlobMinusPrefix(mox.IgnoreArg(),
    126                                        mox.IgnoreArg()).AndReturn(to_return)
    127 
    128 
    129     def testAnyManifestsSinceRev(self):
    130         """Ensure we can tell if builds have succeeded since a given rev."""
    131         rev = 'rev'
    132         self._ExpectGlob(['some/paths'])
    133         self.mox.StubOutWithMock(manifest_versions, '_SystemOutput')
    134         manifest_versions._SystemOutput(
    135             mox.And(mox.StrContains('log'),
    136                     mox.StrContains(rev))).MultipleTimes().AndReturn(
    137                         self._MANIFESTS_STRING)
    138         self.mox.ReplayAll()
    139         self.assertTrue(self.mv.AnyManifestsSinceRev(rev))
    140 
    141 
    142     def testNoManifestsSinceRev(self):
    143         """Ensure we can tell if no builds have succeeded since a given rev."""
    144         rev = 'rev'
    145         self._ExpectGlob(['some/paths'])
    146         self.mox.StubOutWithMock(manifest_versions, '_SystemOutput')
    147         manifest_versions._SystemOutput(
    148             mox.And(mox.StrContains('log'),
    149                     mox.StrContains(rev))).MultipleTimes().AndReturn(' ')
    150         self.mox.ReplayAll()
    151         self.assertFalse(self.mv.AnyManifestsSinceRev(rev))
    152 
    153 
    154     def testNoManifestsPathsSinceRev(self):
    155         """Ensure we can tell that we have no paths to check for new builds."""
    156         rev = 'rev'
    157         self._ExpectGlob([])
    158         self.mox.ReplayAll()
    159         self.assertFalse(self.mv.AnyManifestsSinceRev(rev))
    160 
    161 
    162     def testManifestsSinceDate(self):
    163         """Ensure we can get manifests for a board since N days ago."""
    164         since_date = datetime.datetime(year=2015, month=2, day=1)
    165         board = 'x86-alex'
    166         self._ExpectGlob(['some/paths'])
    167         self.mox.StubOutWithMock(manifest_versions, '_SystemOutput')
    168         manifest_versions._SystemOutput(
    169             mox.StrContains('log')).MultipleTimes().AndReturn(
    170                 self._MANIFESTS_STRING)
    171         self.mox.ReplayAll()
    172         br_man = self.mv.ManifestsSinceDate(since_date, board)
    173         for pair in br_man.keys():
    174             self.assertTrue(pair, self._BRANCHES)
    175         for manifest_list in br_man.itervalues():
    176             self.assertTrue(manifest_list)
    177         self.assertEquals(br_man[('release', '20')][-1], '2057.0.10')
    178 
    179 
    180     def testNoManifestsSinceDate(self):
    181         """Ensure we can deal with no manifests since N days ago."""
    182         since_date = datetime.datetime(year=2015, month=2, day=1)
    183         board = 'x86-alex'
    184         self._ExpectGlob(['some/paths'])
    185         self.mox.StubOutWithMock(manifest_versions, '_SystemOutput')
    186         manifest_versions._SystemOutput(mox.StrContains('log')).AndReturn([])
    187         self.mox.ReplayAll()
    188         br_man = self.mv.ManifestsSinceDate(since_date, board)
    189         self.assertEquals(br_man, {})
    190 
    191 
    192     def testNoManifestsPathsSinceDate(self):
    193         """Ensure we can deal with finding no paths to pass to'git log'."""
    194         since_date = datetime.datetime(year=2015, month=2, day=1)
    195         board = 'x86-alex'
    196         self._ExpectGlob([])
    197         self.mox.ReplayAll()
    198         br_man = self.mv.ManifestsSinceDate(since_date, board)
    199         self.assertEquals(br_man, {})
    200 
    201 
    202     def testManifestsSinceDateExplodes(self):
    203         """Ensure we handle failures in querying manifests."""
    204         since_date = datetime.datetime(year=2015, month=2, day=1)
    205         board = 'x86-alex'
    206         self._ExpectGlob(['some/paths'])
    207         self.mox.StubOutWithMock(manifest_versions, '_SystemOutput')
    208         manifest_versions._SystemOutput(mox.StrContains('log')).AndRaise(
    209             manifest_versions.QueryException())
    210         self.mox.ReplayAll()
    211         self.assertRaises(manifest_versions.QueryException,
    212                           self.mv.ManifestsSinceDate, since_date, board)
    213 
    214 
    215     def testUnparseableManifestPath(self):
    216         """Ensure we don't explode if we encounter an unparseable path."""
    217         since_date = datetime.datetime(year=2015, month=2, day=1)
    218         board = 'link'
    219         build_name = 'link-depthcharge-pgo-codename-release-suffix-part-two'
    220         manifest = 'build-name/%s/pass/25/1234.0.0.xml' % build_name
    221         self._ExpectGlob(['some/paths'])
    222         self.mox.StubOutWithMock(manifest_versions, '_SystemOutput')
    223         manifest_versions._SystemOutput(
    224             mox.StrContains('log')).MultipleTimes().AndReturn(manifest)
    225         self.mox.ReplayAll()
    226         br_man = self.mv.ManifestsSinceDate(since_date, board)
    227         # We should skip the manifest that we passed in, as we can't parse it,
    228         # so we should get no manifests back.
    229         self.assertEquals(br_man, {})
    230 
    231 
    232     _BOARD_MANIFESTS = {
    233         'lumpy': [
    234             'lumpy-factory',
    235             'lumpy-release',
    236 #            'lumpy-pgo-release',
    237         ],
    238         'x86-alex': [
    239             'x86-alex-release',
    240             'x86-alex-release-group',
    241         ],
    242         'link': [
    243 #            'link-depthcharge-firmware',
    244         ],
    245     }
    246 
    247 
    248     def testBoardManifestRePattern(self):
    249         """Ensure we can parse the names of builds that are produced."""
    250         for board, builder_names in self._BOARD_MANIFESTS.items():
    251             rgx = re.compile(
    252                 manifest_versions.ManifestVersions._BOARD_MANIFEST_RE_PATTERN %\
    253                     board)
    254             for builder_name in builder_names:
    255                 manifest = 'build-name/%s/pass/25/1234.0.0.xml' % builder_name
    256                 self.assertTrue(rgx.match(manifest), msg=builder_name)
    257 
    258 
    259     def testGetManifests(self):
    260         """Test _GetManifests when pattern is matched and not matched."""
    261         rgx = re.compile(
    262                 self.mv._BOARD_MANIFEST_RE_PATTERN %
    263                 'lumpy')
    264         self.assertEqual(self.mv._GetManifests(
    265             rgx, ['build-name/lumpy-release/pass/25/1234.0.0.xml']),
    266             {('release', '25'): ['1234.0.0']})
    267         self.assertEqual(self.mv._GetManifests(
    268             rgx, ['build-name/stumpy-release/pass/25/1234.0.0.xml']), {})
    269 
    270 
    271 if __name__ == '__main__':
    272     unittest.main()
    273