def take_bug_reports(ads, test_name=None, begin_time=None, destination=None): """Takes bug reports on a list of android devices. If you want to take a bug report, call this function with a list of android_device objects in on_fail. But reports will be taken on all the devices in the list concurrently. Bug report takes a relative long time to take, so use this cautiously. Args: ads: A list of AndroidDevice instances. test_name: Name of the test method that triggered this bug report. If None, the default name "bugreport" will be used. begin_time: timestamp taken when the test started, can be either string or int. If None, the current time will be used. destination: string, path to the directory where the bugreport should be saved. """ if begin_time is None: begin_time = mobly_logger.get_log_file_timestamp() else: begin_time = mobly_logger.sanitize_filename(str(begin_time)) def take_br(test_name, begin_time, ad, destination): ad.take_bug_report(test_name=test_name, begin_time=begin_time, destination=destination) args = [(test_name, begin_time, ad, destination) for ad in ads] utils.concurrent_exec(take_br, args)
def test_sanitize_filename_when_aux(self): for fake_filename, expected_filename in [ ('aux', 'mobly_aux'), ('AUX', 'mobly_AUX'), ('aux.txt', 'mobly_aux.txt'), ('auxiliaries.log', 'auxiliaries.log'), ]: self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def test_sanitize_filename_when_nul(self): for fake_filename, expected_filename in [ ('nul', 'mobly_nul'), ('NUL', 'mobly_NUL'), ('nul.txt', 'mobly_nul.txt'), ('nullptrs.log', 'nullptrs.log'), ]: self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def test_sanitize_filename_when_prn(self): for fake_filename, expected_filename in [ ('prn', 'mobly_prn'), ('PRN', 'mobly_PRN'), ('prn.txt', 'mobly_prn.txt'), ('prnters.log', 'prnters.log'), ]: self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def test_sanitize_filename_when_con(self): for fake_filename, expected_filename in [ ('con', 'mobly_con'), ('CON', 'mobly_CON'), ('con.txt', 'mobly_con.txt'), ('connections.log', 'connections.log'), ]: self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def _normalized_serial(self): """Normalized serial name for usage in log filename. Some Android emulators use ip:port as their serial names, while on Windows `:` is not valid in filename, it should be sanitized first. """ if self._serial is None: return None return mobly_logger.sanitize_filename(self._serial)
def cat_adb_log(self, tag, begin_time): """Takes an excerpt of the adb logcat log from a certain time point to current time. .. deprecated:: 1.10 Use :func:`create_output_excerpts` instead. Args: tag: An identifier of the time period, usualy the name of a test. begin_time: Logline format timestamp of the beginning of the time period. Returns: String, full path to the excerpt file created. """ if not self.adb_logcat_file_path: raise Error( self._ad, 'Attempting to cat adb log when none has been collected.') end_time = mobly_logger.get_log_line_timestamp() self._ad.log.debug('Extracting adb log from logcat.') adb_excerpt_path = os.path.join(self._ad.log_path, 'AdbLogExcerpts') utils.create_dir(adb_excerpt_path) out_name = '%s,%s.txt' % (tag, begin_time) out_name = mobly_logger.sanitize_filename(out_name) full_adblog_path = os.path.join(adb_excerpt_path, out_name) with io.open(full_adblog_path, 'w', encoding='utf-8') as out: in_file = self.adb_logcat_file_path with io.open(in_file, 'r', encoding='utf-8', errors='replace') as f: in_range = False while True: line = None try: line = f.readline() if not line: break except: continue line_time = line[:mobly_logger.log_line_timestamp_len] if not mobly_logger.is_valid_logline_timestamp(line_time): continue if self._is_timestamp_in_range(line_time, begin_time, end_time): in_range = True if not line.endswith('\n'): line += '\n' out.write(line) else: if in_range: break return full_adblog_path
def test_sanitize_filename_when_lpt(self): for fake_filename, expected_filename in [ ('lpt', 'lpt'), ('LPT0', 'mobly_LPT0'), ('lpt1', 'mobly_lpt1'), ('LPT2', 'mobly_LPT2'), ('lpt3', 'mobly_lpt3'), ('LPT4', 'mobly_LPT4'), ('lpt5', 'mobly_lpt5'), ('LPT6', 'mobly_LPT6'), ('lpt7', 'mobly_lpt7'), ('LPT8', 'mobly_LPT8'), ('lpt9', 'mobly_lpt9'), ('lpt3.txt', 'mobly_lpt3.txt'), ('lpt3_file.txt', 'lpt3_file.txt'), ]: self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def test_sanitize_filename_when_com(self): for fake_filename, expected_filename in [ ('com', 'com'), ('COM0', 'mobly_COM0'), ('com1', 'mobly_com1'), ('COM2', 'mobly_COM2'), ('com3', 'mobly_com3'), ('COM4', 'mobly_COM4'), ('com5', 'mobly_com5'), ('COM6', 'mobly_COM6'), ('com7', 'mobly_com7'), ('COM8', 'mobly_COM8'), ('com9', 'mobly_com9'), ('com0.log', 'mobly_com0.log'), ('com0files.log', 'com0files.log'), ]: self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def generate_filename(self, file_type, time_identifier=None, extension_name=None): """Generates a name for an output file related to this device. The name follows the pattern: {file type},{debug_tag},{serial},{model},{time identifier}.{ext} "debug_tag" is only added if it's different from the serial. "ext" is added if specified by user. Args: file_type: string, type of this file, like "logcat" etc. time_identifier: string or RuntimeTestInfo. If a `RuntimeTestInfo` is passed in, the `signature` of the test case will be used. If a string is passed in, the string itself will be used. Otherwise the current timestamp will be used. extension_name: string, the extension name of the file. Returns: String, the filename generated. """ time_str = time_identifier if time_identifier is None: time_str = mobly_logger.get_log_file_timestamp() elif isinstance(time_identifier, runtime_test_info.RuntimeTestInfo): time_str = time_identifier.signature filename_tokens = [file_type] if self.debug_tag != self.serial: filename_tokens.append(self.debug_tag) filename_tokens.extend([self.serial, self.model, time_str]) filename_str = ','.join(filename_tokens) if extension_name is not None: filename_str = '%s.%s' % (filename_str, extension_name) filename_str = mobly_logger.sanitize_filename(filename_str) self.log.debug('Generated filename: %s', filename_str) return filename_str
def test_sanitize_filename_when_over_max_characters(self): fake_filename = 'l' * 300 expected_filename = 'l' * 237 self.assertEqual(len(logger.sanitize_filename(fake_filename)), 237) self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def test_sanitize_filename_when_random_spaces(self): fake_filename = 'log cat file.txt' expected_filename = 'log_cat_file.txt' self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def test_sanitize_filename_when_valid_with_path(self): fake_filename = os.path.join('dir', 'logs', 'logcat.txt') expected_filename = os.path.join('dir', 'logs', 'logcat.txt') self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def test_sanitize_filename_when_valid(self): fake_filename = 'logcat.txt' expected_filename = 'logcat.txt' self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def test_sanitize_filename_when_extension_at_max_characters(self): fake_filename = 'l' * 300 + '.' + 't' * 236 expected_filename = '.' + 't' * 236 self.assertEqual(len(logger.sanitize_filename(fake_filename)), 237) self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def test_sanitize_filename_when_specical_characters(self): fake_filename = '<>:"|?*\x00' expected_filename = '---_,,,0' self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def test_sanitize_filename_when_ends_with_period(self): fake_filename = 'logcat.txt.' expected_filename = 'logcat.txt_' self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)
def test_sanitize_filename_when_over_max_characters_with_extension(self): fake_filename = 'l' * 300 + '.txt' expected_filename = 'l' * 233 + '.txt' self.assertEqual(len(logger.sanitize_filename(fake_filename)), 237) self.assertEqual(logger.sanitize_filename(fake_filename), expected_filename)