aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/classes/testexport.bbclass19
-rw-r--r--meta/classes/testimage.bbclass4
-rw-r--r--meta/lib/oeqa/core/target/base.py26
-rw-r--r--meta/lib/oeqa/runtime/context.py109
4 files changed, 68 insertions, 90 deletions
diff --git a/meta/classes/testexport.bbclass b/meta/classes/testexport.bbclass
index d070f07afad..85b3009ef7c 100644
--- a/meta/classes/testexport.bbclass
+++ b/meta/classes/testexport.bbclass
@@ -58,8 +58,8 @@ def testexport_main(d):
logger = logging.getLogger("BitBake")
target = OERuntimeTestContextExecutor.getTarget(
- d.getVar("TEST_TARGET"), None, d.getVar("TEST_TARGET_IP"),
- d.getVar("TEST_SERVER_IP"))
+ d.getVar("TEST_TARGET"), d.getVar('BBLAYERS').split(), None,
+ d.getVar("TEST_TARGET_IP"), d.getVar("TEST_SERVER_IP"))
host_dumper = OERuntimeTestContextExecutor.getHostDumper(
d.getVar("testimage_dump_host"), d.getVar("TESTIMAGE_DUMP_DIR"))
@@ -108,6 +108,21 @@ def copy_needed_files(d, tc):
else:
shutil.copy2(src, dst)
+ # Get all target files.
+ t_path = os.path.join('lib', 'oeqa', 'core', 'target')
+ targets_to_copy = [os.path.join(root, filename)
+ for path in d.getVar('BBLAYERS').split()
+ for root, _, files in os.walk(os.path.join(path, t_path))
+ for filename in files
+ if filename.endswith('.py') ]
+
+ # Copy all targets.
+ export_target_path = os.path.join(export_path, t_path)
+ oe.path.remove(export_target_path)
+ bb.utils.mkdirhier(export_target_path)
+ for f in targets_to_copy:
+ shutil.copy2(f, export_target_path)
+
# Remove cases and just copy the ones specified
cases_path = os.path.join(export_path, 'lib', 'oeqa', 'runtime', 'cases')
oe.path.remove(cases_path)
diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass
index 0c4a84e1119..c8ae03520e2 100644
--- a/meta/classes/testimage.bbclass
+++ b/meta/classes/testimage.bbclass
@@ -248,8 +248,8 @@ def testimage_main(d):
# the robot dance
target = OERuntimeTestContextExecutor.getTarget(
- d.getVar("TEST_TARGET"), None, d.getVar("TEST_TARGET_IP"),
- d.getVar("TEST_SERVER_IP"), **target_kwargs)
+ d.getVar("TEST_TARGET"), d.getVar('BBLAYERS').split(), None,
+ d.getVar("TEST_TARGET_IP"), d.getVar("TEST_SERVER_IP"), **target_kwargs)
# test context
tc = OERuntimeTestContext(td, logger, target, host_dumper,
diff --git a/meta/lib/oeqa/core/target/base.py b/meta/lib/oeqa/core/target/base.py
index c8864913606..426a57710d3 100644
--- a/meta/lib/oeqa/core/target/base.py
+++ b/meta/lib/oeqa/core/target/base.py
@@ -54,3 +54,29 @@ class OETarget(object):
@abstractmethod
def copyDirTo(self, localSrc, remoteDst):
pass
+
+def discover_targets(layer_paths):
+ """
+ Imports modules found in 'lib/oeqa/core/target'.
+
+ This is used to register targets using registerTarget decorator.
+ """
+
+ target_path = 'lib/oeqa/core/target'
+ paths = [os.path.join(p, target_path) for p in layer_paths]
+ for path in paths:
+ files_python = [os.path.join(root, filename)
+ for root, _, filenames in os.walk(path)
+ for filename in filenames
+ if filename.endswith('.py')]
+ for f in files_python:
+ if '__init__.py' in f:
+ continue
+ abs_path = os.path.abspath(f)
+ for sys_path in sys.path:
+ if sys_path in abs_path:
+ rel_path = os.path.relpath(abs_path, sys_path)
+ break
+
+ name = rel_path.replace('.py', '').replace(os.path.sep, '.')
+ importlib.import_module(name)
diff --git a/meta/lib/oeqa/runtime/context.py b/meta/lib/oeqa/runtime/context.py
index 0294003fc7e..2f91a06d567 100644
--- a/meta/lib/oeqa/runtime/context.py
+++ b/meta/lib/oeqa/runtime/context.py
@@ -51,6 +51,10 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
default_target_ip = '192.168.7.2'
default_host_dumper_dir = '/tmp/oe-saved-tests'
default_extract_dir = 'packages/extracted'
+ default_root = os.path.join(
+ os.path.dirname(
+ os.path.dirname(
+ os.path.dirname(os.path.dirname(__file__)))))
def register_commands(self, logger, subparsers):
super(OERuntimeTestContextExecutor, self).register_commands(logger, subparsers)
@@ -58,7 +62,7 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
runtime_group = self.parser.add_argument_group('runtime options')
runtime_group.add_argument('--target-type', action='store',
- default=self.default_target_type, choices=['simpleremote', 'qemu'],
+ default=self.default_target_type,
help="Target type of device under test, default: %s" \
% self.default_target_type)
runtime_group.add_argument('--target-ip', action='store',
@@ -89,8 +93,18 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
help="Qemu boot configuration, only needed when target_type is QEMU.")
@staticmethod
- def getTarget(target_type, logger, target_ip, server_ip, **kwargs):
+ def getTarget(target_type, target_paths, logger, target_ip, server_ip, **kwargs):
+ """
+ Gets target to be used with runtime testing.
+
+ It is possible to add targes using registerTarget decorator and putting
+ the module in 'lib/oeqa/core/target' directory of your layer.
+ """
+
+ from oeqa.core.target.base import discover_targets, targetClasses
+
target = None
+ discover_targets(target_paths)
if target_ip:
target_ip_port = target_ip.split(':')
@@ -98,93 +112,15 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
target_ip = target_ip_port[0]
kwargs['port'] = target_ip_port[1]
- if target_type == 'simpleremote':
- target = OESSHTarget(logger, target_ip, server_ip, **kwargs)
- elif target_type == 'qemu':
- target = OEQemuTarget(logger, target_ip, server_ip, **kwargs)
+ target_class = targetClasses.get(target_type, None)
+ if target_class:
+ target = target_class(logger, target_ip, server_ip, **kwargs)
else:
- # XXX: This code uses the old naming convention for controllers and
- # targets, the idea it is to leave just targets as the controller
- # most of the time was just a wrapper.
- # XXX: This code tries to import modules from lib/oeqa/controllers
- # directory and treat them as controllers, it will less error prone
- # to use introspection to load such modules.
- # XXX: Don't base your targets on this code it will be refactored
- # in the near future.
- # Custom target module loading
- try:
- target_modules_path = kwargs.get('target_modules_path', '')
- controller = OERuntimeTestContextExecutor.getControllerModule(target_type, target_modules_path)
- target = controller(logger, target_ip, server_ip, **kwargs)
- except ImportError as e:
- raise TypeError("Failed to import %s from available controller modules" % target_type)
+ msg = 'Can\'t find "%s" in available targets' % target_type
+ raise TypeError(msg)
return target
- # Search oeqa.controllers module directory for and return a controller
- # corresponding to the given target name.
- # AttributeError raised if not found.
- # ImportError raised if a provided module can not be imported.
- @staticmethod
- def getControllerModule(target, target_modules_path):
- controllerslist = OERuntimeTestContextExecutor._getControllerModulenames(target_modules_path)
- controller = OERuntimeTestContextExecutor._loadControllerFromName(target, controllerslist)
- return controller
-
- # Return a list of all python modules in lib/oeqa/controllers for each
- # layer in bbpath
- @staticmethod
- def _getControllerModulenames(target_modules_path):
-
- controllerslist = []
-
- def add_controller_list(path):
- if not os.path.exists(os.path.join(path, '__init__.py')):
- raise OSError('Controllers directory %s exists but is missing __init__.py' % path)
- files = sorted([f for f in os.listdir(path) if f.endswith('.py') and not f.startswith('_')])
- for f in files:
- module = 'oeqa.controllers.' + f[:-3]
- if module not in controllerslist:
- controllerslist.append(module)
- else:
- raise RuntimeError("Duplicate controller module found for %s. Layers should create unique controller module names" % module)
-
- extpath = target_modules_path.split(':')
- for p in extpath:
- controllerpath = os.path.join(p, 'lib', 'oeqa', 'controllers')
- if os.path.exists(controllerpath):
- add_controller_list(controllerpath)
- return controllerslist
-
- # Search for and return a controller from given target name and
- # set of module names.
- # Raise AttributeError if not found.
- # Raise ImportError if a provided module can not be imported
- @staticmethod
- def _loadControllerFromName(target, modulenames):
- for name in modulenames:
- obj = OERuntimeTestContextExecutor._loadControllerFromModule(target, name)
- if obj:
- return obj
- raise AttributeError("Unable to load {0} from available modules: {1}".format(target, str(modulenames)))
-
- # Search for and return a controller or None from given module name
- @staticmethod
- def _loadControllerFromModule(target, modulename):
- obj = None
- # import module, allowing it to raise import exception
- try:
- module = __import__(modulename, globals(), locals(), [target])
- except Exception as e:
- return obj
- # look for target class in the module, catching any exceptions as it
- # is valid that a module may not have the target class.
- try:
- obj = getattr(module, target)
- except:
- obj = None
- return obj
-
@staticmethod
def readPackagesManifest(manifest):
if not manifest or not os.path.exists(manifest):
@@ -214,7 +150,8 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
self.tc_kwargs['init']['target'] = \
OERuntimeTestContextExecutor.getTarget(args.target_type,
- None, args.target_ip, args.server_ip, **target_kwargs)
+ [self.default_root], None, args.target_ip, args.server_ip,
+ **target_kwargs)
self.tc_kwargs['init']['host_dumper'] = \
OERuntimeTestContextExecutor.getHostDumper(None,
args.host_dumper_dir)