1# 2# diffoscope: in-depth comparison of files, archives, and directories 3# 4# Copyright © 2015 Jérémy Bobbio <lunar@debian.org> 5# Copyright © 2016-2017, 2019-2020 Chris Lamb <lamby@debian.org> 6# 7# diffoscope is free software: you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation, either version 3 of the License, or 10# (at your option) any later version. 11# 12# diffoscope is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with diffoscope. If not, see <https://www.gnu.org/licenses/>. 19 20import struct 21import pytest 22import re 23import subprocess 24 25from diffoscope.comparators.cbfs import CbfsFile 26from diffoscope.comparators.binary import FilesystemFile 27from diffoscope.comparators.utils.specialize import specialize 28 29from ..utils.data import data, get_data 30from ..utils.tools import skip_unless_tools_exist 31from ..utils.nonexisting import assert_non_existing 32 33 34TEST_FILE1_PATH = data("text_ascii1") 35TEST_FILE2_PATH = data("text_ascii2") 36 37 38@pytest.fixture 39def rom1(tmpdir): 40 path = str(tmpdir.join("coreboot1")) 41 42 subprocess.check_call( 43 ("cbfstool", path, "create", "-m", "x86", "-s", "32768") 44 ) 45 46 subprocess.check_call( 47 ( 48 "cbfstool", 49 path, 50 "add", 51 "-f", 52 TEST_FILE1_PATH, 53 "-n", 54 "test file", 55 "-t", 56 "raw", 57 ), 58 ) 59 60 return specialize(FilesystemFile(path)) 61 62 63@pytest.fixture 64def rom2(tmpdir): 65 size = 32768 66 path = str(tmpdir.join("coreboot2.rom")) 67 68 subprocess.check_call( 69 ("cbfstool", path, "create", "-m", "x86", "-s", "%s" % size), 70 ) 71 72 subprocess.check_call( 73 ( 74 "cbfstool", 75 path, 76 "add", 77 "-f", 78 TEST_FILE2_PATH, 79 "-n", 80 "test file", 81 "-t", 82 "raw", 83 ), 84 shell=False, 85 ) 86 87 # Remove the last 4 bytes to exercise the full header search 88 buf = bytearray(size) 89 with open(path, "rb") as f: 90 f.readinto(buf) 91 92 with open(path, "wb") as f: 93 size = struct.unpack_from("!I", buf, offset=len(buf) - 4 - 32 + 8)[0] 94 struct.pack_into("!I", buf, len(buf) - 4 - 32 + 8, size - 4) 95 f.write(buf[:-4]) 96 97 return specialize(FilesystemFile(path)) 98 99 100@skip_unless_tools_exist("cbfstool") 101def test_identification_using_offset(rom1): 102 assert isinstance(rom1, CbfsFile) 103 104 105@skip_unless_tools_exist("cbfstool") 106def test_identification_without_offset(rom2): 107 assert isinstance(rom2, CbfsFile) 108 109 110@skip_unless_tools_exist("cbfstool") 111def test_no_differences(rom1): 112 difference = rom1.compare(rom1) 113 assert difference is None 114 115 116@pytest.fixture 117def differences(rom1, rom2): 118 difference = rom1.compare(rom2) 119 return difference.details 120 121 122@skip_unless_tools_exist("cbfstool") 123def test_listing(differences): 124 # Compares outputs of: "cbfstool $tmpdir/coreboot*.rom print" 125 # 126 # As the output of this command keeps changing slightly (see 127 # https://salsa.debian.org/reproducible-builds/diffoscope/merge_requests/38/ 128 # and the git log of this file), perform only these basic coherence check. 129 130 assert differences[0].source1.startswith("cbfstool") 131 assert re.search(r"\+test file\s.*\sraw\s", differences[0].unified_diff) 132 133 134@skip_unless_tools_exist("cbfstool") 135def test_content(differences): 136 assert differences[1].source1 == "test file" 137 assert differences[1].source2 == "test file" 138 expected_diff = get_data("text_ascii_expected_diff") 139 assert differences[1].unified_diff == expected_diff 140 141 142@skip_unless_tools_exist("cbfstool") 143def test_compare_non_existing(monkeypatch, rom1): 144 assert_non_existing(monkeypatch, rom1) 145