Example #1
0
def test_executable_relative():
    """Validate |Executable| accepts relative paths."""
    if platform.system() != "Windows":
        scripty_path = "./scripty.sh"
        with open(scripty_path, "w") as scripty:
            scripty.write("#!/bin/sh\necho 'hi, my name is scripty :)'\n")
        chmod = which("chmod", log_calls=False)
        chmod("+x", scripty_path)
        scripty = Executable(scripty_path, log_calls=False)
        proc = scripty(stdout=PIPE, stderr=PIPE)
        assert proc.returncode == 0
        assert proc.stderr == b""
        assert proc.stdout.decode("utf-8") == "hi, my name is scripty :)\n"
        rm_rf(scripty_path)
Example #2
0
def test_executable_failures(capsys):
    """Validate failing executables error as expected."""
    git = which("git", log_calls=False)

    # By default, failed invocations terminate.  Make sure this happens.
    # NOTE: as with test_executable_logging, capsys doesn't capture subprocess.run.
    # Check for `git` failure message in non-terminating tests below where we capture
    # using PIPE.
    pipe = {"stdout": PIPE, "stderr": PIPE}
    with pytest.raises(SystemExit) as se_excinfo:
        git("log", "--petty=%B", **pipe)

    captured = capsys.readouterr()
    assert re.match(r".*non-zero exit status (\d+)\.?",
                    captured.err).group(1) == "128"
    assert se_excinfo.value.code == 128

    # Using check=False tells subprocess.run not to raise an Exception.

    proc = git("log", "--petty=%B", check=False, **pipe)
    assert proc.returncode == 128
    assert proc.stdout == b""
    assert b"fatal" in proc.stderr
    assert b"unrecognized argument" in proc.stderr
    assert b"--petty=%B" in proc.stderr

    # Clear capsys before this test.
    captured = capsys.readouterr()

    # Test that invalid kwargs to subprocess.run fail.
    with pytest.raises(SystemExit) as se_excinfo:
        git("status", not_valid_subprocess_kwarg=True)
    assert se_excinfo.value.code == 1
    captured = capsys.readouterr()
    assert captured.out == ""
    assert "Executable.__call__: invalid kwarg(s) for subprocess.run" in captured.err
    assert "unexpected keyword argument 'not_valid_subprocess_kwarg'" in captured.err
Example #3
0
def test_which(capsys):
    """Validate that |which| finds or does not find executables."""
    # Make sure ci_exec.core.which and shutil.which agree (how could then not? xD).
    git = which("git")
    git_path = shutil.which("git")
    assert git.exe_path == git_path

    # This command should not exist.  Right?
    no_cmd = "ja" * 22
    with pytest.raises(SystemExit) as se_excinfo:
        which(no_cmd)
    assert se_excinfo.value.code == 1
    captured = capsys.readouterr()
    assert captured.out == ""
    prefix = colorize("[X] ", color=Colors.Red, style=Styles.Bold)
    expected_error_message = "{prefix}Could not find '{no_cmd}' in $PATH.\n".format(
        prefix=prefix, no_cmd=no_cmd)
    assert captured.err == expected_error_message

    # Test manual $PATH override / make sure same python is found.
    actual_python = Path(sys.executable)
    python_name = actual_python.name
    python_dir = str(actual_python.parent)
    python = which(python_name, path=python_dir, log_calls=False)
    assert python.exe_path == str(actual_python)

    # Throwing in the __str__ test here because it doesn't deserve its own test method.
    assert str(python) == "Executable('{py}')".format(py=str(actual_python))

    proc = python("-c",
                  "import sys; print(sys.version_info)",
                  stdout=PIPE,
                  stderr=PIPE)
    assert proc.returncode == 0
    assert proc.stderr == b""
    assert proc.stdout.decode("utf-8").strip() == "{v}".format(
        v=sys.version_info)

    # :)
    with pytest.raises(TypeError) as te_excinfo:
        which("git", log_callz=False)
    assert "unexpected keyword argument 'log_callz'" in str(te_excinfo.value)
Example #4
0
def test_executable_logging(capsys):
    """Validate |Executable| runs and logs as expected."""
    # NOTE: capsys is not able to capture subprocess.run() output directly, so what we
    # do instead is run with PIPEs and print it to simulate how it would run normally.
    pipe = {"stdout": PIPE, "stderr": PIPE}

    def run_and_print(exe: Executable, *args, **kwargs) -> str:
        """Run the executable and print to stdout / stderr, return expected logging."""
        proc = exe(*args, **kwargs)
        assert proc.returncode == 0
        print(proc.stderr.decode("utf-8"), file=sys.stderr, end="")
        print(proc.stdout.decode("utf-8"), end="")
        if exe.log_calls:
            popen_args = (exe.exe_path, *args)
            message = f"{exe.log_prefix}{' '.join(popen_args)}"
            if exe.log_color:
                message = colorize(message,
                                   color=exe.log_color,
                                   style=exe.log_style)
            return message
        else:
            return ""

    def startswith(out: str, prefix: str, color: str, style: str) -> bool:
        """External check for cross-validating run_and_print."""
        colored_prefix = colorize(prefix, color=color, style=style)
        colored = colored_prefix.split(Ansi.Clear)[0]
        return out.startswith(colored)

    git = which("git")
    log_template = "{logged}\norigin\n"

    # Test default logging (bold cyan).
    logged = run_and_print(git, "remote", **pipe)
    captured = capsys.readouterr()
    assert captured.err == ""
    assert captured.out == log_template.format(logged=logged)
    assert startswith(captured.out, "$ ", Colors.Cyan, Styles.Bold)

    # Test custom log color.
    git.log_color = Colors.Magenta
    logged = run_and_print(git, "remote", **pipe)
    captured = capsys.readouterr()
    assert captured.err == ""
    assert captured.out == log_template.format(logged=logged)
    assert startswith(captured.out, "$ ", Colors.Magenta, Styles.Bold)

    # Test custom log style.
    git.log_style = Styles.BoldInverted
    logged = run_and_print(git, "remote", **pipe)
    captured = capsys.readouterr()
    assert captured.err == ""
    assert captured.out == log_template.format(logged=logged)
    assert startswith(captured.out, "$ ", Colors.Magenta, Styles.BoldInverted)

    # Test custom log prefix.
    git.log_prefix = ">>> "
    logged = run_and_print(git, "remote", **pipe)
    captured = capsys.readouterr()
    assert captured.err == ""
    assert captured.out == log_template.format(logged=logged)
    assert startswith(captured.out, ">>> ", Colors.Magenta,
                      Styles.BoldInverted)

    # Test log without colors.
    git.log_color = None
    logged = run_and_print(git, "remote", **pipe)
    captured = capsys.readouterr()
    assert captured.err == ""
    assert captured.out.startswith(">>> ")

    # Test log turned off only outputs command.
    git.log_calls = False
    run_and_print(git, "remote", **pipe)
    captured = capsys.readouterr()
    assert captured.err == ""
    assert captured.out == "origin\n"