Commit d6fcb861 authored by Jérémy Bobbio's avatar Jérémy Bobbio

Add --new-file to treat absent files as empty

When specifying --new-file, diffoscope will treat non-existing files
(which also applies to containers) as empty.

We had to change perform_fuzzy_matching to return names so we can
pop them out the dictionaries with the set of files that have not
been compared.

Thanks Jakub Wilk for the suggestion.

Closes: #797560
parent bdbff7a1
......@@ -68,6 +68,8 @@ def create_parser():
'(0 to disable, %d is default, 400 is high fuzziness)' %
(Config.general.fuzzy_threshold),
default=Config.general.fuzzy_threshold)
parser.add_argument('--new-file', dest='new_file', action='store_true',
help='treat absent files as empty')
parser.add_argument('--css', metavar='url', dest='css_url',
help='link to an extra CSS for the HTML report')
parser.add_argument('file1', help='first file to compare')
......@@ -107,6 +109,7 @@ def run_diffoscope(parsed_args):
Config.general.max_diff_input_lines = parsed_args.max_diff_input_lines
Config.general.max_report_size = parsed_args.max_report_size
Config.general.fuzzy_threshold = parsed_args.fuzzy_threshold
Config.general.new_file = parsed_args.new_file
if parsed_args.debug:
logger.setLevel(logging.DEBUG)
set_locale()
......
......@@ -127,6 +127,9 @@ class Changes(object):
return [os.path.join(self._directory, z['name'])
for z in self._data['Files']]
def keys(self):
return self._data.keys()
def __getitem__(self, key):
"""
Returns the value of the rfc822 key specified.
......
......@@ -28,7 +28,7 @@ from diffoscope import logger, tool_required
from diffoscope.config import Config
from diffoscope.difference import Difference
from diffoscope.comparators.binary import \
File, FilesystemFile, compare_binary_files
File, FilesystemFile, NonExistingFile, compare_binary_files
from diffoscope.comparators.bzip2 import Bzip2File
from diffoscope.comparators.java import ClassFile
from diffoscope.comparators.cpio import CpioFile
......@@ -61,15 +61,22 @@ from diffoscope.comparators.xz import XzFile
from diffoscope.comparators.zip import ZipFile
def compare_root_paths(path1, path2):
if not all(map(os.path.lexists, (path1, path2))):
for path in (path1, path2):
def bail_if_non_existing(*paths):
if not all(map(os.path.lexists, paths)):
for path in paths:
if not os.path.lexists(path):
sys.stderr.write('%s: %s: No such file or directory\n' % (sys.argv[0], path))
sys.exit(2)
def compare_root_paths(path1, path2):
if not Config.general.new_file:
bail_if_non_existing(path1, path2)
if os.path.isdir(path1) and os.path.isdir(path2):
return compare_directories(path1, path2)
return compare_files(specialize(FilesystemFile(path1)), specialize(FilesystemFile(path2)))
file1 = specialize(FilesystemFile(path1))
file2 = specialize(FilesystemFile(path2))
return compare_files(file1, file2)
def compare_files(file1, file2, source=None):
......@@ -80,7 +87,11 @@ def compare_files(file1, file2, source=None):
return None
specialize(file1)
specialize(file2)
if file1.__class__.__name__ != file2.__class__.__name__:
if isinstance(file1, NonExistingFile):
file1.other_file = file2
elif isinstance(file2, NonExistingFile):
file2.other_file = file1
elif file1.__class__.__name__ != file2.__class__.__name__:
return file1.compare_bytes(file2, source)
return file1.compare(file2, source)
......@@ -88,6 +99,7 @@ def compare_files(file1, file2, source=None):
# The order matters! They will be tried in turns.
FILE_CLASSES = (
Directory,
NonExistingFile,
Symlink,
Device,
DotChangesFile,
......@@ -132,23 +144,25 @@ def specialize(file):
return file
def perform_fuzzy_matching(files1, files2):
def perform_fuzzy_matching(members1, members2):
if Config.general.fuzzy_threshold == 0:
return
files2 = set(files2)
already_compared = set()
for file1 in filter(lambda f: not f.is_directory(), files1):
if not file1.fuzzy_hash:
# Perform local copies because they will be modified by consumer
members1 = dict(members1)
members2 = dict(members2)
for name1, file1 in members1.iteritems():
if file1.is_directory() or not file1.fuzzy_hash:
continue
comparisons = []
for file2 in files2 - already_compared:
if file2.is_directory() or not file2.fuzzy_hash:
for name2, file2 in members2.iteritems():
if name2 in already_compared or file2.is_directory() or not file2.fuzzy_hash:
continue
comparisons.append((tlsh.diff(file1.fuzzy_hash, file2.fuzzy_hash), file2))
comparisons.append((tlsh.diff(file1.fuzzy_hash, file2.fuzzy_hash), name2))
if comparisons:
comparisons.sort(key=operator.itemgetter(0))
score, file2 = comparisons[0]
logger.debug('fuzzy top match %s %s: %d difference score', file1.name, file2.name, score)
score, name2 = comparisons[0]
logger.debug('fuzzy top match %s %s: %d difference score', name1, name2, score)
if score < Config.general.fuzzy_threshold:
yield file1, file2, score
already_compared.add(file2)
yield name1, name2, score
already_compared.add(name2)
......@@ -26,8 +26,10 @@ import os.path
import re
from stat import S_ISCHR, S_ISBLK
import subprocess
import tempfile
import tlsh
import magic
from diffoscope.config import Config
from diffoscope.difference import Difference
from diffoscope import tool_required, RequiredToolNotFound, logger
......@@ -197,6 +199,7 @@ class File(object):
return difference
return self.compare_bytes(other, source)
class FilesystemFile(File):
def __init__(self, path):
self._path = None
......@@ -220,3 +223,78 @@ class FilesystemFile(File):
def is_device(self):
mode = os.lstat(self._name).st_mode
return S_ISCHR(mode) or S_ISBLK(mode)
class NonExistingFile(File):
"""Represents a missing file when comparing containers"""
@staticmethod
def recognizes(file):
if isinstance(file, FilesystemFile) and not os.path.lexists(file.name):
assert Config.general.new_file, '%s does not exist' % file.name
return True
return False
def __init__(self, path, other_file=None):
self._path = None
self._name = path
self._other_file = other_file
@property
def other_file(self):
return self._other_file
@other_file.setter
def other_file(self, value):
self._other_file = value
def has_same_content_as(self, other):
return False
@contextmanager
def get_content(self):
self._path = '/dev/null'
yield
self._path = None
def is_directory(self):
return False
def is_symlink(self):
return False
def is_device(self):
return False
def compare(self, other, source=None):
# So now that comparators are all object-oriented, we don't have any clue on how to
# perform a meaningful comparison right here. So we are good do the comparison backward
# (where knowledge of the file format lies) and and then reverse it.
if isinstance(other, NonExistingFile):
return Difference(None, self.name, other.name, comment='Trying to compare two non-existing files.')
logger.debug('Performing backward comparison')
backward_diff = other.compare(self, source)
if not backward_diff:
return None
return backward_diff.get_reverse()
# Be nice to text comparisons
@property
def encoding(self):
return self._other_file.encoding
# Be nice to device comparisons
def get_device(self):
return ''
# Be nice to metadata comparisons
@property
def magic_file_type(self):
return self._other_file.magic_file_type
# Be nice to .changes comparisons
@property
def changes(self):
class DummyChanges(dict):
get_as_string = lambda self, _: ''
return DummyChanges(Files=[], Version='')
......@@ -108,7 +108,7 @@ class Md5sumsFile(File):
@needs_content
def compare(self, other, source=None):
if self.has_same_content_as(other):
if self.has_same_content_as(other) or other.path is None:
return None
try:
my_md5sums = Md5sumsFile.parse_md5sums(self.path)
......
......@@ -22,8 +22,9 @@ import os.path
import re
from diffoscope.changes import Changes
import diffoscope.comparators
from diffoscope.comparators.binary import File, needs_content
from diffoscope.comparators.binary import File, NonExistingFile, needs_content
from diffoscope.comparators.utils import Container, NO_COMMENT
from diffoscope.config import Config
from diffoscope.difference import Difference
......@@ -121,10 +122,17 @@ class DotChangesFile(File):
def compare_details(self, other, source=None):
differences = []
for field in DOT_CHANGES_FIELDS:
for field in sorted(set(self.changes.keys()).union(set(other.changes.keys()))):
if field.startswith('Checksums-') or field == 'Files':
continue
my_value = ''
if field in self.changes:
my_value = self.changes.get_as_string(field).lstrip()
other_value = ''
if field in other.changes:
other_value = other.changes.get_as_string(field).lstrip()
differences.append(Difference.from_unicode(
self.changes[field].lstrip(),
other.changes[field].lstrip(),
my_value, other_value,
self.path, other.path, source=field))
# compare Files as string
differences.append(Difference.from_unicode(self.changes.get_as_string('Files'),
......
......@@ -28,7 +28,8 @@ import subprocess
import tempfile
from threading import Thread
import diffoscope.comparators
from diffoscope.comparators.binary import File
from diffoscope.comparators.binary import File, NonExistingFile
from diffoscope.config import Config
from diffoscope.difference import Difference
from diffoscope import logger, tool_required
......@@ -44,6 +45,8 @@ def make_temp_directory():
@tool_required('ar')
def get_ar_content(path):
if path == '/dev/null':
return ''
return subprocess.check_output(
['ar', 'tv', path], stderr=subprocess.STDOUT, shell=False).decode('utf-8')
......@@ -177,9 +180,16 @@ class Container(object):
other_members = other.get_members()
for name in sorted(set(my_members.iterkeys()).intersection(set(other_members.iterkeys()))):
yield my_members.pop(name), other_members.pop(name), NO_COMMENT
for my_file, other_file, score in diffoscope.comparators.perform_fuzzy_matching(my_members.values(), other_members.values()):
for my_name, other_name, score in diffoscope.comparators.perform_fuzzy_matching(my_members, other_members):
comment = 'Files similar despite different names (difference score: %d)' % score
yield my_file, other_file, comment
yield my_members.pop(my_name), other_members.pop(other_name), comment
if Config.general.new_file:
for my_name in set(my_members.iterkeys()) - set(other_members.iterkeys()):
my_file = my_members[my_name]
yield my_file, NonExistingFile('/dev/null', my_file), NO_COMMENT
for other_name in set(other_members.iterkeys()) - set(my_members.iterkeys()):
other_file = other_members[other_name]
yield NonExistingFile('/dev/null', other_file), other_file, NO_COMMENT
def compare(self, other, source=None):
differences = []
......@@ -238,7 +248,9 @@ class Archive(Container):
@contextmanager
def open(self):
if self._archive is not None:
if isinstance(self.source, NonExistingFile):
yield NonExistingArchive(self.source)
elif self._archive is not None:
yield self
else:
with self.source.get_content():
......@@ -271,3 +283,43 @@ class Archive(Container):
def get_member(self, member_name):
return ArchiveMember(self, member_name)
class NonExistingArchiveLikeObject(object):
def getnames(self):
return []
def list(self, *args, **kwargs):
return ''
def close(self):
pass
class NonExistingArchive(Archive):
@property
def archive(self):
return NonExistingArchiveLikeObject()
def open_archive(self):
# should never be called
raise NotImplemented
def close_archive(self):
# should never be called
raise NotImplemented
def get_member_names(self):
return []
def extract(self, member_name, dest_dir):
# should never be called
raise NotImplemented
def get_member(self, member_name):
return NonExistingFile('/dev/null')
# Be nice to gzip and the likes
@property
def path(self):
return '/dev/null'
......@@ -31,6 +31,7 @@ class Config(object):
self._max_diff_input_lines = 100000 # GNU diff cannot process arbitrary large files :(
self._max_report_size = 2000 * 2 ** 10 # 2000 kB
self._fuzzy_threshold = 60
self._new_file = False
@classproperty
def general(cls):
......@@ -69,3 +70,11 @@ class Config(object):
@fuzzy_threshold.setter
def fuzzy_threshold(self, value):
self._fuzzy_threshold = value
@property
def new_file(self):
return self._new_file
@new_file.setter
def new_file(self, value):
self._new_file = value
......@@ -220,6 +220,12 @@ def make_feeder_from_unicode(content):
return feeder
def empty_file_feeder():
def feeder(f):
return False
return feeder
def make_feeder_from_file(in_file, filter=lambda buf: buf.encode('utf-8')):
def feeder(out_file):
line_count = 0
......@@ -236,6 +242,7 @@ def make_feeder_from_file(in_file, filter=lambda buf: buf.encode('utf-8')):
return end_nl
return feeder
def make_feeder_from_command(command):
def feeder(out_file):
end_nl = make_feeder_from_file(command.stdout, command.filter)(out_file)
......@@ -264,7 +271,10 @@ class Difference(object):
def __init__(self, unified_diff, path1, path2, source=None, comment=None):
self._comments = []
if comment:
self._comments.append(comment)
if type(comment) is list:
self._comments.extend(comment)
else:
self._comments.append(comment)
self._unified_diff = unified_diff
# allow to override declared file paths, useful when comparing
# tempfiles
......@@ -314,22 +324,30 @@ class Difference(object):
if 'command_args' in kwargs:
command_args = kwargs['command_args']
del kwargs['command_args']
command1 = cls(path1, *command_args)
command2 = cls(path2, *command_args)
command1 = None
if path1 == '/dev/null':
feeder1 = empty_file_feeder()
else:
command1 = cls(path1, *command_args)
feeder1 = make_feeder_from_command(command1)
command2 = None
if path2 == '/dev/null':
feeder2 = empty_file_feeder()
else:
command2 = cls(path2, *command_args)
feeder2 = make_feeder_from_command(command2)
if 'source' not in kwargs:
kwargs['source'] = ' '.join(map(lambda x: '{}' if x == command1.path else x, command1.cmdline()))
difference = Difference.from_feeder(make_feeder_from_command(command1),
make_feeder_from_command(command2),
path1, path2, *args, **kwargs)
source_cmd = command1 or command2
kwargs['source'] = ' '.join(map(lambda x: '{}' if x == source_cmd.path else x, source_cmd.cmdline()))
difference = Difference.from_feeder(feeder1, feeder2, path1, path2, *args, **kwargs)
if not difference:
return None
if command1.stderr_content or command2.stderr_content:
if command1.stderr_content:
difference.add_comment('stderr from `%s`:' % ' '.join(command1.cmdline()))
difference.add_comment(command1.stderr_content)
if command2.stderr_content:
difference.add_comment('stderr from `%s`:' % ' '.join(command2.cmdline()))
difference.add_comment(command2.stderr_content)
if command1 and command1.stderr_content:
difference.add_comment('stderr from `%s`:' % ' '.join(command1.cmdline()))
difference.add_comment(command1.stderr_content)
if command2 and command2.stderr_content:
difference.add_comment('stderr from `%s`:' % ' '.join(command2.cmdline()))
difference.add_comment(command2.stderr_content)
return difference
@property
......@@ -364,8 +382,41 @@ class Difference(object):
raise TypeError("'differences' must contains Difference objects'")
self._details.extend(differences)
def get_reverse(self):
if self._unified_diff is None:
unified_diff = None
else:
unified_diff = reverse_unified_diff(self._unified_diff)
logger.debug('reverse orig %s %s', self._source1, self._source2)
difference = Difference(unified_diff, None, None, source=[self._source2, self._source1], comment=self._comments)
difference.add_details([d.get_reverse() for d in self._details])
return difference
def get_source(path1, path2):
if os.path.basename(path1) == os.path.basename(path2):
return os.path.basename(path1)
return None
def reverse_unified_diff(diff):
res = []
for line in diff.splitlines(True): # keepends=True
found = DiffParser.RANGE_RE.match(line)
if found:
before = found.group('start2')
if found.group('len2') is not None:
before += ',' + found.group('len2')
after = found.group('start1')
if found.group('len1') is not None:
after += ',' + found.group('len1')
res.append('@@ -%s +%s @@\n' % (before, after))
elif line.startswith('-'):
res.append('+')
res.append(line[1:])
elif line.startswith('+'):
res.append('-')
res.append(line[1:])
else:
res.append(line)
return ''.join(res)
......@@ -23,7 +23,7 @@ import subprocess
import pytest
from diffoscope.comparators import specialize
import diffoscope.comparators.binary
from diffoscope.comparators.binary import File, FilesystemFile
from diffoscope.comparators.binary import File, FilesystemFile, NonExistingFile
from diffoscope.difference import Difference
from diffoscope import RequiredToolNotFound, tool_required
......@@ -71,6 +71,10 @@ def test_compare_with_xxd(binary1, binary2):
expected_diff = open(os.path.join(os.path.dirname(__file__), '../data/binary_expected_diff')).read()
assert difference.unified_diff == expected_diff
def test_compare_non_existing_with_xxd(binary1):
difference = binary1.compare_bytes(NonExistingFile('/nonexisting', binary1))
assert difference.source2 == '/dev/null'
@pytest.fixture
def xxd_not_found(monkeypatch):
def mock_xxd(path):
......@@ -133,3 +137,9 @@ def test_with_compare_details_and_tool_not_found(monkeypatch):
assert 'nonexistent' in difference.comment
assert 'some-package' in difference.comment
assert difference.unified_diff == expected_diff
def test_compare_two_nonexisting_files():
file1 = NonExistingFile('/nonexisting1')
file2 = NonExistingFile('/nonexisting2')
difference = file1.compare(file2)
assert 'non-existing' in difference.comment
......@@ -22,8 +22,9 @@ import os.path
import shutil
import pytest
from diffoscope.comparators import specialize
from diffoscope.comparators.binary import FilesystemFile
from diffoscope.comparators.binary import FilesystemFile, NonExistingFile
from diffoscope.comparators.bzip2 import Bzip2File
from diffoscope.config import Config
TEST_FILE1_PATH = os.path.join(os.path.dirname(__file__), '../data/test1.bz2')
TEST_FILE2_PATH = os.path.join(os.path.dirname(__file__), '../data/test2.bz2')
......@@ -67,3 +68,8 @@ def test_content_source_without_extension(tmpdir):
def test_content_diff(differences):
expected_diff = open(os.path.join(os.path.dirname(__file__), '../data/text_ascii_expected_diff')).read()
assert differences[0].unified_diff == expected_diff
def test_compare_non_existing(monkeypatch, bzip1):
monkeypatch.setattr(Config, 'new_file', True)
difference = bzip1.compare(NonExistingFile('/nonexisting', bzip1))
assert difference.source2 == '/nonexisting'
......@@ -21,8 +21,9 @@
import os.path
import pytest
from diffoscope.comparators import specialize
from diffoscope.comparators.binary import FilesystemFile
from diffoscope.comparators.binary import FilesystemFile, NonExistingFile
from diffoscope.comparators.cpio import CpioFile
from diffoscope.config import Config
TEST_FILE1_PATH = os.path.join(os.path.dirname(__file__), '../data/test1.cpio')
TEST_FILE2_PATH = os.path.join(os.path.dirname(__file__), '../data/test2.cpio')
......@@ -61,3 +62,9 @@ def test_compressed_files(differences):
assert differences[2].source2 == 'dir/text'
expected_diff = open(os.path.join(os.path.dirname(__file__), '../data/text_ascii_expected_diff')).read()
assert differences[2].unified_diff == expected_diff
def test_compare_non_existing(monkeypatch, cpio1):
monkeypatch.setattr(Config.general, 'new_file', True)
difference = cpio1.compare(NonExistingFile('/nonexisting', cpio1))
assert difference.source2 == '/nonexisting'
assert difference.details[-1].source2 == '/dev/null'
......@@ -22,8 +22,9 @@ import os.path
import pytest
import diffoscope.comparators
from diffoscope.comparators import specialize
from diffoscope.comparators.binary import FilesystemFile
from diffoscope.comparators.binary import FilesystemFile, NonExistingFile
from diffoscope.comparators.deb import DebFile, Md5sumsFile, DebDataTarFile
from diffoscope.config import Config
TEST_FILE1_PATH = os.path.join(os.path.dirname(__file__), '../data/test1.deb')
TEST_FILE2_PATH = os.path.join(os.path.dirname(__file__), '../data/test2.deb')
......@@ -104,3 +105,9 @@ def test_skip_comparison_of_known_identical_files(deb1, deb2, monkeypatch):
monkeypatch.setattr(diffoscope.comparators, 'compare_files', probe)
deb1.compare(deb2)
assert './usr/share/doc/test/README.Debian' not in compared
def test_compare_non_existing(monkeypatch, deb1):
monkeypatch.setattr(Config.general, 'new_file', True)
difference = deb1.compare(NonExistingFile('/nonexisting', deb1))
assert difference.source2 == '/nonexisting'
assert difference.details[-1].source2 == '/dev/null'
......@@ -24,8 +24,9 @@ import os.path
import shutil
import pytest
from diffoscope.comparators import specialize
from diffoscope.comparators.binary import FilesystemFile
from diffoscope.comparators.binary import FilesystemFile, NonExistingFile
from diffoscope.comparators.debian import DotChangesFile
from diffoscope.config import Config
from diffoscope.presenters.text import output_text
TEST_DOT_CHANGES_FILE1_PATH = os.path.join(os.path.dirname(__file__), '../data/test1.changes')
......@@ -71,3 +72,10 @@ def test_description(differences):
def test_internal_diff(differences):
assert differences[2].source1 == 'test_1_all.deb'
def test_compare_non_existing(monkeypatch, dot_changes1):
monkeypatch.setattr(Config.general, 'new_file', True)
difference = dot_changes1.compare(NonExistingFile('/nonexisting', dot_changes1))
output_text(difference, print_func=print)
assert difference.source2 == '/nonexisting'
assert difference.details[-1].source2 == '/dev/null'
......@@ -21,8 +21,9 @@
import os.path
import pytest
from diffoscope.comparators import specialize
from diffoscope.comparators.binary import FilesystemFile
from diffoscope.comparators.binary import FilesystemFile, NonExistingFile
from diffoscope.comparators.elf import ElfFile, StaticLibFile
from diffoscope.config import Config
TEST_OBJ1_PATH = os.path.join(os.path.dirname(__file__), '../data/test1.o')
TEST_OBJ2_PATH = os.path.join(os.path.dirname(__file__), '../data/test2.o')
......@@ -46,6 +47,11 @@ def test_obj_no_differences(obj1):
def obj_differences(obj1, obj2):
return obj1.compare(obj2).details
def test_obj_compare_non_existing(monkeypatch, obj1):
monkeypatch.setattr(Config, 'new_file', True)
difference = obj1.compare(NonExistingFile('/nonexisting', obj1))
assert difference.source2 == '/nonexisting'
def test_diff(obj_differences):
assert len(obj_differences) == 1
expected_diff = open(os.path.join(os.path.dirname(__file__), '../data/elf_obj_expected_diff')).read()
......@@ -81,3 +87,8 @@ def test_lib_differences(lib_differences):
assert 'objdump' in lib_differences[1].source1
expected_objdump_diff = open(os.path.join(os.path.dirname(__file__), '../data/elf_lib_objdump_expected_diff')).read()
assert lib_differences[1].unified_diff == expected_objdump_diff
def test_lib_compare_non_existing(monkeypatch, lib1):
monkeypatch.setattr(Config, 'new_file', True)
difference = lib1.compare(NonExistingFile('/nonexisting', lib1))
assert difference.source2 == '/nonexisting'
......@@ -21,8 +21,9 @@
import os.path
import pytest
from diffoscope.comparators import specialize
from diffoscope.comparators.binary import FilesystemFile
from diffoscope.comparators.binary import FilesystemFile, NonExistingFile
from diffoscope.comparators.fonts import TtfFile
from diffoscope.config import Config
from conftest import tool_missing
TEST_FILE1_PATH = os.path.join(os.path.dirname(__file__), '../data/Samyak-Malayalam1.ttf')
......@@ -51,3 +52,8 @@ def differences(ttf1, ttf2):
def test_diff(differences):
expected_diff = open(os.path.join(os.path.dirname(__file__), '../data/ttf_expected_diff')).read()
assert differences[0].unified_diff == expected_diff
def test_compare_non_existing(monkeypatch, ttf1):
monkeypatch.setattr(Config, 'new_file', True)
difference = ttf1.compare(NonExistingFile('/nonexisting', ttf1))
assert difference.source2 == '/nonexisting'
......@@ -22,8 +22,9 @@ import codecs
import os.path
import pytest
from diffoscope.comparators import specialize
from diffoscope.comparators.binary import FilesystemFile
from diffoscope.comparators.binary import FilesystemFile, NonExistingFile
from diffoscope.comparators.gettext import MoFile
from diffoscope.config import Config
TEST_FILE1_PATH = os.path.join(os.path.dirname(__file__), '../data/test1.mo')
TEST_FILE2_PATH = os.path.join(os.path.dirname(__file__), '../data/test2.mo')
......@@ -63,3 +64,8 @@ def test_charsets(mo_no_charset, mo_iso8859_1):
difference = mo_no_charset.compare(mo_iso8859_1)
expected_diff = codecs.open(os.path.join(os.path.dirname(__file__), '../data/mo_charsets_expected_diff'), encoding='utf-8').read()
assert difference.details[0].unified_diff == expected_diff
def test_compare_non_existing(monkeypatch, mo1):
monkeypatch.setattr(Config, 'new_file', True)
difference = mo1.compare(NonExistingFile('/nonexisting', mo1))
assert difference.source2 == '/nonexisting'
......@@ -22,8 +22,9 @@ import os.path
import shutil
import pytest
from diffoscope.comparators import specialize
from diffoscope.comparators.binary import FilesystemFile
from diffoscope.comparators.binary import FilesystemFile, NonExistingFile
from diffoscope.comparators.gzip import GzipFile
from diffoscope.config import Config
TEST_FILE1_PATH = os.path.join(os.path.dirname(__file__), '../data/test1.gz')
TEST_FILE2_PATH = os.path.join(os.path.dirname(__file__), '../data/test2.gz')
......@@ -71,3 +72,9 @@ def test_content_source_without_extension(tmpdir):
def test_content_diff(differences):
expected_diff = open(os.path.join(os.path.dirname(__file__), '../data/text_ascii_expected_diff')).read()
assert differences[1].unified_diff == expected_diff
def test_compare_non_existing(monkeypatch, gzip1):
monkeypatch.setattr(Config.general, 'new_file', True)
difference = gzip1.compare(NonExistingFile('/nonexisting', gzip1))
assert difference.source2 == '/nonexisting'
assert difference.details[-1].source2 == '/dev/null'