Skip to content
Snippets Groups Projects
test_presenters.py 7.83 KiB
Newer Older
  • Learn to ignore specific revisions
  • #
    # diffoscope: in-depth comparison of files, archives, and directories
    #
    
    Chris Lamb's avatar
    Chris Lamb committed
    # Copyright © 2017-2020, 2022-2023 Chris Lamb <lamby@debian.org>
    
    #
    # diffoscope is free software: you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.
    #
    # diffoscope is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with diffoscope.  If not, see <https://www.gnu.org/licenses/>.
    
    import os
    
    import re
    
    import pytest
    
    from diffoscope.main import main
    
    from diffoscope.readers import load_diff_from_path
    
    from diffoscope.presenters.utils import (
        create_limited_print_func,
        PrintLimitReached,
        PartialString,
    )
    
    from diffoscope.presenters.json import JSONPresenter
    
    from .utils import diff_expand
    from .utils.data import cwd_data, data, get_data
    
    from .utils.tools import (
        skip_unless_tools_exist,
        skip_unless_file_version_is_at_least,
    )
    
    re_html = re.compile(
    
        r'.*<body(?P<body>.*)<div class="footer">', re.MULTILINE | re.DOTALL
    )
    
    def run(capsys, *args, pair=("test1.tar", "test2.tar")):
    
        with pytest.raises(SystemExit) as exc, cwd_data():
    
        out, err = capsys.readouterr()
    
    
        assert err == ""
    
        assert exc.value.code == 1
        return out
    
    def run_images(capsys, *args):
    
        return run(capsys, *args, pair=("test1.png", "test2.png"))
    
    def extract_body(val):
        """
        Extract the salient parts of HTML fixtures that won't change between
        versions, etc.
        """
    
    
        result = re_html.search(val).group("body")
    
    
        # Ensure that we extracted something
        assert len(result) > 0
    
        return result
    
    
    def expand_collapsed_json(tmpdir, name):
        diff = load_diff_from_path(data(name + ".collapsed-diff.json"))
    
        diff_path = str(tmpdir.join(name + ".diff.json"))
        with open(diff_path, "w") as fp:
    
            JSONPresenter(lambda x: print(x, file=fp)).start(
                diff.fmap(diff_expand)
            )
    
        return diff_path
    
    
    
    def test_text_option_is_default(capsys):
        out = run(capsys)
    
    
        assert out == get_data("output.txt")
    
    @skip_unless_file_version_is_at_least("5.44")
    
    def test_text_proper_indentation(capsys):
    
        out = run(capsys, pair=("archive1.tar", "archive2.tar"))
    
        assert out == get_data("archive12.diff.txt")
    
    def test_text_option_color(capsys):
    
        out = run(capsys, "--text-color=always")
    
        assert out == get_data("output.colored.txt")
    
    def test_text_option_with_file(tmpdir, capsys):
    
        report_path = str(tmpdir.join("report.txt"))
    
        out = run(capsys, "--text", report_path)
    
        assert out == ""
    
        with open(report_path, "r", encoding="utf-8") as f:
            assert f.read() == get_data("output.txt")
    
    def test_text_option_with_stdout(capsys):
    
        out = run(capsys, "--text", "-")
    
        assert out == get_data("output.txt")
    
    def test_markdown(capsys):
    
        out = run(capsys, "--markdown", "-")
    
        assert out == get_data("output.md")
    
    def test_restructuredtext(capsys):
    
        out = run(capsys, "--restructured-text", "-")
    
        assert out == get_data("output.rst")
    
        out = run(capsys, "--json", "-")
    
        assert out == get_data("output.json")
    
    def test_no_report_option(capsys):
    
        out = run(capsys)
    
        assert out == get_data("output.txt")
    
    def test_html_option_with_file(tmpdir, capsys):
    
        report_path = str(tmpdir.join("report.html"))
    
        out = run(capsys, "--html", report_path)
    
        assert out == ""
        with open(report_path, "r", encoding="utf-8") as f:
    
            body = extract_body(f.read())
    
            assert body.count('div class="difference"') == 4
    
    @skip_unless_tools_exist("compare", "convert", "sng")
    
    def test_html_visuals(tmpdir, capsys):
    
        report_path = str(tmpdir.join("report.html"))
    
        out = run_images(capsys, "--html", report_path)
    
        assert out == ""
        body = extract_body(open(report_path, "r", encoding="utf-8").read())
    
        assert '<img src="data:image/png;base64' in body
        assert '<img src="data:image/gif;base64' in body
    
    
    def test_htmldir_option(tmpdir, capsys):
    
        html_dir = os.path.join(str(tmpdir), "target")
    
        out = run(capsys, "--html-dir", html_dir, "--jquery", "disable")
    
        assert out == ""
    
        assert os.path.isdir(html_dir)
    
            os.path.join(html_dir, "index.html"), "r", encoding="utf-8"
    
            body = extract_body(f.read())
    
            assert body.count('div class="difference"') == 4
    
    def test_html_option_with_stdout(capsys):
    
        body = extract_body(run(capsys, "--html", "-"))
    
        assert body.count('div class="difference"') == 4
    
    def test_html_regression_875281(tmpdir, capsys):
    
        diff_path = expand_collapsed_json(tmpdir, "debian-bug-875281")
        report_path = str(tmpdir.join("report.html"))
    
            capsys,
    
            report_path,
    
            "--max-page-size=5000",
    
            f"--load-existing-diff={diff_path}",
    
        assert out == ""
    
        with open(report_path, "r", encoding="utf-8") as f:
    
            assert extract_body(f.read()) == get_data(
    
                "output_regression_875281.html"
    
    def test_limited_print():
    
        with pytest.raises(PrintLimitReached):
            p = create_limited_print_func(fake, 5)
            p("123456")
        with pytest.raises(PrintLimitReached):
            p = create_limited_print_func(fake, 5)
            p("123")
            p("456")
        p = create_limited_print_func(fake, 5)
        p("123")
        p("456", force=True)
    
    def test_partial_string():
        a, b = object(), object()
        tmpl = PartialString("{0} {1}", a, b)
        assert tmpl.holes == (a, b)
    
        assert tmpl.format({a: "Hello,", b: "World!"}) == "Hello, World!"
        assert tmpl.pformat({a: "Hello,"}) == PartialString("Hello, {0}", b)
        assert tmpl.pformat({b: "World!"}) == PartialString("{0} World!", a)
    
        assert tmpl.base_len, tmpl.num_holes == (1, 2)
        assert tmpl.size(hole_size=33) == 67
    
        assert tmpl.pformat({a: PartialString("{0}", b)}) == PartialString(
            "{0} {0}", b
    
        assert tmpl.pformat({a: tmpl}) == PartialString("{0} {1} {1}", a, b)
        assert tmpl.pformat({b: tmpl}) == PartialString("{0} {0} {1}", a, b)
    
        PartialString("{1}", a, b)
        with pytest.raises(IndexError):
            PartialString("{0} {1} {2}", a, b)
    
    def test_partial_string_cont():
        t, cont = PartialString.cont()
        t = cont(t, "x: {0}\ny: {1}\n{-1}", object(), object())
        t = cont(t, "z: {0}\n{-1}", object())
        t = cont(t, "")
        key = t.holes
    
        assert (
            t.format({key[0]: "line1", key[1]: "line2", key[2]: "line3"})
    
            == "x: line1\ny: line2\nz: line3\n"
    
        assert t.size(hole_size=5) == 27
    
    def test_partial_string_numl():
        tmpl = PartialString.numl("{0} {1} {2}", 2, object())
        assert tmpl.holes[:2] == (0, 1)
    
        assert tmpl.pformatl("(1)", "(2)", "(o)") == PartialString("(1) (2) (o)")
    
        tmpl = PartialString.numl(
            "find {0} -name {1} " + PartialString.escape(r"-exec ls -la {} \;"), 2
        )
    
        assert tmpl == PartialString(
    
            "find {0} -name {1} -exec ls -la {{}} \\;", *tmpl.holes
    
        assert tmpl.size() == 33
        assert tmpl.size(4) == 39
    
        assert tmpl == PartialString.numl(
    
            r"find {0} -name {1} -exec ls -la {2} \;", 3
        ).pformat({2: "{}"})
    
        assert tmpl.pformatl("my{}path", "my{}file") == PartialString(
    
            "find my{{}}path -name my{{}}file -exec ls -la {{}} \\;"
    
        )
        assert (
            tmpl.formatl("my{}path", "my{}file")
    
            == "find my{}path -name my{}file -exec ls -la {} \\;"
    
    
        esc = PartialString("{{}} {0}", None)
        assert esc.pformat({None: PartialString.of(None)}) == esc
        assert esc.format({None: "0"}) == "{} 0"
        with pytest.raises(ValueError):
            PartialString("{}")