add recover tests for completely damaged headers
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Fri, 11 Aug 2017 08:53:09 +0000 (10:53 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Mon, 2 Apr 2018 11:34:09 +0000 (13:34 +0200)
runtests.py
testing/test_recover.py

index 2ed85cb..6e25aba 100755 (executable)
@@ -28,7 +28,10 @@ from testing.test_recover import \
     , RecoverCorruptPayloadGZAESTest \
     , RecoverCorruptHeaderTest \
     , RecoverCorruptHeaderGZTest \
-    , RecoverCorruptHeaderGZAESTest
+    , RecoverCorruptHeaderGZAESTest \
+    , RecoverCorruptEntireHeaderTest \
+    , RecoverCorruptEntireHeaderGZTest \
+    , RecoverCorruptEntireHeaderGZAESTest
 from testing.test_rescue_tar import RescueTarTest
 from testing.test_encryption import EncryptionTest
 from testing.test_deltatar import (DeltaTarTest, DeltaTar2Test,
@@ -69,6 +72,9 @@ if __name__ == "__main__":
                          , RecoverCorruptHeaderTest
                          , RecoverCorruptHeaderGZTest
                          , RecoverCorruptHeaderGZAESTest
+                         , RecoverCorruptEntireHeaderTest
+                         , RecoverCorruptEntireHeaderGZTest
+                         , RecoverCorruptEntireHeaderGZAESTest
                          ]:
                 try:
                     t = group (n)
index fd85707..9f584e0 100644 (file)
@@ -26,6 +26,8 @@ def flip_bits (fname, off, b=0x01, n=1):
         assert pos == off
         chunk = os.read (fd, n)
         chunk = bytes (map (lambda v: v ^ b, chunk))
+        pos = os.lseek (fd, off, os.SEEK_SET)
+        assert pos == off
         os.write (fd, chunk)
     finally:
         os.close (fd)
@@ -54,6 +56,7 @@ def gz_header_size (fname, off=0):
 
     return off
 
+
 def is_pdt_encrypted (fname):
     """
     Returns true if the file contains at least one PDT header plus enough
@@ -91,6 +94,18 @@ def corrupt_header (_, fname, compress, encrypt):
         flip_bits (fname, 100 + 8 + 8 + 8 + 12 + 12 + 1)
 
 
+def corrupt_entire_header (_, fname, compress, encrypt):
+    """
+    Flip all bits in the first object header.
+    """
+    if encrypt is True:
+        flip_bits (fname, 0, 0xff, crypto.PDTCRYPT_HDR_SIZE)
+    elif compress is True: # invalidate magic
+        flip_bits (fname, 0, 0xff, gz_header_size (fname))
+    else:
+        flip_bits (fname, 0, 0xff, tarfile.BLOCKSIZE)
+
+
 def corrupt_payload_start (_, fname, compress, encrypt):
     """
     Modify the byte following the object header structure of the format.
@@ -145,9 +160,9 @@ class RecoverTest (BaseTest):
         os.system("rm -rf source_dir source_dir2 backup_dir*")
 
 
-    def test_recover_corrupt_byte (self):
+    def test_recover_corrupt (self):
         """
-        Flip a bit in a non-header byte of a backup set, then recover.
+        Perform various damaging actions that cause unreadable objects.
 
         Expects the extraction to fail in normal mode. With disaster recovery,
         extraction must succeed, and exactly one file must be missing.
@@ -224,7 +239,6 @@ class RecoverTest (BaseTest):
                                          "%s/%s" % (bak_path, index_file)
                                      ])
 
-        print("¤¤¤ failed", failed)
         assert len (failed) == self.FAILURES
 
         # with one file missing
@@ -278,3 +292,24 @@ class RecoverCorruptHeaderGZAESTest (RecoverTest):
     FAILURES    = 1
     CORRUPT     = corrupt_header
 
+
+class RecoverCorruptEntireHeaderTest (RecoverTest):
+    COMPRESSION = None
+    PASSWORD    = None
+    FAILURES    = 1
+    CORRUPT     = corrupt_entire_header
+
+
+class RecoverCorruptEntireHeaderGZTest (RecoverTest):
+    COMPRESSION = "#gz"
+    PASSWORD    = None
+    FAILURES    = 1
+    CORRUPT     = corrupt_entire_header
+
+
+class RecoverCorruptEntireHeaderGZAESTest (RecoverTest):
+    COMPRESSION = "#gz"
+    PASSWORD    = TEST_PASSWORD
+    FAILURES    = 1
+    CORRUPT     = corrupt_entire_header
+