Mike Frysinger | f1ba7ad | 2022-09-12 05:42:57 -0400 | [diff] [blame] | 1 | # Copyright 2018 The ChromiumOS Authors |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | """Tests for scripts/repo_sync_manifest.""" |
| 6 | |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 7 | import os |
Mike Frysinger | 166fea0 | 2021-02-12 05:30:33 -0500 | [diff] [blame] | 8 | from unittest import mock |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 9 | |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 10 | from chromite.lib import cros_build_lib |
| 11 | from chromite.lib import cros_test_lib |
| 12 | from chromite.lib import git |
| 13 | from chromite.lib import osutils |
| 14 | from chromite.lib import parallel_unittest |
Mike Frysinger | 40ffb53 | 2021-02-12 07:36:08 -0500 | [diff] [blame] | 15 | from chromite.lib import repo_util |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 16 | from chromite.scripts import create_manifest_snapshot |
Mike Frysinger | bf34782 | 2022-03-28 19:58:37 -0400 | [diff] [blame] | 17 | from chromite.utils import repo_manifest |
| 18 | from chromite.utils import repo_manifest_unittest |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 19 | |
| 20 | |
| 21 | MANIFEST_XML = """<?xml version="1.0" encoding="UTF-8"?> |
| 22 | <manifest> |
| 23 | <remote name="origin"/> |
| 24 | <default remote="origin"/> |
| 25 | <project name="project/a" revision="f01dab1e"/> |
| 26 | <project name="project/b" revision="cafe1234" upstream="short"/> |
Mike Frysinger | 6e3f23c | 2021-02-17 14:06:19 -0500 | [diff] [blame] | 27 | <project name="project/c" revision="deadbeef" upstream="refs/heads/main"/> |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 28 | <project name="dupe" revision="d1" upstream="dupe"/> |
| 29 | <project name="dupe" revision="d2" upstream="dupe"/> |
| 30 | </manifest> |
| 31 | """ |
| 32 | |
| 33 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 34 | class CreateManifestSnapshotTest( |
| 35 | cros_test_lib.MockTempDirTestCase, repo_manifest_unittest.XMLTestCase |
| 36 | ): |
| 37 | """Unit tests for create_manifest_snapshot.""" |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 38 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 39 | # pylint: disable=protected-access |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 40 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 41 | def setUp(self): |
| 42 | self.manifest = repo_manifest.Manifest.FromString(MANIFEST_XML) |
| 43 | self.project_a = self.manifest.GetUniqueProject("project/a") |
| 44 | self.project_b = self.manifest.GetUniqueProject("project/b") |
| 45 | self.project_c = self.manifest.GetUniqueProject("project/c") |
| 46 | self.dupes = [x for x in self.manifest.Projects() if x.name == "dupe"] |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 47 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 48 | self.mock_is_reachable = self.PatchObject(git, "IsReachable") |
| 49 | self.mock_git_push = self.PatchObject(git, "GitPush") |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 50 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 51 | self.repo_root = os.path.join(self.tempdir, "root") |
| 52 | os.makedirs(os.path.join(self.repo_root, ".repo")) |
| 53 | self.output_file = os.path.join(self.tempdir, "snapshot.xml") |
| 54 | self.main_args = [ |
| 55 | "--repo-path", |
| 56 | self.repo_root, |
| 57 | "--log-level", |
| 58 | "fatal", |
| 59 | "--jobs", |
| 60 | "1", |
| 61 | "--output-file", |
| 62 | self.output_file, |
| 63 | ] |
| 64 | self.PatchObject( |
| 65 | repo_util.Repository, "Manifest", return_value=self.manifest |
| 66 | ) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 67 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 68 | def testGetUpstreamBranchNoUpstream(self): |
| 69 | """Test _GetUpstreamBranch with no upstream.""" |
| 70 | branch = create_manifest_snapshot._GetUpstreamBranch(self.project_a) |
| 71 | self.assertIsNone(branch) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 72 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 73 | def testGetUpstreamBranchShortUpstream(self): |
| 74 | """Test _GetUpstreamBranch with short upstream ref.""" |
| 75 | branch = create_manifest_snapshot._GetUpstreamBranch(self.project_b) |
| 76 | self.assertEqual(branch, "short") |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 77 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 78 | def testGetUpstreamBranchFullUpstream(self): |
| 79 | """Test _GetUpstreamBranch with full upstream ref.""" |
| 80 | branch = create_manifest_snapshot._GetUpstreamBranch(self.project_c) |
| 81 | self.assertEqual(branch, "main") |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 82 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 83 | def testNeedsSnapshotReachable(self): |
| 84 | """Test _NeedsSnapshot with revision reachable from upstream.""" |
| 85 | self.mock_is_reachable.return_value = True |
| 86 | result = create_manifest_snapshot._NeedsSnapshot("root", self.project_c) |
| 87 | self.assertFalse(result) |
| 88 | self.mock_is_reachable.assert_called_with( |
| 89 | "root/project/c", "deadbeef", "refs/remotes/origin/main" |
| 90 | ) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 91 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 92 | def testNeedsSnapshotUnreachable(self): |
| 93 | """Test _NeedsSnapshot with revision reachable from upstream.""" |
| 94 | self.mock_is_reachable.return_value = False |
| 95 | result = create_manifest_snapshot._NeedsSnapshot("root", self.project_b) |
| 96 | self.assertTrue(result) |
| 97 | self.mock_is_reachable.assert_called_with( |
| 98 | "root/project/b", "cafe1234", "refs/remotes/origin/short" |
| 99 | ) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 100 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 101 | def testNeedsSnapshotNoUpstream(self): |
| 102 | """Test _NeedsSnapshot with no project upstream.""" |
| 103 | create_manifest_snapshot._NeedsSnapshot("root", self.project_a) |
| 104 | self.mock_is_reachable.assert_called_with( |
| 105 | "root/project/a", "f01dab1e", "refs/remotes/origin/main" |
| 106 | ) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 107 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 108 | def testNeedsSnapshotIsReachableFailure(self): |
| 109 | """Test _NeedsSnapshot with no project upstream.""" |
| 110 | self.mock_is_reachable.side_effect = cros_build_lib.RunCommandError("") |
| 111 | result = create_manifest_snapshot._NeedsSnapshot("root", self.project_a) |
| 112 | self.assertTrue(result) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 113 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 114 | def testMakeUniqueRefMain(self): |
| 115 | """Test _MakeUniqueRef with upstream main.""" |
| 116 | used = set() |
| 117 | ref1 = create_manifest_snapshot._MakeUniqueRef( |
| 118 | self.project_c, "base", used |
| 119 | ) |
| 120 | ref2 = create_manifest_snapshot._MakeUniqueRef( |
| 121 | self.project_c, "base", used |
| 122 | ) |
| 123 | ref3 = create_manifest_snapshot._MakeUniqueRef( |
| 124 | self.project_c, "base", used |
| 125 | ) |
| 126 | self.assertEqual(ref1, "base") |
| 127 | self.assertEqual(ref2, "base/1") |
| 128 | self.assertEqual(ref3, "base/2") |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 129 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 130 | def testMakeUniqueRefNonMain(self): |
| 131 | """Test _MakeUniqueRef with non-main upstream.""" |
| 132 | used = set() |
| 133 | ref1 = create_manifest_snapshot._MakeUniqueRef( |
| 134 | self.project_b, "base", used |
| 135 | ) |
| 136 | ref2 = create_manifest_snapshot._MakeUniqueRef( |
| 137 | self.project_b, "base", used |
| 138 | ) |
| 139 | self.assertEqual(ref1, "base/short") |
| 140 | self.assertEqual(ref2, "base/short/1") |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 141 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 142 | def testGitPushProjectUpstream(self): |
| 143 | """Test _GitPushProjectUpstream.""" |
| 144 | create_manifest_snapshot._GitPushProjectUpstream( |
| 145 | "root", self.project_b, False |
| 146 | ) |
| 147 | self.mock_git_push.assert_called_with( |
| 148 | "root/project/b", |
| 149 | "cafe1234", |
| 150 | git.RemoteRef("origin", "short"), |
| 151 | dry_run=False, |
| 152 | ) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 153 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 154 | def testGitPushProjectUpstreamDryRun(self): |
| 155 | """Test _GitPushProjectUpstream with dry_run=True.""" |
| 156 | create_manifest_snapshot._GitPushProjectUpstream( |
| 157 | "root", self.project_b, True |
| 158 | ) |
| 159 | self.mock_git_push.assert_called_with( |
| 160 | "root/project/b", |
| 161 | "cafe1234", |
| 162 | git.RemoteRef("origin", "short"), |
| 163 | dry_run=True, |
| 164 | ) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 165 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 166 | def testMainNoSnapshots(self): |
| 167 | """Test main with projects that don't need snapshots.""" |
| 168 | self.mock_is_reachable.return_value = True |
| 169 | create_manifest_snapshot.main(self.main_args) |
| 170 | snapshot_xml = osutils.ReadFile(self.output_file) |
| 171 | self.AssertXMLAlmostEqual(snapshot_xml, MANIFEST_XML) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 172 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 173 | def testMainSnapshots(self): |
| 174 | """Test main with projects that need snapshots.""" |
| 175 | self.mock_is_reachable.return_value = False |
| 176 | args = self.main_args + ["--snapshot-ref", "refs/snap"] |
| 177 | with parallel_unittest.ParallelMock(): |
| 178 | create_manifest_snapshot.main(args) |
| 179 | snapshot_xml = osutils.ReadFile(self.output_file) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 180 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 181 | self.mock_git_push.assert_has_calls( |
| 182 | [ |
| 183 | mock.call( |
| 184 | os.path.join(self.repo_root, "project/a"), |
| 185 | "f01dab1e", |
| 186 | git.RemoteRef("origin", "refs/snap"), |
| 187 | dry_run=False, |
| 188 | ), |
| 189 | mock.call( |
| 190 | os.path.join(self.repo_root, "project/b"), |
| 191 | "cafe1234", |
| 192 | git.RemoteRef("origin", "refs/snap"), |
| 193 | dry_run=False, |
| 194 | ), |
| 195 | mock.call( |
| 196 | os.path.join(self.repo_root, "project/c"), |
| 197 | "deadbeef", |
| 198 | git.RemoteRef("origin", "refs/snap"), |
| 199 | dry_run=False, |
| 200 | ), |
| 201 | mock.call( |
| 202 | os.path.join(self.repo_root, "dupe"), |
| 203 | "d1", |
| 204 | git.RemoteRef("origin", "refs/snap/dupe"), |
| 205 | dry_run=False, |
| 206 | ), |
| 207 | mock.call( |
| 208 | os.path.join(self.repo_root, "dupe"), |
| 209 | "d2", |
| 210 | git.RemoteRef("origin", "refs/snap/dupe/1"), |
| 211 | dry_run=False, |
| 212 | ), |
| 213 | ], |
| 214 | any_order=True, |
| 215 | ) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 216 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 217 | expected = repo_manifest.Manifest.FromString(MANIFEST_XML) |
| 218 | for project in expected.Projects(): |
| 219 | if project.name == "dupe": |
| 220 | if project.revision == "d1": |
| 221 | project.upstream = "refs/snap/dupe" |
| 222 | else: |
| 223 | project.upstream = "refs/snap/dupe/1" |
| 224 | else: |
| 225 | project.upstream = "refs/snap" |
| 226 | expected_xml = repo_manifest_unittest.ManifestToString(expected) |
| 227 | self.AssertXMLAlmostEqual(snapshot_xml, expected_xml) |
Lann Martin | 4fbdf20 | 2018-08-30 12:02:52 -0600 | [diff] [blame] | 228 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 229 | def testMainNeedsSnapshotNoSnapshotRef(self): |
| 230 | """Test main with projects that need snapshots but no --snapshot-ref.""" |
| 231 | self.mock_is_reachable.return_value = False |
| 232 | with self.assertRaises(SystemExit): |
| 233 | create_manifest_snapshot.main(self.main_args) |