From 3692fd8273fb3d823d17ff40f968bb83090c5022 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Tue, 15 Aug 2017 16:54:30 +0200 Subject: [PATCH] test corruption by tearing a hole in a volume --- runtests.py | 8 +++++- testing/test_recover.py | 70 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/runtests.py b/runtests.py index eb81a83..c03a7df 100755 --- a/runtests.py +++ b/runtests.py @@ -49,7 +49,10 @@ from testing.test_recover import \ , 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, @@ -111,6 +114,9 @@ if __name__ == "__main__": , RecoverCorruptVolumeTest , RecoverCorruptVolumeGZTest , RecoverCorruptVolumeGZAESTest + , RecoverCorruptHoleTest + , RecoverCorruptHoleGZTest + , RecoverCorruptHoleGZAESTest ]: try: t = group (n) diff --git a/testing/test_recover.py b/testing/test_recover.py index e936e89..91b10f7 100644 --- a/testing/test_recover.py +++ b/testing/test_recover.py @@ -1,6 +1,7 @@ import logging import os import shutil +import stat import deltatar.deltatar as deltatar import deltatar.crypto as crypto @@ -77,6 +78,10 @@ def is_pdt_encrypted (fname): return True +############################################################################### +## corruption simulators ## +############################################################################### + def corrupt_header (_, fname, compress, encrypt): """ Modify a significant byte in the object header of the format. @@ -148,6 +153,36 @@ def corrupt_volume (_, fname, compress, encrypt): 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 ## ############################################################################### @@ -503,17 +538,36 @@ class RecoverCorruptVolumeBaseTest (RecoverTest): 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 -- 1.7.1