aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAri Hausman-Cohen <arihc@google.com>2016-05-02 16:55:22 -0700
committerAri Hausman-Cohen <arihc@google.com>2016-05-03 15:23:06 -0700
commitb2b082128abb2bc060c0ef101ee7cc7162624c39 (patch)
tree5c41446d7200ecfbe060a5d23883bca8faf3966b
parent3be19546686aa051bf36ff9ddb0b3af6e4900b86 (diff)
downloadbdk-b2b082128abb2bc060c0ef101ee7cc7162624c39.tar.gz
Adding platform object.
Abstracts Platforms into a unified object. Not yet integrated. BUG: 28401438 Change-Id: I7c727f277c4493e0bd93339fc614f2d2d93e77c7 TEST: unit tests pass
-rw-r--r--cli/lib/bsp/device_stub.py6
-rw-r--r--cli/lib/bsp/manifest_stub.py15
-rw-r--r--cli/lib/project/common.py5
-rw-r--r--cli/lib/project/platform.py212
-rw-r--r--cli/lib/project/platform_unittest.py165
5 files changed, 389 insertions, 14 deletions
diff --git a/cli/lib/bsp/device_stub.py b/cli/lib/bsp/device_stub.py
index 257aac2..6372f6d 100644
--- a/cli/lib/bsp/device_stub.py
+++ b/cli/lib/bsp/device_stub.py
@@ -22,6 +22,10 @@ from bsp import device
from test import stubs
+class Error(device.Error):
+ """Raised when a caller attempts to link to the incorrect OS version."""
+
+
class StubDevice(object):
def __init__(self, name='', vendor='', arch='', package_map=None,
@@ -36,7 +40,7 @@ class StubDevice(object):
def linked(self, os_version):
if not self.should_link_version == os_version:
- raise device.Error('Not supposed to link to {} (only to {})'.format(
+ raise Error('Not supposed to link to {} (only to {})'.format(
os_version, self.should_link_version))
return stubs.StubContextManager()
diff --git a/cli/lib/bsp/manifest_stub.py b/cli/lib/bsp/manifest_stub.py
index ed4e50f..b533b24 100644
--- a/cli/lib/bsp/manifest_stub.py
+++ b/cli/lib/bsp/manifest_stub.py
@@ -26,20 +26,15 @@ class StubManifest(object):
from_json_devices = {}
def __init__(self, devices):
- """devices should be {name: (device, available)}"""
- self.devices = {name: device
- for (name, (device, _))
- in devices.iteritems()}
- self._available = {name: available
- for (name, (_, available))
- in devices.iteritems()}
+ """devices should be {name: device}."""
+ self.devices = devices
def is_bsp_available(self, device):
if not device in self.devices:
- raise StubManifestGenerator.UnknownBspError(
+ raise StubManifestModule.UnknownBspError(
'No such device {}, options are {}'.format(
device, self.devices.keys()))
- return self._available[device]
+ return self.devices[device].is_available()
# pylint: disable=unused-argument
@classmethod
@@ -47,7 +42,7 @@ class StubManifest(object):
return cls(cls.from_json_devices)
-class StubManifestGenerator(object):
+class StubManifestModule(object):
class Error(error.Error):
pass
diff --git a/cli/lib/project/common.py b/cli/lib/project/common.py
index 40b78fc..836e4db 100644
--- a/cli/lib/project/common.py
+++ b/cli/lib/project/common.py
@@ -84,11 +84,10 @@ class LoadError(Error):
class LoadErrorWithOrigin(LoadError):
- def __init__(self, origin, message):
+ def __init__(self, origin, message='', errno=error.GENERIC_ERRNO):
# Prefix where the error occurred at.
message = '{}: {}'.format(origin, message)
- super(LoadErrorWithOrigin, self).__init__(message)
-
+ super(LoadErrorWithOrigin, self).__init__(message, errno=errno)
class UnknownAttributes(LoadErrorWithOrigin):
pass
diff --git a/cli/lib/project/platform.py b/cli/lib/project/platform.py
new file mode 100644
index 0000000..b1884fb
--- /dev/null
+++ b/cli/lib/project/platform.py
@@ -0,0 +1,212 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""An object representing a Platform (OS + BSP combination)."""
+
+
+import os
+
+from bsp import manifest
+from core import user_config
+from core import util
+from project import common
+
+
+BUILD_TYPES = ('user', 'userdebug', 'eng')
+
+
+# Note: this should be kept in sync with
+# commands.environment.setup.SAMPLE_MAKEFILE_TEMPLATE
+PLATFORM_CACHE_FORMAT = os.path.join('{user_configured_platform_cache}',
+ '{os_namespace}',
+ '{board_namespace}')
+
+
+class Error(common.Error):
+ """General Error for targets."""
+
+
+class OsError(Error):
+ """Raised when there is a problem with the specified os/version."""
+ description = 'Invalid OS'
+
+
+class BoardError(Error):
+ """Raised when there is a problem with the specified board/version."""
+ description = 'Invalid board'
+
+
+class BuildTypeError(Error):
+ """Raised when an invalid build type is specified."""
+ description = 'Invalid build type'
+
+
+class NotDownloadedError(Error):
+ """Raised when the specified OS or BSP isn't downloaded."""
+ description = 'Missing download'
+
+
+class Platform(object):
+ """A (read-only) OS + BSP combination.
+
+ Initialization raises an Error if an invalid OS, board, or build_type
+ is requested.
+ """
+
+ def __init__(self, os_name='', os_version='', board='', board_version='',
+ build_type=''):
+ """Initialize a Platform.
+
+ Args:
+ os_name: The name of the OS for this platform. Must be "brillo".
+ os_version: The version of the OS for this platform.
+ board: The name of the board for this platform.
+ board_version: The version of the board for this platform.
+ build_type: The type of build for this platform. Must be one of
+ the designated platform.BUILD_TYPES.
+
+ Raises:
+ OsError: If the OS requested is invalid.
+ BoardError: If the board requested is invalid.
+ BuildTypeError: If the build type requested is invalid.
+ """
+ # OS.
+ if os_name != 'brillo':
+ raise OsError('"{}" ("brillo" is the only supported '
+ 'operating system).'.format(os_name))
+ if os_version != util.GetOSVersion():
+ # Eventually we will support multiple OS versions,
+ # at which point this check should just confirm that
+ # the requested version exists, and an additional check
+ # should be added to verify_downloaded().
+ raise OsError('version {} ({} is the only supported '
+ 'OS version).'.format(
+ util.GetOSVersion(), os_version))
+ self._os = os_name
+ self._os_version = os_version
+
+ # Board.
+ self._board = board
+ self._board_version = board_version
+ self._device = None
+ # Init device raises a BoardError if it can't get the device.
+ self._init_device()
+
+ # TODO(b/27654613): Check OS and board compatibility.
+
+ # Build type.
+ if build_type not in BUILD_TYPES:
+ raise BuildTypeError('{} (acceptable values are {}).'.format(
+ build_type, BUILD_TYPES))
+ self._build_type = build_type
+
+ # Helper variable.
+ self._cache_path = PLATFORM_CACHE_FORMAT.format(
+ user_configured_platform_cache=(
+ user_config.USER_CONFIG.platform_cache),
+ os_namespace=self.os_namespace,
+ board_namespace=self.board_namespace)
+
+ def _init_device(self):
+ """Initialize the bsp.Device associated with this Target.
+
+ Raises:
+ BoardError: If the target board and version is not in the manifest.
+ """
+ bsp_manifest = manifest.Manifest.from_json()
+ device = bsp_manifest.devices.get(self.board)
+ if not device:
+ raise BoardError('unrecognized name "{}". Run `bdk bsp list` '
+ 'to see available boards.'.format(
+ self.board))
+ if device.version != self.board_version:
+ raise BoardError('version {} ({} is the only available '
+ 'version for {}).'.format(
+ self.board_version, device.version, self.board))
+ self._device = device
+
+ @property
+ def os(self):
+ return self._os
+
+ @property
+ def os_version(self):
+ return self._os_version
+
+ @property
+ def os_namespace(self):
+ return '{}.{}'.format(self.os, self.os_version)
+
+ @property
+ def board(self):
+ return self._board
+
+ @property
+ def board_version(self):
+ return self._board_version
+
+ @property
+ def board_namespace(self):
+ return '{}.{}'.format(self.board, self.board_version)
+
+ @property
+ def build_type(self):
+ return self._build_type
+
+ @property
+ def device(self):
+ return self._device
+
+ @property
+ def build_cache(self):
+ return self.cache_path(self.build_type)
+
+ @property
+ def product_out_cache(self):
+ return os.path.join(self.build_cache, 'target', 'product', self.board)
+
+ @property
+ def toolchain(self):
+ return self.cache_path('toolchain')
+
+ @property
+ def sysroot(self):
+ return self.cache_path('sysroot')
+
+ def cache_path(self, *relpath):
+ return os.path.join(self._cache_path, *relpath)
+
+ def os_path(self, *relpath):
+ # TODO(b/28527859): implemented here instead of wrapping.
+ return util.GetOSPath(self.os_version, *relpath)
+
+ def linked(self):
+ return self.device.linked(self.os_version)
+
+ def verify_downloaded(self):
+ """Checks that a platform is downloaded.
+
+ Raises:
+ NotDownloadedError: If the platform isn't downloaded.
+ """
+ # TODO
+ # Check that the known OS version matches the desired version.
+
+ # Check that the BSP is downloaded.
+ if not self.device.is_available():
+ raise NotDownloadedError(
+ 'Board Support Package for "{0}". '
+ 'Run `bdk bsp download {0}`.'.format(self.board))
diff --git a/cli/lib/project/platform_unittest.py b/cli/lib/project/platform_unittest.py
new file mode 100644
index 0000000..601f54c
--- /dev/null
+++ b/cli/lib/project/platform_unittest.py
@@ -0,0 +1,165 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+"""Unit tests for platform.py."""
+
+
+import unittest
+
+from bsp import device_stub
+from bsp import manifest_stub
+from core import user_config_stub
+from core import util_stub
+from project import platform
+from test import stubs
+
+
+class PlatformTest(unittest.TestCase):
+
+ _OS = 'brillo'
+ _OS_VERSION = '99.11'
+ _BSP = 'this_is_a_board'
+ _BSP_VERSION = '80.80'
+ _BUILD_TYPE = 'userdebug'
+ # Should not match any other version used above.
+ _BAD_VERSION = '0.0'
+
+ def setUp(self):
+ self.stub_manifest = manifest_stub.StubManifestModule()
+ self.stub_os = stubs.StubOs()
+ self.stub_user_config = user_config_stub.StubUserConfig()
+ self.stub_util = util_stub.StubUtil(os_version=self._OS_VERSION)
+
+ platform.manifest = self.stub_manifest
+ platform.os = self.stub_os
+ platform.user_config = self.stub_user_config
+ platform.util = self.stub_util
+
+ self.dev = device_stub.StubDevice(self._BSP, version=self._BSP_VERSION,
+ downloaded=True)
+ self.stub_manifest.Manifest.from_json_devices = {self._BSP: self.dev}
+ self.platform = platform.Platform(
+ os_name=self._OS, os_version=self._OS_VERSION, board=self._BSP,
+ board_version=self._BSP_VERSION, build_type=self._BUILD_TYPE)
+
+ def test_init_valid(self):
+ # Check all the properties of our correctly initialized platform.
+
+ # Boring ones.
+ self.assertEqual(self.platform.os, self._OS)
+ self.assertEqual(self.platform.os_version, self._OS_VERSION)
+ self.assertEqual(self.platform.board, self._BSP)
+ self.assertEqual(self.platform.board_version, self._BSP_VERSION)
+ self.assertEqual(self.platform.build_type, self._BUILD_TYPE)
+
+ # Generated ones.
+ # Namespaces should somehow be related to names & versions.
+ self.assertIn(self._OS, self.platform.os_namespace)
+ self.assertIn(self._OS_VERSION, self.platform.os_namespace)
+ self.assertIn(self._BSP, self.platform.board_namespace)
+ self.assertIn(self._BSP_VERSION, self.platform.board_namespace)
+ self.assertEqual(self.platform.device, self.dev)
+ cache_root = self.stub_os.path.join(
+ self.stub_user_config.USER_CONFIG.platform_cache,
+ self.platform.os_namespace,
+ self.platform.board_namespace)
+ self.assertEqual(
+ self.platform.build_cache,
+ self.stub_os.path.join(cache_root, self.platform.build_type))
+ self.assertEqual(self.platform.sysroot,
+ self.stub_os.path.join(cache_root, 'sysroot'))
+ self.assertEqual(self.platform.toolchain,
+ self.stub_os.path.join(cache_root, 'toolchain'))
+ self.assertEqual(
+ self.platform.product_out_cache,
+ self.stub_os.path.join(
+ self.platform.build_cache, 'target', 'product',
+ self.platform.board))
+
+ def test_init_bad_build_type(self):
+ with self.assertRaises(platform.BuildTypeError):
+ platform.Platform(os_name=self._OS,
+ os_version=self._OS_VERSION,
+ board=self._BSP,
+ board_version=self._BSP_VERSION,
+ build_type='not_a_build_type')
+
+ def test_init_bad_board_version(self):
+ with self.assertRaises(platform.BoardError):
+ platform.Platform(os_name=self._OS,
+ os_version=self._OS_VERSION,
+ board=self._BSP,
+ board_version=self._BAD_VERSION,
+ build_type=self._BUILD_TYPE)
+
+ def test_init_bad_board(self):
+ with self.assertRaises(platform.BoardError):
+ platform.Platform(os_name=self._OS,
+ os_version=self._OS_VERSION,
+ board='not_a_board',
+ board_version=self._BSP_VERSION,
+ build_type=self._BUILD_TYPE)
+
+ def test_init_bad_os_version(self):
+ with self.assertRaises(platform.OsError):
+ platform.Platform(os_name=self._OS,
+ os_version=self._BAD_VERSION,
+ board=self._BSP,
+ board_version=self._BSP_VERSION,
+ build_type=self._BUILD_TYPE)
+
+ def test_init_bad_os(self):
+ with self.assertRaises(platform.OsError):
+ platform.Platform(os_name='not_brillo',
+ os_version=self._OS_VERSION,
+ board=self._BSP,
+ board_version=self._BSP_VERSION,
+ build_type=self._BUILD_TYPE)
+
+ def test_cache_path(self):
+ cache_root = self.stub_os.path.join(
+ self.stub_user_config.USER_CONFIG.platform_cache,
+ self.platform.os_namespace,
+ self.platform.board_namespace)
+ self.assertEqual(
+ self.platform.cache_path('a', 'nother', 'path'),
+ self.stub_os.path.join(cache_root, 'a', 'nother', 'path'))
+
+ def test_os_path(self):
+ self.assertEqual(
+ self.platform.os_path('going', 'down', 'into', 'files'),
+ self.stub_util.GetOSPath(self._OS_VERSION,
+ 'going', 'down', 'into', 'files'))
+
+ def test_link(self):
+ self.dev.should_link_version = self._OS_VERSION
+ 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
+
+ def test_verify_downloaded(self):
+ self.platform.verify_downloaded()
+
+ def test_verify_not_downloaded(self):
+ self.dev.downloaded = False
+ with self.assertRaises(platform.NotDownloadedError):
+ self.platform.verify_downloaded()