2 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Unit tests for portage_util.py."""
8 from __future__ import print_function
16 sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)),
18 from chromite.cbuildbot import constants
19 from chromite.lib import cros_build_lib
20 from chromite.lib import cros_test_lib
21 from chromite.lib import git
22 from chromite.lib import osutils
23 from chromite.lib import portage_util
25 # pylint: disable=W0212
26 MANIFEST = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
28 class _Package(object):
29 """Package helper class."""
30 def __init__(self, package):
31 self.package = package
34 class _DummyCommandResult(object):
35 """Create mock RunCommand results."""
36 def __init__(self, output):
37 # Members other than 'output' are expected to be unused, so
40 # All shell output will be newline terminated; we add the
41 # newline here for convenience.
42 self.output = output + '\n'
45 class EBuildTest(cros_test_lib.MoxTestCase):
46 """Ebuild related tests."""
48 def _makeFakeEbuild(self, fake_ebuild_path, fake_ebuild_content=''):
49 self.mox.StubOutWithMock(fileinput, 'input')
50 fileinput.input(fake_ebuild_path).AndReturn(fake_ebuild_content)
52 fake_ebuild = portage_util.EBuild(fake_ebuild_path)
56 def testParseEBuildPath(self):
57 # Test with ebuild with revision number.
58 fake_ebuild_path = '/path/to/test_package/test_package-0.0.1-r1.ebuild'
59 fake_ebuild = self._makeFakeEbuild(fake_ebuild_path)
61 self.assertEquals(fake_ebuild._category, 'to')
62 self.assertEquals(fake_ebuild._pkgname, 'test_package')
63 self.assertEquals(fake_ebuild.version_no_rev, '0.0.1')
64 self.assertEquals(fake_ebuild.current_revision, 1)
65 self.assertEquals(fake_ebuild.version, '0.0.1-r1')
66 self.assertEquals(fake_ebuild.package, 'to/test_package')
67 self.assertEquals(fake_ebuild._ebuild_path_no_version,
68 '/path/to/test_package/test_package')
69 self.assertEquals(fake_ebuild.ebuild_path_no_revision,
70 '/path/to/test_package/test_package-0.0.1')
71 self.assertEquals(fake_ebuild._unstable_ebuild_path,
72 '/path/to/test_package/test_package-9999.ebuild')
73 self.assertEquals(fake_ebuild.ebuild_path, fake_ebuild_path)
75 def testParseEBuildPathNoRevisionNumber(self):
76 # Test with ebuild without revision number.
77 fake_ebuild_path = '/path/to/test_package/test_package-9999.ebuild'
78 fake_ebuild = self._makeFakeEbuild(fake_ebuild_path)
80 self.assertEquals(fake_ebuild._category, 'to')
81 self.assertEquals(fake_ebuild._pkgname, 'test_package')
82 self.assertEquals(fake_ebuild.version_no_rev, '9999')
83 self.assertEquals(fake_ebuild.current_revision, 0)
84 self.assertEquals(fake_ebuild.version, '9999')
85 self.assertEquals(fake_ebuild.package, 'to/test_package')
86 self.assertEquals(fake_ebuild._ebuild_path_no_version,
87 '/path/to/test_package/test_package')
88 self.assertEquals(fake_ebuild.ebuild_path_no_revision,
89 '/path/to/test_package/test_package-9999')
90 self.assertEquals(fake_ebuild._unstable_ebuild_path,
91 '/path/to/test_package/test_package-9999.ebuild')
92 self.assertEquals(fake_ebuild.ebuild_path, fake_ebuild_path)
94 def testGetCommitId(self):
95 fake_sources = '/path/to/sources'
96 fake_hash = '24ab3c9f6d6b5c744382dba2ca8fb444b9808e9f'
97 fake_ebuild_path = '/path/to/test_package/test_package-9999.ebuild'
98 fake_ebuild = self._makeFakeEbuild(fake_ebuild_path)
101 self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
102 result = _DummyCommandResult(fake_hash)
103 cros_build_lib.RunCommand(
106 print_cmd=portage_util.EBuild.VERBOSE,
107 capture_output=True).AndReturn(result)
110 test_hash = fake_ebuild.GetCommitId(fake_sources)
112 self.assertEquals(test_hash, fake_hash)
114 def testEBuildStable(self):
115 """Test ebuild w/keyword variations"""
116 fake_ebuild_path = '/path/to/test_package/test_package-9999.ebuild'
121 ('~amd64 ~arm ~x86', False),
122 ('~amd64 arm ~x86', True),
126 for keywords, stable in datasets:
127 fake_ebuild = self._makeFakeEbuild(
128 fake_ebuild_path, fake_ebuild_content=['KEYWORDS="%s"\n' % keywords])
129 self.assertEquals(fake_ebuild.is_stable, stable)
130 self.mox.UnsetStubs()
132 def testEBuildBlacklisted(self):
133 """Test blacklisted ebuild"""
134 fake_ebuild_path = '/path/to/test_package/test_package-9999.ebuild'
136 fake_ebuild = self._makeFakeEbuild(fake_ebuild_path)
137 self.assertEquals(fake_ebuild.is_blacklisted, False)
138 self.mox.UnsetStubs()
140 fake_ebuild = self._makeFakeEbuild(
141 fake_ebuild_path, fake_ebuild_content=['CROS_WORKON_BLACKLIST="1"\n'])
142 self.assertEquals(fake_ebuild.is_blacklisted, True)
145 class ProjectAndPathTest(cros_test_lib.MoxTempDirTestCase):
146 """Project and Path related tests."""
148 def _MockParseWorkonVariables(self, fake_projects, _fake_localname,
149 _fake_subdir, fake_ebuild_contents):
150 """Mock the necessary calls, start Replay mode, call GetSourcePath()."""
151 # pylint: disable=E1120
152 self.mox.StubOutWithMock(os.path, 'isdir')
153 self.mox.StubOutWithMock(MANIFEST, 'FindCheckoutFromPath')
155 # We need 'chromeos-base' here because it controls default _SUBDIR values.
156 ebuild_path = os.path.join(self.tempdir, 'chromeos-base', 'package',
157 'package-9999.ebuild')
158 osutils.WriteFile(ebuild_path, fake_ebuild_contents, makedirs=True)
159 for p in fake_projects:
160 os.path.isdir(mox.IgnoreArg()).AndReturn(False)
161 for p in fake_projects:
162 os.path.isdir(mox.IgnoreArg()).AndReturn(True)
163 MANIFEST.FindCheckoutFromPath(mox.IgnoreArg()).AndReturn({ 'name': p })
166 ebuild = portage_util.EBuild(ebuild_path)
167 result = ebuild.GetSourcePath(self.tempdir, MANIFEST)
171 def testParseLegacyWorkonVariables(self):
172 """Tests if ebuilds in a single item format are correctly parsed."""
173 fake_project = 'my_project1'
174 fake_localname = 'foo'
176 fake_ebuild_contents = """
177 CROS_WORKON_PROJECT=%s
178 CROS_WORKON_LOCALNAME=%s
179 CROS_WORKON_SUBDIR=%s
180 """ % (fake_project, fake_localname, fake_subdir)
181 project, subdir = self._MockParseWorkonVariables(
182 [fake_project], [fake_localname], [fake_subdir], fake_ebuild_contents)
183 self.assertEquals(project, [fake_project])
184 self.assertEquals(subdir, [os.path.join(
185 self.tempdir, 'platform', '%s/%s' % (fake_localname, fake_subdir))])
187 def testParseArrayWorkonVariables(self):
188 """Tests if ebuilds in an array format are correctly parsed."""
189 fake_projects = ['my_project1', 'my_project2', 'my_project3']
190 fake_localname = ['foo', 'bar', 'bas']
191 fake_subdir = ['sub1', 'sub2', 'sub3']
192 # The test content is formatted using the same function that
193 # formats ebuild output, ensuring that we can parse our own
195 fake_ebuild_contents = """
196 CROS_WORKON_PROJECT=%s
197 CROS_WORKON_LOCALNAME=%s
198 CROS_WORKON_SUBDIR=%s
199 """ % (portage_util.EBuild.FormatBashArray(fake_projects),
200 portage_util.EBuild.FormatBashArray(fake_localname),
201 portage_util.EBuild.FormatBashArray(fake_subdir))
202 project, subdir = self._MockParseWorkonVariables(
203 fake_projects, fake_localname, fake_subdir, fake_ebuild_contents)
204 self.assertEquals(project, fake_projects)
205 fake_path = ['%s/%s' % (fake_localname[i], fake_subdir[i])
206 for i in range(0, len(fake_projects))]
207 fake_path = map(lambda x: os.path.realpath(
208 os.path.join(self.tempdir, 'platform', x)), fake_path)
209 self.assertEquals(subdir, fake_path)
212 class StubEBuild(portage_util.EBuild):
213 """Test helper to StubEBuild."""
214 def __init__(self, path):
215 super(StubEBuild, self).__init__(path)
216 self.is_workon = True
217 self.is_stable = True
219 def _ReadEBuild(self, path):
222 def GetCommitId(self, srcpath):
225 'p1_path1' : 'my_id1',
226 'p1_path2' : 'my_id2'
228 if srcpath in id_map:
229 return id_map[srcpath]
234 class EBuildRevWorkonTest(cros_test_lib.MoxTempDirTestCase):
235 """Tests for EBuildRevWorkon."""
236 # Lines that we will feed as fake ebuild contents to
237 # EBuild.MarAsStable(). This is the minimum content needed
238 # to test the various branches in the function's main processing
240 _mock_ebuild = ['EAPI=2\n',
241 'CROS_WORKON_COMMIT=old_id\n',
242 'KEYWORDS=\"~x86 ~arm ~amd64\"\n',
244 _mock_ebuild_multi = ['EAPI=2\n',
245 'CROS_WORKON_COMMIT=("old_id1","old_id2")\n',
246 'KEYWORDS=\"~x86 ~arm ~amd64\"\n',
250 self.overlay = '/sources/overlay'
251 package_name = os.path.join(self.overlay,
252 'category/test_package/test_package-0.0.1')
253 ebuild_path = package_name + '-r1.ebuild'
254 self.m_ebuild = StubEBuild(ebuild_path)
255 self.revved_ebuild_path = package_name + '-r2.ebuild'
257 def createRevWorkOnMocks(self, ebuild_content, rev, multi=False):
258 # pylint: disable=E1120
259 self.mox.StubOutWithMock(os.path, 'exists')
260 self.mox.StubOutWithMock(cros_build_lib, 'Die')
261 self.mox.StubOutWithMock(portage_util.shutil, 'copyfile')
262 self.mox.StubOutWithMock(os, 'unlink')
263 self.mox.StubOutWithMock(portage_util.EBuild, '_RunGit')
264 self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
265 self.mox.StubOutWithMock(portage_util.filecmp, 'cmp')
266 self.mox.StubOutWithMock(portage_util.fileinput, 'input')
267 self.mox.StubOutWithMock(portage_util.EBuild, 'GetVersion')
268 self.mox.StubOutWithMock(portage_util.EBuild, 'GetSourcePath')
269 self.mox.StubOutWithMock(portage_util.EBuild, 'GetTreeId')
272 portage_util.EBuild.GetSourcePath('/sources', MANIFEST).AndReturn(
273 (['fake_project1','fake_project2'], ['p1_path1','p1_path2']))
275 portage_util.EBuild.GetSourcePath('/sources', MANIFEST).AndReturn(
276 (['fake_project1'], ['p1_path']))
277 portage_util.EBuild.GetVersion('/sources', MANIFEST, '0.0.1').AndReturn(
280 portage_util.EBuild.GetTreeId('p1_path1').AndReturn('treehash1')
281 portage_util.EBuild.GetTreeId('p1_path2').AndReturn('treehash2')
283 portage_util.EBuild.GetTreeId('p1_path').AndReturn('treehash')
285 ebuild_9999 = self.m_ebuild._unstable_ebuild_path
286 os.path.exists(ebuild_9999).AndReturn(True)
288 # These calls come from MarkAsStable()
289 portage_util.shutil.copyfile(ebuild_9999, self.revved_ebuild_path)
291 m_file = self.mox.CreateMock(file)
292 portage_util.fileinput.input(self.revved_ebuild_path,
293 inplace=1).AndReturn(ebuild_content)
294 m_file.write('EAPI=2\n')
297 m_file.write('CROS_WORKON_COMMIT=("my_id1" "my_id2")\n')
298 m_file.write('CROS_WORKON_TREE=("treehash1" "treehash2")\n')
300 m_file.write('CROS_WORKON_COMMIT="my_id"\n')
301 m_file.write('CROS_WORKON_TREE="treehash"\n')
303 m_file.write('KEYWORDS=\"x86 arm amd64\"\n')
304 m_file.write('src_unpack(){}\n')
305 # MarkAsStable() returns here
307 portage_util.filecmp.cmp(self.m_ebuild.ebuild_path,
308 self.revved_ebuild_path,
309 shallow=False).AndReturn(not rev)
311 cmd = ['add', self.revved_ebuild_path]
312 portage_util.EBuild._RunGit(self.overlay, cmd)
313 if self.m_ebuild.is_stable:
314 cmd = ['rm', self.m_ebuild.ebuild_path]
315 portage_util.EBuild._RunGit(self.overlay, cmd)
317 os.unlink(self.revved_ebuild_path)
321 def testRevWorkOnEBuild(self):
322 """Test Uprev of a single project ebuild."""
323 m_file = self.createRevWorkOnMocks(self._mock_ebuild, rev=True)
325 result = self.m_ebuild.RevWorkOnEBuild('/sources', MANIFEST,
326 redirect_file=m_file)
328 self.assertEqual(result, 'category/test_package-0.0.1-r2')
330 def testRevWorkOnMultiEBuild(self):
331 """Test Uprev of a multi-project (array) ebuild."""
332 m_file = self.createRevWorkOnMocks(self._mock_ebuild_multi, rev=True,
335 result = self.m_ebuild.RevWorkOnEBuild('/sources', MANIFEST,
336 redirect_file=m_file)
338 self.assertEqual(result, 'category/test_package-0.0.1-r2')
340 def testRevUnchangedEBuild(self):
341 m_file = self.createRevWorkOnMocks(self._mock_ebuild, rev=False)
344 result = self.m_ebuild.RevWorkOnEBuild('/sources', MANIFEST,
345 redirect_file=m_file)
347 self.assertEqual(result, None)
349 def testRevMissingEBuild(self):
350 self.revved_ebuild_path = self.m_ebuild.ebuild_path
351 self.m_ebuild.ebuild_path = self.m_ebuild._unstable_ebuild_path
352 self.m_ebuild.current_revision = 0
353 self.m_ebuild.is_stable = False
355 m_file = self.createRevWorkOnMocks(
356 self._mock_ebuild[0:1] + self._mock_ebuild[2:], rev=True)
359 result = self.m_ebuild.RevWorkOnEBuild('/sources', MANIFEST,
360 redirect_file=m_file)
362 self.assertEqual(result, 'category/test_package-0.0.1-r1')
364 def testCommitChange(self):
365 self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
366 mock_message = 'Commitme'
367 git.RunGit('.', ['commit', '-a', '-m', mock_message])
369 self.m_ebuild.CommitChange(mock_message, '.')
372 def testUpdateCommitHashesForChanges(self):
373 """Tests that we can update the commit hashes for changes correctly."""
374 cls = portage_util.EBuild
375 ebuild1 = self.mox.CreateMock(cls)
376 ebuild1.ebuild_path = 'public_overlay/ebuild.ebuild'
377 ebuild1.package = 'test/project'
379 self.mox.StubOutWithMock(portage_util, 'FindOverlays')
380 self.mox.StubOutWithMock(cls, '_GetEBuildPaths')
381 self.mox.StubOutWithMock(cls, '_GetSHA1ForPath')
382 self.mox.StubOutWithMock(cls, 'UpdateEBuild')
383 self.mox.StubOutWithMock(cls, 'CommitChange')
384 self.mox.StubOutWithMock(cls, 'GitRepoHasChanges')
386 build_root = 'fakebuildroot'
387 overlays = ['public_overlay']
388 changes = ['fake change']
389 paths = ['fake_path1', 'fake_path2']
390 path_ebuilds = {ebuild1: paths}
391 portage_util.FindOverlays(
392 constants.BOTH_OVERLAYS, buildroot=build_root).AndReturn(overlays)
393 cls._GetEBuildPaths(build_root, mox.IgnoreArg(), overlays,
394 changes).AndReturn(path_ebuilds)
395 for i, p in enumerate(paths):
396 cls._GetSHA1ForPath(mox.IgnoreArg(), p).InAnyOrder().AndReturn(str(i))
397 cls.UpdateEBuild(ebuild1.ebuild_path, dict(CROS_WORKON_COMMIT='("0" "1")'))
398 cls.GitRepoHasChanges('public_overlay').AndReturn(True)
399 cls.CommitChange(mox.IgnoreArg(), overlay='public_overlay')
401 cls.UpdateCommitHashesForChanges(changes, build_root, MANIFEST)
404 def testGitRepoHasChanges(self):
405 """Tests that GitRepoHasChanges works correctly."""
406 url = 'file://' + os.path.join(constants.SOURCE_ROOT, 'chromite')
407 git.RunGit(self.tempdir, ['clone', '--depth=1', url, self.tempdir])
408 # No changes yet as we just cloned the repo.
409 self.assertFalse(portage_util.EBuild.GitRepoHasChanges(self.tempdir))
410 # Update metadata but no real changes.
411 osutils.Touch(os.path.join(self.tempdir, 'LICENSE'))
412 self.assertFalse(portage_util.EBuild.GitRepoHasChanges(self.tempdir))
414 osutils.WriteFile(os.path.join(self.tempdir, 'LICENSE'), 'hi')
415 self.assertTrue(portage_util.EBuild.GitRepoHasChanges(self.tempdir))
418 class FindOverlaysTest(cros_test_lib.MockTestCase):
419 """Tests related to finding overlays."""
421 FAKE, MARIO = 'fake-board', 'x86-mario'
422 PRIVATE = constants.PRIVATE_OVERLAYS
423 PUBLIC = constants.PUBLIC_OVERLAYS
424 BOTH = constants.BOTH_OVERLAYS
427 """Fetch all overlays."""
429 for b in (None, self.FAKE, self.MARIO):
430 self.overlays[b] = d = {}
431 for o in (self.PRIVATE, self.PUBLIC, self.BOTH, None):
432 d[o] = portage_util.FindOverlays(o, b, constants.SOURCE_ROOT)
433 self._no_overlays = not bool(any(d.values()))
435 def _MaybeSkip(self):
436 """Skip the test if no overlays are available."""
437 # TODO: Should create a local buildroot to test against instead ...
438 if self._no_overlays:
439 raise unittest.SkipTest('no overlays found in src/overlays/')
441 def testMissingPrimaryOverlay(self):
442 """Test what happens when a primary overlay is missing.
444 If the overlay doesn't exist, FindOverlays should throw a
445 MissingOverlayException.
447 self.assertRaises(portage_util.MissingOverlayException,
448 portage_util.FindPrimaryOverlay, self.BOTH,
449 self.FAKE, constants.SOURCE_ROOT)
451 def testDuplicates(self):
452 """Verify that no duplicate overlays are returned."""
453 for d in self.overlays.itervalues():
454 for overlays in d.itervalues():
455 self.assertEqual(len(overlays), len(set(overlays)))
457 def testOverlaysExist(self):
458 """Verify that all overlays returned actually exist on disk."""
459 for d in self.overlays.itervalues():
460 for overlays in d.itervalues():
461 self.assertTrue(all(os.path.isdir(x) for x in overlays))
463 def testPrivatePublicOverlayTypes(self):
464 """Verify public/private filtering.
466 If we ask for results from 'both overlays', we should
467 find all public and all private overlays.
469 There should always be at least one public overlay. (Note:
470 there may not be any private overlays, e.g. if the user has
475 for d in self.overlays.itervalues():
476 self.assertGreaterEqual(set(d[self.BOTH]), set(d[self.PUBLIC]))
477 self.assertGreater(set(d[self.BOTH]), set(d[self.PRIVATE]))
478 self.assertTrue(set(d[self.PUBLIC]).isdisjoint(d[self.PRIVATE]))
480 def testNoOverlayType(self):
481 """If we specify overlay_type=None, no results should be returned."""
482 self.assertTrue(all(d[None] == [] for d in self.overlays.itervalues()))
484 def testNonExistentBoard(self):
485 """Test what happens when a non-existent board is supplied.
487 If we specify a non-existent board to FindOverlays, only generic
488 overlays should be returned.
492 for o in (self.PUBLIC, self.BOTH):
493 self.assertLess(set(self.overlays[self.FAKE][o]),
494 set(self.overlays[self.MARIO][o]))
496 def testAllBoards(self):
497 """If we specify board=None, all overlays should be returned."""
500 for o in (self.PUBLIC, self.BOTH):
501 for b in (self.FAKE, self.MARIO):
502 self.assertLess(set(self.overlays[b][o]), set(self.overlays[None][o]))
504 def testMarioPrimaryOverlay(self):
505 """Verify that mario has a primary overlay.
507 Further, the only difference between the public overlays for mario and a
508 fake board is the primary overlay, which is listed last.
512 mario_primary = portage_util.FindPrimaryOverlay(self.BOTH, self.MARIO,
513 constants.SOURCE_ROOT)
514 self.assertIn(mario_primary, self.overlays[self.MARIO][self.BOTH])
515 self.assertNotIn(mario_primary, self.overlays[self.FAKE][self.BOTH])
516 self.assertEqual(mario_primary, self.overlays[self.MARIO][self.PUBLIC][-1])
517 self.assertEqual(self.overlays[self.MARIO][self.PUBLIC][:-1],
518 self.overlays[self.FAKE][self.PUBLIC])
520 def testReadOverlayFile(self):
521 """Verify that the boards are examined in the right order"""
522 m = self.PatchObject(osutils, 'ReadFile',
523 side_effect=IOError(os.errno.ENOENT, 'ENOENT'))
524 portage_util.ReadOverlayFile('test', self.PUBLIC, self.MARIO,
525 constants.SOURCE_ROOT)
526 read_overlays = [x[0][0][:-5] for x in m.call_args_list]
527 overlays = [x for x in reversed(self.overlays[self.MARIO][self.PUBLIC])]
528 self.assertEqual(read_overlays, overlays)
531 class UtilFuncsTest(cros_test_lib.TempDirTestCase):
532 """Basic tests for utility functions"""
534 def _CreateProfilesRepoName(self, name):
535 """Write |name| to profiles/repo_name"""
536 profiles = os.path.join(self.tempdir, 'profiles')
537 osutils.SafeMakedirs(profiles)
538 repo_name = os.path.join(profiles, 'repo_name')
539 osutils.WriteFile(repo_name, name)
541 def testGetOverlayNameNone(self):
542 """If the overlay has no name, it should be fine"""
543 self.assertEqual(portage_util.GetOverlayName(self.tempdir), None)
545 def testGetOverlayNameProfilesRepoName(self):
546 """Verify profiles/repo_name can be read"""
547 self._CreateProfilesRepoName('hi!')
548 self.assertEqual(portage_util.GetOverlayName(self.tempdir), 'hi!')
550 def testGetOverlayNameProfilesLayoutConf(self):
551 """Verify metadata/layout.conf is read before profiles/repo_name"""
552 self._CreateProfilesRepoName('hi!')
553 metadata = os.path.join(self.tempdir, 'metadata')
554 osutils.SafeMakedirs(metadata)
555 layout_conf = os.path.join(metadata, 'layout.conf')
556 osutils.WriteFile(layout_conf, 'repo-name = bye')
557 self.assertEqual(portage_util.GetOverlayName(self.tempdir), 'bye')
559 def testGetOverlayNameProfilesLayoutConfNoRepoName(self):
560 """Verify metadata/layout.conf w/out repo-name is ignored"""
561 self._CreateProfilesRepoName('hi!')
562 metadata = os.path.join(self.tempdir, 'metadata')
563 osutils.SafeMakedirs(metadata)
564 layout_conf = os.path.join(metadata, 'layout.conf')
565 osutils.WriteFile(layout_conf, 'here = we go')
566 self.assertEqual(portage_util.GetOverlayName(self.tempdir), 'hi!')
569 class BuildEBuildDictionaryTest(cros_test_lib.MoxTestCase):
570 """Tests of the EBuild Dictionary."""
573 self.mox.StubOutWithMock(os, 'walk')
574 self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
575 self.package = 'chromeos-base/test_package'
576 self.root = '/overlay/chromeos-base/test_package'
577 self.package_path = self.root + '/test_package-0.0.1.ebuild'
578 paths = [[self.root, [], []]]
579 os.walk("/overlay").AndReturn(paths)
580 self.mox.StubOutWithMock(portage_util, '_FindUprevCandidates')
582 def testWantedPackage(self):
583 overlays = {"/overlay": []}
584 package = _Package(self.package)
585 portage_util._FindUprevCandidates([]).AndReturn(package)
587 portage_util.BuildEBuildDictionary(overlays, False, [self.package])
589 self.assertEquals(len(overlays), 1)
590 self.assertEquals(overlays["/overlay"], [package])
592 def testUnwantedPackage(self):
593 overlays = {"/overlay": []}
594 package = _Package(self.package)
595 portage_util._FindUprevCandidates([]).AndReturn(package)
597 portage_util.BuildEBuildDictionary(overlays, False, [])
598 self.assertEquals(len(overlays), 1)
599 self.assertEquals(overlays["/overlay"], [])
603 class ProjectMappingTest(cros_test_lib.TestCase):
604 """Tests related to Proejct Mapping."""
606 def testSplitEbuildPath(self):
607 """Test if we can split an ebuild path into its components."""
608 ebuild_path = 'chromeos-base/platform2/platform2-9999.ebuild'
609 components = ['chromeos-base', 'platform2', 'platform2-9999']
610 for path in (ebuild_path, './' + ebuild_path, 'foo.bar/' + ebuild_path):
611 self.assertEquals(components, portage_util.SplitEbuildPath(path))
613 def testSplitPV(self):
614 """Test splitting PVs into package and version components."""
615 pv = 'bar-1.2.3_rc1-r5'
616 package, version_no_rev, rev = tuple(pv.split('-'))
617 split_pv = portage_util.SplitPV(pv)
618 self.assertEquals(split_pv.pv, pv)
619 self.assertEquals(split_pv.package, package)
620 self.assertEquals(split_pv.version_no_rev, version_no_rev)
621 self.assertEquals(split_pv.rev, rev)
622 self.assertEquals(split_pv.version, '%s-%s' % (version_no_rev, rev))
624 def testSplitCPV(self):
625 """Test splitting CPV into components."""
626 cpv = 'foo/bar-4.5.6_alpha-r6'
627 cat, pv = cpv.split('/', 1)
628 split_pv = portage_util.SplitPV(pv)
629 split_cpv = portage_util.SplitCPV(cpv)
630 self.assertEquals(split_cpv.category, cat)
631 for k, v in split_pv._asdict().iteritems():
632 self.assertEquals(getattr(split_cpv, k), v)
634 def testFindWorkonProjects(self):
635 """Test if we can find the list of workon projects."""
636 ply_image = 'media-gfx/ply-image'
637 ply_image_project = 'chromiumos/third_party/ply-image'
638 kernel = 'sys-kernel/chromeos-kernel'
639 kernel_project = 'chromiumos/third_party/kernel'
641 ([ply_image], set([ply_image_project])),
642 ([kernel], set([kernel_project])),
643 ([ply_image, kernel], set([ply_image_project, kernel_project]))
645 if portage_util.FindOverlays(constants.BOTH_OVERLAYS):
646 for packages, projects in matches:
647 self.assertEquals(projects,
648 portage_util.FindWorkonProjects(packages))
651 class PackageDBTest(cros_test_lib.MoxTempDirTestCase):
652 """Package Database related tests."""
654 fake_pkgdb = { 'category1' : [ 'package-1', 'package-2' ],
655 'category2' : [ 'package-3', 'package-4' ],
656 'category3' : [ 'invalid', 'semi-invalid' ],
663 self.build_root = self.tempdir
664 self.fake_packages = []
665 # Prepare a fake chroot.
666 self.fake_chroot = os.path.join(self.build_root, 'chroot/build/amd64-host')
667 fake_pkgdb_path = os.path.join(self.fake_chroot, 'var/db/pkg')
668 os.makedirs(fake_pkgdb_path)
669 for cat, pkgs in self.fake_pkgdb.iteritems():
670 catpath = os.path.join(fake_pkgdb_path, cat)
672 # Invalid category is a file. Should not be delved into.
673 osutils.Touch(catpath)
677 pkgpath = os.path.join(catpath, pkg)
679 # Invalid package is a file instead of a directory/
680 osutils.Touch(pkgpath)
683 if pkg.endswith('-invalid'):
684 # Invalid package does not meet existence of "%s/%s.ebuild" file.
685 osutils.Touch(os.path.join(pkgpath, 'whatever'))
688 osutils.Touch(os.path.join(pkgpath, pkg + '.ebuild'))
689 pv = portage_util.SplitPV(pkg)
690 key = '%s/%s' % (cat, pv.package)
691 self.fake_packages.append((key, pv.version))
693 def testListInstalledPackages(self):
694 """Test if listing packages installed into a root works."""
695 packages = portage_util.ListInstalledPackages(self.fake_chroot)
696 # Sort the lists, because the filesystem might reorder the entries for us.
698 self.fake_packages.sort()
699 self.assertEquals(self.fake_packages, packages)
701 def testIsPackageInstalled(self):
702 """Test if checking the existence of an installed package works."""
703 self.assertTrue(portage_util.IsPackageInstalled(
705 sysroot=self.fake_chroot))
706 self.assertFalse(portage_util.IsPackageInstalled(
708 sysroot=self.fake_chroot))
711 if __name__ == '__main__':