Esempio n. 1
0
def run_test(
        test_cmd,
        pkg_path,
        name,
        retryable,
        continue_on_errors,
):
    """Run test_cmd in the given pkg_path."""
    logging.info('Running `%s` in %s...', ' '.join(test_cmd), pkg_path)
    start = datetime.now()

    proc = subprocess.Popen(
        test_cmd,
        cwd=pkg_path,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        preexec_fn=os.setsid,
        shell=False)
    stdout = []

    def kill_proc():
        logging.info('KILLING TEST: %s', name)
        # Kill the group so child processes are also cleaned up.
        os.killpg(os.getpgid(proc.pid), signal.SIGKILL)
    timer = threading.Timer(MAX_RUN_TIME_IN_SECONDS, kill_proc)

    try:
        timer.start()
        for line in iter(proc.stdout.readline, ''):
            # line is a bytes string literal in Python 3.
            logging.info('[%s %s]: %s', test_cmd[0], name, line.rstrip().decode('utf-8'))
            stdout.append(line)
        proc.wait()
    finally:
        timer.cancel()

    end = datetime.now()

    if proc.returncode:
        logging.info(
            'TEST %s: %s (exit code: %d)\nstdout:\n%s',
            'ERROR' if timer.is_alive() else 'TIMED OUT',
            name,
            proc.returncode,
            ''.join(stdout).rstrip(),
        )
        if retryable and is_retryable_error(''.join(stdout)):
            logging.info('RETRYING TEST: %s', name)
            time.sleep(3)
            run_test(test_cmd, pkg_path, name, False, continue_on_errors)
            return
        if not continue_on_errors:
            raise utils.TestFailureError(
                'TEST FAILED: %s %s (exit code: %d)' %
                (test_cmd[0], name, proc.returncode),
                proc.returncode,
            )
    else:
        logging.info('TEST PASSED: %s (%s seconds)', name, (end - start).seconds)
Esempio n. 2
0
def run_test(test_cmd,
             pkg_path,
             name,
             retryable,
             continue_on_errors,
             is_integration_test=False):
    """Run test_cmd in the given pkg_path."""
    logging.info("Running `%s` in %s...", " ".join(test_cmd), pkg_path)
    start = datetime.now()

    env = None
    # If we're running integration tests in parallel, assign a unique NUCLIDE_SERVER_PORT.
    if is_integration_test:
        process_identity = multiprocessing.current_process()._identity
        if len(process_identity) > 0:
            # process_id is numbered starting from 1.
            process_id = process_identity[0] - 1
            if process_id < len(OPEN_PORTS):
                env = os.environ.copy()
                env["TEST_NUCLIDE_SERVER_PORT"] = str(OPEN_PORTS[process_id])

    proc = subprocess.Popen(
        test_cmd,
        cwd=pkg_path,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        preexec_fn=os.setsid,
        shell=False,
        env=env,
    )
    # Record the pgid now - sometimes the process exits but not its children.
    proc_pgid = os.getpgid(proc.pid)
    stdout = []

    def kill_proc():
        logging.info("KILLING TEST: %s", name)
        # Kill the group so child processes are also cleaned up.
        os.killpg(proc_pgid, signal.SIGKILL)

    timer = threading.Timer(MAX_RUN_TIME_IN_SECONDS, kill_proc)

    try:
        timer.start()
        for line in iter(proc.stdout.readline, ""):
            # line is a bytes string literal in Python 3.
            logging.info("[%s %s]: %s", test_cmd[0], name,
                         line.rstrip().decode("utf-8"))
            stdout.append(line)
        proc.wait()
    # pylint: disable-msg=W0612
    # flake8: noqa
    except KeyboardInterrupt as e:
        # Cleanly kill all child processes before terminating.
        kill_proc()
        sys.exit(1)
    finally:
        timer.cancel()

    end = datetime.now()

    if proc.returncode:
        logging.info(
            "TEST %s: %s (exit code: %d)\nstdout:\n%s",
            "ERROR" if timer.is_alive() else "TIMED OUT",
            name,
            proc.returncode,
            "".join(stdout).rstrip(),
        )
        if retryable and is_retryable_error("".join(stdout)):
            logging.info("RETRYING TEST: %s", name)
            time.sleep(3)
            run_test(test_cmd, pkg_path, name, False, continue_on_errors)
            return
        if not continue_on_errors:
            raise utils.TestFailureError(
                "TEST FAILED: %s %s (exit code: %d)" %
                (test_cmd[0], name, proc.returncode),
                proc.returncode,
            )
    else:
        logging.info("TEST PASSED: %s (%s seconds)", name,
                     (end - start).seconds)