Back to index

obnam  1.1
metadata_tests.py
Go to the documentation of this file.
00001 # Copyright (C) 2009  Lars Wirzenius
00002 #
00003 # This program is free software: you can redistribute it and/or modify
00004 # it under the terms of the GNU General Public License as published by
00005 # the Free Software Foundation, either version 3 of the License, or
00006 # (at your option) any later version.
00007 #
00008 # This program is distributed in the hope that it will be useful,
00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 # GNU General Public License for more details.
00012 #
00013 # You should have received a copy of the GNU General Public License
00014 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
00015 
00016 
00017 import os
00018 import stat
00019 import tempfile
00020 import unittest
00021 
00022 import obnamlib
00023 
00024 
00025 class FakeFS(object):
00026 
00027     def __init__(self):
00028         self.st_atime_sec = 1
00029         self.st_atime_nsec = 11
00030         self.st_blocks = 2
00031         self.st_dev = 3
00032         self.st_gid = 4
00033         self.st_ino = 5
00034         self.st_mode = 6
00035         self.st_mtime_sec = 7
00036         self.st_mtime_nsec = 71
00037         self.st_nlink = 8
00038         self.st_size = 9
00039         self.st_uid = 10
00040         self.groupname = 'group'
00041         self.username = 'user'
00042         self.target = 'target'
00043 
00044     def lstat(self, filename):
00045         return self
00046 
00047     def readlink(self, filename):
00048         return 'target'
00049 
00050     def getpwuid(self, uid):
00051         return (self.username, None, self.st_uid, self.st_gid, 
00052                 None, None, None)
00053     
00054     def getgrgid(self, gid):
00055         return (self.groupname, None, self.st_gid, None)
00056 
00057     def fail_getpwuid(self, uid):
00058         raise KeyError(uid)
00059     
00060     def fail_getgrgid(self, gid):
00061         raise KeyError(gid)
00062 
00063     def llistxattr(self, filename):
00064         return []
00065 
00066 
00067 class MetadataTests(unittest.TestCase):
00068 
00069     def test_sets_mtime_from_kwarg(self):
00070         metadata = obnamlib.Metadata(st_mtime_sec=123)
00071         self.assertEqual(metadata.st_mtime_sec, 123)
00072 
00073     def test_isdir_returns_false_for_regular_file(self):
00074         metadata = obnamlib.Metadata(st_mode=stat.S_IFREG)
00075         self.assertFalse(metadata.isdir())
00076 
00077     def test_isdir_returns_true_for_directory(self):
00078         metadata = obnamlib.Metadata(st_mode=stat.S_IFDIR)
00079         self.assert_(metadata.isdir())
00080 
00081     def test_isdir_returns_false_when_st_mode_is_not_set(self):
00082         metadata = obnamlib.Metadata()
00083         self.assertFalse(metadata.isdir())
00084 
00085     def test_islink_returns_false_for_regular_file(self):
00086         metadata = obnamlib.Metadata(st_mode=stat.S_IFREG)
00087         self.assertFalse(metadata.islink())
00088 
00089     def test_islink_returns_true_for_symlink(self):
00090         metadata = obnamlib.Metadata(st_mode=stat.S_IFLNK)
00091         self.assert_(metadata.islink())
00092 
00093     def test_islink_returns_false_when_st_mode_is_not_set(self):
00094         metadata = obnamlib.Metadata()
00095         self.assertFalse(metadata.islink())
00096 
00097     def test_isfile_returns_true_for_regular_file(self):
00098         metadata = obnamlib.Metadata(st_mode=stat.S_IFREG)
00099         self.assert_(metadata.isfile())
00100 
00101     def test_isfile_returns_false_when_st_mode_is_not_set(self):
00102         metadata = obnamlib.Metadata()
00103         self.assertFalse(metadata.isfile())
00104 
00105     def test_has_no_md5_by_default(self):
00106         metadata = obnamlib.Metadata()
00107         self.assertEqual(metadata.md5, None)
00108 
00109     def test_sets_md5(self):
00110         metadata = obnamlib.Metadata(md5='checksum')
00111         self.assertEqual(metadata.md5, 'checksum')
00112 
00113     def test_is_equal_to_itself(self):
00114         metadata = obnamlib.Metadata(st_mode=stat.S_IFREG)
00115         self.assertEqual(metadata, metadata)
00116 
00117     def test_less_than_works(self):
00118         m1 = obnamlib.Metadata(st_size=1)
00119         m2 = obnamlib.Metadata(st_size=2)
00120         self.assert_(m1 < m2)
00121 
00122     def test_greater_than_works(self):
00123         m1 = obnamlib.Metadata(st_size=1)
00124         m2 = obnamlib.Metadata(st_size=2)
00125         self.assert_(m2 > m1)
00126 
00127 
00128 class ReadMetadataTests(unittest.TestCase):
00129 
00130     def setUp(self):
00131         self.fakefs = FakeFS()
00132 
00133     def test_returns_stat_fields_correctly(self):
00134         metadata = obnamlib.read_metadata(self.fakefs, 'foo', 
00135                                           getpwuid=self.fakefs.getpwuid,
00136                                           getgrgid=self.fakefs.getgrgid)
00137         fields = ['st_atime_sec','st_atime_nsec', 'st_blocks', 'st_dev', 
00138                   'st_gid', 'st_ino', 'st_mode', 'st_mtime_sec', 
00139                   'st_mtime_nsec', 'st_nlink', 'st_size', 'st_uid',
00140                   'groupname', 'username']
00141         for field in fields:
00142             self.assertEqual(getattr(metadata, field),
00143                              getattr(self.fakefs, field),
00144                              field)
00145 
00146     def test_returns_symlink_fields_correctly(self):
00147         self.fakefs.st_mode |= stat.S_IFLNK;
00148         metadata = obnamlib.read_metadata(self.fakefs, 'foo', 
00149                                           getpwuid=self.fakefs.getpwuid,
00150                                           getgrgid=self.fakefs.getgrgid)
00151         fields = ['st_mode', 'target']
00152         for field in fields:
00153             self.assertEqual(getattr(metadata, field),
00154                              getattr(self.fakefs, field),
00155                              field)
00156 
00157     def test_reads_username_as_None_if_lookup_fails(self):
00158         metadata = obnamlib.read_metadata(self.fakefs, 'foo',
00159                                           getpwuid=self.fakefs.fail_getpwuid,
00160                                           getgrgid=self.fakefs.fail_getgrgid)
00161         self.assertEqual(metadata.username, None)
00162 
00163 
00164 class SetMetadataTests(unittest.TestCase):
00165 
00166     def setUp(self):
00167         self.metadata = obnamlib.Metadata()
00168         self.metadata.st_atime_sec = 12765
00169         self.metadata.st_atime_nsec = 0
00170         self.metadata.st_mode = 42 | stat.S_IFREG
00171         self.metadata.st_mtime_sec = 10**9
00172         self.metadata.st_mtime_nsec = 0
00173         self.metadata.st_uid = 1234
00174         self.metadata.st_gid = 5678
00175         
00176         fd, self.filename = tempfile.mkstemp()
00177         os.close(fd)
00178         
00179         self.fs = obnamlib.LocalFS('/')
00180         self.fs.connect()
00181 
00182         self.uid_set = None
00183         self.gid_set = None
00184         self.fs.lchown = self.fake_lchown
00185 
00186         obnamlib.set_metadata(self.fs, self.filename, self.metadata)
00187         
00188         self.st = os.stat(self.filename)
00189         
00190     def tearDown(self):
00191         self.fs.close()
00192         os.remove(self.filename)
00193 
00194     def fake_lchown(self, filename, uid, gid):
00195         self.uid_set = uid
00196         self.gid_set = gid
00197         
00198     def test_sets_atime(self):
00199         self.assertEqual(self.st.st_atime, self.metadata.st_atime_sec)
00200 
00201     def test_sets_mode(self):
00202         self.assertEqual(self.st.st_mode, self.metadata.st_mode)
00203 
00204     def test_sets_mtime(self):
00205         self.assertEqual(self.st.st_mtime, self.metadata.st_mtime_sec)
00206 
00207     def test_does_not_set_uid_when_not_running_as_root(self):
00208         self.assertEqual(self.st.st_uid, os.getuid())
00209 
00210     def test_does_not_set_gid_when_not_running_as_root(self):
00211         self.assertEqual(self.st.st_gid, os.getgid())
00212 
00213     def test_sets_uid_when_running_as_root(self):
00214         obnamlib.set_metadata(self.fs, self.filename, self.metadata,
00215                               getuid=lambda: 0)
00216         self.assertEqual(self.uid_set, self.metadata.st_uid)
00217 
00218     def test_sets_gid_when_running_as_root(self):
00219         obnamlib.set_metadata(self.fs, self.filename, self.metadata,
00220                               getuid=lambda: 0)
00221         self.assertEqual(self.gid_set, self.metadata.st_gid)
00222 
00223     def test_sets_symlink_target(self):
00224         self.fs.remove(self.filename)
00225         self.metadata.st_mode = 0777 | stat.S_IFLNK;
00226         self.metadata.target = 'target'
00227         obnamlib.set_metadata(self.fs, self.filename, self.metadata)
00228         self.assertEqual(self.fs.readlink(self.filename), 'target')
00229 
00230     def test_sets_symlink_mtime_perms(self):
00231         self.fs.remove(self.filename)
00232         self.metadata.st_mode = 0777 | stat.S_IFLNK;
00233         self.metadata.target = 'target'
00234         obnamlib.set_metadata(self.fs, self.filename, self.metadata)
00235         st = os.lstat(self.filename)
00236         self.assertEqual(st.st_mode, self.metadata.st_mode)
00237         self.assertEqual(st.st_mtime, self.metadata.st_mtime_sec)
00238 
00239 
00240 class MetadataCodingTests(unittest.TestCase):
00241 
00242     def test_round_trip(self):
00243         metadata = obnamlib.metadata.Metadata(st_mode=1, 
00244                                               st_mtime_sec=2, 
00245                                               st_mtime_nsec=12756,
00246                                               st_nlink=3,
00247                                               st_size=4, 
00248                                               st_uid=5, 
00249                                               st_blocks=6, 
00250                                               st_dev=7,
00251                                               st_gid=8, 
00252                                               st_ino=9,  
00253                                               st_atime_sec=10, 
00254                                               st_atime_nsec=123, 
00255                                               groupname='group',
00256                                               username='user',
00257                                               target='target',
00258                                               md5='checksum')
00259         encoded = obnamlib.encode_metadata(metadata)
00260         decoded = obnamlib.decode_metadata(encoded)
00261         for name in dir(metadata):
00262             if name in obnamlib.metadata.metadata_fields:
00263                 self.assertEqual(getattr(metadata, name), 
00264                                  getattr(decoded, name),
00265                                  'attribute %s must be equal (%s vs %s)' % 
00266                                     (name, getattr(metadata, name),
00267                                      getattr(decoded, name)))
00268 
00269     def test_round_trip_for_None_values(self):
00270         metadata = obnamlib.metadata.Metadata()
00271         encoded = obnamlib.encode_metadata(metadata)
00272         decoded = obnamlib.decode_metadata(encoded)
00273         for name in dir(metadata):
00274             if name in obnamlib.metadata.metadata_fields:
00275                 self.assertEqual(getattr(decoded, name), None,
00276                                  'attribute %s must be None' % name)
00277