Newer
Older
#
# diffoscope: in-depth comparison of files, archives, and directories
#
# 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 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,
)
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():

Ximin Luo
committed
main(args + pair)
assert exc.value.code == 1
return out
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)
)
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")
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)
with open(report_path, "r", encoding="utf-8") as f:
assert f.read() == get_data("output.txt")
def test_text_option_with_stdout(capsys):
assert out == get_data("output.txt")
out = run(capsys, "--markdown", "-")
assert out == get_data("output.md")
out = run(capsys, "--restructured-text", "-")
assert out == get_data("output.rst")
def test_json(capsys):
assert out == get_data("output.json")
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())

Chris Lamb
committed
assert body.count('div class="difference"') == 4
@skip_unless_tools_exist("compare", "convert", "sng")
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")
os.path.join(html_dir, "index.html"), "r", encoding="utf-8"
body = extract_body(f.read())

Chris Lamb
committed
assert body.count('div class="difference"') == 4
def test_html_option_with_stdout(capsys):
body = extract_body(run(capsys, "--html", "-"))

Chris Lamb
committed
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"))

Chris Lamb
committed
out = run(
f"--load-existing-diff={diff_path}",

Chris Lamb
committed
)
with open(report_path, "r", encoding="utf-8") as f:

Chris Lamb
committed
assert extract_body(f.read()) == get_data(

Chris Lamb
committed
)
def fake(x):
return None
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"
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)")

Ximin Luo
committed
def test_partial_string_escape():
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

Ximin Luo
committed
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 {} \\;"

Ximin Luo
committed
esc = PartialString("{{}} {0}", None)
assert esc.pformat({None: PartialString.of(None)}) == esc
assert esc.format({None: "0"}) == "{} 0"
with pytest.raises(ValueError):
PartialString("{}")