| # Copyright 2012 The ChromiumOS Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Unittests for repository.py.""" |
| |
| import os |
| import time |
| from unittest import mock |
| |
| from chromite.cbuildbot import repository |
| from chromite.lib import config_lib |
| from chromite.lib import constants |
| from chromite.lib import cros_build_lib |
| from chromite.lib import cros_test_lib |
| from chromite.lib import git |
| from chromite.lib import osutils |
| |
| |
| # pylint: disable=protected-access |
| |
| |
| class RepositoryTests(cros_test_lib.RunCommandTestCase): |
| """Test cases related to repository checkout methods.""" |
| |
| def testIsLocalPath(self): |
| """test IsLocalPath.""" |
| self.assertTrue(repository._IsLocalPath("/tmp/chromiumos/")) |
| self.assertTrue(repository._IsLocalPath("file:///chromiumos/")) |
| self.assertFalse(repository._IsLocalPath("https://chromiumos/")) |
| self.assertFalse(repository._IsLocalPath("http://chromiumos/")) |
| self.assertFalse(repository._IsLocalPath("ssh://chromiumos/")) |
| self.assertFalse(repository._IsLocalPath("git://chromiumos/")) |
| |
| |
| class RepoInitTests(cros_test_lib.TempDirTestCase, cros_test_lib.MockTestCase): |
| """Test cases related to repository initialization.""" |
| |
| def __init__(self, *args, **kwargs): |
| self.repo = None |
| super().__init__(*args, **kwargs) |
| |
| def setUp(self): |
| self.PatchObject(time, "sleep") |
| |
| def _Initialize(self, branch="master"): |
| site_params = config_lib.GetSiteParams() |
| self.repo = repository.RepoRepository( |
| site_params.MANIFEST_URL, self.tempdir, branch=branch |
| ) |
| self.repo.Initialize() |
| |
| @cros_test_lib.pytestmark_network_test |
| def testReInitialization(self): |
| """Test ability to switch between branches.""" |
| self._Initialize("release-R19-2046.B") |
| self._Initialize("master") |
| |
| # Test that a failed re-init due to bad branch doesn't leave repo in bad |
| # state. |
| # repo init on 'monkey' will retry on failures. |
| self.assertRaises(Exception, self._Initialize, "monkey") |
| self._Initialize("release-R20-2268.B") |
| |
| @cros_test_lib.pytestmark_network_test |
| def testBuildRootGitCleanup(self): |
| """Test successful repo cleanup.""" |
| self._Initialize() |
| run_cmd_mock = self.PatchObject( |
| cros_build_lib, "run", wraps=cros_build_lib.run |
| ) |
| self.repo.BuildRootGitCleanup(prune_all=True) |
| |
| # run should be called twice. |
| self.assertEqual(run_cmd_mock.call_count, 2) |
| |
| @cros_test_lib.pytestmark_network_test |
| def testCleanStaleLocks(self): |
| """Test successful repo lock cleanup.""" |
| self._Initialize("release-R19-2046.B") |
| self.PatchObject(git, "GetGitGitdir") |
| dsl = self.PatchObject(git, "DeleteStaleLocks") |
| self.repo.CleanStaleLocks() |
| |
| self.assertEqual(dsl.call_count, 198) |
| |
| def testInitializationWithRepoInitRetry(self): |
| """Test Initialization with repo init retry.""" |
| self.PatchObject(repository.RepoRepository, "_RepoSelfupdate") |
| mock_cleanup = self.PatchObject( |
| repository.RepoRepository, "_CleanUpRepoManifest" |
| ) |
| error_result = cros_build_lib.CompletedProcess(["cmd"], returncode=1) |
| ex = cros_build_lib.RunCommandError("error_msg", error_result) |
| mock_init = self.PatchObject(cros_build_lib, "run", side_effect=ex) |
| |
| self.assertRaises(Exception, self._Initialize) |
| self.assertEqual( |
| mock_cleanup.call_count, repository.REPO_INIT_RETRY_LIMIT + 1 |
| ) |
| self.assertEqual( |
| mock_init.call_count, repository.REPO_INIT_RETRY_LIMIT + 1 |
| ) |
| |
| def testInitializationWithoutRepoInitRetry(self): |
| """Test Initialization without repo init retry.""" |
| self.PatchObject(repository.RepoRepository, "_RepoSelfupdate") |
| mock_cleanup = self.PatchObject( |
| repository.RepoRepository, "_CleanUpRepoManifest" |
| ) |
| mock_init = self.PatchObject(cros_build_lib, "run") |
| |
| self._Initialize() |
| self.assertEqual(mock_cleanup.call_count, 0) |
| self.assertEqual(mock_init.call_count, 1) |
| |
| |
| class RepoInitChromeBotTests(RepoInitTests): |
| """Test that Re-init works with the chrome-bot account. |
| |
| In testing, repo init behavior on the buildbots is different from a |
| local run, because there is some logic in 'repo' that filters changes based |
| on GIT_COMMITTER_IDENT. So for sanity's sake, try to emulate running on the |
| buildbots. |
| """ |
| |
| def setUp(self): |
| os.putenv("GIT_COMMITTER_EMAIL", "chrome-bot@chromium.org") |
| os.putenv("GIT_AUTHOR_EMAIL", "chrome-bot@chromium.org") |
| |
| |
| class RepoSyncTests(cros_test_lib.TempDirTestCase, cros_test_lib.MockTestCase): |
| """Test cases related to repository Sync""" |
| |
| def setUp(self): |
| site_params = config_lib.GetSiteParams() |
| self.repo = repository.RepoRepository( |
| site_params.MANIFEST_URL, self.tempdir, branch="master" |
| ) |
| self.PatchObject(repository.RepoRepository, "_RepoDebugInfo") |
| self.PatchObject(repository.RepoRepository, "Initialize") |
| self.PatchObject(repository.RepoRepository, "_EnsureMirroring") |
| self.PatchObject(repository.RepoRepository, "BuildRootGitCleanup") |
| self.PatchObject(time, "sleep") |
| |
| def testSyncWithException(self): |
| """Test Sync retry on repo network sync failure""" |
| # Return value here isn't super important. |
| result = cros_build_lib.CompletedProcess( |
| ["cmd"], returncode=0, stderr="error" |
| ) |
| ex = cros_build_lib.RunCommandError("msg", result) |
| |
| run_cmd_mock = self.PatchObject(cros_build_lib, "run", side_effect=ex) |
| |
| # repo.Sync raises SrcCheckOutException. |
| self.assertRaises( |
| repository.SrcCheckOutException, |
| self.repo.Sync, |
| local_manifest="local_manifest", |
| network_only=True, |
| ) |
| |
| # run should be called SYNC_RETRIES + 1 times. |
| self.assertEqual(run_cmd_mock.call_count, constants.SYNC_RETRIES + 1) |
| |
| def testSyncWithoutException(self): |
| """Test successful repo sync without exception and retry""" |
| # Return value here isn't super important. |
| run_cmd_mock = self.PatchObject(cros_build_lib, "run") |
| self.repo.Sync(local_manifest="local_manifest", network_only=True) |
| |
| # run should be called once. |
| self.assertEqual(run_cmd_mock.call_count, 1) |
| |
| def test_RepoSelfupdateRaisesWarning(self): |
| """Test _RepoSelfupdate when repo version warning is raised.""" |
| warnning_stderr = """ |
| info: A new version of repo is available |
| |
| ... |
| |
| gpg: Can't check signature: public key not found |
| |
| ... |
| |
| warning: Skipped upgrade to unverified version |
| """ |
| cmd_result = cros_build_lib.CompletedProcess(stderr=warnning_stderr) |
| self.PatchObject(cros_build_lib, "run", return_value=cmd_result) |
| with mock.patch.object(osutils, "RmDir") as mock_rm: |
| self.repo._RepoSelfupdate() |
| mock_rm.assert_called_once_with(mock.ANY, ignore_missing=True) |
| |
| def test_RepoSelfupdateRaisesException(self): |
| """Test _RepoSelfupdate when exception is raised.""" |
| ex = cros_build_lib.RunCommandError("msg") |
| self.PatchObject(cros_build_lib, "run", side_effect=ex) |
| with mock.patch.object(osutils, "RmDir") as mock_rm: |
| self.repo._RepoSelfupdate() |
| mock_rm.assert_called_once_with(mock.ANY, ignore_missing=True) |
| |
| def test_RepoSelfupdateSucceeds(self): |
| cmd_result = cros_build_lib.CompletedProcess() |
| self.PatchObject(cros_build_lib, "run", return_value=cmd_result) |
| with mock.patch.object(osutils, "RmDir") as mock_rm: |
| self.repo._RepoSelfupdate() |
| self.assertFalse(mock_rm.called) |