def CallVtableDumper(self, lib_path): """Calls vndk-vtable-dumper and returns its output. Args: lib_path: The host-side path to the library. Returns: A string which is the output of vndk-vtable-dumper Raises: VtableError if the command fails. """ bin_dir = os.path.join(self._dumper_path, "bin") if not utils.is_on_windows(): bin_path = os.path.join(bin_dir, self.VNDK_VTABLE_DUMPER) cmd = "%s %s -mangled" % (bin_path, lib_path) else: bin_path = os.path.join(bin_dir, self.VNDK_VTABLE_DUMPER_EXE) dll_dir = os.path.join(self._dumper_path, "lib") cmd = 'set "PATH=%s;%%PATH%%" && %s %s -mangled' % ( dll_dir, bin_path, lib_path) logging.debug("Execute command: %s" % cmd) stdout, stderr, exit_code = cmd_utils.ExecuteOneShellCommand(cmd) logging.debug("stdout: " + stdout) logging.debug("stderr: " + stderr) if exit_code: raise VtableError("command: %s\n" "exit code: %s\n" "stdout: %s\n" "stderr: %s" % (cmd, exit_code, stdout, stderr)) return stdout
def runTestClass(test_class): """Execute one test class. This will create a TestRunner, execute one test run with one test class. Args: test_class: The test class to instantiate and execute. Returns: The TestResult object that holds the results of the test run. """ test_cls_name = test_class.__name__ if len(sys.argv) < 2: logging.warning("Missing a configuration file. Using the default.") test_configs = [config_parser.GetDefaultConfig(test_cls_name)] else: try: config_path = sys.argv[1] baseline_config = config_parser.GetDefaultConfig(test_cls_name) baseline_config[keys.ConfigKeys.KEY_TESTBED] = [ baseline_config[keys.ConfigKeys.KEY_TESTBED] ] test_configs = config_parser.load_test_config_file( config_path, baseline_config=baseline_config) except IndexError: logging.error("No valid config file found.") sys.exit(1) test_identifiers = [(test_cls_name, None)] for config in test_configs: if keys.ConfigKeys.KEY_TEST_MAX_TIMEOUT in config: timeout_sec = int( config[keys.ConfigKeys.KEY_TEST_MAX_TIMEOUT]) / 1000.0 else: timeout_sec = 60 * 60 * 3 logging.warning("%s unspecified. Set timeout to %s seconds.", keys.ConfigKeys.KEY_TEST_MAX_TIMEOUT, timeout_sec) # The default SIGINT handler sends KeyboardInterrupt to main thread. # On Windows, raising CTRL_C_EVENT, which is received as SIGINT, # has no effect on non-console process. interrupt_main() works but # does not unblock main thread's IO immediately. timeout_func = (raiseSigint if not utils.is_on_windows() else thread.interrupt_main) sig_timer = threading.Timer(timeout_sec, timeout_func) tr = TestRunner(config, test_identifiers) tr.parseTestConfig(config) try: sig_timer.start() tr.runTestClass(test_class, None) except KeyboardInterrupt as e: logging.exception("Aborted by timeout or ctrl+C: %s", e) finally: sig_timer.cancel() tr.stop() return tr.results
def __init__(self, dumper_path): """Initializes the dumper path and its permission.""" self._dumper_path = dumper_path if not utils.is_on_windows(): bin_path = os.path.join(self._dumper_path, "bin", self.VNDK_VTABLE_DUMPER) try: mode = os.stat(bin_path).st_mode os.chmod(bin_path, mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) except OSError as e: logging.warning("Fail to chmod vtable dumper: %s", e)
def _ExecuteOneShellCommandWithTimeout(cmd, timeout, callback_on_timeout=None, *args): """Executes a command with timeout. If the process times out, this function terminates it and continues waiting. Args: proc: Popen object, the process to wait for. timeout: float, timeout in seconds. callback_on_timeout: callable, callback function for the case when the command times out. args: arguments for the callback_on_timeout. Returns: tuple(string, string, int) which are stdout, stderr and return code. """ # On Windows, subprocess.Popen(shell=True) starts two processes, cmd.exe # and the command. The Popen object represents the cmd.exe process, so # calling Popen.kill() does not terminate the command. # This function uses process group to ensure command termination. proc = utils.start_standing_subprocess(cmd) result = [] def WaitForProcess(): out, err = proc.communicate() result.append((out, err, proc.returncode)) wait_thread = threading.Thread(target=WaitForProcess) wait_thread.daemon = True wait_thread.start() try: wait_thread.join(timeout) finally: if proc.poll() is None: utils.kill_process_group(proc) if callback_on_timeout is not None: if ((utils.is_on_windows() and proc.returncode == EXIT_CODE_TIMEOUT_ON_WINDOWS) or proc.returncode == EXIT_CODE_TIMEOUT_ON_LINUX): callback_on_timeout(*args) wait_thread.join() if len(result) != 1: logging.error("Unexpected command result: %s", result) return "", "", proc.returncode return result[0]
def watchStdin(): while True: line = sys.stdin.readline() if not line: break watcher_enabled.wait() logging.info("Attempt to interrupt runner thread.") if not utils.is_on_windows(): # Default SIGINT handler sends KeyboardInterrupt to main thread # and unblocks it. os.kill(os.getpid(), signal.SIGINT) else: # On Windows, raising CTRL_C_EVENT, which is received as # SIGINT, has no effect on non-console process. # interrupt_main() behaves like SIGINT but does not unblock # main thread immediately. thread.interrupt_main()