diff options
author | Ari Hausman-Cohen <arihc@google.com> | 2016-05-09 16:00:27 -0700 |
---|---|---|
committer | Ari Hausman-Cohen <arihc@google.com> | 2016-05-09 17:20:26 -0700 |
commit | ae13a180487a8f9314e76ec827f2dfe8ce09e2bd (patch) | |
tree | a40f9871992ab78fdc0a4419b3a6ee398a06f3a2 | |
parent | 8d656f43fd2d2ff5f76edb41a21c52e70424e2fa (diff) | |
download | bdk-ae13a180487a8f9314e76ec827f2dfe8ce09e2bd.tar.gz |
Moved platform link context manager into platform.
BUG: 28527859
Change-Id: I7ecde3882f601e33243ad30e1ec5872d662efced
TEST: unit tests pass, ran modified commands
-rw-r--r-- | cli/lib/bsp/device.py | 75 | ||||
-rw-r--r-- | cli/lib/bsp/device_stub.py | 17 | ||||
-rw-r--r-- | cli/lib/bsp/device_unittest.py | 99 | ||||
-rw-r--r-- | cli/lib/bsp/operating_system.py | 3 | ||||
-rw-r--r-- | cli/lib/commands/bsp/download.py | 5 | ||||
-rw-r--r-- | cli/lib/commands/product/build.py | 16 | ||||
-rw-r--r-- | cli/lib/commands/product/provision.py | 14 | ||||
-rw-r--r-- | cli/lib/core/build_unittest.py | 5 | ||||
-rw-r--r-- | cli/lib/core/image_build_unittest.py | 9 | ||||
-rw-r--r-- | cli/lib/core/provision_unittest.py | 5 | ||||
-rw-r--r-- | cli/lib/core/tool_unittest.py | 4 | ||||
-rw-r--r-- | cli/lib/environment/toolchain_util_unittest.py | 3 | ||||
-rw-r--r-- | cli/lib/project/platform.py | 47 | ||||
-rw-r--r-- | cli/lib/project/platform_stub.py | 24 | ||||
-rw-r--r-- | cli/lib/project/platform_unittest.py | 11 |
15 files changed, 147 insertions, 190 deletions
diff --git a/cli/lib/bsp/device.py b/cli/lib/bsp/device.py index 6378051..8570659 100644 --- a/cli/lib/bsp/device.py +++ b/cli/lib/bsp/device.py @@ -57,37 +57,6 @@ class PackageUnlinkError(Error): description = 'Failed to unlink BSP from OS tree' -class _LinkContext(object): - """A context manager to allow temporary linking of a device to an OS. - - Attributes: - device: The device to temporarily link. - os_version: The os version to temporarily link to. - """ - - def __init__(self, device, os_version): - self.device = device - self.os_version = os_version - - def __enter__(self): - success = False - try: - self.device.link(self.os_version) - success = True - finally: - # If something goes wrong, leave unlinked. - if not success: - self.cleanup() - - def __exit__(self, type_, value_, traceback_): - # TODO(b/28028440): Even if you were linked initially, when - # exiting the context the links will be removed. - self.cleanup() - - def cleanup(self): - self.device.unlink(self.os_version) - - class Device(object): """Class to represent devices with BSPs available. @@ -166,13 +135,13 @@ class Device(object): """ return self.status()[0] == status.INSTALLED - def link(self, os_version): + def link(self, os_): """Links an OS to this device. Does not overwrite anything; ignores situations where it would need to. Args: - os_version: The OS to link to this device. + os_: The OS to link to this device. Raises: PackageLinkError: if a package problem occurs while linking. @@ -181,7 +150,7 @@ class Device(object): errors = [] for (pkg, subpackage_map) in self._package_map.iteritems(): for (subpackage_name, relpath) in subpackage_map.iteritems(): - link = util.GetOSPath(os_version, relpath) + link = os_.path(relpath) # Don't overwrite anything. if os.path.exists(link): continue @@ -196,16 +165,16 @@ class Device(object): break if errors: - raise PackageLinkError('OS version {}: {}'.format(os_version, - errors)) + raise PackageLinkError('{} to {}: {}'.format(self.name, + os_, errors)) - def unlink(self, os_version): + def unlink(self, os_): """Unlinks this device from an OS. Removes links of LINKED subpackages. Args: - os_version: The OS to unlink from. + os_: The OS to unlink from. Raises: PackageUnlinkError: if a package problem occurs while unlinking. @@ -214,7 +183,7 @@ class Device(object): errors = [] for (pkg, subpackage_map) in self._package_map.iteritems(): for (subpackage, relpath) in subpackage_map.iteritems(): - link = util.GetOSPath(os_version, relpath) + link = os_.path(relpath) try: subpackage_status, _ = pkg.subpackage_status( subpackage, link) @@ -223,22 +192,8 @@ class Device(object): except package.Error as e: errors.append('{}: {}'.format(pkg, e)) if errors: - raise PackageUnlinkError('OS version {}: {}'.format(os_version, - errors)) - - def linked(self, os_version): - """A context manager for temporary linkage. - - Note: b/28028440: It is a known bug that after exiting the context, - the device will be unlinked, whether or not it was linked going in. - - Args: - os_version: The OS version to temporarily link against. - - Returns: - A context manager within which the BSP and OS will be linked. - """ - return _LinkContext(self, os_version) + raise PackageUnlinkError('{} from {}: {}'.format(self.name, os_, + errors)) def unrecognized_paths(self, os_version): """Get the paths of unrecognized subpackages of this device. @@ -351,7 +306,7 @@ class Device(object): return confirmed - def install(self, extract_only=None, auto_accept=False, link_os_version='', + def install(self, extract_only=None, auto_accept=False, link_os=None, verbose=False): """Installs the BSP for this device. @@ -359,7 +314,7 @@ class Device(object): extract_only: (optional) a map of { package_name : tarball_file }, for packages to skip the tarball download step. auto_accept: (optional) True to accept all licenses automatically. - link_os_version: (optional) An OS version to link packages into. + link_os: (optional) An OS to link packages into. Intended only for when developing the OS/BSP, not for use with product development flow. verbose: (optional) If True, print status messages. Default False. @@ -370,7 +325,7 @@ class Device(object): Raises: LicenseError: if the user does not accept all licenses. PackageLinkError: if a package fails to link to the tree. - (Will not occur if link_os_version is None or empty) + (Will not occur if link_os is None) PackageDownloadError: if a required bsp.Package fails to download. package.NoSuchSubpackageError: if the package map is not correctly validated and specifies a non-existant subpackage. @@ -405,8 +360,8 @@ class Device(object): pkg.uninstall() # If requested, go ahead and install the links. - if link_os_version: - self.link(link_os_version) + if link_os: + self.link(link_os) def uninstall(self): """Uninstalls all BSP packages for a device. diff --git a/cli/lib/bsp/device_stub.py b/cli/lib/bsp/device_stub.py index 2a47ae9..6200782 100644 --- a/cli/lib/bsp/device_stub.py +++ b/cli/lib/bsp/device_stub.py @@ -19,7 +19,6 @@ from bsp import device -from test import stubs class Error(device.Error): @@ -30,21 +29,21 @@ class StubDevice(object): def __init__(self, name='', full_name='', vendor='', arch='', package_map=None, version='', downloaded=False, - should_link_version=None): + is_linked=False): self.name = name self.full_name = full_name self.vendor = vendor self.arch = arch self.version = version self.package_map = package_map or {} - self.should_link_version = should_link_version + self.is_linked = is_linked self.downloaded = downloaded - def linked(self, os_version): - if not self.should_link_version == os_version: - raise Error('Not supposed to link to {} (only to {})'.format( - os_version, self.should_link_version)) - return stubs.StubContextManager() - def is_available(self): return self.downloaded + + def link(self, _os): + self.is_linked = True + + def unlink(self, _os): + self.is_linked = False diff --git a/cli/lib/bsp/device_unittest.py b/cli/lib/bsp/device_unittest.py index 53ca216..a1afab3 100644 --- a/cli/lib/bsp/device_unittest.py +++ b/cli/lib/bsp/device_unittest.py @@ -20,6 +20,7 @@ import unittest from bsp import device +from bsp import operating_system_stub from bsp import package from bsp import package_stub from bsp import status @@ -29,7 +30,8 @@ from test import stubs class DeviceTest(unittest.TestCase): - _OS_VERSION = '98.76' + _OS_VERSION = '98.76.54' + _OS_PATH = '/path/to/os' def setUp(self): self.dev_json = { @@ -67,6 +69,7 @@ class DeviceTest(unittest.TestCase): 'test_device', 'Test Device', 'test_vendor', 'test_arch', {self.package1: {'subpackage_1': 'path1', 'subpackage_2': 'path2'}, self.package2: {'subpackage_2': 'path3'}}) + self.os_ = operating_system_stub.StubOperatingSystem(root=self._OS_PATH) def test_init(self): # Check all public attributes. @@ -166,14 +169,14 @@ class DeviceTest(unittest.TestCase): self.assertFalse(self.dev.is_available()) def test_link(self): - link1 = self.stub_util.GetOSPath(self._OS_VERSION, 'path1') - link2 = self.stub_util.GetOSPath(self._OS_VERSION, 'path2') - link3 = self.stub_util.GetOSPath(self._OS_VERSION, 'path3') + link1 = self.os_.path('path1') + link2 = self.os_.path('path2') + link3 = self.os_.path('path3') self.package1.should_link['subpackage_1'] = link1 self.package1.should_link['subpackage_2'] = link2 self.package2.should_link['subpackage_2'] = link3 - self.dev.link(self._OS_VERSION) + self.dev.link(self.os_) self.assertEqual(self.package1.subpackage_status( 'subpackage_1', link1)[0], status.LINKED) self.assertEqual(self.package1.subpackage_status( @@ -182,15 +185,15 @@ class DeviceTest(unittest.TestCase): 'subpackage_2', link3)[0], status.LINKED) def test_link_fail(self): - link1 = self.stub_util.GetOSPath(self._OS_VERSION, 'path1') - link2 = self.stub_util.GetOSPath(self._OS_VERSION, 'path2') - link3 = self.stub_util.GetOSPath(self._OS_VERSION, 'path3') + link1 = self.os_.path('path1') + link2 = self.os_.path('path2') + link3 = self.os_.path('path3') self.package1.should_link['subpackage_1'] = link1 # Gonna be problems with package1.subpackage_2 self.package2.should_link['subpackage_2'] = link3 with self.assertRaises(device.PackageLinkError): - self.dev.link(self._OS_VERSION) + self.dev.link(self.os_) # Should still link what it can. self.assertEqual(self.package1.subpackage_status( 'subpackage_1', link1)[0], status.LINKED) @@ -200,16 +203,16 @@ class DeviceTest(unittest.TestCase): 'subpackage_2', link3)[0], status.LINKED) def test_link_not_downloaded(self): - link1 = self.stub_util.GetOSPath(self._OS_VERSION, 'path1') - link2 = self.stub_util.GetOSPath(self._OS_VERSION, 'path2') - link3 = self.stub_util.GetOSPath(self._OS_VERSION, 'path3') + link1 = self.os_.path('path1') + link2 = self.os_.path('path2') + link3 = self.os_.path('path3') self.package1.should_link['subpackage_1'] = link1 self.package1.should_link['subpackage_2'] = link2 self.package2.should_link['subpackage_2'] = link3 self.package2.downloaded = False with self.assertRaises(device.PackageLinkError): - self.dev.link(self._OS_VERSION) + self.dev.link(self.os_) # Should still link what it can. self.assertEqual(self.package1.subpackage_status( 'subpackage_1', link1)[0], status.LINKED) @@ -219,15 +222,15 @@ class DeviceTest(unittest.TestCase): 'subpackage_2', link3)[0], status.LINKED) def test_link_overwrite(self): - link1 = self.stub_util.GetOSPath(self._OS_VERSION, 'path1') - link2 = self.stub_util.GetOSPath(self._OS_VERSION, 'path2') - link3 = self.stub_util.GetOSPath(self._OS_VERSION, 'path3') + link1 = self.os_.path('path1') + link2 = self.os_.path('path2') + link3 = self.os_.path('path3') self.package1.should_link['subpackage_1'] = link1 self.stub_os.path.should_exist = [link2] self.package2.should_link['subpackage_2'] = link3 # Shouldn't raise, but shouldn't link package1.subpackage_2. - self.dev.link(self._OS_VERSION) + self.dev.link(self.os_) self.assertEqual(self.package1.subpackage_status( 'subpackage_1', link1)[0], status.LINKED) self.assertNotEqual(self.package1.subpackage_status( @@ -236,9 +239,9 @@ class DeviceTest(unittest.TestCase): 'subpackage_2', link3)[0], status.LINKED) def test_unlink(self): - link1 = self.stub_util.GetOSPath(self._OS_VERSION, 'path1') - link2 = self.stub_util.GetOSPath(self._OS_VERSION, 'path2') - link3 = self.stub_util.GetOSPath(self._OS_VERSION, 'path3') + link1 = self.os_.path('path1') + link2 = self.os_.path('path2') + link3 = self.os_.path('path3') self.package1.subpackages['subpackage_1'] = status.LINKED self.package1.subpackages['subpackage_2'] = status.LINKED self.package2.subpackages['subpackage_2'] = status.LINKED @@ -246,7 +249,7 @@ class DeviceTest(unittest.TestCase): self.package1.should_unlink['subpackage_2'] = link2 self.package2.should_unlink['subpackage_2'] = link3 - self.dev.unlink(self._OS_VERSION) + self.dev.unlink(self.os_) self.assertEqual(self.package1.subpackage_status( 'subpackage_1', link1)[0], status.INSTALLED) self.assertEqual(self.package1.subpackage_status( @@ -255,9 +258,9 @@ class DeviceTest(unittest.TestCase): 'subpackage_2', link3)[0], status.INSTALLED) def test_partial_unlink(self): - link1 = self.stub_util.GetOSPath(self._OS_VERSION, 'path1') - link2 = self.stub_util.GetOSPath(self._OS_VERSION, 'path2') - link3 = self.stub_util.GetOSPath(self._OS_VERSION, 'path3') + link1 = self.os_.path('path1') + link2 = self.os_.path('path2') + link3 = self.os_.path('path3') self.package1.subpackages['subpackage_1'] = status.MISSING self.package1.subpackages['subpackage_2'] = status.INSTALLED self.package2.subpackages['subpackage_2'] = status.LINKED @@ -266,7 +269,7 @@ class DeviceTest(unittest.TestCase): self.package2.should_unlink['subpackage_2'] = link3 # Should only actually unlink package2.subpackage_2. - self.dev.unlink(self._OS_VERSION) + self.dev.unlink(self.os_) self.assertEqual(self.package1.subpackage_status( 'subpackage_1', link1)[0], status.MISSING) self.assertEqual(self.package1.subpackage_status( @@ -275,14 +278,14 @@ class DeviceTest(unittest.TestCase): 'subpackage_2', link3)[0], status.INSTALLED) def test_failed_unlink(self): - link1 = self.stub_util.GetOSPath(self._OS_VERSION, 'path1') - link2 = self.stub_util.GetOSPath(self._OS_VERSION, 'path2') - link3 = self.stub_util.GetOSPath(self._OS_VERSION, 'path3') + link1 = self.os_.path('path1') + link2 = self.os_.path('path2') + link3 = self.os_.path('path3') self.package2.subpackages['subpackage_2'] = status.LINKED # Should fail to unlink package2.subpackage_2. with self.assertRaises(device.PackageUnlinkError): - self.dev.unlink(self._OS_VERSION) + self.dev.unlink(self.os_) self.assertEqual(self.package1.subpackage_status( 'subpackage_1', link1)[0], status.INSTALLED) self.assertEqual(self.package1.subpackage_status( @@ -290,34 +293,6 @@ class DeviceTest(unittest.TestCase): self.assertEqual(self.package2.subpackage_status( 'subpackage_2', link3)[0], status.LINKED) - def test_linked(self): - link1 = self.stub_util.GetOSPath(self._OS_VERSION, 'path1') - link2 = self.stub_util.GetOSPath(self._OS_VERSION, 'path2') - link3 = self.stub_util.GetOSPath(self._OS_VERSION, 'path3') - self.package1.should_link['subpackage_1'] = link1 - self.package1.should_link['subpackage_2'] = link2 - self.package2.should_link['subpackage_2'] = link3 - self.package1.should_unlink['subpackage_1'] = link1 - self.package1.should_unlink['subpackage_2'] = link2 - self.package2.should_unlink['subpackage_2'] = link3 - - with self.dev.linked(self._OS_VERSION): - # In context, should be linked. - self.assertEqual(self.package1.subpackage_status( - 'subpackage_1', link1)[0], status.LINKED) - self.assertEqual(self.package1.subpackage_status( - 'subpackage_2', link2)[0], status.LINKED) - self.assertEqual(self.package2.subpackage_status( - 'subpackage_2', link3)[0], status.LINKED) - - # Out of context, no longer linked. - self.assertEqual(self.package1.subpackage_status( - 'subpackage_1', link1)[0], status.INSTALLED) - self.assertEqual(self.package1.subpackage_status( - 'subpackage_2', link2)[0], status.INSTALLED) - self.assertEqual(self.package2.subpackage_status( - 'subpackage_2', link3)[0], status.INSTALLED) - def test_unrecognized_paths(self): self.package1.subpackages['subpackage_1'] = status.NOT_INSTALLED self.package1.subpackages['subpackage_2'] = status.UNRECOGNIZED @@ -374,9 +349,9 @@ class DeviceTest(unittest.TestCase): def test_partial_install_with_link(self): self.package1.downloaded = True self.package2.downloaded = False - link1 = self.stub_util.GetOSPath(self._OS_VERSION, 'path1') - link2 = self.stub_util.GetOSPath(self._OS_VERSION, 'path2') - link3 = self.stub_util.GetOSPath(self._OS_VERSION, 'path3') + link1 = self.os_.path('path1') + link2 = self.os_.path('path2') + link3 = self.os_.path('path3') self.package1.should_link['subpackage_1'] = link1 self.package1.should_link['subpackage_2'] = link2 @@ -386,7 +361,7 @@ class DeviceTest(unittest.TestCase): self.package2.should_download = True self.assertFalse(self.dev.is_available()) - self.dev.install(auto_accept=True, link_os_version=self._OS_VERSION) + self.dev.install(auto_accept=True, link_os=self.os_) self.assertTrue(self.dev.is_available()) self.assertEqual(self.package1.subpackage_status( 'subpackage_1', self._OS_VERSION)[0], status.LINKED) @@ -446,7 +421,7 @@ class DeviceTest(unittest.TestCase): self.assertFalse(self.dev.is_available()) with self.assertRaises(device.PackageLinkError): - self.dev.install(auto_accept=True, link_os_version=self._OS_VERSION) + self.dev.install(auto_accept=True, link_os=self.os_) # Should still install, just won't be linked. self.assertTrue(self.dev.is_available()) self.assertNotEqual(self.package1.subpackage_status('subpackage_1')[0], diff --git a/cli/lib/bsp/operating_system.py b/cli/lib/bsp/operating_system.py index d672211..7c39692 100644 --- a/cli/lib/bsp/operating_system.py +++ b/cli/lib/bsp/operating_system.py @@ -69,6 +69,9 @@ class OperatingSystem(object): raise VersionError('{} (version must match regex "{}")'.format( self._version, VERSION_RE)) + def __repr__(self): + return '{}.{}'.format(self.name, self.version) + @property def name(self): return self._name diff --git a/cli/lib/commands/bsp/download.py b/cli/lib/commands/bsp/download.py index 4eeb71e..defc26d 100644 --- a/cli/lib/commands/bsp/download.py +++ b/cli/lib/commands/bsp/download.py @@ -63,8 +63,9 @@ class Update(clicommand.Command): extract_only.keys()) return 1 - os_version = util.GetOSVersion() - link_os = os_version if args.link else '' + os_ = bsp_manifest.operating_systems['brillo'] + os_version = os_.version + link_os = os_ if args.link else '' try: device_.install(extract_only, args.accept_licenses, link_os, diff --git a/cli/lib/commands/product/build.py b/cli/lib/commands/product/build.py index 9151252..c7e3e0f 100644 --- a/cli/lib/commands/product/build.py +++ b/cli/lib/commands/product/build.py @@ -19,12 +19,12 @@ import os -from bsp import manifest from cli import clicommand from commands.product import constants from core import config from core import tool from core import util +from project import platform class Build(clicommand.Command): @@ -55,18 +55,14 @@ class Build(clicommand.Command): store = config.ProductFileStore(args.product_path) - # Get the device so the BSP can be linked. - manifest_ = manifest.Manifest.from_json() - if not manifest_.is_bsp_available(store.device): - print ('BSP for "{0}" is not downloaded. ' - 'Please run `bdk bsp download {0}`.'.format(store.device)) - return 1 - device = manifest_.devices[store.device] - # Pull the buildtype from the config if it is not overridden. if args.buildtype is None: args.buildtype = store.bdk.buildtype + # Get the platform so it can be linked. + platform_ = platform.Platform(os_name='brillo', board=store.device, + build_type=args.buildtype) + no_java = 'BRILLO_NO_JAVA=0' if len(store.bdk.java) and store.bdk.java != '1': no_java = 'BRILLO_NO_JAVA=1' @@ -103,7 +99,7 @@ class Build(clicommand.Command): # TODO(arihc)(b/25952600): Some way to also prevent or at least filter # metrics for build --help - with device.linked(util.GetOSVersion()): + with platform_.linked(): make.run(full_make_args) return 0 diff --git a/cli/lib/commands/product/provision.py b/cli/lib/commands/product/provision.py index 6da7f49..19f3c81 100644 --- a/cli/lib/commands/product/provision.py +++ b/cli/lib/commands/product/provision.py @@ -19,12 +19,12 @@ import os -from bsp import manifest from cli import clicommand from commands.product import constants from core import config from core import tool from core import util +from project import platform class Provision(clicommand.Command): @@ -49,13 +49,9 @@ class Provision(clicommand.Command): store = config.ProductFileStore(args.product_path) - # Get the device so the BSP can be linked. - manifest_ = manifest.Manifest.from_json() - if not manifest_.is_bsp_available(store.device): - print ('BSP for "{0}" is not downloaded. ' - 'Please run `bdk bsp download {0}`.'.format(store.device)) - return 1 - device = manifest_.devices[store.device] + # Get the platform so it can be linked. Build type required but unused. + platform_ = platform.Platform(os_name='brillo', board=store.device, + build_type=platform.BUILD_TYPE_ENG) t = tool.BrunchTargetToolWrapper(store, args.product_path, 'provision-device') @@ -78,6 +74,6 @@ class Provision(clicommand.Command): return 1 if args.s is not None: args.args += ['-s', args.s] - with device.linked(util.GetOSVersion()): + with platform_.linked(): t.run(args.args) return 0 diff --git a/cli/lib/core/build_unittest.py b/cli/lib/core/build_unittest.py index b18bab0..d50f958 100644 --- a/cli/lib/core/build_unittest.py +++ b/cli/lib/core/build_unittest.py @@ -20,7 +20,6 @@ import os import unittest -from bsp import device_stub from core import build from core import util_stub from project import platform_stub @@ -47,12 +46,10 @@ class BuildPlatformTest(unittest.TestCase): build.util = self.stub_util build.subprocess = self.stub_subprocess - self.device = device_stub.StubDevice( - should_link_version=self._OS_VERSION) self.platform = platform_stub.StubPlatform( board=self._BSP, build_type=self._BUILD_TYPE, os_version=self._OS_VERSION, build_cache=self._OUT_DIR, - device=self.device) + should_link=True) def test_success(self): make_command = self.stub_subprocess.AddCommand() diff --git a/cli/lib/core/image_build_unittest.py b/cli/lib/core/image_build_unittest.py index f5c8e6b..d15a595 100644 --- a/cli/lib/core/image_build_unittest.py +++ b/cli/lib/core/image_build_unittest.py @@ -21,7 +21,6 @@ import copy import unittest -from bsp import device_stub from core import image_build from core import util_stub from environment import sysroot_stub @@ -74,13 +73,11 @@ class BuildImageBase(TestData): image_build.sysroot = self.stub_sysroot_generator image_build.util = self.stub_util - self.device = device_stub.StubDevice( - should_link_version=self._BRILLO_VERSION) self.platform = platform_stub.StubPlatform( os_version=self._BRILLO_VERSION, - device=self.device, build_cache=self._PLATFORM_DIR, + build_cache=self._PLATFORM_DIR, product_out_cache=self._PRODUCT_DIR, - os_root=self._OS_ROOT) + os_root=self._OS_ROOT, should_link=True) self.target = target_stub.StubTarget(platform=self.platform) self.config = config_stub.StubConfig( artifact_cache=self._ARTIFACT_CACHE_DIR, @@ -189,7 +186,7 @@ class BaseTests(object): self.stub_util.arch_is_supported = False self.stub_subprocess.AddCommand() # Shouldn't reach the linking point. - self.device.should_link_version = None + self.platform.should_link = False with self.assertRaises(self.stub_util.HostUnsupportedArchError): image_build.BuildImage(self.image_type, self.target, self.config) diff --git a/cli/lib/core/provision_unittest.py b/cli/lib/core/provision_unittest.py index ccc8a0e..2485026 100644 --- a/cli/lib/core/provision_unittest.py +++ b/cli/lib/core/provision_unittest.py @@ -97,7 +97,7 @@ class ProvisionDeviceTest(unittest.TestCase): self._PROVISION_DEVICE_PATH, os.path.join(self.provision_temp_dir, 'provision-device'))) self.stub_os.should_makedirs.append(self.provision_temp_dir) - self.platform.device.should_link_version = self._OS_VERSION + self.platform.should_link = True def test_call(self): """Tests a successful provision-device call.""" @@ -211,7 +211,7 @@ class ProvisionDeviceTest(unittest.TestCase): self.prepare_os_files() self.stub_os.path.should_exist.remove(self._FASTBOOT_PATH) self.stub_subprocess.AddCommand() - + self.platform.should_link = False with self.assertRaises(provision.MissingBuildError): provision.provision_device(self.platform) @@ -220,6 +220,7 @@ class ProvisionDeviceTest(unittest.TestCase): self.prepare_os_files() self.stub_os.path.should_exist.remove(self._PROVISION_DEVICE_PATH) self.stub_subprocess.AddCommand() + self.platform.should_link = False with self.assertRaises(provision.MissingBuildError): provision.provision_device(self.platform) diff --git a/cli/lib/core/tool_unittest.py b/cli/lib/core/tool_unittest.py index a2acb89..9f09093 100644 --- a/cli/lib/core/tool_unittest.py +++ b/cli/lib/core/tool_unittest.py @@ -19,7 +19,6 @@ import unittest -from bsp import device_stub from core import config from core import tool from core import util_stub @@ -41,8 +40,7 @@ class ToolWrapperTest(unittest.TestCase): self.platform = platform_stub.StubPlatform( os_version='12.34', os_root='/source', board='board_name', - device=device_stub.StubDevice(should_link_version='12.34'), - build_cache='/build/out') + should_link=True, build_cache='/build/out') def test_run(self): """Tests a basic tool run.""" diff --git a/cli/lib/environment/toolchain_util_unittest.py b/cli/lib/environment/toolchain_util_unittest.py index 2f36401..20dd349 100644 --- a/cli/lib/environment/toolchain_util_unittest.py +++ b/cli/lib/environment/toolchain_util_unittest.py @@ -20,7 +20,6 @@ import stat import unittest -from bsp import device_stub from core import util_stub from environment import toolchain_util from project import platform_stub @@ -46,7 +45,7 @@ class ToolchainUtilTest(unittest.TestCase): self.platform = platform_stub.StubPlatform( os_version=self.OS_VERSION, - device=device_stub.StubDevice(arch=self.TARGET_ARCH)) + device_arch=self.TARGET_ARCH) def test_generate_toolchain(self): diff --git a/cli/lib/project/platform.py b/cli/lib/project/platform.py index 698b089..7b07fb1 100644 --- a/cli/lib/project/platform.py +++ b/cli/lib/project/platform.py @@ -62,6 +62,35 @@ class NotDownloadedError(Error): description = 'Missing download' +class _LinkContext(object): + """A context manager to allow temporary linking of a device to an OS. + + Attributes: + platform: The platform to link together. + """ + + def __init__(self, platform): + self.platform = platform + + def __enter__(self): + success = False + try: + self.platform.device.link(self.platform.os) + success = True + finally: + # If something goes wrong, leave unlinked. + if not success: + self.cleanup() + + def __exit__(self, type_, value_, traceback_): + # TODO(b/28028440): Even if you were linked initially, when + # exiting the context the links will be removed. + self.cleanup() + + def cleanup(self): + self.platform.device.unlink(self.platform.os) + + class Platform(object): """A (read-only) OS + BSP combination. @@ -94,6 +123,10 @@ class Platform(object): raise OsError('unrecognized name "{}" ' '(available OSes: {}).'.format( os_name, bsp_manifest.operating_systems.keys())) + # For now, since we only have one OS version, + # fill it in as a default if necessary. + if not os_version: + os_version = os_.version if os_.version != os_version: raise OsError('version {} ({} is the only available ' 'version for {}).'.format( @@ -106,6 +139,10 @@ class Platform(object): raise BoardError('unrecognized name "{}". Run `bdk bsp list` ' 'to see available boards.'.format( board)) + # For now, since we only have one device version, + # fill it in as a default if necessary. + if not board_version: + board_version = device.version if device.version != board_version: raise BoardError('version {} ({} is the only available ' 'version for {}).'.format( @@ -167,7 +204,15 @@ class Platform(object): return os.path.join(self._cache_path, *relpath) def linked(self): - return self.device.linked(self.os.version) + """A context manager for temporary linkage. + + Note: b/28028440: It is a known bug that after exiting the context, + the device will be unlinked, whether or not it was linked going in. + + Returns: + A context manager within which the BSP and OS will be linked. + """ + return _LinkContext(self) def verify_downloaded(self): """Checks that a platform is downloaded. diff --git a/cli/lib/project/platform_stub.py b/cli/lib/project/platform_stub.py index 9f96c3e..4568ddd 100644 --- a/cli/lib/project/platform_stub.py +++ b/cli/lib/project/platform_stub.py @@ -21,24 +21,21 @@ import os from bsp import device_stub from bsp import operating_system_stub +from test import stubs class StubPlatform(object): """A Stub for the Platform class.""" def __init__(self, os_name='', os_version='', board='', board_version='', - build_type='', operating_system=None, device=None, os_root='', - build_cache='', product_out_cache='', sysroot='', toolchain='', - cache_dir='', verify_raises=Exception): + build_type='', os_root='', device_arch='', build_cache='', + product_out_cache='', sysroot='', toolchain='', cache_dir='', + should_link=False, verify_raises=Exception): # Properties. - self.os = (operating_system or - operating_system_stub.StubOperatingSystem()) - self.os.name = os_name - self.os.version = os_version - self.os.root = os_root - self.device = device or device_stub.StubDevice() - self.device.name = board - self.device.version = board_version + self.os = operating_system_stub.StubOperatingSystem( + name=os_name, root=os_root, version=os_version) + self.device = device_stub.StubDevice(name=board, version=board_version, + arch=device_arch) self.build_type = build_type self.build_cache = build_cache self.product_out_cache = product_out_cache @@ -47,6 +44,7 @@ class StubPlatform(object): # Helpers. self.cache_dir = cache_dir + self.should_link = should_link self.verify_raises = verify_raises @property @@ -61,7 +59,9 @@ class StubPlatform(object): return os.path.join(self.cache_dir, *relpath) def linked(self): - return self.device.linked(self.os.version) + if not self.should_link: + raise StubPlatformModule.Error('Not supposed to link platform.') + return stubs.StubContextManager() def verify_downloaded(self): if self.verify_raises: diff --git a/cli/lib/project/platform_unittest.py b/cli/lib/project/platform_unittest.py index 7c021f5..28035a5 100644 --- a/cli/lib/project/platform_unittest.py +++ b/cli/lib/project/platform_unittest.py @@ -140,15 +140,10 @@ class PlatformTest(unittest.TestCase): self.stub_os.path.join(cache_root, 'a', 'nother', 'path')) def test_link(self): - self.dev.should_link_version = self._OS_VERSION + self.assertFalse(self.dev.is_linked) with self.platform.linked(): - pass - - def test_no_link(self): - self.dev.should_link_version = None - with self.assertRaises(device_stub.Error): - with self.platform.linked(): - pass + self.assertTrue(self.dev.is_linked) + self.assertFalse(self.dev.is_linked) def test_verify_downloaded(self): self.platform.verify_downloaded() |