4 """Unittests for the posix1e module"""
6 # Copyright (C) 2002-2008 Iustin Pop <iusty@k1024.org>
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Lesser General Public License for more details.
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 TEST_DIR = os.environ.get("TESTDIR", ".")
33 BASIC_ACL_TEXT = "u::rw,g::r,o::-"
36 """Wrapper to skip a test"""
37 new_fn = lambda x: None
38 new_fn.__doc__ = "SKIPPED %s" % fn.__doc__
42 def has_ext(extension):
43 """Decorator to skip tests based on platform support"""
51 """Support functions ACLs"""
59 """tear down function"""
60 for fname in self.rmfiles:
62 for dname in self.rmdirs:
66 """create a temp file"""
67 fh, fname = tempfile.mkstemp(".test", "xattr-", TEST_DIR)
68 self.rmfiles.append(fname)
72 """create a temp dir"""
73 dname = tempfile.mkdtemp(".test", "xattr-", TEST_DIR)
74 self.rmdirs.append(dname)
77 def _getsymlink(self):
78 """create a symlink"""
79 fh, fname = self._getfile()
82 os.symlink(fname + ".non-existent", fname)
86 class LoadTests(aclTest, unittest.TestCase):
87 """Load/create tests"""
88 def testFromFile(self):
89 """Test loading ACLs from a file"""
90 _, fname = self._getfile()
91 acl1 = posix1e.ACL(file=fname)
92 self.failUnless(acl1.valid(), "ACL read from file should be valid")
94 def testFromDir(self):
95 """Test loading ACLs from a directory"""
96 dname = self._getdir()
97 acl1 = posix1e.ACL(file=dname)
98 acl2 = posix1e.ACL(filedef=dname)
99 self.failUnless(acl1.valid(),
100 "ACL read from directory should be valid")
101 # default ACLs might or might not be valid; missing ones are
102 # not valid, so we don't test acl2 for validity
104 def testFromFd(self):
105 """Test loading ACLs from a file descriptor"""
106 fd, _ = self._getfile()
107 acl1 = posix1e.ACL(fd=fd)
108 self.failUnless(acl1.valid(), "ACL read from fd should be valid")
110 def testFromEmpty(self):
111 """Test creating an empty ACL"""
113 self.failIf(acl1.valid(), "Empty ACL should not be valid")
115 def testFromText(self):
116 """Test creating an ACL from text"""
117 acl1 = posix1e.ACL(text=BASIC_ACL_TEXT)
118 self.failUnless(acl1.valid(),
119 "ACL based on standard description should be valid")
121 class AclExtensions(aclTest, unittest.TestCase):
122 """ACL extensions checks"""
124 @has_ext(HAS_ACL_FROM_MODE)
125 def testFromMode(self):
126 """Test loading ACLs from an octal mode"""
127 acl1 = posix1e.ACL(mode=0644)
128 self.failUnless(acl1.valid(),
129 "ACL created via octal mode shoule be valid")
131 @has_ext(HAS_ACL_CHECK)
132 def testAclCheck(self):
133 """Test the acl_check method"""
134 acl1 = posix1e.ACL(text=BASIC_ACL_TEXT)
135 self.failIf(acl1.check(), "ACL is not valid")
137 self.failUnless(acl2.check(), "Empty ACL should not be valid")
139 @has_ext(HAS_EXTENDED_CHECK)
140 def testExtended(self):
141 """Test the acl_extended function"""
142 fd, fname = self._getfile()
143 basic_acl = posix1e.ACL(text=BASIC_ACL_TEXT)
144 basic_acl.applyto(fd)
145 for item in fd, fname:
146 self.failIf(has_extended(item),
147 "A simple ACL should not be reported as extended")
148 enhanced_acl = posix1e.ACL(text="u::rw,g::-,o::-,u:root:rw,mask::r")
149 self.failUnless(enhanced_acl.valid(),
150 "Failure to build an extended ACL")
151 enhanced_acl.applyto(fd)
152 for item in fd, fname:
153 self.failUnless(has_extended(item),
154 "An extended ACL should be reported as such")
156 @has_ext(HAS_EQUIV_MODE)
157 def testEquivMode(self):
158 """Test the equiv_mode function"""
159 if HAS_ACL_FROM_MODE:
160 for mode in 0644, 0755:
161 acl = posix1e.ACL(mode=mode)
162 self.failUnlessEqual(acl.equiv_mode(), mode)
163 acl = posix1e.ACL(text="u::rw,g::r,o::r")
164 self.failUnlessEqual(acl.equiv_mode(), 0644)
165 acl = posix1e.ACL(text="u::rx,g::-,o::-")
166 self.failUnlessEqual(acl.equiv_mode(), 0500)
169 class WriteTests(aclTest, unittest.TestCase):
172 def testDeleteDefault(self):
173 """Test removing the default ACL"""
174 dname = self._getdir()
175 posix1e.delete_default(dname)
177 def testReapply(self):
178 """Test re-applying an ACL"""
179 fd, fname = self._getfile()
180 acl1 = posix1e.ACL(fd=fd)
183 dname = self._getdir()
184 acl2 = posix1e.ACL(file=fname)
188 class ModificationTests(aclTest, unittest.TestCase):
189 """ACL modification tests"""
191 @has_ext(HAS_ACL_ENTRY)
192 def testAppend(self):
193 """Test append a new Entry to the ACL"""
196 e.tag_type = posix1e.ACL_OTHER
199 @has_ext(HAS_ACL_ENTRY)
200 def testDelete(self):
201 """Test delete Entry from the ACL"""
204 e.tag_type = posix1e.ACL_OTHER
209 @has_ext(HAS_ACL_ENTRY)
210 def testDoubleEntries(self):
211 """Test double entries"""
212 acl = posix1e.ACL(text=BASIC_ACL_TEXT)
213 self.failUnless(acl.valid(), "ACL is not valid")
214 for tag_type in (posix1e.ACL_USER_OBJ, posix1e.ACL_GROUP_OBJ,
217 e.tag_type = tag_type
219 self.failIf(acl.valid(),
220 "ACL containing duplicate entries should not be valid")
223 @has_ext(HAS_ACL_ENTRY)
224 def testMultipleGoodEntries(self):
225 """Test multiple valid entries"""
226 acl = posix1e.ACL(text=BASIC_ACL_TEXT)
227 self.failUnless(acl.valid(), "ACL is not valid")
228 for tag_type in (posix1e.ACL_USER,
230 for obj_id in range(5):
232 e.tag_type = tag_type
236 self.failUnless(acl.valid(),
237 "ACL should be able to hold multiple"
238 " user/group entries")
240 @has_ext(HAS_ACL_ENTRY)
241 def testMultipleBadEntries(self):
242 """Test multiple invalid entries"""
243 acl = posix1e.ACL(text=BASIC_ACL_TEXT)
244 self.failUnless(acl.valid(), "ACL built from standard description"
246 for tag_type in (posix1e.ACL_USER,
249 e1.tag_type = tag_type
253 self.failUnless(acl.valid(), "ACL should be able to add a"
256 e2.tag_type = tag_type
260 self.failIf(acl.valid(), "ACL should not validate when"
261 " containing two duplicate entries")
265 @has_ext(HAS_ACL_ENTRY)
266 def testPermset(self):
267 """Test permissions"""
273 posix1e.ACL_READ: "read",
274 posix1e.ACL_WRITE: "write",
275 posix1e.ACL_EXECUTE: "execute",
278 self.failIf(ps.test(perm), "Empty permission set should not"
279 " have permission '%s'" % pmap[perm])
281 self.failUnless(ps.test(perm), "Permission '%s' should exist"
282 " after addition" % pmap[perm])
284 self.failIf(ps.test(perm), "Permission '%s' should not exist"
285 " after deletion" % pmap[perm])
288 if __name__ == "__main__":