#!/usr/bin/python # # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Unit tests for site_utils/manifest_versions.py.""" # Turn off "access to protected member of class" # pylint: disable=W0212 import datetime import os import re import time import unittest import mox import common from autotest_lib.client.common_lib import error from autotest_lib.client.common_lib import utils from autotest_lib.site_utils.suite_scheduler import manifest_versions class ManifestVersionsTest(mox.MoxTestBase): """Unit tests for ManifestVersions. @var _BRANCHES: canned branches that should parse out of the below. @var _MANIFESTS_STRING: canned (string) list of manifest file paths. """ _BRANCHES = [('release', '18'), ('release', '19'), ('release', '20'), ('factory', '20'), ('firmware', '20')] _MANIFESTS_STRING = """ build-name/x86-alex-release-group/pass/20/2057.0.9.xml build-name/x86-alex-release-group/pass/20/2057.0.10.xml build-name/x86-alex-release-group/pass/20/2054.0.0.xml build-name/x86-alex-release/pass/18/1660.103.0.xml build-name/x86-alex-release-group/pass/20/2051.0.0.xml build-name/x86-alex-firmware/pass/20/2048.1.1.xml build-name/x86-alex-release/pass/19/2046.3.0.xml build-name/x86-alex-release-group/pass/20/2050.0.0.xml build-name/x86-alex-release-group/pass/20/2048.0.0.xml build-name/x86-alex-factory/pass/20/2048.1.0.xml """ def setUp(self): """Initialization for unit tests.""" super(ManifestVersionsTest, self).setUp() self.mv = manifest_versions.ManifestVersions() def testInitialize(self): """Ensure we can initialize a ManifestVersions.""" self.mox.StubOutWithMock(self.mv, '_Clone') self.mox.StubOutWithMock(time, 'sleep') self.mv._Clone() self.mox.ReplayAll() self.mv.Initialize() def testInitializeRetry(self): """Ensure we retry _Clone() the correct number of times.""" self.mox.StubOutWithMock(self.mv, '_Clone') self.mox.StubOutWithMock(time, 'sleep') for i in range(0, self.mv._CLONE_MAX_RETRIES): self.mv._Clone().AndRaise( error.CmdError('retried git clone failure', utils.CmdResult())) time.sleep(self.mv._CLONE_RETRY_SECONDS) self.mv._Clone() self.mox.ReplayAll() self.mv.Initialize() def testInitializeFail(self): """Ensure we fail after too many _Clone() retries.""" self.mox.StubOutWithMock(self.mv, '_Clone') self.mox.StubOutWithMock(time, 'sleep') for i in range(0, self.mv._CLONE_MAX_RETRIES): self.mv._Clone().AndRaise( error.CmdError('retried git clone failure', utils.CmdResult())) time.sleep(self.mv._CLONE_RETRY_SECONDS) self.mv._Clone().AndRaise( error.CmdError('final git clone failure', utils.CmdResult())) self.mox.ReplayAll() self.assertRaises(manifest_versions.CloneException, self.mv.Initialize) def testGlobs(self): """Ensure that we expand globs correctly.""" desired_paths = ['one/path', 'two/path', 'three/path'] tempdir = self.mv._tempdir.name for path in desired_paths: os.makedirs(os.path.join(tempdir, path)) for path in self.mv._ExpandGlobMinusPrefix(tempdir, '*/path'): self.assertTrue(path in desired_paths) def _ExpectGlob(self, to_return): self.mox.StubOutWithMock(self.mv, '_ExpandGlobMinusPrefix') self.mv._ExpandGlobMinusPrefix(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(to_return) def testAnyManifestsSinceRev(self): """Ensure we can tell if builds have succeeded since a given rev.""" rev = 'rev' self._ExpectGlob(['some/paths']) self.mox.StubOutWithMock(manifest_versions, '_SystemOutput') manifest_versions._SystemOutput( mox.And(mox.StrContains('log'), mox.StrContains(rev))).MultipleTimes().AndReturn( self._MANIFESTS_STRING) self.mox.ReplayAll() self.assertTrue(self.mv.AnyManifestsSinceRev(rev)) def testNoManifestsSinceRev(self): """Ensure we can tell if no builds have succeeded since a given rev.""" rev = 'rev' self._ExpectGlob(['some/paths']) self.mox.StubOutWithMock(manifest_versions, '_SystemOutput') manifest_versions._SystemOutput( mox.And(mox.StrContains('log'), mox.StrContains(rev))).MultipleTimes().AndReturn(' ') self.mox.ReplayAll() self.assertFalse(self.mv.AnyManifestsSinceRev(rev)) def testNoManifestsPathsSinceRev(self): """Ensure we can tell that we have no paths to check for new builds.""" rev = 'rev' self._ExpectGlob([]) self.mox.ReplayAll() self.assertFalse(self.mv.AnyManifestsSinceRev(rev)) def testManifestsSinceDate(self): """Ensure we can get manifests for a board since N days ago.""" since_date = datetime.datetime(year=2015, month=2, day=1) board = 'x86-alex' self._ExpectGlob(['some/paths']) self.mox.StubOutWithMock(manifest_versions, '_SystemOutput') manifest_versions._SystemOutput( mox.StrContains('log')).MultipleTimes().AndReturn( self._MANIFESTS_STRING) self.mox.ReplayAll() br_man = self.mv.ManifestsSinceDate(since_date, board) for pair in br_man.keys(): self.assertTrue(pair, self._BRANCHES) for manifest_list in br_man.itervalues(): self.assertTrue(manifest_list) self.assertEquals(br_man[('release', '20')][-1], '2057.0.10') def testNoManifestsSinceDate(self): """Ensure we can deal with no manifests since N days ago.""" since_date = datetime.datetime(year=2015, month=2, day=1) board = 'x86-alex' self._ExpectGlob(['some/paths']) self.mox.StubOutWithMock(manifest_versions, '_SystemOutput') manifest_versions._SystemOutput(mox.StrContains('log')).AndReturn([]) self.mox.ReplayAll() br_man = self.mv.ManifestsSinceDate(since_date, board) self.assertEquals(br_man, {}) def testNoManifestsPathsSinceDate(self): """Ensure we can deal with finding no paths to pass to'git log'.""" since_date = datetime.datetime(year=2015, month=2, day=1) board = 'x86-alex' self._ExpectGlob([]) self.mox.ReplayAll() br_man = self.mv.ManifestsSinceDate(since_date, board) self.assertEquals(br_man, {}) def testManifestsSinceDateExplodes(self): """Ensure we handle failures in querying manifests.""" since_date = datetime.datetime(year=2015, month=2, day=1) board = 'x86-alex' self._ExpectGlob(['some/paths']) self.mox.StubOutWithMock(manifest_versions, '_SystemOutput') manifest_versions._SystemOutput(mox.StrContains('log')).AndRaise( manifest_versions.QueryException()) self.mox.ReplayAll() self.assertRaises(manifest_versions.QueryException, self.mv.ManifestsSinceDate, since_date, board) def testUnparseableManifestPath(self): """Ensure we don't explode if we encounter an unparseable path.""" since_date = datetime.datetime(year=2015, month=2, day=1) board = 'link' build_name = 'link-depthcharge-pgo-codename-release-suffix-part-two' manifest = 'build-name/%s/pass/25/1234.0.0.xml' % build_name self._ExpectGlob(['some/paths']) self.mox.StubOutWithMock(manifest_versions, '_SystemOutput') manifest_versions._SystemOutput( mox.StrContains('log')).MultipleTimes().AndReturn(manifest) self.mox.ReplayAll() br_man = self.mv.ManifestsSinceDate(since_date, board) # We should skip the manifest that we passed in, as we can't parse it, # so we should get no manifests back. self.assertEquals(br_man, {}) _BOARD_MANIFESTS = { 'lumpy': [ 'lumpy-factory', 'lumpy-release', # 'lumpy-pgo-release', ], 'x86-alex': [ 'x86-alex-release', 'x86-alex-release-group', ], 'link': [ # 'link-depthcharge-firmware', ], } def testBoardManifestRePattern(self): """Ensure we can parse the names of builds that are produced.""" for board, builder_names in self._BOARD_MANIFESTS.items(): rgx = re.compile( manifest_versions.ManifestVersions._BOARD_MANIFEST_RE_PATTERN %\ board) for builder_name in builder_names: manifest = 'build-name/%s/pass/25/1234.0.0.xml' % builder_name self.assertTrue(rgx.match(manifest), msg=builder_name) def testGetManifests(self): """Test _GetManifests when pattern is matched and not matched.""" rgx = re.compile( self.mv._BOARD_MANIFEST_RE_PATTERN % 'lumpy') self.assertEqual(self.mv._GetManifests( rgx, ['build-name/lumpy-release/pass/25/1234.0.0.xml']), {('release', '25'): ['1234.0.0']}) self.assertEqual(self.mv._GetManifests( rgx, ['build-name/stumpy-release/pass/25/1234.0.0.xml']), {}) if __name__ == '__main__': unittest.main()