Esempio n. 1
0
    def verify_all(colored_output: str):
        """Validate all parameters from the specified (maybe) colorized output."""
        # Remove trailing \n to make comparisons easier.
        colored_output = colored_output.strip()

        # Test coloring / style (do first to create un-colored version to test others).
        if color is not None:
            ansi_color, ansi_clear = colorize("!", color=color, style=style).split("!")
            assert colored_output.startswith(ansi_color)
            assert colored_output.endswith(ansi_clear)
            assert color in colored_output
            if style is not None:
                assert style in colored_output
        else:
            ansi_color, ansi_clear = "", ""
            assert Ansi.Escape not in colored_output
            assert Ansi.Clear not in colored_output

        # Create uncolored version to make later tests easier.
        stripped_out = colored_output.replace(ansi_color, "").replace(ansi_clear, "")

        # Need at least (fill_width - 1) / 2 available.
        if fill_width < 3:
            fill = None
        else:
            if fill_width % 2 == 0:
                fill = fill_char * (fill_width // 2)
            else:
                fill = fill_char * ((fill_width - 1) // 2)

        # Verify the expected fill was used.
        if fill is not None:
            assert colored_output.count(fill) == 2
        else:
            assert fill_char not in colored_output

        # Verify the padding specified is used.
        if fill is not None:
            l_fill, r_fill = stripped_out.split(stage)
            assert l_pad == l_fill.split(fill)[-1]
            assert r_pad == r_fill.split(fill)[0]
        else:
            if l_pad != "":
                assert l_pad not in stripped_out
            if r_pad != "":
                assert r_pad not in stripped_out
            assert stripped_out == stage

        # Verify the width is as expected.
        expected_width = len(ansi_color) + len(stage) + len(ansi_clear)
        if fill is not None:
            expected_width += (len(fill) * 2) + len(l_pad) + len(r_pad)
            if fill_width % 2 != 0:
                expected_width += len(fill_char)
        assert len(colored_output) == expected_width
        if fill_width >= 3:
            assert len(stripped_out) == full_width
        else:
            assert stripped_out == stage
Esempio n. 2
0
def test_colorize(color: str, style: str):
    """Test |colorize| colors as expected for each platform."""
    message = "colors!"
    colored = colorize(message, color=color, style=style)

    if style == Styles.Regular:
        assert colored.startswith(f"{Ansi.Escape}{color}m")
    else:
        assert colored.startswith(f"{Ansi.Escape}{color};{style}m")
    assert colored.endswith(f"{Ansi.Clear}")
    assert message in colored
Esempio n. 3
0
 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 ""
Esempio n. 4
0
def test_fail(capsys, why: str, exit_code: int, no_prefix: bool):
    """Validate |fail| exits as expected."""
    with pytest.raises(SystemExit) as se_excinfo:
        # Make sure calling this raises SystemExit with appropriate code.
        fail(why, exit_code=exit_code, no_prefix=no_prefix)

    # Make sure we exited with the expected code.
    assert se_excinfo.value.code == exit_code

    # Check printout of sys.stderr and make sure expected message was printed.
    if no_prefix:
        prefix = ""
    else:
        prefix = colorize("[X] ", color=Colors.Red, style=Styles.Bold)
    expected_error_message = f"{prefix}{why}\n"
    captured = capsys.readouterr()
    assert captured.out == ""
    assert captured.err == expected_error_message
Esempio n. 5
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)
Esempio n. 6
0
def test_dump_predefined_color_styles(capsys):
    """Validate :func:`~ci_exec.colorize.dump_predefined_color_styles` dumps all."""
    dump_predefined_color_styles()
    captured = capsys.readouterr()
    assert captured.err == ""

    # Collect the printed results.
    colors_seen = {}
    spec_regex = re.compile(r"color=([a-zA-Z]+), style=([a-zA-Z]+)")
    for match in spec_regex.finditer(captured.out):
        color, style = match.groups()
        if color in colors_seen:
            colors_seen[color].append(style)
        else:
            colors_seen[color] = [style]

    # Make sure every color in every style was presented.
    all_colors = Colors.all_colors()
    all_styles = set(Styles.all_styles())

    assert len(colors_seen) == len(all_colors)
    for color_name, style_names in colors_seen.items():
        # The style names are printed, get the values
        styles_seen = [getattr(Styles, style) for style in style_names]
        assert len(styles_seen) == len(style_names)
        assert set(styles_seen) == all_styles

        # Check the actual colors showed up.
        color = getattr(Colors, color_name)
        for style_name, style in zip(style_names, styles_seen):
            expected = colorize(
                "color={color_name}, style={style_name}".format(
                    color_name=color_name, style_name=style_name
                ),
                color=color,
                style=style
            )
            assert expected in captured.out
Esempio n. 7
0
def test_filter_file(capsys):
    """Validate that |filter_file| patches / errors as expected."""
    # Non-existent files cannot be patched.
    with pytest.raises(SystemExit):
        filter_file("i_dont_exist", "boom", "blam")
    red_x = colorize("[X] ", color=Colors.Red, style=Styles.Bold)
    captured = capsys.readouterr()
    assert captured.out == ""
    err = "{red_x}Cannot filter 'i_dont_exist', no such file!".format(
        red_x=red_x)
    assert captured.err.strip() == err

    # Backup extension must not be empty string.
    with pytest.raises(SystemExit):
        filter_file("tox.ini", "boom", "blam", backup_extension="")
    captured = capsys.readouterr()
    assert captured.out == ""
    err = "{red_x}filter_file: 'backup_extension' may not be the empty string.".format(
        red_x=red_x)
    assert captured.err.strip() == err

    def read_both(cml: Path, bku: Path) -> Tuple[str, str]:
        """Open and read both files, returning the results."""
        with cml.open() as cml_f:
            cml_contents = cml_f.read()
        with bku.open() as bku_f:
            bku_contents = bku_f.read()
        return (cml_contents, bku_contents)

    for line_based in (True, False):
        # Filtering nothing should error.
        filter_town, cmake_lists_txt = _make_dummy()
        with pytest.raises(SystemExit):
            filter_file(cmake_lists_txt, "", "", line_based=line_based)
        captured = capsys.readouterr()
        assert captured.out == ""
        assert "filter_file: no changes made to '" in captured.err
        assert "CMakeLists.txt'" in captured.err

        # Invalid replacement should trigger failure.
        filter_town, cmake_lists_txt = _make_dummy()
        with pytest.raises(SystemExit):
            filter_file(cmake_lists_txt,
                        "export",
                        lambda x: 11,
                        line_based=line_based)
        captured = capsys.readouterr()
        assert captured.out == ""
        assert captured.err.startswith(
            "{red_x}Unable to filter".format(red_x=red_x))
        assert "expected str instance, int found" in captured.err

        # No filtering with demand_different=False should not error.
        filter_town, cmake_lists_txt = _make_dummy()
        backup = filter_file(cmake_lists_txt,
                             "",
                             "",
                             demand_different=False,
                             line_based=line_based)
        cml, bku = read_both(cmake_lists_txt, backup)
        assert cml == bku

        # Test an actual patch.
        filter_town, cmake_lists_txt = _make_dummy()
        backup = filter_file(cmake_lists_txt,
                             "super_project",
                             "SUPER_PROJECT",
                             line_based=line_based)
        cml, bku = read_both(cmake_lists_txt, backup)
        assert cml != bku
        assert bku == _please_stop
        assert cml == _please_stop.replace("super_project", "SUPER_PROJECT")

    # Cleanup
    rm_rf(filter_town)
Esempio n. 8
0
 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)