All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] Allow to install packages in the DUT during runtime testing
@ 2016-05-24 12:44 mariano.lopez
  2016-05-24 12:44 ` [PATCH 01/10] testexport.bbclass: Stop exporting test context mariano.lopez
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: mariano.lopez @ 2016-05-24 12:44 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

This series enable the functionality to install packages in the DUT
during runtime testing. Such packages must had been build previously
by bitbake and the packages are specified using a JSON file. This
functionality works with testimage and with testexport.

A documentation draft has been submitted in bug 9672 to be added to
the Reference Manual.

This address several bugs:
  - 7850 (not solved completely)
  - 8478
  - 8694
  - 8536

The following changes since commit c7e614c438706fb3ed7520b4990ebb3973366942:

  useradd: Fix infinite build loop (2016-05-23 10:33:45 +0100)

are available in the git repository at:

  git://git.yoctoproject.org/poky-contrib mariano/bug7850v2
  http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=mariano/bug7850v2

Mariano Lopez (10):
  testexport.bbclass: Stop exporting test context
  oetest.py: Move getTests() outside loadTests() method
  oeqa/utils/package_manager.py: Add get_package_manager()
  oetest.py: Add json file support to specify packages needed in runtime
    tests
  oetest.py: Add extract_packages() to RuntimeTestContext class
  oetest.py: Add support to copy unextracted packages for runtime
    testing
  lib/oe/package_manager.py: Add pkgpath to dict returned by
    package_info
  oetest.py: Add install/uninstall functionality for DUTs
  cpio: Add native variant
  testimage.bbclass: Make dependency of cpio when using RPMs

 meta/classes/testexport.bbclass        |  33 +++--
 meta/classes/testimage.bbclass         |  47 ++++++-
 meta/lib/oe/package_manager.py         |  41 +++---
 meta/lib/oeqa/oetest.py                | 239 ++++++++++++++++++++++++++++++---
 meta/lib/oeqa/utils/package_manager.py |  29 ++++
 meta/recipes-extended/cpio/cpio_v2.inc |   2 +
 6 files changed, 347 insertions(+), 44 deletions(-)
 create mode 100644 meta/lib/oeqa/utils/package_manager.py

-- 
2.6.6



^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 01/10] testexport.bbclass: Stop exporting test context
  2016-05-24 12:44 [PATCH 00/10] Allow to install packages in the DUT during runtime testing mariano.lopez
@ 2016-05-24 12:44 ` mariano.lopez
  2016-05-24 12:44 ` [PATCH 02/10] oetest.py: Move getTests() outside loadTests() method mariano.lopez
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: mariano.lopez @ 2016-05-24 12:44 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

Because runexported.py instance an ExportTestContext
object, there is no need to export the data in
to reconstruct the object based in a dummy class.

[YOCTO #8478]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/classes/testexport.bbclass | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/meta/classes/testexport.bbclass b/meta/classes/testexport.bbclass
index 0aac030..e06c668 100644
--- a/meta/classes/testexport.bbclass
+++ b/meta/classes/testexport.bbclass
@@ -43,10 +43,6 @@ def exportTests(d,tc):
     savedata = {}
     savedata["d"] = {}
     savedata["target"] = {}
-    for key in tc.__dict__:
-        # special cases
-        if key not in ['d', 'target', 'suite']:
-            savedata[key] = getattr(tc, key)
     savedata["target"]["ip"] = tc.target.ip or d.getVar("TEST_TARGET_IP", True)
     savedata["target"]["server_ip"] = tc.target.server_ip or d.getVar("TEST_SERVER_IP", True)
 
-- 
2.6.6



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 02/10] oetest.py: Move getTests() outside loadTests() method
  2016-05-24 12:44 [PATCH 00/10] Allow to install packages in the DUT during runtime testing mariano.lopez
  2016-05-24 12:44 ` [PATCH 01/10] testexport.bbclass: Stop exporting test context mariano.lopez
@ 2016-05-24 12:44 ` mariano.lopez
  2016-05-24 12:44 ` [PATCH 03/10] oeqa/utils/package_manager.py: Add get_package_manager() mariano.lopez
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: mariano.lopez @ 2016-05-24 12:44 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

The method getTests() can be useful to all the class,
not just to loadTests().

[YOCTO #8694]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/lib/oeqa/oetest.py | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index 70db119..8ad3715 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -264,6 +264,22 @@ class TestContext(object):
 
         return testslist
 
+    def getTests(self, test):
+        '''Return all individual tests executed when running the suite.'''
+        # Unfortunately unittest does not have an API for this, so we have
+        # to rely on implementation details. This only needs to work
+        # for TestSuite containing TestCase.
+        method = getattr(test, '_testMethodName', None)
+        if method:
+            # leaf case: a TestCase
+            yield test
+        else:
+            # Look into TestSuite.
+            tests = getattr(test, '_tests', [])
+            for t1 in tests:
+                for t2 in self.getTests(t1):
+                    yield t2
+
     def loadTests(self):
         setattr(oeTest, "tc", self)
 
@@ -272,36 +288,20 @@ class TestContext(object):
         suites = [testloader.loadTestsFromName(name) for name in self.testslist]
         suites = filterByTagExp(suites, getattr(self, "tagexp", None))
 
-        def getTests(test):
-            '''Return all individual tests executed when running the suite.'''
-            # Unfortunately unittest does not have an API for this, so we have
-            # to rely on implementation details. This only needs to work
-            # for TestSuite containing TestCase.
-            method = getattr(test, '_testMethodName', None)
-            if method:
-                # leaf case: a TestCase
-                yield test
-            else:
-                # Look into TestSuite.
-                tests = getattr(test, '_tests', [])
-                for t1 in tests:
-                    for t2 in getTests(t1):
-                        yield t2
-
         # Determine dependencies between suites by looking for @skipUnlessPassed
         # method annotations. Suite A depends on suite B if any method in A
         # depends on a method on B.
         for suite in suites:
             suite.dependencies = []
             suite.depth = 0
-            for test in getTests(suite):
+            for test in self.getTests(suite):
                 methodname = getattr(test, '_testMethodName', None)
                 if methodname:
                     method = getattr(test, methodname)
                     depends_on = getattr(method, '_depends_on', None)
                     if depends_on:
                         for dep_suite in suites:
-                            if depends_on in [getattr(t, '_testMethodName', None) for t in getTests(dep_suite)]:
+                            if depends_on in [getattr(t, '_testMethodName', None) for t in self.getTests(dep_suite)]:
                                 if dep_suite not in suite.dependencies and \
                                    dep_suite is not suite:
                                     suite.dependencies.append(dep_suite)
-- 
2.6.6



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 03/10] oeqa/utils/package_manager.py: Add get_package_manager()
  2016-05-24 12:44 [PATCH 00/10] Allow to install packages in the DUT during runtime testing mariano.lopez
  2016-05-24 12:44 ` [PATCH 01/10] testexport.bbclass: Stop exporting test context mariano.lopez
  2016-05-24 12:44 ` [PATCH 02/10] oetest.py: Move getTests() outside loadTests() method mariano.lopez
@ 2016-05-24 12:44 ` mariano.lopez
  2016-05-24 12:44 ` [PATCH 04/10] oetest.py: Add json file support to specify packages needed in runtime tests mariano.lopez
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: mariano.lopez @ 2016-05-24 12:44 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

This new file just contain one function to return an OE package
manager, this depends in the current packaging method.

[YOCTO #8694]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/lib/oeqa/utils/package_manager.py | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 meta/lib/oeqa/utils/package_manager.py

diff --git a/meta/lib/oeqa/utils/package_manager.py b/meta/lib/oeqa/utils/package_manager.py
new file mode 100644
index 0000000..099ecc9
--- /dev/null
+++ b/meta/lib/oeqa/utils/package_manager.py
@@ -0,0 +1,29 @@
+def get_package_manager(d, root_path):
+    """
+    Returns an OE package manager that can install packages in root_path.
+    """
+    from oe.package_manager import RpmPM, OpkgPM, DpkgPM
+
+    pkg_class = d.getVar("IMAGE_PKGTYPE", True)
+    if pkg_class == "rpm":
+        pm = RpmPM(d,
+                   root_path,
+                   d.getVar('TARGET_VENDOR', True))
+        pm.create_configs()
+
+    elif pkg_class == "ipk":
+        pm = OpkgPM(d,
+                    root_path,
+                    d.getVar("IPKGCONF_TARGET", True),
+                    d.getVar("ALL_MULTILIB_PACKAGE_ARCHS", True))
+
+    elif pkg_class == "deb":
+        pm = DpkgPM(d,
+                    root_path,
+                    d.getVar('PACKAGE_ARCHS', True),
+                    d.getVar('DPKG_ARCH', True))
+
+    pm.write_index()
+    pm.update()
+
+    return pm
-- 
2.6.6



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 04/10] oetest.py: Add json file support to specify packages needed in runtime tests
  2016-05-24 12:44 [PATCH 00/10] Allow to install packages in the DUT during runtime testing mariano.lopez
                   ` (2 preceding siblings ...)
  2016-05-24 12:44 ` [PATCH 03/10] oeqa/utils/package_manager.py: Add get_package_manager() mariano.lopez
@ 2016-05-24 12:44 ` mariano.lopez
  2016-05-24 12:44 ` [PATCH 05/10] oetest.py: Add extract_packages() to RuntimeTestContext class mariano.lopez
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: mariano.lopez @ 2016-05-24 12:44 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

This adds the functionality to use a json file to
specify the packages needed for a particular test.

The content of the json file is a dictionary with
dictionaries inside, using the test name as the hash.

The json file must have the same name as the class
module name and must be in the same path.

[YOCTO #7850]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/lib/oeqa/oetest.py | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index 8ad3715..7abd850 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -385,6 +385,43 @@ class RuntimeTestContext(TestContext):
         if oeTest.hasPackage("procps"):
             oeRuntimeTest.pscmd = "ps -ef"
 
+    def _getJsonFile(self, module):
+        """
+        Returns the path of the JSON file for a module, empty if doesn't exitst.
+        """
+
+        module_file = module.filename
+        json_file = "%s.json" % module_file.rsplit(".", 1)[0]
+        if os.path.isfile(module_file) and os.path.isfile(json_file):
+            return json_file
+        else:
+            return ""
+
+    def _getNeededPackages(self, json_file, test=None):
+        """
+        Returns a dict with needed packages based on a JSON file.
+
+
+        If a test is specified it will return the dict just for that test.
+        """
+
+        import json
+
+        needed_packages = {}
+
+        with open(json_file) as f:
+            test_packages = json.load(f)
+        for key,value in test_packages.items():
+            needed_packages[key] = value
+
+        if test:
+            if test in needed_packages:
+                needed_packages = needed_packages[test]
+            else:
+                needed_packages = {}
+
+        return needed_packages
+
 class ImageTestContext(RuntimeTestContext):
     def __init__(self, d, target, host_dumper):
         super(ImageTestContext, self).__init__(d, target)
-- 
2.6.6



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 05/10] oetest.py: Add extract_packages() to RuntimeTestContext class
  2016-05-24 12:44 [PATCH 00/10] Allow to install packages in the DUT during runtime testing mariano.lopez
                   ` (3 preceding siblings ...)
  2016-05-24 12:44 ` [PATCH 04/10] oetest.py: Add json file support to specify packages needed in runtime tests mariano.lopez
@ 2016-05-24 12:44 ` mariano.lopez
  2016-05-24 12:44 ` [PATCH 06/10] oetest.py: Add support to copy unextracted packages for runtime testing mariano.lopez
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: mariano.lopez @ 2016-05-24 12:44 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

This new method extracts the content of package (RPM, DEB, or IPK)
to a directory inside of WORKDIR. The extraction is needed for later
install in the DUTs without using a package manager.

[YOCTO #8694]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/lib/oeqa/oetest.py | 70 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index 7abd850..8dd494a 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -12,6 +12,7 @@ import unittest
 import inspect
 import subprocess
 import signal
+import shutil
 try:
     import bb
 except ImportError:
@@ -264,6 +265,22 @@ class TestContext(object):
 
         return testslist
 
+    def getTestModules(self):
+        """
+        Returns all the test modules in the testlist.
+        """
+
+        import pkgutil
+
+        modules = []
+        for test in self.testslist:
+            if re.search("\w+\.\w+\.test_\S+", test):
+                test = '.'.join(t.split('.')[:3])
+            module = pkgutil.get_loader(test)
+            modules.append(module)
+
+        return modules
+
     def getTests(self, test):
         '''Return all individual tests executed when running the suite.'''
         # Unfortunately unittest does not have an API for this, so we have
@@ -385,6 +402,44 @@ class RuntimeTestContext(TestContext):
         if oeTest.hasPackage("procps"):
             oeRuntimeTest.pscmd = "ps -ef"
 
+    def extract_packages(self):
+        """
+        Find and extract packages that will be needed during runtime.
+        """
+
+        needed_packages = {}
+        extracted_path = self.d.getVar("TEST_EXTRACTED_DIR", True)
+        modules = self.getTestModules()
+        bbpaths = self.d.getVar("BBPATH", True).split(":")
+
+        for module in modules:
+            json_file = self._getJsonFile(module)
+            if json_file:
+                needed_packages = self._getNeededPackages(json_file)
+
+        for key,value in needed_packages.items():
+            packages = ()
+            if isinstance(value, dict):
+                packages = (value, )
+            elif isinstance(value, list):
+                packages = value
+            else:
+                bb.fatal("Failed to process needed packages for %s; "
+                         "Value must be a dict or list" % key)
+
+            for package in packages:
+                pkg = package["pkg"]
+                rm = package.get("rm", False)
+                extract = package.get("extract", True)
+                if extract:
+                    dst_dir = os.path.join(extracted_path, pkg)
+
+                # Extract package and copy it to TEST_EXTRACTED_DIR
+                if extract and not os.path.exists(dst_dir):
+                    pkg_dir = self._extract_in_tmpdir(pkg)
+                    shutil.copytree(pkg_dir, dst_dir)
+                    shutil.rmtree(pkg_dir)
+
     def _getJsonFile(self, module):
         """
         Returns the path of the JSON file for a module, empty if doesn't exitst.
@@ -422,6 +477,21 @@ class RuntimeTestContext(TestContext):
 
         return needed_packages
 
+    def _extract_in_tmpdir(self, pkg):
+        """"
+        Returns path to a temp directory where the package was
+        extracted without dependencies.
+        """
+
+        from oeqa.utils.package_manager import get_package_manager
+
+        pkg_path = os.path.join(self.d.getVar("TEST_INSTALL_TMP_DIR", True), pkg)
+        pm = get_package_manager(self.d, pkg_path)
+        extract_dir = pm.extract(pkg)
+        shutil.rmtree(pkg_path)
+
+        return extract_dir
+
 class ImageTestContext(RuntimeTestContext):
     def __init__(self, d, target, host_dumper):
         super(ImageTestContext, self).__init__(d, target)
-- 
2.6.6



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 06/10] oetest.py: Add support to copy unextracted packages for runtime testing
  2016-05-24 12:44 [PATCH 00/10] Allow to install packages in the DUT during runtime testing mariano.lopez
                   ` (4 preceding siblings ...)
  2016-05-24 12:44 ` [PATCH 05/10] oetest.py: Add extract_packages() to RuntimeTestContext class mariano.lopez
@ 2016-05-24 12:44 ` mariano.lopez
  2016-05-24 12:44 ` [PATCH 07/10] lib/oe/package_manager.py: Add pkgpath to dict returned by package_info mariano.lopez
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: mariano.lopez @ 2016-05-24 12:44 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

Sometimes is needed to have a package without extraction when
running a test. This patch adds the functionality.

[YOCTO #8536]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/lib/oeqa/oetest.py | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index 8dd494a..a50f9d8 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -409,6 +409,7 @@ class RuntimeTestContext(TestContext):
 
         needed_packages = {}
         extracted_path = self.d.getVar("TEST_EXTRACTED_DIR", True)
+        packaged_path = self.d.getVar("TEST_PACKAGED_DIR", True)
         modules = self.getTestModules()
         bbpaths = self.d.getVar("BBPATH", True).split(":")
 
@@ -433,6 +434,8 @@ class RuntimeTestContext(TestContext):
                 extract = package.get("extract", True)
                 if extract:
                     dst_dir = os.path.join(extracted_path, pkg)
+                else:
+                    dst_dir = os.path.join(packaged_path)
 
                 # Extract package and copy it to TEST_EXTRACTED_DIR
                 if extract and not os.path.exists(dst_dir):
@@ -440,6 +443,10 @@ class RuntimeTestContext(TestContext):
                     shutil.copytree(pkg_dir, dst_dir)
                     shutil.rmtree(pkg_dir)
 
+                # Copy package to TEST_PACKAGED_DIR
+                elif not extract:
+                    self._copy_package(pkg)
+
     def _getJsonFile(self, module):
         """
         Returns the path of the JSON file for a module, empty if doesn't exitst.
@@ -492,6 +499,21 @@ class RuntimeTestContext(TestContext):
 
         return extract_dir
 
+    def _copy_package(self, pkg):
+        """
+        Copy the RPM, DEB or IPK package to dst_dir
+        """
+
+        from oeqa.utils.package_manager import get_package_manager
+
+        pkg_path = os.path.join(self.d.getVar("TEST_INSTALL_TMP_DIR", True), pkg)
+        dst_dir = self.d.getVar("TEST_PACKAGED_DIR", True)
+        pm = get_package_manager(self.d, pkg_path)
+        pkg_info = pm.package_info(pkg)
+        file_path = pkg_info[pkg]["filepath"]
+        shutil.copy2(file_path, dst_dir)
+        shutil.rmtree(pkg_path)
+
 class ImageTestContext(RuntimeTestContext):
     def __init__(self, d, target, host_dumper):
         super(ImageTestContext, self).__init__(d, target)
-- 
2.6.6



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 07/10] lib/oe/package_manager.py: Add pkgpath to dict returned by package_info
  2016-05-24 12:44 [PATCH 00/10] Allow to install packages in the DUT during runtime testing mariano.lopez
                   ` (5 preceding siblings ...)
  2016-05-24 12:44 ` [PATCH 06/10] oetest.py: Add support to copy unextracted packages for runtime testing mariano.lopez
@ 2016-05-24 12:44 ` mariano.lopez
  2016-05-24 12:44 ` [PATCH 08/10] oetest.py: Add install/uninstall functionality for DUTs mariano.lopez
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: mariano.lopez @ 2016-05-24 12:44 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

Having the package path with all the other package info allows to
reuse more code and have this information outside the package manager,
without additional processing.

[YOCTO #8536]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/lib/oe/package_manager.py | 41 ++++++++++++++++++++++++-----------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/meta/lib/oe/package_manager.py b/meta/lib/oe/package_manager.py
index 2d7da96..79b3206 100644
--- a/meta/lib/oe/package_manager.py
+++ b/meta/lib/oe/package_manager.py
@@ -1444,8 +1444,10 @@ class RpmPM(PackageManager):
                 break
 
         # To have the same data type than other package_info methods
+        filepath = os.path.join(self.deploy_dir, arch, filename)
         pkg_dict = {}
-        pkg_dict[pkg] = {"arch":arch, "ver":ver, "filename":filename}
+        pkg_dict[pkg] = {"arch":arch, "ver":ver, "filename":filename,
+                         "filepath": filepath}
 
         return pkg_dict
 
@@ -1461,9 +1463,7 @@ class RpmPM(PackageManager):
             bb.fatal("Unable to get information for package '%s' while "
                      "trying to extract the package."  % pkg)
 
-        pkg_arch = pkg_info[pkg]["arch"]
-        pkg_filename = pkg_info[pkg]["filename"]
-        pkg_path = os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
+        pkg_path = pkg_info[pkg]["filepath"]
 
         cpio_cmd = bb.utils.which(os.getenv("PATH"), "cpio")
         rpm2cpio_cmd = bb.utils.which(os.getenv("PATH"), "rpm2cpio")
@@ -1522,10 +1522,11 @@ class OpkgDpkgPM(PackageManager):
 
     This method extracts the common parts for Opkg and Dpkg
     """
-    def extract(self, pkg, pkg_path):
+    def extract(self, pkg, pkg_info):
 
         ar_cmd = bb.utils.which(os.getenv("PATH"), "ar")
         tar_cmd = bb.utils.which(os.getenv("PATH"), "tar")
+        pkg_path = pkg_info[pkg]["filepath"]
 
         if not os.path.isfile(pkg_path):
             bb.fatal("Unable to extract package for '%s'."
@@ -1897,7 +1898,14 @@ class OpkgPM(OpkgDpkgPM):
     """
     def package_info(self, pkg):
         cmd = "%s %s info %s" % (self.opkg_cmd, self.opkg_args, pkg)
-        return super(OpkgPM, self).package_info(pkg, cmd)
+        pkg_info = super(OpkgPM, self).package_info(pkg, cmd)
+
+        pkg_arch = pkg_info[pkg]["arch"]
+        pkg_filename = pkg_info[pkg]["filename"]
+        pkg_info[pkg]["filepath"] = \
+                os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
+
+        return pkg_info
 
     """
     Returns the path to a tmpdir where resides the contents of a package.
@@ -1910,11 +1918,7 @@ class OpkgPM(OpkgDpkgPM):
             bb.fatal("Unable to get information for package '%s' while "
                      "trying to extract the package."  % pkg)
 
-        pkg_arch = pkg_info[pkg]["arch"]
-        pkg_filename = pkg_info[pkg]["filename"]
-        pkg_path = os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
-
-        tmp_dir = super(OpkgPM, self).extract(pkg, pkg_path)
+        tmp_dir = super(OpkgPM, self).extract(pkg, pkg_info)
         bb.utils.remove(os.path.join(tmp_dir, "data.tar.gz"))
 
         return tmp_dir
@@ -2219,7 +2223,14 @@ class DpkgPM(OpkgDpkgPM):
     """
     def package_info(self, pkg):
         cmd = "%s show %s" % (self.apt_cache_cmd, pkg)
-        return super(DpkgPM, self).package_info(pkg, cmd)
+        pkg_info = super(DpkgPM, self).package_info(pkg, cmd)
+
+        pkg_arch = pkg_info[pkg]["pkgarch"]
+        pkg_filename = pkg_info[pkg]["filename"]
+        pkg_info[pkg]["filepath"] = \
+                os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
+
+        return pkg_info
 
     """
     Returns the path to a tmpdir where resides the contents of a package.
@@ -2232,11 +2243,7 @@ class DpkgPM(OpkgDpkgPM):
             bb.fatal("Unable to get information for package '%s' while "
                      "trying to extract the package."  % pkg)
 
-        pkg_arch = pkg_info[pkg]["pkgarch"]
-        pkg_filename = pkg_info[pkg]["filename"]
-        pkg_path = os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
-
-        tmp_dir = super(DpkgPM, self).extract(pkg, pkg_path)
+        tmp_dir = super(DpkgPM, self).extract(pkg, pkg_info)
         bb.utils.remove(os.path.join(tmp_dir, "data.tar.xz"))
 
         return tmp_dir
-- 
2.6.6



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 08/10] oetest.py: Add install/uninstall functionality for DUTs
  2016-05-24 12:44 [PATCH 00/10] Allow to install packages in the DUT during runtime testing mariano.lopez
                   ` (6 preceding siblings ...)
  2016-05-24 12:44 ` [PATCH 07/10] lib/oe/package_manager.py: Add pkgpath to dict returned by package_info mariano.lopez
@ 2016-05-24 12:44 ` mariano.lopez
  2016-05-24 12:44 ` [PATCH 09/10] cpio: Add native variant mariano.lopez
  2016-05-24 12:44 ` [PATCH 10/10] testimage.bbclass: Make dependency of cpio when using RPMs mariano.lopez
  9 siblings, 0 replies; 11+ messages in thread
From: mariano.lopez @ 2016-05-24 12:44 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

Add the functionality to install/unistall packages in the
DUTs without the use of the package manager. This is possible
with the extraction introduced in the previous commits.

testimage and testexport bbclasses has been modified in order
to support this new feature.

[YOCTO #8694]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/classes/testexport.bbclass | 29 +++++++++++++---
 meta/classes/testimage.bbclass  | 45 ++++++++++++++++++++++++-
 meta/lib/oeqa/oetest.py         | 74 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 143 insertions(+), 5 deletions(-)

diff --git a/meta/classes/testexport.bbclass b/meta/classes/testexport.bbclass
index e06c668..21a2bf7 100644
--- a/meta/classes/testexport.bbclass
+++ b/meta/classes/testexport.bbclass
@@ -16,6 +16,9 @@
 
 TEST_LOG_DIR ?= "${WORKDIR}/testexport"
 TEST_EXPORT_DIR ?= "${TMPDIR}/testexport/${PN}"
+TEST_EXPORT_PACKAGED_DIR ?= "packages/packaged"
+TEST_EXPORT_EXTRACTED_DIR ?= "packages/extracted"
+
 TEST_TARGET ?= "simpleremote"
 TEST_TARGET_IP ?= ""
 TEST_SERVER_IP ?= ""
@@ -27,9 +30,9 @@ python do_testexport() {
     testexport_main(d)
 }
 
-addtask testexport
+addtask testexport after do_test_extract_packages
 do_testimage[nostamp] = "1"
-do_testimage[depends] += "${TEST_EXPORT_DEPENDS}"
+do_testimage[depends] += "${TEST_EXPORT_DEPENDS} ${TESTIMAGEDEPENDS}"
 do_testimage[lockfiles] += "${TEST_EXPORT_LOCK}"
 
 def exportTests(d,tc):
@@ -96,6 +99,10 @@ def exportTests(d,tc):
                         shutil.copytree(foldername, target_folder)
         if not isfolder:
             shutil.copy2(mod.filename, os.path.join(exportpath, "oeqa/runtime"))
+            json_file = "%s.json" % mod.filename.rsplit(".", 1)[0]
+            if os.path.isfile(json_file):
+                shutil.copy2(json_file, os.path.join(exportpath, "oeqa/runtime"))
+
     # copy __init__.py files
     oeqadir = pkgutil.get_loader("oeqa").filename
     shutil.copy2(os.path.join(oeqadir, "__init__.py"), os.path.join(exportpath, "oeqa"))
@@ -113,6 +120,19 @@ def exportTests(d,tc):
         for f in files:
             shutil.copy2(os.path.join(root, f), os.path.join(exportpath, "oeqa/runtime/files"))
 
+    # Copy packages needed for runtime testing
+    export_pkg_dir = os.path.join(d.getVar("TEST_EXPORT_DIR", True), "packages")
+    test_pkg_dir = d.getVar("TEST_NEEDED_PACKAGES_DIR", True)
+    for root, subdirs, files in os.walk(test_pkg_dir):
+        for subdir in subdirs:
+            tmp_dir = os.path.join(root.replace(test_pkg_dir, "").lstrip("/"), subdir)
+            new_dir = os.path.join(export_pkg_dir, tmp_dir)
+            bb.utils.mkdirhier(new_dir)
+
+        for f in files:
+            src_f = os.path.join(root, f)
+            dst_f = os.path.join(export_pkg_dir, root.replace(test_pkg_dir, "").lstrip("/"), f)
+            shutil.copy2(src_f, dst_f)
     bb.plain("Exported tests to: %s" % exportpath)
 
 def testexport_main(d):
@@ -120,9 +140,10 @@ def testexport_main(d):
     from oeqa.targetcontrol import get_target_controller
     from oeqa.utils.dump import get_host_dumper
 
+    export_dir = d.getVar("TEST_EXPORT_DIR", True)
     bb.utils.mkdirhier(d.getVar("TEST_LOG_DIR", True))
-    bb.utils.remove(d.getVar("TEST_EXPORT_DIR", True), recurse=True)
-    bb.utils.mkdirhier(d.getVar("TEST_EXPORT_DIR", True))
+    bb.utils.remove(export_dir, recurse=True)
+    bb.utils.mkdirhier(export_dir)
 
     # the robot dance
     target = get_target_controller(d)
diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass
index a2e13df..436dec4 100644
--- a/meta/classes/testimage.bbclass
+++ b/meta/classes/testimage.bbclass
@@ -30,6 +30,10 @@
 TEST_LOG_DIR ?= "${WORKDIR}/testimage"
 
 TEST_EXPORT_DIR ?= "${TMPDIR}/testimage/${PN}"
+TEST_INSTALL_TMP_DIR ?= "${WORKDIR}/testimage/install_tmp"
+TEST_NEEDED_PACKAGES_DIR ?= "${WORKDIR}/testimage/packages"
+TEST_EXTRACTED_DIR ?= "${TEST_NEEDED_PACKAGES_DIR}/extracted"
+TEST_PACKAGED_DIR ?= "${TEST_NEEDED_PACKAGES_DIR}/packaged"
 
 RPMTESTSUITE = "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'smart rpm', '', d)}"
 MINTESTSUITE = "ping"
@@ -100,7 +104,16 @@ testimage_dump_host () {
 python do_testimage() {
     testimage_main(d)
 }
-addtask testimage
+
+python do_test_extract_packages() {
+    test_extract_packages(d)
+}
+
+addtask test_extract_packages
+do_test_extract_packages[nostamp] = "1"
+do_test_extract_packages[depends] += "${TESTIMAGEDEPENDS}"
+
+addtask testimage after do_test_extract_packages
 do_testimage[nostamp] = "1"
 do_testimage[depends] += "${TESTIMAGEDEPENDS}"
 do_testimage[lockfiles] += "${TESTIMAGELOCK}"
@@ -155,6 +168,36 @@ def testimage_main(d):
         signal.signal(signal.SIGTERM, tc.origsigtermhandler)
         target.stop()
 
+def test_extract_packages(d):
+    from oeqa.oetest import ExportTestContext
+    from oeqa.targetcontrol import get_target_controller
+
+    install_path = d.getVar("TEST_INSTALL_TMP_DIR", True)
+    package_path = d.getVar("TEST_PACKAGED_DIR", True)
+    extracted_path = d.getVar("TEST_EXTRACTED_DIR", True)
+    bb.utils.mkdirhier(d.getVar("TEST_LOG_DIR", True))
+    bb.utils.remove(package_path, recurse=True)
+    bb.utils.mkdirhier(install_path)
+    bb.utils.mkdirhier(package_path)
+    bb.utils.mkdirhier(extracted_path)
+
+    # the robot dance
+    target = get_target_controller(d)
+
+    # test context
+    tc = ExportTestContext(d, target)
+
+    # this is a dummy load of tests we are doing this for later
+    # extraction of packages, before booting/exporting the tests
+    try:
+        tc.loadTests()
+    except Exception as e:
+        import traceback
+        bb.fatal("Loading tests failed:\n%s" % traceback.format_exc())
+
+    tc.extract_packages()
+
+
 testimage_main[vardepsexclude] =+ "BB_ORIGENV"
 
 inherit testsdk
diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index a50f9d8..dfac09b 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -80,6 +80,9 @@ class oeRuntimeTest(oeTest):
         super(oeRuntimeTest, self).__init__(methodName)
 
     def setUp(self):
+        # Install packages in the DUT
+        self.tc.install_uninstall_packages(self.id())
+
         # Check if test needs to run
         if self.tc.sigterm:
             self.fail("Got SIGTERM")
@@ -93,6 +96,9 @@ class oeRuntimeTest(oeTest):
         pass
 
     def tearDown(self):
+        # Unistall packages in the DUT
+        self.tc.install_uninstall_packages(self.id(), False)
+
         res = getResults()
         # If a test fails or there is an exception dump
         # for QemuTarget only
@@ -281,6 +287,19 @@ class TestContext(object):
 
         return modules
 
+    def getModulefromID(self, test_id):
+        """
+        Returns the test module based on a test id.
+        """
+
+        module_name = ".".join(test_id.split(".")[:3])
+        modules = self.getTestModules()
+        for module in modules:
+            if module.fullname == module_name:
+                return module
+
+        return None
+
     def getTests(self, test):
         '''Return all individual tests executed when running the suite.'''
         # Unfortunately unittest does not have an API for this, so we have
@@ -514,6 +533,43 @@ class RuntimeTestContext(TestContext):
         shutil.copy2(file_path, dst_dir)
         shutil.rmtree(pkg_path)
 
+    def install_uninstall_packages(self, test_id, pkg_dir, install):
+        """
+        Check if the test requires a package and Install/Unistall it in the DUT
+        """
+
+        test = test_id.split(".")[4]
+        module = self.getModulefromID(test_id)
+        json = self._getJsonFile(module)
+        if json:
+            needed_packages = self._getNeededPackages(json, test)
+            if needed_packages:
+                self._install_uninstall_packages(needed_packages, pkg_dir, install)
+
+    def _install_uninstall_packages(self, needed_packages, pkg_dir, install=True):
+        """
+        Install/Unistall packages in the DUT without using a package manager
+        """
+
+        if isinstance(needed_packages, dict):
+            packages = [needed_packages]
+        elif isinstance(needed_packages, list):
+            packages = needed_packages
+
+        for package in packages:
+            pkg = package["pkg"]
+            rm = package.get("rm", False)
+            extract = package.get("extract", True)
+            src_dir = os.path.join(pkg_dir, pkg)
+
+            # Install package
+            if install and extract:
+                self.target.connection.copy_dir_to(src_dir, "/")
+
+            # Unistall package
+            elif not install and rm:
+                self.target.connection.delete_dir_structure(src_dir, "/")
+
 class ImageTestContext(RuntimeTestContext):
     def __init__(self, d, target, host_dumper):
         super(ImageTestContext, self).__init__(d, target)
@@ -529,11 +585,29 @@ class ImageTestContext(RuntimeTestContext):
         self.sigterm = True
         self.target.stop()
 
+    def install_uninstall_packages(self, test_id, install=True):
+        """
+        Check if the test requires a package and Install/Unistall it in the DUT
+        """
+
+        pkg_dir = self.d.getVar("TEST_EXTRACTED_DIR", True)
+        super(ImageTestContext, self).install_uninstall_packages(test_id, pkg_dir, install)
+
 class ExportTestContext(RuntimeTestContext):
     def __init__(self, d, target, exported=False):
         super(ExportTestContext, self).__init__(d, target, exported)
         self.sigterm = None
 
+    def install_uninstall_packages(self, test_id, install=True):
+        """
+        Check if the test requires a package and Install/Unistall it in the DUT
+        """
+
+        export_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+        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 SDKTestContext(TestContext):
     def __init__(self, d, sdktestdir, sdkenv, tcname, *args):
         super(SDKTestContext, self).__init__(d)
-- 
2.6.6



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 09/10] cpio: Add native variant
  2016-05-24 12:44 [PATCH 00/10] Allow to install packages in the DUT during runtime testing mariano.lopez
                   ` (7 preceding siblings ...)
  2016-05-24 12:44 ` [PATCH 08/10] oetest.py: Add install/uninstall functionality for DUTs mariano.lopez
@ 2016-05-24 12:44 ` mariano.lopez
  2016-05-24 12:44 ` [PATCH 10/10] testimage.bbclass: Make dependency of cpio when using RPMs mariano.lopez
  9 siblings, 0 replies; 11+ messages in thread
From: mariano.lopez @ 2016-05-24 12:44 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/recipes-extended/cpio/cpio_v2.inc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/meta/recipes-extended/cpio/cpio_v2.inc b/meta/recipes-extended/cpio/cpio_v2.inc
index 1bdc617..31adb71 100644
--- a/meta/recipes-extended/cpio/cpio_v2.inc
+++ b/meta/recipes-extended/cpio/cpio_v2.inc
@@ -39,3 +39,5 @@ ALTERNATIVE_LINK_NAME[cpio] = "${base_bindir}/cpio"
 
 ALTERNATIVE_PRIORITY[rmt] = "50"
 ALTERNATIVE_LINK_NAME[rmt] = "${base_sbindir}/rmt"
+
+BBCLASSEXTEND = "native"
-- 
2.6.6



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 10/10] testimage.bbclass: Make dependency of cpio when using RPMs
  2016-05-24 12:44 [PATCH 00/10] Allow to install packages in the DUT during runtime testing mariano.lopez
                   ` (8 preceding siblings ...)
  2016-05-24 12:44 ` [PATCH 09/10] cpio: Add native variant mariano.lopez
@ 2016-05-24 12:44 ` mariano.lopez
  9 siblings, 0 replies; 11+ messages in thread
From: mariano.lopez @ 2016-05-24 12:44 UTC (permalink / raw)
  To: openembedded-core

From: Mariano Lopez <mariano.lopez@linux.intel.com>

do_test_extract_packages task needs cpio when building and image
using RPM packages, not all distros include cpio by default, so
we need to build it.

[YOCTO #8694]

Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
---
 meta/classes/testimage.bbclass | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass
index 436dec4..4f2abb8 100644
--- a/meta/classes/testimage.bbclass
+++ b/meta/classes/testimage.bbclass
@@ -68,6 +68,8 @@ TEST_TARGET ?= "qemu"
 
 TESTIMAGEDEPENDS = ""
 TESTIMAGEDEPENDS_qemuall = "qemu-native:do_populate_sysroot qemu-helper-native:do_populate_sysroot"
+TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'cpio-native:do_populate_sysroot', '', d)}"
+TESTIMAGEDEPENDS_qemuall += "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'cpio-native:do_populate_sysroot', '', d)}"
 
 TESTIMAGELOCK = "${TMPDIR}/testimage.lock"
 TESTIMAGELOCK_qemuall = ""
-- 
2.6.6



^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2016-05-24 20:49 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-24 12:44 [PATCH 00/10] Allow to install packages in the DUT during runtime testing mariano.lopez
2016-05-24 12:44 ` [PATCH 01/10] testexport.bbclass: Stop exporting test context mariano.lopez
2016-05-24 12:44 ` [PATCH 02/10] oetest.py: Move getTests() outside loadTests() method mariano.lopez
2016-05-24 12:44 ` [PATCH 03/10] oeqa/utils/package_manager.py: Add get_package_manager() mariano.lopez
2016-05-24 12:44 ` [PATCH 04/10] oetest.py: Add json file support to specify packages needed in runtime tests mariano.lopez
2016-05-24 12:44 ` [PATCH 05/10] oetest.py: Add extract_packages() to RuntimeTestContext class mariano.lopez
2016-05-24 12:44 ` [PATCH 06/10] oetest.py: Add support to copy unextracted packages for runtime testing mariano.lopez
2016-05-24 12:44 ` [PATCH 07/10] lib/oe/package_manager.py: Add pkgpath to dict returned by package_info mariano.lopez
2016-05-24 12:44 ` [PATCH 08/10] oetest.py: Add install/uninstall functionality for DUTs mariano.lopez
2016-05-24 12:44 ` [PATCH 09/10] cpio: Add native variant mariano.lopez
2016-05-24 12:44 ` [PATCH 10/10] testimage.bbclass: Make dependency of cpio when using RPMs mariano.lopez

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.