* [PATCHv3 01/30] oeqa/core: Add base OEQA framework
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 02/30] oeqa/core: Add utils module for " Aníbal Limón
` (28 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
case: Defines OETestCase base class that provides custom
methods/attrs defined by the framework.
Every OETestCase instance contains a reference to the test
data (d), the test context (tc) and the logger.
Also implements _oe{SetUp,TearDown}Class for make special
handling of OEQA decorators and validations.
runner: Defines OETestRunner/OETestResult with support for RAW
and XML result logs.
exception: Custom exceptions related to the OEQA framework based
on class OEQAException.
[YOCTO #10230]
[YOCTO #10233]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/core/__init__.py | 0
meta/lib/oeqa/core/case.py | 46 +++++++++++++++++++++++++
meta/lib/oeqa/core/exception.py | 14 ++++++++
meta/lib/oeqa/core/runner.py | 76 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 136 insertions(+)
create mode 100644 meta/lib/oeqa/core/__init__.py
create mode 100644 meta/lib/oeqa/core/case.py
create mode 100644 meta/lib/oeqa/core/exception.py
create mode 100644 meta/lib/oeqa/core/runner.py
diff --git a/meta/lib/oeqa/core/__init__.py b/meta/lib/oeqa/core/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/meta/lib/oeqa/core/case.py b/meta/lib/oeqa/core/case.py
new file mode 100644
index 0000000..d2dbf20
--- /dev/null
+++ b/meta/lib/oeqa/core/case.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import unittest
+
+from oeqa.core.exception import OEQAMissingVariable
+
+def _validate_td_vars(td, td_vars, type_msg):
+ if td_vars:
+ for v in td_vars:
+ if not v in td:
+ raise OEQAMissingVariable("Test %s need %s variable but"\
+ " isn't into td" % (type_msg, v))
+
+class OETestCase(unittest.TestCase):
+ # TestContext and Logger instance set by OETestLoader.
+ tc = None
+ logger = None
+
+ # td has all the variables needed by the test cases
+ # is the same across all the test cases.
+ td = None
+
+ # td_vars has the variables needed by a test class
+ # or test case instance, if some var isn't into td a
+ # OEMissingVariable exception is raised
+ td_vars = None
+
+ @classmethod
+ def _oeSetUpClass(clss):
+ _validate_td_vars(clss.td, clss.td_vars, "class")
+ clss.setUpClassMethod()
+
+ @classmethod
+ def _oeTearDownClass(clss):
+ clss.tearDownClassMethod()
+
+ def _oeSetUp(self):
+ for d in self.decorators:
+ d.setUpDecorator()
+ self.setUpMethod()
+
+ def _oeTearDown(self):
+ for d in self.decorators:
+ d.tearDownDecorator()
+ self.tearDownMethod()
diff --git a/meta/lib/oeqa/core/exception.py b/meta/lib/oeqa/core/exception.py
new file mode 100644
index 0000000..2dfd840
--- /dev/null
+++ b/meta/lib/oeqa/core/exception.py
@@ -0,0 +1,14 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+class OEQAException(Exception):
+ pass
+
+class OEQATimeoutError(OEQAException):
+ pass
+
+class OEQAMissingVariable(OEQAException):
+ pass
+
+class OEQADependency(OEQAException):
+ pass
diff --git a/meta/lib/oeqa/core/runner.py b/meta/lib/oeqa/core/runner.py
new file mode 100644
index 0000000..8f5af57
--- /dev/null
+++ b/meta/lib/oeqa/core/runner.py
@@ -0,0 +1,76 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import os
+import time
+import unittest
+import logging
+
+xmlEnabled = False
+try:
+ import xmlrunner
+ from xmlrunner.result import _XMLTestResult as _TestResult
+ from xmlrunner.runner import XMLTestRunner as _TestRunner
+ xmlEnabled = True
+except ImportError:
+ # use the base runner instead
+ from unittest import TextTestResult as _TestResult
+ from unittest import TextTestRunner as _TestRunner
+
+class OEStreamLogger(object):
+ def __init__(self, logger):
+ self.logger = logger
+ self.buffer = ""
+
+ def write(self, msg):
+ if msg[-1] != '\n':
+ self.buffer += msg
+ else:
+ self.logger.log(logging.INFO, self.buffer.rstrip("\n"))
+ self.buffer = ""
+
+ def flush(self):
+ for handler in self.logger.handlers:
+ handler.flush()
+
+class OETestResult(_TestResult):
+ def __init__(self, tc, *args, **kwargs):
+ super(OETestResult, self).__init__(*args, **kwargs)
+
+ self.tc = tc
+
+ self.tc._results['failures'] = self.failures
+ self.tc._results['errors'] = self.errors
+ self.tc._results['skipped'] = self.skipped
+ self.tc._results['expectedFailures'] = self.expectedFailures
+
+ def startTest(self, test):
+ super(OETestResult, self).startTest(test)
+
+class OETestRunner(_TestRunner):
+ def __init__(self, tc, *args, **kwargs):
+ if xmlEnabled:
+ if not kwargs.get('output'):
+ kwargs['output'] = os.path.join(os.getcwd(),
+ 'TestResults_%s' % time.strftime("%Y%m%d%H%M%S"))
+
+ super(OETestRunner, self).__init__(*args, **kwargs)
+ self.tc = tc
+ self.resultclass = OETestResult
+
+ # XXX: The unittest-xml-reporting package defines _make_result method instead
+ # of _makeResult standard on unittest.
+ if xmlEnabled:
+ def _make_result(self):
+ """
+ Creates a TestResult object which will be used to store
+ information about the executed tests.
+ """
+ # override in subclasses if necessary.
+ return self.resultclass(self.tc,
+ self.stream, self.descriptions, self.verbosity, self.elapsed_times
+ )
+ else:
+ def _makeResult(self):
+ return self.resultclass(self.tc, self.stream, self.descriptions,
+ self.verbosity)
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 02/30] oeqa/core: Add utils module for OEQA framework
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 01/30] oeqa/core: Add base OEQA framework Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 03/30] oeqa/core: Add loader, context and decorator modules Aníbal Limón
` (27 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
From: Mariano Lopez <mariano.lopez@linux.intel.com>
misc: Functions for transform object to other types.
path: Functions for path handling.
test: Functions for operations related to test cases and suites.
[YOCTO #10232]
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/lib/oeqa/core/utils/__init__.py | 0
meta/lib/oeqa/core/utils/misc.py | 37 +++++++++++++++++++
meta/lib/oeqa/core/utils/path.py | 19 ++++++++++
meta/lib/oeqa/core/utils/test.py | 71 ++++++++++++++++++++++++++++++++++++
4 files changed, 127 insertions(+)
create mode 100644 meta/lib/oeqa/core/utils/__init__.py
create mode 100644 meta/lib/oeqa/core/utils/misc.py
create mode 100644 meta/lib/oeqa/core/utils/path.py
create mode 100644 meta/lib/oeqa/core/utils/test.py
diff --git a/meta/lib/oeqa/core/utils/__init__.py b/meta/lib/oeqa/core/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/meta/lib/oeqa/core/utils/misc.py b/meta/lib/oeqa/core/utils/misc.py
new file mode 100644
index 0000000..6ae58ad
--- /dev/null
+++ b/meta/lib/oeqa/core/utils/misc.py
@@ -0,0 +1,37 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+def toList(obj, obj_type, obj_name="Object"):
+ if isinstance(obj, obj_type):
+ return [obj]
+ elif isinstance(obj, list):
+ return obj
+ else:
+ raise TypeError("%s must be %s or list" % (obj_name, obj_type))
+
+def toSet(obj, obj_type, obj_name="Object"):
+ if isinstance(obj, obj_type):
+ return {obj}
+ elif isinstance(obj, list):
+ return set(obj)
+ elif isinstance(obj, set):
+ return obj
+ else:
+ raise TypeError("%s must be %s or set" % (obj_name, obj_type))
+
+def strToList(obj, obj_name="Object"):
+ return toList(obj, str, obj_name)
+
+def strToSet(obj, obj_name="Object"):
+ return toSet(obj, str, obj_name)
+
+def intToList(obj, obj_name="Object"):
+ return toList(obj, int, obj_name)
+
+def dataStoteToDict(d, variables):
+ data = {}
+
+ for v in variables:
+ data[v] = d.getVar(v, True)
+
+ return data
diff --git a/meta/lib/oeqa/core/utils/path.py b/meta/lib/oeqa/core/utils/path.py
new file mode 100644
index 0000000..a21caad
--- /dev/null
+++ b/meta/lib/oeqa/core/utils/path.py
@@ -0,0 +1,19 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import os
+import sys
+
+def findFile(file_name, directory):
+ """
+ Search for a file in directory and returns its complete path.
+ """
+ for r, d, f in os.walk(directory):
+ if file_name in f:
+ return os.path.join(r, file_name)
+ return None
+
+def remove_safe(path):
+ if os.path.exists(path):
+ os.remove(path)
+
diff --git a/meta/lib/oeqa/core/utils/test.py b/meta/lib/oeqa/core/utils/test.py
new file mode 100644
index 0000000..820b997
--- /dev/null
+++ b/meta/lib/oeqa/core/utils/test.py
@@ -0,0 +1,71 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import os
+import unittest
+
+def getSuiteCases(suite):
+ """
+ Returns individual test from a test suite.
+ """
+ tests = []
+ for item in suite:
+ if isinstance(item, unittest.suite.TestSuite):
+ tests.extend(getSuiteCases(item))
+ elif isinstance(item, unittest.TestCase):
+ tests.append(item)
+ return tests
+
+def getSuiteModules(suite):
+ """
+ Returns modules in a test suite.
+ """
+ modules = set()
+ for test in getSuiteCases(suite):
+ modules.add(getCaseModule(test))
+ return modules
+
+def getSuiteCasesInfo(suite, func):
+ """
+ Returns test case info from suite. Info is fetched from func.
+ """
+ tests = []
+ for test in getSuiteCases(suite):
+ tests.append(func(test))
+ return tests
+
+def getSuiteCasesNames(suite):
+ """
+ Returns test case names from suite.
+ """
+ return getSuiteCasesInfo(suite, getCaseMethod)
+
+def getSuiteCasesIDs(suite):
+ """
+ Returns test case ids from suite.
+ """
+ return getSuiteCasesInfo(suite, getCaseID)
+
+def getCaseModule(test_case):
+ """
+ Returns test case module name.
+ """
+ return test_case.__module__
+
+def getCaseClass(test_case):
+ """
+ Returns test case class name.
+ """
+ return test_case.__class__.__name__
+
+def getCaseID(test_case):
+ """
+ Returns test case complete id.
+ """
+ return test_case.id()
+
+def getCaseMethod(test_case):
+ """
+ Returns test case method name.
+ """
+ return getCaseID(test_case).split('.')[-1]
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 03/30] oeqa/core: Add loader, context and decorator modules
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 01/30] oeqa/core: Add base OEQA framework Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 02/30] oeqa/core: Add utils module for " Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 04/30] oeqa/core/decorator: Add support for OETestDepends Aníbal Limón
` (26 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
loader: Implements OETestLoader handling OETestDecorator
and filtering support when load tests. The OETestLoader is
responsible to set custom methods, attrs of the OEQA
frameowork.
[YOCTO #10231]
[YOCTO #10317]
[YOCTO #10353]
decorator: Add base class OETestDecorator to provide a common
way to define decorators to be used over OETestCase's, every
decorator has a method to be called when loading tests and
before test execution starts. Special decorators could be
implemented for filter tests on loading phase.
context: Provides HIGH level API for loadTests and runTests
of certain test component (i.e. runtime, sdk, selftest).
[YOCTO #10230]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/core/context.py | 140 ++++++++++++++++++
meta/lib/oeqa/core/decorator/__init__.py | 71 ++++++++++
meta/lib/oeqa/core/loader.py | 235 +++++++++++++++++++++++++++++++
3 files changed, 446 insertions(+)
create mode 100644 meta/lib/oeqa/core/context.py
create mode 100644 meta/lib/oeqa/core/decorator/__init__.py
create mode 100644 meta/lib/oeqa/core/loader.py
diff --git a/meta/lib/oeqa/core/context.py b/meta/lib/oeqa/core/context.py
new file mode 100644
index 0000000..3499994
--- /dev/null
+++ b/meta/lib/oeqa/core/context.py
@@ -0,0 +1,140 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import os
+import sys
+import json
+import time
+import logging
+import collections
+import re
+
+from oeqa.core.loader import OETestLoader
+from oeqa.core.runner import OETestRunner, OEStreamLogger, xmlEnabled
+
+class OETestContext(object):
+ loaderClass = OETestLoader
+ runnerClass = OETestRunner
+ streamLoggerClass = OEStreamLogger
+
+ files_dir = os.path.abspath(os.path.join(os.path.dirname(
+ os.path.abspath(__file__)), "../files"))
+
+ def __init__(self, td=None, logger=None):
+ if not type(td) is dict:
+ raise TypeError("td isn't dictionary type")
+
+ self.td = td
+ self.logger = logger
+ self._registry = {}
+ self._registry['cases'] = collections.OrderedDict()
+ self._results = {}
+
+ def _read_modules_from_manifest(self, manifest):
+ if not os.path.exists(manifest):
+ raise
+
+ modules = []
+ for line in open(manifest).readlines():
+ line = line.strip()
+ if line and not line.startswith("#"):
+ modules.append(line)
+
+ return modules
+
+ def loadTests(self, module_paths, modules=[], tests=[],
+ modules_manifest="", modules_required=[], filters={}):
+ if modules_manifest:
+ modules = self._read_modules_from_manifest(modules_manifest)
+
+ self.loader = self.loaderClass(self, module_paths, modules, tests,
+ modules_required, filters)
+ self.suites = self.loader.discover()
+
+ def runTests(self):
+ streamLogger = self.streamLoggerClass(self.logger)
+ self.runner = self.runnerClass(self, stream=streamLogger, verbosity=2)
+
+ self._run_start_time = time.time()
+ result = self.runner.run(self.suites)
+ self._run_end_time = time.time()
+
+ return result
+
+ def logSummary(self, result, component, context_msg=''):
+ self.logger.info("SUMMARY:")
+ self.logger.info("%s (%s) - Ran %d test%s in %.3fs" % (component,
+ context_msg, result.testsRun, result.testsRun != 1 and "s" or "",
+ (self._run_end_time - self._run_start_time)))
+
+ if result.wasSuccessful():
+ msg = "%s - OK - All required tests passed" % component
+ else:
+ msg = "%s - FAIL - Required tests failed" % component
+ skipped = len(self._results['skipped'])
+ if skipped:
+ msg += " (skipped=%d)" % skipped
+ self.logger.info(msg)
+
+ def _logDetailsNotPassed(self, case, type, desc):
+ found = False
+
+ for (scase, msg) in self._results[type]:
+ # XXX: When XML reporting is enabled scase is
+ # xmlrunner.result._TestInfo instance instead of
+ # string.
+ if xmlEnabled:
+ if case.id() == scase.test_id:
+ found = True
+ break
+ scase_str = scase.test_id
+ else:
+ if case == scase:
+ found = True
+ break
+ scase_str = str(scase)
+
+ # When fails at module or class level the class name is passed as string
+ # so figure out to see if match
+ m = re.search("^setUpModule \((?P<module_name>.*)\)$", scase_str)
+ if m:
+ if case.__class__.__module__ == m.group('module_name'):
+ found = True
+ break
+
+ m = re.search("^setUpClass \((?P<class_name>.*)\)$", scase_str)
+ if m:
+ class_name = "%s.%s" % (case.__class__.__module__,
+ case.__class__.__name__)
+
+ if class_name == m.group('class_name'):
+ found = True
+ break
+
+ if found:
+ self.logger.info("RESULTS - %s - Testcase %s: %s" % (case.id(),
+ case.oe_id if hasattr(case, 'oeid') else '-1', desc))
+ if msg:
+ self.logger.info(msg)
+
+ return found
+
+ def logDetails(self):
+ self.logger.info("RESULTS:")
+ for case_name in self._registry['cases']:
+ case = self._registry['cases'][case_name]
+
+ result_types = ['failures', 'errors', 'skipped', 'expectedFailures']
+ result_desc = ['FAILED', 'ERROR', 'SKIPPED', 'EXPECTEDFAIL']
+
+ match = False
+ for idx, name in enumerate(result_types):
+ match = self._logDetailsNotPassed(case, result_types[idx],
+ result_desc[idx])
+ if match:
+ break
+
+ if not match:
+ self.logger.info("RESULTS - %s - Testcase %s: %s" % (case.id(),
+ case.oe_id if hasattr(case, 'oeid') else '-1',
+ 'PASSED'))
diff --git a/meta/lib/oeqa/core/decorator/__init__.py b/meta/lib/oeqa/core/decorator/__init__.py
new file mode 100644
index 0000000..855b6b9
--- /dev/null
+++ b/meta/lib/oeqa/core/decorator/__init__.py
@@ -0,0 +1,71 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from functools import wraps
+from abc import abstractmethod
+
+decoratorClasses = set()
+
+def registerDecorator(obj):
+ decoratorClasses.add(obj)
+ return obj
+
+class OETestDecorator(object):
+ case = None # Reference of OETestCase decorated
+ attrs = None # Attributes to be loaded by decorator implementation
+
+ def __init__(self, *args, **kwargs):
+ if not self.attrs:
+ return
+
+ for idx, attr in enumerate(self.attrs):
+ if attr in kwargs:
+ value = kwargs[attr]
+ else:
+ value = args[idx]
+ setattr(self, attr, value)
+
+ def __call__(self, func):
+ @wraps(func)
+ def wrapped_f(*args, **kwargs):
+ self.attrs = self.attrs # XXX: Enables OETestLoader discover
+ return func(*args, **kwargs)
+ return wrapped_f
+
+ # OETestLoader call it when is loading test cases.
+ # XXX: Most methods would change the registry for later
+ # processing; be aware that filtrate method needs to
+ # run later than bind, so there could be data (in the
+ # registry) of a cases that were filtered.
+ def bind(self, registry, case):
+ self.case = case
+ self.logger = case.tc.logger
+ self.case.decorators.append(self)
+
+ # OETestRunner call this method when tries to run
+ # the test case.
+ def setUpDecorator(self):
+ pass
+
+ # OETestRunner call it after a test method has been
+ # called even if the method raised an exception.
+ def tearDownDecorator(self):
+ pass
+
+class OETestDiscover(OETestDecorator):
+
+ # OETestLoader call it after discover test cases
+ # needs to return the cases to be run.
+ @staticmethod
+ def discover(registry):
+ return registry['cases']
+
+class OETestFilter(OETestDecorator):
+
+ # OETestLoader call it while loading the tests
+ # in loadTestsFromTestCase method, it needs to
+ # return a bool, True if needs to be filtered.
+ # This method must consume the filter used.
+ @abstractmethod
+ def filtrate(self, filters):
+ return False
diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py
new file mode 100644
index 0000000..c73ef9a
--- /dev/null
+++ b/meta/lib/oeqa/core/loader.py
@@ -0,0 +1,235 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import os
+import sys
+import unittest
+
+from oeqa.core.utils.path import findFile
+from oeqa.core.utils.test import getSuiteModules, getCaseID
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator import decoratorClasses, OETestDecorator, \
+ OETestFilter, OETestDiscover
+
+def _make_failed_test(classname, methodname, exception, suiteClass):
+ """
+ When loading tests unittest framework stores the exception in a new
+ class created for be displayed into run().
+
+ For our purposes will be better to raise the exception in loading
+ step instead of wait to run the test suite.
+ """
+ raise exception
+unittest.loader._make_failed_test = _make_failed_test
+
+def _find_duplicated_modules(suite, directory):
+ for module in getSuiteModules(suite):
+ path = findFile('%s.py' % module, directory)
+ if path:
+ raise ImportError("Duplicated %s module found in %s" % (module, path))
+
+class OETestLoader(unittest.TestLoader):
+ caseClass = OETestCase
+
+ kwargs_names = ['testMethodPrefix', 'sortTestMethodUsing', 'suiteClass',
+ '_top_level_dir']
+
+ def __init__(self, tc, module_paths, modules, tests, modules_required,
+ filters, *args, **kwargs):
+ self.tc = tc
+
+ self.modules = modules
+ self.tests = tests
+ self.modules_required = modules_required
+
+ self.filters = filters
+ self.decorator_filters = [d for d in decoratorClasses if \
+ issubclass(d, OETestFilter)]
+ self._validateFilters(self.filters, self.decorator_filters)
+ self.used_filters = [d for d in self.decorator_filters
+ for f in self.filters
+ if f in d.attrs]
+
+ if isinstance(module_paths, str):
+ module_paths = [module_paths]
+ elif not isinstance(module_paths, list):
+ raise TypeError('module_paths must be a str or a list of str')
+ self.module_paths = module_paths
+
+ for kwname in self.kwargs_names:
+ if kwname in kwargs:
+ setattr(self, kwname, kwargs[kwname])
+
+ self._patchCaseClass(self.caseClass)
+
+ def _patchCaseClass(self, testCaseClass):
+ # Adds custom attributes to the OETestCase class
+ setattr(testCaseClass, 'tc', self.tc)
+ setattr(testCaseClass, 'td', self.tc.td)
+ setattr(testCaseClass, 'logger', self.tc.logger)
+
+ def _validateFilters(self, filters, decorator_filters):
+ # Validate if filter isn't empty
+ for key,value in filters.items():
+ if not value:
+ raise TypeError("Filter %s specified is empty" % key)
+
+ # Validate unique attributes
+ attr_filters = [attr for clss in decorator_filters \
+ for attr in clss.attrs]
+ dup_attr = [attr for attr in attr_filters
+ if attr_filters.count(attr) > 1]
+ if dup_attr:
+ raise TypeError('Detected duplicated attribute(s) %s in filter'
+ ' decorators' % ' ,'.join(dup_attr))
+
+ # Validate if filter is supported
+ for f in filters:
+ if f not in attr_filters:
+ classes = ', '.join([d.__name__ for d in decorator_filters])
+ raise TypeError('Found "%s" filter but not declared in any of '
+ '%s decorators' % (f, classes))
+
+ def _registerTestCase(self, case):
+ case_id = case.id()
+ self.tc._registry['cases'][case_id] = case
+
+ def _handleTestCaseDecorators(self, case):
+ def _handle(obj):
+ if isinstance(obj, OETestDecorator):
+ if not obj.__class__ in decoratorClasses:
+ raise Exception("Decorator %s isn't registered" \
+ " in decoratorClasses." % obj.__name__)
+ obj.bind(self.tc._registry, case)
+
+ def _walk_closure(obj):
+ if hasattr(obj, '__closure__') and obj.__closure__:
+ for f in obj.__closure__:
+ obj = f.cell_contents
+ _handle(obj)
+ _walk_closure(obj)
+ method = getattr(case, case._testMethodName, None)
+ _walk_closure(method)
+
+ def _filterTest(self, case):
+ """
+ Returns True if test case must be filtered, False otherwise.
+ """
+ if self.filters:
+ filters = self.filters.copy()
+ case_decorators = [cd for cd in case.decorators
+ if cd.__class__ in self.used_filters]
+
+ # Iterate over case decorators to check if needs to be filtered.
+ for cd in case_decorators:
+ if cd.filtrate(filters):
+ return True
+
+ # Case is missing one or more decorators for all the filters
+ # being used, so filter test case.
+ if filters:
+ return True
+
+ return False
+
+ def _getTestCase(self, testCaseClass, tcName):
+ if not hasattr(testCaseClass, '__oeqa_loader'):
+ # In order to support data_vars validation
+ # monkey patch the default setUp/tearDown{Class} to use
+ # the ones provided by OETestCase
+ setattr(testCaseClass, 'setUpClassMethod',
+ getattr(testCaseClass, 'setUpClass'))
+ setattr(testCaseClass, 'tearDownClassMethod',
+ getattr(testCaseClass, 'tearDownClass'))
+ setattr(testCaseClass, 'setUpClass',
+ testCaseClass._oeSetUpClass)
+ setattr(testCaseClass, 'tearDownClass',
+ testCaseClass._oeTearDownClass)
+
+ # In order to support decorators initialization
+ # monkey patch the default setUp/tearDown to use
+ # a setUpDecorators/tearDownDecorators that methods
+ # will call setUp/tearDown original methods.
+ setattr(testCaseClass, 'setUpMethod',
+ getattr(testCaseClass, 'setUp'))
+ setattr(testCaseClass, 'tearDownMethod',
+ getattr(testCaseClass, 'tearDown'))
+ setattr(testCaseClass, 'setUp', testCaseClass._oeSetUp)
+ setattr(testCaseClass, 'tearDown', testCaseClass._oeTearDown)
+
+ setattr(testCaseClass, '__oeqa_loader', True)
+
+ case = testCaseClass(tcName)
+ setattr(case, 'decorators', [])
+
+ return case
+
+ def loadTestsFromTestCase(self, testCaseClass):
+ """
+ Returns a suite of all tests cases contained in testCaseClass.
+ """
+ if issubclass(testCaseClass, unittest.suite.TestSuite):
+ raise TypeError("Test cases should not be derived from TestSuite." \
+ " Maybe you meant to derive from TestCase?")
+ if not issubclass(testCaseClass, self.caseClass):
+ raise TypeError("Test cases need to be derived from %s" % \
+ caseClass.__name__)
+
+
+ testCaseNames = self.getTestCaseNames(testCaseClass)
+ if not testCaseNames and hasattr(testCaseClass, 'runTest'):
+ testCaseNames = ['runTest']
+
+ suite = []
+ for tcName in testCaseNames:
+ case = self._getTestCase(testCaseClass, tcName)
+ # Filer by case id
+ if not (self.tests and not 'all' in self.tests
+ and not getCaseID(case) in self.tests):
+ self._handleTestCaseDecorators(case)
+
+ # Filter by decorators
+ if not self._filterTest(case):
+ self._registerTestCase(case)
+ suite.append(case)
+
+ return self.suiteClass(suite)
+
+ def discover(self):
+ big_suite = self.suiteClass()
+ for path in self.module_paths:
+ _find_duplicated_modules(big_suite, path)
+ suite = super(OETestLoader, self).discover(path,
+ pattern='*.py', top_level_dir=path)
+ big_suite.addTests(suite)
+
+ cases = None
+ discover_classes = [clss for clss in decoratorClasses
+ if issubclass(clss, OETestDiscover)]
+ for clss in discover_classes:
+ cases = clss.discover(self.tc._registry)
+
+ return self.suiteClass(cases) if cases else big_suite
+
+ # XXX After Python 3.5, remove backward compatibility hacks for
+ # use_load_tests deprecation via *args and **kws. See issue 16662.
+ if sys.version_info >= (3,5):
+ def loadTestsFromModule(self, module, *args, pattern=None, **kws):
+ if not self.modules or "all" in self.modules or \
+ module.__name__ in self.modules:
+ return super(OETestLoader, self).loadTestsFromModule(
+ module, *args, pattern=pattern, **kws)
+ else:
+ return self.suiteClass()
+ else:
+ def loadTestsFromModule(self, module, use_load_tests=True):
+ """
+ Returns a suite of all tests cases contained in module.
+ """
+ if not self.modules or "all" in self.modules or \
+ module.__name__ in self.modules:
+ return super(OETestLoader, self).loadTestsFromModule(
+ module, use_load_tests)
+ else:
+ return self.suiteClass()
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 04/30] oeqa/core/decorator: Add support for OETestDepends
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (2 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 03/30] oeqa/core: Add loader, context and decorator modules Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 05/30] oeqa/core/decorator: Add support for OETestID and OETestTag Aníbal Limón
` (25 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
The OETestDepends decorator could be used over test cases to
define some dependency between them.
At loading time sorting the tests to grauntee that a test case
executes before also raise an exception if found a circular
dependency between test cases.
At before test case run reviews if the dependency if meet, in the
case of don't it skips the test case run.
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/core/decorator/depends.py | 94 +++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
create mode 100644 meta/lib/oeqa/core/decorator/depends.py
diff --git a/meta/lib/oeqa/core/decorator/depends.py b/meta/lib/oeqa/core/decorator/depends.py
new file mode 100644
index 0000000..195711c
--- /dev/null
+++ b/meta/lib/oeqa/core/decorator/depends.py
@@ -0,0 +1,94 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from unittest import SkipTest
+
+from oeqa.core.exception import OEQADependency
+
+from . import OETestDiscover, registerDecorator
+
+def _add_depends(registry, case, depends):
+ module_name = case.__module__
+ class_name = case.__class__.__name__
+
+ case_id = case.id()
+
+ for depend in depends:
+ dparts = depend.split('.')
+
+ if len(dparts) == 1:
+ depend_id = ".".join((module_name, class_name, dparts[0]))
+ elif len(dparts) == 2:
+ depend_id = ".".join((module_name, dparts[0], dparts[1]))
+ else:
+ depend_id = depend
+
+ if not case_id in registry:
+ registry[case_id] = []
+ if not depend_id in registry[case_id]:
+ registry[case_id].append(depend_id)
+
+def _validate_test_case_depends(cases, depends):
+ for case in depends:
+ if not case in cases:
+ continue
+ for dep in depends[case]:
+ if not dep in cases:
+ raise OEQADependency("TestCase %s depends on %s and isn't available"\
+ ", cases available %s." % (case, dep, str(cases.keys())))
+
+def _order_test_case_by_depends(cases, depends):
+ def _dep_resolve(graph, node, resolved, seen):
+ seen.append(node)
+ for edge in graph[node]:
+ if edge not in resolved:
+ if edge in seen:
+ raise OEQADependency("Test cases %s and %s have a circular" \
+ " dependency." % (node, edge))
+ _dep_resolve(graph, edge, resolved, seen)
+ resolved.append(node)
+
+ dep_graph = {}
+ dep_graph['__root__'] = cases.keys()
+ for case in cases:
+ if case in depends:
+ dep_graph[case] = depends[case]
+ else:
+ dep_graph[case] = []
+
+ cases_ordered = []
+ _dep_resolve(dep_graph, '__root__', cases_ordered, [])
+ cases_ordered.remove('__root__')
+
+ return [cases[case_id] for case_id in cases_ordered]
+
+def _skipTestDependency(case, depends):
+ results = case.tc._results
+ skipReasons = ['errors', 'failures', 'skipped']
+
+ for reason in skipReasons:
+ for test, _ in results[reason]:
+ if test.id() in depends:
+ raise SkipTest("Test case %s depends on %s and was in %s." \
+ % (case.id(), test.id(), reason))
+
+@registerDecorator
+class OETestDepends(OETestDiscover):
+ attrs = ('depends',)
+
+ def bind(self, registry, case):
+ super(OETestDepends, self).bind(registry, case)
+ if not registry.get('depends'):
+ registry['depends'] = {}
+ _add_depends(registry['depends'], case, self.depends)
+
+ @staticmethod
+ def discover(registry):
+ if registry.get('depends'):
+ _validate_test_case_depends(registry['cases'], registry['depends'])
+ return _order_test_case_by_depends(registry['cases'], registry['depends'])
+ else:
+ return [registry['cases'][case_id] for case_id in registry['cases']]
+
+ def setUpDecorator(self):
+ _skipTestDependency(self.case, self.depends)
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 05/30] oeqa/core/decorator: Add support for OETestID and OETestTag
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (3 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 04/30] oeqa/core/decorator: Add support for OETestDepends Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 06/30] oeqa/core/decorator: Add support for OETimeout decorator Aníbal Limón
` (24 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
From: Mariano Lopez <mariano.lopez@linux.intel.com>
These two decorators stores certain TAG or ID for the test case
also provides support for filtering in loading step.
[YOCTO #10236]
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/lib/oeqa/core/decorator/oeid.py | 23 +++++++++++++++++++++++
meta/lib/oeqa/core/decorator/oetag.py | 24 ++++++++++++++++++++++++
2 files changed, 47 insertions(+)
create mode 100644 meta/lib/oeqa/core/decorator/oeid.py
create mode 100644 meta/lib/oeqa/core/decorator/oetag.py
diff --git a/meta/lib/oeqa/core/decorator/oeid.py b/meta/lib/oeqa/core/decorator/oeid.py
new file mode 100644
index 0000000..ea8017a
--- /dev/null
+++ b/meta/lib/oeqa/core/decorator/oeid.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from . import OETestFilter, registerDecorator
+from oeqa.core.utils.misc import intToList
+
+def _idFilter(oeid, filters):
+ return False if oeid in filters else True
+
+@registerDecorator
+class OETestID(OETestFilter):
+ attrs = ('oeid',)
+
+ def bind(self, registry, case):
+ super(OETestID, self).bind(registry, case)
+
+ def filtrate(self, filters):
+ if filters.get('oeid'):
+ filterx = intToList(filters['oeid'], 'oeid')
+ del filters['oeid']
+ if _idFilter(self.oeid, filterx):
+ return True
+ return False
diff --git a/meta/lib/oeqa/core/decorator/oetag.py b/meta/lib/oeqa/core/decorator/oetag.py
new file mode 100644
index 0000000..ad38ab7
--- /dev/null
+++ b/meta/lib/oeqa/core/decorator/oetag.py
@@ -0,0 +1,24 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from . import OETestFilter, registerDecorator
+from oeqa.core.utils.misc import strToList
+
+def _tagFilter(tags, filters):
+ return False if set(tags) & set(filters) else True
+
+@registerDecorator
+class OETestTag(OETestFilter):
+ attrs = ('oetag',)
+
+ def bind(self, registry, case):
+ super(OETestTag, self).bind(registry, case)
+ self.oetag = strToList(self.oetag, 'oetag')
+
+ def filtrate(self, filters):
+ if filters.get('oetag'):
+ filterx = strToList(filters['oetag'], 'oetag')
+ del filters['oetag']
+ if _tagFilter(self.oetag, filterx):
+ return True
+ return False
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 06/30] oeqa/core/decorator: Add support for OETimeout decorator
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (4 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 05/30] oeqa/core/decorator: Add support for OETestID and OETestTag Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 07/30] oeqa/core/decorator: Add support for OETestDataDepends and skipIfDataVar Aníbal Limón
` (23 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
From: Mariano Lopez <mariano.lopez@linux.intel.com>
The OETimeout provides support for specify certain timeout
in seconds for a test case, if the timeout is reach the SIGALRM
is sent and an exception is raised to notify the timeout.
[YOCTO #10235]
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/lib/oeqa/core/decorator/oetimeout.py | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 meta/lib/oeqa/core/decorator/oetimeout.py
diff --git a/meta/lib/oeqa/core/decorator/oetimeout.py b/meta/lib/oeqa/core/decorator/oetimeout.py
new file mode 100644
index 0000000..a247583
--- /dev/null
+++ b/meta/lib/oeqa/core/decorator/oetimeout.py
@@ -0,0 +1,25 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import signal
+from . import OETestDecorator, registerDecorator
+from oeqa.core.exception import OEQATimeoutError
+
+@registerDecorator
+class OETimeout(OETestDecorator):
+ attrs = ('oetimeout',)
+
+ def setUpDecorator(self):
+ timeout = self.oetimeout
+ def _timeoutHandler(signum, frame):
+ raise OEQATimeoutError("Timed out after %s "
+ "seconds of execution" % timeout)
+
+ self.logger.debug("Setting up a %d second(s) timeout" % self.oetimeout)
+ self.alarmSignal = signal.signal(signal.SIGALRM, _timeoutHandler)
+ signal.alarm(self.oetimeout)
+
+ def tearDownDecorator(self):
+ signal.alarm(0)
+ signal.signal(signal.SIGALRM, self.alarmSignal)
+ self.logger.debug("Removed SIGALRM handler")
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 07/30] oeqa/core/decorator: Add support for OETestDataDepends and skipIfDataVar
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (5 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 06/30] oeqa/core/decorator: Add support for OETimeout decorator Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 08/30] oeqa/core: Add tests for the OEQA framework Aníbal Limón
` (22 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
The OETestDataDepends decorator skips a test case if a variable
isn't into test data (d).
The skipIfDataVar decorator skips a test case if a variable
has certain value.
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/core/decorator/data.py | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 meta/lib/oeqa/core/decorator/data.py
diff --git a/meta/lib/oeqa/core/decorator/data.py b/meta/lib/oeqa/core/decorator/data.py
new file mode 100644
index 0000000..73cca88
--- /dev/null
+++ b/meta/lib/oeqa/core/decorator/data.py
@@ -0,0 +1,36 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from oeqa.core.exception import OEQAMissingVariable
+
+from . import OETestDecorator, registerDecorator
+
+@registerDecorator
+class skipIfDataVar(OETestDecorator):
+ """
+ Skip test based on value of a data store's variable.
+
+ It will get the info of var from the data store and will
+ check it against value; if are equal it will skip the test
+ with msg as the reason.
+ """
+
+ attrs = ('var', 'value', 'msg')
+
+ def setUpDecorator(self):
+ msg = 'Checking if %r value is %r to skip test' % (self.var, self.value)
+ self.logger.debug(msg)
+ if self.case.td.get(self.var) == self.value:
+ self.case.skipTest(self.msg)
+
+@registerDecorator
+class OETestDataDepends(OETestDecorator):
+ attrs = ('td_depends',)
+
+ def setUpDecorator(self):
+ for v in self.td_depends:
+ try:
+ value = self.case.td[v]
+ except KeyError:
+ raise OEQAMissingVariable("Test case need %s variable but"\
+ " isn't into td" % v)
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 08/30] oeqa/core: Add tests for the OEQA framework
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (6 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 07/30] oeqa/core/decorator: Add support for OETestDataDepends and skipIfDataVar Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 09/30] scripts/oe-test: Add new oe-test script Aníbal Limón
` (21 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
From: Mariano Lopez <mariano.lopez@linux.intel.com>
This test suite covers the current functionality for the OEQA
framework.
For run certain test suite,
$ cd meta/lib/oeqa/core/tests
$ ./test_data.py
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/core/tests/__init__.py | 0
meta/lib/oeqa/core/tests/cases/data.py | 20 +++
meta/lib/oeqa/core/tests/cases/depends.py | 38 ++++++
.../oeqa/core/tests/cases/loader/invalid/oeid.py | 15 +++
.../oeqa/core/tests/cases/loader/valid/another.py | 9 ++
meta/lib/oeqa/core/tests/cases/oeid.py | 18 +++
meta/lib/oeqa/core/tests/cases/oetag.py | 18 +++
meta/lib/oeqa/core/tests/cases/timeout.py | 18 +++
meta/lib/oeqa/core/tests/common.py | 35 ++++++
meta/lib/oeqa/core/tests/test_data.py | 51 ++++++++
meta/lib/oeqa/core/tests/test_decorators.py | 135 +++++++++++++++++++++
meta/lib/oeqa/core/tests/test_loader.py | 86 +++++++++++++
meta/lib/oeqa/core/tests/test_runner.py | 38 ++++++
13 files changed, 481 insertions(+)
create mode 100644 meta/lib/oeqa/core/tests/__init__.py
create mode 100644 meta/lib/oeqa/core/tests/cases/data.py
create mode 100644 meta/lib/oeqa/core/tests/cases/depends.py
create mode 100644 meta/lib/oeqa/core/tests/cases/loader/invalid/oeid.py
create mode 100644 meta/lib/oeqa/core/tests/cases/loader/valid/another.py
create mode 100644 meta/lib/oeqa/core/tests/cases/oeid.py
create mode 100644 meta/lib/oeqa/core/tests/cases/oetag.py
create mode 100644 meta/lib/oeqa/core/tests/cases/timeout.py
create mode 100644 meta/lib/oeqa/core/tests/common.py
create mode 100755 meta/lib/oeqa/core/tests/test_data.py
create mode 100755 meta/lib/oeqa/core/tests/test_decorators.py
create mode 100755 meta/lib/oeqa/core/tests/test_loader.py
create mode 100755 meta/lib/oeqa/core/tests/test_runner.py
diff --git a/meta/lib/oeqa/core/tests/__init__.py b/meta/lib/oeqa/core/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/meta/lib/oeqa/core/tests/cases/data.py b/meta/lib/oeqa/core/tests/cases/data.py
new file mode 100644
index 0000000..88003a6
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/data.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator.oetag import OETestTag
+from oeqa.core.decorator.data import OETestDataDepends
+
+class DataTest(OETestCase):
+ data_vars = ['IMAGE', 'ARCH']
+
+ @OETestDataDepends(['MACHINE',])
+ @OETestTag('dataTestOk')
+ def testDataOk(self):
+ self.assertEqual(self.td.get('IMAGE'), 'core-image-minimal')
+ self.assertEqual(self.td.get('ARCH'), 'x86')
+ self.assertEqual(self.td.get('MACHINE'), 'qemuarm')
+
+ @OETestTag('dataTestFail')
+ def testDataFail(self):
+ pass
diff --git a/meta/lib/oeqa/core/tests/cases/depends.py b/meta/lib/oeqa/core/tests/cases/depends.py
new file mode 100644
index 0000000..17cdd90
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/depends.py
@@ -0,0 +1,38 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator.depends import OETestDepends
+
+class DependsTest(OETestCase):
+
+ def testDependsFirst(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsFirst'])
+ def testDependsSecond(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsSecond'])
+ def testDependsThird(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsSecond'])
+ def testDependsFourth(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsThird', 'testDependsFourth'])
+ def testDependsFifth(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsCircular3'])
+ def testDependsCircular1(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsCircular1'])
+ def testDependsCircular2(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestDepends(['testDependsCircular2'])
+ def testDependsCircular3(self):
+ self.assertTrue(True, msg='How is this possible?')
diff --git a/meta/lib/oeqa/core/tests/cases/loader/invalid/oeid.py b/meta/lib/oeqa/core/tests/cases/loader/invalid/oeid.py
new file mode 100644
index 0000000..038d445
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/loader/invalid/oeid.py
@@ -0,0 +1,15 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from oeqa.core.case import OETestCase
+
+class AnotherIDTest(OETestCase):
+
+ def testAnotherIdGood(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ def testAnotherIdOther(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ def testAnotherIdNone(self):
+ self.assertTrue(True, msg='How is this possible?')
diff --git a/meta/lib/oeqa/core/tests/cases/loader/valid/another.py b/meta/lib/oeqa/core/tests/cases/loader/valid/another.py
new file mode 100644
index 0000000..c9ffd17
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/loader/valid/another.py
@@ -0,0 +1,9 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from oeqa.core.case import OETestCase
+
+class AnotherTest(OETestCase):
+
+ def testAnother(self):
+ self.assertTrue(True, msg='How is this possible?')
diff --git a/meta/lib/oeqa/core/tests/cases/oeid.py b/meta/lib/oeqa/core/tests/cases/oeid.py
new file mode 100644
index 0000000..c2d3d32
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/oeid.py
@@ -0,0 +1,18 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator.oeid import OETestID
+
+class IDTest(OETestCase):
+
+ @OETestID(101)
+ def testIdGood(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestID(102)
+ def testIdOther(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ def testIdNone(self):
+ self.assertTrue(True, msg='How is this possible?')
diff --git a/meta/lib/oeqa/core/tests/cases/oetag.py b/meta/lib/oeqa/core/tests/cases/oetag.py
new file mode 100644
index 0000000..0cae02e
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/oetag.py
@@ -0,0 +1,18 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator.oetag import OETestTag
+
+class TagTest(OETestCase):
+
+ @OETestTag('goodTag')
+ def testTagGood(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETestTag('otherTag')
+ def testTagOther(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ def testTagNone(self):
+ self.assertTrue(True, msg='How is this possible?')
diff --git a/meta/lib/oeqa/core/tests/cases/timeout.py b/meta/lib/oeqa/core/tests/cases/timeout.py
new file mode 100644
index 0000000..870c3157
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/cases/timeout.py
@@ -0,0 +1,18 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from time import sleep
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator.oetimeout import OETimeout
+
+class TimeoutTest(OETestCase):
+
+ @OETimeout(1)
+ def testTimeoutPass(self):
+ self.assertTrue(True, msg='How is this possible?')
+
+ @OETimeout(1)
+ def testTimeoutFail(self):
+ sleep(2)
+ self.assertTrue(True, msg='How is this possible?')
diff --git a/meta/lib/oeqa/core/tests/common.py b/meta/lib/oeqa/core/tests/common.py
new file mode 100644
index 0000000..52b18a1
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/common.py
@@ -0,0 +1,35 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import sys
+import os
+
+import unittest
+import logging
+import os
+
+logger = logging.getLogger("oeqa")
+logger.setLevel(logging.INFO)
+consoleHandler = logging.StreamHandler()
+formatter = logging.Formatter('OEQATest: %(message)s')
+consoleHandler.setFormatter(formatter)
+logger.addHandler(consoleHandler)
+
+def setup_sys_path():
+ directory = os.path.dirname(os.path.abspath(__file__))
+ oeqa_lib = os.path.realpath(os.path.join(directory, '../../../'))
+ if not oeqa_lib in sys.path:
+ sys.path.insert(0, oeqa_lib)
+
+class TestBase(unittest.TestCase):
+ def setUp(self):
+ self.logger = logger
+ directory = os.path.dirname(os.path.abspath(__file__))
+ self.cases_path = os.path.join(directory, 'cases')
+
+ def _testLoader(self, d={}, modules=[], tests=[], filters={}):
+ from oeqa.core.context import OETestContext
+ tc = OETestContext(d, self.logger)
+ tc.loadTests(self.cases_path, modules=modules, tests=tests,
+ filters=filters)
+ return tc
diff --git a/meta/lib/oeqa/core/tests/test_data.py b/meta/lib/oeqa/core/tests/test_data.py
new file mode 100755
index 0000000..320468c
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/test_data.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import unittest
+import logging
+import os
+
+from common import setup_sys_path, TestBase
+setup_sys_path()
+
+from oeqa.core.exception import OEQAMissingVariable
+from oeqa.core.utils.test import getCaseMethod, getSuiteCasesNames
+
+class TestData(TestBase):
+ modules = ['data']
+
+ def test_data_fail_missing_variable(self):
+ expectedException = "oeqa.core.exception.OEQAMissingVariable"
+
+ tc = self._testLoader(modules=self.modules)
+ self.assertEqual(False, tc.runTests().wasSuccessful())
+ for test, data in tc._results['errors']:
+ expect = False
+ if expectedException in data:
+ expect = True
+
+ self.assertTrue(expect)
+
+ def test_data_fail_wrong_variable(self):
+ expectedError = 'AssertionError'
+ d = {'IMAGE' : 'core-image-sato', 'ARCH' : 'arm'}
+
+ tc = self._testLoader(d=d, modules=self.modules)
+ self.assertEqual(False, tc.runTests().wasSuccessful())
+ for test, data in tc._results['failures']:
+ expect = False
+ if expectedError in data:
+ expect = True
+
+ self.assertTrue(expect)
+
+ def test_data_ok(self):
+ d = {'IMAGE' : 'core-image-minimal', 'ARCH' : 'x86', 'MACHINE' : 'qemuarm'}
+
+ tc = self._testLoader(d=d, modules=self.modules)
+ self.assertEqual(True, tc.runTests().wasSuccessful())
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/meta/lib/oeqa/core/tests/test_decorators.py b/meta/lib/oeqa/core/tests/test_decorators.py
new file mode 100755
index 0000000..f7d11e8
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/test_decorators.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import signal
+import unittest
+
+from common import setup_sys_path, TestBase
+setup_sys_path()
+
+from oeqa.core.exception import OEQADependency
+from oeqa.core.utils.test import getCaseMethod, getSuiteCasesNames, getSuiteCasesIDs
+
+class TestFilterDecorator(TestBase):
+
+ def _runFilterTest(self, modules, filters, expect, msg):
+ tc = self._testLoader(modules=modules, filters=filters)
+ test_loaded = set(getSuiteCasesNames(tc.suites))
+ self.assertEqual(expect, test_loaded, msg=msg)
+
+ def test_oetag(self):
+ # Get all cases without filtering.
+ filter_all = {}
+ test_all = {'testTagGood', 'testTagOther', 'testTagNone'}
+ msg_all = 'Failed to get all oetag cases without filtering.'
+
+ # Get cases with 'goodTag'.
+ filter_good = {'oetag':'goodTag'}
+ test_good = {'testTagGood'}
+ msg_good = 'Failed to get just one test filtering with "goodTag" oetag.'
+
+ # Get cases with an invalid tag.
+ filter_invalid = {'oetag':'invalidTag'}
+ test_invalid = set()
+ msg_invalid = 'Failed to filter all test using an invalid oetag.'
+
+ tests = ((filter_all, test_all, msg_all),
+ (filter_good, test_good, msg_good),
+ (filter_invalid, test_invalid, msg_invalid))
+
+ for test in tests:
+ self._runFilterTest(['oetag'], test[0], test[1], test[2])
+
+ def test_oeid(self):
+ # Get all cases without filtering.
+ filter_all = {}
+ test_all = {'testIdGood', 'testIdOther', 'testIdNone'}
+ msg_all = 'Failed to get all oeid cases without filtering.'
+
+ # Get cases with '101' oeid.
+ filter_good = {'oeid': 101}
+ test_good = {'testIdGood'}
+ msg_good = 'Failed to get just one tes filtering with "101" oeid.'
+
+ # Get cases with an invalid id.
+ filter_invalid = {'oeid':999}
+ test_invalid = set()
+ msg_invalid = 'Failed to filter all test using an invalid oeid.'
+
+ tests = ((filter_all, test_all, msg_all),
+ (filter_good, test_good, msg_good),
+ (filter_invalid, test_invalid, msg_invalid))
+
+ for test in tests:
+ self._runFilterTest(['oeid'], test[0], test[1], test[2])
+
+class TestDependsDecorator(TestBase):
+ modules = ['depends']
+
+ def test_depends_order(self):
+ tests = ['depends.DependsTest.testDependsFirst',
+ 'depends.DependsTest.testDependsSecond',
+ 'depends.DependsTest.testDependsThird',
+ 'depends.DependsTest.testDependsFourth',
+ 'depends.DependsTest.testDependsFifth']
+ tests2 = list(tests)
+ tests2[2], tests2[3] = tests[3], tests[2]
+ tc = self._testLoader(modules=self.modules, tests=tests)
+ test_loaded = getSuiteCasesIDs(tc.suites)
+ result = True if test_loaded == tests or test_loaded == tests2 else False
+ msg = 'Failed to order tests using OETestDepends decorator.\nTest order:'\
+ ' %s.\nExpected: %s\nOr: %s' % (test_loaded, tests, tests2)
+ self.assertTrue(result, msg=msg)
+
+ def test_depends_fail_missing_dependency(self):
+ expect = "TestCase depends.DependsTest.testDependsSecond depends on "\
+ "depends.DependsTest.testDependsFirst and isn't available"
+ tests = ['depends.DependsTest.testDependsSecond']
+ try:
+ # Must throw OEQADependency because missing 'testDependsFirst'
+ tc = self._testLoader(modules=self.modules, tests=tests)
+ self.fail('Expected OEQADependency exception')
+ except OEQADependency as e:
+ result = True if expect in str(e) else False
+ msg = 'Expected OEQADependency exception missing testDependsFirst test'
+ self.assertTrue(result, msg=msg)
+
+ def test_depends_fail_circular_dependency(self):
+ expect = 'have a circular dependency'
+ tests = ['depends.DependsTest.testDependsCircular1',
+ 'depends.DependsTest.testDependsCircular2',
+ 'depends.DependsTest.testDependsCircular3']
+ try:
+ # Must throw OEQADependency because circular dependency
+ tc = self._testLoader(modules=self.modules, tests=tests)
+ self.fail('Expected OEQADependency exception')
+ except OEQADependency as e:
+ result = True if expect in str(e) else False
+ msg = 'Expected OEQADependency exception having a circular dependency'
+ self.assertTrue(result, msg=msg)
+
+class TestTimeoutDecorator(TestBase):
+ modules = ['timeout']
+
+ def test_timeout(self):
+ tests = ['timeout.TimeoutTest.testTimeoutPass']
+ msg = 'Failed to run test using OETestTimeout'
+ alarm_signal = signal.getsignal(signal.SIGALRM)
+ tc = self._testLoader(modules=self.modules, tests=tests)
+ self.assertTrue(tc.runTests().wasSuccessful(), msg=msg)
+ msg = "OETestTimeout didn't restore SIGALRM"
+ self.assertIs(alarm_signal, signal.getsignal(signal.SIGALRM), msg=msg)
+
+ def test_timeout_fail(self):
+ tests = ['timeout.TimeoutTest.testTimeoutFail']
+ msg = "OETestTimeout test didn't timeout as expected"
+ alarm_signal = signal.getsignal(signal.SIGALRM)
+ tc = self._testLoader(modules=self.modules, tests=tests)
+ self.assertFalse(tc.runTests().wasSuccessful(), msg=msg)
+ msg = "OETestTimeout didn't restore SIGALRM"
+ self.assertIs(alarm_signal, signal.getsignal(signal.SIGALRM), msg=msg)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/meta/lib/oeqa/core/tests/test_loader.py b/meta/lib/oeqa/core/tests/test_loader.py
new file mode 100755
index 0000000..b79b8ba
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/test_loader.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import os
+import unittest
+
+from common import setup_sys_path, TestBase
+setup_sys_path()
+
+from oeqa.core.exception import OEQADependency
+from oeqa.core.utils.test import getSuiteModules, getSuiteCasesIDs
+
+class TestLoader(TestBase):
+
+ def test_fail_empty_filter(self):
+ filters = {'oetag' : ''}
+ expect = 'Filter oetag specified is empty'
+ msg = 'Expected TypeError exception for having invalid filter'
+ try:
+ # Must throw TypeError because empty filter
+ tc = self._testLoader(filters=filters)
+ self.fail(msg)
+ except TypeError as e:
+ result = True if expect in str(e) else False
+ self.assertTrue(result, msg=msg)
+
+ def test_fail_invalid_filter(self):
+ filters = {'invalid' : 'good'}
+ expect = 'filter but not declared in any of'
+ msg = 'Expected TypeError exception for having invalid filter'
+ try:
+ # Must throw TypeError because invalid filter
+ tc = self._testLoader(filters=filters)
+ self.fail(msg)
+ except TypeError as e:
+ result = True if expect in str(e) else False
+ self.assertTrue(result, msg=msg)
+
+ def test_fail_duplicated_module(self):
+ cases_path = self.cases_path
+ invalid_path = os.path.join(cases_path, 'loader', 'invalid')
+ self.cases_path = [self.cases_path, invalid_path]
+ expect = 'Duplicated oeid module found in'
+ msg = 'Expected ImportError exception for having duplicated module'
+ try:
+ # Must throw ImportEror because duplicated module
+ tc = self._testLoader()
+ self.fail(msg)
+ except ImportError as e:
+ result = True if expect in str(e) else False
+ self.assertTrue(result, msg=msg)
+ finally:
+ self.cases_path = cases_path
+
+ def test_filter_modules(self):
+ expected_modules = {'oeid', 'oetag'}
+ tc = self._testLoader(modules=expected_modules)
+ modules = getSuiteModules(tc.suites)
+ msg = 'Expected just %s modules' % ', '.join(expected_modules)
+ self.assertEqual(modules, expected_modules, msg=msg)
+
+ def test_filter_cases(self):
+ modules = ['oeid', 'oetag', 'data']
+ expected_cases = {'data.DataTest.testDataOk',
+ 'oetag.TagTest.testTagGood',
+ 'oeid.IDTest.testIdGood'}
+ tc = self._testLoader(modules=modules, tests=expected_cases)
+ cases = set(getSuiteCasesIDs(tc.suites))
+ msg = 'Expected just %s cases' % ', '.join(expected_cases)
+ self.assertEqual(cases, expected_cases, msg=msg)
+
+ def test_import_from_paths(self):
+ cases_path = self.cases_path
+ cases2_path = os.path.join(cases_path, 'loader', 'valid')
+ expected_modules = {'oeid', 'another'}
+ self.cases_path = [self.cases_path, cases2_path]
+ tc = self._testLoader(modules=expected_modules)
+ modules = getSuiteModules(tc.suites)
+ self.cases_path = cases_path
+ msg = 'Expected modules from two different paths'
+ self.assertEqual(modules, expected_modules, msg=msg)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/meta/lib/oeqa/core/tests/test_runner.py b/meta/lib/oeqa/core/tests/test_runner.py
new file mode 100755
index 0000000..a3f3861
--- /dev/null
+++ b/meta/lib/oeqa/core/tests/test_runner.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import unittest
+import logging
+import tempfile
+
+from common import setup_sys_path, TestBase
+setup_sys_path()
+
+from oeqa.core.runner import OEStreamLogger
+
+class TestRunner(TestBase):
+ def test_stream_logger(self):
+ fp = tempfile.TemporaryFile(mode='w+')
+
+ logging.basicConfig(format='%(message)s', stream=fp)
+ logger = logging.getLogger()
+ logger.setLevel(logging.INFO)
+
+ oeSL = OEStreamLogger(logger)
+
+ lines = ['init', 'bigline_' * 65535, 'morebigline_' * 65535 * 4, 'end']
+ for line in lines:
+ oeSL.write(line)
+
+ fp.seek(0)
+ fp_lines = fp.readlines()
+ for i, fp_line in enumerate(fp_lines):
+ fp_line = fp_line.strip()
+ self.assertEqual(lines[i], fp_line)
+
+ fp.close()
+
+if __name__ == '__main__':
+ unittest.main()
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 09/30] scripts/oe-test: Add new oe-test script
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (7 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 08/30] oeqa/core: Add tests for the OEQA framework Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 10/30] oeqa/core/context: Add support of OETestContextExecutor Aníbal Limón
` (20 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
The new oe-test script will be use to run test components with
one single script.
The oe-test script search for test components inside meta/lib/oeqa,
the test components needs to implement OETestContextExecutor inside
context module in order to be supported by oe-test.
[YOCTO #10230]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
scripts/oe-test | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 98 insertions(+)
create mode 100755 scripts/oe-test
diff --git a/scripts/oe-test b/scripts/oe-test
new file mode 100755
index 0000000..9222dea
--- /dev/null
+++ b/scripts/oe-test
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+
+# OpenEmbedded test tool
+#
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import os
+import sys
+import argparse
+import importlib
+import logging
+
+scripts_path = os.path.dirname(os.path.realpath(__file__))
+lib_path = scripts_path + '/lib'
+sys.path = sys.path + [lib_path]
+import argparse_oe
+import scriptutils
+import scriptpath
+scriptpath.add_oe_lib_path()
+
+from oeqa.core.context import OETestContextExecutor
+
+logger = scriptutils.logger_create('oe-test')
+
+def _load_test_components(logger):
+ components = {}
+
+ for path in sys.path:
+ base_dir = os.path.join(path, 'oeqa')
+ if os.path.exists(base_dir) and os.path.isdir(base_dir):
+ for file in os.listdir(base_dir):
+ comp_name = file
+ comp_context = os.path.join(base_dir, file, 'context.py')
+ if os.path.exists(comp_context):
+ comp_plugin = importlib.import_module('oeqa.%s.%s' % \
+ (comp_name, 'context'))
+ try:
+ if not issubclass(comp_plugin._executor_class,
+ OETestContextExecutor):
+ raise TypeError("Component %s in %s, _executor_class "\
+ "isn't derived from OETestContextExecutor."\
+ % (comp_name, comp_context))
+
+ components[comp_name] = comp_plugin._executor_class()
+ except AttributeError:
+ raise AttributeError("Component %s in %s don't have "\
+ "_executor_class defined." % (comp_name, comp_context))
+
+ return components
+
+def main():
+ parser = argparse_oe.ArgumentParser(description="OpenEmbedded test tool",
+ add_help=False,
+ epilog="Use %(prog)s <subcommand> --help to get help on a specific command")
+ parser.add_argument('-d', '--debug', help='Enable debug output', action='store_true')
+ parser.add_argument('-q', '--quiet', help='Print only errors', action='store_true')
+ global_args, unparsed_args = parser.parse_known_args()
+
+ # Help is added here rather than via add_help=True, as we don't want it to
+ # be handled by parse_known_args()
+ parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS,
+ help='show this help message and exit')
+
+ if global_args.debug:
+ logger.setLevel(logging.DEBUG)
+ elif global_args.quiet:
+ logger.setLevel(logging.ERROR)
+
+ components = _load_test_components(logger)
+
+ subparsers = parser.add_subparsers(dest="subparser_name", title='subcommands', metavar='<subcommand>')
+ subparsers.add_subparser_group('components', 'Test components')
+ subparsers.required = True
+ for comp_name in sorted(components.keys()):
+ comp = components[comp_name]
+ comp.register_commands(logger, subparsers)
+
+ try:
+ args = parser.parse_args(unparsed_args, namespace=global_args)
+ ret = args.func(logger, args)
+ except SystemExit as err:
+ if err.code != 0:
+ raise err
+ ret = err.code
+ except argparse_oe.ArgumentUsageError as ae:
+ parser.error_subcommand(ae.message, ae.subcommand)
+
+ return ret
+
+if __name__ == '__main__':
+ try:
+ ret = main()
+ except Exception:
+ ret = 1
+ import traceback
+ traceback.print_exc()
+ sys.exit(ret)
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 10/30] oeqa/core/context: Add support of OETestContextExecutor
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (8 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 09/30] scripts/oe-test: Add new oe-test script Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 11/30] oeqa/core/cases: Add example test cases Aníbal Limón
` (19 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
The OETestContextExecutor class supports to use oe-test for run core
test component also is a base class for the other test components
(runtime, sdk, selftest).
Te principal functionality is to support cmdline parsing and execution
of OETestContext, the test components could extend the common options
to provide specific ones. The common options between test components
are test data file, output log and test cases path's to scan.
Also it initializes the logger to be passed to the whole OEQA framework.
[YOCTO #10230]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/core/context.py | 85 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 85 insertions(+)
diff --git a/meta/lib/oeqa/core/context.py b/meta/lib/oeqa/core/context.py
index 3499994..316f90f 100644
--- a/meta/lib/oeqa/core/context.py
+++ b/meta/lib/oeqa/core/context.py
@@ -138,3 +138,88 @@ class OETestContext(object):
self.logger.info("RESULTS - %s - Testcase %s: %s" % (case.id(),
case.oe_id if hasattr(case, 'oeid') else '-1',
'PASSED'))
+
+class OETestContextExecutor(object):
+ _context_class = OETestContext
+
+ name = 'core'
+ help = 'core test component example'
+ description = 'executes core test suite example'
+
+ default_cases = [os.path.join(os.path.abspath(os.path.dirname(__file__)),
+ 'cases/example')]
+ default_test_data = os.path.join(default_cases[0], 'data.json')
+
+ def register_commands(self, logger, subparsers):
+ self.parser = subparsers.add_parser(self.name, help=self.help,
+ description=self.description, group='components')
+
+ self.default_output_log = '%s-results-%s.log' % (self.name,
+ time.strftime("%Y%m%d%H%M%S"))
+ self.parser.add_argument('--output-log', action='store',
+ default=self.default_output_log,
+ help="results output log, default: %s" % self.default_output_log)
+
+ if self.default_test_data:
+ self.parser.add_argument('--test-data-file', action='store',
+ default=self.default_test_data,
+ help="data file to load, default: %s" % self.default_test_data)
+ else:
+ self.parser.add_argument('--test-data-file', action='store',
+ help="data file to load")
+
+ if self.default_cases:
+ self.parser.add_argument('CASES_PATHS', action='store',
+ default=self.default_cases, nargs='*',
+ help="paths to directories with test cases, default: %s"\
+ % self.default_cases)
+ else:
+ self.parser.add_argument('CASES_PATHS', action='store',
+ nargs='+', help="paths to directories with test cases")
+
+ self.parser.set_defaults(func=self.run)
+
+ def _setup_logger(self, logger, args):
+ formatter = logging.Formatter('%(asctime)s - ' + self.name + \
+ ' - %(levelname)s - %(message)s')
+ sh = logger.handlers[0]
+ sh.setFormatter(formatter)
+ fh = logging.FileHandler(args.output_log)
+ fh.setFormatter(formatter)
+ logger.addHandler(fh)
+
+ return logger
+
+ def _process_args(self, logger, args):
+ self.tc_kwargs = {}
+ self.tc_kwargs['init'] = {}
+ self.tc_kwargs['load'] = {}
+ self.tc_kwargs['run'] = {}
+
+ self.tc_kwargs['init']['logger'] = self._setup_logger(logger, args)
+ if args.test_data_file:
+ self.tc_kwargs['init']['td'] = json.load(
+ open(args.test_data_file, "r"))
+ else:
+ self.tc_kwargs['init']['td'] = {}
+
+ self.module_paths = args.CASES_PATHS
+
+ def run(self, logger, args):
+ self._process_args(logger, args)
+
+ self.tc = self._context_class(**self.tc_kwargs['init'])
+ self.tc.loadTests(self.module_paths, **self.tc_kwargs['load'])
+ rc = self.tc.runTests(**self.tc_kwargs['run'])
+ self.tc.logSummary(rc, self.name)
+ self.tc.logDetails()
+
+ output_link = os.path.join(os.path.dirname(args.output_log),
+ "%s-results.log" % self.name)
+ if os.path.exists(output_link):
+ os.remove(output_link)
+ os.symlink(args.output_log, output_link)
+
+ return rc
+
+_executor_class = OETestContextExecutor
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 11/30] oeqa/core/cases: Add example test cases
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (9 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 10/30] oeqa/core/context: Add support of OETestContextExecutor Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 12/30] oeqa/core: Add README Aníbal Limón
` (18 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
Serves as an first input of how to the OEQA framework works.
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/core/cases/__init__.py | 0
meta/lib/oeqa/core/cases/example/data.json | 1 +
meta/lib/oeqa/core/cases/example/test_basic.py | 20 ++++++++++++++++++++
3 files changed, 21 insertions(+)
create mode 100644 meta/lib/oeqa/core/cases/__init__.py
create mode 100644 meta/lib/oeqa/core/cases/example/data.json
create mode 100644 meta/lib/oeqa/core/cases/example/test_basic.py
diff --git a/meta/lib/oeqa/core/cases/__init__.py b/meta/lib/oeqa/core/cases/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/meta/lib/oeqa/core/cases/example/data.json b/meta/lib/oeqa/core/cases/example/data.json
new file mode 100644
index 0000000..21d6b16
--- /dev/null
+++ b/meta/lib/oeqa/core/cases/example/data.json
@@ -0,0 +1 @@
+{"ARCH": "x86", "IMAGE": "core-image-minimal"}
\ No newline at end of file
diff --git a/meta/lib/oeqa/core/cases/example/test_basic.py b/meta/lib/oeqa/core/cases/example/test_basic.py
new file mode 100644
index 0000000..11cf380
--- /dev/null
+++ b/meta/lib/oeqa/core/cases/example/test_basic.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from oeqa.core.case import OETestCase
+from oeqa.core.decorator.depends import OETestDepends
+
+class OETestExample(OETestCase):
+ def test_example(self):
+ self.logger.info('IMAGE: %s' % self.td.get('IMAGE'))
+ self.assertEqual('core-image-minimal', self.td.get('IMAGE'))
+ self.logger.info('ARCH: %s' % self.td.get('ARCH'))
+ self.assertEqual('x86', self.td.get('ARCH'))
+
+class OETestExampleDepend(OETestCase):
+ @OETestDepends(['OETestExample.test_example'])
+ def test_example_depends(self):
+ pass
+
+ def test_example_no_depends(self):
+ pass
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 12/30] oeqa/core: Add README
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (10 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 11/30] oeqa/core/cases: Add example test cases Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 13/30] oe/data: Add export2json function Aníbal Limón
` (17 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
The README has an introduction and explains how to run the test suite
and creates a new Test component.
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/core/README | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 meta/lib/oeqa/core/README
diff --git a/meta/lib/oeqa/core/README b/meta/lib/oeqa/core/README
new file mode 100644
index 0000000..0c859fd
--- /dev/null
+++ b/meta/lib/oeqa/core/README
@@ -0,0 +1,38 @@
+= OEQA Framework =
+
+== Introduction ==
+
+This is the new OEQA framework the base clases of the framework
+are in this module oeqa/core the subsequent components needs to
+extend this classes.
+
+A new/unique runner was created called oe-test and is under scripts/
+oe-test, this new runner scans over oeqa module searching for test
+components that supports OETestContextExecutor implemented in context
+module (i.e. oeqa/core/context.py).
+
+For execute an example:
+
+$ source oe-init-build-env
+$ oe-test core
+
+For list supported components:
+
+$ oe-test -h
+
+== Create new Test component ==
+
+Usally for add a new Test component the developer needs to extend
+OETestContext/OETestContextExecutor in context.py and OETestCase in
+case.py.
+
+== How to run the testing of the OEQA framework ==
+
+Run all tests:
+
+$ PATH=$PATH:../../ python3 -m unittest discover -s tests
+
+Run some test:
+
+$ cd tests/
+$ ./test_data.py
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 13/30] oe/data: Add export2json function
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (11 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 12/30] oeqa/core: Add README Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 14/30] classes/rootfs-postcommands: Add write_image_test_data Aníbal Limón
` (16 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
The export2json function export the variables contained in
the data store to JSON format, the main usage for now will be
to provide test data to QA framework.
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/lib/oe/data.py | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/meta/lib/oe/data.py b/meta/lib/oe/data.py
index ee48950..db3bd6d 100644
--- a/meta/lib/oe/data.py
+++ b/meta/lib/oe/data.py
@@ -1,3 +1,4 @@
+import json
import oe.maketype
def typed_value(key, d):
@@ -15,3 +16,30 @@ def typed_value(key, d):
return oe.maketype.create(d.getVar(key, True) or '', var_type, **flags)
except (TypeError, ValueError) as exc:
bb.msg.fatal("Data", "%s: %s" % (key, str(exc)))
+
+def export2json(d, json_file, expand=True):
+ data2export = {}
+ keys2export = []
+
+ for key in d.keys():
+ if key.startswith("_"):
+ continue
+ elif key.startswith("BB"):
+ continue
+ elif key.startswith("B_pn"):
+ continue
+ elif key.startswith("do_"):
+ continue
+ elif d.getVarFlag(key, "func", True):
+ continue
+
+ keys2export.append(key)
+
+ for key in keys2export:
+ try:
+ data2export[key] = d.getVar(key, expand)
+ except bb.data_smart.ExpansionError:
+ data2export[key] = ''
+
+ with open(json_file, "w") as f:
+ json.dump(data2export, f, skipkeys=True, indent=4, sort_keys=True)
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 14/30] classes/rootfs-postcommands: Add write_image_test_data
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (12 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 13/30] oe/data: Add export2json function Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 15/30] classes/populate_sdk_base: Add write_sdk_test_data to postprocess Aníbal Limón
` (15 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
This function will generates testdata.json by image type.
[YOCTO #10231]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/classes/rootfs-postcommands.bbclass | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/meta/classes/rootfs-postcommands.bbclass b/meta/classes/rootfs-postcommands.bbclass
index 0c7ceea..5cfd2fe 100644
--- a/meta/classes/rootfs-postcommands.bbclass
+++ b/meta/classes/rootfs-postcommands.bbclass
@@ -14,6 +14,9 @@ ROOTFS_POSTPROCESS_COMMAND += "rootfs_update_timestamp ; "
# Tweak the mount options for rootfs in /etc/fstab if read-only-rootfs is enabled
ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", "read_only_rootfs_hook; ", "",d)}'
+# Generates test data file with data store variables expanded in json format
+ROOTFS_POSTPROCESS_COMMAND += "write_image_test_data ; "
+
# Write manifest
IMAGE_MANIFEST = "${IMGDEPLOYDIR}/${IMAGE_NAME}.rootfs.manifest"
ROOTFS_POSTUNINSTALL_COMMAND =+ "write_image_manifest ; "
@@ -278,3 +281,18 @@ rootfs_check_host_user_contaminated () {
rootfs_sysroot_relativelinks () {
sysroot-relativelinks.py ${SDK_OUTPUT}/${SDKTARGETSYSROOT}
}
+
+# Generated test data json file
+python write_image_test_data() {
+ from oe.data import export2json
+
+ testdata = "%s/%s.testdata.json" % (d.getVar('DEPLOY_DIR_IMAGE', True), d.getVar('IMAGE_NAME', True))
+ testdata_link = "%s/%s.testdata.json" % (d.getVar('DEPLOY_DIR_IMAGE', True), d.getVar('IMAGE_LINK_NAME', True))
+
+ bb.utils.mkdirhier(os.path.dirname(testdata))
+ export2json(d, testdata)
+
+ if os.path.lexists(testdata_link):
+ os.remove(testdata_link)
+ os.symlink(os.path.basename(testdata), testdata_link)
+}
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 15/30] classes/populate_sdk_base: Add write_sdk_test_data to postprocess
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (13 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 14/30] classes/rootfs-postcommands: Add write_image_test_data Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 16/30] oeqa: Move common files to oeqa/files instead of runtime only Aníbal Limón
` (14 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
This function will generates testdata.json per SDK type.
[YOCTO #10231]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/classes/populate_sdk_base.bbclass | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/meta/classes/populate_sdk_base.bbclass b/meta/classes/populate_sdk_base.bbclass
index 220cde6..f0fc089 100644
--- a/meta/classes/populate_sdk_base.bbclass
+++ b/meta/classes/populate_sdk_base.bbclass
@@ -73,6 +73,13 @@ python write_target_sdk_manifest () {
output.write(format_pkg_list(pkgs, 'ver'))
}
+python write_sdk_test_data() {
+ from oe.data import export2json
+ testdata = "%s/%s.testdata.json" % (d.getVar('SDKDEPLOYDIR', True), d.getVar('TOOLCHAIN_OUTPUTNAME', True))
+ bb.utils.mkdirhier(os.path.dirname(testdata))
+ export2json(d, testdata)
+}
+
python write_host_sdk_manifest () {
from oe.sdk import sdk_list_installed_packages
from oe.utils import format_pkg_list
@@ -84,7 +91,7 @@ python write_host_sdk_manifest () {
output.write(format_pkg_list(pkgs, 'ver'))
}
-POPULATE_SDK_POST_TARGET_COMMAND_append = " write_target_sdk_manifest ; "
+POPULATE_SDK_POST_TARGET_COMMAND_append = " write_target_sdk_manifest ; write_sdk_test_data ; "
POPULATE_SDK_POST_HOST_COMMAND_append = " write_host_sdk_manifest; "
SDK_PACKAGING_COMMAND = "${@'${SDK_PACKAGING_FUNC};' if '${SDK_PACKAGING_FUNC}' else ''}"
SDK_POSTPROCESS_COMMAND = " create_sdk_files; check_sdk_sysroots; tar_sdk; ${SDK_PACKAGING_COMMAND} "
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 16/30] oeqa: Move common files to oeqa/files instead of runtime only
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (14 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 15/30] classes/populate_sdk_base: Add write_sdk_test_data to postprocess Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 17/30] oeqa/sdk: Move test cases inside cases directory Aníbal Limón
` (13 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
Those files are used by runtime and sdk test cases, so move to
base directory of oeqa module.
[YOCTO #10599]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/{runtime => }/files/test.c | 0
meta/lib/oeqa/{runtime => }/files/test.cpp | 0
meta/lib/oeqa/{runtime => }/files/test.pl | 0
meta/lib/oeqa/{runtime => }/files/test.py | 0
4 files changed, 0 insertions(+), 0 deletions(-)
rename meta/lib/oeqa/{runtime => }/files/test.c (100%)
rename meta/lib/oeqa/{runtime => }/files/test.cpp (100%)
rename meta/lib/oeqa/{runtime => }/files/test.pl (100%)
rename meta/lib/oeqa/{runtime => }/files/test.py (100%)
diff --git a/meta/lib/oeqa/runtime/files/test.c b/meta/lib/oeqa/files/test.c
similarity index 100%
rename from meta/lib/oeqa/runtime/files/test.c
rename to meta/lib/oeqa/files/test.c
diff --git a/meta/lib/oeqa/runtime/files/test.cpp b/meta/lib/oeqa/files/test.cpp
similarity index 100%
rename from meta/lib/oeqa/runtime/files/test.cpp
rename to meta/lib/oeqa/files/test.cpp
diff --git a/meta/lib/oeqa/runtime/files/test.pl b/meta/lib/oeqa/files/test.pl
similarity index 100%
rename from meta/lib/oeqa/runtime/files/test.pl
rename to meta/lib/oeqa/files/test.pl
diff --git a/meta/lib/oeqa/runtime/files/test.py b/meta/lib/oeqa/files/test.py
similarity index 100%
rename from meta/lib/oeqa/runtime/files/test.py
rename to meta/lib/oeqa/files/test.py
--
2.1.4
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCHv3 17/30] oeqa/sdk: Move test cases inside cases directory
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (15 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 16/30] oeqa: Move common files to oeqa/files instead of runtime only Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 18/30] oeqa/{runtime, sdk}/files: Move testsdkmakefile from runtime to sdk module Aníbal Limón
` (12 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
For match with the new structure of the OEQA framework.
In the new framework Test component base directory in this case
sdk module will contain case and context implementations.
[YOCTO #10599]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/sdk/{ => cases}/__init__.py | 0
meta/lib/oeqa/sdk/{ => cases}/buildcvs.py | 0
meta/lib/oeqa/sdk/{ => cases}/buildgalculator.py | 0
meta/lib/oeqa/sdk/{ => cases}/buildiptables.py | 0
meta/lib/oeqa/sdk/{ => cases}/gcc.py | 0
meta/lib/oeqa/sdk/{ => cases}/perl.py | 0
meta/lib/oeqa/sdk/{ => cases}/python.py | 0
7 files changed, 0 insertions(+), 0 deletions(-)
rename meta/lib/oeqa/sdk/{ => cases}/__init__.py (100%)
rename meta/lib/oeqa/sdk/{ => cases}/buildcvs.py (100%)
rename meta/lib/oeqa/sdk/{ => cases}/buildgalculator.py (100%)
rename meta/lib/oeqa/sdk/{ => cases}/buildiptables.py (100%)
rename meta/lib/oeqa/sdk/{ => cases}/gcc.py (100%)
rename meta/lib/oeqa/sdk/{ => cases}/perl.py (100%)
rename meta/lib/oeqa/sdk/{ => cases}/python.py (100%)
diff --git a/meta/lib/oeqa/sdk/__init__.py b/meta/lib/oeqa/sdk/cases/__init__.py
similarity index 100%
rename from meta/lib/oeqa/sdk/__init__.py
rename to meta/lib/oeqa/sdk/cases/__init__.py
diff --git a/meta/lib/oeqa/sdk/buildcvs.py b/meta/lib/oeqa/sdk/cases/buildcvs.py
similarity index 100%
rename from meta/lib/oeqa/sdk/buildcvs.py
rename to meta/lib/oeqa/sdk/cases/buildcvs.py
diff --git a/meta/lib/oeqa/sdk/buildgalculator.py b/meta/lib/oeqa/sdk/cases/buildgalculator.py
similarity index 100%
rename from meta/lib/oeqa/sdk/buildgalculator.py
rename to meta/lib/oeqa/sdk/cases/buildgalculator.py
diff --git a/meta/lib/oeqa/sdk/buildiptables.py b/meta/lib/oeqa/sdk/cases/buildiptables.py
similarity index 100%
rename from meta/lib/oeqa/sdk/buildiptables.py
rename to meta/lib/oeqa/sdk/cases/buildiptables.py
diff --git a/meta/lib/oeqa/sdk/gcc.py b/meta/lib/oeqa/sdk/cases/gcc.py
similarity index 100%
rename from meta/lib/oeqa/sdk/gcc.py
rename to meta/lib/oeqa/sdk/cases/gcc.py
diff --git a/meta/lib/oeqa/sdk/perl.py b/meta/lib/oeqa/sdk/cases/perl.py
similarity index 100%
rename from meta/lib/oeqa/sdk/perl.py
rename to meta/lib/oeqa/sdk/cases/perl.py
diff --git a/meta/lib/oeqa/sdk/python.py b/meta/lib/oeqa/sdk/cases/python.py
similarity index 100%
rename from meta/lib/oeqa/sdk/python.py
rename to meta/lib/oeqa/sdk/cases/python.py
--
2.1.4
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCHv3 18/30] oeqa/{runtime, sdk}/files: Move testsdkmakefile from runtime to sdk module
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (16 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 17/30] oeqa/sdk: Move test cases inside cases directory Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 19/30] oeqa/sdk: Add case and context modules for the SDK component Aníbal Limón
` (11 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
It doesn't make sense to have files related to sdk module into runtime
module.
[YOCTO #10599]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/{runtime => sdk}/files/testsdkmakefile | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename meta/lib/oeqa/{runtime => sdk}/files/testsdkmakefile (100%)
diff --git a/meta/lib/oeqa/runtime/files/testsdkmakefile b/meta/lib/oeqa/sdk/files/testsdkmakefile
similarity index 100%
rename from meta/lib/oeqa/runtime/files/testsdkmakefile
rename to meta/lib/oeqa/sdk/files/testsdkmakefile
--
2.1.4
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCHv3 19/30] oeqa/sdk: Add case and context modules for the SDK component
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (17 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 18/30] oeqa/{runtime, sdk}/files: Move testsdkmakefile from runtime to sdk module Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 20/30] classes/testsdk: Migrates testsdk.bbclass to use new OESDKTestContext Aníbal Limón
` (10 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
Adds case and context modules for SDK based on oetest.py old code.
Enables SDK Test component usage with oe-test, the SDK Test component
adds command line options for specify sdk installed dir, sdk environment
and target/hosts maniftest.
[YOCTO #10599]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/oetest.py | 51 ----------------
meta/lib/oeqa/sdk/__init__.py | 0
meta/lib/oeqa/sdk/case.py | 12 ++++
meta/lib/oeqa/sdk/context.py | 133 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 145 insertions(+), 51 deletions(-)
create mode 100644 meta/lib/oeqa/sdk/__init__.py
create mode 100644 meta/lib/oeqa/sdk/case.py
create mode 100644 meta/lib/oeqa/sdk/context.py
diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index 95d3bf7..4a98b0f1 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -145,20 +145,6 @@ class OETestCalledProcessError(subprocess.CalledProcessError):
subprocess.CalledProcessError = OETestCalledProcessError
-class oeSDKTest(oeTest):
- def __init__(self, methodName='runTest'):
- self.sdktestdir = oeSDKTest.tc.sdktestdir
- super(oeSDKTest, self).__init__(methodName)
-
- @classmethod
- def hasHostPackage(self, pkg):
- if re.search(pkg, oeTest.tc.hostpkgmanifest):
- return True
- return False
-
- def _run(self, cmd):
- return subprocess.check_output(". %s > /dev/null; %s;" % (self.tc.sdkenv, cmd), shell=True, stderr=subprocess.STDOUT).decode("utf-8")
-
class oeSDKExtTest(oeSDKTest):
def _run(self, cmd):
# extensible sdk shows a warning if found bitbake in the path
@@ -657,43 +643,6 @@ class ExportTestContext(RuntimeTestContext):
pkg_dir = os.path.join(export_dir, extracted_dir)
super(ExportTestContext, self).install_uninstall_packages(test_id, pkg_dir, install)
-class SDKTestContext(TestContext):
- def __init__(self, d, sdktestdir, sdkenv, tcname, *args):
- super(SDKTestContext, self).__init__(d)
-
- self.sdktestdir = sdktestdir
- self.sdkenv = sdkenv
- self.tcname = tcname
-
- if not hasattr(self, 'target_manifest'):
- self.target_manifest = d.getVar("SDK_TARGET_MANIFEST", True)
- try:
- self.pkgmanifest = {}
- with open(self.target_manifest) as f:
- for line in f:
- (pkg, arch, version) = line.strip().split()
- self.pkgmanifest[pkg] = (version, arch)
- except IOError as e:
- bb.fatal("No package manifest file found. Did you build the sdk image?\n%s" % e)
-
- if not hasattr(self, 'host_manifest'):
- self.host_manifest = d.getVar("SDK_HOST_MANIFEST", True)
- try:
- with open(self.host_manifest) as f:
- self.hostpkgmanifest = f.read()
- except IOError as e:
- bb.fatal("No host package manifest file found. Did you build the sdk image?\n%s" % e)
-
- def _get_test_namespace(self):
- return "sdk"
-
- def _get_test_suites(self):
- return (self.d.getVar("TEST_SUITES_SDK", True) or "auto").split()
-
- def _get_test_suites_required(self):
- return [t for t in (self.d.getVar("TEST_SUITES_SDK", True) or \
- "auto").split() if t != "auto"]
-
class SDKExtTestContext(SDKTestContext):
def __init__(self, d, sdktestdir, sdkenv, tcname, *args):
self.target_manifest = d.getVar("SDK_EXT_TARGET_MANIFEST", True)
diff --git a/meta/lib/oeqa/sdk/__init__.py b/meta/lib/oeqa/sdk/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/meta/lib/oeqa/sdk/case.py b/meta/lib/oeqa/sdk/case.py
new file mode 100644
index 0000000..782db8b
--- /dev/null
+++ b/meta/lib/oeqa/sdk/case.py
@@ -0,0 +1,12 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import subprocess
+
+from oeqa.core.case import OETestCase
+
+class OESDKTestCase(OETestCase):
+ def _run(self, cmd):
+ return subprocess.check_output(". %s > /dev/null; %s;" % \
+ (self.tc.sdk_env, cmd), shell=True,
+ stderr=subprocess.STDOUT).decode("utf-8")
diff --git a/meta/lib/oeqa/sdk/context.py b/meta/lib/oeqa/sdk/context.py
new file mode 100644
index 0000000..0189ed8
--- /dev/null
+++ b/meta/lib/oeqa/sdk/context.py
@@ -0,0 +1,133 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import os
+import sys
+import glob
+import re
+
+from oeqa.core.context import OETestContext, OETestContextExecutor
+
+class OESDKTestContext(OETestContext):
+ sdk_files_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files")
+
+ def __init__(self, td=None, logger=None, sdk_dir=None, sdk_env=None,
+ target_pkg_manifest=None, host_pkg_manifest=None):
+ super(OESDKTestContext, self).__init__(td, logger)
+
+ self.sdk_dir = sdk_dir
+ self.sdk_env = sdk_env
+ self.target_pkg_manifest = target_pkg_manifest
+ self.host_pkg_manifest = host_pkg_manifest
+
+ def _hasPackage(self, manifest, pkg):
+ for host_pkg in manifest.keys():
+ if re.search(pkg, host_pkg):
+ return True
+ return False
+
+ def hasHostPackage(self, pkg):
+ return self._hasPackage(self.host_pkg_manifest, pkg)
+
+ def hasTargetPackage(self, pkg):
+ return self._hasPackage(self.target_pkg_manifest, pkg)
+
+class OESDKTestContextExecutor(OETestContextExecutor):
+ _context_class = OESDKTestContext
+
+ name = 'sdk'
+ help = 'sdk test component'
+ description = 'executes sdk tests'
+
+ default_cases = [os.path.join(os.path.abspath(os.path.dirname(__file__)),
+ 'cases')]
+ default_test_data = None
+
+ def register_commands(self, logger, subparsers):
+ import argparse_oe
+
+ super(OESDKTestContextExecutor, self).register_commands(logger, subparsers)
+
+ sdk_group = self.parser.add_argument_group('sdk options')
+ sdk_group.add_argument('--sdk-env', action='store',
+ help='sdk environment')
+ sdk_group.add_argument('--target-manifest', action='store',
+ help='sdk target manifest')
+ sdk_group.add_argument('--host-manifest', action='store',
+ help='sdk host manifest')
+
+ sdk_dgroup = self.parser.add_argument_group('sdk display options')
+ sdk_dgroup.add_argument('--list-sdk-env', action='store_true',
+ default=False, help='sdk list available environment')
+
+ # XXX this option is required but argparse_oe has a bug handling
+ # required options, seems that don't keep track of already parsed
+ # options
+ sdk_rgroup = self.parser.add_argument_group('sdk required options')
+ sdk_rgroup.add_argument('--sdk-dir', required=False, action='store',
+ help='sdk installed directory')
+
+ @staticmethod
+ def _load_manifest(manifest):
+ pkg_manifest = {}
+ if manifest:
+ with open(manifest) as f:
+ for line in f:
+ (pkg, arch, version) = line.strip().split()
+ pkg_manifest[pkg] = (version, arch)
+
+ return pkg_manifest
+
+ def _process_args(self, logger, args):
+ super(OESDKTestContextExecutor, self)._process_args(logger, args)
+
+ self.tc_kwargs['init']['sdk_dir'] = args.sdk_dir
+ self.tc_kwargs['init']['sdk_env'] = self.sdk_env
+ self.tc_kwargs['init']['target_pkg_manifest'] = \
+ OESDKTestContextExecutor._load_manifest(args.target_manifest)
+ self.tc_kwargs['init']['host_pkg_manifest'] = \
+ OESDKTestContextExecutor._load_manifest(args.host_manifest)
+
+ @staticmethod
+ def _get_sdk_environs(sdk_dir):
+ sdk_env = {}
+
+ environ_pattern = sdk_dir + '/environment-setup-*'
+ full_sdk_env = glob.glob(sdk_dir + '/environment-setup-*')
+ for env in full_sdk_env:
+ m = re.search('environment-setup-(.*)', env)
+ if m:
+ sdk_env[m.group(1)] = env
+
+ return sdk_env
+
+ def _display_sdk_envs(self, log, args, sdk_envs):
+ log("Available SDK environments at directory %s:" \
+ % args.sdk_dir)
+ log("")
+ for env in sdk_envs:
+ log(env)
+
+ def run(self, logger, args):
+ if not args.sdk_dir:
+ raise argparse_oe.ArgumentUsageError("No SDK directory "\
+ "specified please do, --sdk-dir SDK_DIR", self.name)
+
+ sdk_envs = OESDKTestContextExecutor._get_sdk_environs(args.sdk_dir)
+ if not sdk_envs:
+ raise argparse_oe.ArgumentUsageError("No available SDK "\
+ "enviroments found at %s" % args.sdk_dir, self.name)
+
+ if args.list_sdk_env:
+ self._display_sdk_envs(logger.info, args, sdk_envs)
+ sys.exit(0)
+
+ if not args.sdk_env in sdk_envs:
+ self._display_sdk_envs(logger.error, args, sdk_envs)
+ raise argparse_oe.ArgumentUsageError("No valid SDK "\
+ "environment (%s) specified" % args.sdk_env, self.name)
+
+ self.sdk_env = sdk_envs[args.sdk_env]
+ super(OESDKTestContextExecutor, self).run(logger, args)
+
+_executor_class = OESDKTestContextExecutor
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 20/30] classes/testsdk: Migrates testsdk.bbclass to use new OESDKTestContext
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (18 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 19/30] oeqa/sdk: Add case and context modules for the SDK component Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 21/30] oeqa/utils: Move targetbuild to buildproject module Aníbal Limón
` (9 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
The functionality provided is the same with imporvements on code
reuse and better interfaces.
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/classes/testsdk.bbclass | 67 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 55 insertions(+), 12 deletions(-)
diff --git a/meta/classes/testsdk.bbclass b/meta/classes/testsdk.bbclass
index 06b4c50..959fb38 100644
--- a/meta/classes/testsdk.bbclass
+++ b/meta/classes/testsdk.bbclass
@@ -50,30 +50,74 @@ def run_test_context(CTestContext, d, testdir, tcname, pn, *args):
def testsdk_main(d):
import os
- import oeqa.sdk
import subprocess
- from oeqa.oetest import SDKTestContext
+ import json
+ import logging
+
+ from bb.utils import export_proxies
+ from oeqa.core.runner import OEStreamLogger
+ from oeqa.sdk.context import OESDKTestContext, OESDKTestContextExecutor
pn = d.getVar("PN", True)
- bb.utils.mkdirhier(d.getVar("TEST_LOG_DIR", True))
+ logger = logging.getLogger("BitBake")
+
+ # sdk use network for download projects for build
+ export_proxies(d)
+
+ test_log_dir = d.getVar("TEST_LOG_DIR", True)
+
+ bb.utils.mkdirhier(test_log_dir)
tcname = d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh")
if not os.path.exists(tcname):
bb.fatal("The toolchain %s is not built. Build it before running the tests: 'bitbake <image> -c populate_sdk' ." % tcname)
- sdktestdir = d.expand("${WORKDIR}/testimage-sdk/")
- bb.utils.remove(sdktestdir, True)
- bb.utils.mkdirhier(sdktestdir)
+ tdname = d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.testdata.json")
+ test_data = json.load(open(tdname, "r"))
+ test_data['TEST_LOG_DIR'] = test_log_dir
+
+ target_pkg_manifest = OESDKTestContextExecutor._load_manifest(
+ d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.target.manifest"))
+ host_pkg_manifest = OESDKTestContextExecutor._load_manifest(
+ d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.host.manifest"))
+
+ sdk_dir = d.expand("${WORKDIR}/testimage-sdk/")
+ bb.utils.remove(sdk_dir, True)
+ bb.utils.mkdirhier(sdk_dir)
try:
- subprocess.check_output("cd %s; %s <<EOF\n./tc\nY\nEOF" % (sdktestdir, tcname), shell=True)
+ subprocess.check_output("cd %s; %s <<EOF\n./\nY\nEOF" % (sdk_dir, tcname), shell=True)
except subprocess.CalledProcessError as e:
bb.fatal("Couldn't install the SDK:\n%s" % e.output.decode("utf-8"))
- try:
- run_test_context(SDKTestContext, d, sdktestdir, tcname, pn)
- finally:
- bb.utils.remove(sdktestdir, True)
+ fail = False
+ sdk_envs = OESDKTestContextExecutor._get_sdk_environs(sdk_dir)
+ for s in sdk_envs:
+ sdk_env = sdk_envs[s]
+ bb.plain("SDK testing environment: %s" % s)
+ tc = OESDKTestContext(td=test_data, logger=logger, sdk_dir=sdk_dir,
+ sdk_env=sdk_env, target_pkg_manifest=target_pkg_manifest,
+ host_pkg_manifest=host_pkg_manifest)
+ try:
+ tc.loadTests(OESDKTestContextExecutor.default_cases)
+ except Exception as e:
+ import traceback
+ bb.fatal("Loading tests failed:\n%s" % traceback.format_exc())
+
+ result = tc.runTests()
+
+ component = "%s %s" % (pn, OESDKTestContextExecutor.name)
+ context_msg = "%s:%s" % (os.path.basename(tcname), os.path.basename(sdk_env))
+
+ tc.logSummary(result, component, context_msg)
+ tc.logDetails()
+
+ if not result.wasSuccessful():
+ fail = True
+
+ if fail:
+ bb.fatal("%s - FAILED - check the task log and the commands log" % pn)
+
testsdk_main[vardepsexclude] =+ "BB_ORIGENV"
python do_testsdk() {
@@ -94,7 +138,6 @@ def testsdkext_main(d):
from oeqa.oetest import SDKTestContext, SDKExtTestContext
from oeqa.utils import avoid_paths_in_environ
-
# extensible sdk use network
export_proxies(d)
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 21/30] oeqa/utils: Move targetbuild to buildproject module
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (19 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 20/30] classes/testsdk: Migrates testsdk.bbclass to use new OESDKTestContext Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 22/30] oeqa/utils: {Target, SDK, }BuildProject remove dependency of bb Aníbal Limón
` (8 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
The new buildproject module will contain only BuildProject class
a helper class for build source code.
The remaining classes TargetBuildProject and SDKBuildProject was
move to runtime and sdk respectively.
[YOCTO #10599]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/runtime/utils/__init__.py | 0
meta/lib/oeqa/runtime/utils/targetbuildproject.py | 33 +++++++++++
meta/lib/oeqa/sdk/utils/__init__.py | 0
meta/lib/oeqa/sdk/utils/sdkbuildproject.py | 45 ++++++++++++++
.../oeqa/utils/{targetbuild.py => buildproject.py} | 68 +---------------------
5 files changed, 79 insertions(+), 67 deletions(-)
create mode 100644 meta/lib/oeqa/runtime/utils/__init__.py
create mode 100644 meta/lib/oeqa/runtime/utils/targetbuildproject.py
create mode 100644 meta/lib/oeqa/sdk/utils/__init__.py
create mode 100644 meta/lib/oeqa/sdk/utils/sdkbuildproject.py
rename meta/lib/oeqa/utils/{targetbuild.py => buildproject.py} (48%)
diff --git a/meta/lib/oeqa/runtime/utils/__init__.py b/meta/lib/oeqa/runtime/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/meta/lib/oeqa/runtime/utils/targetbuildproject.py b/meta/lib/oeqa/runtime/utils/targetbuildproject.py
new file mode 100644
index 0000000..138b5ef
--- /dev/null
+++ b/meta/lib/oeqa/runtime/utils/targetbuildproject.py
@@ -0,0 +1,33 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+from oeqa.utils.buildproject import BuildProject
+
+class TargetBuildProject(BuildProject):
+
+ def __init__(self, target, d, uri, foldername=None):
+ self.target = target
+ self.targetdir = "~/"
+ BuildProject.__init__(self, d, uri, foldername, tmpdir="/tmp")
+
+ def download_archive(self):
+
+ self._download_archive()
+
+ (status, output) = self.target.copy_to(self.localarchive, self.targetdir)
+ if status != 0:
+ raise Exception("Failed to copy archive to target, output: %s" % output)
+
+ (status, output) = self.target.run('tar xf %s%s -C %s' % (self.targetdir, self.archive, self.targetdir))
+ if status != 0:
+ raise Exception("Failed to extract archive, output: %s" % output)
+
+ #Change targetdir to project folder
+ self.targetdir = self.targetdir + self.fname
+
+ # The timeout parameter of target.run is set to 0 to make the ssh command
+ # run with no timeout.
+ def _run(self, cmd):
+ return self.target.run(cmd, 0)[0]
+
+
diff --git a/meta/lib/oeqa/sdk/utils/__init__.py b/meta/lib/oeqa/sdk/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/meta/lib/oeqa/sdk/utils/sdkbuildproject.py b/meta/lib/oeqa/sdk/utils/sdkbuildproject.py
new file mode 100644
index 0000000..1aa8a69
--- /dev/null
+++ b/meta/lib/oeqa/sdk/utils/sdkbuildproject.py
@@ -0,0 +1,45 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import os
+import subprocess
+
+from oeqa.utils.buildproject import BuildProject
+
+class SDKBuildProject(BuildProject):
+
+ def __init__(self, testpath, sdkenv, d, uri, foldername=None):
+ self.sdkenv = sdkenv
+ self.testdir = testpath
+ self.targetdir = testpath
+ bb.utils.mkdirhier(testpath)
+ self.datetime = d.getVar('DATETIME', True)
+ self.testlogdir = d.getVar("TEST_LOG_DIR", True)
+ bb.utils.mkdirhier(self.testlogdir)
+ self.logfile = os.path.join(self.testlogdir, "sdk_target_log.%s" % self.datetime)
+ BuildProject.__init__(self, d, uri, foldername, tmpdir=testpath)
+
+ def download_archive(self):
+
+ self._download_archive()
+
+ cmd = 'tar xf %s%s -C %s' % (self.targetdir, self.archive, self.targetdir)
+ subprocess.check_call(cmd, shell=True)
+
+ #Change targetdir to project folder
+ self.targetdir = os.path.join(self.targetdir, self.fname)
+
+ def run_configure(self, configure_args='', extra_cmds=' gnu-configize; '):
+ return super(SDKBuildProject, self).run_configure(configure_args=(configure_args or '$CONFIGURE_FLAGS'), extra_cmds=extra_cmds)
+
+ def run_install(self, install_args=''):
+ return super(SDKBuildProject, self).run_install(install_args=(install_args or "DESTDIR=%s/../install" % self.targetdir))
+
+ def log(self, msg):
+ if self.logfile:
+ with open(self.logfile, "a") as f:
+ f.write("%s\n" % msg)
+
+ def _run(self, cmd):
+ self.log("Running . %s; " % self.sdkenv + cmd)
+ return subprocess.call(". %s; " % self.sdkenv + cmd, shell=True)
diff --git a/meta/lib/oeqa/utils/targetbuild.py b/meta/lib/oeqa/utils/buildproject.py
similarity index 48%
rename from meta/lib/oeqa/utils/targetbuild.py
rename to meta/lib/oeqa/utils/buildproject.py
index 59593f5..0e1ed8a 100644
--- a/meta/lib/oeqa/utils/targetbuild.py
+++ b/meta/lib/oeqa/utils/buildproject.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2013 Intel Corporation
+# Copyright (C) 2013-2016 Intel Corporation
#
# Released under the MIT license (see COPYING.MIT)
@@ -67,69 +67,3 @@ class BuildProject(metaclass=ABCMeta):
self._run('rm -rf %s' % self.targetdir)
subprocess.call('rm -f %s' % self.localarchive, shell=True)
pass
-
-class TargetBuildProject(BuildProject):
-
- def __init__(self, target, d, uri, foldername=None):
- self.target = target
- self.targetdir = "~/"
- BuildProject.__init__(self, d, uri, foldername, tmpdir="/tmp")
-
- def download_archive(self):
-
- self._download_archive()
-
- (status, output) = self.target.copy_to(self.localarchive, self.targetdir)
- if status != 0:
- raise Exception("Failed to copy archive to target, output: %s" % output)
-
- (status, output) = self.target.run('tar xf %s%s -C %s' % (self.targetdir, self.archive, self.targetdir))
- if status != 0:
- raise Exception("Failed to extract archive, output: %s" % output)
-
- #Change targetdir to project folder
- self.targetdir = self.targetdir + self.fname
-
- # The timeout parameter of target.run is set to 0 to make the ssh command
- # run with no timeout.
- def _run(self, cmd):
- return self.target.run(cmd, 0)[0]
-
-
-class SDKBuildProject(BuildProject):
-
- def __init__(self, testpath, sdkenv, d, uri, foldername=None):
- self.sdkenv = sdkenv
- self.testdir = testpath
- self.targetdir = testpath
- bb.utils.mkdirhier(testpath)
- self.datetime = d.getVar('DATETIME', True)
- self.testlogdir = d.getVar("TEST_LOG_DIR", True)
- bb.utils.mkdirhier(self.testlogdir)
- self.logfile = os.path.join(self.testlogdir, "sdk_target_log.%s" % self.datetime)
- BuildProject.__init__(self, d, uri, foldername, tmpdir=testpath)
-
- def download_archive(self):
-
- self._download_archive()
-
- cmd = 'tar xf %s%s -C %s' % (self.targetdir, self.archive, self.targetdir)
- subprocess.check_call(cmd, shell=True)
-
- #Change targetdir to project folder
- self.targetdir = os.path.join(self.targetdir, self.fname)
-
- def run_configure(self, configure_args='', extra_cmds=' gnu-configize; '):
- return super(SDKBuildProject, self).run_configure(configure_args=(configure_args or '$CONFIGURE_FLAGS'), extra_cmds=extra_cmds)
-
- def run_install(self, install_args=''):
- return super(SDKBuildProject, self).run_install(install_args=(install_args or "DESTDIR=%s/../install" % self.targetdir))
-
- def log(self, msg):
- if self.logfile:
- with open(self.logfile, "a") as f:
- f.write("%s\n" % msg)
-
- def _run(self, cmd):
- self.log("Running . %s; " % self.sdkenv + cmd)
- return subprocess.call(". %s; " % self.sdkenv + cmd, shell=True)
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 22/30] oeqa/utils: {Target, SDK, }BuildProject remove dependency of bb
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (20 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 21/30] oeqa/utils: Move targetbuild to buildproject module Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 23/30] oeqa/sdk/cases: Migrate tests to the new OEQA framework Aníbal Limón
` (7 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
Don't use bitbake references inside utils modules, in order todo
that changes getVar calls for arguments in the __init__ method like
dl_dir for all the classes and testlogdir, builddatetime in
SDKBUildProject.
Also don't export proxies inside _download_archive method, a good
practice is to setup the proxies at init of the process instead of
do it in this helper module.
[YOCTO #10231]
[YOCTO #10599]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/lib/oeqa/runtime/utils/targetbuildproject.py | 6 ++---
meta/lib/oeqa/sdk/utils/sdkbuildproject.py | 14 +++++-----
meta/lib/oeqa/utils/buildproject.py | 31 +++++------------------
3 files changed, 17 insertions(+), 34 deletions(-)
diff --git a/meta/lib/oeqa/runtime/utils/targetbuildproject.py b/meta/lib/oeqa/runtime/utils/targetbuildproject.py
index 138b5ef..006d4d4 100644
--- a/meta/lib/oeqa/runtime/utils/targetbuildproject.py
+++ b/meta/lib/oeqa/runtime/utils/targetbuildproject.py
@@ -5,13 +5,13 @@ from oeqa.utils.buildproject import BuildProject
class TargetBuildProject(BuildProject):
- def __init__(self, target, d, uri, foldername=None):
+ def __init__(self, target, uri, foldername=None, dl_dir=None):
self.target = target
self.targetdir = "~/"
- BuildProject.__init__(self, d, uri, foldername, tmpdir="/tmp")
+ BuildProject.__init__(self, uri, foldername, tmpdir="/tmp",
+ dl_dir=dl_dir)
def download_archive(self):
-
self._download_archive()
(status, output) = self.target.copy_to(self.localarchive, self.targetdir)
diff --git a/meta/lib/oeqa/sdk/utils/sdkbuildproject.py b/meta/lib/oeqa/sdk/utils/sdkbuildproject.py
index 1aa8a69..cc34e0c 100644
--- a/meta/lib/oeqa/sdk/utils/sdkbuildproject.py
+++ b/meta/lib/oeqa/sdk/utils/sdkbuildproject.py
@@ -7,17 +7,17 @@ import subprocess
from oeqa.utils.buildproject import BuildProject
class SDKBuildProject(BuildProject):
-
- def __init__(self, testpath, sdkenv, d, uri, foldername=None):
+ def __init__(self, testpath, sdkenv, uri, testlogdir, builddatetime,
+ foldername=None, dl_dir=None):
self.sdkenv = sdkenv
self.testdir = testpath
self.targetdir = testpath
- bb.utils.mkdirhier(testpath)
- self.datetime = d.getVar('DATETIME', True)
- self.testlogdir = d.getVar("TEST_LOG_DIR", True)
- bb.utils.mkdirhier(self.testlogdir)
+ os.makedirs(testpath, exist_ok=True)
+ self.datetime = builddatetime
+ self.testlogdir = testlogdir
+ os.makedirs(self.testlogdir, exist_ok=True)
self.logfile = os.path.join(self.testlogdir, "sdk_target_log.%s" % self.datetime)
- BuildProject.__init__(self, d, uri, foldername, tmpdir=testpath)
+ BuildProject.__init__(self, uri, foldername, tmpdir=testpath, dl_dir=dl_dir)
def download_archive(self):
diff --git a/meta/lib/oeqa/utils/buildproject.py b/meta/lib/oeqa/utils/buildproject.py
index 0e1ed8a..386a927 100644
--- a/meta/lib/oeqa/utils/buildproject.py
+++ b/meta/lib/oeqa/utils/buildproject.py
@@ -6,17 +6,17 @@
import os
import re
-import bb.utils
import subprocess
+import shutil
+
from abc import ABCMeta, abstractmethod
class BuildProject(metaclass=ABCMeta):
-
- def __init__(self, d, uri, foldername=None, tmpdir="/tmp/"):
- self.d = d
+ def __init__(self, uri, foldername=None, tmpdir="/tmp/", dl_dir=None):
self.uri = uri
self.archive = os.path.basename(uri)
self.localarchive = os.path.join(tmpdir,self.archive)
+ self.dl_dir = dl_dir
if foldername:
self.fname = foldername
else:
@@ -24,27 +24,11 @@ class BuildProject(metaclass=ABCMeta):
# Download self.archive to self.localarchive
def _download_archive(self):
-
- dl_dir = self.d.getVar("DL_DIR", True)
- if dl_dir and os.path.exists(os.path.join(dl_dir, self.archive)):
- bb.utils.copyfile(os.path.join(dl_dir, self.archive), self.localarchive)
+ if self.dl_dir and os.path.exists(os.path.join(self.dl_dir, self.archive)):
+ shutil.copyfile(os.path.join(self.dl_dir, self.archive), self.localarchive)
return
- exportvars = ['HTTP_PROXY', 'http_proxy',
- 'HTTPS_PROXY', 'https_proxy',
- 'FTP_PROXY', 'ftp_proxy',
- 'FTPS_PROXY', 'ftps_proxy',
- 'NO_PROXY', 'no_proxy',
- 'ALL_PROXY', 'all_proxy',
- 'SOCKS5_USER', 'SOCKS5_PASSWD']
-
- cmd = ''
- for var in exportvars:
- val = self.d.getVar(var, True)
- if val:
- cmd = 'export ' + var + '=\"%s\"; %s' % (val, cmd)
-
- cmd = cmd + "wget -O %s %s" % (self.localarchive, self.uri)
+ cmd = "wget -O %s %s" % (self.localarchive, self.uri)
subprocess.check_call(cmd, shell=True)
# This method should provide a way to run a command in the desired environment.
@@ -66,4 +50,3 @@ class BuildProject(metaclass=ABCMeta):
def clean(self):
self._run('rm -rf %s' % self.targetdir)
subprocess.call('rm -f %s' % self.localarchive, shell=True)
- pass
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 23/30] oeqa/sdk/cases: Migrate tests to the new OEQA framework
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (21 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 22/30] oeqa/utils: {Target, SDK, }BuildProject remove dependency of bb Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 24/30] classes/testsdk: Remove the need of TEST_LOG_DIR variable Aníbal Limón
` (6 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
Summary of the changes:
- Remove auto extend_path using pkgutil at __init__, is not needed.
- Change base class to OESDKTestCase.
- Add td_vars attr to set dependencies of certain variables in test
data.
- Change skips from module level to class level because Test context
(tc)
now isn't at module level.
- Variable names changes to be consistent (i.e. sdktestdir ->
sdk_dir).
[YOCTO #10599]
- Don't use bb.utils functions use instead remove_safe and shutil
for copy files.
- SDKBuildProject pass test data variables instead of call getVar
inside.
[YOCTO #10231]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
meta/lib/oeqa/sdk/cases/__init__.py | 3 ---
meta/lib/oeqa/sdk/cases/buildcvs.py | 15 ++++++-----
meta/lib/oeqa/sdk/cases/buildgalculator.py | 28 ++++++++++++--------
meta/lib/oeqa/sdk/cases/buildiptables.py | 16 +++++++-----
meta/lib/oeqa/sdk/cases/gcc.py | 41 +++++++++++++++++-------------
meta/lib/oeqa/sdk/cases/perl.py | 25 +++++++++---------
meta/lib/oeqa/sdk/cases/python.py | 25 +++++++++---------
7 files changed, 84 insertions(+), 69 deletions(-)
delete mode 100644 meta/lib/oeqa/sdk/cases/__init__.py
diff --git a/meta/lib/oeqa/sdk/cases/__init__.py b/meta/lib/oeqa/sdk/cases/__init__.py
deleted file mode 100644
index 4cf3fa7..0000000
--- a/meta/lib/oeqa/sdk/cases/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# Enable other layers to have tests in the same named directory
-from pkgutil import extend_path
-__path__ = extend_path(__path__, __name__)
diff --git a/meta/lib/oeqa/sdk/cases/buildcvs.py b/meta/lib/oeqa/sdk/cases/buildcvs.py
index c7146fa..ee7fb73 100644
--- a/meta/lib/oeqa/sdk/cases/buildcvs.py
+++ b/meta/lib/oeqa/sdk/cases/buildcvs.py
@@ -1,13 +1,16 @@
-from oeqa.oetest import oeSDKTest, skipModule
-from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import SDKBuildProject
+from oeqa.sdk.case import OESDKTestCase
+from oeqa.sdk.utils.sdkbuildproject import SDKBuildProject
-class BuildCvsTest(oeSDKTest):
+class BuildCvsTest(OESDKTestCase):
+ td_vars = ['TEST_LOG_DIR', 'DATETIME']
@classmethod
def setUpClass(self):
- self.project = SDKBuildProject(oeSDKTest.tc.sdktestdir + "/cvs/", oeSDKTest.tc.sdkenv, oeSDKTest.tc.d,
- "http://ftp.gnu.org/non-gnu/cvs/source/feature/1.12.13/cvs-1.12.13.tar.bz2")
+ dl_dir = self.td.get('DL_DIR', None)
+
+ self.project = SDKBuildProject(self.tc.sdk_dir + "/cvs/", self.tc.sdk_env,
+ "http://ftp.gnu.org/non-gnu/cvs/source/feature/1.12.13/cvs-1.12.13.tar.bz2",
+ self.td['TEST_LOG_DIR'], self.td['DATETIME'], dl_dir=dl_dir)
self.project.download_archive()
def test_cvs(self):
diff --git a/meta/lib/oeqa/sdk/cases/buildgalculator.py b/meta/lib/oeqa/sdk/cases/buildgalculator.py
index dc2fa9c..d2c1189 100644
--- a/meta/lib/oeqa/sdk/cases/buildgalculator.py
+++ b/meta/lib/oeqa/sdk/cases/buildgalculator.py
@@ -1,17 +1,25 @@
-from oeqa.oetest import oeSDKTest, skipModule
-from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import SDKBuildProject
+import unittest
-def setUpModule():
- if not (oeSDKTest.hasPackage("gtk+3") or oeSDKTest.hasPackage("libgtk-3.0")):
- skipModule("Image doesn't have gtk+3 in manifest")
+from oeqa.sdk.case import OESDKTestCase
+from oeqa.sdk.utils.sdkbuildproject import SDKBuildProject
+
+class GalculatorTest(OESDKTestCase):
+ td_vars = ['TEST_LOG_DIR', 'DATETIME']
+
+ @classmethod
+ def setUpClass(self):
+ if not (self.tc.hasTargetPackage("gtk+3") or\
+ self.tc.hasTargetPackage("libgtk-3.0")):
+ raise unittest.SkipTest("%s class: SDK don't support gtk+3" % self.__name__)
-class GalculatorTest(oeSDKTest):
def test_galculator(self):
+ dl_dir = self.td.get('DL_DIR', None)
+ project = None
try:
- project = SDKBuildProject(oeSDKTest.tc.sdktestdir + "/galculator/",
- oeSDKTest.tc.sdkenv, oeSDKTest.tc.d,
- "http://galculator.mnim.org/downloads/galculator-2.1.4.tar.bz2")
+ project = SDKBuildProject(self.tc.sdk_dir + "/galculator/",
+ self.tc.sdk_env,
+ "http://galculator.mnim.org/downloads/galculator-2.1.4.tar.bz2",
+ self.td['TEST_LOG_DIR'], self.td['DATETIME'], dl_dir=dl_dir)
project.download_archive()
diff --git a/meta/lib/oeqa/sdk/cases/buildiptables.py b/meta/lib/oeqa/sdk/cases/buildiptables.py
index f0cb8a4..a50fb5d 100644
--- a/meta/lib/oeqa/sdk/cases/buildiptables.py
+++ b/meta/lib/oeqa/sdk/cases/buildiptables.py
@@ -1,14 +1,16 @@
-from oeqa.oetest import oeSDKTest
-from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import SDKBuildProject
+from oeqa.sdk.case import OESDKTestCase
+from oeqa.sdk.utils.sdkbuildproject import SDKBuildProject
-
-class BuildIptablesTest(oeSDKTest):
+class BuildIptablesTest(OESDKTestCase):
+ td_vars = ['TEST_LOG_DIR', 'DATETIME']
@classmethod
def setUpClass(self):
- self.project = SDKBuildProject(oeSDKTest.tc.sdktestdir + "/iptables/", oeSDKTest.tc.sdkenv, oeSDKTest.tc.d,
- "http://downloads.yoctoproject.org/mirror/sources/iptables-1.4.13.tar.bz2")
+ dl_dir = self.td.get('DL_DIR', None)
+
+ self.project = SDKBuildProject(self.tc.sdk_dir + "/iptables/", self.tc.sdk_env,
+ "http://downloads.yoctoproject.org/mirror/sources/iptables-1.4.13.tar.bz2",
+ self.td['TEST_LOG_DIR'], self.td['DATETIME'], dl_dir=dl_dir)
self.project.download_archive()
def test_iptables(self):
diff --git a/meta/lib/oeqa/sdk/cases/gcc.py b/meta/lib/oeqa/sdk/cases/gcc.py
index 8395b9b..e06af4c 100644
--- a/meta/lib/oeqa/sdk/cases/gcc.py
+++ b/meta/lib/oeqa/sdk/cases/gcc.py
@@ -1,36 +1,43 @@
-import unittest
import os
import shutil
-from oeqa.oetest import oeSDKTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- machine = oeSDKTest.tc.d.getVar("MACHINE", True)
- if not oeSDKTest.hasHostPackage("packagegroup-cross-canadian-" + machine):
- skipModule("SDK doesn't contain a cross-canadian toolchain")
+import unittest
+from oeqa.core.utils.path import remove_safe
+from oeqa.sdk.case import OESDKTestCase
-class GccCompileTest(oeSDKTest):
+class GccCompileTest(OESDKTestCase):
+ td_vars = ['MACHINE']
@classmethod
def setUpClass(self):
- for f in ['test.c', 'test.cpp', 'testsdkmakefile']:
- shutil.copyfile(os.path.join(self.tc.filesdir, f), self.tc.sdktestdir + f)
+ files = {'test.c' : self.tc.files_dir, 'test.cpp' : self.tc.files_dir,
+ 'testsdkmakefile' : self.tc.sdk_files_dir}
+ for f in files:
+ shutil.copyfile(os.path.join(files[f], f),
+ os.path.join(self.tc.sdk_dir, f))
+
+ def setUp(self):
+ machine = self.td.get("MACHINE")
+ if not self.tc.hasHostPackage("packagegroup-cross-canadian-%s" % machine):
+ raise unittest.SkipTest("%s class: SDK doesn't contain a cross-canadian toolchain",
+ self.__name__)
def test_gcc_compile(self):
- self._run('$CC %s/test.c -o %s/test -lm' % (self.tc.sdktestdir, self.tc.sdktestdir))
+ self._run('$CC %s/test.c -o %s/test -lm' % (self.tc.sdk_dir, self.tc.sdk_dir))
def test_gpp_compile(self):
- self._run('$CXX %s/test.c -o %s/test -lm' % (self.tc.sdktestdir, self.tc.sdktestdir))
+ self._run('$CXX %s/test.c -o %s/test -lm' % (self.tc.sdk_dir, self.tc.sdk_dir))
def test_gpp2_compile(self):
- self._run('$CXX %s/test.cpp -o %s/test -lm' % (self.tc.sdktestdir, self.tc.sdktestdir))
+ self._run('$CXX %s/test.cpp -o %s/test -lm' % (self.tc.sdk_dir, self.tc.sdk_dir))
def test_make(self):
- self._run('cd %s; make -f testsdkmakefile' % self.tc.sdktestdir)
+ self._run('cd %s; make -f testsdkmakefile' % self.tc.sdk_dir)
@classmethod
def tearDownClass(self):
- files = [self.tc.sdktestdir + f for f in ['test.c', 'test.cpp', 'test.o', 'test', 'testsdkmakefile']]
+ files = [os.path.join(self.tc.sdk_dir, f) \
+ for f in ['test.c', 'test.cpp', 'test.o', 'test',
+ 'testsdkmakefile']]
for f in files:
- bb.utils.remove(f)
+ remove_safe(f)
diff --git a/meta/lib/oeqa/sdk/cases/perl.py b/meta/lib/oeqa/sdk/cases/perl.py
index 45f422e..e1bded2 100644
--- a/meta/lib/oeqa/sdk/cases/perl.py
+++ b/meta/lib/oeqa/sdk/cases/perl.py
@@ -1,28 +1,27 @@
-import unittest
import os
import shutil
-from oeqa.oetest import oeSDKTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeSDKTest.hasHostPackage("nativesdk-perl"):
- skipModule("No perl package in the SDK")
-
+import unittest
-class PerlTest(oeSDKTest):
+from oeqa.core.utils.path import remove_safe
+from oeqa.sdk.case import OESDKTestCase
+class PerlTest(OESDKTestCase):
@classmethod
def setUpClass(self):
+ if not self.tc.hasHostPackage("nativesdk-perl"):
+ raise unittest.SkipTest("No perl package in the SDK")
+
for f in ['test.pl']:
- shutil.copyfile(os.path.join(self.tc.filesdir, f), self.tc.sdktestdir + f)
- self.testfile = self.tc.sdktestdir + "test.pl"
+ shutil.copyfile(os.path.join(self.tc.files_dir, f),
+ os.path.join(self.tc.sdk_dir, f))
+ self.testfile = os.path.join(self.tc.sdk_dir, "test.pl")
def test_perl_exists(self):
self._run('which perl')
def test_perl_works(self):
- self._run('perl %s/test.pl' % self.tc.sdktestdir)
+ self._run('perl %s' % self.testfile)
@classmethod
def tearDownClass(self):
- bb.utils.remove("%s/test.pl" % self.tc.sdktestdir)
+ remove_safe(self.testfile)
diff --git a/meta/lib/oeqa/sdk/cases/python.py b/meta/lib/oeqa/sdk/cases/python.py
index 896fab4..94a296f 100644
--- a/meta/lib/oeqa/sdk/cases/python.py
+++ b/meta/lib/oeqa/sdk/cases/python.py
@@ -1,26 +1,25 @@
-import unittest
import os
import shutil
-from oeqa.oetest import oeSDKTest, skipModule
-from oeqa.utils.decorators import *
-
-def setUpModule():
- if not oeSDKTest.hasHostPackage("nativesdk-python"):
- skipModule("No python package in the SDK")
-
+import unittest
-class PythonTest(oeSDKTest):
+from oeqa.core.utils.path import remove_safe
+from oeqa.sdk.case import OESDKTestCase
+class PythonTest(OESDKTestCase):
@classmethod
def setUpClass(self):
+ if not self.tc.hasHostPackage("nativesdk-python"):
+ raise unittest.SkipTest("No python package in the SDK")
+
for f in ['test.py']:
- shutil.copyfile(os.path.join(self.tc.filesdir, f), self.tc.sdktestdir + f)
+ shutil.copyfile(os.path.join(self.tc.files_dir, f),
+ os.path.join(self.tc.sdk_dir, f))
def test_python_exists(self):
self._run('which python')
def test_python_stdout(self):
- output = self._run('python %s/test.py' % self.tc.sdktestdir)
+ output = self._run('python %s/test.py' % self.tc.sdk_dir)
self.assertEqual(output.strip(), "the value of a is 0.01", msg="Incorrect output: %s" % output)
def test_python_testfile(self):
@@ -28,5 +27,5 @@ class PythonTest(oeSDKTest):
@classmethod
def tearDownClass(self):
- bb.utils.remove("%s/test.py" % self.tc.sdktestdir)
- bb.utils.remove("/tmp/testfile.python")
+ remove_safe("%s/test.py" % self.tc.sdk_dir)
+ remove_safe("/tmp/testfile.python")
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 24/30] classes/testsdk: Remove the need of TEST_LOG_DIR variable
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (22 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 23/30] oeqa/sdk/cases: Migrate tests to the new OEQA framework Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 25/30] oeqa/sdkext: Move test cases inside cases directory Aníbal Limón
` (5 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
The TEST_LOG_DIR was used for store sdk_target_log this log
contains the output of the run of build commands now that information
could be found also on log.do_testsdk under WORKDIR.
The log will continue to store into SDK_DIR instead of TEST_LOG_DIR.
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/classes/testsdk.bbclass | 6 ------
meta/lib/oeqa/sdk/cases/buildcvs.py | 4 ++--
meta/lib/oeqa/sdk/cases/buildgalculator.py | 4 ++--
meta/lib/oeqa/sdk/cases/buildiptables.py | 4 ++--
4 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/meta/classes/testsdk.bbclass b/meta/classes/testsdk.bbclass
index 959fb38..4c4df10 100644
--- a/meta/classes/testsdk.bbclass
+++ b/meta/classes/testsdk.bbclass
@@ -14,7 +14,6 @@
#
# where "<image-name>" is an image like core-image-sato.
-TEST_LOG_DIR ?= "${WORKDIR}/testimage"
TESTSDKLOCK = "${TMPDIR}/testsdk.lock"
def run_test_context(CTestContext, d, testdir, tcname, pn, *args):
@@ -64,17 +63,12 @@ def testsdk_main(d):
# sdk use network for download projects for build
export_proxies(d)
- test_log_dir = d.getVar("TEST_LOG_DIR", True)
-
- bb.utils.mkdirhier(test_log_dir)
-
tcname = d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh")
if not os.path.exists(tcname):
bb.fatal("The toolchain %s is not built. Build it before running the tests: 'bitbake <image> -c populate_sdk' ." % tcname)
tdname = d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.testdata.json")
test_data = json.load(open(tdname, "r"))
- test_data['TEST_LOG_DIR'] = test_log_dir
target_pkg_manifest = OESDKTestContextExecutor._load_manifest(
d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.target.manifest"))
diff --git a/meta/lib/oeqa/sdk/cases/buildcvs.py b/meta/lib/oeqa/sdk/cases/buildcvs.py
index ee7fb73..6222a8e 100644
--- a/meta/lib/oeqa/sdk/cases/buildcvs.py
+++ b/meta/lib/oeqa/sdk/cases/buildcvs.py
@@ -2,7 +2,7 @@ from oeqa.sdk.case import OESDKTestCase
from oeqa.sdk.utils.sdkbuildproject import SDKBuildProject
class BuildCvsTest(OESDKTestCase):
- td_vars = ['TEST_LOG_DIR', 'DATETIME']
+ td_vars = ['DATETIME']
@classmethod
def setUpClass(self):
@@ -10,7 +10,7 @@ class BuildCvsTest(OESDKTestCase):
self.project = SDKBuildProject(self.tc.sdk_dir + "/cvs/", self.tc.sdk_env,
"http://ftp.gnu.org/non-gnu/cvs/source/feature/1.12.13/cvs-1.12.13.tar.bz2",
- self.td['TEST_LOG_DIR'], self.td['DATETIME'], dl_dir=dl_dir)
+ self.tc.sdk_dir, self.td['DATETIME'], dl_dir=dl_dir)
self.project.download_archive()
def test_cvs(self):
diff --git a/meta/lib/oeqa/sdk/cases/buildgalculator.py b/meta/lib/oeqa/sdk/cases/buildgalculator.py
index d2c1189..bdc8b6a 100644
--- a/meta/lib/oeqa/sdk/cases/buildgalculator.py
+++ b/meta/lib/oeqa/sdk/cases/buildgalculator.py
@@ -4,7 +4,7 @@ from oeqa.sdk.case import OESDKTestCase
from oeqa.sdk.utils.sdkbuildproject import SDKBuildProject
class GalculatorTest(OESDKTestCase):
- td_vars = ['TEST_LOG_DIR', 'DATETIME']
+ td_vars = ['DATETIME']
@classmethod
def setUpClass(self):
@@ -19,7 +19,7 @@ class GalculatorTest(OESDKTestCase):
project = SDKBuildProject(self.tc.sdk_dir + "/galculator/",
self.tc.sdk_env,
"http://galculator.mnim.org/downloads/galculator-2.1.4.tar.bz2",
- self.td['TEST_LOG_DIR'], self.td['DATETIME'], dl_dir=dl_dir)
+ self.tc.sdk_dir, self.td['DATETIME'], dl_dir=dl_dir)
project.download_archive()
diff --git a/meta/lib/oeqa/sdk/cases/buildiptables.py b/meta/lib/oeqa/sdk/cases/buildiptables.py
index a50fb5d..532b5de 100644
--- a/meta/lib/oeqa/sdk/cases/buildiptables.py
+++ b/meta/lib/oeqa/sdk/cases/buildiptables.py
@@ -2,7 +2,7 @@ from oeqa.sdk.case import OESDKTestCase
from oeqa.sdk.utils.sdkbuildproject import SDKBuildProject
class BuildIptablesTest(OESDKTestCase):
- td_vars = ['TEST_LOG_DIR', 'DATETIME']
+ td_vars = ['DATETIME']
@classmethod
def setUpClass(self):
@@ -10,7 +10,7 @@ class BuildIptablesTest(OESDKTestCase):
self.project = SDKBuildProject(self.tc.sdk_dir + "/iptables/", self.tc.sdk_env,
"http://downloads.yoctoproject.org/mirror/sources/iptables-1.4.13.tar.bz2",
- self.td['TEST_LOG_DIR'], self.td['DATETIME'], dl_dir=dl_dir)
+ self.tc.sdk_dir, self.td['DATETIME'], dl_dir=dl_dir)
self.project.download_archive()
def test_iptables(self):
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 25/30] oeqa/sdkext: Move test cases inside cases directory
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (23 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 24/30] classes/testsdk: Remove the need of TEST_LOG_DIR variable Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 26/30] oeqa/sdkext: Adds case and context modules Aníbal Limón
` (4 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
For match with the new structure of the OEQA framework.
In the new framework Test component base directory in this case
sdk module will contain case and context implementations.
[YOCTO #10599]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/lib/oeqa/sdkext/__init__.py | 3 ---
meta/lib/oeqa/sdkext/{ => cases}/devtool.py | 0
meta/lib/oeqa/sdkext/{ => cases}/sdk_update.py | 0
3 files changed, 3 deletions(-)
rename meta/lib/oeqa/sdkext/{ => cases}/devtool.py (100%)
rename meta/lib/oeqa/sdkext/{ => cases}/sdk_update.py (100%)
diff --git a/meta/lib/oeqa/sdkext/__init__.py b/meta/lib/oeqa/sdkext/__init__.py
index 4cf3fa7..e69de29 100644
--- a/meta/lib/oeqa/sdkext/__init__.py
+++ b/meta/lib/oeqa/sdkext/__init__.py
@@ -1,3 +0,0 @@
-# Enable other layers to have tests in the same named directory
-from pkgutil import extend_path
-__path__ = extend_path(__path__, __name__)
diff --git a/meta/lib/oeqa/sdkext/devtool.py b/meta/lib/oeqa/sdkext/cases/devtool.py
similarity index 100%
rename from meta/lib/oeqa/sdkext/devtool.py
rename to meta/lib/oeqa/sdkext/cases/devtool.py
diff --git a/meta/lib/oeqa/sdkext/sdk_update.py b/meta/lib/oeqa/sdkext/cases/sdk_update.py
similarity index 100%
rename from meta/lib/oeqa/sdkext/sdk_update.py
rename to meta/lib/oeqa/sdkext/cases/sdk_update.py
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 26/30] oeqa/sdkext: Adds case and context modules.
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (24 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 25/30] oeqa/sdkext: Move test cases inside cases directory Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 27/30] classes/testsdk: Migrate to use the new OESDKExtTestContext Aníbal Limón
` (3 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
The extensible sdk context and case modules extends the sdk ones,
this means that the tests from sdk are run also the sdkext tests.
Enables support in context for use oe-test esdk command for run
the test suites, the same options of sdk are required for run esdk tests.
Removes old related to case and context inside oetest.py.
[YOCTO #10599]
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/classes/testsdk.bbclass | 99 +++++++++++++++++++----------------------
meta/lib/oeqa/oetest.py | 40 -----------------
meta/lib/oeqa/sdkext/case.py | 21 +++++++++
meta/lib/oeqa/sdkext/context.py | 21 +++++++++
4 files changed, 88 insertions(+), 93 deletions(-)
create mode 100644 meta/lib/oeqa/sdkext/case.py
create mode 100644 meta/lib/oeqa/sdkext/context.py
diff --git a/meta/classes/testsdk.bbclass b/meta/classes/testsdk.bbclass
index 4c4df10..24529ca 100644
--- a/meta/classes/testsdk.bbclass
+++ b/meta/classes/testsdk.bbclass
@@ -16,37 +16,6 @@
TESTSDKLOCK = "${TMPDIR}/testsdk.lock"
-def run_test_context(CTestContext, d, testdir, tcname, pn, *args):
- import glob
- import time
-
- targets = glob.glob(d.expand(testdir + "/tc/environment-setup-*"))
- for sdkenv in targets:
- bb.plain("Testing %s" % sdkenv)
- tc = CTestContext(d, testdir, sdkenv, tcname, args)
-
- # this is a dummy load of tests
- # we are doing that to find compile errors in the tests themselves
- # before booting the image
- try:
- tc.loadTests()
- except Exception as e:
- import traceback
- bb.fatal("Loading tests failed:\n%s" % traceback.format_exc())
-
- starttime = time.time()
- result = tc.runTests()
- stoptime = time.time()
- if result.wasSuccessful():
- bb.plain("%s SDK(%s):%s - Ran %d test%s in %.3fs" % (pn, os.path.basename(tcname), os.path.basename(sdkenv),result.testsRun, result.testsRun != 1 and "s" or "", stoptime - starttime))
- msg = "%s - OK - All required tests passed" % pn
- skipped = len(result.skipped)
- if skipped:
- msg += " (skipped=%d)" % skipped
- bb.plain(msg)
- else:
- bb.fatal("%s - FAILED - check the task log and the commands log" % pn)
-
def testsdk_main(d):
import os
import subprocess
@@ -121,16 +90,20 @@ addtask testsdk
do_testsdk[nostamp] = "1"
do_testsdk[lockfiles] += "${TESTSDKLOCK}"
-TEST_LOG_SDKEXT_DIR ?= "${WORKDIR}/testsdkext"
TESTSDKEXTLOCK = "${TMPDIR}/testsdkext.lock"
def testsdkext_main(d):
import os
- import oeqa.sdkext
+ import json
import subprocess
+ import logging
+
from bb.utils import export_proxies
- from oeqa.oetest import SDKTestContext, SDKExtTestContext
from oeqa.utils import avoid_paths_in_environ
+ from oeqa.sdk.context import OESDKExtTestContext, OESDKExtTestContextExecutor
+
+ pn = d.getVar("PN", True)
+ logger = logging.getLogger("BitBake")
# extensible sdk use network
export_proxies(d)
@@ -141,20 +114,24 @@ def testsdkext_main(d):
d.getVar('BASE_WORKDIR', True)]
os.environ['PATH'] = avoid_paths_in_environ(paths_to_avoid)
- pn = d.getVar("PN", True)
- bb.utils.mkdirhier(d.getVar("TEST_LOG_SDKEXT_DIR", True))
-
tcname = d.expand("${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.sh")
if not os.path.exists(tcname):
bb.fatal("The toolchain ext %s is not built. Build it before running the" \
" tests: 'bitbake <image> -c populate_sdk_ext' ." % tcname)
- testdir = d.expand("${WORKDIR}/testsdkext/")
- bb.utils.remove(testdir, True)
- bb.utils.mkdirhier(testdir)
- sdkdir = os.path.join(testdir, 'tc')
+ tdname = d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.testdata.json")
+ test_data = json.load(open(tdname, "r"))
+
+ target_pkg_manifest = OESDKExtTestContextExecutor._load_manifest(
+ d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.target.manifest"))
+ host_pkg_manifest = OESDKExtTestContextExecutor._load_manifest(
+ d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.host.manifest"))
+
+ sdk_dir = d.expand("${WORKDIR}/testsdkext/")
+ bb.utils.remove(sdk_dir, True)
+ bb.utils.mkdirhier(sdk_dir)
try:
- subprocess.check_output("%s -y -d %s" % (tcname, sdkdir), shell=True)
+ subprocess.check_output("%s -y -d %s" % (tcname, sdk_dir), shell=True)
except subprocess.CalledProcessError as e:
msg = "Couldn't install the extensible SDK:\n%s" % e.output.decode("utf-8")
logfn = os.path.join(sdkdir, 'preparing_build_system.log')
@@ -165,19 +142,35 @@ def testsdkext_main(d):
msg += line
bb.fatal(msg)
- try:
- bb.plain("Running SDK Compatibility tests ...")
- run_test_context(SDKExtTestContext, d, testdir, tcname, pn, True)
- finally:
- pass
+ fail = False
+ sdk_envs = OESDKExtTestContextExecutor._get_sdk_environs(sdk_dir)
+ for s in sdk_envs:
+ bb.plain("Extensible SDK testing environment: %s" % s)
- try:
- bb.plain("Running Extensible SDK tests ...")
- run_test_context(SDKExtTestContext, d, testdir, tcname, pn)
- finally:
- pass
+ sdk_env = sdk_envs[s]
+ tc = OESDKExtTestContext(td=test_data, logger=logger, sdk_dir=sdk_dir,
+ sdk_env=sdk_env, target_pkg_manifest=target_pkg_manifest,
+ host_pkg_manifest=host_pkg_manifest)
- bb.utils.remove(testdir, True)
+ try:
+ tc.loadTests(OESDKExtTestContextExecutor.default_cases)
+ except Exception as e:
+ import traceback
+ bb.fatal("Loading tests failed:\n%s" % traceback.format_exc())
+
+ result = tc.runTests()
+
+ component = "%s %s" % (pn, OESDKExtTestContextExecutor.name)
+ context_msg = "%s:%s" % (os.path.basename(tcname), os.path.basename(sdk_env))
+
+ tc.logSummary(result, component, context_msg)
+ tc.logDetails()
+
+ if not result.wasSuccessful():
+ fail = True
+
+ if fail:
+ bb.fatal("%s - FAILED - check the task log and the commands log" % pn)
testsdkext_main[vardepsexclude] =+ "BB_ORIGENV"
diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index 4a98b0f1..f9e9025 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -27,7 +27,6 @@ try:
except ImportError:
pass
from oeqa.utils.decorators import LogResults, gettag, getResults
-from oeqa.utils import avoid_paths_in_environ
logger = logging.getLogger("BitBake")
@@ -145,18 +144,6 @@ class OETestCalledProcessError(subprocess.CalledProcessError):
subprocess.CalledProcessError = OETestCalledProcessError
-class oeSDKExtTest(oeSDKTest):
- def _run(self, cmd):
- # extensible sdk shows a warning if found bitbake in the path
- # because can cause contamination, i.e. use devtool from
- # poky/scripts instead of eSDK one.
- env = os.environ.copy()
- paths_to_avoid = ['bitbake/bin', 'poky/scripts']
- env['PATH'] = avoid_paths_in_environ(paths_to_avoid)
-
- return subprocess.check_output(". %s > /dev/null;"\
- " %s;" % (self.tc.sdkenv, cmd), stderr=subprocess.STDOUT, shell=True, env=env).decode("utf-8")
-
def getmodule(pos=2):
# stack returns a list of tuples containg frame information
# First element of the list the is current frame, caller is 1
@@ -642,30 +629,3 @@ class ExportTestContext(RuntimeTestContext):
extracted_dir = self.d.getVar("TEST_EXPORT_EXTRACTED_DIR", True)
pkg_dir = os.path.join(export_dir, extracted_dir)
super(ExportTestContext, self).install_uninstall_packages(test_id, pkg_dir, install)
-
-class SDKExtTestContext(SDKTestContext):
- def __init__(self, d, sdktestdir, sdkenv, tcname, *args):
- self.target_manifest = d.getVar("SDK_EXT_TARGET_MANIFEST", True)
- self.host_manifest = d.getVar("SDK_EXT_HOST_MANIFEST", True)
- if args:
- self.cm = args[0] # Compatibility mode for run SDK tests
- else:
- self.cm = False
-
- super(SDKExtTestContext, self).__init__(d, sdktestdir, sdkenv, tcname)
-
- self.sdkextfilesdir = os.path.join(os.path.dirname(os.path.abspath(
- oeqa.sdkext.__file__)), "files")
-
- def _get_test_namespace(self):
- if self.cm:
- return "sdk"
- else:
- return "sdkext"
-
- def _get_test_suites(self):
- return (self.d.getVar("TEST_SUITES_SDK_EXT", True) or "auto").split()
-
- def _get_test_suites_required(self):
- return [t for t in (self.d.getVar("TEST_SUITES_SDK_EXT", True) or \
- "auto").split() if t != "auto"]
diff --git a/meta/lib/oeqa/sdkext/case.py b/meta/lib/oeqa/sdkext/case.py
new file mode 100644
index 0000000..6f708aa
--- /dev/null
+++ b/meta/lib/oeqa/sdkext/case.py
@@ -0,0 +1,21 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import os
+import subprocess
+
+from oeqa.utils import avoid_paths_in_environ
+from oeqa.sdk.case import OESDKTestCase
+
+class OESDKExtTestCase(OESDKTestCase):
+ def _run(self, cmd):
+ # extensible sdk shows a warning if found bitbake in the path
+ # because can cause contamination, i.e. use devtool from
+ # poky/scripts instead of eSDK one.
+ env = os.environ.copy()
+ paths_to_avoid = ['bitbake/bin', 'poky/scripts']
+ env['PATH'] = avoid_paths_in_environ(paths_to_avoid)
+
+ return subprocess.check_output(". %s > /dev/null;"\
+ " %s;" % (self.tc.sdk_env, cmd), stderr=subprocess.STDOUT,
+ shell=True, env=env).decode("utf-8")
diff --git a/meta/lib/oeqa/sdkext/context.py b/meta/lib/oeqa/sdkext/context.py
new file mode 100644
index 0000000..8dbcd80
--- /dev/null
+++ b/meta/lib/oeqa/sdkext/context.py
@@ -0,0 +1,21 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
+import os
+from oeqa.sdk.context import OESDKTestContext, OESDKTestContextExecutor
+
+class OESDKExtTestContext(OESDKTestContext):
+ esdk_files_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files")
+
+class OESDKExtTestContextExecutor(OESDKTestContextExecutor):
+ _context_class = OESDKExtTestContext
+
+ name = 'esdk'
+ help = 'esdk test component'
+ description = 'executes esdk tests'
+
+ default_cases = [OESDKTestContextExecutor.default_cases[0],
+ os.path.join(os.path.abspath(os.path.dirname(__file__)), 'cases')]
+ default_test_data = None
+
+_executor_class = OESDKExtTestContextExecutor
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 27/30] classes/testsdk: Migrate to use the new OESDKExtTestContext
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (25 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 26/30] oeqa/sdkext: Adds case and context modules Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 28/30] oeqa/sdkext/cases: Migrate test case to new OEQA framework Aníbal Limón
` (2 subsequent siblings)
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/classes/testsdk.bbclass | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/meta/classes/testsdk.bbclass b/meta/classes/testsdk.bbclass
index 24529ca..1d6547a 100644
--- a/meta/classes/testsdk.bbclass
+++ b/meta/classes/testsdk.bbclass
@@ -100,7 +100,7 @@ def testsdkext_main(d):
from bb.utils import export_proxies
from oeqa.utils import avoid_paths_in_environ
- from oeqa.sdk.context import OESDKExtTestContext, OESDKExtTestContextExecutor
+ from oeqa.sdkext.context import OESDKExtTestContext, OESDKExtTestContextExecutor
pn = d.getVar("PN", True)
logger = logging.getLogger("BitBake")
@@ -119,13 +119,13 @@ def testsdkext_main(d):
bb.fatal("The toolchain ext %s is not built. Build it before running the" \
" tests: 'bitbake <image> -c populate_sdk_ext' ." % tcname)
- tdname = d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.testdata.json")
+ tdname = d.expand("${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.testdata.json")
test_data = json.load(open(tdname, "r"))
target_pkg_manifest = OESDKExtTestContextExecutor._load_manifest(
- d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.target.manifest"))
+ d.expand("${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.target.manifest"))
host_pkg_manifest = OESDKExtTestContextExecutor._load_manifest(
- d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.host.manifest"))
+ d.expand("${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.host.manifest"))
sdk_dir = d.expand("${WORKDIR}/testsdkext/")
bb.utils.remove(sdk_dir, True)
@@ -134,7 +134,7 @@ def testsdkext_main(d):
subprocess.check_output("%s -y -d %s" % (tcname, sdk_dir), shell=True)
except subprocess.CalledProcessError as e:
msg = "Couldn't install the extensible SDK:\n%s" % e.output.decode("utf-8")
- logfn = os.path.join(sdkdir, 'preparing_build_system.log')
+ logfn = os.path.join(sdk_dir, 'preparing_build_system.log')
if os.path.exists(logfn):
msg += '\n\nContents of preparing_build_system.log:\n'
with open(logfn, 'r') as f:
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 28/30] oeqa/sdkext/cases: Migrate test case to new OEQA framework
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (26 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 27/30] classes/testsdk: Migrate to use the new OESDKExtTestContext Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 29/30] oeqa/runtime: Fix TargetBuildProject instances Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 30/30] oeqa: Fix files handling on runtime tests Aníbal Limón
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
Summary,
- Changes base case class to OESDKExtTest.
- Changes decorator classes to new ones.
- Chnages variable names sdktestdir -> sdk_dir.
- Added missing license to MIT.
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/lib/oeqa/sdk/cases/buildgalculator.py | 2 +-
meta/lib/oeqa/sdk/cases/gcc.py | 2 +-
meta/lib/oeqa/sdkext/cases/devtool.py | 49 ++++++++++++++++--------------
meta/lib/oeqa/sdkext/cases/sdk_update.py | 17 ++++++-----
4 files changed, 38 insertions(+), 32 deletions(-)
diff --git a/meta/lib/oeqa/sdk/cases/buildgalculator.py b/meta/lib/oeqa/sdk/cases/buildgalculator.py
index bdc8b6a..b9b24ee 100644
--- a/meta/lib/oeqa/sdk/cases/buildgalculator.py
+++ b/meta/lib/oeqa/sdk/cases/buildgalculator.py
@@ -10,7 +10,7 @@ class GalculatorTest(OESDKTestCase):
def setUpClass(self):
if not (self.tc.hasTargetPackage("gtk+3") or\
self.tc.hasTargetPackage("libgtk-3.0")):
- raise unittest.SkipTest("%s class: SDK don't support gtk+3" % self.__name__)
+ raise unittest.SkipTest("%s class: SDK don't support gtk+3" % self.__class__.__name__)
def test_galculator(self):
dl_dir = self.td.get('DL_DIR', None)
diff --git a/meta/lib/oeqa/sdk/cases/gcc.py b/meta/lib/oeqa/sdk/cases/gcc.py
index e06af4c..36725e3 100644
--- a/meta/lib/oeqa/sdk/cases/gcc.py
+++ b/meta/lib/oeqa/sdk/cases/gcc.py
@@ -20,7 +20,7 @@ class GccCompileTest(OESDKTestCase):
machine = self.td.get("MACHINE")
if not self.tc.hasHostPackage("packagegroup-cross-canadian-%s" % machine):
raise unittest.SkipTest("%s class: SDK doesn't contain a cross-canadian toolchain",
- self.__name__)
+ self.__class__.__name__)
def test_gcc_compile(self):
self._run('$CC %s/test.c -o %s/test -lm' % (self.tc.sdk_dir, self.tc.sdk_dir))
diff --git a/meta/lib/oeqa/sdkext/cases/devtool.py b/meta/lib/oeqa/sdkext/cases/devtool.py
index 65f41f6..da0050c 100644
--- a/meta/lib/oeqa/sdkext/cases/devtool.py
+++ b/meta/lib/oeqa/sdkext/cases/devtool.py
@@ -1,18 +1,22 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
import shutil
import subprocess
-import urllib.request
-from oeqa.oetest import oeSDKExtTest
-from oeqa.utils.decorators import *
-class DevtoolTest(oeSDKExtTest):
+from oeqa.sdkext.case import OESDKExtTestCase
+from oeqa.core.decorator.depends import OETestDepends
+from oeqa.core.decorator.oeid import OETestID
+
+class DevtoolTest(OESDKExtTestCase):
@classmethod
def setUpClass(self):
- self.myapp_src = os.path.join(self.tc.sdkextfilesdir, "myapp")
- self.myapp_dst = os.path.join(self.tc.sdktestdir, "myapp")
+ self.myapp_src = os.path.join(self.tc.esdk_files_dir, "myapp")
+ self.myapp_dst = os.path.join(self.tc.sdk_dir, "myapp")
shutil.copytree(self.myapp_src, self.myapp_dst)
- self.myapp_cmake_src = os.path.join(self.tc.sdkextfilesdir, "myapp_cmake")
- self.myapp_cmake_dst = os.path.join(self.tc.sdktestdir, "myapp_cmake")
+ self.myapp_cmake_src = os.path.join(self.tc.esdk_files_dir, "myapp_cmake")
+ self.myapp_cmake_dst = os.path.join(self.tc.sdk_dir, "myapp_cmake")
shutil.copytree(self.myapp_cmake_src, self.myapp_cmake_dst)
def _test_devtool_build(self, directory):
@@ -37,31 +41,31 @@ class DevtoolTest(oeSDKExtTest):
def test_devtool_location(self):
output = self._run('which devtool')
- self.assertEqual(output.startswith(self.tc.sdktestdir), True, \
+ self.assertEqual(output.startswith(self.tc.sdk_dir), True, \
msg="Seems that devtool isn't the eSDK one: %s" % output)
- @skipUnlessPassed('test_devtool_location')
+ @OETestDepends(['test_devtool_location'])
def test_devtool_add_reset(self):
self._run('devtool add myapp %s' % self.myapp_dst)
self._run('devtool reset myapp')
- @testcase(1473)
- @skipUnlessPassed('test_devtool_location')
+ @OETestID(1473)
+ @OETestDepends(['test_devtool_location'])
def test_devtool_build_make(self):
self._test_devtool_build(self.myapp_dst)
- @testcase(1474)
- @skipUnlessPassed('test_devtool_location')
+ @OETestID(1474)
+ @OETestDepends(['test_devtool_location'])
def test_devtool_build_esdk_package(self):
self._test_devtool_build_package(self.myapp_dst)
- @testcase(1479)
- @skipUnlessPassed('test_devtool_location')
+ @OETestID(1479)
+ @OETestDepends(['test_devtool_location'])
def test_devtool_build_cmake(self):
self._test_devtool_build(self.myapp_cmake_dst)
- @testcase(1482)
- @skipUnlessPassed('test_devtool_location')
+ @OETestID(1482)
+ @OETestDepends(['test_devtool_location'])
def test_extend_autotools_recipe_creation(self):
req = 'https://github.com/rdfa/librdfa'
recipe = "bbexample"
@@ -74,8 +78,8 @@ class DevtoolTest(oeSDKExtTest):
raise e
self._run('devtool reset %s' % recipe)
- @testcase(1484)
- @skipUnlessPassed('test_devtool_location')
+ @OETestID(1484)
+ @OETestDepends(['test_devtool_location'])
def test_devtool_kernelmodule(self):
docfile = 'https://github.com/umlaeute/v4l2loopback.git'
recipe = 'v4l2loopback-driver'
@@ -88,8 +92,8 @@ class DevtoolTest(oeSDKExtTest):
raise e
self._run('devtool reset %s' % recipe)
- @testcase(1478)
- @skipUnlessPassed('test_devtool_location')
+ @OETestID(1478)
+ @OETestDepends(['test_devtool_location'])
def test_recipes_for_nodejs(self):
package_nodejs = "npm://registry.npmjs.org;name=winston;version=2.2.0"
self._run('devtool add %s ' % package_nodejs)
@@ -101,7 +105,6 @@ class DevtoolTest(oeSDKExtTest):
raise e
self._run('devtool reset %s '% package_nodejs)
-
@classmethod
def tearDownClass(self):
shutil.rmtree(self.myapp_dst)
diff --git a/meta/lib/oeqa/sdkext/cases/sdk_update.py b/meta/lib/oeqa/sdkext/cases/sdk_update.py
index 2ade839..2f8598b 100644
--- a/meta/lib/oeqa/sdkext/cases/sdk_update.py
+++ b/meta/lib/oeqa/sdkext/cases/sdk_update.py
@@ -1,23 +1,26 @@
+# Copyright (C) 2016 Intel Corporation
+# Released under the MIT license (see COPYING.MIT)
+
import os
import shutil
import subprocess
-from oeqa.oetest import oeSDKExtTest
+from oeqa.sdkext.case import OESDKExtTestCase
from oeqa.utils.httpserver import HTTPService
-class SdkUpdateTest(oeSDKExtTest):
-
+class SdkUpdateTest(OESDKExtTestCase):
@classmethod
def setUpClass(self):
- self.publish_dir = os.path.join(self.tc.sdktestdir, 'esdk_publish')
+ self.publish_dir = os.path.join(self.tc.sdk_dir, 'esdk_publish')
if os.path.exists(self.publish_dir):
shutil.rmtree(self.publish_dir)
os.mkdir(self.publish_dir)
- tcname_new = self.tc.d.expand(
- "${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}-new.sh")
+ base_tcname = "%s/%s" % (self.td.get("SDK_DEPLOY", ''),
+ self.td.get("TOOLCHAINEXT_OUTPUTNAME", ''))
+ tcname_new = "%s-new.sh" % base_tcname
if not os.path.exists(tcname_new):
- tcname_new = self.tc.tcname
+ tcname_new = "%s.sh" % base_tcname
cmd = 'oe-publish-sdk %s %s' % (tcname_new, self.publish_dir)
subprocess.check_output(cmd, shell=True)
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 29/30] oeqa/runtime: Fix TargetBuildProject instances
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (27 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 28/30] oeqa/sdkext/cases: Migrate test case to new OEQA framework Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
2016-12-08 16:20 ` [PATCHv3 30/30] oeqa: Fix files handling on runtime tests Aníbal Limón
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
TargetBuildProject was refactored to avoid bitbake dependency so
the instance don't allow to pass data store anymore.
classes/testimage: Export proxies before run tests
The TargetBuildProject based tests download archives from network.
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/classes/testimage.bbclass | 4 ++++
meta/lib/oeqa/runtime/buildcvs.py | 9 +++++----
meta/lib/oeqa/runtime/buildgalculator.py | 8 +++++---
meta/lib/oeqa/runtime/buildiptables.py | 8 +++++---
4 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass
index 6b6781d..89ed003 100644
--- a/meta/classes/testimage.bbclass
+++ b/meta/classes/testimage.bbclass
@@ -129,11 +129,15 @@ def testimage_main(d):
from oeqa.oetest import ImageTestContext
from oeqa.targetcontrol import get_target_controller
from oeqa.utils.dump import get_host_dumper
+ from bb.utils import export_proxies
pn = d.getVar("PN", True)
bb.utils.mkdirhier(d.getVar("TEST_LOG_DIR", True))
test_create_extract_dirs(d)
+ # runtime use network for download projects for build
+ export_proxies(d)
+
# we need the host dumper in test context
host_dumper = get_host_dumper(d)
diff --git a/meta/lib/oeqa/runtime/buildcvs.py b/meta/lib/oeqa/runtime/buildcvs.py
index fe6cbfb..a5ca3a5 100644
--- a/meta/lib/oeqa/runtime/buildcvs.py
+++ b/meta/lib/oeqa/runtime/buildcvs.py
@@ -1,6 +1,6 @@
from oeqa.oetest import oeRuntimeTest, skipModule
from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import TargetBuildProject
+from oeqa.runtime.utils.targetbuildproject import TargetBuildProject
def setUpModule():
if not oeRuntimeTest.hasFeature("tools-sdk"):
@@ -10,9 +10,10 @@ class BuildCvsTest(oeRuntimeTest):
@classmethod
def setUpClass(self):
- self.project = TargetBuildProject(oeRuntimeTest.tc.target, oeRuntimeTest.tc.d,
- "http://ftp.gnu.org/non-gnu/cvs/source/feature/1.12.13/cvs-1.12.13.tar.bz2")
- self.project.download_archive()
+ dl_dir = oeRuntimeTest.tc.d.getVar('DL_DIR', True)
+ self.project = TargetBuildProject(oeRuntimeTest.tc.target,
+ "http://ftp.gnu.org/non-gnu/cvs/source/feature/1.12.13/cvs-1.12.13.tar.bz2",
+ dl_dir=dl_dir)
@testcase(205)
@skipUnlessPassed("test_ssh")
diff --git a/meta/lib/oeqa/runtime/buildgalculator.py b/meta/lib/oeqa/runtime/buildgalculator.py
index 220101d..20f0a79 100644
--- a/meta/lib/oeqa/runtime/buildgalculator.py
+++ b/meta/lib/oeqa/runtime/buildgalculator.py
@@ -1,6 +1,6 @@
from oeqa.oetest import oeRuntimeTest, skipModule
from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import TargetBuildProject
+from oeqa.runtime.utils.targetbuildproject import TargetBuildProject
def setUpModule():
if not oeRuntimeTest.hasFeature("tools-sdk"):
@@ -10,9 +10,11 @@ class GalculatorTest(oeRuntimeTest):
@testcase(1526)
@skipUnlessPassed("test_ssh")
def test_galculator(self):
+ dl_dir = oeRuntimeTest.tc.d.getVar('DL_DIR', True)
try:
- project = TargetBuildProject(oeRuntimeTest.tc.target, oeRuntimeTest.tc.d,
- "http://galculator.mnim.org/downloads/galculator-2.1.4.tar.bz2")
+ project = TargetBuildProject(oeRuntimeTest.tc.target,
+ "http://galculator.mnim.org/downloads/galculator-2.1.4.tar.bz2",
+ dl_dir=dl_dir)
project.download_archive()
self.assertEqual(project.run_configure(), 0,
diff --git a/meta/lib/oeqa/runtime/buildiptables.py b/meta/lib/oeqa/runtime/buildiptables.py
index bc75d0a..a0e82f0 100644
--- a/meta/lib/oeqa/runtime/buildiptables.py
+++ b/meta/lib/oeqa/runtime/buildiptables.py
@@ -1,6 +1,6 @@
from oeqa.oetest import oeRuntimeTest, skipModule
from oeqa.utils.decorators import *
-from oeqa.utils.targetbuild import TargetBuildProject
+from oeqa.runtime.utils.targetbuildproject import TargetBuildProject
def setUpModule():
if not oeRuntimeTest.hasFeature("tools-sdk"):
@@ -10,8 +10,10 @@ class BuildIptablesTest(oeRuntimeTest):
@classmethod
def setUpClass(self):
- self.project = TargetBuildProject(oeRuntimeTest.tc.target, oeRuntimeTest.tc.d,
- "http://downloads.yoctoproject.org/mirror/sources/iptables-1.4.13.tar.bz2")
+ dl_dir = oeRuntimeTest.tc.d.getVar('DL_DIR', True)
+ self.project = TargetBuildProject(oeRuntimeTest.tc.target,
+ "http://downloads.yoctoproject.org/mirror/sources/iptables-1.4.13.tar.bz2",
+ dl_dir=dl_dir)
self.project.download_archive()
@testcase(206)
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCHv3 30/30] oeqa: Fix files handling on runtime tests.
2016-12-08 16:20 [PATCHv3 00/30] OEQA Framework Refactor & Improvements Aníbal Limón
` (28 preceding siblings ...)
2016-12-08 16:20 ` [PATCHv3 29/30] oeqa/runtime: Fix TargetBuildProject instances Aníbal Limón
@ 2016-12-08 16:20 ` Aníbal Limón
29 siblings, 0 replies; 31+ messages in thread
From: Aníbal Limón @ 2016-12-08 16:20 UTC (permalink / raw)
To: openembedded-core
Common files was move to oeqa/files from oeqa/runtime/files
because the same files are used across Runtime,SDK,eSDK tests.
Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
---
meta/classes/testexport.bbclass | 5 +++++
meta/lib/oeqa/oetest.py | 1 +
meta/lib/oeqa/runtime/gcc.py | 4 ++--
meta/lib/oeqa/runtime/perl.py | 2 +-
meta/lib/oeqa/runtime/python.py | 2 +-
5 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/meta/classes/testexport.bbclass b/meta/classes/testexport.bbclass
index 5147020..a3ccd63 100644
--- a/meta/classes/testexport.bbclass
+++ b/meta/classes/testexport.bbclass
@@ -87,6 +87,7 @@ def exportTests(d,tc):
# - the contents of oeqa/utils and oeqa/runtime/files
# - oeqa/oetest.py and oeqa/runexport.py (this will get copied to exportpath not exportpath/oeqa)
# - __init__.py files
+ bb.utils.mkdirhier(os.path.join(exportpath, "oeqa/files"))
bb.utils.mkdirhier(os.path.join(exportpath, "oeqa/runtime/files"))
bb.utils.mkdirhier(os.path.join(exportpath, "oeqa/utils"))
# copy test modules, this should cover tests in other layers too
@@ -124,6 +125,10 @@ def exportTests(d,tc):
for f in files:
if f.endswith(".py"):
shutil.copy2(os.path.join(root, f), os.path.join(exportpath, "oeqa/utils"))
+ # copy oeqa/files/*
+ for root, dirs, files in os.walk(os.path.join(oeqadir, "files")):
+ for f in files:
+ shutil.copy2(os.path.join(root, f), os.path.join(exportpath, "oeqa/files"))
# copy oeqa/runtime/files/*
for root, dirs, files in os.walk(os.path.join(oeqadir, "runtime/files")):
for f in files:
diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index f9e9025..48bcafc 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -201,6 +201,7 @@ class TestContext(object):
self.testsrequired = self._get_test_suites_required()
self.filesdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "runtime/files")
+ self.corefilesdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files")
self.imagefeatures = d.getVar("IMAGE_FEATURES", True).split()
self.distrofeatures = d.getVar("DISTRO_FEATURES", True).split()
diff --git a/meta/lib/oeqa/runtime/gcc.py b/meta/lib/oeqa/runtime/gcc.py
index d90cd17..6edb89f 100644
--- a/meta/lib/oeqa/runtime/gcc.py
+++ b/meta/lib/oeqa/runtime/gcc.py
@@ -12,9 +12,9 @@ class GccCompileTest(oeRuntimeTest):
@classmethod
def setUpClass(self):
- oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "test.c"), "/tmp/test.c")
+ oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.corefilesdir, "test.c"), "/tmp/test.c")
oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "testmakefile"), "/tmp/testmakefile")
- oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "test.cpp"), "/tmp/test.cpp")
+ oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.corefilesdir, "test.cpp"), "/tmp/test.cpp")
@testcase(203)
def test_gcc_compile(self):
diff --git a/meta/lib/oeqa/runtime/perl.py b/meta/lib/oeqa/runtime/perl.py
index e044d0a..6bf98f1 100644
--- a/meta/lib/oeqa/runtime/perl.py
+++ b/meta/lib/oeqa/runtime/perl.py
@@ -12,7 +12,7 @@ class PerlTest(oeRuntimeTest):
@classmethod
def setUpClass(self):
- oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "test.pl"), "/tmp/test.pl")
+ oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.corefilesdir, "test.pl"), "/tmp/test.pl")
@testcase(1141)
def test_perl_exists(self):
diff --git a/meta/lib/oeqa/runtime/python.py b/meta/lib/oeqa/runtime/python.py
index 29a231c..93e822c 100644
--- a/meta/lib/oeqa/runtime/python.py
+++ b/meta/lib/oeqa/runtime/python.py
@@ -12,7 +12,7 @@ class PythonTest(oeRuntimeTest):
@classmethod
def setUpClass(self):
- oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "test.py"), "/tmp/test.py")
+ oeRuntimeTest.tc.target.copy_to(os.path.join(oeRuntimeTest.tc.corefilesdir, "test.py"), "/tmp/test.py")
@testcase(1145)
def test_python_exists(self):
--
2.1.4
^ permalink raw reply related [flat|nested] 31+ messages in thread