#!/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()