blob: 9822de0f75f1b2b27970ee6fd2775b7c22078d80 [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
7from __future__ import print_function
8
9import os
Gwendal Grignou89afc082016-09-29 21:03:20 -070010import xml.etree.ElementTree as ElementTree
Mike Frysinger1b8565b2016-09-13 16:03:49 -040011
12from chromite.lib import cros_test_lib
13from chromite.lib import osutils
Gwendal Grignou89afc082016-09-29 21:03:20 -070014from chromite.lib import partial_mock
Mike Frysinger1b8565b2016-09-13 16:03:49 -040015from chromite.scripts import loman
16
17
Gwendal Grignou89afc082016-09-29 21:03:20 -070018class RunGitMock(partial_mock.PartialCmdMock):
19 """Partial mock for git.RunGit."""
20 TARGET = 'chromite.lib.git'
21 ATTRS = ('RunGit',)
22 DEFAULT_ATTR = 'RunGit'
23
24 def RunGit(self, _git_repo, cmd, _retry=True, **kwargs):
25 return self._results['RunGit'].LookupResult(
26 (cmd,), hook_args=(cmd,), hook_kwargs=kwargs)
27
28
Mike Frysinger1b8565b2016-09-13 16:03:49 -040029class ParserTest(cros_test_lib.OutputTestCase):
30 """Tests for the CLI parser."""
31
32 def setUp(self):
33 self.parser = loman.GetParser()
34
35 def testNoCommand(self):
36 """Require a command at least."""
37 with self.OutputCapturer():
38 self.assertRaises(SystemExit, self.parser.parse_args, [])
39
40 def testBadCommand(self):
41 """Reject unknown commands."""
42 with self.OutputCapturer():
43 self.assertRaises(SystemExit, self.parser.parse_args, ['flyaway'])
44
45 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(['add', 'project', 'path', '--remote', 'foo'])
50
Mike Frysinger1b8565b2016-09-13 16:03:49 -040051
52class ManifestTest(cros_test_lib.TempDirTestCase):
53 """Tests that need a real .repo/ manifest layout."""
54
55 def setUp(self):
56 # The loman code looks for the repo root, so make one, and chdir there.
57 os.chdir(self.tempdir)
58
59 for d in ('repo', 'manifests', 'manifests.git'):
60 osutils.SafeMakedirs(os.path.join('.repo', d))
61
62 for m in ('default.xml', 'full.xml', 'minilayout.xml'):
63 osutils.Touch(os.path.join('.repo', 'manifests', m))
64
65 self._SetManifest('default.xml')
66
67 def _SetManifest(self, manifest):
68 """Set active manifest to point to |manifest|."""
69 source = os.path.join('.repo', 'manifest.xml')
Gwendal Grignouf9d6d362016-09-30 09:29:20 -070070 target = os.path.join('manifests', manifest)
Mike Frysinger1b8565b2016-09-13 16:03:49 -040071 osutils.SafeUnlink(source)
72 os.symlink(target, source)
73
74
Mike Frysinger1b8565b2016-09-13 16:03:49 -040075class AddTest(cros_test_lib.MockOutputTestCase, ManifestTest):
76 """Tests for the add command."""
77
78 def testRejectBadCommands(self):
79 """Reject bad invocations."""
80 bad_cmds = (
81 # Missing path.
82 ['add'],
83 # Extra project.
84 ['add', '--workon', 'path', 'project'],
85 # Missing --remote.
86 ['add', 'path', 'project'],
87 # Missing project.
88 ['add', 'path', '--remote', 'remote'],
89 )
90 with self.OutputCapturer():
91 for cmd in bad_cmds:
92 self.assertRaises(SystemExit, loman.main, cmd)
Gwendal Grignouf9d6d362016-09-30 09:29:20 -070093
94
95class NoMiniayoutTest(cros_test_lib.MockOutputTestCase, ManifestTest):
96 """Check deprecated minilayout setups are detected."""
97
98 def setUp(self):
99 self._SetManifest('minilayout.xml')
100
101 def testMiniLayoutDetected(self):
102 """Check error is raised when repo is setup with minilayout."""
103
104 class _Error(Exception):
105 """Stub for test."""
106
107 self.PatchObject(loman, '_AssertNotMiniLayout', side_effect=_Error)
108 cmd = ['add', '-w', 'foo']
109 with self.OutputCapturer():
110 self.assertRaises(_Error, loman.main, cmd)
Gwendal Grignou89afc082016-09-29 21:03:20 -0700111
112
113class IncludeXmlTest(cros_test_lib.MockOutputTestCase, ManifestTest):
114 """End to End tests for reading and producing XML trees."""
115
116 PROJECT = 'chromiumos/repohooks'
117
118 def setUp(self):
119 INCLUDING_XML = 'including.xml'
120 INCLUDED_XML = 'included.xml'
121 osutils.WriteFile(os.path.join('.repo', 'manifests', INCLUDING_XML),
122 """
123<manifest>
124 <include name="%s" />
125 <project remote="cros-internal" path="crostools" groups="br" name="ct" />
126</manifest>""" % (INCLUDED_XML,))
127
128 osutils.WriteFile(os.path.join('.repo', 'manifests', INCLUDED_XML),
129 """
130<manifest>
131 <default remote="cros" revision="HEAD" />
132 <remote name="cros" />
133 <remote name="cros-internal" />
134 <project path="src/repohooks" name="%s" groups="minilayout,bt" />
135</manifest>""" % (self.PROJECT,))
136 self._SetManifest(INCLUDING_XML)
137
138 self.git_mock = self.StartPatcher(RunGitMock())
139 self.git_mock.AddCmdResult(
140 ['symbolic-ref', '-q', 'HEAD'], output='default')
141 self.git_mock.AddCmdResult(
142 ['config', '--get-regexp', 'branch\\.default\\.(remote|merge)'],
143 output='branch.default.merge firmware-branch')
144
145 self.git_mock.AddCmdResult(
146 ['config',
147 '-f', os.path.join(self.tempdir, '.repo', 'manifests.git', 'config'),
148 '--get', 'manifest.groups'], output='group1,group2')
149
150 def testAddExistingProject(self):
151 """Add an existing project, check no local_manifest.xml are created."""
152 self.git_mock.AddCmdResult(
153 ['config',
154 '-f', os.path.join(self.tempdir, '.repo', 'manifests.git', 'config'),
155 'manifest.groups',
156 'minilayout,platform-linux,group1,group2,name:%s' % (self.PROJECT,)])
157 cmd = ['add', '-w', self.PROJECT]
158 with self.OutputCapturer():
159 self.assertEqual(loman.main(cmd), 0)
160 self.assertNotExists(os.path.join('.repo', 'local_manifest.xml'))
161
162 def testAddNewProject(self):
163 """Add new project to the repo.
164
165 Check local_manifest.xml is created and valid.
166 """
167 new_project = 'project'
168 self.git_mock.AddCmdResult(
169 ['config',
170 '-f', os.path.join(self.tempdir, '.repo', 'manifests.git', 'config'),
171 'manifest.groups',
172 'minilayout,platform-linux,group1,group2,name:%s' % (new_project,)],)
173 cmd = ['add', new_project, 'path', '-r', 'remote']
174 with self.OutputCapturer():
175 self.assertEqual(loman.main(cmd), 0)
176 expected_local_manifest_nodes = ElementTree.fromstring("""
177<manifest>
178 <project name="project" path="path" remote="remote" workon="False" />
179</manifest>""")
180 with open(os.path.join('.repo', 'local_manifest.xml')) as f:
181 local_manifest_nodes = ElementTree.fromstring(f.read())
182
183 # Read project, check for failure.
184 self.assertEqual(ElementTree.tostring(expected_local_manifest_nodes),
185 ElementTree.tostring(local_manifest_nodes))
186
187 # Check that re-adding triggers error.
188 cmd = ['add', new_project, 'path', '-r', 'remote']
189 with self.OutputCapturer() as output:
190 self.assertRaises(SystemExit, loman.main, cmd)
191 self.assertIn('conflicts with', '\n'.join(output.GetStderrLines()))