| """Tests for repo_utils.""" |
| |
| from __future__ import absolute_import |
| import os |
| import sys |
| import tempfile |
| import unittest |
| |
| # Allow imports from cq/scripts folder |
| sys.path.insert( |
| 0, |
| os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir))) |
| from helpers import repo_utils # pylint: disable=g-import-not-at-top |
| |
| SAMPLE_MANIFEST_STRING = """ |
| <?xml version="1.0" encoding="UTF-8"?> |
| <manifest> |
| <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> |
| <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> |
| |
| <default revision="master"/> |
| |
| <project name="chromium/src" remote="eureka" revision="unfork_m43"/> |
| <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> |
| <project name="chromiumos/third_party/autotest" path="autotest" remote="chromium"/> |
| <project name="continuous-tests" remote="eureka"/> |
| <project name="fragglerock" remote="eureka"/> |
| <project name="prebuilt/toolchain" path="toolchain" remote="eureka"/> |
| <project name="test" remote="eureka"/> |
| <project name="legacyname.git" path="path/to/legacy" remote="eureka"/> |
| </manifest> |
| """ |
| |
| SAMPLE_MANIFEST_STRING_WITH_DUPLICATE_NAMES = """ |
| <?xml version="1.0" encoding="UTF-8"?> |
| <manifest> |
| <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> |
| <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> |
| |
| <default revision="master"/> |
| |
| <project name="chromium/src" remote="eureka" revision="unfork_m43"/> |
| <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> |
| <project name="chromiumos/third_party/autotest" path="autotest" remote="chromium"/> |
| <project name="continuous-tests" remote="eureka"/> |
| <project name="fragglerock" remote="eureka"/> |
| <project name="prebuilt/toolchain" path="toolchain" remote="eureka"/> |
| <project name="test" path="test1" remote="eureka"/> |
| <project name="test" path="test2" remote="eureka"/> |
| </manifest> |
| """ |
| |
| SAMPLE_MANIFEST_INCOMPLETE_STRING = """ |
| <?xml version="1.0" encoding="UTF-8"?> |
| <manifest> |
| <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> |
| <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> |
| |
| <default revision="master"/> |
| |
| <project name="chromium/src" remote="eureka" revision="unfork_m43"/> |
| <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> |
| <project name="chromiumos/third_party/autotest" path="autotest" remote="chromium"/> |
| <project name="continuous-tests" remote="eureka"/> |
| <project name="fragglerock" remote="eureka"/> |
| <project name="prebuilt/toolchain" path="toolchain" remote="eureka"/> |
| """ |
| |
| SAMPLE_MANIFEST_WITH_DEFAULT_REMOTE = """ |
| <manifest> |
| <remote fetch="https://nest-internal.googlesource.com" name="cq-manifest" review="https://nest-internal-review.googlesource.com/"/> |
| <default remote="cq-manifest" revision="master"/> |
| <project name="nep/nest-harness-tests" path="nep/nest-harness-tests" /> |
| </manifest> |
| """ |
| |
| SAMPLE_MANIFEST_WITH_INTERNAL_GITHUB = """<manifest> |
| <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> |
| <remote fetch="https://github.googlesource.com" name="github" review="https://github-review.googlesource.com/"/> |
| <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> |
| <default revision="master"/> |
| <project name="chromium/src" remote="eureka" revision="unfork_m43"/> |
| <project name="test-project1" remote="github"/> |
| <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> |
| </manifest> |
| """ |
| |
| SAMPLE_MANIFEST_WITH_EXTERNAL_GITHUB = """<?xml version="1.0" encoding="UTF-8"?> |
| <manifest> |
| <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> |
| <remote fetch="https://github.com" name="github"/> |
| <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> |
| <default revision="master"/> |
| <project name="chromium/src" remote="eureka" revision="unfork_m43"/> |
| <project name="test-project1" remote="github"/> |
| <project name="chromiumos/chromite" path="chromite/chromite" remote="chromium"/> |
| </manifest> |
| """ |
| |
| TEST_MANIFEST_URL = 'https://foo.bar.googlesource.com/bat/baz' |
| |
| |
| _SAMPLE_MANIFEST_STRING_WITH_MULTI_REVISIONS_OF_SAME_NAMES = """ |
| <?xml version="1.0" encoding="UTF-8"?> |
| <manifest> |
| <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> |
| <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> |
| |
| <project name="test" path="test1" remote="eureka" revision="branch1"/> |
| <project name="test" path="test2" remote="eureka" revision="branch2"/> |
| </manifest> |
| """ |
| |
| _SAMPLE_MANIFEST_WITH_UPSTREAMS_SET = """ |
| <?xml version="1.0" encoding="UTF-8"?> |
| <manifest> |
| <remote fetch="https://chromium.googlesource.com/" name="chromium" review="https://chromium-review.googlesource.com/"/> |
| <remote fetch="https://eureka-internal.googlesource.com/" name="eureka" review="sso://eureka-internal"/> |
| |
| <project name="test" path="test1" remote="eureka" revision="sha1" upstream="branch1"/> |
| <project name="test" path="test2" remote="eureka" revision="branch2"/> |
| </manifest> |
| """ |
| |
| |
| class RepoUtilsTest(unittest.TestCase): |
| """Tests for the repo utils module.""" |
| |
| def testParseEmptyManifest(self): |
| """Tests parsing an empty manifest file.""" |
| manifest = '' |
| expected_lookup = { |
| 'eureka/manifest': '.repo/manifests', |
| } |
| project_lookup = repo_utils.parse_manifest_for_path( |
| manifest, repo_utils.EUREKA_MANIFEST_URL) |
| for key, expected_value in expected_lookup.items(): |
| self.assertEqual(project_lookup[key], expected_value) |
| |
| def testParseManifest(self): |
| """Tests parsing a manifest file for paths.""" |
| expected_lookup = { |
| 'chromium/src': 'chromium/src', |
| 'chromiumos/chromite': 'chromite/chromite', |
| 'chromiumos/third_party/autotest': 'autotest', |
| 'continuous-tests': 'continuous-tests', |
| 'eureka/manifest': '.repo/manifests', |
| 'fragglerock': 'fragglerock', |
| 'legacyname.git': 'path/to/legacy', |
| 'prebuilt/toolchain': 'toolchain', |
| 'test': 'test' |
| } |
| project_lookup = repo_utils.parse_manifest_for_path( |
| SAMPLE_MANIFEST_STRING, |
| repo_utils.EUREKA_MANIFEST_URL) |
| for key, expected_value in expected_lookup.items(): |
| self.assertEqual(project_lookup[key], expected_value) |
| |
| def testParseManifestForNonEurekaManifest(self): |
| """Tests parsing a non-eureka manifest for path.""" |
| expected_lookup = { |
| 'bat/baz': '.repo/manifests', |
| 'chromium/src': 'chromium/src', |
| 'chromiumos/chromite': 'chromite/chromite', |
| 'chromiumos/third_party/autotest': 'autotest', |
| 'continuous-tests': 'continuous-tests', |
| 'fragglerock': 'fragglerock', |
| 'legacyname.git': 'path/to/legacy', |
| 'prebuilt/toolchain': 'toolchain', |
| 'test': 'test' |
| } |
| try: |
| original_map = dict(repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME) |
| repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME = {TEST_MANIFEST_URL: |
| 'bat/baz'} |
| project_lookup = repo_utils.parse_manifest_for_path( |
| SAMPLE_MANIFEST_STRING, TEST_MANIFEST_URL) |
| for key, expected_value in expected_lookup.items(): |
| self.assertEqual(project_lookup[key], expected_value) |
| finally: |
| repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME = original_map |
| |
| def testParseManifestRemotes(self): |
| """Tests parsing a manifest file for remotes.""" |
| expected_lookup = { |
| 'chromium/src': 'eureka', |
| 'chromiumos/chromite': 'chromium', |
| 'chromiumos/third_party/autotest': 'chromium', |
| 'continuous-tests': 'eureka', |
| 'eureka/manifest': 'origin', |
| 'fragglerock': 'eureka', |
| 'legacyname.git': 'eureka', |
| 'prebuilt/toolchain': 'eureka', |
| 'test': 'eureka' |
| } |
| project_lookup = repo_utils.parse_manifest_for_remote( |
| SAMPLE_MANIFEST_STRING, |
| repo_utils.EUREKA_MANIFEST_URL) |
| for key, expected_value in expected_lookup.items(): |
| self.assertEqual(project_lookup[key], expected_value) |
| |
| def testParseManifestRemotesForNonEurekaManifest(self): |
| """Tests parsing a non-eureka manifest for remotes.""" |
| expected_lookup = { |
| 'bat/baz': 'origin', |
| 'chromium/src': 'eureka', |
| 'chromiumos/chromite': 'chromium', |
| 'chromiumos/third_party/autotest': 'chromium', |
| 'continuous-tests': 'eureka', |
| 'fragglerock': 'eureka', |
| 'legacyname.git': 'eureka', |
| 'prebuilt/toolchain': 'eureka', |
| 'test': 'eureka' |
| } |
| try: |
| original_map = dict(repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME) |
| repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME = {TEST_MANIFEST_URL: |
| 'bat/baz'} |
| project_lookup = repo_utils.parse_manifest_for_remote( |
| SAMPLE_MANIFEST_STRING, TEST_MANIFEST_URL) |
| for key, expected_value in expected_lookup.items(): |
| self.assertEqual(project_lookup[key], expected_value) |
| finally: |
| repo_utils.REPO_MANIFEST_URL_TO_PROJECT_NAME = original_map |
| |
| def testParseManifestRemotesForNonEurekaDefaultRemote(self): |
| expected_lookup = { |
| 'nep/nest-harness-tests': 'cq-manifest' |
| } |
| project_lookup = repo_utils.parse_manifest_for_remote( |
| SAMPLE_MANIFEST_WITH_DEFAULT_REMOTE, TEST_MANIFEST_URL) |
| for key, expected_value in expected_lookup.items(): |
| self.assertEqual(project_lookup[key], expected_value) |
| |
| def testParseManifestRevisions(self): |
| """Tests parsing a manifest file for revisions.""" |
| expected_lookup = { |
| 'chromium/src': 'unfork_m43', |
| 'chromiumos/chromite': 'master', |
| 'chromiumos/third_party/autotest': 'master', |
| 'continuous-tests': 'master', |
| 'eureka/manifest': 'unfork_m51', |
| 'fragglerock': 'master', |
| 'legacyname.git': 'master', |
| 'prebuilt/toolchain': 'master', |
| 'test': 'master' |
| } |
| project_lookup = repo_utils.parse_manifest_for_revision( |
| SAMPLE_MANIFEST_STRING, |
| repo_utils.EUREKA_MANIFEST_URL, |
| 'unfork_m51') |
| for key, expected_value in expected_lookup.items(): |
| self.assertEqual(project_lookup[key], expected_value) |
| |
| def testParseManifestWithDups(self): |
| """Tests parsing a manifest file with duplicates.""" |
| expected_lookup = { |
| 'chromium/src': 'chromium/src', |
| 'chromiumos/chromite': 'chromite/chromite', |
| 'chromiumos/third_party/autotest': 'autotest', |
| 'continuous-tests': 'continuous-tests', |
| 'eureka/manifest': '.repo/manifests', |
| 'fragglerock': 'fragglerock', |
| 'prebuilt/toolchain': 'toolchain', |
| } |
| expected_duplicate = 'test' |
| project_lookup = repo_utils.parse_manifest_for_path( |
| SAMPLE_MANIFEST_STRING_WITH_DUPLICATE_NAMES, |
| repo_utils.EUREKA_MANIFEST_URL) |
| for key, expected_value in expected_lookup.items(): |
| self.assertEqual(project_lookup[key], expected_value) |
| with self.assertRaises(repo_utils.DuplicateLookupError): |
| project_lookup[expected_duplicate] # pylint: disable=pointless-statement |
| |
| def testLookupDuplicateRepoRaisesError(self): |
| """Tests a lookup on a duplicate repo raises an error.""" |
| |
| class MockExecutor(object): |
| |
| # pylint: disable=invalid-name,no-method-argument, no-self-argument |
| def exec_subprocess(*args, **kwargs): |
| del kwargs |
| return SAMPLE_MANIFEST_STRING_WITH_DUPLICATE_NAMES |
| |
| lookup = repo_utils.get_project_path_lookup( |
| MockExecutor(), repo_utils.EUREKA_MANIFEST_URL) |
| |
| self.assertEqual('continuous-tests', lookup.get('continuous-tests')) |
| with self.assertRaises(KeyError): |
| lookup.get('foobar') |
| with self.assertRaises(repo_utils.DuplicateLookupError): |
| lookup.get('test') |
| self.assertEqual('continuous-tests', lookup['continuous-tests']) |
| with self.assertRaises(KeyError): |
| lookup['foobar'] # pylint: disable=pointless-statement |
| with self.assertRaises(repo_utils.DuplicateLookupError): |
| lookup['test'] # pylint: disable=pointless-statement |
| |
| def testManifestParseError(self): |
| """Tests parsing an incorrect manifest file.""" |
| |
| class MockExecutor(object): |
| |
| # pylint: disable=invalid-name,no-method-argument, no-self-argument |
| def exec_subprocess(*args, **kwargs): |
| del kwargs |
| return SAMPLE_MANIFEST_INCOMPLETE_STRING |
| |
| with self.assertRaises(repo_utils.ManifestParseError): |
| _ = repo_utils.get_manifest(MockExecutor()) |
| |
| def testEmptyChangeDoesNotRequireRepoSync(self): |
| """Tests that an empty commit does not require a sync.""" |
| project = 'eureka/manifest' |
| |
| files = [] |
| self.assertFalse(repo_utils.requires_repo_sync(project, files)) |
| |
| def testSyncNotRequiredForOtherProjects(self): |
| """Tests that a sync is not required for other projects.""" |
| project = 'third_party/foobar' |
| |
| files = ['default.xml'] |
| self.assertFalse(repo_utils.requires_repo_sync(project, files)) |
| |
| def testChangeToAnyManifestFileRequiresRepoSync(self): |
| """Tests that a change to any manifest requires a sync.""" |
| project = 'eureka/manifest' |
| |
| files = ['default.xml'] |
| self.assertTrue(repo_utils.requires_repo_sync(project, files)) |
| |
| files = ['foobar.xml'] |
| self.assertTrue(repo_utils.requires_repo_sync(project, files)) |
| |
| def testProjectLookupWithTrailingSlash(self): |
| """Tests searching by project with a trailing slash.""" |
| expected_lookup = { |
| 'chromium/src': 'chromium/src', |
| 'chromiumos/chromite': 'chromite/chromite', |
| 'chromiumos/third_party/autotest': 'autotest', |
| 'continuous-tests': 'continuous-tests', |
| 'eureka/manifest': '.repo/manifests', |
| 'fragglerock': 'fragglerock', |
| 'prebuilt/toolchain': 'toolchain', |
| 'test': 'test' |
| } |
| project_lookup = repo_utils.parse_manifest_for_path( |
| SAMPLE_MANIFEST_STRING, |
| repo_utils.EUREKA_MANIFEST_URL) |
| for key, expected_value in expected_lookup.items(): |
| self.assertEqual(expected_value, project_lookup.get(key)) |
| self.assertEqual(expected_value, project_lookup.get(key + '/')) |
| |
| def testProjectLookupWithGitSuffix(self): |
| """Tests finding a project name that has a .git suffix.""" |
| key_without_git_suffix = 'legacyname' |
| key_with_git_suffix = 'legacyname.git' |
| expected_path = 'path/to/legacy' |
| project_lookup = repo_utils.parse_manifest_for_path( |
| SAMPLE_MANIFEST_STRING, |
| repo_utils.EUREKA_MANIFEST_URL) |
| |
| actual_path = project_lookup.get(key_without_git_suffix) |
| self.assertEqual(expected_path, actual_path) |
| |
| actual_path = project_lookup.get(key_with_git_suffix) |
| self.assertEqual(expected_path, actual_path) |
| |
| def testNormalizeManifestSwapsOutInternalGithub(self): |
| """Tests github.com is temporarily used for the remote fetch.""" |
| with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: |
| f.write(SAMPLE_MANIFEST_WITH_INTERNAL_GITHUB) |
| temp_manifest = f.name |
| with repo_utils.normalize_manifest_if_exists(temp_manifest): |
| with open(temp_manifest, 'r') as f: |
| manifest_content = f.read() |
| self.assertEqual(manifest_content, |
| SAMPLE_MANIFEST_WITH_EXTERNAL_GITHUB) |
| with open(temp_manifest, 'r') as f: |
| manifest_content = f.read() |
| self.assertEqual(manifest_content, SAMPLE_MANIFEST_WITH_INTERNAL_GITHUB) |
| os.unlink(temp_manifest) |
| |
| def testParseManifestWithSameNamesFromDifferentRevisions(self): |
| project_lookup = repo_utils.parse_manifest_for_path( |
| _SAMPLE_MANIFEST_STRING_WITH_MULTI_REVISIONS_OF_SAME_NAMES, |
| repo_utils.EUREKA_MANIFEST_URL) |
| self.assertEqual(project_lookup[('test', 'branch1')], 'test1') |
| self.assertEqual(project_lookup[('test', 'branch2')], 'test2') |
| |
| def testParseManifestUseUpstreamFirstThenRevision(self): |
| project_lookup = repo_utils.parse_manifest_for_path( |
| _SAMPLE_MANIFEST_WITH_UPSTREAMS_SET, repo_utils.EUREKA_MANIFEST_URL) |
| self.assertEqual(project_lookup[('test', 'branch1')], 'test1') |
| self.assertEqual(project_lookup[('test', 'branch2')], 'test2') |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |