xref: /openbmc/openbmc/poky/meta/lib/oeqa/sdk/testsdk.py (revision 39653566)
1#
2# Copyright 2018 by Garmin Ltd. or its subsidiaries
3#
4# SPDX-License-Identifier: MIT
5#
6
7from oeqa.sdk.context import OESDKTestContext, OESDKTestContextExecutor
8
9class TestSDKBase(object):
10    @staticmethod
11    def get_sdk_configuration(d, test_type):
12        import platform
13        import oe.lsb
14        from oeqa.utils.metadata import get_layers
15        configuration = {'TEST_TYPE': test_type,
16                        'MACHINE': d.getVar("MACHINE"),
17                        'SDKMACHINE': d.getVar("SDKMACHINE"),
18                        'IMAGE_BASENAME': d.getVar("IMAGE_BASENAME"),
19                        'IMAGE_PKGTYPE': d.getVar("IMAGE_PKGTYPE"),
20                        'STARTTIME': d.getVar("DATETIME"),
21                        'HOST_DISTRO': oe.lsb.distro_identifier().replace(' ', '-'),
22                        'LAYERS': get_layers(d.getVar("BBLAYERS"))}
23        return configuration
24
25    @staticmethod
26    def get_sdk_result_id(configuration):
27        return '%s_%s_%s_%s_%s' % (configuration['TEST_TYPE'], configuration['IMAGE_BASENAME'], configuration['SDKMACHINE'], configuration['MACHINE'], configuration['STARTTIME'])
28
29class TestSDK(TestSDKBase):
30    context_executor_class = OESDKTestContextExecutor
31    context_class = OESDKTestContext
32    test_type = 'sdk'
33
34    def get_tcname(self, d):
35        """
36        Get the name of the SDK file
37        """
38        return d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh")
39
40    def extract_sdk(self, tcname, sdk_dir, d):
41        """
42        Extract the SDK to the specified location
43        """
44        import subprocess
45
46        try:
47            subprocess.check_output("cd %s; %s <<EOF\n./\nY\nEOF" % (sdk_dir, tcname), shell=True)
48        except subprocess.CalledProcessError as e:
49            bb.fatal("Couldn't install the SDK:\n%s" % e.output.decode("utf-8"))
50
51    def setup_context(self, d):
52        """
53        Return a dictionary of additional arguments that should be passed to
54        the context_class on construction
55        """
56        return dict()
57
58    def run(self, d):
59
60        import os
61        import subprocess
62        import json
63        import logging
64
65        from bb.utils import export_proxies
66        from oeqa.utils import make_logger_bitbake_compatible
67        from oeqa.utils import get_json_result_dir
68
69        pn = d.getVar("PN")
70        logger = make_logger_bitbake_compatible(logging.getLogger("BitBake"))
71
72        # sdk use network for download projects for build
73        export_proxies(d)
74
75        # We need the original PATH for testing the eSDK, not with our manipulations
76        os.environ['PATH'] = d.getVar("BB_ORIGENV", False).getVar("PATH")
77
78        tcname = self.get_tcname(d)
79
80        if not os.path.exists(tcname):
81            bb.fatal("The toolchain %s is not built. Build it before running the tests: 'bitbake <image> -c populate_sdk' ." % tcname)
82
83        tdname = d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.testdata.json")
84        test_data = json.load(open(tdname, "r"))
85
86        target_pkg_manifest = self.context_executor_class._load_manifest(
87            d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.target.manifest"))
88        host_pkg_manifest = self.context_executor_class._load_manifest(
89            d.expand("${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.host.manifest"))
90
91        processes = d.getVar("TESTIMAGE_NUMBER_THREADS") or d.getVar("BB_NUMBER_THREADS")
92        if processes:
93            try:
94                import testtools, subunit
95            except ImportError:
96                bb.warn("Failed to import testtools or subunit, the testcases will run serially")
97                processes = None
98
99        sdk_dir = d.expand("${WORKDIR}/testimage-sdk/")
100        bb.utils.remove(sdk_dir, True)
101        bb.utils.mkdirhier(sdk_dir)
102
103        context_args = self.setup_context(d)
104
105        self.extract_sdk(tcname, sdk_dir, d)
106
107        fail = False
108        sdk_envs = self.context_executor_class._get_sdk_environs(sdk_dir)
109        for s in sdk_envs:
110            sdk_env = sdk_envs[s]
111            bb.plain("SDK testing environment: %s" % s)
112            tc = self.context_class(td=test_data, logger=logger, sdk_dir=sdk_dir,
113                sdk_env=sdk_env, target_pkg_manifest=target_pkg_manifest,
114                host_pkg_manifest=host_pkg_manifest, **context_args)
115
116            try:
117                tc.loadTests(self.context_executor_class.default_cases)
118            except Exception as e:
119                import traceback
120                bb.fatal("Loading tests failed:\n%s" % traceback.format_exc())
121
122            if processes:
123                result = tc.runTests(processes=int(processes))
124            else:
125                result = tc.runTests()
126
127            component = "%s %s" % (pn, self.context_executor_class.name)
128            context_msg = "%s:%s" % (os.path.basename(tcname), os.path.basename(sdk_env))
129            configuration = self.get_sdk_configuration(d, self.test_type)
130            result.logDetails(get_json_result_dir(d),
131                            configuration,
132                            self.get_sdk_result_id(configuration))
133            result.logSummary(component, context_msg)
134
135            if not result.wasSuccessful():
136                fail = True
137
138        if fail:
139            bb.fatal("%s - FAILED - check the task log and the commands log" % pn)
140
141
142