add unit test tracking behavior wrt symlinks
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Fri, 4 Nov 2016 10:59:34 +0000 (11:59 +0100)
committerPhilipp Gesang <philipp.gesang@intra2net.com>
Fri, 4 Nov 2016 10:59:34 +0000 (11:59 +0100)
testing/__init__.py
testing/test_deltatar.py

index c538fef..527c751 100644 (file)
@@ -60,12 +60,21 @@ class BaseTest(unittest.TestCase):
             write_handle.write(data[:remainder])
         return self.md5sum(path)
 
-    def md5sum(self, filename):
+    def create_symlink(self, linkname, path):
+        os.symlink(linkname, path)
+        return self.md5sum(path, linkname=linkname)
+
+    def md5sum(self, filename, linkname=None):
         '''
-        Returns the md5sum of a file specified by its filename/path
+        Returns the md5sum of a file specified by its filename/path or, if
+        ``linkname`` is specified, the hash of both paths (for symlinks).
         '''
         md5 = hashlib.md5()
-        with open(filename,'rb') as f:
-            for chunk in iter(lambda: f.read(128*md5.block_size), b''):
-                md5.update(chunk)
+        if linkname is None:
+            with open(filename,'rb') as f:
+                for chunk in iter(lambda: f.read(128*md5.block_size), b''):
+                    md5.update(chunk)
+        else: # symlink; hash paths
+            md5.update(filename.encode("UTF-8"))
+            md5.update(linkname.encode("UTF-8"))
         return md5.hexdigest()
index 8c8f67b..ca3e8cb 100644 (file)
@@ -16,6 +16,7 @@
 
 # Author: Eduardo Robles Elvira <edulix@wadobo.com>
 
+import errno
 import os
 import re
 import random
@@ -34,6 +35,8 @@ import filesplit
 from . import BaseTest
 from . import new_volume_handler
 
+SYMLINK_GOOD = 0
+SYMLINK_BAD = 1
 
 class DeltaTarTest(BaseTest):
     """
@@ -1389,6 +1392,53 @@ class DeltaTarTest(BaseTest):
                 print("TITEM: " + str(titem))
                 raise e
 
+    def test_create_no_symlinks(self):
+        '''
+        Creates a full backup from different varieties of symlinks. The
+        extracted archive may not contain any symlinks but the file contents
+        '''
+
+        os.system("rm -rf source_dir")
+        os.makedirs("source_dir/symlinks")
+        fd = os.open("source_dir/symlinks/valid_linkname",
+                     os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644)
+        os.write(fd, b"valid link target for symlink tests; please ignore\n")
+        os.close(fd)
+        # first one is good, the rest points nowhere
+        self.create_symlink("valid_linkname", "source_dir/symlinks/whatever")
+        self.create_symlink("/foo/bar/baz", "source_dir/symlinks/xyzzy")
+        self.create_symlink("burp/../buzz", "source_dir/symlinks/blup")
+        self.create_symlink("../../../../biz", "source_dir/symlinks/bleep")
+        deltatar = DeltaTar(mode=self.MODE, password=self.PASSWORD,
+                            logger=self.consoleLogger)
+
+        # create first backup
+        deltatar.create_full_backup(source_path="source_dir",
+                                    backup_path="backup_dir")
+
+        assert os.path.exists("backup_dir")
+        shutil.rmtree("source_dir")
+        assert not os.path.exists("source_dir")
+
+        tar_filename = deltatar.volume_name_func('backup_dir', True, 0)
+        tar_path = os.path.join("backup_dir", tar_filename)
+
+        deltatar.restore_backup(target_path="source_dir",
+                                backup_tar_path=tar_path)
+
+        for _r, _ds, fs in os.walk("source_dir/symlinks"):
+        # only the valid link plus the linked file may be found in the
+        # extracted archive
+            assert len(fs) == 2
+            for f in fs:
+                # the link must have been resolved and file contents must match
+                # the linked file
+                assert not os.path.islink(f)
+                with open("source_dir/symlinks/valid_linkname") as a:
+                    with open("source_dir/symlinks/whatever") as b:
+                        assert a.read() == b.read()
+
+
 class DeltaTar2Test(DeltaTarTest):
     '''
     Same as DeltaTar but with specific ":" mode