, RecoverCorruptTrailingDataGZAESMultiTest \
, RecoverCorruptVolumeTest \
, RecoverCorruptVolumeGZTest \
- , RecoverCorruptVolumeGZAESTest
+ , RecoverCorruptVolumeGZAESTest \
+ , RecoverCorruptHoleTest \
+ , RecoverCorruptHoleGZTest \
+ , RecoverCorruptHoleGZAESTest
from testing.test_rescue_tar import RescueTarTest
from testing.test_encryption import EncryptionTest
from testing.test_deltatar import (DeltaTarTest, DeltaTar2Test,
, RecoverCorruptVolumeTest
, RecoverCorruptVolumeGZTest
, RecoverCorruptVolumeGZAESTest
+ , RecoverCorruptHoleTest
+ , RecoverCorruptHoleGZTest
+ , RecoverCorruptHoleGZAESTest
]:
try:
t = group (n)
import logging
import os
import shutil
+import stat
import deltatar.deltatar as deltatar
import deltatar.crypto as crypto
return True
+###############################################################################
+## corruption simulators ##
+###############################################################################
+
def corrupt_header (_, fname, compress, encrypt):
"""
Modify a significant byte in the object header of the format.
os.close (fd)
+def corrupt_hole (_, fname, compress, encrypt):
+ """
+ Cut file in three pieces, reassemble without the middle one.
+ """
+ aname = os.path.abspath (fname)
+ infd = os.open (fname, os.O_RDONLY)
+ size = os.lseek (infd, 0, os.SEEK_END)
+ assert os.lseek (infd, 0, os.SEEK_SET) == 0
+ assert size > 3 * TEST_BLOCKSIZE
+ hole = (size / 3, size * 2 / 3)
+ outfd = os.open (os.path.dirname (aname), os.O_WRONLY | os.O_TMPFILE,
+ stat.S_IRUSR | stat.S_IWUSR)
+
+ zeros = bytes (b'\x00' * TEST_BLOCKSIZE)
+ done = 0
+ while done < size:
+ data = os.read (infd, TEST_BLOCKSIZE)
+ if done < hole [0] or hole [1] < done:
+ # only copy from outside hole
+ os.write (outfd, data)
+ done += len (data)
+
+ os.close (infd)
+ os.unlink (fname)
+
+ path = "/proc/self/fd/%d" % outfd
+ os.link (path, aname, src_dir_fd=0, follow_symlinks=True)
+ os.close (outfd)
+
+
###############################################################################
## tests ##
###############################################################################
class RecoverCorruptVolumeTest (RecoverCorruptVolumeBaseTest):
pass
-class RecoverCorruptVolumeGZTest (RecoverTest):
+class RecoverCorruptVolumeGZTest (RecoverCorruptVolumeBaseTest):
+ COMPRESSION = "#gz"
+
+class RecoverCorruptVolumeGZAESTest (RecoverCorruptVolumeBaseTest):
COMPRESSION = "#gz"
+ PASSWORD = TEST_PASSWORD
+
+
+class RecoverCorruptHoleBaseTest (RecoverTest):
+ """
+ Cut bytes from the middle of a volume.
+
+ Index-based recovery works only up to the hole.
+ """
+ COMPRESSION = None
PASSWORD = None
- FAILURES = 8
- CORRUPT = corrupt_volume
- VOLUMES = 3
+ FAILURES = 3
+ CORRUPT = corrupt_hole
+ VOLUMES = 2 # request two vols to swell up the first one
+ MISMATCHES = 1
+
+class RecoverCorruptHoleTest (RecoverCorruptHoleBaseTest):
+ FAILURES = 2
+
+class RecoverCorruptHoleGZTest (RecoverCorruptHoleBaseTest):
+ COMPRESSION = "#gz"
+ MISSING = 2
-class RecoverCorruptVolumeGZAESTest (RecoverTest):
+class RecoverCorruptHoleGZAESTest (RecoverCorruptHoleBaseTest):
COMPRESSION = "#gz"
PASSWORD = TEST_PASSWORD
- FAILURES = 8
- CORRUPT = corrupt_volume
- VOLUMES = 3
+ MISSING = 2