1#!/usr/bin/env python3 2# 3# Copyright 2016 - Google 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16""" 17 Base Class for Defining Common Telephony Test Functionality 18""" 19 20import logging 21import os 22import re 23import shutil 24import time 25 26from acts import asserts 27from acts import logger as acts_logger 28from acts import signals 29from acts.base_test import BaseTestClass 30from acts.controllers.android_device import DEFAULT_QXDM_LOG_PATH 31from acts.controllers.android_device import DEFAULT_SDM_LOG_PATH 32from acts.keys import Config 33from acts import records 34from acts import utils 35 36from acts.test_utils.tel.tel_subscription_utils import \ 37 initial_set_up_for_subid_infomation 38from acts.test_utils.tel.tel_subscription_utils import \ 39 set_default_sub_for_all_services 40from acts.test_utils.tel.tel_subscription_utils import get_subid_from_slot_index 41from acts.test_utils.tel.tel_test_utils import build_id_override 42from acts.test_utils.tel.tel_test_utils import disable_qxdm_logger 43from acts.test_utils.tel.tel_test_utils import enable_connectivity_metrics 44from acts.test_utils.tel.tel_test_utils import enable_radio_log_on 45from acts.test_utils.tel.tel_test_utils import ensure_phone_default_state 46from acts.test_utils.tel.tel_test_utils import ensure_phone_idle 47from acts.test_utils.tel.tel_test_utils import ensure_wifi_connected 48from acts.test_utils.tel.tel_test_utils import force_connectivity_metrics_upload 49from acts.test_utils.tel.tel_test_utils import get_operator_name 50from acts.test_utils.tel.tel_test_utils import get_screen_shot_log 51from acts.test_utils.tel.tel_test_utils import get_sim_state 52from acts.test_utils.tel.tel_test_utils import get_tcpdump_log 53from acts.test_utils.tel.tel_test_utils import multithread_func 54from acts.test_utils.tel.tel_test_utils import print_radio_info 55from acts.test_utils.tel.tel_test_utils import reboot_device 56from acts.test_utils.tel.tel_test_utils import recover_build_id 57from acts.test_utils.tel.tel_test_utils import run_multithread_func 58from acts.test_utils.tel.tel_test_utils import setup_droid_properties 59from acts.test_utils.tel.tel_test_utils import set_phone_screen_on 60from acts.test_utils.tel.tel_test_utils import set_phone_silent_mode 61from acts.test_utils.tel.tel_test_utils import set_qxdm_logger_command 62from acts.test_utils.tel.tel_test_utils import start_qxdm_logger 63from acts.test_utils.tel.tel_test_utils import start_qxdm_loggers 64from acts.test_utils.tel.tel_test_utils import start_sdm_loggers 65from acts.test_utils.tel.tel_test_utils import start_sdm_logger 66from acts.test_utils.tel.tel_test_utils import start_tcpdumps 67from acts.test_utils.tel.tel_test_utils import stop_qxdm_logger 68from acts.test_utils.tel.tel_test_utils import stop_sdm_loggers 69from acts.test_utils.tel.tel_test_utils import stop_sdm_logger 70from acts.test_utils.tel.tel_test_utils import stop_tcpdumps 71from acts.test_utils.tel.tel_test_utils import synchronize_device_time 72from acts.test_utils.tel.tel_test_utils import unlock_sim 73from acts.test_utils.tel.tel_test_utils import wait_for_sim_ready_by_adb 74from acts.test_utils.tel.tel_test_utils import wait_for_sims_ready_by_adb 75from acts.test_utils.tel.tel_test_utils import activate_wfc_on_device 76from acts.test_utils.tel.tel_test_utils import install_googleaccountutil_apk 77from acts.test_utils.tel.tel_test_utils import add_google_account 78from acts.test_utils.tel.tel_test_utils import install_googlefi_apk 79from acts.test_utils.tel.tel_test_utils import activate_google_fi_account 80from acts.test_utils.tel.tel_test_utils import check_google_fi_activated 81from acts.test_utils.tel.tel_test_utils import check_fi_apk_installed 82from acts.test_utils.tel.tel_test_utils import phone_switch_to_msim_mode 83from acts.test_utils.tel.tel_test_utils import activate_esim_using_suw 84from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND 85from acts.test_utils.tel.tel_defines import SINGLE_SIM_CONFIG, MULTI_SIM_CONFIG 86from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND 87from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_RINGING 88from acts.test_utils.tel.tel_defines import SIM_STATE_ABSENT 89from acts.test_utils.tel.tel_defines import SIM_STATE_UNKNOWN 90from acts.test_utils.tel.tel_defines import WIFI_VERBOSE_LOGGING_ENABLED 91from acts.test_utils.tel.tel_defines import WIFI_VERBOSE_LOGGING_DISABLED 92from acts.test_utils.tel.tel_defines import INVALID_SUB_ID 93 94 95class TelephonyBaseTest(BaseTestClass): 96 # Use for logging in the test cases to facilitate 97 # faster log lookup and reduce ambiguity in logging. 98 @staticmethod 99 def tel_test_wrap(fn): 100 def _safe_wrap_test_case(self, *args, **kwargs): 101 test_id = "%s:%s:%s" % (self.__class__.__name__, self.test_name, 102 self.log_begin_time.replace(' ', '-')) 103 self.test_id = test_id 104 self.result_detail = "" 105 self.testsignal_details = "" 106 self.testsignal_extras = {} 107 tries = int(self.user_params.get("telephony_auto_rerun", 1)) 108 for ad in self.android_devices: 109 ad.log_path = self.log_path 110 for i in range(tries + 1): 111 result = True 112 if i > 0: 113 log_string = "[Test Case] RERUN %s" % self.test_name 114 self.log.info(log_string) 115 self._teardown_test(self.test_name) 116 self._setup_test(self.test_name) 117 try: 118 result = fn(self, *args, **kwargs) 119 except signals.TestFailure as e: 120 self.testsignal_details = e.details 121 self.testsignal_extras = e.extras 122 result = False 123 except signals.TestSignal: 124 raise 125 except Exception as e: 126 self.log.exception(e) 127 asserts.fail(self.result_detail) 128 if result is False: 129 if i < tries: 130 continue 131 else: 132 break 133 if self.user_params.get("check_crash", True): 134 new_crash = ad.check_crash_report(self.test_name, 135 self.begin_time, True) 136 if new_crash: 137 msg = "Find new crash reports %s" % new_crash 138 ad.log.error(msg) 139 self.result_detail = "%s %s %s" % (self.result_detail, 140 ad.serial, msg) 141 result = False 142 if result is not False: 143 asserts.explicit_pass(self.result_detail) 144 else: 145 if self.result_detail: 146 asserts.fail(self.result_detail) 147 else: 148 asserts.fail(self.testsignal_details, self.testsignal_extras) 149 150 return _safe_wrap_test_case 151 152 def setup_class(self): 153 super().setup_class() 154 self.wifi_network_ssid = self.user_params.get( 155 "wifi_network_ssid") or self.user_params.get( 156 "wifi_network_ssid_2g") or self.user_params.get( 157 "wifi_network_ssid_5g") 158 self.wifi_network_pass = self.user_params.get( 159 "wifi_network_pass") or self.user_params.get( 160 "wifi_network_pass_2g") or self.user_params.get( 161 "wifi_network_ssid_5g") 162 163 self.log_path = getattr(logging, "log_path", None) 164 self.qxdm_log = self.user_params.get("qxdm_log", True) 165 self.sdm_log = self.user_params.get("sdm_log", False) 166 self.enable_radio_log_on = self.user_params.get( 167 "enable_radio_log_on", False) 168 self.cbrs_esim = self.user_params.get("cbrs_esim", False) 169 self.account_util = self.user_params.get("account_util", None) 170 self.save_passing_logs = self.user_params.get("save_passing_logs", False) 171 if isinstance(self.account_util, list): 172 self.account_util = self.account_util[0] 173 self.fi_util = self.user_params.get("fi_util", None) 174 if isinstance(self.fi_util, list): 175 self.fi_util = self.fi_util[0] 176 tasks = [(self._init_device, [ad]) for ad in self.android_devices] 177 multithread_func(self.log, tasks) 178 self.skip_reset_between_cases = self.user_params.get( 179 "skip_reset_between_cases", True) 180 self.log_path = getattr(logging, "log_path", None) 181 self.sim_config = { 182 "config":SINGLE_SIM_CONFIG, 183 "number_of_sims":1 184 } 185 186 for ad in self.android_devices: 187 if hasattr(ad, "dsds"): 188 self.sim_config = { 189 "config":MULTI_SIM_CONFIG, 190 "number_of_sims":2 191 } 192 break 193 if "anritsu_md8475a_ip_address" in self.user_params: 194 return 195 qxdm_log_mask_cfg = self.user_params.get("qxdm_log_mask_cfg", None) 196 if isinstance(qxdm_log_mask_cfg, list): 197 qxdm_log_mask_cfg = qxdm_log_mask_cfg[0] 198 if qxdm_log_mask_cfg and "dev/null" in qxdm_log_mask_cfg: 199 qxdm_log_mask_cfg = None 200 sim_conf_file = self.user_params.get("sim_conf_file") 201 if not sim_conf_file: 202 self.log.info("\"sim_conf_file\" is not provided test bed config!") 203 else: 204 if isinstance(sim_conf_file, list): 205 sim_conf_file = sim_conf_file[0] 206 # If the sim_conf_file is not a full path, attempt to find it 207 # relative to the config file. 208 if not os.path.isfile(sim_conf_file): 209 sim_conf_file = os.path.join( 210 self.user_params[Config.key_config_path.value], 211 sim_conf_file) 212 if not os.path.isfile(sim_conf_file): 213 self.log.error("Unable to load user config %s ", 214 sim_conf_file) 215 216 tasks = [(self._setup_device, [ad, sim_conf_file, qxdm_log_mask_cfg]) 217 for ad in self.android_devices] 218 return multithread_func(self.log, tasks) 219 220 def _init_device(self, ad): 221 synchronize_device_time(ad) 222 ad.log_path = self.log_path 223 print_radio_info(ad) 224 unlock_sim(ad) 225 ad.wakeup_screen() 226 ad.adb.shell("input keyevent 82") 227 228 def wait_for_sim_ready(self,ad): 229 wait_for_sim_ready_on_sim_config = { 230 SINGLE_SIM_CONFIG : lambda:wait_for_sim_ready_by_adb(self.log,ad), 231 MULTI_SIM_CONFIG : lambda:wait_for_sims_ready_by_adb(self.log,ad) 232 } 233 if not wait_for_sim_ready_on_sim_config[self.sim_config["config"]]: 234 raise signals.TestAbortClass("unable to load the SIM") 235 236 def _setup_device(self, ad, sim_conf_file, qxdm_log_mask_cfg=None): 237 ad.qxdm_log = getattr(ad, "qxdm_log", self.qxdm_log) 238 ad.sdm_log = getattr(ad, "sdm_log", self.sdm_log) 239 if self.user_params.get("enable_connectivity_metrics", False): 240 enable_connectivity_metrics(ad) 241 if self.user_params.get("build_id_override", False): 242 build_postfix = self.user_params.get("build_id_postfix", 243 "LAB_TEST") 244 build_id_override( 245 ad, 246 new_build_id=self.user_params.get("build_id_override_with", 247 None), 248 postfix=build_postfix) 249 if self.enable_radio_log_on: 250 enable_radio_log_on(ad) 251 if "sdm" in ad.model or "msm" in ad.model or "kon" in ad.model: 252 phone_mode = "ssss" 253 if hasattr(ad, "mtp_dsds"): 254 phone_mode = "dsds" 255 if ad.adb.getprop("persist.radio.multisim.config") != phone_mode: 256 ad.adb.shell("setprop persist.radio.multisim.config %s" \ 257 % phone_mode) 258 reboot_device(ad) 259 260 stop_qxdm_logger(ad) 261 if ad.qxdm_log: 262 qxdm_log_mask = getattr(ad, "qxdm_log_mask", None) 263 if qxdm_log_mask_cfg: 264 qxdm_mask_path = self.user_params.get("qxdm_log_path", 265 DEFAULT_QXDM_LOG_PATH) 266 ad.adb.shell("mkdir %s" % qxdm_mask_path) 267 ad.log.info("Push %s to %s", qxdm_log_mask_cfg, qxdm_mask_path) 268 ad.adb.push("%s %s" % (qxdm_log_mask_cfg, qxdm_mask_path)) 269 mask_file_name = os.path.split(qxdm_log_mask_cfg)[-1] 270 qxdm_log_mask = os.path.join(qxdm_mask_path, mask_file_name) 271 set_qxdm_logger_command(ad, mask=qxdm_log_mask) 272 start_qxdm_logger(ad, utils.get_current_epoch_time()) 273 elif ad.sdm_log: 274 start_sdm_logger(ad) 275 else: 276 disable_qxdm_logger(ad) 277 if not unlock_sim(ad): 278 raise signals.TestAbortClass("unable to unlock the SIM") 279 280 # eSIM enablement 281 if hasattr(ad, "fi_esim"): 282 if not ensure_wifi_connected(self.log, ad, self.wifi_network_ssid, 283 self.wifi_network_pass): 284 ad.log.error("Failed to connect to wifi") 285 if check_google_fi_activated(ad): 286 ad.log.info("Google Fi is already Activated") 287 else: 288 install_googleaccountutil_apk(ad, self.account_util) 289 add_google_account(ad) 290 install_googlefi_apk(ad, self.fi_util) 291 if not activate_google_fi_account(ad): 292 ad.log.error("Failed to activate Fi") 293 check_google_fi_activated(ad) 294 if hasattr(ad, "dsds"): 295 sim_mode = ad.droid.telephonyGetPhoneCount() 296 if sim_mode == 1: 297 ad.log.info("Phone in Single SIM Mode") 298 if not phone_switch_to_msim_mode(ad): 299 ad.log.error("Failed to switch to Dual SIM Mode") 300 return False 301 elif sim_mode == 2: 302 ad.log.info("Phone already in Dual SIM Mode") 303 if get_sim_state(ad) in (SIM_STATE_ABSENT, SIM_STATE_UNKNOWN): 304 ad.log.info("Device has no or unknown SIM in it") 305 # eSIM needs activation 306 activate_esim_using_suw(ad) 307 ensure_phone_idle(self.log, ad) 308 elif self.user_params.get("Attenuator"): 309 ad.log.info("Device in chamber room") 310 ensure_phone_idle(self.log, ad) 311 setup_droid_properties(self.log, ad, sim_conf_file) 312 else: 313 self.wait_for_sim_ready(ad) 314 ensure_phone_default_state(self.log, ad) 315 setup_droid_properties(self.log, ad, sim_conf_file) 316 317 default_slot = getattr(ad, "default_slot", 0) 318 if get_subid_from_slot_index(ad.log, ad, default_slot) != INVALID_SUB_ID: 319 ad.log.info("Slot %s is the default slot.", default_slot) 320 set_default_sub_for_all_services(ad, default_slot) 321 else: 322 ad.log.warning("Slot %s is NOT a valid slot. Slot %s will be used by default.", 323 default_slot, 1-default_slot) 324 set_default_sub_for_all_services(ad, 1-default_slot) 325 326 # Activate WFC on Verizon, AT&T and Canada operators as per # b/33187374 & 327 # b/122327716 328 activate_wfc_on_device(self.log, ad) 329 330 # Sub ID setup 331 initial_set_up_for_subid_infomation(self.log, ad) 332 333 # If device is setup already, skip the following setup procedures 334 if getattr(ad, "telephony_test_setup", None): 335 return True 336 337 try: 338 ad.droid.wifiEnableVerboseLogging(WIFI_VERBOSE_LOGGING_ENABLED) 339 except Exception: 340 pass 341 342 # Disable Emergency alerts 343 # Set chrome browser start with no-first-run verification and 344 # disable-fre. Give permission to read from and write to storage. 345 for cmd in ("pm disable com.android.cellbroadcastreceiver", 346 "pm grant com.android.chrome " 347 "android.permission.READ_EXTERNAL_STORAGE", 348 "pm grant com.android.chrome " 349 "android.permission.WRITE_EXTERNAL_STORAGE", 350 "rm /data/local/chrome-command-line", 351 "am set-debug-app --persistent com.android.chrome", 352 'echo "chrome --no-default-browser-check --no-first-run ' 353 '--disable-fre" > /data/local/tmp/chrome-command-line'): 354 ad.adb.shell(cmd, ignore_status=True) 355 356 # Curl for 2016/7 devices 357 if not getattr(ad, "curl_capable", False): 358 try: 359 out = ad.adb.shell("/data/curl --version") 360 if not out or "not found" in out: 361 if int(ad.adb.getprop("ro.product.first_api_level")) >= 25: 362 tel_data = self.user_params.get("tel_data", "tel_data") 363 if isinstance(tel_data, list): 364 tel_data = tel_data[0] 365 curl_file_path = os.path.join(tel_data, "curl") 366 if not os.path.isfile(curl_file_path): 367 curl_file_path = os.path.join( 368 self.user_params[Config.key_config_path.value], 369 curl_file_path) 370 if os.path.isfile(curl_file_path): 371 ad.log.info("Pushing Curl to /data dir") 372 ad.adb.push("%s /data" % (curl_file_path)) 373 ad.adb.shell( 374 "chmod 777 /data/curl", ignore_status=True) 375 else: 376 setattr(ad, "curl_capable", True) 377 except Exception: 378 ad.log.info("Failed to push curl on this device") 379 380 # Ensure that a test class starts from a consistent state that 381 # improves chances of valid network selection and facilitates 382 # logging. 383 try: 384 if not set_phone_screen_on(self.log, ad): 385 self.log.error("Failed to set phone screen-on time.") 386 return False 387 if not set_phone_silent_mode(self.log, ad): 388 self.log.error("Failed to set phone silent mode.") 389 return False 390 ad.droid.telephonyAdjustPreciseCallStateListenLevel( 391 PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND, True) 392 ad.droid.telephonyAdjustPreciseCallStateListenLevel( 393 PRECISE_CALL_STATE_LISTEN_LEVEL_RINGING, True) 394 ad.droid.telephonyAdjustPreciseCallStateListenLevel( 395 PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND, True) 396 except Exception as e: 397 self.log.error("Failure with %s", e) 398 setattr(ad, "telephony_test_setup", True) 399 return True 400 401 def _teardown_device(self, ad): 402 try: 403 stop_qxdm_logger(ad) 404 stop_sdm_logger(ad) 405 except Exception as e: 406 self.log.error("Failure with %s", e) 407 try: 408 ad.droid.disableDevicePassword() 409 except Exception as e: 410 self.log.error("Failure with %s", e) 411 if self.user_params.get("enable_connectivity_metrics", False): 412 if not ensure_wifi_connected(self.log, ad, self.wifi_network_ssid, 413 self.wifi_network_pass): 414 ad.log.error("Failed to connect to wifi") 415 force_connectivity_metrics_upload(ad) 416 time.sleep(30) 417 try: 418 ad.droid.wifiEnableVerboseLogging(WIFI_VERBOSE_LOGGING_DISABLED) 419 except Exception as e: 420 self.log.error("Failure with %s", e) 421 try: 422 if self.user_params.get("build_id_override", 423 False) and self.user_params.get( 424 "recover_build_id", False): 425 recover_build_id(ad) 426 except Exception as e: 427 self.log.error("Failure with %s", e) 428 429 def teardown_class(self): 430 tasks = [(self._teardown_device, [ad]) for ad in self.android_devices] 431 multithread_func(self.log, tasks) 432 return True 433 434 def setup_test(self): 435 if getattr(self, "qxdm_log", True): 436 if not self.user_params.get("qxdm_log_mask_cfg", None): 437 if "wfc" in self.test_name: 438 for ad in self.android_devices: 439 if not getattr(ad, "qxdm_logger_command", None) or ( 440 "IMS_DS_CNE_LnX_Golden.cfg" not in getattr( 441 ad, "qxdm_logger_command", "")): 442 set_qxdm_logger_command( 443 ad, "IMS_DS_CNE_LnX_Golden.cfg") 444 else: 445 for ad in self.android_devices: 446 if not getattr(ad, "qxdm_logger_command", None) or ( 447 "IMS_DS_CNE_LnX_Golden.cfg" in getattr( 448 ad, "qxdm_logger_command", "")): 449 set_qxdm_logger_command(ad, None) 450 start_qxdm_loggers(self.log, self.android_devices, self.begin_time) 451 if getattr(self, "sdm_log", False): 452 start_sdm_loggers(self.log, self.android_devices) 453 if getattr(self, "tcpdump_log", False) or "wfc" in self.test_name: 454 mask = getattr(self, "tcpdump_mask", "all") 455 interface = getattr(self, "tcpdump_interface", "wlan0") 456 start_tcpdumps( 457 self.android_devices, 458 begin_time=self.begin_time, 459 interface=interface, 460 mask=mask) 461 else: 462 stop_tcpdumps(self.android_devices) 463 for ad in self.android_devices: 464 if self.skip_reset_between_cases: 465 ensure_phone_idle(self.log, ad) 466 else: 467 ensure_phone_default_state(self.log, ad) 468 for session in ad._sl4a_manager.sessions.values(): 469 ed = session.get_event_dispatcher() 470 ed.clear_all_events() 471 output = ad.adb.logcat("-t 1") 472 match = re.search(r"\d+-\d+\s\d+:\d+:\d+.\d+", output) 473 if match: 474 ad.test_log_begin_time = match.group(0) 475 476 def teardown_test(self): 477 stop_tcpdumps(self.android_devices) 478 479 def on_fail(self, test_name, begin_time): 480 self._take_bug_report(test_name, begin_time) 481 482 def on_pass(self, test_name, begin_time): 483 if self.save_passing_logs: 484 self._take_bug_report(test_name, begin_time) 485 486 def _ad_take_extra_logs(self, ad, test_name, begin_time): 487 ad.adb.wait_for_device() 488 result = True 489 490 try: 491 # get tcpdump and screen shot log 492 get_tcpdump_log(ad, test_name, begin_time) 493 get_screen_shot_log(ad, test_name, begin_time) 494 except Exception as e: 495 ad.log.error("Exception error %s", e) 496 result = False 497 498 try: 499 ad.check_crash_report(test_name, begin_time, log_crash_report=True) 500 except Exception as e: 501 ad.log.error("Failed to check crash report for %s with error %s", 502 test_name, e) 503 result = False 504 505 extra_qxdm_logs_in_seconds = self.user_params.get( 506 "extra_qxdm_logs_in_seconds", 60 * 3) 507 if getattr(ad, "qxdm_log", True): 508 # Gather qxdm log modified 3 minutes earlier than test start time 509 if begin_time: 510 qxdm_begin_time = begin_time - 1000 * extra_qxdm_logs_in_seconds 511 else: 512 qxdm_begin_time = None 513 try: 514 time.sleep(10) 515 ad.get_qxdm_logs(test_name, qxdm_begin_time) 516 except Exception as e: 517 ad.log.error("Failed to get QXDM log for %s with error %s", 518 test_name, e) 519 result = False 520 if getattr(ad, "sdm_log", False): 521 # Gather sdm log modified 3 minutes earlier than test start time 522 if begin_time: 523 sdm_begin_time = begin_time - 1000 * extra_qxdm_logs_in_seconds 524 else: 525 sdm_begin_time = None 526 try: 527 time.sleep(10) 528 ad.get_sdm_logs(test_name, sdm_begin_time) 529 except Exception as e: 530 ad.log.error("Failed to get SDM log for %s with error %s", 531 test_name, e) 532 result = False 533 534 return result 535 536 def _take_bug_report(self, test_name, begin_time): 537 if self._skip_bug_report(test_name): 538 return 539 dev_num = getattr(self, "number_of_devices", None) or len( 540 self.android_devices) 541 tasks = [(self._ad_take_bugreport, (ad, test_name, begin_time)) 542 for ad in self.android_devices[:dev_num]] 543 tasks.extend([(self._ad_take_extra_logs, (ad, test_name, begin_time)) 544 for ad in self.android_devices[:dev_num]]) 545 run_multithread_func(self.log, tasks) 546 for ad in self.android_devices[:dev_num]: 547 if getattr(ad, "reboot_to_recover", False): 548 reboot_device(ad) 549 ad.reboot_to_recover = False 550 # Zip log folder 551 if not self.user_params.get("zip_log", False): return 552 src_dir = os.path.join(self.log_path, test_name) 553 os.makedirs(src_dir, exist_ok=True) 554 file_name = "%s_%s" % (src_dir, begin_time) 555 self.log.info("Zip folder %s to %s.zip", src_dir, file_name) 556 shutil.make_archive(file_name, "zip", src_dir) 557 shutil.rmtree(src_dir) 558 559 def _block_all_test_cases(self, tests, reason='Failed class setup'): 560 """Over-write _block_all_test_cases in BaseTestClass.""" 561 for (i, (test_name, test_func)) in enumerate(tests): 562 signal = signals.TestFailure(reason) 563 record = records.TestResultRecord(test_name, self.TAG) 564 record.test_begin() 565 # mark all test cases as FAIL 566 record.test_fail(signal) 567 self.results.add_record(record) 568 # only gather bug report for the first test case 569 if i == 0: 570 self.on_fail(test_name, record.begin_time) 571 572 def get_stress_test_number(self): 573 """Gets the stress_test_number param from user params. 574 575 Gets the stress_test_number param. If absent, returns default 100. 576 """ 577 return int(self.user_params.get("stress_test_number", 100)) 578