xref: /OK3568_Linux_fs/yocto/poky/meta/lib/oeqa/selftest/context.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#
2*4882a593Smuzhiyun# Copyright (C) 2017 Intel Corporation
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun# SPDX-License-Identifier: MIT
5*4882a593Smuzhiyun#
6*4882a593Smuzhiyun
7*4882a593Smuzhiyunimport os
8*4882a593Smuzhiyunimport time
9*4882a593Smuzhiyunimport glob
10*4882a593Smuzhiyunimport sys
11*4882a593Smuzhiyunimport importlib
12*4882a593Smuzhiyunimport subprocess
13*4882a593Smuzhiyunimport unittest
14*4882a593Smuzhiyunfrom random import choice
15*4882a593Smuzhiyun
16*4882a593Smuzhiyunimport oeqa
17*4882a593Smuzhiyunimport oe
18*4882a593Smuzhiyunimport bb.utils
19*4882a593Smuzhiyun
20*4882a593Smuzhiyunfrom oeqa.core.context import OETestContext, OETestContextExecutor
21*4882a593Smuzhiyunfrom oeqa.core.exception import OEQAPreRun, OEQATestNotFound
22*4882a593Smuzhiyun
23*4882a593Smuzhiyunfrom oeqa.utils.commands import runCmd, get_bb_vars, get_test_layer
24*4882a593Smuzhiyun
25*4882a593Smuzhiyunclass NonConcurrentTestSuite(unittest.TestSuite):
26*4882a593Smuzhiyun    def __init__(self, suite, processes, setupfunc, removefunc):
27*4882a593Smuzhiyun        super().__init__([suite])
28*4882a593Smuzhiyun        self.processes = processes
29*4882a593Smuzhiyun        self.suite = suite
30*4882a593Smuzhiyun        self.setupfunc = setupfunc
31*4882a593Smuzhiyun        self.removefunc = removefunc
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun    def run(self, result):
34*4882a593Smuzhiyun        (builddir, newbuilddir) = self.setupfunc("-st", None, self.suite)
35*4882a593Smuzhiyun        ret = super().run(result)
36*4882a593Smuzhiyun        os.chdir(builddir)
37*4882a593Smuzhiyun        if newbuilddir and ret.wasSuccessful() and self.removefunc:
38*4882a593Smuzhiyun            self.removefunc(newbuilddir)
39*4882a593Smuzhiyun
40*4882a593Smuzhiyundef removebuilddir(d):
41*4882a593Smuzhiyun    delay = 5
42*4882a593Smuzhiyun    while delay and (os.path.exists(d + "/bitbake.lock") or os.path.exists(d + "/cache/hashserv.db-wal")):
43*4882a593Smuzhiyun        time.sleep(1)
44*4882a593Smuzhiyun        delay = delay - 1
45*4882a593Smuzhiyun    # Deleting these directories takes a lot of time, use autobuilder
46*4882a593Smuzhiyun    # clobberdir if its available
47*4882a593Smuzhiyun    clobberdir = os.path.expanduser("~/yocto-autobuilder-helper/janitor/clobberdir")
48*4882a593Smuzhiyun    if os.path.exists(clobberdir):
49*4882a593Smuzhiyun        try:
50*4882a593Smuzhiyun            subprocess.check_call([clobberdir, d])
51*4882a593Smuzhiyun            return
52*4882a593Smuzhiyun        except subprocess.CalledProcessError:
53*4882a593Smuzhiyun            pass
54*4882a593Smuzhiyun    bb.utils.prunedir(d, ionice=True)
55*4882a593Smuzhiyun
56*4882a593Smuzhiyunclass OESelftestTestContext(OETestContext):
57*4882a593Smuzhiyun    def __init__(self, td=None, logger=None, machines=None, config_paths=None, newbuilddir=None, keep_builddir=None):
58*4882a593Smuzhiyun        super(OESelftestTestContext, self).__init__(td, logger)
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun        self.machines = machines
61*4882a593Smuzhiyun        self.custommachine = None
62*4882a593Smuzhiyun        self.config_paths = config_paths
63*4882a593Smuzhiyun        self.newbuilddir = newbuilddir
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun        if keep_builddir:
66*4882a593Smuzhiyun            self.removebuilddir = None
67*4882a593Smuzhiyun        else:
68*4882a593Smuzhiyun            self.removebuilddir = removebuilddir
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun    def setup_builddir(self, suffix, selftestdir, suite):
71*4882a593Smuzhiyun        builddir = os.environ['BUILDDIR']
72*4882a593Smuzhiyun        if not selftestdir:
73*4882a593Smuzhiyun            selftestdir = get_test_layer()
74*4882a593Smuzhiyun        if self.newbuilddir:
75*4882a593Smuzhiyun            newbuilddir = os.path.join(self.newbuilddir, 'build' + suffix)
76*4882a593Smuzhiyun        else:
77*4882a593Smuzhiyun            newbuilddir = builddir + suffix
78*4882a593Smuzhiyun        newselftestdir = newbuilddir + "/meta-selftest"
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun        if os.path.exists(newbuilddir):
81*4882a593Smuzhiyun            self.logger.error("Build directory %s already exists, aborting" % newbuilddir)
82*4882a593Smuzhiyun            sys.exit(1)
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun        bb.utils.mkdirhier(newbuilddir)
85*4882a593Smuzhiyun        oe.path.copytree(builddir + "/conf", newbuilddir + "/conf")
86*4882a593Smuzhiyun        oe.path.copytree(builddir + "/cache", newbuilddir + "/cache")
87*4882a593Smuzhiyun        oe.path.copytree(selftestdir, newselftestdir)
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun        for e in os.environ:
90*4882a593Smuzhiyun            if builddir + "/" in os.environ[e]:
91*4882a593Smuzhiyun                os.environ[e] = os.environ[e].replace(builddir + "/", newbuilddir + "/")
92*4882a593Smuzhiyun            if os.environ[e].endswith(builddir):
93*4882a593Smuzhiyun                os.environ[e] = os.environ[e].replace(builddir, newbuilddir)
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun        subprocess.check_output("git init; git add *; git commit -a -m 'initial'", cwd=newselftestdir, shell=True)
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun        # Tried to used bitbake-layers add/remove but it requires recipe parsing and hence is too slow
98*4882a593Smuzhiyun        subprocess.check_output("sed %s/conf/bblayers.conf -i -e 's#%s#%s#g'" % (newbuilddir, selftestdir, newselftestdir), cwd=newbuilddir, shell=True)
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun        os.chdir(newbuilddir)
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun        def patch_test(t):
103*4882a593Smuzhiyun            if not hasattr(t, "tc"):
104*4882a593Smuzhiyun                return
105*4882a593Smuzhiyun            cp = t.tc.config_paths
106*4882a593Smuzhiyun            for p in cp:
107*4882a593Smuzhiyun                if selftestdir in cp[p] and newselftestdir not in cp[p]:
108*4882a593Smuzhiyun                    cp[p] = cp[p].replace(selftestdir, newselftestdir)
109*4882a593Smuzhiyun                if builddir in cp[p] and newbuilddir not in cp[p]:
110*4882a593Smuzhiyun                    cp[p] = cp[p].replace(builddir, newbuilddir)
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun        def patch_suite(s):
113*4882a593Smuzhiyun            for x in s:
114*4882a593Smuzhiyun                if isinstance(x, unittest.TestSuite):
115*4882a593Smuzhiyun                    patch_suite(x)
116*4882a593Smuzhiyun                else:
117*4882a593Smuzhiyun                    patch_test(x)
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun        patch_suite(suite)
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun        return (builddir, newbuilddir)
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun    def prepareSuite(self, suites, processes):
124*4882a593Smuzhiyun        if processes:
125*4882a593Smuzhiyun            from oeqa.core.utils.concurrencytest import ConcurrentTestSuite
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun            return ConcurrentTestSuite(suites, processes, self.setup_builddir, self.removebuilddir)
128*4882a593Smuzhiyun        else:
129*4882a593Smuzhiyun            return NonConcurrentTestSuite(suites, processes, self.setup_builddir, self.removebuilddir)
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun    def runTests(self, processes=None, machine=None, skips=[]):
132*4882a593Smuzhiyun        if machine:
133*4882a593Smuzhiyun            self.custommachine = machine
134*4882a593Smuzhiyun            if machine == 'random':
135*4882a593Smuzhiyun                self.custommachine = choice(self.machines)
136*4882a593Smuzhiyun            self.logger.info('Run tests with custom MACHINE set to: %s' % \
137*4882a593Smuzhiyun                    self.custommachine)
138*4882a593Smuzhiyun        return super(OESelftestTestContext, self).runTests(processes, skips)
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun    def listTests(self, display_type, machine=None):
141*4882a593Smuzhiyun        return super(OESelftestTestContext, self).listTests(display_type)
142*4882a593Smuzhiyun
143*4882a593Smuzhiyunclass OESelftestTestContextExecutor(OETestContextExecutor):
144*4882a593Smuzhiyun    _context_class = OESelftestTestContext
145*4882a593Smuzhiyun    _script_executor = 'oe-selftest'
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun    name = 'oe-selftest'
148*4882a593Smuzhiyun    help = 'oe-selftest test component'
149*4882a593Smuzhiyun    description = 'Executes selftest tests'
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun    def register_commands(self, logger, parser):
152*4882a593Smuzhiyun        group = parser.add_mutually_exclusive_group(required=True)
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun        group.add_argument('-a', '--run-all-tests', default=False,
155*4882a593Smuzhiyun                action="store_true", dest="run_all_tests",
156*4882a593Smuzhiyun                help='Run all (unhidden) tests')
157*4882a593Smuzhiyun        group.add_argument('-R', '--skip-tests', required=False, action='store',
158*4882a593Smuzhiyun                nargs='+', dest="skips", default=None,
159*4882a593Smuzhiyun                help='Run all (unhidden) tests except the ones specified. Format should be <module>[.<class>[.<test_method>]]')
160*4882a593Smuzhiyun        group.add_argument('-r', '--run-tests', required=False, action='store',
161*4882a593Smuzhiyun                nargs='+', dest="run_tests", default=None,
162*4882a593Smuzhiyun                help='Select what tests to run (modules, classes or test methods). Format should be: <module>.<class>.<test_method>')
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun        group.add_argument('-m', '--list-modules', required=False,
165*4882a593Smuzhiyun                action="store_true", default=False,
166*4882a593Smuzhiyun                help='List all available test modules.')
167*4882a593Smuzhiyun        group.add_argument('--list-classes', required=False,
168*4882a593Smuzhiyun                action="store_true", default=False,
169*4882a593Smuzhiyun                help='List all available test classes.')
170*4882a593Smuzhiyun        group.add_argument('-l', '--list-tests', required=False,
171*4882a593Smuzhiyun                action="store_true", default=False,
172*4882a593Smuzhiyun                help='List all available tests.')
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun        parser.add_argument('-j', '--num-processes', dest='processes', action='store',
175*4882a593Smuzhiyun                type=int, help="number of processes to execute in parallel with")
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun        parser.add_argument('--machine', required=False, choices=['random', 'all'],
178*4882a593Smuzhiyun                            help='Run tests on different machines (random/all).')
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun        parser.add_argument('-t', '--select-tag', dest="select_tags",
181*4882a593Smuzhiyun                action='append', default=None,
182*4882a593Smuzhiyun                help='Filter all (unhidden) tests to any that match any of the specified tag(s).')
183*4882a593Smuzhiyun        parser.add_argument('-T', '--exclude-tag', dest="exclude_tags",
184*4882a593Smuzhiyun                action='append', default=None,
185*4882a593Smuzhiyun                help='Exclude all (unhidden) tests that match any of the specified tag(s). (exclude applies before select)')
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun        parser.add_argument('-K', '--keep-builddir', action='store_true',
188*4882a593Smuzhiyun                help='Keep the test build directory even if all tests pass')
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun        parser.add_argument('-B', '--newbuilddir', help='New build directory to use for tests.')
191*4882a593Smuzhiyun        parser.add_argument('-v', '--verbose', action='store_true')
192*4882a593Smuzhiyun        parser.set_defaults(func=self.run)
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun    def _get_available_machines(self):
195*4882a593Smuzhiyun        machines = []
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun        bbpath = self.tc_kwargs['init']['td']['BBPATH'].split(':')
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun        for path in bbpath:
200*4882a593Smuzhiyun            found_machines = glob.glob(os.path.join(path, 'conf', 'machine', '*.conf'))
201*4882a593Smuzhiyun            if found_machines:
202*4882a593Smuzhiyun                for i in found_machines:
203*4882a593Smuzhiyun                    # eg: '/home/<user>/poky/meta-intel/conf/machine/intel-core2-32.conf'
204*4882a593Smuzhiyun                    machines.append(os.path.splitext(os.path.basename(i))[0])
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun        return machines
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun    def _get_cases_paths(self, bbpath):
209*4882a593Smuzhiyun        cases_paths = []
210*4882a593Smuzhiyun        for layer in bbpath:
211*4882a593Smuzhiyun            cases_dir = os.path.join(layer, 'lib', 'oeqa', 'selftest', 'cases')
212*4882a593Smuzhiyun            if os.path.isdir(cases_dir):
213*4882a593Smuzhiyun                cases_paths.append(cases_dir)
214*4882a593Smuzhiyun        return cases_paths
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun    def _process_args(self, logger, args):
217*4882a593Smuzhiyun        args.test_start_time = time.strftime("%Y%m%d%H%M%S")
218*4882a593Smuzhiyun        args.test_data_file = None
219*4882a593Smuzhiyun        args.CASES_PATHS = None
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun        bbvars = get_bb_vars()
222*4882a593Smuzhiyun        logdir = os.environ.get("BUILDDIR")
223*4882a593Smuzhiyun        if 'LOG_DIR' in bbvars:
224*4882a593Smuzhiyun            logdir = bbvars['LOG_DIR']
225*4882a593Smuzhiyun        bb.utils.mkdirhier(logdir)
226*4882a593Smuzhiyun        args.output_log = logdir + '/%s-results-%s.log' % (self.name, args.test_start_time)
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun        super(OESelftestTestContextExecutor, self)._process_args(logger, args)
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun        if args.list_modules:
231*4882a593Smuzhiyun            args.list_tests = 'module'
232*4882a593Smuzhiyun        elif args.list_classes:
233*4882a593Smuzhiyun            args.list_tests = 'class'
234*4882a593Smuzhiyun        elif args.list_tests:
235*4882a593Smuzhiyun            args.list_tests = 'name'
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun        self.tc_kwargs['init']['td'] = bbvars
238*4882a593Smuzhiyun        self.tc_kwargs['init']['machines'] = self._get_available_machines()
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun        builddir = os.environ.get("BUILDDIR")
241*4882a593Smuzhiyun        self.tc_kwargs['init']['config_paths'] = {}
242*4882a593Smuzhiyun        self.tc_kwargs['init']['config_paths']['testlayer_path'] = get_test_layer()
243*4882a593Smuzhiyun        self.tc_kwargs['init']['config_paths']['builddir'] = builddir
244*4882a593Smuzhiyun        self.tc_kwargs['init']['config_paths']['localconf'] = os.path.join(builddir, "conf/local.conf")
245*4882a593Smuzhiyun        self.tc_kwargs['init']['config_paths']['bblayers'] = os.path.join(builddir, "conf/bblayers.conf")
246*4882a593Smuzhiyun        self.tc_kwargs['init']['newbuilddir'] = args.newbuilddir
247*4882a593Smuzhiyun        self.tc_kwargs['init']['keep_builddir'] = args.keep_builddir
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun        def tag_filter(tags):
250*4882a593Smuzhiyun            if args.exclude_tags:
251*4882a593Smuzhiyun                if any(tag in args.exclude_tags for tag in tags):
252*4882a593Smuzhiyun                    return True
253*4882a593Smuzhiyun            if args.select_tags:
254*4882a593Smuzhiyun                if not tags or not any(tag in args.select_tags for tag in tags):
255*4882a593Smuzhiyun                    return True
256*4882a593Smuzhiyun            return False
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun        if args.select_tags or args.exclude_tags:
259*4882a593Smuzhiyun            self.tc_kwargs['load']['tags_filter'] = tag_filter
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun        self.tc_kwargs['run']['skips'] = args.skips
262*4882a593Smuzhiyun        self.tc_kwargs['run']['processes'] = args.processes
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun    def _pre_run(self):
265*4882a593Smuzhiyun        def _check_required_env_variables(vars):
266*4882a593Smuzhiyun            for var in vars:
267*4882a593Smuzhiyun                if not os.environ.get(var):
268*4882a593Smuzhiyun                    self.tc.logger.error("%s is not set. Did you forget to source your build environment setup script?" % var)
269*4882a593Smuzhiyun                    raise OEQAPreRun
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun        def _check_presence_meta_selftest():
272*4882a593Smuzhiyun            builddir = os.environ.get("BUILDDIR")
273*4882a593Smuzhiyun            if os.getcwd() != builddir:
274*4882a593Smuzhiyun                self.tc.logger.info("Changing cwd to %s" % builddir)
275*4882a593Smuzhiyun                os.chdir(builddir)
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun            if not "meta-selftest" in self.tc.td["BBLAYERS"]:
278*4882a593Smuzhiyun                self.tc.logger.warning("meta-selftest layer not found in BBLAYERS, adding it")
279*4882a593Smuzhiyun                meta_selftestdir = os.path.join(
280*4882a593Smuzhiyun                    self.tc.td["BBLAYERS_FETCH_DIR"], 'meta-selftest')
281*4882a593Smuzhiyun                if os.path.isdir(meta_selftestdir):
282*4882a593Smuzhiyun                    runCmd("bitbake-layers add-layer %s" %meta_selftestdir)
283*4882a593Smuzhiyun                    # reload data is needed because a meta-selftest layer was add
284*4882a593Smuzhiyun                    self.tc.td = get_bb_vars()
285*4882a593Smuzhiyun                    self.tc.config_paths['testlayer_path'] = get_test_layer()
286*4882a593Smuzhiyun                else:
287*4882a593Smuzhiyun                    self.tc.logger.error("could not locate meta-selftest in:\n%s" % meta_selftestdir)
288*4882a593Smuzhiyun                    raise OEQAPreRun
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun        def _add_layer_libs():
291*4882a593Smuzhiyun            bbpath = self.tc.td['BBPATH'].split(':')
292*4882a593Smuzhiyun            layer_libdirs = [p for p in (os.path.join(l, 'lib') \
293*4882a593Smuzhiyun                    for l in bbpath) if os.path.exists(p)]
294*4882a593Smuzhiyun            if layer_libdirs:
295*4882a593Smuzhiyun                self.tc.logger.info("Adding layer libraries:")
296*4882a593Smuzhiyun                for l in layer_libdirs:
297*4882a593Smuzhiyun                    self.tc.logger.info("\t%s" % l)
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun                sys.path.extend(layer_libdirs)
300*4882a593Smuzhiyun                importlib.reload(oeqa.selftest)
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun        _check_required_env_variables(["BUILDDIR"])
303*4882a593Smuzhiyun        _check_presence_meta_selftest()
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun        if "buildhistory.bbclass" in self.tc.td["BBINCLUDED"]:
306*4882a593Smuzhiyun            self.tc.logger.error("You have buildhistory enabled already and this isn't recommended for selftest, please disable it first.")
307*4882a593Smuzhiyun            raise OEQAPreRun
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun        if "rm_work.bbclass" in self.tc.td["BBINCLUDED"]:
310*4882a593Smuzhiyun            self.tc.logger.error("You have rm_work enabled which isn't recommended while running oe-selftest. Please disable it before continuing.")
311*4882a593Smuzhiyun            raise OEQAPreRun
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun        if "PRSERV_HOST" in self.tc.td:
314*4882a593Smuzhiyun            self.tc.logger.error("Please unset PRSERV_HOST in order to run oe-selftest")
315*4882a593Smuzhiyun            raise OEQAPreRun
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun        if "SANITY_TESTED_DISTROS" in self.tc.td:
318*4882a593Smuzhiyun            self.tc.logger.error("Please unset SANITY_TESTED_DISTROS in order to run oe-selftest")
319*4882a593Smuzhiyun            raise OEQAPreRun
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun        _add_layer_libs()
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun        self.tc.logger.info("Running bitbake -e to test the configuration is valid/parsable")
324*4882a593Smuzhiyun        runCmd("bitbake -e")
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun    def get_json_result_dir(self, args):
327*4882a593Smuzhiyun        json_result_dir = os.path.join(self.tc.td["LOG_DIR"], 'oeqa')
328*4882a593Smuzhiyun        if "OEQA_JSON_RESULT_DIR" in self.tc.td:
329*4882a593Smuzhiyun            json_result_dir = self.tc.td["OEQA_JSON_RESULT_DIR"]
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun        return json_result_dir
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun    def get_configuration(self, args):
334*4882a593Smuzhiyun        import platform
335*4882a593Smuzhiyun        from oeqa.utils.metadata import metadata_from_bb
336*4882a593Smuzhiyun        metadata = metadata_from_bb()
337*4882a593Smuzhiyun        configuration = {'TEST_TYPE': 'oeselftest',
338*4882a593Smuzhiyun                        'STARTTIME': args.test_start_time,
339*4882a593Smuzhiyun                        'MACHINE': self.tc.td["MACHINE"],
340*4882a593Smuzhiyun                        'HOST_DISTRO': oe.lsb.distro_identifier().replace(' ', '-'),
341*4882a593Smuzhiyun                        'HOST_NAME': metadata['hostname'],
342*4882a593Smuzhiyun                        'LAYERS': metadata['layers']}
343*4882a593Smuzhiyun        return configuration
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun    def get_result_id(self, configuration):
346*4882a593Smuzhiyun        return '%s_%s_%s_%s' % (configuration['TEST_TYPE'], configuration['HOST_DISTRO'], configuration['MACHINE'], configuration['STARTTIME'])
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun    def _internal_run(self, logger, args):
349*4882a593Smuzhiyun        self.module_paths = self._get_cases_paths(
350*4882a593Smuzhiyun                self.tc_kwargs['init']['td']['BBPATH'].split(':'))
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun        self.tc = self._context_class(**self.tc_kwargs['init'])
353*4882a593Smuzhiyun        try:
354*4882a593Smuzhiyun            self.tc.loadTests(self.module_paths, **self.tc_kwargs['load'])
355*4882a593Smuzhiyun        except OEQATestNotFound as ex:
356*4882a593Smuzhiyun            logger.error(ex)
357*4882a593Smuzhiyun            sys.exit(1)
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun        if args.list_tests:
360*4882a593Smuzhiyun            rc = self.tc.listTests(args.list_tests, **self.tc_kwargs['list'])
361*4882a593Smuzhiyun        else:
362*4882a593Smuzhiyun            self._pre_run()
363*4882a593Smuzhiyun            rc = self.tc.runTests(**self.tc_kwargs['run'])
364*4882a593Smuzhiyun            configuration = self.get_configuration(args)
365*4882a593Smuzhiyun            rc.logDetails(self.get_json_result_dir(args),
366*4882a593Smuzhiyun                          configuration,
367*4882a593Smuzhiyun                          self.get_result_id(configuration))
368*4882a593Smuzhiyun            rc.logSummary(self.name)
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun        return rc
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun    def run(self, logger, args):
373*4882a593Smuzhiyun        self._process_args(logger, args)
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun        rc = None
376*4882a593Smuzhiyun        try:
377*4882a593Smuzhiyun            if args.machine:
378*4882a593Smuzhiyun                logger.info('Custom machine mode enabled. MACHINE set to %s' %
379*4882a593Smuzhiyun                        args.machine)
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun                if args.machine == 'all':
382*4882a593Smuzhiyun                    results = []
383*4882a593Smuzhiyun                    for m in self.tc_kwargs['init']['machines']:
384*4882a593Smuzhiyun                        self.tc_kwargs['run']['machine'] = m
385*4882a593Smuzhiyun                        results.append(self._internal_run(logger, args))
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun                        # XXX: the oe-selftest script only needs to know if one
388*4882a593Smuzhiyun                        # machine run fails
389*4882a593Smuzhiyun                        for r in results:
390*4882a593Smuzhiyun                            rc = r
391*4882a593Smuzhiyun                            if not r.wasSuccessful():
392*4882a593Smuzhiyun                                break
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun                else:
395*4882a593Smuzhiyun                    self.tc_kwargs['run']['machine'] = args.machine
396*4882a593Smuzhiyun                    return self._internal_run(logger, args)
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun            else:
399*4882a593Smuzhiyun                self.tc_kwargs['run']['machine'] = args.machine
400*4882a593Smuzhiyun                rc = self._internal_run(logger, args)
401*4882a593Smuzhiyun        finally:
402*4882a593Smuzhiyun            config_paths = self.tc_kwargs['init']['config_paths']
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun            output_link = os.path.join(os.path.dirname(args.output_log),
405*4882a593Smuzhiyun                    "%s-results.log" % self.name)
406*4882a593Smuzhiyun            if os.path.lexists(output_link):
407*4882a593Smuzhiyun                os.remove(output_link)
408*4882a593Smuzhiyun            os.symlink(args.output_log, output_link)
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun        return rc
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun_executor_class = OESelftestTestContextExecutor
413