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 json 32*cfb92d14SAndroid Build Coastguard Workerimport logging 33*cfb92d14SAndroid Build Coastguard Workerimport os 34*cfb92d14SAndroid Build Coastguard Workerimport subprocess 35*cfb92d14SAndroid Build Coastguard Workerimport re 36*cfb92d14SAndroid Build Coastguard Workerimport time 37*cfb92d14SAndroid Build Coastguard Workerimport unittest 38*cfb92d14SAndroid Build Coastguard Worker 39*cfb92d14SAndroid Build Coastguard Workerfrom selenium import webdriver 40*cfb92d14SAndroid Build Coastguard Workerfrom selenium.webdriver import ActionChains 41*cfb92d14SAndroid Build Coastguard Workerfrom selenium.webdriver.support.ui import Select 42*cfb92d14SAndroid Build Coastguard Workerfrom selenium.common.exceptions import UnexpectedAlertPresentException 43*cfb92d14SAndroid Build Coastguard Workerfrom selenium.common.exceptions import NoSuchElementException 44*cfb92d14SAndroid Build Coastguard Workerfrom functools import reduce 45*cfb92d14SAndroid Build Coastguard Worker 46*cfb92d14SAndroid Build Coastguard Workerfrom autothreadharness import settings 47*cfb92d14SAndroid Build Coastguard Workerfrom autothreadharness.exceptions import FailError, FatalError, GoldenDeviceNotEnoughError 48*cfb92d14SAndroid Build Coastguard Workerfrom autothreadharness.harness_controller import HarnessController 49*cfb92d14SAndroid Build Coastguard Workerfrom autothreadharness.helpers import HistoryHelper 50*cfb92d14SAndroid Build Coastguard Workerfrom autothreadharness.open_thread_controller import OpenThreadController 51*cfb92d14SAndroid Build Coastguard Workerfrom autothreadharness.pdu_controller_factory import PduControllerFactory 52*cfb92d14SAndroid Build Coastguard Workerfrom autothreadharness.rf_shield_controller import get_rf_shield_controller 53*cfb92d14SAndroid Build Coastguard Worker 54*cfb92d14SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__) 55*cfb92d14SAndroid Build Coastguard Worker 56*cfb92d14SAndroid Build Coastguard WorkerTHREAD_CHANNEL_MAX = 26 57*cfb92d14SAndroid Build Coastguard Worker"""Maximum channel number of thread protocol""" 58*cfb92d14SAndroid Build Coastguard Worker 59*cfb92d14SAndroid Build Coastguard WorkerTHREAD_CHANNEL_MIN = 11 60*cfb92d14SAndroid Build Coastguard Worker"""Minimum channel number of thread protocol""" 61*cfb92d14SAndroid Build Coastguard Worker 62*cfb92d14SAndroid Build Coastguard WorkerDEFAULT_TIMEOUT = 2700 63*cfb92d14SAndroid Build Coastguard Worker"""Timeout for each test case in seconds""" 64*cfb92d14SAndroid Build Coastguard Worker 65*cfb92d14SAndroid Build Coastguard Worker 66*cfb92d14SAndroid Build Coastguard Workerdef wait_until(what, times=-1): 67*cfb92d14SAndroid Build Coastguard Worker """Wait until `what` return True 68*cfb92d14SAndroid Build Coastguard Worker 69*cfb92d14SAndroid Build Coastguard Worker Args: 70*cfb92d14SAndroid Build Coastguard Worker what (Callable[bool]): Call `wait()` again and again until it returns True 71*cfb92d14SAndroid Build Coastguard Worker times (int): Maximum times of trials before giving up 72*cfb92d14SAndroid Build Coastguard Worker 73*cfb92d14SAndroid Build Coastguard Worker Returns: 74*cfb92d14SAndroid Build Coastguard Worker True if success, False if times threshold reached 75*cfb92d14SAndroid Build Coastguard Worker 76*cfb92d14SAndroid Build Coastguard Worker """ 77*cfb92d14SAndroid Build Coastguard Worker while times: 78*cfb92d14SAndroid Build Coastguard Worker logger.info('Waiting times left %d', times) 79*cfb92d14SAndroid Build Coastguard Worker try: 80*cfb92d14SAndroid Build Coastguard Worker if what() is True: 81*cfb92d14SAndroid Build Coastguard Worker return True 82*cfb92d14SAndroid Build Coastguard Worker except BaseException: 83*cfb92d14SAndroid Build Coastguard Worker logger.exception('Wait failed') 84*cfb92d14SAndroid Build Coastguard Worker else: 85*cfb92d14SAndroid Build Coastguard Worker logger.warning('Trial[%d] failed', times) 86*cfb92d14SAndroid Build Coastguard Worker times -= 1 87*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 88*cfb92d14SAndroid Build Coastguard Worker 89*cfb92d14SAndroid Build Coastguard Worker return False 90*cfb92d14SAndroid Build Coastguard Worker 91*cfb92d14SAndroid Build Coastguard Worker 92*cfb92d14SAndroid Build Coastguard Workerclass HarnessCase(unittest.TestCase): 93*cfb92d14SAndroid Build Coastguard Worker """This is the case class of all automation test cases. 94*cfb92d14SAndroid Build Coastguard Worker 95*cfb92d14SAndroid Build Coastguard Worker All test case classes MUST define properties `role`, `case` and `golden_devices_required` 96*cfb92d14SAndroid Build Coastguard Worker """ 97*cfb92d14SAndroid Build Coastguard Worker 98*cfb92d14SAndroid Build Coastguard Worker channel = settings.THREAD_CHANNEL 99*cfb92d14SAndroid Build Coastguard Worker """int: Thread channel. 100*cfb92d14SAndroid Build Coastguard Worker 101*cfb92d14SAndroid Build Coastguard Worker Thread channel ranges from 11 to 26. 102*cfb92d14SAndroid Build Coastguard Worker """ 103*cfb92d14SAndroid Build Coastguard Worker 104*cfb92d14SAndroid Build Coastguard Worker ROLE_LEADER = 1 105*cfb92d14SAndroid Build Coastguard Worker ROLE_ROUTER = 2 106*cfb92d14SAndroid Build Coastguard Worker ROLE_SED = 4 107*cfb92d14SAndroid Build Coastguard Worker ROLE_BORDER = 8 108*cfb92d14SAndroid Build Coastguard Worker ROLE_REED = 16 109*cfb92d14SAndroid Build Coastguard Worker ROLE_ED = 32 110*cfb92d14SAndroid Build Coastguard Worker ROLE_COMMISSIONER = 64 111*cfb92d14SAndroid Build Coastguard Worker ROLE_JOINER = 128 112*cfb92d14SAndroid Build Coastguard Worker ROLE_FED = 512 113*cfb92d14SAndroid Build Coastguard Worker ROLE_MED = 1024 114*cfb92d14SAndroid Build Coastguard Worker 115*cfb92d14SAndroid Build Coastguard Worker role = None 116*cfb92d14SAndroid Build Coastguard Worker """int: role id. 117*cfb92d14SAndroid Build Coastguard Worker 118*cfb92d14SAndroid Build Coastguard Worker 1 119*cfb92d14SAndroid Build Coastguard Worker Leader 120*cfb92d14SAndroid Build Coastguard Worker 2 121*cfb92d14SAndroid Build Coastguard Worker Router 122*cfb92d14SAndroid Build Coastguard Worker 4 123*cfb92d14SAndroid Build Coastguard Worker Sleepy end device 124*cfb92d14SAndroid Build Coastguard Worker 16 125*cfb92d14SAndroid Build Coastguard Worker Router eligible end device 126*cfb92d14SAndroid Build Coastguard Worker 32 127*cfb92d14SAndroid Build Coastguard Worker End device 128*cfb92d14SAndroid Build Coastguard Worker 64 129*cfb92d14SAndroid Build Coastguard Worker Commissioner 130*cfb92d14SAndroid Build Coastguard Worker 128 131*cfb92d14SAndroid Build Coastguard Worker Joiner 132*cfb92d14SAndroid Build Coastguard Worker 512 133*cfb92d14SAndroid Build Coastguard Worker Full end device 134*cfb92d14SAndroid Build Coastguard Worker 1024 135*cfb92d14SAndroid Build Coastguard Worker Minimal end device 136*cfb92d14SAndroid Build Coastguard Worker """ 137*cfb92d14SAndroid Build Coastguard Worker 138*cfb92d14SAndroid Build Coastguard Worker case = None 139*cfb92d14SAndroid Build Coastguard Worker """str: Case id, e.g. '6 5 1'. 140*cfb92d14SAndroid Build Coastguard Worker """ 141*cfb92d14SAndroid Build Coastguard Worker 142*cfb92d14SAndroid Build Coastguard Worker golden_devices_required = 0 143*cfb92d14SAndroid Build Coastguard Worker """int: Golden devices needed to finish the test 144*cfb92d14SAndroid Build Coastguard Worker """ 145*cfb92d14SAndroid Build Coastguard Worker 146*cfb92d14SAndroid Build Coastguard Worker child_timeout = settings.THREAD_CHILD_TIMEOUT 147*cfb92d14SAndroid Build Coastguard Worker """int: Child timeout in seconds 148*cfb92d14SAndroid Build Coastguard Worker """ 149*cfb92d14SAndroid Build Coastguard Worker 150*cfb92d14SAndroid Build Coastguard Worker sed_polling_interval = settings.THREAD_SED_POLLING_INTERVAL 151*cfb92d14SAndroid Build Coastguard Worker """int: SED polling interval in seconds 152*cfb92d14SAndroid Build Coastguard Worker """ 153*cfb92d14SAndroid Build Coastguard Worker 154*cfb92d14SAndroid Build Coastguard Worker auto_dut = settings.AUTO_DUT 155*cfb92d14SAndroid Build Coastguard Worker """bool: whether use harness auto dut feature""" 156*cfb92d14SAndroid Build Coastguard Worker 157*cfb92d14SAndroid Build Coastguard Worker timeout = hasattr(settings, 'TIMEOUT') and settings.TIMEOUT or DEFAULT_TIMEOUT 158*cfb92d14SAndroid Build Coastguard Worker """number: timeout in seconds to stop running this test case""" 159*cfb92d14SAndroid Build Coastguard Worker 160*cfb92d14SAndroid Build Coastguard Worker started = 0 161*cfb92d14SAndroid Build Coastguard Worker """number: test case started timestamp""" 162*cfb92d14SAndroid Build Coastguard Worker 163*cfb92d14SAndroid Build Coastguard Worker case_need_shield = False 164*cfb92d14SAndroid Build Coastguard Worker """bool: whether needs RF-box""" 165*cfb92d14SAndroid Build Coastguard Worker 166*cfb92d14SAndroid Build Coastguard Worker device_order = [] 167*cfb92d14SAndroid Build Coastguard Worker """list: device drag order in TestHarness TestBed page""" 168*cfb92d14SAndroid Build Coastguard Worker 169*cfb92d14SAndroid Build Coastguard Worker def __init__(self, *args, **kwargs): 170*cfb92d14SAndroid Build Coastguard Worker self.dut = None 171*cfb92d14SAndroid Build Coastguard Worker self._browser = None 172*cfb92d14SAndroid Build Coastguard Worker self._hc = None 173*cfb92d14SAndroid Build Coastguard Worker self.result_dir = '%s\\%s' % (settings.OUTPUT_PATH, self.__class__.__name__) 174*cfb92d14SAndroid Build Coastguard Worker self.history = HistoryHelper() 175*cfb92d14SAndroid Build Coastguard Worker self.add_all_devices = False 176*cfb92d14SAndroid Build Coastguard Worker self.new_th = False 177*cfb92d14SAndroid Build Coastguard Worker 178*cfb92d14SAndroid Build Coastguard Worker harness_info = ConfigParser.ConfigParser() 179*cfb92d14SAndroid Build Coastguard Worker harness_info.read('%s\\info.ini' % settings.HARNESS_HOME) 180*cfb92d14SAndroid Build Coastguard Worker if harness_info.has_option('Thread_Harness_Info', 'Version') and harness_info.has_option( 181*cfb92d14SAndroid Build Coastguard Worker 'Thread_Harness_Info', 'Mode'): 182*cfb92d14SAndroid Build Coastguard Worker harness_version = harness_info.get('Thread_Harness_Info', 'Version').rsplit(' ', 1)[1] 183*cfb92d14SAndroid Build Coastguard Worker harness_mode = harness_info.get('Thread_Harness_Info', 'Mode') 184*cfb92d14SAndroid Build Coastguard Worker 185*cfb92d14SAndroid Build Coastguard Worker if harness_mode == 'External' and harness_version > '1.4.0': 186*cfb92d14SAndroid Build Coastguard Worker self.new_th = True 187*cfb92d14SAndroid Build Coastguard Worker 188*cfb92d14SAndroid Build Coastguard Worker if harness_mode == 'Internal' and harness_version > '49.4': 189*cfb92d14SAndroid Build Coastguard Worker self.new_th = True 190*cfb92d14SAndroid Build Coastguard Worker 191*cfb92d14SAndroid Build Coastguard Worker super(HarnessCase, self).__init__(*args, **kwargs) 192*cfb92d14SAndroid Build Coastguard Worker 193*cfb92d14SAndroid Build Coastguard Worker def _init_devices(self): 194*cfb92d14SAndroid Build Coastguard Worker """Reboot all usb devices. 195*cfb92d14SAndroid Build Coastguard Worker 196*cfb92d14SAndroid Build Coastguard Worker Note: 197*cfb92d14SAndroid Build Coastguard Worker If PDU_CONTROLLER_TYPE is not valid, usb devices is not rebooted. 198*cfb92d14SAndroid Build Coastguard Worker """ 199*cfb92d14SAndroid Build Coastguard Worker if not settings.PDU_CONTROLLER_TYPE: 200*cfb92d14SAndroid Build Coastguard Worker if settings.AUTO_DUT: 201*cfb92d14SAndroid Build Coastguard Worker return 202*cfb92d14SAndroid Build Coastguard Worker 203*cfb92d14SAndroid Build Coastguard Worker for device in settings.GOLDEN_DEVICES: 204*cfb92d14SAndroid Build Coastguard Worker port, _ = device 205*cfb92d14SAndroid Build Coastguard Worker try: 206*cfb92d14SAndroid Build Coastguard Worker with OpenThreadController(port) as otc: 207*cfb92d14SAndroid Build Coastguard Worker logger.info('Resetting %s', port) 208*cfb92d14SAndroid Build Coastguard Worker otc.reset() 209*cfb92d14SAndroid Build Coastguard Worker except BaseException: 210*cfb92d14SAndroid Build Coastguard Worker logger.exception('Failed to reset device %s', port) 211*cfb92d14SAndroid Build Coastguard Worker self.history.mark_bad_golden_device(device) 212*cfb92d14SAndroid Build Coastguard Worker 213*cfb92d14SAndroid Build Coastguard Worker return 214*cfb92d14SAndroid Build Coastguard Worker 215*cfb92d14SAndroid Build Coastguard Worker tries = 3 216*cfb92d14SAndroid Build Coastguard Worker pdu_factory = PduControllerFactory() 217*cfb92d14SAndroid Build Coastguard Worker 218*cfb92d14SAndroid Build Coastguard Worker while True: 219*cfb92d14SAndroid Build Coastguard Worker try: 220*cfb92d14SAndroid Build Coastguard Worker pdu = pdu_factory.create_pdu_controller(settings.PDU_CONTROLLER_TYPE) 221*cfb92d14SAndroid Build Coastguard Worker pdu.open(**settings.PDU_CONTROLLER_OPEN_PARAMS) 222*cfb92d14SAndroid Build Coastguard Worker except EOFError: 223*cfb92d14SAndroid Build Coastguard Worker logger.warning('Failed to connect to telnet') 224*cfb92d14SAndroid Build Coastguard Worker tries = tries - 1 225*cfb92d14SAndroid Build Coastguard Worker if tries: 226*cfb92d14SAndroid Build Coastguard Worker time.sleep(10) 227*cfb92d14SAndroid Build Coastguard Worker continue 228*cfb92d14SAndroid Build Coastguard Worker else: 229*cfb92d14SAndroid Build Coastguard Worker logger.error('Fatal error: cannot connect to apc') 230*cfb92d14SAndroid Build Coastguard Worker raise 231*cfb92d14SAndroid Build Coastguard Worker else: 232*cfb92d14SAndroid Build Coastguard Worker pdu.reboot(**settings.PDU_CONTROLLER_REBOOT_PARAMS) 233*cfb92d14SAndroid Build Coastguard Worker pdu.close() 234*cfb92d14SAndroid Build Coastguard Worker break 235*cfb92d14SAndroid Build Coastguard Worker 236*cfb92d14SAndroid Build Coastguard Worker time.sleep(len(settings.GOLDEN_DEVICES)) 237*cfb92d14SAndroid Build Coastguard Worker 238*cfb92d14SAndroid Build Coastguard Worker def _init_harness(self): 239*cfb92d14SAndroid Build Coastguard Worker """Restart harness backend service. 240*cfb92d14SAndroid Build Coastguard Worker 241*cfb92d14SAndroid Build Coastguard Worker Please start the harness controller before running the cases, otherwise, nothing happens 242*cfb92d14SAndroid Build Coastguard Worker """ 243*cfb92d14SAndroid Build Coastguard Worker self._hc = HarnessController(self.result_dir) 244*cfb92d14SAndroid Build Coastguard Worker self._hc.stop() 245*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 246*cfb92d14SAndroid Build Coastguard Worker self._hc.start() 247*cfb92d14SAndroid Build Coastguard Worker time.sleep(2) 248*cfb92d14SAndroid Build Coastguard Worker 249*cfb92d14SAndroid Build Coastguard Worker harness_config = ConfigParser.ConfigParser() 250*cfb92d14SAndroid Build Coastguard Worker harness_config.read('%s\\Config\\Configuration.ini' % settings.HARNESS_HOME) 251*cfb92d14SAndroid Build Coastguard Worker if harness_config.has_option('THREAD_HARNESS_CONFIG', 'BrowserAutoNavigate') and harness_config.getboolean( 252*cfb92d14SAndroid Build Coastguard Worker 'THREAD_HARNESS_CONFIG', 'BrowserAutoNavigate'): 253*cfb92d14SAndroid Build Coastguard Worker logger.error('BrowserAutoNavigate in Configuration.ini should be False') 254*cfb92d14SAndroid Build Coastguard Worker raise FailError('BrowserAutoNavigate in Configuration.ini should be False') 255*cfb92d14SAndroid Build Coastguard Worker if settings.MIXED_DEVICE_TYPE: 256*cfb92d14SAndroid Build Coastguard Worker if harness_config.has_option('THREAD_HARNESS_CONFIG', 257*cfb92d14SAndroid Build Coastguard Worker 'EnableDeviceSelection') and not harness_config.getboolean( 258*cfb92d14SAndroid Build Coastguard Worker 'THREAD_HARNESS_CONFIG', 'EnableDeviceSelection'): 259*cfb92d14SAndroid Build Coastguard Worker logger.error('EnableDeviceSelection in Configuration.ini should be True') 260*cfb92d14SAndroid Build Coastguard Worker raise FailError('EnableDeviceSelection in Configuration.ini should be True') 261*cfb92d14SAndroid Build Coastguard Worker 262*cfb92d14SAndroid Build Coastguard Worker def _destroy_harness(self): 263*cfb92d14SAndroid Build Coastguard Worker """Stop harness backend service 264*cfb92d14SAndroid Build Coastguard Worker 265*cfb92d14SAndroid Build Coastguard Worker Stop harness service. 266*cfb92d14SAndroid Build Coastguard Worker """ 267*cfb92d14SAndroid Build Coastguard Worker self._hc.stop() 268*cfb92d14SAndroid Build Coastguard Worker time.sleep(2) 269*cfb92d14SAndroid Build Coastguard Worker 270*cfb92d14SAndroid Build Coastguard Worker def _init_dut(self): 271*cfb92d14SAndroid Build Coastguard Worker """Initialize the DUT. 272*cfb92d14SAndroid Build Coastguard Worker 273*cfb92d14SAndroid Build Coastguard Worker DUT will be restarted. and openthread will started. 274*cfb92d14SAndroid Build Coastguard Worker """ 275*cfb92d14SAndroid Build Coastguard Worker if self.auto_dut: 276*cfb92d14SAndroid Build Coastguard Worker self.dut = None 277*cfb92d14SAndroid Build Coastguard Worker return 278*cfb92d14SAndroid Build Coastguard Worker 279*cfb92d14SAndroid Build Coastguard Worker dut_port = settings.DUT_DEVICE[0] 280*cfb92d14SAndroid Build Coastguard Worker dut = OpenThreadController(dut_port) 281*cfb92d14SAndroid Build Coastguard Worker self.dut = dut 282*cfb92d14SAndroid Build Coastguard Worker 283*cfb92d14SAndroid Build Coastguard Worker def _destroy_dut(self): 284*cfb92d14SAndroid Build Coastguard Worker self.dut = None 285*cfb92d14SAndroid Build Coastguard Worker 286*cfb92d14SAndroid Build Coastguard Worker def _init_browser(self): 287*cfb92d14SAndroid Build Coastguard Worker """Open harness web page. 288*cfb92d14SAndroid Build Coastguard Worker 289*cfb92d14SAndroid Build Coastguard Worker Open a quiet chrome which: 290*cfb92d14SAndroid Build Coastguard Worker 1. disables extensions, 291*cfb92d14SAndroid Build Coastguard Worker 2. ignore certificate errors and 292*cfb92d14SAndroid Build Coastguard Worker 3. always allow notifications. 293*cfb92d14SAndroid Build Coastguard Worker """ 294*cfb92d14SAndroid Build Coastguard Worker try: 295*cfb92d14SAndroid Build Coastguard Worker chrome_options = webdriver.ChromeOptions() 296*cfb92d14SAndroid Build Coastguard Worker chrome_options.add_argument('--disable-extensions') 297*cfb92d14SAndroid Build Coastguard Worker chrome_options.add_argument('--disable-infobars') 298*cfb92d14SAndroid Build Coastguard Worker chrome_options.add_argument('--ignore-certificate-errors') 299*cfb92d14SAndroid Build Coastguard Worker chrome_options.add_experimental_option('prefs', 300*cfb92d14SAndroid Build Coastguard Worker {'profile.managed_default_content_settings.notifications': 1}) 301*cfb92d14SAndroid Build Coastguard Worker 302*cfb92d14SAndroid Build Coastguard Worker browser = webdriver.Chrome(chrome_options=chrome_options) 303*cfb92d14SAndroid Build Coastguard Worker browser.set_page_load_timeout(20) 304*cfb92d14SAndroid Build Coastguard Worker browser.implicitly_wait(1) 305*cfb92d14SAndroid Build Coastguard Worker browser.get(settings.HARNESS_URL) 306*cfb92d14SAndroid Build Coastguard Worker browser.maximize_window() 307*cfb92d14SAndroid Build Coastguard Worker self._browser = browser 308*cfb92d14SAndroid Build Coastguard Worker if not wait_until(lambda: 'Thread' in browser.title, 30): 309*cfb92d14SAndroid Build Coastguard Worker self.assertIn('Thread', browser.title) 310*cfb92d14SAndroid Build Coastguard Worker return True 311*cfb92d14SAndroid Build Coastguard Worker except Exception as e: 312*cfb92d14SAndroid Build Coastguard Worker logger.info('Init chrome error: {0}'.format(type(e).__name__)) 313*cfb92d14SAndroid Build Coastguard Worker return False 314*cfb92d14SAndroid Build Coastguard Worker 315*cfb92d14SAndroid Build Coastguard Worker def _destroy_browser(self): 316*cfb92d14SAndroid Build Coastguard Worker """Close the browser. 317*cfb92d14SAndroid Build Coastguard Worker """ 318*cfb92d14SAndroid Build Coastguard Worker if self._browser: 319*cfb92d14SAndroid Build Coastguard Worker self._browser.close() 320*cfb92d14SAndroid Build Coastguard Worker self._browser = None 321*cfb92d14SAndroid Build Coastguard Worker 322*cfb92d14SAndroid Build Coastguard Worker def _init_rf_shield(self): 323*cfb92d14SAndroid Build Coastguard Worker if getattr(settings, 'SHIELD_CONTROLLER_TYPE', None) and getattr(settings, 'SHIELD_CONTROLLER_PARAMS', None): 324*cfb92d14SAndroid Build Coastguard Worker self.rf_shield = get_rf_shield_controller(shield_type=settings.SHIELD_CONTROLLER_TYPE, 325*cfb92d14SAndroid Build Coastguard Worker params=settings.SHIELD_CONTROLLER_PARAMS) 326*cfb92d14SAndroid Build Coastguard Worker else: 327*cfb92d14SAndroid Build Coastguard Worker self.rf_shield = None 328*cfb92d14SAndroid Build Coastguard Worker 329*cfb92d14SAndroid Build Coastguard Worker def _destroy_rf_shield(self): 330*cfb92d14SAndroid Build Coastguard Worker self.rf_shield = None 331*cfb92d14SAndroid Build Coastguard Worker 332*cfb92d14SAndroid Build Coastguard Worker def setUp(self): 333*cfb92d14SAndroid Build Coastguard Worker """Prepare to run test case. 334*cfb92d14SAndroid Build Coastguard Worker 335*cfb92d14SAndroid Build Coastguard Worker Start harness service, init golden devices, reset DUT and open browser. 336*cfb92d14SAndroid Build Coastguard Worker """ 337*cfb92d14SAndroid Build Coastguard Worker if self.__class__ is HarnessCase: 338*cfb92d14SAndroid Build Coastguard Worker return 339*cfb92d14SAndroid Build Coastguard Worker 340*cfb92d14SAndroid Build Coastguard Worker logger.info('Setting up') 341*cfb92d14SAndroid Build Coastguard Worker # clear files 342*cfb92d14SAndroid Build Coastguard Worker 343*cfb92d14SAndroid Build Coastguard Worker logger.info('Deleting all .pcapng') 344*cfb92d14SAndroid Build Coastguard Worker os.system('del /q "%s\\Captures\\*.pcapng"' % settings.HARNESS_HOME) 345*cfb92d14SAndroid Build Coastguard Worker logger.info('Empty files in Logs') 346*cfb92d14SAndroid Build Coastguard Worker os.system('del /q "%s\\Logs\\*.*"' % settings.HARNESS_HOME) 347*cfb92d14SAndroid Build Coastguard Worker 348*cfb92d14SAndroid Build Coastguard Worker # using temp files to fix excel downloading fail 349*cfb92d14SAndroid Build Coastguard Worker if self.new_th: 350*cfb92d14SAndroid Build Coastguard Worker logger.info('Empty files in Reports') 351*cfb92d14SAndroid Build Coastguard Worker os.system('del /q "%s\\Reports\\*.*"' % settings.HARNESS_HOME) 352*cfb92d14SAndroid Build Coastguard Worker else: 353*cfb92d14SAndroid Build Coastguard Worker logger.info('Empty files in temps') 354*cfb92d14SAndroid Build Coastguard Worker os.system('del /q "%s\\Thread_Harness\\temp\\*.*"' % settings.HARNESS_HOME) 355*cfb92d14SAndroid Build Coastguard Worker 356*cfb92d14SAndroid Build Coastguard Worker # create directory 357*cfb92d14SAndroid Build Coastguard Worker os.system('mkdir %s' % self.result_dir) 358*cfb92d14SAndroid Build Coastguard Worker self._init_harness() 359*cfb92d14SAndroid Build Coastguard Worker self._init_devices() 360*cfb92d14SAndroid Build Coastguard Worker self._init_dut() 361*cfb92d14SAndroid Build Coastguard Worker self._init_rf_shield() 362*cfb92d14SAndroid Build Coastguard Worker 363*cfb92d14SAndroid Build Coastguard Worker def tearDown(self): 364*cfb92d14SAndroid Build Coastguard Worker """Clean up after each case. 365*cfb92d14SAndroid Build Coastguard Worker 366*cfb92d14SAndroid Build Coastguard Worker Stop harness service, close browser and close DUT. 367*cfb92d14SAndroid Build Coastguard Worker """ 368*cfb92d14SAndroid Build Coastguard Worker if self.__class__ is HarnessCase: 369*cfb92d14SAndroid Build Coastguard Worker return 370*cfb92d14SAndroid Build Coastguard Worker 371*cfb92d14SAndroid Build Coastguard Worker logger.info('Tearing down') 372*cfb92d14SAndroid Build Coastguard Worker self._destroy_harness() 373*cfb92d14SAndroid Build Coastguard Worker self._destroy_browser() 374*cfb92d14SAndroid Build Coastguard Worker self._destroy_dut() 375*cfb92d14SAndroid Build Coastguard Worker self._destroy_rf_shield() 376*cfb92d14SAndroid Build Coastguard Worker 377*cfb92d14SAndroid Build Coastguard Worker def _setup_page(self): 378*cfb92d14SAndroid Build Coastguard Worker """Do sniffer settings and general settings 379*cfb92d14SAndroid Build Coastguard Worker """ 380*cfb92d14SAndroid Build Coastguard Worker if not self.started: 381*cfb92d14SAndroid Build Coastguard Worker self.started = time.time() 382*cfb92d14SAndroid Build Coastguard Worker 383*cfb92d14SAndroid Build Coastguard Worker # Detect Sniffer 384*cfb92d14SAndroid Build Coastguard Worker try: 385*cfb92d14SAndroid Build Coastguard Worker dialog = self._browser.find_element_by_id('capture-Setup-modal') 386*cfb92d14SAndroid Build Coastguard Worker except BaseException: 387*cfb92d14SAndroid Build Coastguard Worker logger.exception('Failed to get dialog.') 388*cfb92d14SAndroid Build Coastguard Worker else: 389*cfb92d14SAndroid Build Coastguard Worker if dialog and dialog.get_attribute('aria-hidden') == 'false': 390*cfb92d14SAndroid Build Coastguard Worker times = 100 391*cfb92d14SAndroid Build Coastguard Worker while times: 392*cfb92d14SAndroid Build Coastguard Worker status = dialog.find_element_by_class_name('status-notify').text 393*cfb92d14SAndroid Build Coastguard Worker if 'Searching' in status: 394*cfb92d14SAndroid Build Coastguard Worker logger.info('Still detecting..') 395*cfb92d14SAndroid Build Coastguard Worker elif 'Not' in status: 396*cfb92d14SAndroid Build Coastguard Worker logger.warning('Sniffer device not verified!') 397*cfb92d14SAndroid Build Coastguard Worker button = dialog.find_element_by_id('snifferAutoDetectBtn') 398*cfb92d14SAndroid Build Coastguard Worker button.click() 399*cfb92d14SAndroid Build Coastguard Worker elif 'Verified' in status: 400*cfb92d14SAndroid Build Coastguard Worker logger.info('Verified!') 401*cfb92d14SAndroid Build Coastguard Worker button = dialog.find_element_by_id('saveCaptureSettings') 402*cfb92d14SAndroid Build Coastguard Worker button.click() 403*cfb92d14SAndroid Build Coastguard Worker break 404*cfb92d14SAndroid Build Coastguard Worker else: 405*cfb92d14SAndroid Build Coastguard Worker logger.warning('Unexpected sniffer verification status') 406*cfb92d14SAndroid Build Coastguard Worker 407*cfb92d14SAndroid Build Coastguard Worker times = times - 1 408*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 409*cfb92d14SAndroid Build Coastguard Worker 410*cfb92d14SAndroid Build Coastguard Worker if not times: 411*cfb92d14SAndroid Build Coastguard Worker raise Exception('Unable to detect sniffer device') 412*cfb92d14SAndroid Build Coastguard Worker 413*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 414*cfb92d14SAndroid Build Coastguard Worker 415*cfb92d14SAndroid Build Coastguard Worker try: 416*cfb92d14SAndroid Build Coastguard Worker skip_button = self._browser.find_element_by_id('SkipPrepareDevice') 417*cfb92d14SAndroid Build Coastguard Worker if skip_button.is_enabled(): 418*cfb92d14SAndroid Build Coastguard Worker skip_button.click() 419*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 420*cfb92d14SAndroid Build Coastguard Worker except BaseException: 421*cfb92d14SAndroid Build Coastguard Worker logger.info('Still detecting sniffers') 422*cfb92d14SAndroid Build Coastguard Worker 423*cfb92d14SAndroid Build Coastguard Worker try: 424*cfb92d14SAndroid Build Coastguard Worker next_button = self._browser.find_element_by_id('nextButton') 425*cfb92d14SAndroid Build Coastguard Worker except BaseException: 426*cfb92d14SAndroid Build Coastguard Worker logger.exception('Failed to finish setup') 427*cfb92d14SAndroid Build Coastguard Worker return 428*cfb92d14SAndroid Build Coastguard Worker 429*cfb92d14SAndroid Build Coastguard Worker if not next_button.is_enabled(): 430*cfb92d14SAndroid Build Coastguard Worker logger.info('Harness is still not ready') 431*cfb92d14SAndroid Build Coastguard Worker return 432*cfb92d14SAndroid Build Coastguard Worker 433*cfb92d14SAndroid Build Coastguard Worker # General Setup 434*cfb92d14SAndroid Build Coastguard Worker try: 435*cfb92d14SAndroid Build Coastguard Worker if self.child_timeout or self.sed_polling_interval: 436*cfb92d14SAndroid Build Coastguard Worker logger.info('finding general Setup button') 437*cfb92d14SAndroid Build Coastguard Worker button = self._browser.find_element_by_id('general-Setup') 438*cfb92d14SAndroid Build Coastguard Worker button.click() 439*cfb92d14SAndroid Build Coastguard Worker time.sleep(2) 440*cfb92d14SAndroid Build Coastguard Worker 441*cfb92d14SAndroid Build Coastguard Worker dialog = self._browser.find_element_by_id('general-Setup-modal') 442*cfb92d14SAndroid Build Coastguard Worker if dialog.get_attribute('aria-hidden') != 'false': 443*cfb92d14SAndroid Build Coastguard Worker raise Exception('Missing General Setup dialog') 444*cfb92d14SAndroid Build Coastguard Worker 445*cfb92d14SAndroid Build Coastguard Worker field = dialog.find_element_by_id('inp_general_child_update_wait_time') 446*cfb92d14SAndroid Build Coastguard Worker field.clear() 447*cfb92d14SAndroid Build Coastguard Worker if self.child_timeout: 448*cfb92d14SAndroid Build Coastguard Worker field.send_keys(str(self.child_timeout)) 449*cfb92d14SAndroid Build Coastguard Worker 450*cfb92d14SAndroid Build Coastguard Worker field = dialog.find_element_by_id('inp_general_sed_polling_rate') 451*cfb92d14SAndroid Build Coastguard Worker field.clear() 452*cfb92d14SAndroid Build Coastguard Worker if self.sed_polling_interval: 453*cfb92d14SAndroid Build Coastguard Worker field.send_keys(str(self.sed_polling_interval)) 454*cfb92d14SAndroid Build Coastguard Worker 455*cfb92d14SAndroid Build Coastguard Worker button = dialog.find_element_by_id('saveGeneralSettings') 456*cfb92d14SAndroid Build Coastguard Worker button.click() 457*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 458*cfb92d14SAndroid Build Coastguard Worker 459*cfb92d14SAndroid Build Coastguard Worker except BaseException: 460*cfb92d14SAndroid Build Coastguard Worker logger.info('general setup exception') 461*cfb92d14SAndroid Build Coastguard Worker logger.exception('Failed to do general setup') 462*cfb92d14SAndroid Build Coastguard Worker return 463*cfb92d14SAndroid Build Coastguard Worker 464*cfb92d14SAndroid Build Coastguard Worker # Finish this page 465*cfb92d14SAndroid Build Coastguard Worker next_button.click() 466*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 467*cfb92d14SAndroid Build Coastguard Worker 468*cfb92d14SAndroid Build Coastguard Worker def _connect_devices(self): 469*cfb92d14SAndroid Build Coastguard Worker connect_all = self._browser.find_element_by_link_text('Connect All') 470*cfb92d14SAndroid Build Coastguard Worker connect_all.click() 471*cfb92d14SAndroid Build Coastguard Worker 472*cfb92d14SAndroid Build Coastguard Worker def _add_device(self, port, device_type_id): 473*cfb92d14SAndroid Build Coastguard Worker browser = self._browser 474*cfb92d14SAndroid Build Coastguard Worker test_bed = browser.find_element_by_id('test-bed') 475*cfb92d14SAndroid Build Coastguard Worker device = browser.find_element_by_id(device_type_id) 476*cfb92d14SAndroid Build Coastguard Worker # drag 477*cfb92d14SAndroid Build Coastguard Worker action_chains = ActionChains(browser) 478*cfb92d14SAndroid Build Coastguard Worker action_chains.click_and_hold(device) 479*cfb92d14SAndroid Build Coastguard Worker action_chains.move_to_element(test_bed).perform() 480*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 481*cfb92d14SAndroid Build Coastguard Worker 482*cfb92d14SAndroid Build Coastguard Worker # drop 483*cfb92d14SAndroid Build Coastguard Worker drop_hw = browser.find_element_by_class_name('drop-hw') 484*cfb92d14SAndroid Build Coastguard Worker action_chains = ActionChains(browser) 485*cfb92d14SAndroid Build Coastguard Worker action_chains.move_to_element(drop_hw) 486*cfb92d14SAndroid Build Coastguard Worker action_chains.release(drop_hw).perform() 487*cfb92d14SAndroid Build Coastguard Worker 488*cfb92d14SAndroid Build Coastguard Worker time.sleep(0.5) 489*cfb92d14SAndroid Build Coastguard Worker selected_hw = browser.find_element_by_class_name('selected-hw') 490*cfb92d14SAndroid Build Coastguard Worker form_inputs = selected_hw.find_elements_by_tag_name('input') 491*cfb92d14SAndroid Build Coastguard Worker form_port = form_inputs[0] 492*cfb92d14SAndroid Build Coastguard Worker form_port.clear() 493*cfb92d14SAndroid Build Coastguard Worker form_port.send_keys(port) 494*cfb92d14SAndroid Build Coastguard Worker 495*cfb92d14SAndroid Build Coastguard Worker def _test_bed(self): 496*cfb92d14SAndroid Build Coastguard Worker """Set up the test bed. 497*cfb92d14SAndroid Build Coastguard Worker 498*cfb92d14SAndroid Build Coastguard Worker Connect number of golden devices required by each case. 499*cfb92d14SAndroid Build Coastguard Worker """ 500*cfb92d14SAndroid Build Coastguard Worker browser = self._browser 501*cfb92d14SAndroid Build Coastguard Worker test_bed = browser.find_element_by_id('test-bed') 502*cfb92d14SAndroid Build Coastguard Worker time.sleep(3) 503*cfb92d14SAndroid Build Coastguard Worker selected_hw_set = test_bed.find_elements_by_class_name('selected-hw') 504*cfb92d14SAndroid Build Coastguard Worker selected_hw_num = len(selected_hw_set) 505*cfb92d14SAndroid Build Coastguard Worker 506*cfb92d14SAndroid Build Coastguard Worker while selected_hw_num: 507*cfb92d14SAndroid Build Coastguard Worker remove_button = selected_hw_set[selected_hw_num - 1].find_element_by_class_name('removeSelectedDevice') 508*cfb92d14SAndroid Build Coastguard Worker remove_button.click() 509*cfb92d14SAndroid Build Coastguard Worker selected_hw_num = selected_hw_num - 1 510*cfb92d14SAndroid Build Coastguard Worker 511*cfb92d14SAndroid Build Coastguard Worker devices = [ 512*cfb92d14SAndroid Build Coastguard Worker device for device in settings.GOLDEN_DEVICES if not self.history.is_bad_golden_device(device[0]) and 513*cfb92d14SAndroid Build Coastguard Worker not (settings.DUT_DEVICE and device[0] == settings.DUT_DEVICE[0]) 514*cfb92d14SAndroid Build Coastguard Worker ] 515*cfb92d14SAndroid Build Coastguard Worker logger.info('Available golden devices: %s', json.dumps(devices, indent=2)) 516*cfb92d14SAndroid Build Coastguard Worker 517*cfb92d14SAndroid Build Coastguard Worker shield_devices = [ 518*cfb92d14SAndroid Build Coastguard Worker shield_device for shield_device in settings.SHIELD_GOLDEN_DEVICES 519*cfb92d14SAndroid Build Coastguard Worker if not self.history.is_bad_golden_device(shield_device[0]) and 520*cfb92d14SAndroid Build Coastguard Worker not (settings.DUT2_DEVICE and shield_device[0] == settings.DUT2_DEVICE[0]) 521*cfb92d14SAndroid Build Coastguard Worker ] 522*cfb92d14SAndroid Build Coastguard Worker logger.info('Available shield golden devices: %s', json.dumps(shield_devices, indent=2)) 523*cfb92d14SAndroid Build Coastguard Worker golden_devices_required = self.golden_devices_required 524*cfb92d14SAndroid Build Coastguard Worker 525*cfb92d14SAndroid Build Coastguard Worker dut_device = () 526*cfb92d14SAndroid Build Coastguard Worker if settings.DUT_DEVICE: 527*cfb92d14SAndroid Build Coastguard Worker dut_device = settings.DUT_DEVICE 528*cfb92d14SAndroid Build Coastguard Worker """check if test case needs to use RF-shield box and its device order in Testbed page 529*cfb92d14SAndroid Build Coastguard Worker Two parameters case_need_shield & device_order should be set in the case script 530*cfb92d14SAndroid Build Coastguard Worker according to the requires: https://openthread.io/certification/test-cases#rf_shielding 531*cfb92d14SAndroid Build Coastguard Worker Example: 532*cfb92d14SAndroid Build Coastguard Worker In case script leader_9_2_9.py: 533*cfb92d14SAndroid Build Coastguard Worker case_need_shield = True 534*cfb92d14SAndroid Build Coastguard Worker device_order = [('Router_2', False), ('Commissioner', True), ('Router_1', False), ('DUT', True)] 535*cfb92d14SAndroid Build Coastguard Worker On the TestBed page of the Test Harness, the device sort order for Leader_9_2_9 536*cfb92d14SAndroid Build Coastguard Worker should be like: 537*cfb92d14SAndroid Build Coastguard Worker Router_2 538*cfb92d14SAndroid Build Coastguard Worker Commissioner 539*cfb92d14SAndroid Build Coastguard Worker Router_1 540*cfb92d14SAndroid Build Coastguard Worker DUT 541*cfb92d14SAndroid Build Coastguard Worker The ('Commissioner', True) and ('DUT', True) indicate Commissioner device and DUT2 device should 542*cfb92d14SAndroid Build Coastguard Worker be in the RF-box and choose from SHIELD_GOLDEN_DEVICES and DUT2_DEVICE. Otherwise ('DUT', False) means 543*cfb92d14SAndroid Build Coastguard Worker DUT device is not in RF-box and use DUT_DEVICE. The other roles devices with False should be selected 544*cfb92d14SAndroid Build Coastguard Worker from GOLDEN_DEVICES. 545*cfb92d14SAndroid Build Coastguard Worker 546*cfb92d14SAndroid Build Coastguard Worker In case script med_6_3_2.py: 547*cfb92d14SAndroid Build Coastguard Worker case_need_shield = True 548*cfb92d14SAndroid Build Coastguard Worker device_order = [] # or not defined 549*cfb92d14SAndroid Build Coastguard Worker means no device drag order. DUT2_DEVICE should be applied as DUT and the other golden devices 550*cfb92d14SAndroid Build Coastguard Worker are from GOLDEN_DEVICES. 551*cfb92d14SAndroid Build Coastguard Worker """ 552*cfb92d14SAndroid Build Coastguard Worker if self.case_need_shield: 553*cfb92d14SAndroid Build Coastguard Worker if not settings.DUT2_DEVICE: 554*cfb92d14SAndroid Build Coastguard Worker logger.info('Must set DUT2_DEVICE') 555*cfb92d14SAndroid Build Coastguard Worker raise FailError('DUT2_DEVICE must be set in settings.py') 556*cfb92d14SAndroid Build Coastguard Worker if isinstance(self.device_order, list) and self.device_order: 557*cfb92d14SAndroid Build Coastguard Worker logger.info('case %s devices ordered by %s ', self.case, self.device_order) 558*cfb92d14SAndroid Build Coastguard Worker else: 559*cfb92d14SAndroid Build Coastguard Worker logger.info('case %s uses %s as DUT', self.case, settings.DUT2_DEVICE) 560*cfb92d14SAndroid Build Coastguard Worker 561*cfb92d14SAndroid Build Coastguard Worker # for test bed with multi-vendor devices 562*cfb92d14SAndroid Build Coastguard Worker if settings.MIXED_DEVICE_TYPE: 563*cfb92d14SAndroid Build Coastguard Worker topo_file = settings.HARNESS_HOME + "\\Thread_Harness\\TestScripts\\TopologyConfig.txt" 564*cfb92d14SAndroid Build Coastguard Worker try: 565*cfb92d14SAndroid Build Coastguard Worker f_topo = open(topo_file, 'r') 566*cfb92d14SAndroid Build Coastguard Worker except IOError: 567*cfb92d14SAndroid Build Coastguard Worker logger.info('%s can NOT be found', topo_file) 568*cfb92d14SAndroid Build Coastguard Worker raise GoldenDeviceNotEnoughError() 569*cfb92d14SAndroid Build Coastguard Worker topo_mixed_devices = [] 570*cfb92d14SAndroid Build Coastguard Worker try: 571*cfb92d14SAndroid Build Coastguard Worker while True: 572*cfb92d14SAndroid Build Coastguard Worker topo_line = f_topo.readline().strip() 573*cfb92d14SAndroid Build Coastguard Worker if re.match(r'#.*', topo_line): 574*cfb92d14SAndroid Build Coastguard Worker continue 575*cfb92d14SAndroid Build Coastguard Worker match_line = re.match(r'(.*)-(.*)', topo_line, re.M | re.I) 576*cfb92d14SAndroid Build Coastguard Worker if not match_line: 577*cfb92d14SAndroid Build Coastguard Worker continue 578*cfb92d14SAndroid Build Coastguard Worker case_id = match_line.group(1) 579*cfb92d14SAndroid Build Coastguard Worker 580*cfb92d14SAndroid Build Coastguard Worker if re.sub(r'\.', ' ', case_id) == self.case: 581*cfb92d14SAndroid Build Coastguard Worker logger.info('Get line by case %s: %s', case_id, topo_line) 582*cfb92d14SAndroid Build Coastguard Worker topo_device_list = re.split(',', match_line.group(2)) 583*cfb92d14SAndroid Build Coastguard Worker for i in range(len(topo_device_list)): 584*cfb92d14SAndroid Build Coastguard Worker topo_device = re.split(':', topo_device_list[i]) 585*cfb92d14SAndroid Build Coastguard Worker topo_mixed_devices.append(tuple(topo_device)) 586*cfb92d14SAndroid Build Coastguard Worker break 587*cfb92d14SAndroid Build Coastguard Worker else: 588*cfb92d14SAndroid Build Coastguard Worker continue 589*cfb92d14SAndroid Build Coastguard Worker except Exception as e: 590*cfb92d14SAndroid Build Coastguard Worker logger.info('Get devices from topology config file error: %s', e) 591*cfb92d14SAndroid Build Coastguard Worker raise GoldenDeviceNotEnoughError() 592*cfb92d14SAndroid Build Coastguard Worker logger.info('Golden devices in topology config file for case %s: %s', case_id, topo_mixed_devices) 593*cfb92d14SAndroid Build Coastguard Worker f_topo.close() 594*cfb92d14SAndroid Build Coastguard Worker golden_device_candidates = [] 595*cfb92d14SAndroid Build Coastguard Worker missing_golden_devices = topo_mixed_devices[:] 596*cfb92d14SAndroid Build Coastguard Worker 597*cfb92d14SAndroid Build Coastguard Worker # mapping topology config devices with golden devices by device order 598*cfb92d14SAndroid Build Coastguard Worker if self.case_need_shield and self.device_order: 599*cfb92d14SAndroid Build Coastguard Worker matched_dut = False 600*cfb92d14SAndroid Build Coastguard Worker for device_order_item in self.device_order: 601*cfb92d14SAndroid Build Coastguard Worker matched = False 602*cfb92d14SAndroid Build Coastguard Worker for mixed_device_item in topo_mixed_devices: 603*cfb92d14SAndroid Build Coastguard Worker # mapping device in device_order which needs to be shielded 604*cfb92d14SAndroid Build Coastguard Worker if device_order_item[1]: 605*cfb92d14SAndroid Build Coastguard Worker if 'DUT' in device_order_item[0]: 606*cfb92d14SAndroid Build Coastguard Worker golden_device_candidates.append(settings.DUT2_DEVICE) 607*cfb92d14SAndroid Build Coastguard Worker dut_device = settings.DUT2_DEVICE 608*cfb92d14SAndroid Build Coastguard Worker matched_dut = True 609*cfb92d14SAndroid Build Coastguard Worker matched = True 610*cfb92d14SAndroid Build Coastguard Worker break 611*cfb92d14SAndroid Build Coastguard Worker for device_item in shield_devices: 612*cfb92d14SAndroid Build Coastguard Worker if (device_order_item[0] == mixed_device_item[0] and 613*cfb92d14SAndroid Build Coastguard Worker mixed_device_item[1] == device_item[1]): 614*cfb92d14SAndroid Build Coastguard Worker golden_device_candidates.append(device_item) 615*cfb92d14SAndroid Build Coastguard Worker shield_devices.remove(device_item) 616*cfb92d14SAndroid Build Coastguard Worker matched = True 617*cfb92d14SAndroid Build Coastguard Worker break 618*cfb92d14SAndroid Build Coastguard Worker # mapping device in device_order which does not need to be shielded 619*cfb92d14SAndroid Build Coastguard Worker else: 620*cfb92d14SAndroid Build Coastguard Worker if 'DUT' in device_order_item[0]: 621*cfb92d14SAndroid Build Coastguard Worker golden_device_candidates.append(settings.DUT_DEVICE) 622*cfb92d14SAndroid Build Coastguard Worker matched_dut = True 623*cfb92d14SAndroid Build Coastguard Worker matched = True 624*cfb92d14SAndroid Build Coastguard Worker break 625*cfb92d14SAndroid Build Coastguard Worker for device_item in devices: 626*cfb92d14SAndroid Build Coastguard Worker if (device_order_item[0] == mixed_device_item[0] and 627*cfb92d14SAndroid Build Coastguard Worker mixed_device_item[1] == device_item[1]): 628*cfb92d14SAndroid Build Coastguard Worker golden_device_candidates.append(device_item) 629*cfb92d14SAndroid Build Coastguard Worker devices.remove(device_item) 630*cfb92d14SAndroid Build Coastguard Worker matched = True 631*cfb92d14SAndroid Build Coastguard Worker break 632*cfb92d14SAndroid Build Coastguard Worker if not matched: 633*cfb92d14SAndroid Build Coastguard Worker logger.info('Golden device not enough in : no %s', device_order_item) 634*cfb92d14SAndroid Build Coastguard Worker raise GoldenDeviceNotEnoughError() 635*cfb92d14SAndroid Build Coastguard Worker if not matched_dut: 636*cfb92d14SAndroid Build Coastguard Worker raise FailError('Failed to find DUT in device_order') 637*cfb92d14SAndroid Build Coastguard Worker devices = golden_device_candidates 638*cfb92d14SAndroid Build Coastguard Worker self.add_all_devices = True 639*cfb92d14SAndroid Build Coastguard Worker else: 640*cfb92d14SAndroid Build Coastguard Worker for mixed_device_item in topo_mixed_devices: 641*cfb92d14SAndroid Build Coastguard Worker for device_item in devices: 642*cfb92d14SAndroid Build Coastguard Worker if mixed_device_item[1] == device_item[1]: 643*cfb92d14SAndroid Build Coastguard Worker golden_device_candidates.append(device_item) 644*cfb92d14SAndroid Build Coastguard Worker devices.remove(device_item) 645*cfb92d14SAndroid Build Coastguard Worker missing_golden_devices.remove(mixed_device_item) 646*cfb92d14SAndroid Build Coastguard Worker break 647*cfb92d14SAndroid Build Coastguard Worker logger.info('Golden devices in topology config file mapped in settings : %s', golden_device_candidates) 648*cfb92d14SAndroid Build Coastguard Worker if len(topo_mixed_devices) != len(golden_device_candidates): 649*cfb92d14SAndroid Build Coastguard Worker device_dict = dict() 650*cfb92d14SAndroid Build Coastguard Worker for missing_device in missing_golden_devices: 651*cfb92d14SAndroid Build Coastguard Worker if missing_device[1] in device_dict: 652*cfb92d14SAndroid Build Coastguard Worker device_dict[missing_device[1]] += 1 653*cfb92d14SAndroid Build Coastguard Worker else: 654*cfb92d14SAndroid Build Coastguard Worker device_dict[missing_device[1]] = 1 655*cfb92d14SAndroid Build Coastguard Worker logger.info('Missing Devices: %s', device_dict) 656*cfb92d14SAndroid Build Coastguard Worker raise GoldenDeviceNotEnoughError() 657*cfb92d14SAndroid Build Coastguard Worker else: 658*cfb92d14SAndroid Build Coastguard Worker devices = golden_device_candidates 659*cfb92d14SAndroid Build Coastguard Worker golden_devices_required = len(devices) 660*cfb92d14SAndroid Build Coastguard Worker logger.info('All case-needed golden devices: %s', json.dumps(devices, indent=2)) 661*cfb92d14SAndroid Build Coastguard Worker # for test bed with single vendor devices 662*cfb92d14SAndroid Build Coastguard Worker else: 663*cfb92d14SAndroid Build Coastguard Worker golden_device_candidates = [] 664*cfb92d14SAndroid Build Coastguard Worker if self.case_need_shield and self.device_order: 665*cfb92d14SAndroid Build Coastguard Worker matched_dut = False 666*cfb92d14SAndroid Build Coastguard Worker for device_order_item in self.device_order: 667*cfb92d14SAndroid Build Coastguard Worker matched = False 668*cfb92d14SAndroid Build Coastguard Worker # choose device which needs to be shielded 669*cfb92d14SAndroid Build Coastguard Worker if device_order_item[1]: 670*cfb92d14SAndroid Build Coastguard Worker if 'DUT' in device_order_item[0]: 671*cfb92d14SAndroid Build Coastguard Worker golden_device_candidates.append(settings.DUT2_DEVICE) 672*cfb92d14SAndroid Build Coastguard Worker dut_device = settings.DUT2_DEVICE 673*cfb92d14SAndroid Build Coastguard Worker matched_dut = True 674*cfb92d14SAndroid Build Coastguard Worker matched = True 675*cfb92d14SAndroid Build Coastguard Worker else: 676*cfb92d14SAndroid Build Coastguard Worker for device_item in shield_devices: 677*cfb92d14SAndroid Build Coastguard Worker golden_device_candidates.append(device_item) 678*cfb92d14SAndroid Build Coastguard Worker shield_devices.remove(device_item) 679*cfb92d14SAndroid Build Coastguard Worker matched = True 680*cfb92d14SAndroid Build Coastguard Worker break 681*cfb92d14SAndroid Build Coastguard Worker # choose device which does not need to be shielded 682*cfb92d14SAndroid Build Coastguard Worker else: 683*cfb92d14SAndroid Build Coastguard Worker if 'DUT' in device_order_item[0]: 684*cfb92d14SAndroid Build Coastguard Worker golden_device_candidates.append(settings.DUT_DEVICE) 685*cfb92d14SAndroid Build Coastguard Worker matched_dut = True 686*cfb92d14SAndroid Build Coastguard Worker matched = True 687*cfb92d14SAndroid Build Coastguard Worker else: 688*cfb92d14SAndroid Build Coastguard Worker for device_item in devices: 689*cfb92d14SAndroid Build Coastguard Worker golden_device_candidates.append(device_item) 690*cfb92d14SAndroid Build Coastguard Worker devices.remove(device_item) 691*cfb92d14SAndroid Build Coastguard Worker matched = True 692*cfb92d14SAndroid Build Coastguard Worker break 693*cfb92d14SAndroid Build Coastguard Worker if not matched: 694*cfb92d14SAndroid Build Coastguard Worker logger.info('Golden device not enough in : no %s', device_order_item) 695*cfb92d14SAndroid Build Coastguard Worker raise GoldenDeviceNotEnoughError() 696*cfb92d14SAndroid Build Coastguard Worker if not matched_dut: 697*cfb92d14SAndroid Build Coastguard Worker raise FailError('Failed to find DUT in device_order') 698*cfb92d14SAndroid Build Coastguard Worker devices = golden_device_candidates 699*cfb92d14SAndroid Build Coastguard Worker self.add_all_devices = True 700*cfb92d14SAndroid Build Coastguard Worker 701*cfb92d14SAndroid Build Coastguard Worker if self.auto_dut and not settings.DUT_DEVICE: 702*cfb92d14SAndroid Build Coastguard Worker if settings.MIXED_DEVICE_TYPE: 703*cfb92d14SAndroid Build Coastguard Worker logger.info('Must set DUT_DEVICE') 704*cfb92d14SAndroid Build Coastguard Worker raise FailError('DUT_DEVICE must be set for mixed testbed') 705*cfb92d14SAndroid Build Coastguard Worker golden_devices_required += 1 706*cfb92d14SAndroid Build Coastguard Worker 707*cfb92d14SAndroid Build Coastguard Worker if len(devices) < golden_devices_required: 708*cfb92d14SAndroid Build Coastguard Worker raise GoldenDeviceNotEnoughError() 709*cfb92d14SAndroid Build Coastguard Worker 710*cfb92d14SAndroid Build Coastguard Worker # add golden devices 711*cfb92d14SAndroid Build Coastguard Worker number_of_devices_to_add = len(devices) if self.add_all_devices else golden_devices_required 712*cfb92d14SAndroid Build Coastguard Worker for i in range(number_of_devices_to_add): 713*cfb92d14SAndroid Build Coastguard Worker self._add_device(*devices.pop()) 714*cfb92d14SAndroid Build Coastguard Worker 715*cfb92d14SAndroid Build Coastguard Worker # add DUT 716*cfb92d14SAndroid Build Coastguard Worker if self.case_need_shield: 717*cfb92d14SAndroid Build Coastguard Worker if not self.device_order: 718*cfb92d14SAndroid Build Coastguard Worker self._add_device(*settings.DUT2_DEVICE) 719*cfb92d14SAndroid Build Coastguard Worker else: 720*cfb92d14SAndroid Build Coastguard Worker if settings.DUT_DEVICE: 721*cfb92d14SAndroid Build Coastguard Worker self._add_device(*settings.DUT_DEVICE) 722*cfb92d14SAndroid Build Coastguard Worker 723*cfb92d14SAndroid Build Coastguard Worker # enable AUTO DUT 724*cfb92d14SAndroid Build Coastguard Worker if self.auto_dut: 725*cfb92d14SAndroid Build Coastguard Worker checkbox_auto_dut = browser.find_element_by_id('EnableAutoDutSelection') 726*cfb92d14SAndroid Build Coastguard Worker if not checkbox_auto_dut.is_selected(): 727*cfb92d14SAndroid Build Coastguard Worker checkbox_auto_dut.click() 728*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 729*cfb92d14SAndroid Build Coastguard Worker 730*cfb92d14SAndroid Build Coastguard Worker if settings.DUT_DEVICE: 731*cfb92d14SAndroid Build Coastguard Worker radio_auto_dut = browser.find_element_by_class_name('AutoDUT_RadBtns') 732*cfb92d14SAndroid Build Coastguard Worker if not radio_auto_dut.is_selected() and not self.device_order: 733*cfb92d14SAndroid Build Coastguard Worker radio_auto_dut.click() 734*cfb92d14SAndroid Build Coastguard Worker 735*cfb92d14SAndroid Build Coastguard Worker if self.device_order: 736*cfb92d14SAndroid Build Coastguard Worker selected_hw_set = test_bed.find_elements_by_class_name('selected-hw') 737*cfb92d14SAndroid Build Coastguard Worker for selected_hw in selected_hw_set: 738*cfb92d14SAndroid Build Coastguard Worker form_inputs = selected_hw.find_elements_by_tag_name('input') 739*cfb92d14SAndroid Build Coastguard Worker form_port = form_inputs[0] 740*cfb92d14SAndroid Build Coastguard Worker port = form_port.get_attribute('value').encode('utf8') 741*cfb92d14SAndroid Build Coastguard Worker if port == dut_device[0]: 742*cfb92d14SAndroid Build Coastguard Worker radio_auto_dut = selected_hw.find_element_by_class_name('AutoDUT_RadBtns') 743*cfb92d14SAndroid Build Coastguard Worker if not radio_auto_dut.is_selected(): 744*cfb92d14SAndroid Build Coastguard Worker radio_auto_dut.click() 745*cfb92d14SAndroid Build Coastguard Worker 746*cfb92d14SAndroid Build Coastguard Worker while True: 747*cfb92d14SAndroid Build Coastguard Worker try: 748*cfb92d14SAndroid Build Coastguard Worker self._connect_devices() 749*cfb92d14SAndroid Build Coastguard Worker button_next = browser.find_element_by_id('nextBtn') 750*cfb92d14SAndroid Build Coastguard Worker if not wait_until( 751*cfb92d14SAndroid Build Coastguard Worker lambda: 'disabled' not in button_next.get_attribute('class'), 752*cfb92d14SAndroid Build Coastguard Worker times=(30 + 4 * number_of_devices_to_add), 753*cfb92d14SAndroid Build Coastguard Worker ): 754*cfb92d14SAndroid Build Coastguard Worker bad_ones = [] 755*cfb92d14SAndroid Build Coastguard Worker selected_hw_set = test_bed.find_elements_by_class_name('selected-hw') 756*cfb92d14SAndroid Build Coastguard Worker for selected_hw in selected_hw_set: 757*cfb92d14SAndroid Build Coastguard Worker form_inputs = selected_hw.find_elements_by_tag_name('input') 758*cfb92d14SAndroid Build Coastguard Worker form_port = form_inputs[0] 759*cfb92d14SAndroid Build Coastguard Worker if form_port.is_enabled(): 760*cfb92d14SAndroid Build Coastguard Worker bad_ones.append(selected_hw) 761*cfb92d14SAndroid Build Coastguard Worker 762*cfb92d14SAndroid Build Coastguard Worker for selected_hw in bad_ones: 763*cfb92d14SAndroid Build Coastguard Worker form_inputs = selected_hw.find_elements_by_tag_name('input') 764*cfb92d14SAndroid Build Coastguard Worker form_port = form_inputs[0] 765*cfb92d14SAndroid Build Coastguard Worker port = form_port.get_attribute('value').encode('utf8') 766*cfb92d14SAndroid Build Coastguard Worker if port == dut_device[0]: 767*cfb92d14SAndroid Build Coastguard Worker if settings.PDU_CONTROLLER_TYPE is None: 768*cfb92d14SAndroid Build Coastguard Worker # connection error cannot recover without power 769*cfb92d14SAndroid Build Coastguard Worker # cycling 770*cfb92d14SAndroid Build Coastguard Worker raise FatalError('Failed to connect to DUT') 771*cfb92d14SAndroid Build Coastguard Worker else: 772*cfb92d14SAndroid Build Coastguard Worker raise FailError('Failed to connect to DUT') 773*cfb92d14SAndroid Build Coastguard Worker 774*cfb92d14SAndroid Build Coastguard Worker if settings.PDU_CONTROLLER_TYPE is None: 775*cfb92d14SAndroid Build Coastguard Worker # port cannot recover without power cycling 776*cfb92d14SAndroid Build Coastguard Worker self.history.mark_bad_golden_device(port) 777*cfb92d14SAndroid Build Coastguard Worker 778*cfb92d14SAndroid Build Coastguard Worker # remove the bad one 779*cfb92d14SAndroid Build Coastguard Worker selected_hw.find_element_by_class_name('removeSelectedDevice').click() 780*cfb92d14SAndroid Build Coastguard Worker time.sleep(0.1) 781*cfb92d14SAndroid Build Coastguard Worker 782*cfb92d14SAndroid Build Coastguard Worker if len(devices): 783*cfb92d14SAndroid Build Coastguard Worker self._add_device(*devices.pop()) 784*cfb92d14SAndroid Build Coastguard Worker else: 785*cfb92d14SAndroid Build Coastguard Worker devices = None 786*cfb92d14SAndroid Build Coastguard Worker 787*cfb92d14SAndroid Build Coastguard Worker if devices is None: 788*cfb92d14SAndroid Build Coastguard Worker logger.warning('Golden devices not enough') 789*cfb92d14SAndroid Build Coastguard Worker raise GoldenDeviceNotEnoughError() 790*cfb92d14SAndroid Build Coastguard Worker else: 791*cfb92d14SAndroid Build Coastguard Worker logger.info('Try again with new golden devices') 792*cfb92d14SAndroid Build Coastguard Worker continue 793*cfb92d14SAndroid Build Coastguard Worker 794*cfb92d14SAndroid Build Coastguard Worker if self.auto_dut and not settings.DUT_DEVICE: 795*cfb92d14SAndroid Build Coastguard Worker radio_auto_dut = browser.find_element_by_class_name('AutoDUT_RadBtns') 796*cfb92d14SAndroid Build Coastguard Worker if not radio_auto_dut.is_selected(): 797*cfb92d14SAndroid Build Coastguard Worker radio_auto_dut.click() 798*cfb92d14SAndroid Build Coastguard Worker 799*cfb92d14SAndroid Build Coastguard Worker time.sleep(5) 800*cfb92d14SAndroid Build Coastguard Worker 801*cfb92d14SAndroid Build Coastguard Worker button_next.click() 802*cfb92d14SAndroid Build Coastguard Worker if not wait_until(lambda: self._browser.current_url.endswith('TestExecution.html'), 20): 803*cfb92d14SAndroid Build Coastguard Worker raise Exception('Failed to load TestExecution page') 804*cfb92d14SAndroid Build Coastguard Worker except FailError: 805*cfb92d14SAndroid Build Coastguard Worker raise 806*cfb92d14SAndroid Build Coastguard Worker except BaseException: 807*cfb92d14SAndroid Build Coastguard Worker logger.exception('Unexpected error') 808*cfb92d14SAndroid Build Coastguard Worker else: 809*cfb92d14SAndroid Build Coastguard Worker break 810*cfb92d14SAndroid Build Coastguard Worker 811*cfb92d14SAndroid Build Coastguard Worker def _select_case(self, role, case): 812*cfb92d14SAndroid Build Coastguard Worker """Select the test case. 813*cfb92d14SAndroid Build Coastguard Worker """ 814*cfb92d14SAndroid Build Coastguard Worker # select the case 815*cfb92d14SAndroid Build Coastguard Worker elem = Select(self._browser.find_element_by_id('select-dut')) 816*cfb92d14SAndroid Build Coastguard Worker elem.select_by_value(str(role)) 817*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 818*cfb92d14SAndroid Build Coastguard Worker 819*cfb92d14SAndroid Build Coastguard Worker checkbox = None 820*cfb92d14SAndroid Build Coastguard Worker wait_until(lambda: self._browser.find_elements_by_css_selector('.tree-node .tree-title') and True) 821*cfb92d14SAndroid Build Coastguard Worker elems = self._browser.find_elements_by_css_selector('.tree-node .tree-title') 822*cfb92d14SAndroid Build Coastguard Worker finder = re.compile(r'.*\b' + case + r'\b') 823*cfb92d14SAndroid Build Coastguard Worker finder_dotted = re.compile(r'.*\b' + case.replace(' ', r'\.') + r'\b') 824*cfb92d14SAndroid Build Coastguard Worker for elem in elems: 825*cfb92d14SAndroid Build Coastguard Worker # elem.txt might be null when the required reference devices could 826*cfb92d14SAndroid Build Coastguard Worker # not be met (either due to the quantity or the type) for specific test. 827*cfb92d14SAndroid Build Coastguard Worker # perform() will throw exceptions if elem.text is null since Chrome 828*cfb92d14SAndroid Build Coastguard Worker # and chromedriver 80. If elem is not shown in current case list 829*cfb92d14SAndroid Build Coastguard Worker # window, move_to_element() will not work either. 830*cfb92d14SAndroid Build Coastguard Worker if not elem.text: 831*cfb92d14SAndroid Build Coastguard Worker continue 832*cfb92d14SAndroid Build Coastguard Worker # execute a javascript to scroll the window to the elem 833*cfb92d14SAndroid Build Coastguard Worker self._browser.execute_script('arguments[0].scrollIntoView();', elem) 834*cfb92d14SAndroid Build Coastguard Worker action_chains = ActionChains(self._browser) 835*cfb92d14SAndroid Build Coastguard Worker action_chains.move_to_element(elem) 836*cfb92d14SAndroid Build Coastguard Worker action_chains.perform() 837*cfb92d14SAndroid Build Coastguard Worker logger.debug(elem.text) 838*cfb92d14SAndroid Build Coastguard Worker if finder.match(elem.text) or finder_dotted.match(elem.text): 839*cfb92d14SAndroid Build Coastguard Worker parent = elem.find_element_by_xpath('..') 840*cfb92d14SAndroid Build Coastguard Worker checkbox = parent.find_element_by_class_name('tree-checkbox') 841*cfb92d14SAndroid Build Coastguard Worker break 842*cfb92d14SAndroid Build Coastguard Worker 843*cfb92d14SAndroid Build Coastguard Worker if not checkbox: 844*cfb92d14SAndroid Build Coastguard Worker time.sleep(5) 845*cfb92d14SAndroid Build Coastguard Worker raise Exception('Failed to find the case') 846*cfb92d14SAndroid Build Coastguard Worker 847*cfb92d14SAndroid Build Coastguard Worker self._browser.execute_script("$('.overview').css('left', '0')") 848*cfb92d14SAndroid Build Coastguard Worker checkbox.click() 849*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 850*cfb92d14SAndroid Build Coastguard Worker 851*cfb92d14SAndroid Build Coastguard Worker elem = self._browser.find_element_by_id('runTest') 852*cfb92d14SAndroid Build Coastguard Worker elem.click() 853*cfb92d14SAndroid Build Coastguard Worker if not wait_until(lambda: self._browser.find_element_by_id('stopTest') and True, 10): 854*cfb92d14SAndroid Build Coastguard Worker raise Exception('Failed to start test case') 855*cfb92d14SAndroid Build Coastguard Worker 856*cfb92d14SAndroid Build Coastguard Worker def _collect_result(self): 857*cfb92d14SAndroid Build Coastguard Worker """Collect test result. 858*cfb92d14SAndroid Build Coastguard Worker 859*cfb92d14SAndroid Build Coastguard Worker Copy PDF and pcap file to result directory 860*cfb92d14SAndroid Build Coastguard Worker """ 861*cfb92d14SAndroid Build Coastguard Worker 862*cfb92d14SAndroid Build Coastguard Worker if self.new_th: 863*cfb92d14SAndroid Build Coastguard Worker os.system('copy "%s\\Reports\\*.*" "%s"' % (settings.HARNESS_HOME, self.result_dir)) 864*cfb92d14SAndroid Build Coastguard Worker else: 865*cfb92d14SAndroid Build Coastguard Worker os.system('copy "%s\\Thread_Harness\\temp\\*.*" "%s"' % (settings.HARNESS_HOME, self.result_dir)) 866*cfb92d14SAndroid Build Coastguard Worker 867*cfb92d14SAndroid Build Coastguard Worker os.system('copy "%s\\Captures\\*.pcapng" %s\\' % (settings.HARNESS_HOME, self.result_dir)) 868*cfb92d14SAndroid Build Coastguard Worker 869*cfb92d14SAndroid Build Coastguard Worker def _wait_dialog(self): 870*cfb92d14SAndroid Build Coastguard Worker """Wait for dialogs and handle them until done. 871*cfb92d14SAndroid Build Coastguard Worker """ 872*cfb92d14SAndroid Build Coastguard Worker logger.debug('waiting for dialog') 873*cfb92d14SAndroid Build Coastguard Worker done = False 874*cfb92d14SAndroid Build Coastguard Worker error = False 875*cfb92d14SAndroid Build Coastguard Worker 876*cfb92d14SAndroid Build Coastguard Worker logger.info('self timeout %d', self.timeout) 877*cfb92d14SAndroid Build Coastguard Worker while not done and self.timeout: 878*cfb92d14SAndroid Build Coastguard Worker try: 879*cfb92d14SAndroid Build Coastguard Worker dialog = self._browser.find_element_by_id('RemoteConfirm') 880*cfb92d14SAndroid Build Coastguard Worker except BaseException: 881*cfb92d14SAndroid Build Coastguard Worker logger.exception('Failed to get dialog.') 882*cfb92d14SAndroid Build Coastguard Worker else: 883*cfb92d14SAndroid Build Coastguard Worker if dialog and dialog.get_attribute('aria-hidden') == 'false': 884*cfb92d14SAndroid Build Coastguard Worker title = dialog.find_element_by_class_name('modal-title').text 885*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 886*cfb92d14SAndroid Build Coastguard Worker logger.info('Handling dialog[%s]', title) 887*cfb92d14SAndroid Build Coastguard Worker 888*cfb92d14SAndroid Build Coastguard Worker try: 889*cfb92d14SAndroid Build Coastguard Worker done = self._handle_dialog(dialog, title) 890*cfb92d14SAndroid Build Coastguard Worker except BaseException: 891*cfb92d14SAndroid Build Coastguard Worker logger.exception('Error handling dialog: %s', title) 892*cfb92d14SAndroid Build Coastguard Worker error = True 893*cfb92d14SAndroid Build Coastguard Worker 894*cfb92d14SAndroid Build Coastguard Worker if done is None: 895*cfb92d14SAndroid Build Coastguard Worker raise FailError('Unexpected dialog occurred') 896*cfb92d14SAndroid Build Coastguard Worker 897*cfb92d14SAndroid Build Coastguard Worker dialog.find_element_by_id('ConfirmOk').click() 898*cfb92d14SAndroid Build Coastguard Worker 899*cfb92d14SAndroid Build Coastguard Worker time.sleep(1) 900*cfb92d14SAndroid Build Coastguard Worker 901*cfb92d14SAndroid Build Coastguard Worker try: 902*cfb92d14SAndroid Build Coastguard Worker stop_button = self._browser.find_element_by_id('stopTest') 903*cfb92d14SAndroid Build Coastguard Worker if done: 904*cfb92d14SAndroid Build Coastguard Worker stop_button.click() 905*cfb92d14SAndroid Build Coastguard Worker # wait for stop procedure end 906*cfb92d14SAndroid Build Coastguard Worker time.sleep(10) 907*cfb92d14SAndroid Build Coastguard Worker except NoSuchElementException: 908*cfb92d14SAndroid Build Coastguard Worker logger.info('Test stopped') 909*cfb92d14SAndroid Build Coastguard Worker time.sleep(5) 910*cfb92d14SAndroid Build Coastguard Worker done = True 911*cfb92d14SAndroid Build Coastguard Worker 912*cfb92d14SAndroid Build Coastguard Worker self.timeout -= 1 913*cfb92d14SAndroid Build Coastguard Worker 914*cfb92d14SAndroid Build Coastguard Worker # check if already ended capture 915*cfb92d14SAndroid Build Coastguard Worker if self.timeout % 10 == 0: 916*cfb92d14SAndroid Build Coastguard Worker lines = self._hc.tail() 917*cfb92d14SAndroid Build Coastguard Worker if 'SUCCESS: The process "dumpcap.exe" with PID ' in lines: 918*cfb92d14SAndroid Build Coastguard Worker logger.info('Tshark should be ended now, lets wait at most 30 seconds.') 919*cfb92d14SAndroid Build Coastguard Worker if not wait_until(lambda: 'tshark.exe' not in subprocess.check_output('tasklist'), 30): 920*cfb92d14SAndroid Build Coastguard Worker res = subprocess.check_output('taskkill /t /f /im tshark.exe', 921*cfb92d14SAndroid Build Coastguard Worker stderr=subprocess.STDOUT, 922*cfb92d14SAndroid Build Coastguard Worker shell=True) 923*cfb92d14SAndroid Build Coastguard Worker logger.info(res) 924*cfb92d14SAndroid Build Coastguard Worker 925*cfb92d14SAndroid Build Coastguard Worker # Wait until case really stopped 926*cfb92d14SAndroid Build Coastguard Worker wait_until(lambda: self._browser.find_element_by_id('runTest') and True, 30) 927*cfb92d14SAndroid Build Coastguard Worker 928*cfb92d14SAndroid Build Coastguard Worker if error: 929*cfb92d14SAndroid Build Coastguard Worker raise FailError('Fail for previous exceptions') 930*cfb92d14SAndroid Build Coastguard Worker 931*cfb92d14SAndroid Build Coastguard Worker def _handle_dialog(self, dialog, title): 932*cfb92d14SAndroid Build Coastguard Worker """Handle a dialog. 933*cfb92d14SAndroid Build Coastguard Worker 934*cfb92d14SAndroid Build Coastguard Worker Returns: 935*cfb92d14SAndroid Build Coastguard Worker bool True if no more dialogs expected, 936*cfb92d14SAndroid Build Coastguard Worker False if more dialogs needed, and 937*cfb92d14SAndroid Build Coastguard Worker None if not handled 938*cfb92d14SAndroid Build Coastguard Worker """ 939*cfb92d14SAndroid Build Coastguard Worker done = self.on_dialog(dialog, title) 940*cfb92d14SAndroid Build Coastguard Worker if isinstance(done, bool): 941*cfb92d14SAndroid Build Coastguard Worker return done 942*cfb92d14SAndroid Build Coastguard Worker 943*cfb92d14SAndroid Build Coastguard Worker if title.startswith('Start DUT'): 944*cfb92d14SAndroid Build Coastguard Worker body = dialog.find_element_by_id('cnfrmMsg').text 945*cfb92d14SAndroid Build Coastguard Worker if 'Sleepy End Device' in body: 946*cfb92d14SAndroid Build Coastguard Worker self.dut.mode = 's' 947*cfb92d14SAndroid Build Coastguard Worker self.dut.child_timeout = self.child_timeout 948*cfb92d14SAndroid Build Coastguard Worker elif 'End Device' in body: 949*cfb92d14SAndroid Build Coastguard Worker self.dut.mode = 'rn' 950*cfb92d14SAndroid Build Coastguard Worker self.dut.child_timeout = self.child_timeout 951*cfb92d14SAndroid Build Coastguard Worker else: 952*cfb92d14SAndroid Build Coastguard Worker self.dut.mode = 'rdn' 953*cfb92d14SAndroid Build Coastguard Worker 954*cfb92d14SAndroid Build Coastguard Worker if 'at channel' in body: 955*cfb92d14SAndroid Build Coastguard Worker self.channel = int(body.split(':')[1]) 956*cfb92d14SAndroid Build Coastguard Worker 957*cfb92d14SAndroid Build Coastguard Worker self.dut.channel = self.channel 958*cfb92d14SAndroid Build Coastguard Worker self.dut.panid = settings.THREAD_PANID 959*cfb92d14SAndroid Build Coastguard Worker self.dut.networkname = settings.THREAD_NETWORKNAME 960*cfb92d14SAndroid Build Coastguard Worker self.dut.extpanid = settings.THREAD_EXTPANID 961*cfb92d14SAndroid Build Coastguard Worker self.dut.start() 962*cfb92d14SAndroid Build Coastguard Worker 963*cfb92d14SAndroid Build Coastguard Worker elif title.startswith('MAC Address Required') or title.startswith('DUT Random Extended MAC Address Required'): 964*cfb92d14SAndroid Build Coastguard Worker mac = self.dut.mac 965*cfb92d14SAndroid Build Coastguard Worker inp = dialog.find_element_by_id('cnfrmInpText') 966*cfb92d14SAndroid Build Coastguard Worker inp.clear() 967*cfb92d14SAndroid Build Coastguard Worker inp.send_keys('0x%s' % mac) 968*cfb92d14SAndroid Build Coastguard Worker 969*cfb92d14SAndroid Build Coastguard Worker elif title.startswith('LL64 Address'): 970*cfb92d14SAndroid Build Coastguard Worker ll64 = None 971*cfb92d14SAndroid Build Coastguard Worker for addr in self.dut.addrs: 972*cfb92d14SAndroid Build Coastguard Worker addr = addr.lower() 973*cfb92d14SAndroid Build Coastguard Worker if addr.startswith('fe80') and not re.match('.+ff:fe00:[0-9a-f]{0,4}$', addr): 974*cfb92d14SAndroid Build Coastguard Worker ll64 = addr 975*cfb92d14SAndroid Build Coastguard Worker break 976*cfb92d14SAndroid Build Coastguard Worker 977*cfb92d14SAndroid Build Coastguard Worker if not ll64: 978*cfb92d14SAndroid Build Coastguard Worker raise FailError('No link local address found') 979*cfb92d14SAndroid Build Coastguard Worker 980*cfb92d14SAndroid Build Coastguard Worker logger.info('Link local address is %s', ll64) 981*cfb92d14SAndroid Build Coastguard Worker inp = dialog.find_element_by_id('cnfrmInpText') 982*cfb92d14SAndroid Build Coastguard Worker inp.clear() 983*cfb92d14SAndroid Build Coastguard Worker inp.send_keys(ll64) 984*cfb92d14SAndroid Build Coastguard Worker 985*cfb92d14SAndroid Build Coastguard Worker elif title.startswith('Enter Channel'): 986*cfb92d14SAndroid Build Coastguard Worker self.dut.channel = self.channel 987*cfb92d14SAndroid Build Coastguard Worker inp = dialog.find_element_by_id('cnfrmInpText') 988*cfb92d14SAndroid Build Coastguard Worker inp.clear() 989*cfb92d14SAndroid Build Coastguard Worker inp.send_keys(str(self.dut.channel)) 990*cfb92d14SAndroid Build Coastguard Worker 991*cfb92d14SAndroid Build Coastguard Worker elif title.startswith('User Action Needed'): 992*cfb92d14SAndroid Build Coastguard Worker body = dialog.find_element_by_id('cnfrmMsg').text 993*cfb92d14SAndroid Build Coastguard Worker if body.startswith('Power Down the DUT'): 994*cfb92d14SAndroid Build Coastguard Worker self.dut.stop() 995*cfb92d14SAndroid Build Coastguard Worker return True 996*cfb92d14SAndroid Build Coastguard Worker 997*cfb92d14SAndroid Build Coastguard Worker elif title.startswith('Short Address'): 998*cfb92d14SAndroid Build Coastguard Worker short_addr = '0x%s' % self.dut.short_addr 999*cfb92d14SAndroid Build Coastguard Worker inp = dialog.find_element_by_id('cnfrmInpText') 1000*cfb92d14SAndroid Build Coastguard Worker inp.clear() 1001*cfb92d14SAndroid Build Coastguard Worker inp.send_keys(short_addr) 1002*cfb92d14SAndroid Build Coastguard Worker 1003*cfb92d14SAndroid Build Coastguard Worker elif title.startswith('ML64 Address'): 1004*cfb92d14SAndroid Build Coastguard Worker ml64 = None 1005*cfb92d14SAndroid Build Coastguard Worker for addr in self.dut.addrs: 1006*cfb92d14SAndroid Build Coastguard Worker if addr.startswith('fd') and not re.match('.+ff:fe00:[0-9a-f]{0,4}$', addr): 1007*cfb92d14SAndroid Build Coastguard Worker ml64 = addr 1008*cfb92d14SAndroid Build Coastguard Worker break 1009*cfb92d14SAndroid Build Coastguard Worker 1010*cfb92d14SAndroid Build Coastguard Worker if not ml64: 1011*cfb92d14SAndroid Build Coastguard Worker raise Exception('No mesh local address found') 1012*cfb92d14SAndroid Build Coastguard Worker 1013*cfb92d14SAndroid Build Coastguard Worker logger.info('Mesh local address is %s', ml64) 1014*cfb92d14SAndroid Build Coastguard Worker inp = dialog.find_element_by_id('cnfrmInpText') 1015*cfb92d14SAndroid Build Coastguard Worker inp.clear() 1016*cfb92d14SAndroid Build Coastguard Worker inp.send_keys(ml64) 1017*cfb92d14SAndroid Build Coastguard Worker 1018*cfb92d14SAndroid Build Coastguard Worker elif title.startswith('Shield Devices') or title.startswith('Shield DUT'): 1019*cfb92d14SAndroid Build Coastguard Worker time.sleep(2) 1020*cfb92d14SAndroid Build Coastguard Worker if self.rf_shield: 1021*cfb92d14SAndroid Build Coastguard Worker logger.info('Shielding devices') 1022*cfb92d14SAndroid Build Coastguard Worker with self.rf_shield: 1023*cfb92d14SAndroid Build Coastguard Worker self.rf_shield.shield() 1024*cfb92d14SAndroid Build Coastguard Worker elif self.dut and settings.SHIELD_SIMULATION: 1025*cfb92d14SAndroid Build Coastguard Worker self.dut.channel = (self.channel == THREAD_CHANNEL_MAX and THREAD_CHANNEL_MIN) or (self.channel + 1) 1026*cfb92d14SAndroid Build Coastguard Worker else: 1027*cfb92d14SAndroid Build Coastguard Worker input('Shield DUT and press enter to continue..') 1028*cfb92d14SAndroid Build Coastguard Worker 1029*cfb92d14SAndroid Build Coastguard Worker elif title.startswith('Unshield Devices') or title.startswith('Bring DUT back to network'): 1030*cfb92d14SAndroid Build Coastguard Worker time.sleep(5) 1031*cfb92d14SAndroid Build Coastguard Worker if self.rf_shield: 1032*cfb92d14SAndroid Build Coastguard Worker logger.info('Unshielding devices') 1033*cfb92d14SAndroid Build Coastguard Worker with self.rf_shield: 1034*cfb92d14SAndroid Build Coastguard Worker self.rf_shield.unshield() 1035*cfb92d14SAndroid Build Coastguard Worker elif self.dut and settings.SHIELD_SIMULATION: 1036*cfb92d14SAndroid Build Coastguard Worker self.dut.channel = self.channel 1037*cfb92d14SAndroid Build Coastguard Worker else: 1038*cfb92d14SAndroid Build Coastguard Worker input('Bring DUT and press enter to continue..') 1039*cfb92d14SAndroid Build Coastguard Worker 1040*cfb92d14SAndroid Build Coastguard Worker elif title.startswith('Configure Prefix on DUT'): 1041*cfb92d14SAndroid Build Coastguard Worker body = dialog.find_element_by_id('cnfrmMsg').text 1042*cfb92d14SAndroid Build Coastguard Worker body = body.split(': ')[1] 1043*cfb92d14SAndroid Build Coastguard Worker params = reduce( 1044*cfb92d14SAndroid Build Coastguard Worker lambda params, param: params.update(((param[0].strip(' '), param[1]),)) or params, 1045*cfb92d14SAndroid Build Coastguard Worker [it.split('=') for it in body.split(', ')], 1046*cfb92d14SAndroid Build Coastguard Worker {}, 1047*cfb92d14SAndroid Build Coastguard Worker ) 1048*cfb92d14SAndroid Build Coastguard Worker prefix = params['P_Prefix'].strip('\0\r\n\t ') 1049*cfb92d14SAndroid Build Coastguard Worker flags = [] 1050*cfb92d14SAndroid Build Coastguard Worker if params.get('P_slaac_preferred', 0) == '1': 1051*cfb92d14SAndroid Build Coastguard Worker flags.append('p') 1052*cfb92d14SAndroid Build Coastguard Worker flags.append('ao') 1053*cfb92d14SAndroid Build Coastguard Worker if params.get('P_stable', 0) == '1': 1054*cfb92d14SAndroid Build Coastguard Worker flags.append('s') 1055*cfb92d14SAndroid Build Coastguard Worker if params.get('P_default', 0) == '1': 1056*cfb92d14SAndroid Build Coastguard Worker flags.append('r') 1057*cfb92d14SAndroid Build Coastguard Worker prf = 'high' 1058*cfb92d14SAndroid Build Coastguard Worker self.dut.add_prefix(prefix, ''.join(flags), prf) 1059*cfb92d14SAndroid Build Coastguard Worker 1060*cfb92d14SAndroid Build Coastguard Worker return False 1061*cfb92d14SAndroid Build Coastguard Worker 1062*cfb92d14SAndroid Build Coastguard Worker def test(self): 1063*cfb92d14SAndroid Build Coastguard Worker """This method will only start test case in child class""" 1064*cfb92d14SAndroid Build Coastguard Worker if self.__class__ is HarnessCase: 1065*cfb92d14SAndroid Build Coastguard Worker logger.warning('Skip this harness itself') 1066*cfb92d14SAndroid Build Coastguard Worker return 1067*cfb92d14SAndroid Build Coastguard Worker 1068*cfb92d14SAndroid Build Coastguard Worker logger.info('Testing role[%d] case[%s]', self.role, self.case) 1069*cfb92d14SAndroid Build Coastguard Worker 1070*cfb92d14SAndroid Build Coastguard Worker init_browser_times = 5 1071*cfb92d14SAndroid Build Coastguard Worker while True: 1072*cfb92d14SAndroid Build Coastguard Worker if self._init_browser(): 1073*cfb92d14SAndroid Build Coastguard Worker break 1074*cfb92d14SAndroid Build Coastguard Worker elif init_browser_times > 0: 1075*cfb92d14SAndroid Build Coastguard Worker init_browser_times -= 1 1076*cfb92d14SAndroid Build Coastguard Worker self._destroy_browser() 1077*cfb92d14SAndroid Build Coastguard Worker else: 1078*cfb92d14SAndroid Build Coastguard Worker raise SystemExit() 1079*cfb92d14SAndroid Build Coastguard Worker 1080*cfb92d14SAndroid Build Coastguard Worker try: 1081*cfb92d14SAndroid Build Coastguard Worker # prepare test case 1082*cfb92d14SAndroid Build Coastguard Worker while True: 1083*cfb92d14SAndroid Build Coastguard Worker url = self._browser.current_url 1084*cfb92d14SAndroid Build Coastguard Worker if url.endswith('SetupPage.html'): 1085*cfb92d14SAndroid Build Coastguard Worker self._setup_page() 1086*cfb92d14SAndroid Build Coastguard Worker elif url.endswith('TestBed.html'): 1087*cfb92d14SAndroid Build Coastguard Worker self._test_bed() 1088*cfb92d14SAndroid Build Coastguard Worker elif url.endswith('TestExecution.html'): 1089*cfb92d14SAndroid Build Coastguard Worker logger.info('Ready to handle dialogs') 1090*cfb92d14SAndroid Build Coastguard Worker break 1091*cfb92d14SAndroid Build Coastguard Worker time.sleep(2) 1092*cfb92d14SAndroid Build Coastguard Worker except UnexpectedAlertPresentException: 1093*cfb92d14SAndroid Build Coastguard Worker logger.exception('Failed to connect to harness server') 1094*cfb92d14SAndroid Build Coastguard Worker raise SystemExit() 1095*cfb92d14SAndroid Build Coastguard Worker except FatalError: 1096*cfb92d14SAndroid Build Coastguard Worker logger.exception('Test stopped for fatal error') 1097*cfb92d14SAndroid Build Coastguard Worker raise SystemExit() 1098*cfb92d14SAndroid Build Coastguard Worker except FailError: 1099*cfb92d14SAndroid Build Coastguard Worker logger.exception('Test failed') 1100*cfb92d14SAndroid Build Coastguard Worker raise 1101*cfb92d14SAndroid Build Coastguard Worker except BaseException: 1102*cfb92d14SAndroid Build Coastguard Worker logger.exception('Something wrong') 1103*cfb92d14SAndroid Build Coastguard Worker 1104*cfb92d14SAndroid Build Coastguard Worker self._select_case(self.role, self.case) 1105*cfb92d14SAndroid Build Coastguard Worker 1106*cfb92d14SAndroid Build Coastguard Worker logger.info('start to wait test process end') 1107*cfb92d14SAndroid Build Coastguard Worker self._wait_dialog() 1108*cfb92d14SAndroid Build Coastguard Worker 1109*cfb92d14SAndroid Build Coastguard Worker try: 1110*cfb92d14SAndroid Build Coastguard Worker self._collect_result() 1111*cfb92d14SAndroid Build Coastguard Worker except BaseException: 1112*cfb92d14SAndroid Build Coastguard Worker logger.exception('Failed to collect results') 1113*cfb92d14SAndroid Build Coastguard Worker raise 1114*cfb92d14SAndroid Build Coastguard Worker 1115*cfb92d14SAndroid Build Coastguard Worker # get case result 1116*cfb92d14SAndroid Build Coastguard Worker status = self._browser.find_element_by_class_name('title-test').get_attribute('innerText') 1117*cfb92d14SAndroid Build Coastguard Worker logger.info(status) 1118*cfb92d14SAndroid Build Coastguard Worker success = 'Pass' in status 1119*cfb92d14SAndroid Build Coastguard Worker self.assertTrue(success) 1120