blob: 990b4964ddbe10b2faaa622ea342d9fcae9f4bee [file] [log] [blame]
Mike Frysinger1b8565b2016-09-13 16:03:49 -04001# Copyright 2016 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Unittests for loman.py"""
6
Mike Frysinger1b8565b2016-09-13 16:03:49 -04007import os
Gwendal Grignou89afc082016-09-29 21:03:20 -07008import xml.etree.ElementTree as ElementTree
Mike Frysinger1b8565b2016-09-13 16:03:49 -04009
10from chromite.lib import cros_test_lib
11from chromite.lib import osutils
Gwendal Grignou89afc082016-09-29 21:03:20 -070012from chromite.lib import partial_mock
Mike Frysinger1b8565b2016-09-13 16:03:49 -040013from chromite.scripts import loman
14
15
Gwendal Grignou89afc082016-09-29 21:03:20 -070016class RunGitMock(partial_mock.PartialCmdMock):
Alex Klein1699fab2022-09-08 08:46:06 -060017 """Partial mock for git.RunGit."""
Gwendal Grignou89afc082016-09-29 21:03:20 -070018
Alex Klein1699fab2022-09-08 08:46:06 -060019 TARGET = "chromite.lib.git"
20 ATTRS = ("RunGit",)
21 DEFAULT_ATTR = "RunGit"
22
23 def RunGit(self, _git_repo, cmd, _retry=True, **kwargs):
24 return self._results["RunGit"].LookupResult(
25 (cmd,), hook_args=(cmd,), hook_kwargs=kwargs
26 )
Gwendal Grignou89afc082016-09-29 21:03:20 -070027
28
Mike Frysinger1b8565b2016-09-13 16:03:49 -040029class ParserTest(cros_test_lib.OutputTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -060030 """Tests for the CLI parser."""
Mike Frysinger1b8565b2016-09-13 16:03:49 -040031
Alex Klein1699fab2022-09-08 08:46:06 -060032 def setUp(self):
33 self.parser = loman.GetParser()
Mike Frysinger1b8565b2016-09-13 16:03:49 -040034
Alex Klein1699fab2022-09-08 08:46:06 -060035 def testNoCommand(self):
36 """Require a command at least."""
37 with self.OutputCapturer():
38 self.assertRaises(SystemExit, self.parser.parse_args, [])
Mike Frysinger1b8565b2016-09-13 16:03:49 -040039
Alex Klein1699fab2022-09-08 08:46:06 -060040 def testBadCommand(self):
41 """Reject unknown commands."""
42 with self.OutputCapturer():
43 self.assertRaises(SystemExit, self.parser.parse_args, ["flyaway"])
Mike Frysinger1b8565b2016-09-13 16:03:49 -040044
Alex Klein1699fab2022-09-08 08:46:06 -060045 def testAddCommand(self):
46 """Verify basic add command behavior."""
47 with self.OutputCapturer():
48 self.parser.parse_args(["add", "--workon", "project"])
49 self.parser.parse_args(
50 ["add", "project", "path", "--remote", "foo"]
51 )
Mike Frysinger1b8565b2016-09-13 16:03:49 -040052
Mike Frysinger1b8565b2016-09-13 16:03:49 -040053
54class ManifestTest(cros_test_lib.TempDirTestCase):
Alex Klein1699fab2022-09-08 08:46:06 -060055 """Tests that need a real .repo/ manifest layout."""
Mike Frysinger1b8565b2016-09-13 16:03:49 -040056
Alex Klein1699fab2022-09-08 08:46:06 -060057 def setUp(self):
58 # The loman code looks for the repo root, so make one, and chdir there.
59 os.chdir(self.tempdir)
Mike Frysinger1b8565b2016-09-13 16:03:49 -040060
Alex Klein1699fab2022-09-08 08:46:06 -060061 for d in ("repo", "manifests", "manifests.git"):
62 osutils.SafeMakedirs(os.path.join(".repo", d))
Mike Frysinger1b8565b2016-09-13 16:03:49 -040063
Alex Klein1699fab2022-09-08 08:46:06 -060064 for m in ("default.xml", "full.xml", "minilayout.xml"):
65 osutils.Touch(os.path.join(".repo", "manifests", m))
Mike Frysinger1b8565b2016-09-13 16:03:49 -040066
Alex Klein1699fab2022-09-08 08:46:06 -060067 self._SetManifest("default.xml")
Mike Frysinger1b8565b2016-09-13 16:03:49 -040068
Alex Klein1699fab2022-09-08 08:46:06 -060069 def _SetManifest(self, manifest):
70 """Set active manifest to point to |manifest|."""
71 source = os.path.join(".repo", "manifest.xml")
72 target = os.path.join("manifests", manifest)
73 osutils.SafeUnlink(source)
74 os.symlink(target, source)
Mike Frysinger1b8565b2016-09-13 16:03:49 -040075
76
Mike Frysinger1b8565b2016-09-13 16:03:49 -040077class AddTest(cros_test_lib.MockOutputTestCase, ManifestTest):
Alex Klein1699fab2022-09-08 08:46:06 -060078 """Tests for the add command."""
Mike Frysinger1b8565b2016-09-13 16:03:49 -040079
Alex Klein1699fab2022-09-08 08:46:06 -060080 def testRejectBadCommands(self):
81 """Reject bad invocations."""
82 bad_cmds = (
83 # Missing path.
84 ["add"],
85 # Extra project.
86 ["add", "--workon", "path", "project"],
87 # Missing --remote.
88 ["add", "path", "project"],
89 # Missing project.
90 ["add", "path", "--remote", "remote"],
91 )
92 with self.OutputCapturer():
93 for cmd in bad_cmds:
94 self.assertRaises(SystemExit, loman.main, cmd)
Gwendal Grignouf9d6d362016-09-30 09:29:20 -070095
96
97class NoMiniayoutTest(cros_test_lib.MockOutputTestCase, ManifestTest):
Alex Klein1699fab2022-09-08 08:46:06 -060098 """Check deprecated minilayout setups are detected."""
Gwendal Grignouf9d6d362016-09-30 09:29:20 -070099
Alex Klein1699fab2022-09-08 08:46:06 -0600100 def setUp(self):
101 self._SetManifest("minilayout.xml")
Gwendal Grignouf9d6d362016-09-30 09:29:20 -0700102
Alex Klein1699fab2022-09-08 08:46:06 -0600103 def testMiniLayoutDetected(self):
104 """Check error is raised when repo is setup with minilayout."""
Gwendal Grignouf9d6d362016-09-30 09:29:20 -0700105
Alex Klein1699fab2022-09-08 08:46:06 -0600106 class _Error(Exception):
107 """Stub for test."""
Gwendal Grignouf9d6d362016-09-30 09:29:20 -0700108
Alex Klein1699fab2022-09-08 08:46:06 -0600109 self.PatchObject(loman, "_AssertNotMiniLayout", side_effect=_Error)
110 cmd = ["add", "-w", "foo"]
111 with self.OutputCapturer():
112 self.assertRaises(_Error, loman.main, cmd)
Gwendal Grignou89afc082016-09-29 21:03:20 -0700113
114
115class IncludeXmlTest(cros_test_lib.MockOutputTestCase, ManifestTest):
Alex Klein1699fab2022-09-08 08:46:06 -0600116 """End to End tests for reading and producing XML trees."""
Gwendal Grignou89afc082016-09-29 21:03:20 -0700117
Alex Klein1699fab2022-09-08 08:46:06 -0600118 PROJECT = "chromiumos/repohooks"
Gwendal Grignou89afc082016-09-29 21:03:20 -0700119
Alex Klein1699fab2022-09-08 08:46:06 -0600120 def setUp(self):
121 INCLUDING_XML = "including.xml"
122 INCLUDED_XML = "included.xml"
123 osutils.WriteFile(
124 os.path.join(".repo", "manifests", INCLUDING_XML),
125 """
Gwendal Grignou89afc082016-09-29 21:03:20 -0700126<manifest>
127 <include name="%s" />
128 <project remote="cros-internal" path="crostools" groups="br" name="ct" />
Alex Klein1699fab2022-09-08 08:46:06 -0600129</manifest>"""
130 % (INCLUDED_XML,),
131 )
Gwendal Grignou89afc082016-09-29 21:03:20 -0700132
Alex Klein1699fab2022-09-08 08:46:06 -0600133 osutils.WriteFile(
134 os.path.join(".repo", "manifests", INCLUDED_XML),
135 """
Gwendal Grignou89afc082016-09-29 21:03:20 -0700136<manifest>
137 <default remote="cros" revision="HEAD" />
138 <remote name="cros" />
139 <remote name="cros-internal" />
140 <project path="src/repohooks" name="%s" groups="minilayout,bt" />
Alex Klein1699fab2022-09-08 08:46:06 -0600141</manifest>"""
142 % (self.PROJECT,),
143 )
144 self._SetManifest(INCLUDING_XML)
Gwendal Grignou89afc082016-09-29 21:03:20 -0700145
Alex Klein1699fab2022-09-08 08:46:06 -0600146 self.git_mock = self.StartPatcher(RunGitMock())
147 self.git_mock.AddCmdResult(
148 ["symbolic-ref", "-q", "HEAD"], stdout="default"
149 )
150 self.git_mock.AddCmdResult(
151 ["config", "--get-regexp", "branch\\.default\\.(remote|merge)"],
152 stdout="branch.default.merge firmware-branch",
153 )
Gwendal Grignou89afc082016-09-29 21:03:20 -0700154
Alex Klein1699fab2022-09-08 08:46:06 -0600155 self.git_mock.AddCmdResult(
156 [
157 "config",
158 "-f",
159 os.path.join(self.tempdir, ".repo", "manifests.git", "config"),
160 "--get",
161 "manifest.groups",
162 ],
163 stdout="group1,group2",
164 )
Gwendal Grignou89afc082016-09-29 21:03:20 -0700165
Alex Klein1699fab2022-09-08 08:46:06 -0600166 def testAddExistingProject(self):
167 """Add an existing project, check no local_manifest.xml are created."""
168 self.git_mock.AddCmdResult(
169 [
170 "config",
171 "-f",
172 os.path.join(self.tempdir, ".repo", "manifests.git", "config"),
173 "manifest.groups",
174 "minilayout,platform-linux,group1,group2,name:%s"
175 % (self.PROJECT,),
176 ]
177 )
178 cmd = ["add", "-w", self.PROJECT]
179 with self.OutputCapturer():
180 self.assertEqual(loman.main(cmd), 0)
181 self.assertNotExists(os.path.join(".repo", "local_manifest.xml"))
Gwendal Grignou89afc082016-09-29 21:03:20 -0700182
Alex Klein1699fab2022-09-08 08:46:06 -0600183 def testAddNewProject(self):
184 """Add new project to the repo.
Gwendal Grignou89afc082016-09-29 21:03:20 -0700185
Alex Klein1699fab2022-09-08 08:46:06 -0600186 Check local_manifest.xml is created and valid.
187 """
188 new_project = "project"
189 self.git_mock.AddCmdResult(
190 [
191 "config",
192 "-f",
193 os.path.join(self.tempdir, ".repo", "manifests.git", "config"),
194 "manifest.groups",
195 "minilayout,platform-linux,group1,group2,name:%s"
196 % (new_project,),
197 ],
198 )
199 cmd = ["add", new_project, "path", "-r", "remote"]
200 with self.OutputCapturer():
201 self.assertEqual(loman.main(cmd), 0)
202 expected_local_manifest_nodes = ElementTree.fromstring(
203 """
Gwendal Grignou89afc082016-09-29 21:03:20 -0700204<manifest>
205 <project name="project" path="path" remote="remote" workon="False" />
Alex Klein1699fab2022-09-08 08:46:06 -0600206</manifest>"""
207 )
208 with open(os.path.join(".repo", "local_manifest.xml")) as f:
209 local_manifest_nodes = ElementTree.fromstring(f.read())
Gwendal Grignou89afc082016-09-29 21:03:20 -0700210
Alex Klein1699fab2022-09-08 08:46:06 -0600211 # Read project, check for failure.
212 self.assertEqual(
213 ElementTree.tostring(expected_local_manifest_nodes),
214 ElementTree.tostring(local_manifest_nodes),
215 )
Gwendal Grignou89afc082016-09-29 21:03:20 -0700216
Alex Klein1699fab2022-09-08 08:46:06 -0600217 # Check that re-adding triggers error.
218 cmd = ["add", new_project, "path", "-r", "remote"]
219 with self.OutputCapturer() as output:
220 self.assertRaises(SystemExit, loman.main, cmd)
221 self.assertIn("conflicts with", "\n".join(output.GetStderrLines()))