| #!/usr/bin/python |
| |
| # Copyright (c) 2011 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. |
| |
| """Unittests for manifest_version. Needs to be run inside of chroot for mox.""" |
| |
| import mox |
| import os |
| import shutil |
| import sys |
| import tempfile |
| import unittest |
| |
| if __name__ == '__main__': |
| import constants |
| sys.path.append(constants.SOURCE_ROOT) |
| |
| from chromite.buildbot import cbuildbot_config |
| from chromite.buildbot import manifest_version |
| from chromite.buildbot import repository |
| from chromite.lib import cros_build_lib as cros_lib |
| |
| FAKE_VERSION = """ |
| CHROMEOS_BUILD=1 |
| CHROMEOS_BRANCH=2 |
| CHROMEOS_PATCH=3 |
| CHROME_BRANCH=13 |
| """ |
| |
| FAKE_VERSION_STRING = '1.2.3' |
| FAKE_VERSION_STRING_NEXT = '1.2.4' |
| CHROME_BRANCH = '13' |
| |
| # Dir to use to sync repo for git testing. |
| GIT_DIR = '/tmp/repo_for_manifest_version_unittest' |
| |
| # Use the chromite repo to actually test git changes. |
| GIT_TEST_PATH = 'chromite' |
| |
| def TouchFile(file_path): |
| """Touches a file specified by file_path""" |
| if not os.path.exists(os.path.dirname(file_path)): |
| os.makedirs(os.path.dirname(file_path)) |
| |
| touch_file = open(file_path, 'w+') |
| touch_file.close() |
| |
| |
| class HelperMethodsTest(unittest.TestCase): |
| """Test methods associated with methods not in a class.""" |
| |
| def setUp(self): |
| self.tmpdir = tempfile.mkdtemp() |
| |
| def testCreateSymlink(self): |
| """Tests that we can create symlinks and remove a previous one.""" |
| (unused_fd, srcfile) = tempfile.mkstemp(dir=self.tmpdir) |
| destfile1 = tempfile.mktemp(dir=os.path.join(self.tmpdir, 'other_dir1')) |
| destfile2 = tempfile.mktemp(dir=os.path.join(self.tmpdir, 'other_dir2')) |
| |
| manifest_version.CreateSymlink(srcfile, destfile1, remove_file=None) |
| self.assertTrue(os.path.lexists(destfile1), |
| 'Unable to create symlink to %s' % destfile1) |
| |
| manifest_version.CreateSymlink(srcfile, destfile2, remove_file=destfile1) |
| self.assertTrue(os.path.lexists(destfile2), |
| 'Unable to create symlink to %s' % destfile2) |
| self.assertFalse(os.path.lexists(destfile1), |
| 'Unable to remove symlink %s' % destfile1) |
| |
| def testRemoveDirs(self): |
| """Tests if _RemoveDirs works with a recursive directory structure.""" |
| otherdir1 = tempfile.mkdtemp(dir=self.tmpdir) |
| tempfile.mkdtemp(dir=otherdir1) |
| manifest_version._RemoveDirs(otherdir1) |
| self.assertFalse(os.path.exists(otherdir1), 'Failed to rmdirs.') |
| |
| def testPushGitChanges(self): |
| """Tests if we can append to an authors file and push it using dryrun.""" |
| if not os.path.exists(GIT_DIR): os.makedirs(GIT_DIR) |
| init_cmd = ['repo', 'init', '-u', constants.MANIFEST_URL, '--repo-url', |
| constants.REPO_URL, '-m', 'minilayout.xml'] |
| cros_lib.RunCommand(init_cmd, cwd=GIT_DIR, input='\n\ny\n') |
| cros_lib.RunCommand(('repo sync --jobs 8').split(), cwd=GIT_DIR) |
| git_dir = os.path.join(GIT_DIR, GIT_TEST_PATH) |
| cros_lib.RunCommand(['git', |
| 'config', |
| 'url.%s.insteadof' % constants.GERRIT_SSH_URL, |
| constants.GIT_HTTP_URL], cwd=git_dir) |
| |
| manifest_version._PrepForChanges(git_dir, dry_run=True) |
| |
| # Change something. |
| cros_lib.RunCommand(('tee --append %s/AUTHORS' % git_dir).split(), |
| input='TEST USER <test_user@chromium.org>') |
| |
| # Push the change with dryrun. |
| manifest_version._PushGitChanges(git_dir, 'Test appending user.', |
| dry_run=True) |
| |
| def testPushGitChangesWithRealPrep(self): |
| """Another push test that tests push but on non-repo does it on a branch.""" |
| git_dir = tempfile.mktemp('manifest_dir') |
| manifest_versions_url = cbuildbot_config.GetManifestVersionsRepoUrl( |
| internal_build=False, read_only=True) |
| cros_lib.RunCommand(['git', 'clone', manifest_versions_url, git_dir]) |
| try: |
| cros_lib.RunCommand(['git', |
| 'config', |
| 'url.%s.insteadof' % constants.GERRIT_SSH_URL, |
| constants.GIT_HTTP_URL], cwd=git_dir) |
| |
| manifest_version._PrepForChanges(git_dir, dry_run=False) |
| |
| # This should not error out if we are running with dry_run=False for |
| # prep for changes. |
| cros_lib.RunCommand(['git', 'show', manifest_version._PUSH_BRANCH], |
| cwd=git_dir) |
| |
| # Change something. |
| cros_lib.RunCommand(('tee --append %s/AUTHORS' % git_dir).split(), |
| input='TEST USER <test_user@chromium.org>') |
| |
| # Push the change with dryrun. |
| manifest_version._PushGitChanges(git_dir, 'Test appending user.', |
| dry_run=True) |
| |
| # This should not error out if we are running with dry_run=False for |
| # prep for changes. |
| cros_lib.RunCommand(['git', 'show', manifest_version._PUSH_BRANCH], |
| cwd=git_dir) |
| finally: |
| shutil.rmtree(git_dir) |
| |
| def tearDown(self): |
| shutil.rmtree(self.tmpdir) |
| |
| |
| class VersionInfoTest(mox.MoxTestBase): |
| """Test methods testing methods in VersionInfo class.""" |
| |
| def setUp(self): |
| mox.MoxTestBase.setUp(self) |
| self.tmpdir = tempfile.mkdtemp() |
| |
| @classmethod |
| def CreateFakeVersionFile(cls, tmpdir): |
| """Helper method to create a version file from FAKE_VERSION.""" |
| (version_file_fh, version_file) = tempfile.mkstemp(dir=tmpdir) |
| os.write(version_file_fh, FAKE_VERSION) |
| os.close(version_file_fh) |
| return version_file |
| |
| def testLoadFromFile(self): |
| """Tests whether we can load from a version file.""" |
| version_file = self.CreateFakeVersionFile(self.tmpdir) |
| info = manifest_version.VersionInfo(version_file=version_file) |
| self.assertEqual(info.VersionString(), FAKE_VERSION_STRING) |
| |
| def testLoadFromString(self): |
| """Tests whether we can load from a string.""" |
| info = manifest_version.VersionInfo(FAKE_VERSION_STRING, CHROME_BRANCH) |
| self.assertEqual(info.VersionString(), FAKE_VERSION_STRING) |
| |
| def CommonTestIncrementVersion(self, incr_type): |
| """Common test increment. Returns path to new incremented file.""" |
| message = 'Incrementing cuz I sed so' |
| self.mox.StubOutWithMock(manifest_version, '_PrepForChanges') |
| self.mox.StubOutWithMock(manifest_version, '_PushGitChanges') |
| |
| manifest_version._PrepForChanges(self.tmpdir, False) |
| |
| version_file = self.CreateFakeVersionFile(self.tmpdir) |
| |
| manifest_version._PushGitChanges(self.tmpdir, message, dry_run=False) |
| |
| self.mox.ReplayAll() |
| info = manifest_version.VersionInfo(version_file=version_file, |
| incr_type=incr_type) |
| info.IncrementVersion(message, dry_run=False) |
| self.mox.VerifyAll() |
| return version_file |
| |
| def testIncrementVersionPatch(self): |
| """Tests whether we can increment a version file by patch number.""" |
| version_file = self.CommonTestIncrementVersion('patch') |
| new_info = manifest_version.VersionInfo(version_file=version_file, |
| incr_type='patch') |
| self.assertEqual(new_info.VersionString(), FAKE_VERSION_STRING_NEXT) |
| |
| def testIncrementVersionBranch(self): |
| """Tests whether we can increment a version file by branch number.""" |
| version_file = self.CommonTestIncrementVersion('branch') |
| new_info = manifest_version.VersionInfo(version_file=version_file, |
| incr_type='branch') |
| self.assertEqual(new_info.VersionString(), '1.3.0') |
| |
| def testIncrementVersionBuild(self): |
| """Tests whether we can increment a version file by build number.""" |
| version_file = self.CommonTestIncrementVersion('build') |
| new_info = manifest_version.VersionInfo(version_file=version_file, |
| incr_type='build') |
| self.assertEqual(new_info.VersionString(), '2.0.0') |
| |
| def tearDown(self): |
| shutil.rmtree(self.tmpdir) |
| |
| |
| class BuildSpecsManagerTest(mox.MoxTestBase): |
| """Tests for the BuildSpecs manager.""" |
| |
| def setUp(self): |
| mox.MoxTestBase.setUp(self) |
| |
| self.tmpdir = tempfile.mkdtemp() |
| os.makedirs(os.path.join(self.tmpdir, '.repo')) |
| self.source_repo = 'ssh://source/repo' |
| self.manifest_repo = 'ssh://manifest/repo' |
| self.version_file = 'version-file.sh' |
| self.branch = 'master' |
| self.build_name = 'x86-generic' |
| self.incr_type = 'patch' |
| |
| # Change default to something we clean up. |
| self.tmpmandir = tempfile.mkdtemp() |
| manifest_version.BuildSpecsManager._TMP_MANIFEST_DIR = self.tmpmandir |
| |
| self.manager = manifest_version.BuildSpecsManager( |
| self.tmpdir, self.source_repo, self.manifest_repo, self.branch, |
| self.build_name, self.incr_type, dry_run=True) |
| |
| def testLoadSpecs(self): |
| """Tests whether we can load specs correctly.""" |
| self.mox.StubOutWithMock(manifest_version, '_RemoveDirs') |
| self.mox.StubOutWithMock(repository, 'CloneGitRepo') |
| info = manifest_version.VersionInfo( |
| FAKE_VERSION_STRING, CHROME_BRANCH, incr_type='patch') |
| m1 = os.path.join(self.manager._TMP_MANIFEST_DIR, 'buildspecs', |
| CHROME_BRANCH, '1.2.2.xml') |
| m2 = os.path.join(self.manager._TMP_MANIFEST_DIR, 'buildspecs', |
| CHROME_BRANCH, '1.2.3.xml') |
| m3 = os.path.join(self.manager._TMP_MANIFEST_DIR, 'buildspecs', |
| CHROME_BRANCH, '1.2.4.xml') |
| m4 = os.path.join(self.manager._TMP_MANIFEST_DIR, 'buildspecs', |
| CHROME_BRANCH, '1.2.5.xml') |
| for_build = os.path.join(self.manager._TMP_MANIFEST_DIR, 'build-name', |
| self.build_name) |
| |
| # Create fake buildspecs. |
| TouchFile(m1) |
| TouchFile(m2) |
| TouchFile(m3) |
| TouchFile(m4) |
| |
| # Fail 1, pass 2, leave 3,4 unprocessed. |
| manifest_version.CreateSymlink(m1, os.path.join( |
| for_build, 'fail', CHROME_BRANCH, os.path.basename(m1))) |
| manifest_version.CreateSymlink(m1, os.path.join( |
| for_build, 'pass', CHROME_BRANCH, os.path.basename(m2))) |
| manifest_version._RemoveDirs(self.manager._TMP_MANIFEST_DIR) |
| repository.CloneGitRepo(self.manager._TMP_MANIFEST_DIR, |
| self.manifest_repo) |
| self.mox.StubOutWithMock(self.manager, '_GetSpecAge') |
| self.manager._GetSpecAge('1.2.5').AndReturn(100) |
| self.mox.ReplayAll() |
| self.manager._LoadSpecs(info) |
| self.mox.VerifyAll() |
| self.assertEqual(self.manager.latest_unprocessed, '1.2.5') |
| |
| def testGetMatchingSpecs(self): |
| """Tests whether we can get sorted specs correctly from a directory.""" |
| self.mox.StubOutWithMock(manifest_version, '_RemoveDirs') |
| self.mox.StubOutWithMock(repository, 'CloneGitRepo') |
| info = manifest_version.VersionInfo( |
| '99.1.2', CHROME_BRANCH, incr_type='branch') |
| |
| specs_dir = os.path.join(self.manager._TMP_MANIFEST_DIR, 'buildspecs', |
| CHROME_BRANCH) |
| m1 = os.path.join(specs_dir, '100.0.0.xml') |
| m2 = os.path.join(specs_dir, '99.3.3.xml') |
| m3 = os.path.join(specs_dir, '99.1.10.xml') |
| m4 = os.path.join(specs_dir, '99.1.5.xml') |
| |
| # Create fake buildspecs. |
| TouchFile(m1) |
| TouchFile(m2) |
| TouchFile(m3) |
| TouchFile(m4) |
| |
| self.mox.ReplayAll() |
| specs = self.manager._GetMatchingSpecs(info, specs_dir) |
| self.mox.VerifyAll() |
| # Should be the latest on the 99.1 branch |
| self.assertEqual(specs[-1], '99.3.3') |
| |
| def testCreateNewBuildSpecNoCopy(self): |
| """Tests whether we can create a new build spec correctly. |
| |
| Tests without pre-existing version file in manifest dir. |
| """ |
| self.mox.StubOutWithMock(repository.RepoRepository, 'ExportManifest') |
| self.mox.StubOutWithMock(manifest_version, '_PrepForChanges') |
| self.mox.StubOutWithMock(manifest_version, '_PushGitChanges') |
| info = manifest_version.VersionInfo( |
| FAKE_VERSION_STRING, CHROME_BRANCH, incr_type='patch') |
| |
| self.manager.all_specs_dir = os.path.join(self.manager._TMP_MANIFEST_DIR, |
| 'buildspecs', '1.2') |
| |
| repository.RepoRepository.ExportManifest(mox.IgnoreArg()) |
| |
| self.mox.ReplayAll() |
| self.manager.all = [] |
| version = self.manager._CreateNewBuildSpec(info) |
| self.mox.VerifyAll() |
| self.assertEqual(FAKE_VERSION_STRING, version) |
| |
| def testCreateNewBuildIncrement(self): |
| """Tests that we create a new version if a previous one exists.""" |
| self.mox.StubOutWithMock(manifest_version.VersionInfo, 'IncrementVersion') |
| self.mox.StubOutWithMock(repository.RepoRepository, 'ExportManifest') |
| self.mox.StubOutWithMock(repository.RepoRepository, 'Sync') |
| |
| version_file = VersionInfoTest.CreateFakeVersionFile(self.tmpdir) |
| info = manifest_version.VersionInfo(version_file=version_file, |
| incr_type='patch') |
| self.manager.all_specs_dir = os.path.join(self.manager._TMP_MANIFEST_DIR, |
| 'buildspecs', '1.2') |
| info.IncrementVersion( |
| 'Automatic: %s - Updating to a new version number from %s' % ( |
| self.build_name, FAKE_VERSION_STRING), |
| dry_run=True).AndReturn(FAKE_VERSION_STRING_NEXT) |
| |
| # TODO(ferringb): Gut the cleanup=False added for 24709. |
| repository.RepoRepository.Sync('default', cleanup=False) |
| repository.RepoRepository.ExportManifest(mox.IgnoreArg()) |
| |
| self.mox.ReplayAll() |
| # Add to existing so we are forced to increment. |
| self.manager.all = [FAKE_VERSION_STRING] |
| version = self.manager._CreateNewBuildSpec(info) |
| self.mox.VerifyAll() |
| self.assertEqual(FAKE_VERSION_STRING_NEXT, version) |
| |
| def NotestGetNextBuildSpec(self): |
| """Meta test. Re-enable if you want to use it to do a big test.""" |
| print self.manager.GetNextBuildSpec(self.version_file, latest=True, |
| retries=0) |
| print self.manager.UpdateStatus('pass') |
| |
| def tearDown(self): |
| if os.path.exists(self.tmpdir): shutil.rmtree(self.tmpdir) |
| shutil.rmtree(self.tmpmandir) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |