def _pull_diag_logs(self, test_name, begin_time): for (logger, session) in self.logger_sessions: self.log.info("Pulling diagnostic session {}".format(logger)) logger.stop(session) diag_path = os.path.join(self.log_path, begin_time) utils.create_dir(diag_path) logger.pull(session, diag_path)
def take_btsnoop_log(ad, testcase, testname): """Grabs the btsnoop_hci log on a device and stores it in the log directory of the test class. If you want grab the btsnoop_hci log, call this function with android_device objects in on_fail. Bug report takes a relative long time to take, so use this cautiously. Args: ad: The android_device instance to take bugreport on. testcase: Name of the test calss that triggered this snoop log. testname: Name of the test case that triggered this bug report. """ testname = "".join(x for x in testname if x.isalnum()) serial = ad.droid.getBuildSerial() device_model = ad.droid.getBuildModel() device_model = device_model.replace(" ", "") out_name = ','.join((testname, device_model, serial)) snoop_path = ad.log_path + "/BluetoothSnoopLogs" utils.create_dir(snoop_path) cmd = ''.join(("adb -s ", serial, " pull /sdcard/btsnoop_hci.log ", snoop_path + '/' + out_name, ".btsnoop_hci.log")) testcase.log.info( "Test failed, grabbing the bt_snoop logs on {} {}.".format( device_model, serial)) exe_cmd(cmd)
def _take_bug_report(self, test_name, begin_time): test_log_path = os.path.join(self.log_path, test_name) utils.create_dir(test_log_path) # Extract test_run_info.txt, test_run_detail.txt for file_name in ("test_run_info.txt", "test_run_details.txt"): extract_test_log( self.log, os.path.join(self.log_path, file_name), os.path.join(test_log_path, "%s_%s" % (test_name, file_name)), "\[Test Case\] %s " % test_name) if self._skip_bug_report(): return dev_num = getattr(self, "number_of_devices", None) or len( self.android_devices) tasks = [(self._ad_take_bugreport, (ad, test_name, begin_time)) for ad in self.android_devices[:dev_num]] tasks.extend([(self._ad_take_extra_logs, (ad, test_name, begin_time)) for ad in self.android_devices[:dev_num]]) run_multithread_func(self.log, tasks) for ad in self.android_devices[:dev_num]: if getattr(ad, "reboot_to_recover", False): reboot_device(ad) ad.reboot_to_recover = False # Zip log folder if not self.user_params.get("zip_log", False): return src_dir = os.path.join(self.log_path, test_name) file_name = "%s_%s" % (src_dir, begin_time) self.log.info("Zip folder %s to %s.zip", src_dir, file_name) shutil.make_archive(file_name, "zip", src_dir) shutil.rmtree(src_dir)
def __init__(self, profile, password, log_path): devices = {} self.device_interface = False self.mainloop = 0 self.property_changed = False self.bd_address = None self.list_daemon = ["dbus", "bluez"] self.log_path = os.path.join(log_path, "bluez") create_dir(self.log_path) self.sudo_command = "echo " + password + " | sudo -S " if profile.lower() == "hfp": self.list_daemon.append("ofonod") elif profile.lower() == "a2dp": self.list_daemon.append("pulseaudio") elif profile.lower() == "multiprofile": self.list_daemon.extend(["pulseaudio", "ofonod"]) if not self.hci_config("up"): logging.error("Can't get device info: No such device") self.run_daemons() self.bus = dbus.SystemBus() self.bus.add_signal_receiver( self.properties_changed, dbus_interface=DBUS_INTERFACE, signal_name=PROPERTIES_CHANGED, arg0=DEVICE_INTERFACE, path_keyword="path") self.om = dbus.Interface( self.bus.get_object(SERVICE_NAME, "/"), OBJECT_MANGER) objects = self.om.GetManagedObjects() for path, interfaces in objects.items(): if ADAPTER_INTERFACE in interfaces: devices[path] = interfaces[ADAPTER_INTERFACE] self.adapter = self.find_adapter(0)
def take_bug_report(self, test_name, begin_time): """Takes a bug report on the device and stores it in a file. Args: test_name: Name of the test case that triggered this bug report. begin_time: Logline format timestamp taken when the test started. """ new_br = True try: self.adb.shell("bugreportz -v") except adb.AdbError: new_br = False br_path = os.path.join(self.log_path, "BugReports") utils.create_dir(br_path) base_name = ",{},{}.txt".format(begin_time, self.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(' ', '\ ')) # 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").decode("utf-8") if not out.startswith("OK"): raise AndroidDeviceError("Failed to take bugreport on %s" % self.serial) br_out_path = out.split(':')[1].strip() self.adb.pull("%s %s" % (br_out_path, full_out_path)) else: self.adb.bugreport(" > {}".format(full_out_path)) self.log.info("Bugreport for %s taken at %s.", test_name, full_out_path)
def start(self, iperf_args, ad, ip): """Starts iperf client on specified port. Args: iperf_args: A string representing arguments to start iperf client. Eg: iperf_args = "-t 10 -p 5001 -w 512k/-u -b 200M -J". ad: Android device object. ip: Iperf server ip address. Returns: full_out_path: Iperf result path. """ iperf_cmd = "iperf3 -c {} ".format(ip) + iperf_args port = iperf_cmd.split(' ')[6] log_path = os.path.join(ad.log_path, "iPerf{}".format(port)) utils.create_dir(log_path) out_file_name = "IPerfClient,{},{}.log".format(port, len(self.log_files)) full_out_path = os.path.join(log_path, out_file_name) if self.client_type == "remote": try: job_result = self.ssh_session.run(iperf_cmd) self.iperf_process = job_result.stdout with open(full_out_path, 'w') as outfile: outfile.write(self.iperf_process) except Exception: logging.info("Iperf run failed.") else: cmd = iperf_cmd.split() with open(full_out_path, "w") as f: subprocess.call(cmd, stdout=f) self.log_files.append(full_out_path) return full_out_path
def setup_class(self): """ This method finds bluetooth protobuf definitions from config file, compile the protobuf and create a log directory for metrics dumping :return: True on success, False on failure """ super(BtMetricsBaseTest, self).setup_class() self.bluetooth_proto_path = self.user_params["bluetooth_proto_path"] if not os.path.isfile(self.bluetooth_proto_path): try: self.bluetooth_proto_path = "{}/bluetooth.proto".format( os.path.dirname(os.path.realpath(__file__))) except Exception: self.log.error("File not found.") if not os.path.isfile(self.bluetooth_proto_path): self.log.error("Unable to find Bluetooth proto {}.".format( self.bluetooth_proto_path)) return False for ad in self.android_devices: ad.metrics_path = os.path.join(ad.log_path, "BluetoothMetrics") create_dir(ad.metrics_path) ad.bluetooth_proto_module = \ compile_import_proto(ad.metrics_path, self.bluetooth_proto_path) if not ad.bluetooth_proto_module: self.log.error("Unable to compile bluetooth proto at " + self.bluetooth_proto_path) return False return True
def __init__(self, config, log_path): self.server_type = "local" self.port = config self.log_path = os.path.join(log_path, "iPerf{}".format(self.port)) utils.create_dir(self.log_path) self.iperf_str = "iperf3 -s -J -p {}".format(self.port) self.log_files = [] self.started = False
def _pull_diag_logs(self, test_name, begin_time): for (mylogger, session) in self.logger_sessions: self.log.info("Pulling diagnostic session %s", mylogger) mylogger.stop(session) diag_path = os.path.join( self.log_path, logger.epoch_to_log_line_timestamp(begin_time)) utils.create_dir(diag_path) mylogger.pull(session, diag_path)
def get_qxdm_logs(self): """Get qxdm logs.""" ad.log.info("Pull QXDM Logs") qxdm_logs = self.get_file_names( "/data/vendor/radio/diag_logs/logs/*.qmdl") if qxdm_logs: qxdm_path = os.path.join(ad.log_path, "QXDM_Logs") utils.create_dir(qxdm_path) ad.pull_files(qxdm_logs, qxdm_path)
def __init__(self, controllers): BtFunhausBaseTest.__init__(self, controllers) self.chameleon = self.chameleon_devices[0] self.dut = self.android_devices[0] self.raw_audio_dest = "{}/{}".format(self.android_devices[0].log_path, "Chameleon_audio") utils.create_dir(self.raw_audio_dest) self.chameleon.audio_board_connect(1, headphone_bus_endpoint) self.chameleon.audio_board_connect(1, fpga_linein_bus_endpoint) time.sleep(delay_after_binding_seconds)
def _collect_bluetooth_manager_dumpsys_logs(self, ads): for ad in ads: serial = ad.serial out_name = "{}_{}".format(serial, "bluetooth_dumpsys.txt") dumpsys_path = ''.join((ad.log_path, "/BluetoothDumpsys")) create_dir(dumpsys_path) cmd = ''.join( ("adb -s ", serial, " shell dumpsys bluetooth_manager > ", dumpsys_path, "/", out_name)) exe_cmd(cmd)
def __init__(self, config, log_path): self.server_type = "remote" self.ssh_settings = settings.from_config(config["ssh_config"]) self.ssh_session = connection.SshConnection(self.ssh_settings) self.port = config["port"] self.log_path = os.path.join(log_path, "iPerf{}".format(self.port)) utils.create_dir(self.log_path) self.iperf_str = "iperf3 -s -J -p {}".format(self.port) self.log_files = [] self.started = False
def _ad_take_reports(self, ad, test_name, begin_time): try: ad.take_bug_report(test_name, begin_time) bugreport_path = os.path.join(ad.log_path, test_name) utils.create_dir(bugreport_path) ad.check_crash_report(test_name, begin_time, True) if getattr(ad, "qxdm_always_on", False): ad.get_qxdm_logs() except Exception as e: ad.log.error("Failed to take a bug report for %s with error %s", test_name, e)
def __init__(self, config, log_path): # Note: skip_sl4a must be set to True in iperf server config since # ACTS may have already initialized and started services on device self.server_type = "adb" self.adb_device = android_device.create(config["AndroidDevice"]) self.adb_device = self.adb_device[0] self.adb_log_path = "~/data" self.port = config["port"] self.log_path = os.path.join(log_path, "iPerf{}".format(self.port)) utils.create_dir(self.log_path) self.iperf_str = "iperf3 -s -J -p {}".format(self.port) self.log_files = [] self.started = False
def setup_test_logger(log_path, prefix=None, filename=None): """Customizes the root logger for a test run. Args: log_path: Location of the report file. prefix: A prefix for each log line in terminal. filename: Name of the files. The default is the time the objects are requested. """ if filename is None: filename = get_log_file_timestamp() create_dir(log_path) logger = _setup_test_logger(log_path, prefix, filename) create_latest_log_alias(log_path)
def _collect_bluetooth_manager_dumpsys_logs(self, ads): """ Collect "adb shell dumpsys bluetooth_manager" logs :param ads: list of active Android devices :return: None """ for ad in ads: serial = ad.serial out_name = "{}_{}".format(serial, "bluetooth_dumpsys.txt") dumpsys_path = ''.join((ad.log_path, "/BluetoothDumpsys")) create_dir(dumpsys_path) cmd = ''.join( ("adb -s ", serial, " shell dumpsys bluetooth_manager > ", dumpsys_path, "/", out_name)) exe_cmd(cmd)
def setup_class(self): self.dut = self.android_devices[0] req_params = ["rssi_test_params", "testbed_params", "main_network"] opt_params = ["RetailAccessPoints"] self.unpack_userparams(req_params, opt_params) self.test_params = self.rssi_test_params self.num_atten = self.attenuators[0].instrument.num_atten self.iperf_server = self.iperf_servers[0] self.access_points = retail_ap.create(self.RetailAccessPoints) self.access_point = self.access_points[0] self.log_path = os.path.join(logging.log_path, "results") utils.create_dir(self.log_path) self.log.info("Access Point Configuration: {}".format( self.access_point.ap_settings)) self.testclass_results = []
def test_check_crash(self): msg = "" for ad in self.android_devices: post_crash = ad.check_crash_report(self.test_id, None, False) pre_crash = getattr(ad, "crash_report_preflight", []) crash_diff = list(set(post_crash).difference(set(pre_crash))) if crash_diff: msg += "%s find new crash reports %s" % (ad.serial, crash_diff) ad.log.error("Find new crash reports %s", crash_diff) crash_path = os.path.join(ad.log_path, self.test_id, "Crashes") utils.create_dir(crash_path) ad.pull_files(crash_diff, crash_path) if msg: fail(msg) return True
def cat_adb_log(self, tag, begin_time): """Takes an excerpt of the adb logcat log from a certain time point to current time. 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. """ if not self.adb_logcat_file_path: raise AndroidDeviceError( ("Attempting to cat adb log when none has" " been collected on Android device %s.") % self.serial) end_time = acts_logger.get_log_line_timestamp() self.log.debug("Extracting adb log from logcat.") adb_excerpt_path = os.path.join(self.log_path, "AdbLogExcerpts") utils.create_dir(adb_excerpt_path) f_name = os.path.basename(self.adb_logcat_file_path) out_name = f_name.replace("adblog,", "").replace(".txt", "") out_name = ",{},{}.txt".format(begin_time, out_name) tag_len = utils.MAX_FILENAME_LEN - len(out_name) tag = tag[:tag_len] out_name = tag + out_name full_adblog_path = os.path.join(adb_excerpt_path, out_name) with open(full_adblog_path, 'w', encoding='utf-8') as out: in_file = self.adb_logcat_file_path with 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[:acts_logger.log_line_timestamp_len] if not acts_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
def _setup_test_logger(log_path, prefix=None, filename=None): """Customizes the root logger for a test run. The logger object has a stream handler and a file handler. The stream handler logs INFO level to the terminal, the file handler logs DEBUG level to files. Args: log_path: Location of the log file. prefix: A prefix for each log line in terminal. filename: Name of the log file. The default is the time the logger is requested. """ log = logging.getLogger() kill_test_logger(log) log.propagate = False log.setLevel(logging.DEBUG) # Log info to stream terminal_format = log_line_format if prefix: terminal_format = "[{}] {}".format(prefix, log_line_format) c_formatter = logging.Formatter(terminal_format, log_line_time_format) ch = logging.StreamHandler(sys.stdout) ch.setFormatter(c_formatter) ch.setLevel(logging.INFO) # Log everything to file f_formatter = logging.Formatter(log_line_format, log_line_time_format) # All the logs of this test class go into one directory if filename is None: filename = get_log_file_timestamp() create_dir(log_path) fh = logging.FileHandler(os.path.join(log_path, 'test_run_details.txt')) fh.setFormatter(f_formatter) fh.setLevel(logging.DEBUG) fh_info = logging.FileHandler(os.path.join(log_path, 'test_run_info.txt')) fh_info.setFormatter(f_formatter) fh_info.setLevel(logging.INFO) fh_error = logging.FileHandler(os.path.join(log_path, 'test_run_error.txt')) fh_error.setFormatter(f_formatter) fh_error.setLevel(logging.WARNING) log.addHandler(ch) log.addHandler(fh) log.addHandler(fh_info) log.addHandler(fh_error) log.log_path = log_path logging.log_path = log_path
def test_check_dialer_crash(self): msg = "" for ad in self.android_devices: tombstones = ad.get_file_names("/data/tombstones/") if not tombstones: continue for tombstone in tombstones: if ad.adb.shell("cat %s | grep pid | grep dialer" % tombstone): message = "%s dialer crash: %s " % (ad.serial, tombstone) ad.log.error(message) msg += message crash_path = os.path.join(ad.log_path, self.test_name, "Crashes") utils.create_dir(crash_path) ad.pull_files([tombstone], crash_path) if msg: fail(msg) return True
def save_to_text_file(monsoon_data, file_path): """Save multiple MonsoonData objects to a text file. Args: monsoon_data: A list of MonsoonData objects to write to a text file. file_path: The full path of the file to save to, including the file name. """ if not monsoon_data: raise MonsoonError("Attempting to write empty Monsoon data to " "file, abort") utils.create_dir(os.path.dirname(file_path)) with open(file_path, 'w') as f: for md in monsoon_data: f.write(str(md)) f.write(MonsoonData.delimiter)
def _take_bug_report(self, test_name, begin_time): if "no_bug_report_on_fail" in self.user_params: return # magical sleep to ensure the runtime restart or reboot begins time.sleep(1) for ad in self.android_devices: try: ad.adb.wait_for_device() ad.take_bug_report(test_name, begin_time) tombstone_path = os.path.join(ad.log_path, "BugReports", "{},{}".format(begin_time, ad.serial).replace(' ','_')) utils.create_dir(tombstone_path) ad.adb.pull('/data/tombstones/', tombstone_path) except: self.log.error("Failed to take a bug report for {}, {}" .format(ad.serial, test_name))
def _get_test_logger(log_path, TAG, prefix=None, filename=None): """Returns a logger object used for tests. The logger object has a stream handler and a file handler. The stream handler logs INFO level to the terminal, the file handler logs DEBUG level to files. Args: log_path: Location of the log file. TAG: Name of the logger's owner. prefix: A prefix for each log line in terminal. filename: Name of the log file. The default is the time the logger is requested. Returns: A logger configured with one stream handler and one file handler """ log = logging.getLogger(TAG) if log.handlers: # This logger has been requested before. return log log.propagate = False log.setLevel(logging.DEBUG) # Log info to stream terminal_format = log_line_format if prefix: terminal_format = "[{}] {}".format(prefix, log_line_format) c_formatter = logging.Formatter(terminal_format, log_line_time_format) ch = logging.StreamHandler(sys.stdout) ch.setFormatter(c_formatter) ch.setLevel(logging.INFO) # Log everything to file f_formatter = logging.Formatter(log_line_format, log_line_time_format) # All the logs of this test class go into one directory if filename is None: filename = get_log_file_timestamp() create_dir(log_path) fh = logging.FileHandler(os.path.join(log_path, 'test_run_details.txt')) fh.setFormatter(f_formatter) fh.setLevel(logging.DEBUG) log.addHandler(ch) log.addHandler(fh) log.log_path = log_path return log
def setup_class(self): # Not to call Base class setup_class() # since it removes the bonded devices for ad in self.android_devices: sync_device_time(ad) self.ad = self.android_devices[0] self.mon = self.monsoons[0] self.mon.set_voltage(self.MONSOON_OUTPUT_VOLTAGE) self.mon.set_max_current(self.MONSOON_MAX_CURRENT) # Monsoon phone self.mon.attach_device(self.ad) self.monsoon_log_path = os.path.join(self.log_path, "MonsoonLog") create_dir(self.monsoon_log_path) asserts.assert_true(self.mon.usb("auto"), "Failed to turn USB mode to auto on monsoon.") asserts.assert_true( force_airplane_mode(self.ad, True), "Can not turn on airplane mode on: %s" % self.ad.serial) asserts.assert_true(bluetooth_enabled_check(self.ad), "Failed to set Bluetooth state to enabled") set_location_service(self.ad, False) set_adaptive_brightness(self.ad, False) set_ambient_display(self.ad, False) self.ad.adb.shell("settings put system screen_brightness 0") set_auto_rotate(self.ad, False) set_phone_screen_on(self.log, self.ad, self.SCREEN_TIME_OFF) wutils.wifi_toggle_state(self.ad, False) # Start PMC app. self.log.info("Start PMC app...") self.ad.adb.shell(self.START_PMC_CMD) self.ad.adb.shell(self.PMC_VERBOSE_CMD) self.log.info("Check to see if PMC app started") for _ in range(self.WAIT_TIME): time.sleep(1) try: self.ad.adb.shell('ps -A | grep "S com.android.pmc"') break except adb.AdbError as e: self.log.info("PMC app is NOT started yet")
def get_test_logger(log_path, TAG, prefix=None, filename=None): """Returns a logger customized for a test run. Args: log_path: Location of the report file. TAG: Name of the logger's owner. prefix: A prefix for each log line in terminal. filename: Name of the files. The default is the time the objects are requested. Returns: A logger object. """ if filename is None: filename = get_log_file_timestamp() create_dir(log_path) logger = _get_test_logger(log_path, TAG, prefix, filename) create_latest_log_alias(log_path) return logger
def start_iperf_server_on_shell(self, server_port): """Starts iperf server on android device with specified. Args: server_port: Port in which server should be started. """ log_path = os.path.join(self.pri_ad.log_path, "iPerf{}".format(server_port)) iperf_server = "iperf3 -s -p {} -J".format(server_port) create_dir(log_path) out_file_name = "IPerfServer,{},{},{}.log".format( server_port, self.tag, len(self.log_files)) self.tag = self.tag + 1 self.iperf_server_path = os.path.join(log_path, out_file_name) cmd = "adb -s {} shell {} > {}".format(self.pri_ad.serial, iperf_server, self.iperf_server_path) self.iperf_process.append(start_standing_subprocess(cmd)) self.log_files.append(self.iperf_server_path) time.sleep(IPERF_SERVER_WAIT_TIME)
def start(self, extra_args="", tag=""): """Starts iperf server on specified port. Args: extra_args: A string representing extra arguments to start iperf server with. tag: Appended to log file name to identify logs from different iperf runs. """ if self.started: return create_dir(self.log_path) self.exec_count += 1 if tag: tag = tag + ',' out_file_name = "IPerfServer,{},{}{}.log".format( self.port, tag, self.exec_count) full_out_path = os.path.join(self.log_path, out_file_name) cmd = "{} {} > {}".format(self.iperf_str, extra_args, full_out_path) self.iperf_process = start_standing_subprocess(cmd) self.started = True
def start_adb_logcat(self): """Starts a standing adb logcat collection in separate subprocesses and save the logcat in a file. """ if self.is_adb_logcat_on: raise AndroidDeviceError(("Android device {} already has an adb " "logcat thread going on. Cannot start " "another one.").format(self.serial)) # Disable adb log spam filter. self.adb.shell("logpersist.start --clear") f_name = "adblog,{},{}.txt".format(self.model, self.serial) utils.create_dir(self.log_path) logcat_file_path = os.path.join(self.log_path, f_name) try: extra_params = self.adb_logcat_param except AttributeError: extra_params = "-b all" cmd = "adb -s {} logcat -v threadtime {} >> {}".format( self.serial, extra_params, logcat_file_path) self.adb_logcat_process = utils.start_standing_subprocess(cmd) self.adb_logcat_file_path = logcat_file_path