|
@@ -6,6 +6,8 @@ import sys
|
|
|
import tempfile
|
|
|
from unittest.mock import patch
|
|
|
|
|
|
+import msgpack
|
|
|
+
|
|
|
import pytest
|
|
|
|
|
|
from ..hashindex import NSIndex
|
|
@@ -555,6 +557,63 @@ class RepositoryAuxiliaryCorruptionTestCase(RepositoryTestCaseBase):
|
|
|
with self.assert_raises(OSError):
|
|
|
self.do_commit()
|
|
|
|
|
|
+ def test_unknown_integrity_version(self):
|
|
|
+ integrity_path = os.path.join(self.repository.path, 'integrity.1')
|
|
|
+ with open(integrity_path, 'r+b') as fd:
|
|
|
+ msgpack.pack({
|
|
|
+ b'version': 4.7,
|
|
|
+ }, fd)
|
|
|
+ fd.truncate()
|
|
|
+ with self.repository:
|
|
|
+ assert len(self.repository) == 1
|
|
|
+ assert self.repository.get(H(0)) == b'foo'
|
|
|
+
|
|
|
+ def _subtly_corrupted_hints_setup(self):
|
|
|
+ with self.repository:
|
|
|
+ self.repository.append_only = True
|
|
|
+ assert len(self.repository) == 1
|
|
|
+ assert self.repository.get(H(0)) == b'foo'
|
|
|
+ self.repository.put(H(1), b'bar')
|
|
|
+ self.repository.put(H(2), b'baz')
|
|
|
+ self.repository.commit()
|
|
|
+ self.repository.put(H(2), b'bazz')
|
|
|
+ self.repository.commit()
|
|
|
+
|
|
|
+ hints_path = os.path.join(self.repository.path, 'hints.5')
|
|
|
+ with open(hints_path, 'r+b') as fd:
|
|
|
+ hints = msgpack.unpack(fd)
|
|
|
+ fd.seek(0)
|
|
|
+ # Corrupt segment refcount
|
|
|
+ assert hints[b'segments'][2] == 1
|
|
|
+ hints[b'segments'][2] = 0
|
|
|
+ msgpack.pack(hints, fd)
|
|
|
+ fd.truncate()
|
|
|
+
|
|
|
+ def test_subtly_corrupted_hints(self):
|
|
|
+ self._subtly_corrupted_hints_setup()
|
|
|
+ with self.repository:
|
|
|
+ self.repository.append_only = False
|
|
|
+ self.repository.put(H(3), b'1234')
|
|
|
+ # Do a compaction run. Succeeds, since the failed checksum prompted a rebuild of the index+hints.
|
|
|
+ self.repository.commit()
|
|
|
+
|
|
|
+ assert len(self.repository) == 4
|
|
|
+ assert self.repository.get(H(0)) == b'foo'
|
|
|
+ assert self.repository.get(H(1)) == b'bar'
|
|
|
+ assert self.repository.get(H(2)) == b'bazz'
|
|
|
+
|
|
|
+ def test_subtly_corrupted_hints_without_integrity(self):
|
|
|
+ self._subtly_corrupted_hints_setup()
|
|
|
+ integrity_path = os.path.join(self.repository.path, 'integrity.5')
|
|
|
+ os.unlink(integrity_path)
|
|
|
+ with self.repository:
|
|
|
+ self.repository.append_only = False
|
|
|
+ self.repository.put(H(3), b'1234')
|
|
|
+ # Do a compaction run. Fails, since the corrupted refcount was not detected and leads to an assertion failure.
|
|
|
+ with pytest.raises(AssertionError) as exc_info:
|
|
|
+ self.repository.commit()
|
|
|
+ assert 'Corrupted segment reference count' in str(exc_info.value)
|
|
|
+
|
|
|
|
|
|
class RepositoryCheckTestCase(RepositoryTestCaseBase):
|
|
|
|