1*cfb92d14SAndroid Build Coastguard Worker#!/usr/bin/env python 2*cfb92d14SAndroid Build Coastguard Worker# 3*cfb92d14SAndroid Build Coastguard Worker# Copyright (c) 2016, The OpenThread Authors. 4*cfb92d14SAndroid Build Coastguard Worker# All rights reserved. 5*cfb92d14SAndroid Build Coastguard Worker# 6*cfb92d14SAndroid Build Coastguard Worker# Redistribution and use in source and binary forms, with or without 7*cfb92d14SAndroid Build Coastguard Worker# modification, are permitted provided that the following conditions are met: 8*cfb92d14SAndroid Build Coastguard Worker# 1. Redistributions of source code must retain the above copyright 9*cfb92d14SAndroid Build Coastguard Worker# notice, this list of conditions and the following disclaimer. 10*cfb92d14SAndroid Build Coastguard Worker# 2. Redistributions in binary form must reproduce the above copyright 11*cfb92d14SAndroid Build Coastguard Worker# notice, this list of conditions and the following disclaimer in the 12*cfb92d14SAndroid Build Coastguard Worker# documentation and/or other materials provided with the distribution. 13*cfb92d14SAndroid Build Coastguard Worker# 3. Neither the name of the copyright holder nor the 14*cfb92d14SAndroid Build Coastguard Worker# names of its contributors may be used to endorse or promote products 15*cfb92d14SAndroid Build Coastguard Worker# derived from this software without specific prior written permission. 16*cfb92d14SAndroid Build Coastguard Worker# 17*cfb92d14SAndroid Build Coastguard Worker# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18*cfb92d14SAndroid Build Coastguard Worker# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*cfb92d14SAndroid Build Coastguard Worker# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*cfb92d14SAndroid Build Coastguard Worker# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21*cfb92d14SAndroid Build Coastguard Worker# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22*cfb92d14SAndroid Build Coastguard Worker# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23*cfb92d14SAndroid Build Coastguard Worker# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24*cfb92d14SAndroid Build Coastguard Worker# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25*cfb92d14SAndroid Build Coastguard Worker# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26*cfb92d14SAndroid Build Coastguard Worker# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27*cfb92d14SAndroid Build Coastguard Worker# POSSIBILITY OF SUCH DAMAGE. 28*cfb92d14SAndroid Build Coastguard Worker# 29*cfb92d14SAndroid Build Coastguard Worker 30*cfb92d14SAndroid Build Coastguard Workerimport ConfigParser 31*cfb92d14SAndroid Build Coastguard Workerimport argparse 32*cfb92d14SAndroid Build Coastguard Workerimport fnmatch 33*cfb92d14SAndroid Build Coastguard Workerimport logging 34*cfb92d14SAndroid Build Coastguard Workerimport json 35*cfb92d14SAndroid Build Coastguard Workerimport os 36*cfb92d14SAndroid Build Coastguard Workerimport sys 37*cfb92d14SAndroid Build Coastguard Workerimport time 38*cfb92d14SAndroid Build Coastguard Workerimport unittest 39*cfb92d14SAndroid Build Coastguard Workerfrom collections import OrderedDict 40*cfb92d14SAndroid Build Coastguard Worker 41*cfb92d14SAndroid Build Coastguard Workerfrom autothreadharness.harness_case import HarnessCase 42*cfb92d14SAndroid Build Coastguard Workerfrom autothreadharness.open_thread_controller import OpenThreadController 43*cfb92d14SAndroid Build Coastguard Workerfrom autothreadharness import settings 44*cfb92d14SAndroid Build Coastguard Worker 45*cfb92d14SAndroid Build Coastguard Workerlogging.basicConfig(level=logging.INFO) 46*cfb92d14SAndroid Build Coastguard Worker 47*cfb92d14SAndroid Build Coastguard Workerlogger = logging.getLogger() 48*cfb92d14SAndroid Build Coastguard Worker"""Logger: The global logger""" 49*cfb92d14SAndroid Build Coastguard Worker 50*cfb92d14SAndroid Build Coastguard Workerlogger.setLevel(logging.INFO) 51*cfb92d14SAndroid Build Coastguard Worker 52*cfb92d14SAndroid Build Coastguard WorkerRESUME_SCRIPT_PATH = "%appdata%\\Microsoft\\Windows\\Start Menu\\Programs\\" "Startup\\continue_harness.bat" 53*cfb92d14SAndroid Build Coastguard Worker 54*cfb92d14SAndroid Build Coastguard Worker 55*cfb92d14SAndroid Build Coastguard Workerclass SimpleTestResult(unittest.TestResult): 56*cfb92d14SAndroid Build Coastguard Worker 57*cfb92d14SAndroid Build Coastguard Worker executions = 0 58*cfb92d14SAndroid Build Coastguard Worker 59*cfb92d14SAndroid Build Coastguard Worker def __init__(self, path, auto_reboot_args=None, keep_explorer=False, add_all_devices=False): 60*cfb92d14SAndroid Build Coastguard Worker """Record test results in json file 61*cfb92d14SAndroid Build Coastguard Worker 62*cfb92d14SAndroid Build Coastguard Worker Args: 63*cfb92d14SAndroid Build Coastguard Worker path (str): File path to record the results 64*cfb92d14SAndroid Build Coastguard Worker auto_reboot (bool): Whether reboot when harness die 65*cfb92d14SAndroid Build Coastguard Worker """ 66*cfb92d14SAndroid Build Coastguard Worker super(SimpleTestResult, self).__init__() 67*cfb92d14SAndroid Build Coastguard Worker self.path = path 68*cfb92d14SAndroid Build Coastguard Worker self.auto_reboot_args = auto_reboot_args 69*cfb92d14SAndroid Build Coastguard Worker self.result = json.load(open(self.path, 'r')) 70*cfb92d14SAndroid Build Coastguard Worker self.log_handler = None 71*cfb92d14SAndroid Build Coastguard Worker self.started = None 72*cfb92d14SAndroid Build Coastguard Worker self.keep_explorer = keep_explorer 73*cfb92d14SAndroid Build Coastguard Worker self.add_all_devices = add_all_devices 74*cfb92d14SAndroid Build Coastguard Worker SimpleTestResult.executions += 1 75*cfb92d14SAndroid Build Coastguard Worker logger.info('Initial state is %s', json.dumps(self.result, indent=2)) 76*cfb92d14SAndroid Build Coastguard Worker 77*cfb92d14SAndroid Build Coastguard Worker def startTest(self, test): 78*cfb92d14SAndroid Build Coastguard Worker logger.info( 79*cfb92d14SAndroid Build Coastguard Worker '\n========================================\n%s\n========================================', 80*cfb92d14SAndroid Build Coastguard Worker test.__class__.__name__, 81*cfb92d14SAndroid Build Coastguard Worker ) 82*cfb92d14SAndroid Build Coastguard Worker 83*cfb92d14SAndroid Build Coastguard Worker test.add_all_devices = self.add_all_devices 84*cfb92d14SAndroid Build Coastguard Worker # create start up script if auto reboot enabled 85*cfb92d14SAndroid Build Coastguard Worker if self.auto_reboot_args: 86*cfb92d14SAndroid Build Coastguard Worker test.auto_reboot = True 87*cfb92d14SAndroid Build Coastguard Worker os.system('echo %s > "%s"' % 88*cfb92d14SAndroid Build Coastguard Worker (' '.join(self.auto_reboot_args + ['-c', test.__class__.__name__]), RESUME_SCRIPT_PATH)) 89*cfb92d14SAndroid Build Coastguard Worker 90*cfb92d14SAndroid Build Coastguard Worker # record start timestamp 91*cfb92d14SAndroid Build Coastguard Worker self.started = time.strftime('%Y-%m-%dT%H:%M:%S') 92*cfb92d14SAndroid Build Coastguard Worker 93*cfb92d14SAndroid Build Coastguard Worker os.system('mkdir %s' % test.result_dir) 94*cfb92d14SAndroid Build Coastguard Worker self.log_handler = logging.FileHandler('%s\\auto-%s.log' % (test.result_dir, time.strftime('%Y%m%d%H%M%S'))) 95*cfb92d14SAndroid Build Coastguard Worker self.log_handler.setLevel(logging.DEBUG) 96*cfb92d14SAndroid Build Coastguard Worker self.log_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s')) 97*cfb92d14SAndroid Build Coastguard Worker logger.addHandler(self.log_handler) 98*cfb92d14SAndroid Build Coastguard Worker 99*cfb92d14SAndroid Build Coastguard Worker def add_result(self, test, passed, error=None): 100*cfb92d14SAndroid Build Coastguard Worker """Record test result into json file 101*cfb92d14SAndroid Build Coastguard Worker 102*cfb92d14SAndroid Build Coastguard Worker Args: 103*cfb92d14SAndroid Build Coastguard Worker test (TestCase): The test just run 104*cfb92d14SAndroid Build Coastguard Worker passed (bool): Whether the case is passed 105*cfb92d14SAndroid Build Coastguard Worker """ 106*cfb92d14SAndroid Build Coastguard Worker fails = self.result.get(test.__class__.__name__, {}).get('fails', 0) 107*cfb92d14SAndroid Build Coastguard Worker if passed is False: 108*cfb92d14SAndroid Build Coastguard Worker fails += 1 109*cfb92d14SAndroid Build Coastguard Worker self.result[str(test.__class__.__name__)] = { 110*cfb92d14SAndroid Build Coastguard Worker 'started': self.started, 111*cfb92d14SAndroid Build Coastguard Worker 'stopped': time.strftime('%Y-%m-%dT%H:%M:%S'), 112*cfb92d14SAndroid Build Coastguard Worker 'passed': passed, 113*cfb92d14SAndroid Build Coastguard Worker 'fails': fails, 114*cfb92d14SAndroid Build Coastguard Worker 'error': error, 115*cfb92d14SAndroid Build Coastguard Worker 'executions': SimpleTestResult.executions, 116*cfb92d14SAndroid Build Coastguard Worker } 117*cfb92d14SAndroid Build Coastguard Worker if self.auto_reboot_args: 118*cfb92d14SAndroid Build Coastguard Worker os.system('del "%s"' % RESUME_SCRIPT_PATH) 119*cfb92d14SAndroid Build Coastguard Worker 120*cfb92d14SAndroid Build Coastguard Worker json.dump(OrderedDict(sorted(self.result.items(), key=lambda t: t[0])), open(self.path, 'w'), indent=2) 121*cfb92d14SAndroid Build Coastguard Worker 122*cfb92d14SAndroid Build Coastguard Worker # save logs 123*cfb92d14SAndroid Build Coastguard Worker logger.removeHandler(self.log_handler) 124*cfb92d14SAndroid Build Coastguard Worker self.log_handler.close() 125*cfb92d14SAndroid Build Coastguard Worker self.log_handler = None 126*cfb92d14SAndroid Build Coastguard Worker time.sleep(2) 127*cfb92d14SAndroid Build Coastguard Worker 128*cfb92d14SAndroid Build Coastguard Worker # close explorers 129*cfb92d14SAndroid Build Coastguard Worker if not self.keep_explorer: 130*cfb92d14SAndroid Build Coastguard Worker os.system('taskkill /f /im explorer.exe && start explorer.exe') 131*cfb92d14SAndroid Build Coastguard Worker 132*cfb92d14SAndroid Build Coastguard Worker def addSuccess(self, test): 133*cfb92d14SAndroid Build Coastguard Worker logger.info('case[%s] pass', test.__class__.__name__) 134*cfb92d14SAndroid Build Coastguard Worker super(SimpleTestResult, self).addSuccess(test) 135*cfb92d14SAndroid Build Coastguard Worker self.add_result(test, True) 136*cfb92d14SAndroid Build Coastguard Worker 137*cfb92d14SAndroid Build Coastguard Worker def addFailure(self, test, err): 138*cfb92d14SAndroid Build Coastguard Worker logger.warning('case[%s] fail', test.__class__.__name__) 139*cfb92d14SAndroid Build Coastguard Worker super(SimpleTestResult, self).addFailure(test, err) 140*cfb92d14SAndroid Build Coastguard Worker self.add_result(test, False) 141*cfb92d14SAndroid Build Coastguard Worker 142*cfb92d14SAndroid Build Coastguard Worker def addError(self, test, err): 143*cfb92d14SAndroid Build Coastguard Worker logger.error('case[%s] error', test.__class__.__name__, exc_info=err) 144*cfb92d14SAndroid Build Coastguard Worker 145*cfb92d14SAndroid Build Coastguard Worker if err and err[0] is SystemExit: 146*cfb92d14SAndroid Build Coastguard Worker if self.auto_reboot_args: 147*cfb92d14SAndroid Build Coastguard Worker logger.warning('rebooting..') 148*cfb92d14SAndroid Build Coastguard Worker os.system('shutdown /r /t 1') 149*cfb92d14SAndroid Build Coastguard Worker else: 150*cfb92d14SAndroid Build Coastguard Worker logger.warning('exiting..') 151*cfb92d14SAndroid Build Coastguard Worker sys.exit(1) 152*cfb92d14SAndroid Build Coastguard Worker 153*cfb92d14SAndroid Build Coastguard Worker super(SimpleTestResult, self).addError(test, err) 154*cfb92d14SAndroid Build Coastguard Worker self.add_result(test, None, str(err[1])) 155*cfb92d14SAndroid Build Coastguard Worker 156*cfb92d14SAndroid Build Coastguard Worker 157*cfb92d14SAndroid Build Coastguard Workerdef list_devices(names=None, continue_from=None, **kwargs): 158*cfb92d14SAndroid Build Coastguard Worker """List devices in settings file and print versions""" 159*cfb92d14SAndroid Build Coastguard Worker 160*cfb92d14SAndroid Build Coastguard Worker if not names: 161*cfb92d14SAndroid Build Coastguard Worker names = [device for device, _type in settings.GOLDEN_DEVICES if _type == 'OpenThread'] 162*cfb92d14SAndroid Build Coastguard Worker 163*cfb92d14SAndroid Build Coastguard Worker if continue_from: 164*cfb92d14SAndroid Build Coastguard Worker continue_from = names.index(continue_from) 165*cfb92d14SAndroid Build Coastguard Worker else: 166*cfb92d14SAndroid Build Coastguard Worker continue_from = 0 167*cfb92d14SAndroid Build Coastguard Worker 168*cfb92d14SAndroid Build Coastguard Worker for port in names[continue_from:]: 169*cfb92d14SAndroid Build Coastguard Worker try: 170*cfb92d14SAndroid Build Coastguard Worker with OpenThreadController(port) as otc: 171*cfb92d14SAndroid Build Coastguard Worker print('%s: %s' % (port, otc.version)) 172*cfb92d14SAndroid Build Coastguard Worker except BaseException: 173*cfb92d14SAndroid Build Coastguard Worker logger.exception('failed to get version of %s' % port) 174*cfb92d14SAndroid Build Coastguard Worker 175*cfb92d14SAndroid Build Coastguard Worker 176*cfb92d14SAndroid Build Coastguard Workerdef discover( 177*cfb92d14SAndroid Build Coastguard Worker names=None, 178*cfb92d14SAndroid Build Coastguard Worker pattern=['*.py'], 179*cfb92d14SAndroid Build Coastguard Worker skip='efp', 180*cfb92d14SAndroid Build Coastguard Worker dry_run=False, 181*cfb92d14SAndroid Build Coastguard Worker denylist=None, 182*cfb92d14SAndroid Build Coastguard Worker name_greps=None, 183*cfb92d14SAndroid Build Coastguard Worker manual_reset=False, 184*cfb92d14SAndroid Build Coastguard Worker delete_history=False, 185*cfb92d14SAndroid Build Coastguard Worker max_devices=0, 186*cfb92d14SAndroid Build Coastguard Worker continue_from=None, 187*cfb92d14SAndroid Build Coastguard Worker result_file='./result.json', 188*cfb92d14SAndroid Build Coastguard Worker auto_reboot=False, 189*cfb92d14SAndroid Build Coastguard Worker keep_explorer=False, 190*cfb92d14SAndroid Build Coastguard Worker add_all_devices=False, 191*cfb92d14SAndroid Build Coastguard Worker): 192*cfb92d14SAndroid Build Coastguard Worker """Discover all test cases and skip those passed 193*cfb92d14SAndroid Build Coastguard Worker 194*cfb92d14SAndroid Build Coastguard Worker Args: 195*cfb92d14SAndroid Build Coastguard Worker pattern (str): Pattern to match case modules, refer python's unittest 196*cfb92d14SAndroid Build Coastguard Worker documentation for more details 197*cfb92d14SAndroid Build Coastguard Worker skip (str): types cases to skip 198*cfb92d14SAndroid Build Coastguard Worker """ 199*cfb92d14SAndroid Build Coastguard Worker if not os.path.exists(settings.OUTPUT_PATH): 200*cfb92d14SAndroid Build Coastguard Worker os.mkdir(settings.OUTPUT_PATH) 201*cfb92d14SAndroid Build Coastguard Worker 202*cfb92d14SAndroid Build Coastguard Worker if delete_history: 203*cfb92d14SAndroid Build Coastguard Worker os.system('del history.json') 204*cfb92d14SAndroid Build Coastguard Worker 205*cfb92d14SAndroid Build Coastguard Worker if denylist: 206*cfb92d14SAndroid Build Coastguard Worker try: 207*cfb92d14SAndroid Build Coastguard Worker excludes = [line.strip('\n') for line in open(denylist, 'r').readlines() if not line.startswith('#')] 208*cfb92d14SAndroid Build Coastguard Worker except BaseException: 209*cfb92d14SAndroid Build Coastguard Worker logger.exception('Failed to open test case denylist file') 210*cfb92d14SAndroid Build Coastguard Worker raise 211*cfb92d14SAndroid Build Coastguard Worker else: 212*cfb92d14SAndroid Build Coastguard Worker excludes = [] 213*cfb92d14SAndroid Build Coastguard Worker 214*cfb92d14SAndroid Build Coastguard Worker log = None 215*cfb92d14SAndroid Build Coastguard Worker if os.path.isfile(result_file): 216*cfb92d14SAndroid Build Coastguard Worker try: 217*cfb92d14SAndroid Build Coastguard Worker log = json.load(open(result_file, 'r')) 218*cfb92d14SAndroid Build Coastguard Worker except BaseException: 219*cfb92d14SAndroid Build Coastguard Worker logger.exception('Failed to open result file') 220*cfb92d14SAndroid Build Coastguard Worker 221*cfb92d14SAndroid Build Coastguard Worker if not log: 222*cfb92d14SAndroid Build Coastguard Worker log = {} 223*cfb92d14SAndroid Build Coastguard Worker json.dump(log, open(result_file, 'w'), indent=2) 224*cfb92d14SAndroid Build Coastguard Worker 225*cfb92d14SAndroid Build Coastguard Worker new_th = False 226*cfb92d14SAndroid Build Coastguard Worker harness_info = ConfigParser.ConfigParser() 227*cfb92d14SAndroid Build Coastguard Worker harness_info.read('%s\\info.ini' % settings.HARNESS_HOME) 228*cfb92d14SAndroid Build Coastguard Worker if harness_info.has_option('Thread_Harness_Info', 'Version') and harness_info.has_option( 229*cfb92d14SAndroid Build Coastguard Worker 'Thread_Harness_Info', 'Mode'): 230*cfb92d14SAndroid Build Coastguard Worker harness_version = harness_info.get('Thread_Harness_Info', 'Version').rsplit(' ', 1)[1] 231*cfb92d14SAndroid Build Coastguard Worker harness_mode = harness_info.get('Thread_Harness_Info', 'Mode') 232*cfb92d14SAndroid Build Coastguard Worker 233*cfb92d14SAndroid Build Coastguard Worker if harness_mode == 'External' and harness_version > '1.4.0': 234*cfb92d14SAndroid Build Coastguard Worker new_th = True 235*cfb92d14SAndroid Build Coastguard Worker 236*cfb92d14SAndroid Build Coastguard Worker if harness_mode == 'Internal' and harness_version > '49.4': 237*cfb92d14SAndroid Build Coastguard Worker new_th = True 238*cfb92d14SAndroid Build Coastguard Worker 239*cfb92d14SAndroid Build Coastguard Worker suite = unittest.TestSuite() 240*cfb92d14SAndroid Build Coastguard Worker if new_th: 241*cfb92d14SAndroid Build Coastguard Worker discovered = unittest.defaultTestLoader.discover('cases', pattern) 242*cfb92d14SAndroid Build Coastguard Worker else: 243*cfb92d14SAndroid Build Coastguard Worker discovered = unittest.defaultTestLoader.discover('cases_R140', pattern) 244*cfb92d14SAndroid Build Coastguard Worker 245*cfb92d14SAndroid Build Coastguard Worker if names and continue_from: 246*cfb92d14SAndroid Build Coastguard Worker names = names[names.index(continue_from):] 247*cfb92d14SAndroid Build Coastguard Worker 248*cfb92d14SAndroid Build Coastguard Worker for s1 in discovered: 249*cfb92d14SAndroid Build Coastguard Worker for s2 in s1: 250*cfb92d14SAndroid Build Coastguard Worker for case in s2: 251*cfb92d14SAndroid Build Coastguard Worker if case.__class__ is HarnessCase: 252*cfb92d14SAndroid Build Coastguard Worker continue 253*cfb92d14SAndroid Build Coastguard Worker case_name = str(case.__class__.__name__) 254*cfb92d14SAndroid Build Coastguard Worker 255*cfb92d14SAndroid Build Coastguard Worker # grep name 256*cfb92d14SAndroid Build Coastguard Worker if name_greps and not any(fnmatch.fnmatch(case_name, name_grep) for name_grep in name_greps): 257*cfb92d14SAndroid Build Coastguard Worker logger.info('case[%s] skipped by name greps', case_name) 258*cfb92d14SAndroid Build Coastguard Worker continue 259*cfb92d14SAndroid Build Coastguard Worker 260*cfb92d14SAndroid Build Coastguard Worker # allowlist 261*cfb92d14SAndroid Build Coastguard Worker if len(names) and case_name not in names: 262*cfb92d14SAndroid Build Coastguard Worker logger.info('case[%s] skipped', case_name) 263*cfb92d14SAndroid Build Coastguard Worker continue 264*cfb92d14SAndroid Build Coastguard Worker 265*cfb92d14SAndroid Build Coastguard Worker # skip cases 266*cfb92d14SAndroid Build Coastguard Worker if case_name in log: 267*cfb92d14SAndroid Build Coastguard Worker if ((log[case_name]['passed'] and ('p' in skip)) or 268*cfb92d14SAndroid Build Coastguard Worker (log[case_name]['passed'] is False and ('f' in skip)) or (log[case_name]['passed'] is None and 269*cfb92d14SAndroid Build Coastguard Worker ('e' in skip))): 270*cfb92d14SAndroid Build Coastguard Worker logger.warning('case[%s] skipped for its status[%s]', case_name, log[case_name]['passed']) 271*cfb92d14SAndroid Build Coastguard Worker continue 272*cfb92d14SAndroid Build Coastguard Worker 273*cfb92d14SAndroid Build Coastguard Worker # continue from 274*cfb92d14SAndroid Build Coastguard Worker if continue_from: 275*cfb92d14SAndroid Build Coastguard Worker if continue_from != case_name: 276*cfb92d14SAndroid Build Coastguard Worker logger.warning('case[%s] skipped for continue from[%s]', case_name, continue_from) 277*cfb92d14SAndroid Build Coastguard Worker continue 278*cfb92d14SAndroid Build Coastguard Worker else: 279*cfb92d14SAndroid Build Coastguard Worker continue_from = None 280*cfb92d14SAndroid Build Coastguard Worker 281*cfb92d14SAndroid Build Coastguard Worker # denylist 282*cfb92d14SAndroid Build Coastguard Worker if case_name in excludes: 283*cfb92d14SAndroid Build Coastguard Worker logger.warning('case[%s] skipped for denylist', case_name) 284*cfb92d14SAndroid Build Coastguard Worker continue 285*cfb92d14SAndroid Build Coastguard Worker 286*cfb92d14SAndroid Build Coastguard Worker # max devices 287*cfb92d14SAndroid Build Coastguard Worker if max_devices and case.golden_devices_required > max_devices: 288*cfb92d14SAndroid Build Coastguard Worker logger.warning('case[%s] skipped for exceeding max golden devices allowed[%d]', case_name, 289*cfb92d14SAndroid Build Coastguard Worker max_devices) 290*cfb92d14SAndroid Build Coastguard Worker continue 291*cfb92d14SAndroid Build Coastguard Worker 292*cfb92d14SAndroid Build Coastguard Worker suite.addTest(case) 293*cfb92d14SAndroid Build Coastguard Worker logger.info('case[%s] added', case_name) 294*cfb92d14SAndroid Build Coastguard Worker 295*cfb92d14SAndroid Build Coastguard Worker if auto_reboot: 296*cfb92d14SAndroid Build Coastguard Worker argv = [] 297*cfb92d14SAndroid Build Coastguard Worker argv.append('"%s"' % os.sep.join([os.getcwd(), 'start.bat'])) 298*cfb92d14SAndroid Build Coastguard Worker argv.extend(['-p', pattern]) 299*cfb92d14SAndroid Build Coastguard Worker argv.extend(['-k', skip]) 300*cfb92d14SAndroid Build Coastguard Worker argv.extend(['-o', result_file]) 301*cfb92d14SAndroid Build Coastguard Worker argv.append('-a') 302*cfb92d14SAndroid Build Coastguard Worker 303*cfb92d14SAndroid Build Coastguard Worker if manual_reset: 304*cfb92d14SAndroid Build Coastguard Worker argv.append('-m') 305*cfb92d14SAndroid Build Coastguard Worker 306*cfb92d14SAndroid Build Coastguard Worker if delete_history: 307*cfb92d14SAndroid Build Coastguard Worker argv.append('-d') 308*cfb92d14SAndroid Build Coastguard Worker 309*cfb92d14SAndroid Build Coastguard Worker auto_reboot_args = argv + names 310*cfb92d14SAndroid Build Coastguard Worker else: 311*cfb92d14SAndroid Build Coastguard Worker auto_reboot_args = None 312*cfb92d14SAndroid Build Coastguard Worker if os.path.isfile(RESUME_SCRIPT_PATH): 313*cfb92d14SAndroid Build Coastguard Worker os.system('del "%s"' % RESUME_SCRIPT_PATH) 314*cfb92d14SAndroid Build Coastguard Worker 315*cfb92d14SAndroid Build Coastguard Worker # manual reset 316*cfb92d14SAndroid Build Coastguard Worker if manual_reset: 317*cfb92d14SAndroid Build Coastguard Worker settings.PDU_CONTROLLER_TYPE = 'MANUAL_PDU_CONTROLLER' 318*cfb92d14SAndroid Build Coastguard Worker settings.PDU_CONTROLLER_OPEN_PARAMS = {} 319*cfb92d14SAndroid Build Coastguard Worker settings.PDU_CONTROLLER_REBOOT_PARAMS = {} 320*cfb92d14SAndroid Build Coastguard Worker 321*cfb92d14SAndroid Build Coastguard Worker result = SimpleTestResult(result_file, auto_reboot_args, keep_explorer, add_all_devices) 322*cfb92d14SAndroid Build Coastguard Worker for case in suite: 323*cfb92d14SAndroid Build Coastguard Worker logger.info(case.__class__.__name__) 324*cfb92d14SAndroid Build Coastguard Worker 325*cfb92d14SAndroid Build Coastguard Worker if dry_run: 326*cfb92d14SAndroid Build Coastguard Worker return 327*cfb92d14SAndroid Build Coastguard Worker 328*cfb92d14SAndroid Build Coastguard Worker suite.run(result) 329*cfb92d14SAndroid Build Coastguard Worker return result 330*cfb92d14SAndroid Build Coastguard Worker 331*cfb92d14SAndroid Build Coastguard Worker 332*cfb92d14SAndroid Build Coastguard Workerdef main(): 333*cfb92d14SAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description='Thread harness test case runner') 334*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--auto-reboot', 335*cfb92d14SAndroid Build Coastguard Worker '-a', 336*cfb92d14SAndroid Build Coastguard Worker action='store_true', 337*cfb92d14SAndroid Build Coastguard Worker default=False, 338*cfb92d14SAndroid Build Coastguard Worker help='restart system when harness service die') 339*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('names', 340*cfb92d14SAndroid Build Coastguard Worker metavar='NAME', 341*cfb92d14SAndroid Build Coastguard Worker type=str, 342*cfb92d14SAndroid Build Coastguard Worker nargs='*', 343*cfb92d14SAndroid Build Coastguard Worker default=None, 344*cfb92d14SAndroid Build Coastguard Worker help='test case name, omit to test all') 345*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--denylist', 346*cfb92d14SAndroid Build Coastguard Worker '-b', 347*cfb92d14SAndroid Build Coastguard Worker metavar='DENYLIST_FILE', 348*cfb92d14SAndroid Build Coastguard Worker type=str, 349*cfb92d14SAndroid Build Coastguard Worker help='file to list test cases to skip', 350*cfb92d14SAndroid Build Coastguard Worker default=None) 351*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--continue-from', '-c', type=str, default=None, help='first case to test') 352*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--delete-history', '-d', action='store_true', default=False, help='clear history on startup') 353*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--keep-explorer', 354*cfb92d14SAndroid Build Coastguard Worker '-e', 355*cfb92d14SAndroid Build Coastguard Worker action='store_true', 356*cfb92d14SAndroid Build Coastguard Worker default=False, 357*cfb92d14SAndroid Build Coastguard Worker help='do not restart explorer.exe at the end') 358*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--name-greps', '-g', action='append', default=None, help='grep case by names') 359*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--list-file', '-i', type=str, default=None, help='file to list cases names to test') 360*cfb92d14SAndroid Build Coastguard Worker parser.add_argument( 361*cfb92d14SAndroid Build Coastguard Worker '--skip', 362*cfb92d14SAndroid Build Coastguard Worker '-k', 363*cfb92d14SAndroid Build Coastguard Worker metavar='SKIP', 364*cfb92d14SAndroid Build Coastguard Worker type=str, 365*cfb92d14SAndroid Build Coastguard Worker help='type of results to skip. e for error, f for fail, p for pass.', 366*cfb92d14SAndroid Build Coastguard Worker default='', 367*cfb92d14SAndroid Build Coastguard Worker ) 368*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--list-devices', '-l', action='store_true', default=False, help='list devices') 369*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--manual-reset', '-m', action='store_true', default=False, help='reset devices manually') 370*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--dry-run', '-n', action='store_true', default=False, help='just show what to run') 371*cfb92d14SAndroid Build Coastguard Worker parser.add_argument( 372*cfb92d14SAndroid Build Coastguard Worker '--result-file', 373*cfb92d14SAndroid Build Coastguard Worker '-o', 374*cfb92d14SAndroid Build Coastguard Worker type=str, 375*cfb92d14SAndroid Build Coastguard Worker default=settings.OUTPUT_PATH + '\\result.json', 376*cfb92d14SAndroid Build Coastguard Worker help='file to store and read current status', 377*cfb92d14SAndroid Build Coastguard Worker ) 378*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--pattern', 379*cfb92d14SAndroid Build Coastguard Worker '-p', 380*cfb92d14SAndroid Build Coastguard Worker metavar='PATTERN', 381*cfb92d14SAndroid Build Coastguard Worker type=str, 382*cfb92d14SAndroid Build Coastguard Worker help='file name pattern, default to "*.py"', 383*cfb92d14SAndroid Build Coastguard Worker default='*.py') 384*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--rerun-fails', '-r', type=int, default=0, help='number of times to rerun failed test cases') 385*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--add-all-devices', 386*cfb92d14SAndroid Build Coastguard Worker '-t', 387*cfb92d14SAndroid Build Coastguard Worker action='store_true', 388*cfb92d14SAndroid Build Coastguard Worker default=False, 389*cfb92d14SAndroid Build Coastguard Worker help='add all devices to the test bed') 390*cfb92d14SAndroid Build Coastguard Worker parser.add_argument('--max-devices', '-u', type=int, default=0, help='max golden devices allowed') 391*cfb92d14SAndroid Build Coastguard Worker 392*cfb92d14SAndroid Build Coastguard Worker args = vars(parser.parse_args()) 393*cfb92d14SAndroid Build Coastguard Worker 394*cfb92d14SAndroid Build Coastguard Worker if args['list_file']: 395*cfb92d14SAndroid Build Coastguard Worker try: 396*cfb92d14SAndroid Build Coastguard Worker names = [line.strip('\n') for line in open(args['list_file'], 'r').readlines() if not line.startswith('#')] 397*cfb92d14SAndroid Build Coastguard Worker except BaseException: 398*cfb92d14SAndroid Build Coastguard Worker logger.exception('Failed to open test case list file') 399*cfb92d14SAndroid Build Coastguard Worker raise 400*cfb92d14SAndroid Build Coastguard Worker else: 401*cfb92d14SAndroid Build Coastguard Worker args['names'] = args['names'] + names 402*cfb92d14SAndroid Build Coastguard Worker 403*cfb92d14SAndroid Build Coastguard Worker args.pop('list_file') 404*cfb92d14SAndroid Build Coastguard Worker 405*cfb92d14SAndroid Build Coastguard Worker if args.pop('list_devices', False): 406*cfb92d14SAndroid Build Coastguard Worker list_devices(**args) 407*cfb92d14SAndroid Build Coastguard Worker return 408*cfb92d14SAndroid Build Coastguard Worker 409*cfb92d14SAndroid Build Coastguard Worker rerun_fails = args.pop('rerun_fails') 410*cfb92d14SAndroid Build Coastguard Worker result = discover(**args) 411*cfb92d14SAndroid Build Coastguard Worker 412*cfb92d14SAndroid Build Coastguard Worker if rerun_fails > 0: 413*cfb92d14SAndroid Build Coastguard Worker for i in range(rerun_fails): 414*cfb92d14SAndroid Build Coastguard Worker failed_names = {name for name in result.result if result.result[name]['passed'] is False} 415*cfb92d14SAndroid Build Coastguard Worker if not failed_names: 416*cfb92d14SAndroid Build Coastguard Worker break 417*cfb92d14SAndroid Build Coastguard Worker logger.info('Rerunning failed test cases') 418*cfb92d14SAndroid Build Coastguard Worker logger.info('Rerun #{}:'.format(i + 1)) 419*cfb92d14SAndroid Build Coastguard Worker result = discover( 420*cfb92d14SAndroid Build Coastguard Worker names=failed_names, 421*cfb92d14SAndroid Build Coastguard Worker pattern=args['pattern'], 422*cfb92d14SAndroid Build Coastguard Worker skip='', 423*cfb92d14SAndroid Build Coastguard Worker result_file=args['result_file'], 424*cfb92d14SAndroid Build Coastguard Worker auto_reboot=args['auto_reboot'], 425*cfb92d14SAndroid Build Coastguard Worker keep_explorer=args['keep_explorer'], 426*cfb92d14SAndroid Build Coastguard Worker add_all_devices=args['add_all_devices'], 427*cfb92d14SAndroid Build Coastguard Worker ) 428*cfb92d14SAndroid Build Coastguard Worker 429*cfb92d14SAndroid Build Coastguard Worker 430*cfb92d14SAndroid Build Coastguard Workerif __name__ == '__main__': 431*cfb92d14SAndroid Build Coastguard Worker main() 432