3 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 """Unit tests for portage_utilities.py."""
15 if __name__ == '__main__':
16 sys.path.insert(0, constants.SOURCE_ROOT)
18 from chromite.lib import cros_build_lib
19 from chromite.lib import cros_test_lib
20 from chromite.lib import git
21 from chromite.lib import osutils
22 from chromite.buildbot import portage_utilities
24 # pylint: disable=W0212
25 MANIFEST = git.ManifestCheckout.Cached(constants.SOURCE_ROOT)
27 class _Package(object):
28 """Package helper class."""
29 def __init__(self, package):
30 self.package = package
33 class _DummyCommandResult(object):
34 """Create mock RunCommand results."""
35 def __init__(self, output):
36 # Members other than 'output' are expected to be unused, so
39 # All shell output will be newline terminated; we add the
40 # newline here for convenience.
41 self.output = output + '\n'
44 class EBuildTest(cros_test_lib.MoxTestCase):
45 """Ebuild related tests."""
47 def _makeFakeEbuild(self, fake_ebuild_path, fake_ebuild_content=''):
48 self.mox.StubOutWithMock(fileinput, 'input')
49 fileinput.input(fake_ebuild_path).AndReturn(fake_ebuild_content)
51 fake_ebuild = portage_utilities.EBuild(fake_ebuild_path)
55 def testParseEBuildPath(self):
56 # Test with ebuild with revision number.
57 fake_ebuild_path = '/path/to/test_package/test_package-0.0.1-r1.ebuild'
58 fake_ebuild = self._makeFakeEbuild(fake_ebuild_path)
60 self.assertEquals(fake_ebuild._category, 'to')
61 self.assertEquals(fake_ebuild._pkgname, 'test_package')
62 self.assertEquals(fake_ebuild.version_no_rev, '0.0.1')
63 self.assertEquals(fake_ebuild.current_revision, 1)
64 self.assertEquals(fake_ebuild.version, '0.0.1-r1')
65 self.assertEquals(fake_ebuild.package, 'to/test_package')
66 self.assertEquals(fake_ebuild._ebuild_path_no_version,
67 '/path/to/test_package/test_package')
68 self.assertEquals(fake_ebuild.ebuild_path_no_revision,
69 '/path/to/test_package/test_package-0.0.1')
70 self.assertEquals(fake_ebuild._unstable_ebuild_path,
71 '/path/to/test_package/test_package-9999.ebuild')
72 self.assertEquals(fake_ebuild.ebuild_path, fake_ebuild_path)
74 def testParseEBuildPathNoRevisionNumber(self):
75 # Test with ebuild without revision number.
76 fake_ebuild_path = '/path/to/test_package/test_package-9999.ebuild'
77 fake_ebuild = self._makeFakeEbuild(fake_ebuild_path)
79 self.assertEquals(fake_ebuild._category, 'to')
80 self.assertEquals(fake_ebuild._pkgname, 'test_package')
81 self.assertEquals(fake_ebuild.version_no_rev, '9999')
82 self.assertEquals(fake_ebuild.current_revision, 0)
83 self.assertEquals(fake_ebuild.version, '9999')
84 self.assertEquals(fake_ebuild.package, 'to/test_package')
85 self.assertEquals(fake_ebuild._ebuild_path_no_version,
86 '/path/to/test_package/test_package')
87 self.assertEquals(fake_ebuild.ebuild_path_no_revision,
88 '/path/to/test_package/test_package-9999')
89 self.assertEquals(fake_ebuild._unstable_ebuild_path,
90 '/path/to/test_package/test_package-9999.ebuild')
91 self.assertEquals(fake_ebuild.ebuild_path, fake_ebuild_path)
93 def testGetCommitId(self):
94 fake_sources = '/path/to/sources'
95 fake_hash = '24ab3c9f6d6b5c744382dba2ca8fb444b9808e9f'
96 fake_ebuild_path = '/path/to/test_package/test_package-9999.ebuild'
97 fake_ebuild = self._makeFakeEbuild(fake_ebuild_path)
100 self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
101 result = _DummyCommandResult(fake_hash)
102 cros_build_lib.RunCommand(
105 print_cmd=portage_utilities.EBuild.VERBOSE,
106 capture_output=True).AndReturn(result)
109 test_hash = fake_ebuild.GetCommitId(fake_sources)
111 self.assertEquals(test_hash, fake_hash)
113 def testEBuildStable(self):
114 """Test ebuild w/keyword variations"""
115 fake_ebuild_path = '/path/to/test_package/test_package-9999.ebuild'
120 ('~amd64 ~arm ~x86', False),
121 ('~amd64 arm ~x86', True),
125 for keywords, stable in datasets:
126 fake_ebuild = self._makeFakeEbuild(
127 fake_ebuild_path, fake_ebuild_content=['KEYWORDS="%s"\n' % keywords])
128 self.assertEquals(fake_ebuild.is_stable, stable)
129 self.mox.UnsetStubs()
131 def testEBuildBlacklisted(self):
132 """Test blacklisted ebuild"""
133 fake_ebuild_path = '/path/to/test_package/test_package-9999.ebuild'
135 fake_ebuild = self._makeFakeEbuild(fake_ebuild_path)
136 self.assertEquals(fake_ebuild.is_blacklisted, False)
137 self.mox.UnsetStubs()
139 fake_ebuild = self._makeFakeEbuild(
140 fake_ebuild_path, fake_ebuild_content=['CROS_WORKON_BLACKLIST="1"\n'])
141 self.assertEquals(fake_ebuild.is_blacklisted, True)
144 class ProjectAndPathTest(cros_test_lib.MoxTempDirTestCase):
145 """Project and Path related tests."""
147 def _MockParseWorkonVariables(self, fake_projects, _fake_localname,
148 _fake_subdir, fake_ebuild_contents):
149 """Mock the necessary calls, start Replay mode, call GetSourcePath()."""
150 # pylint: disable=E1120
151 self.mox.StubOutWithMock(os.path, 'isdir')
152 self.mox.StubOutWithMock(MANIFEST, 'FindCheckoutFromPath')
154 # We need 'chromeos-base' here because it controls default _SUBDIR values.
155 ebuild_path = os.path.join(self.tempdir, 'chromeos-base', 'package',
156 'package-9999.ebuild')
157 osutils.WriteFile(ebuild_path, fake_ebuild_contents, makedirs=True)
158 for p in fake_projects:
159 os.path.isdir(mox.IgnoreArg()).AndReturn(False)
160 for p in fake_projects:
161 os.path.isdir(mox.IgnoreArg()).AndReturn(True)
162 MANIFEST.FindCheckoutFromPath(mox.IgnoreArg()).AndReturn({ 'name': p })
165 ebuild = portage_utilities.EBuild(ebuild_path)
166 result = ebuild.GetSourcePath(self.tempdir, MANIFEST)
170 def testParseLegacyWorkonVariables(self):
171 """Tests if ebuilds in a single item format are correctly parsed."""
172 fake_project = 'my_project1'
173 fake_localname = 'foo'
175 fake_ebuild_contents = """
176 CROS_WORKON_PROJECT=%s
177 CROS_WORKON_LOCALNAME=%s
178 CROS_WORKON_SUBDIR=%s
179 """ % (fake_project, fake_localname, fake_subdir)
180 project, subdir = self._MockParseWorkonVariables(
181 [fake_project], [fake_localname], [fake_subdir], fake_ebuild_contents)
182 self.assertEquals(project, [fake_project])
183 self.assertEquals(subdir, [os.path.join(
184 self.tempdir, 'platform', '%s/%s' % (fake_localname, fake_subdir))])
186 def testParseArrayWorkonVariables(self):
187 """Tests if ebuilds in an array format are correctly parsed."""
188 fake_projects = ['my_project1', 'my_project2', 'my_project3']
189 fake_localname = ['foo', 'bar', 'bas']
190 fake_subdir = ['sub1', 'sub2', 'sub3']
191 # The test content is formatted using the same function that
192 # formats ebuild output, ensuring that we can parse our own
194 fake_ebuild_contents = """
195 CROS_WORKON_PROJECT=%s
196 CROS_WORKON_LOCALNAME=%s
197 CROS_WORKON_SUBDIR=%s
198 """ % (portage_utilities.EBuild.FormatBashArray(fake_projects),
199 portage_utilities.EBuild.FormatBashArray(fake_localname),
200 portage_utilities.EBuild.FormatBashArray(fake_subdir))
201 project, subdir = self._MockParseWorkonVariables(
202 fake_projects, fake_localname, fake_subdir, fake_ebuild_contents)
203 self.assertEquals(project, fake_projects)
204 fake_path = ['%s/%s' % (fake_localname[i], fake_subdir[i])
205 for i in range(0, len(fake_projects))]
206 fake_path = map(lambda x: os.path.realpath(
207 os.path.join(self.tempdir, 'platform', x)), fake_path)
208 self.assertEquals(subdir, fake_path)
211 class StubEBuild(portage_utilities.EBuild):
212 """Test helper to StubEBuild."""
213 def __init__(self, path):
214 super(StubEBuild, self).__init__(path)
215 self.is_workon = True
216 self.is_stable = True
218 def _ReadEBuild(self, path):
221 def GetCommitId(self, srcpath):
224 'p1_path1' : 'my_id1',
225 'p1_path2' : 'my_id2'
227 if srcpath in id_map:
228 return id_map[srcpath]
233 class EBuildRevWorkonTest(cros_test_lib.MoxTempDirTestCase):
234 """Tests for EBuildRevWorkon."""
235 # Lines that we will feed as fake ebuild contents to
236 # EBuild.MarAsStable(). This is the minimum content needed
237 # to test the various branches in the function's main processing
239 _mock_ebuild = ['EAPI=2\n',
240 'CROS_WORKON_COMMIT=old_id\n',
241 'KEYWORDS=\"~x86 ~arm ~amd64\"\n',
243 _mock_ebuild_multi = ['EAPI=2\n',
244 'CROS_WORKON_COMMIT=("old_id1","old_id2")\n',
245 'KEYWORDS=\"~x86 ~arm ~amd64\"\n',
249 self.overlay = '/sources/overlay'
250 package_name = os.path.join(self.overlay,
251 'category/test_package/test_package-0.0.1')
252 ebuild_path = package_name + '-r1.ebuild'
253 self.m_ebuild = StubEBuild(ebuild_path)
254 self.revved_ebuild_path = package_name + '-r2.ebuild'
256 def createRevWorkOnMocks(self, ebuild_content, rev, multi=False):
257 # pylint: disable=E1120
258 self.mox.StubOutWithMock(os.path, 'exists')
259 self.mox.StubOutWithMock(cros_build_lib, 'Die')
260 self.mox.StubOutWithMock(portage_utilities.shutil, 'copyfile')
261 self.mox.StubOutWithMock(os, 'unlink')
262 self.mox.StubOutWithMock(portage_utilities.EBuild, '_RunGit')
263 self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
264 self.mox.StubOutWithMock(portage_utilities.filecmp, 'cmp')
265 self.mox.StubOutWithMock(portage_utilities.fileinput, 'input')
266 self.mox.StubOutWithMock(portage_utilities.EBuild, 'GetVersion')
267 self.mox.StubOutWithMock(portage_utilities.EBuild, 'GetSourcePath')
268 self.mox.StubOutWithMock(portage_utilities.EBuild, 'GetTreeId')
271 portage_utilities.EBuild.GetSourcePath('/sources', MANIFEST).AndReturn(
272 (['fake_project1','fake_project2'], ['p1_path1','p1_path2']))
274 portage_utilities.EBuild.GetSourcePath('/sources', MANIFEST).AndReturn(
275 (['fake_project1'], ['p1_path']))
276 portage_utilities.EBuild.GetVersion('/sources', MANIFEST,
277 '0.0.1').AndReturn('0.0.1')
279 portage_utilities.EBuild.GetTreeId('p1_path1').AndReturn('treehash1')
280 portage_utilities.EBuild.GetTreeId('p1_path2').AndReturn('treehash2')
282 portage_utilities.EBuild.GetTreeId('p1_path').AndReturn('treehash')
284 ebuild_9999 = self.m_ebuild._unstable_ebuild_path
285 os.path.exists(ebuild_9999).AndReturn(True)
287 # These calls come from MarkAsStable()
288 portage_utilities.shutil.copyfile(ebuild_9999, self.revved_ebuild_path)
290 m_file = self.mox.CreateMock(file)
291 portage_utilities.fileinput.input(self.revved_ebuild_path,
292 inplace=1).AndReturn(ebuild_content)
293 m_file.write('EAPI=2\n')
296 m_file.write('CROS_WORKON_COMMIT=("my_id1" "my_id2")\n')
297 m_file.write('CROS_WORKON_TREE=("treehash1" "treehash2")\n')
299 m_file.write('CROS_WORKON_COMMIT="my_id"\n')
300 m_file.write('CROS_WORKON_TREE="treehash"\n')
302 m_file.write('KEYWORDS=\"x86 arm amd64\"\n')
303 m_file.write('src_unpack(){}\n')
304 # MarkAsStable() returns here
306 portage_utilities.filecmp.cmp(self.m_ebuild.ebuild_path,
307 self.revved_ebuild_path,
308 shallow=False).AndReturn(not rev)
310 cmd = ['add', self.revved_ebuild_path]
311 portage_utilities.EBuild._RunGit(self.overlay, cmd)
312 if self.m_ebuild.is_stable:
313 cmd = ['rm', self.m_ebuild.ebuild_path]
314 portage_utilities.EBuild._RunGit(self.overlay, cmd)
316 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_utilities.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_utilities, '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_utilities.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_utilities.EBuild.GitRepoHasChanges(self.tempdir))
410 # Update metadata but no real changes.
411 osutils.Touch(os.path.join(self.tempdir, 'LICENSE'))
412 self.assertFalse(portage_utilities.EBuild.GitRepoHasChanges(self.tempdir))
414 osutils.WriteFile(os.path.join(self.tempdir, 'LICENSE'), 'hi')
415 self.assertTrue(portage_utilities.EBuild.GitRepoHasChanges(self.tempdir))
418 class FindOverlaysTest(cros_test_lib.MoxTestCase):
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_utilities.FindOverlays(o, b, constants.SOURCE_ROOT)
433 self.no_overlays = not bool(any(d.values()))
435 def testMissingPrimaryOverlay(self):
436 """Test what happens when a primary overlay is missing.
438 If the overlay doesn't exist, FindOverlays should throw a
439 MissingOverlayException.
441 self.assertRaises(portage_utilities.MissingOverlayException,
442 portage_utilities.FindPrimaryOverlay, self.BOTH,
443 self.FAKE, constants.SOURCE_ROOT)
445 def testDuplicates(self):
446 """Verify that no duplicate overlays are returned."""
447 for d in self.overlays.itervalues():
448 for overlays in d.itervalues():
449 self.assertEqual(len(overlays), len(set(overlays)))
451 def testOverlaysExist(self):
452 """Verify that all overlays returned actually exist on disk."""
453 for d in self.overlays.itervalues():
454 for overlays in d.itervalues():
455 self.assertTrue(all(os.path.isdir(x) for x in overlays))
457 def testPrivatePublicOverlayTypes(self):
458 """Verify public/private filtering.
460 If we ask for results from 'both overlays', we should
461 find all public and all private overlays.
463 There should always be at least one public overlay. (Note:
464 there may not be any private overlays, e.g. if the user has
470 for d in self.overlays.itervalues():
471 self.assertTrue(set(d[self.BOTH]) >= set(d[self.PUBLIC]))
472 self.assertTrue(set(d[self.BOTH]) > set(d[self.PRIVATE]))
473 self.assertTrue(set(d[self.PUBLIC]).isdisjoint(d[self.PRIVATE]))
475 def testNoOverlayType(self):
476 """If we specify overlay_type=None, no results should be returned."""
477 self.assertTrue(all(d[None] == [] for d in self.overlays.itervalues()))
479 def testNonExistentBoard(self):
480 """Test what happens when a non-existent board is supplied.
482 If we specify a non-existent board to FindOverlays, only generic
483 overlays should be returned.
488 for o in (self.PUBLIC, self.BOTH):
489 self.assertTrue(set(self.overlays[self.FAKE][o]) <
490 set(self.overlays[self.MARIO][o]))
492 def testAllBoards(self):
493 """If we specify board=None, all overlays should be returned."""
497 for o in (self.PUBLIC, self.BOTH):
498 for b in (self.FAKE, self.MARIO):
499 self.assertTrue(set(self.overlays[b][o]) < set(self.overlays[None][o]))
501 def testMarioPrimaryOverlay(self):
502 """Verify that mario has a primary overlay.
504 Further, the only difference between the public overlays for mario and a
505 fake board is the primary overlay, which is listed last.
510 mario_primary = portage_utilities.FindPrimaryOverlay(self.BOTH, self.MARIO,
511 constants.SOURCE_ROOT)
512 self.assertTrue(mario_primary in self.overlays[self.MARIO][self.BOTH])
513 self.assertTrue(mario_primary not in self.overlays[self.FAKE][self.BOTH])
514 self.assertEqual(mario_primary, self.overlays[self.MARIO][self.PUBLIC][-1])
515 self.assertEqual(self.overlays[self.MARIO][self.PUBLIC][:-1],
516 self.overlays[self.FAKE][self.PUBLIC])
518 def testReadOverlayFile(self):
519 """Verify that the boards are examined in the right order"""
520 overlays = self.overlays[self.MARIO][self.PUBLIC]
521 self.mox.StubOutWithMock(osutils, 'ReadFile')
522 for overlay in overlays:
523 osutils.ReadFile(os.path.join(overlay, 'test')).AndRaise(
524 IOError(os.errno.ENOENT, 'ENOENT'))
526 portage_utilities.ReadOverlayFile('test', self.PUBLIC, self.MARIO,
527 constants.SOURCE_ROOT)
531 class BuildEBuildDictionaryTest(cros_test_lib.MoxTestCase):
532 """Tests of the EBuild Dictionary."""
535 self.mox.StubOutWithMock(os, 'walk')
536 self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
537 self.package = 'chromeos-base/test_package'
538 self.root = '/overlay/chromeos-base/test_package'
539 self.package_path = self.root + '/test_package-0.0.1.ebuild'
540 paths = [[self.root, [], []]]
541 os.walk("/overlay").AndReturn(paths)
542 self.mox.StubOutWithMock(portage_utilities, '_FindUprevCandidates')
545 def testWantedPackage(self):
546 overlays = {"/overlay": []}
547 package = _Package(self.package)
548 portage_utilities._FindUprevCandidates([]).AndReturn(package)
550 portage_utilities.BuildEBuildDictionary(overlays, False, [self.package])
552 self.assertEquals(len(overlays), 1)
553 self.assertEquals(overlays["/overlay"], [package])
555 def testUnwantedPackage(self):
556 overlays = {"/overlay": []}
557 package = _Package(self.package)
558 portage_utilities._FindUprevCandidates([]).AndReturn(package)
560 portage_utilities.BuildEBuildDictionary(overlays, False, [])
561 self.assertEquals(len(overlays), 1)
562 self.assertEquals(overlays["/overlay"], [])
566 class ProjectMappingTest(cros_test_lib.TestCase):
567 """Tests related to Proejct Mapping."""
569 def testSplitEbuildPath(self):
570 """Test if we can split an ebuild path into its components."""
571 ebuild_path = 'chromeos-base/platform2/platform2-9999.ebuild'
572 components = ['chromeos-base', 'platform2', 'platform2-9999']
573 for path in (ebuild_path, './' + ebuild_path, 'foo.bar/' + ebuild_path):
574 self.assertEquals(components, portage_utilities.SplitEbuildPath(path))
576 def testSplitPV(self):
577 """Test splitting PVs into package and version components."""
578 pv = 'bar-1.2.3_rc1-r5'
579 package, version_no_rev, rev = tuple(pv.split('-'))
580 split_pv = portage_utilities.SplitPV(pv)
581 self.assertEquals(split_pv.pv, pv)
582 self.assertEquals(split_pv.package, package)
583 self.assertEquals(split_pv.version_no_rev, version_no_rev)
584 self.assertEquals(split_pv.rev, rev)
585 self.assertEquals(split_pv.version, '%s-%s' % (version_no_rev, rev))
587 def testSplitCPV(self):
588 """Test splitting CPV into components."""
589 cpv = 'foo/bar-4.5.6_alpha-r6'
590 cat, pv = cpv.split('/', 1)
591 split_pv = portage_utilities.SplitPV(pv)
592 split_cpv = portage_utilities.SplitCPV(cpv)
593 self.assertEquals(split_cpv.category, cat)
594 for k, v in split_pv._asdict().iteritems():
595 self.assertEquals(getattr(split_cpv, k), v)
597 def testFindWorkonProjects(self):
598 """Test if we can find the list of workon projects."""
599 ply_image = 'media-gfx/ply-image'
600 ply_image_project = 'chromiumos/third_party/ply-image'
601 kernel = 'sys-kernel/chromeos-kernel'
602 kernel_project = 'chromiumos/third_party/kernel'
604 ([ply_image], set([ply_image_project])),
605 ([kernel], set([kernel_project])),
606 ([ply_image, kernel], set([ply_image_project, kernel_project]))
608 if portage_utilities.FindOverlays(constants.BOTH_OVERLAYS):
609 for packages, projects in matches:
610 self.assertEquals(projects,
611 portage_utilities.FindWorkonProjects(packages))
613 class PackageDBTest(cros_test_lib.MoxTempDirTestCase):
614 """Package Database related tests."""
616 fake_pkgdb = { 'category1' : [ 'package-1', 'package-2' ],
617 'category2' : [ 'package-3', 'package-4' ],
618 'category3' : [ 'invalid', 'semi-invalid' ],
625 self.build_root = self.tempdir
626 self.fake_packages = []
627 # Prepare a fake chroot.
628 self.fake_chroot = os.path.join(self.build_root, 'chroot/build/amd64-host')
629 fake_pkgdb_path = os.path.join(self.fake_chroot, 'var/db/pkg')
630 os.makedirs(fake_pkgdb_path)
631 for cat, pkgs in self.fake_pkgdb.iteritems():
632 catpath = os.path.join(fake_pkgdb_path, cat)
634 # Invalid category is a file. Should not be delved into.
635 osutils.Touch(catpath)
639 pkgpath = os.path.join(catpath, pkg)
641 # Invalid package is a file instead of a directory/
642 osutils.Touch(pkgpath)
645 if pkg.endswith('-invalid'):
646 # Invalid package does not meet existence of "%s/%s.ebuild" file.
647 osutils.Touch(os.path.join(pkgpath, 'whatever'))
650 osutils.Touch(os.path.join(pkgpath, pkg + '.ebuild'))
651 pv = portage_utilities.SplitPV(pkg)
652 key = '%s/%s' % (cat, pv.package)
653 self.fake_packages.append((key, pv.version))
655 def testListInstalledPackages(self):
656 """Test if listing packages installed into a root works."""
657 packages = portage_utilities.ListInstalledPackages(self.fake_chroot)
658 # Sort the lists, because the filesystem might reorder the entries for us.
660 self.fake_packages.sort()
661 self.assertEquals(self.fake_packages, packages)
663 def testIsPackageInstalled(self):
664 """Test if checking the existence of an installed package works."""
665 self.assertTrue(portage_utilities.IsPackageInstalled(
667 sysroot=self.fake_chroot))
668 self.assertFalse(portage_utilities.IsPackageInstalled(
670 sysroot=self.fake_chroot))
673 if __name__ == '__main__':