# Copyright 2015 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Test the path_util module.""" from __future__ import print_function import itertools import mock import os import tempfile from chromite.cbuildbot import constants from chromite.lib import cros_build_lib_unittest from chromite.lib import cros_test_lib from chromite.lib import git from chromite.lib import partial_mock from chromite.lib import path_util FAKE_SOURCE_PATH = '/path/to/source/tree' FAKE_REPO_PATH = '/path/to/repo' CUSTOM_SOURCE_PATH = '/custom/source/path' class DetermineCheckoutTest(cros_test_lib.MockTempDirTestCase): """Verify functionality for figuring out what checkout we're in.""" def setUp(self): self.rc_mock = cros_build_lib_unittest.RunCommandMock() self.StartPatcher(self.rc_mock) self.rc_mock.SetDefaultCmdResult() def RunTest(self, dir_struct, cwd, expected_root, expected_type, expected_src): """Run a test with specific parameters and expected results.""" cros_test_lib.CreateOnDiskHierarchy(self.tempdir, dir_struct) cwd = os.path.join(self.tempdir, cwd) checkout_info = path_util.DetermineCheckout(cwd) full_root = expected_root if expected_root is not None: full_root = os.path.join(self.tempdir, expected_root) full_src = expected_src if expected_src is not None: full_src = os.path.join(self.tempdir, expected_src) self.assertEquals(checkout_info.root, full_root) self.assertEquals(checkout_info.type, expected_type) self.assertEquals(checkout_info.chrome_src_dir, full_src) def testGclientRepo(self): """Recognizes a GClient repo checkout.""" dir_struct = [ 'a/.gclient', 'a/b/.repo/', 'a/b/c/.gclient', 'a/b/c/d/somefile', ] self.RunTest(dir_struct, 'a/b/c', 'a/b/c', path_util.CHECKOUT_TYPE_GCLIENT, 'a/b/c/src') self.RunTest(dir_struct, 'a/b/c/d', 'a/b/c', path_util.CHECKOUT_TYPE_GCLIENT, 'a/b/c/src') self.RunTest(dir_struct, 'a/b', 'a/b', path_util.CHECKOUT_TYPE_REPO, None) self.RunTest(dir_struct, 'a', 'a', path_util.CHECKOUT_TYPE_GCLIENT, 'a/src') def testGitUnderGclient(self): """Recognizes a chrome git checkout by gclient.""" self.rc_mock.AddCmdResult( partial_mock.In('config'), output=constants.CHROMIUM_GOB_URL) dir_struct = [ 'a/.gclient', 'a/src/.git/', ] self.RunTest(dir_struct, 'a/src', 'a', path_util.CHECKOUT_TYPE_GCLIENT, 'a/src') def testGitUnderRepo(self): """Recognizes a chrome git checkout by repo.""" self.rc_mock.AddCmdResult( partial_mock.In('config'), output=constants.CHROMIUM_GOB_URL) dir_struct = [ 'a/.repo/', 'a/b/.git/', ] self.RunTest(dir_struct, 'a/b', 'a', path_util.CHECKOUT_TYPE_REPO, None) def testBadGit1(self): """.git is not a directory.""" self.RunTest(['a/.git'], 'a', None, path_util.CHECKOUT_TYPE_UNKNOWN, None) def testBadGit2(self): """'git config' returns nothing.""" self.RunTest(['a/.repo/', 'a/b/.git/'], 'a/b', 'a', path_util.CHECKOUT_TYPE_REPO, None) def testBadGit3(self): """'git config' returns error.""" self.rc_mock.AddCmdResult(partial_mock.In('config'), returncode=5) self.RunTest(['a/.git/'], 'a', None, path_util.CHECKOUT_TYPE_UNKNOWN, None) class FindCacheDirTest(cros_test_lib.MockTempDirTestCase): """Test cache dir specification and finding functionality.""" def setUp(self): dir_struct = [ 'repo/.repo/', 'repo/manifest/', 'gclient/.gclient', ] cros_test_lib.CreateOnDiskHierarchy(self.tempdir, dir_struct) self.repo_root = os.path.join(self.tempdir, 'repo') self.gclient_root = os.path.join(self.tempdir, 'gclient') self.nocheckout_root = os.path.join(self.tempdir, 'nothing') self.rc_mock = self.StartPatcher(cros_build_lib_unittest.RunCommandMock()) self.cwd_mock = self.PatchObject(os, 'getcwd') def testRepoRoot(self): """Test when we are inside a repo checkout.""" self.cwd_mock.return_value = self.repo_root self.assertEquals( path_util.FindCacheDir(), os.path.join(self.repo_root, path_util.GENERAL_CACHE_DIR)) def testGclientRoot(self): """Test when we are inside a gclient checkout.""" self.cwd_mock.return_value = self.gclient_root self.assertEquals( path_util.FindCacheDir(), os.path.join(self.gclient_root, path_util.CHROME_CACHE_DIR)) def testTempdir(self): """Test when we are not in any checkout.""" self.cwd_mock.return_value = self.nocheckout_root self.assertStartsWith( path_util.FindCacheDir(), os.path.join(tempfile.gettempdir(), '')) class TestPathResolver(cros_test_lib.MockTestCase): """Tests of ChrootPathResolver class.""" def setUp(self): self.PatchObject(constants, 'SOURCE_ROOT', new=FAKE_SOURCE_PATH) self.PatchObject(path_util, 'GetCacheDir', return_value='/path/to/cache') self.PatchObject(git, 'FindRepoDir', return_value=os.path.join(FAKE_REPO_PATH, '.fake_repo')) self.chroot_path = None def FakeCwd(self, base_path): return os.path.join(base_path, 'somewhere/in/there') def SetChrootPath(self, source_path): """Set and fake the chroot path.""" self.chroot_path = os.path.join(source_path, constants.DEFAULT_CHROOT_DIR) @mock.patch('chromite.lib.cros_build_lib.IsInsideChroot', return_value=True) def testInsideChroot(self, _): """Tests {To,From}Chroot() call from inside the chroot.""" self.SetChrootPath(constants.SOURCE_ROOT) resolver = path_util.ChrootPathResolver() self.assertEqual(os.path.realpath('some/path'), resolver.ToChroot('some/path')) self.assertEqual(os.path.realpath('/some/path'), resolver.ToChroot('/some/path')) self.assertEqual(os.path.realpath('some/path'), resolver.FromChroot('some/path')) self.assertEqual(os.path.realpath('/some/path'), resolver.FromChroot('/some/path')) @mock.patch('chromite.lib.cros_build_lib.IsInsideChroot', return_value=False) def testOutsideChrootInbound(self, _): """Tests ToChroot() calls from outside the chroot.""" for source_path, source_from_path_repo in itertools.product( (None, CUSTOM_SOURCE_PATH), (False, True)): if source_from_path_repo: actual_source_path = FAKE_REPO_PATH else: actual_source_path = source_path or constants.SOURCE_ROOT fake_cwd = self.FakeCwd(actual_source_path) self.PatchObject(os, 'getcwd', return_value=fake_cwd) self.SetChrootPath(actual_source_path) resolver = path_util.ChrootPathResolver( source_path=source_path, source_from_path_repo=source_from_path_repo) source_rel_cwd = os.path.relpath(fake_cwd, actual_source_path) # Case: path inside the chroot space. self.assertEqual( '/some/path', resolver.ToChroot(os.path.join(self.chroot_path, 'some/path'))) # Case: path inside the cache directory. self.assertEqual( os.path.join(constants.CHROOT_CACHE_ROOT, 'some/path'), resolver.ToChroot(os.path.join(path_util.GetCacheDir(), 'some/path'))) # Case: absolute path inside the source tree. if source_from_path_repo: self.assertEqual( os.path.join(constants.CHROOT_SOURCE_ROOT, 'some/path'), resolver.ToChroot(os.path.join(FAKE_REPO_PATH, 'some/path'))) else: self.assertEqual( os.path.join(constants.CHROOT_SOURCE_ROOT, 'some/path'), resolver.ToChroot(os.path.join(actual_source_path, 'some/path'))) # Case: relative path inside the source tree. if source_from_path_repo: self.assertEqual( os.path.join(constants.CHROOT_SOURCE_ROOT, source_rel_cwd, 'some/path'), resolver.ToChroot('some/path')) else: self.assertEqual( os.path.join(constants.CHROOT_SOURCE_ROOT, source_rel_cwd, 'some/path'), resolver.ToChroot('some/path')) # Case: unreachable, path with improper source root prefix. with self.assertRaises(ValueError): resolver.ToChroot(os.path.join(actual_source_path + '-foo', 'some/path')) # Case: unreachable (random). with self.assertRaises(ValueError): resolver.ToChroot('/some/path') @mock.patch('chromite.lib.cros_build_lib.IsInsideChroot', return_value=False) def testOutsideChrootOutbound(self, _): """Tests FromChroot() calls from outside the chroot.""" self.PatchObject(os, 'getcwd', return_value=self.FakeCwd(FAKE_SOURCE_PATH)) self.SetChrootPath(constants.SOURCE_ROOT) resolver = path_util.ChrootPathResolver() # Case: source root path. self.assertEqual( os.path.join(constants.SOURCE_ROOT, 'some/path'), resolver.FromChroot(os.path.join(constants.CHROOT_SOURCE_ROOT, 'some/path'))) # Case: cyclic source/chroot sub-path elimination. self.assertEqual( os.path.join(constants.SOURCE_ROOT, 'some/path'), resolver.FromChroot(os.path.join( constants.CHROOT_SOURCE_ROOT, constants.DEFAULT_CHROOT_DIR, constants.CHROOT_SOURCE_ROOT.lstrip(os.path.sep), constants.DEFAULT_CHROOT_DIR, constants.CHROOT_SOURCE_ROOT.lstrip(os.path.sep), 'some/path'))) # Case: path inside the cache directory. self.assertEqual( os.path.join(path_util.GetCacheDir(), 'some/path'), resolver.FromChroot(os.path.join(constants.CHROOT_CACHE_ROOT, 'some/path'))) # Case: non-rooted chroot paths. self.assertEqual( os.path.join(self.chroot_path, 'some/path'), resolver.FromChroot('/some/path'))