def take_bug_report(self, test_name=None, begin_time=None, timeout=300, destination=None): """Takes a bug report on the device and stores it in a file. Args: test_name: Name of the test method that triggered this bug report. begin_time: Timestamp of when the test started. If not set, then this will default to the current time. timeout: float, the number of seconds to wait for bugreport to complete, default is 5min. destination: string, path to the directory where the bugreport should be saved. Returns: A string that is the absolute path to the bug report on the host. """ prefix = DEFAULT_BUG_REPORT_NAME if test_name: prefix = '%s,%s' % (DEFAULT_BUG_REPORT_NAME, test_name) if begin_time is None: begin_time = mobly_logger.get_log_file_timestamp() new_br = True try: stdout = self.adb.shell('bugreportz -v').decode('utf-8') # This check is necessary for builds before N, where adb shell's ret # code and stderr are not propagated properly. if 'not found' in stdout: new_br = False except adb.AdbError: new_br = False if destination is None: destination = os.path.join(self.log_path, 'BugReports') br_path = utils.abs_path(destination) utils.create_dir(br_path) filename = self.generate_filename(prefix, str(begin_time), 'txt') if new_br: filename = filename.replace('.txt', '.zip') full_out_path = os.path.join(br_path, filename) # in case device restarted, wait for adb interface to return self.wait_for_boot_completion() self.log.debug('Start taking bugreport.') if new_br: out = self.adb.shell('bugreportz', timeout=timeout).decode('utf-8') if not out.startswith('OK'): raise DeviceError(self, 'Failed to take bugreport: %s' % out) br_out_path = out.split(':')[1].strip() self.adb.pull([br_out_path, full_out_path]) else: # shell=True as this command redirects the stdout to a local file # using shell redirection. self.adb.bugreport(' > "%s"' % full_out_path, shell=True, timeout=timeout) self.log.debug('Bugreport taken at %s.', full_out_path) return full_out_path
def load_test_config_file(test_config_path, tb_filters=None): """Processes the test configuration file provied by user. Loads the configuration file into a dict, unpacks each testbed config into its own dict, and validate the configuration in the process. Args: test_config_path: Path to the test configuration file. tb_filters: A subset of test bed names to be pulled from the config file. If None, then all test beds will be selected. Returns: A list of test configuration dicts to be passed to test_runner.TestRunner. """ configs = _load_config_file(test_config_path) if tb_filters: tbs = [] for tb in configs[keys.Config.key_testbed.value]: if tb[keys.Config.key_testbed_name.value] in tb_filters: tbs.append(tb) if len(tbs) != len(tb_filters): raise MoblyConfigError( 'Expect to find %d test bed configs, found %d. Check if' ' you have the correct test bed names.' % (len(tb_filters), len(tbs))) configs[keys.Config.key_testbed.value] = tbs mobly_params = configs.get(keys.Config.key_mobly_params.value, {}) # Decide log path. log_path = mobly_params.get(keys.Config.key_log_path.value, _DEFAULT_LOG_PATH) if ENV_MOBLY_LOGPATH in os.environ: log_path = os.environ[ENV_MOBLY_LOGPATH] log_path = utils.abs_path(log_path) # Validate configs _validate_test_config(configs) _validate_testbed_configs(configs[keys.Config.key_testbed.value]) # Transform config dict from user-facing key mapping to internal config object. test_configs = [] for original_bed_config in configs[keys.Config.key_testbed.value]: test_run_config = TestRunConfig() test_run_config.testbed_name = original_bed_config[ keys.Config.key_testbed_name.value] # Deprecated, use testbed_name test_run_config.test_bed_name = test_run_config.testbed_name test_run_config.log_path = log_path test_run_config.controller_configs = original_bed_config.get( keys.Config.key_testbed_controllers.value, {}) test_run_config.user_params = original_bed_config.get( keys.Config.key_testbed_test_params.value, {}) test_configs.append(test_run_config) return test_configs
def take_bug_report(self, test_name, begin_time, timeout=300, destination=None): """Takes a bug report on the device and stores it in a file. Args: test_name: Name of the test method that triggered this bug report. begin_time: Timestamp of when the test started. timeout: float, the number of seconds to wait for bugreport to complete, default is 5min. destination: string, path to the directory where the bugreport should be saved. """ new_br = True try: stdout = self.adb.shell('bugreportz -v').decode('utf-8') # This check is necessary for builds before N, where adb shell's ret # code and stderr are not propagated properly. if 'not found' in stdout: new_br = False except adb.AdbError: new_br = False if destination: br_path = utils.abs_path(destination) else: br_path = os.path.join(self.log_path, 'BugReports') utils.create_dir(br_path) base_name = ',%s,%s.txt' % (begin_time, self._normalized_serial) if new_br: base_name = base_name.replace('.txt', '.zip') test_name_len = utils.MAX_FILENAME_LEN - len(base_name) out_name = test_name[:test_name_len] + base_name full_out_path = os.path.join(br_path, out_name.replace(' ', r'\ ')) # in case device restarted, wait for adb interface to return self.wait_for_boot_completion() self.log.info('Taking bugreport for %s.', test_name) if new_br: out = self.adb.shell('bugreportz', timeout=timeout).decode('utf-8') if not out.startswith('OK'): raise DeviceError(self, 'Failed to take bugreport: %s' % out) br_out_path = out.split(':')[1].strip() self.adb.pull([br_out_path, full_out_path]) else: # shell=True as this command redirects the stdout to a local file # using shell redirection. self.adb.bugreport(' > "%s"' % full_out_path, shell=True, timeout=timeout) self.log.info('Bugreport for %s taken at %s.', test_name, full_out_path)
def _load_config_file(path): """Loads a test config file. The test config file has to be in YAML format. Args: path: A string that is the full path to the config file, including the file name. Returns: A dict that represents info in the config file. """ with open(utils.abs_path(path), 'r') as f: conf = yaml.load(f) return conf
def load_test_config_file(test_config_path, tb_filters=None): """Processes the test configuration file provied by user. Loads the configuration file into a json object, unpacks each testbed config into its own json object, and validate the configuration in the process. Args: test_config_path: Path to the test configuration file. tb_filters: A subset of test bed names to be pulled from the config file. If None, then all test beds will be selected. Returns: A list of test configuration json objects to be passed to test_runner.TestRunner. """ configs = utils.load_config(test_config_path) if tb_filters: tbs = [] for tb in configs[keys.Config.key_testbed.value]: if tb[keys.Config.key_testbed_name.value] in tb_filters: tbs.append(tb) if len(tbs) != len(tb_filters): raise MoblyConfigError( ("Expect to find %d test bed configs, found %d. Check if" " you have the correct test bed names.") % (len(tb_filters), len(tbs))) configs[keys.Config.key_testbed.value] = tbs if (not keys.Config.key_log_path.value in configs and _ENV_MOBLY_LOGPATH in os.environ): print('Using environment log path: %s' % (os.environ[_ENV_MOBLY_LOGPATH])) configs[keys.Config.key_log_path.value] = os.environ[_ENV_MOBLY_LOGPATH] if (not keys.Config.key_test_paths.value in configs and _ENV_MOBLY_TESTPATHS in os.environ): print('Using environment test paths: %s' % (os.environ[_ENV_MOBLY_TESTPATHS])) configs[keys.Config.key_test_paths.value] = os.environ[ _ENV_MOBLY_TESTPATHS].split(_PATH_SEPARATOR) _validate_test_config(configs) _validate_testbed_configs(configs[keys.Config.key_testbed.value]) k_log_path = keys.Config.key_log_path.value configs[k_log_path] = utils.abs_path(configs[k_log_path]) config_path, _ = os.path.split(utils.abs_path(test_config_path)) configs[keys.Config.key_config_path] = config_path tps = configs[keys.Config.key_test_paths.value] # Unpack testbeds into separate json objects. beds = configs.pop(keys.Config.key_testbed.value) config_jsons = [] # TODO: See if there is a better way to do this: b/29836695 config_path, _ = os.path.split(utils.abs_path(test_config_path)) configs[keys.Config.key_config_path] = config_path for original_bed_config in beds: new_test_config = dict(configs) new_test_config[keys.Config.key_testbed.value] = original_bed_config # Keys in each test bed config will be copied to a level up to be # picked up for user_params. If the key already exists in the upper # level, the local one defined in test bed config overwrites the # general one. new_test_config.update(original_bed_config) config_jsons.append(new_test_config) return config_jsons
def __init__(self, test_name, log_path, record): self._name = test_name self._record = record self._signature = '%s-%s' % (test_name, record.begin_time) self._output_dir_path = utils.abs_path( os.path.join(log_path, self._signature))
def __init__(self, test_name, log_path, record): self._name = test_name self._record = record self._output_dir_path = utils.abs_path( os.path.join(log_path, self._record.signature))