File: location_map_hardlinks_test.py

package info (click to toggle)
rdiff-backup 2.2.6-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,640 kB
  • sloc: python: 24,129; javascript: 9,512; sh: 1,230; ansic: 580; makefile: 36
file content (89 lines) | stat: -rw-r--r-- 3,459 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
"""
Test the handling of hardlinks with api version >= 201
"""
import os
import unittest

import commontest as comtst
import fileset


class LocationMapHardlinksTest(unittest.TestCase):
    """
    Test that rdiff-backup properly handles hardlinks
    """

    def setUp(self):
        self.base_dir = os.path.join(comtst.abs_test_dir,
                                     b"location_map_hardlinks")
        self.from1_struct = {
            "from1": {"contents": {
                "hardlink1": {"content": "initial", "inode": "hardlink1"},
                "hardlink2": {"inode": "hardlink1"},
                "hardlink3": {"inode": "hardlink1"},
            }}
        }
        self.from1_path = os.path.join(self.base_dir, b"from1")
        fileset.create_fileset(self.base_dir, self.from1_struct)
        fileset.remove_fileset(self.base_dir, {"bak": {"type": "dir"}})
        fileset.remove_fileset(self.base_dir, {"to1": {"type": "dir"}})
        self.bak_path = os.path.join(self.base_dir, b"bak")
        self.to1_path = os.path.join(self.base_dir, b"to1")
        self.success = False

    def test_location_map_hardlinks_rotate(self):
        """
        verify that hardlinked files can be rotated, see issue #272
        i.e. first one removed and new one added.
        """
        # backup a 1st time
        self.assertEqual(comtst.rdiff_backup_action(
            True, True, self.from1_path, self.bak_path,
            ("--api-version", "201", "--current-time", "10000"),
            b"backup", ()), 0)

        # kind of rotate the hard linked file
        os.remove(os.path.join(self.from1_path, b'hardlink1'))
        os.link(os.path.join(self.from1_path, b'hardlink3'),
                os.path.join(self.from1_path, b'hardlink4'))

        # backup a 2nd time
        self.assertEqual(comtst.rdiff_backup_action(
            True, True, self.from1_path, self.bak_path,
            ("--api-version", "201", "--current-time", "20000"),
            b"backup", ()), 0)

        # verify that the files still have the same inode in the repo
        self.assertEqual(
            os.lstat(os.path.join(self.bak_path, b'hardlink2')).st_ino,
            os.lstat(os.path.join(self.bak_path, b'hardlink3')).st_ino)
        self.assertEqual(
            os.lstat(os.path.join(self.bak_path, b'hardlink3')).st_ino,
            os.lstat(os.path.join(self.bak_path, b'hardlink4')).st_ino)

        # restore the hardlinked files
        self.assertEqual(comtst.rdiff_backup_action(
            True, True, self.bak_path, self.to1_path,
            ("--api-version", "201"), b"restore", ()), 0)

        # verify that the files have been properly restored with same inodes
        self.assertEqual(
            os.lstat(os.path.join(self.to1_path, b'hardlink2')).st_ino,
            os.lstat(os.path.join(self.to1_path, b'hardlink3')).st_ino)
        self.assertEqual(
            os.lstat(os.path.join(self.to1_path, b'hardlink3')).st_ino,
            os.lstat(os.path.join(self.to1_path, b'hardlink4')).st_ino)

        # all tests were successful
        self.success = True

    def tearDown(self):
        # we clean-up only if the test was successful
        if self.success:
            fileset.remove_fileset(self.base_dir, self.from1_struct)
            fileset.remove_fileset(self.base_dir, {"bak": {"type": "dir"}})
            fileset.remove_fileset(self.base_dir, {"to1": {"type": "dir"}})


if __name__ == "__main__":
    unittest.main()