mirror of
https://github.com/borgbackup/borg.git
synced 2025-02-20 21:27:32 +00:00
repository: add complementary index corruption test
This commit is contained in:
parent
2e067a7ae8
commit
54e023c75a
2 changed files with 36 additions and 6 deletions
|
@ -490,6 +490,8 @@ def rename_tmp(file):
|
|||
b'storage_quota_use': self.storage_quota_use,
|
||||
}
|
||||
integrity = {
|
||||
# Integrity version started at 2, the current hints version.
|
||||
# Thus, integrity version == hints version, for now.
|
||||
b'version': 2,
|
||||
}
|
||||
transaction_id = self.io.get_segments_transaction_id()
|
||||
|
|
|
@ -503,11 +503,6 @@ def setUp(self):
|
|||
self.repository.commit()
|
||||
self.repository.close()
|
||||
|
||||
def corrupt(self, file):
|
||||
with open(file, 'r+b') as fd:
|
||||
fd.seek(-1, io.SEEK_END)
|
||||
fd.write(b'1')
|
||||
|
||||
def do_commit(self):
|
||||
with self.repository:
|
||||
self.repository.put(H(0), b'fox')
|
||||
|
@ -544,12 +539,42 @@ def test_index_outside_transaction(self):
|
|||
with self.repository:
|
||||
assert len(self.repository) == 1
|
||||
|
||||
def _corrupt_index(self):
|
||||
# HashIndex is able to detect incorrect headers and file lengths,
|
||||
# but on its own it can't tell if the data is correct.
|
||||
index_path = os.path.join(self.repository.path, 'index.1')
|
||||
with open(index_path, 'r+b') as fd:
|
||||
index_data = fd.read()
|
||||
# Flip one bit in a key stored in the index
|
||||
corrupted_key = (int.from_bytes(H(0), 'little') ^ 1).to_bytes(32, 'little')
|
||||
corrupted_index_data = index_data.replace(H(0), corrupted_key)
|
||||
assert corrupted_index_data != index_data
|
||||
assert len(corrupted_index_data) == len(index_data)
|
||||
fd.seek(0)
|
||||
fd.write(corrupted_index_data)
|
||||
|
||||
def test_index_corrupted(self):
|
||||
self.corrupt(os.path.join(self.repository.path, 'index.1'))
|
||||
# HashIndex is able to detect incorrect headers and file lengths,
|
||||
# but on its own it can't tell if the data itself is correct.
|
||||
self._corrupt_index()
|
||||
with self.repository:
|
||||
# Data corruption is detected due to mismatching checksums
|
||||
# and fixed by rebuilding the index.
|
||||
assert len(self.repository) == 1
|
||||
assert self.repository.get(H(0)) == b'foo'
|
||||
|
||||
def test_index_corrupted_without_integrity(self):
|
||||
self._corrupt_index()
|
||||
integrity_path = os.path.join(self.repository.path, 'integrity.1')
|
||||
os.unlink(integrity_path)
|
||||
with self.repository:
|
||||
# Since the corrupted key is not noticed, the repository still thinks
|
||||
# it contains one key...
|
||||
assert len(self.repository) == 1
|
||||
with pytest.raises(Repository.ObjectNotFound):
|
||||
# ... but the real, uncorrupted key is not found in the corrupted index.
|
||||
self.repository.get(H(0))
|
||||
|
||||
def test_unreadable_index(self):
|
||||
index = os.path.join(self.repository.path, 'index.1')
|
||||
os.unlink(index)
|
||||
|
@ -558,13 +583,16 @@ def test_unreadable_index(self):
|
|||
self.do_commit()
|
||||
|
||||
def test_unknown_integrity_version(self):
|
||||
# For now an unknown integrity data version is ignored and not an error.
|
||||
integrity_path = os.path.join(self.repository.path, 'integrity.1')
|
||||
with open(integrity_path, 'r+b') as fd:
|
||||
msgpack.pack({
|
||||
# Borg only understands version 2
|
||||
b'version': 4.7,
|
||||
}, fd)
|
||||
fd.truncate()
|
||||
with self.repository:
|
||||
# No issues accessing the repository
|
||||
assert len(self.repository) == 1
|
||||
assert self.repository.get(H(0)) == b'foo'
|
||||
|
||||
|
|
Loading…
Reference in a new issue