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