4 """Unittests for the posix1e module"""
6 # Copyright (C) 2002-2009 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::-"
35 # This is to workaround python 2/3 differences at syntactic level
36 # (which can't be worked around via if's)
37 M0500 = 320 # octal 0500
38 M0644 = 420 # octal 0644
39 M0755 = 493 # octal 755
42 """Wrapper to skip a test"""
43 new_fn = lambda x: None
44 new_fn.__doc__ = "SKIPPED %s" % fn.__doc__
48 def has_ext(extension):
49 """Decorator to skip tests based on platform support"""
57 """Support functions ACLs"""
65 """tear down function"""
66 for fname in self.rmfiles:
68 for dname in self.rmdirs:
72 """create a temp file"""
73 fh, fname = tempfile.mkstemp(".test", "xattr-", TEST_DIR)
74 self.rmfiles.append(fname)
78 """create a temp dir"""
79 dname = tempfile.mkdtemp(".test", "xattr-", TEST_DIR)
80 self.rmdirs.append(dname)
83 def _getsymlink(self):
84 """create a symlink"""
85 fh, fname = self._getfile()
88 os.symlink(fname + ".non-existent", fname)
92 class LoadTests(aclTest, unittest.TestCase):
93 """Load/create tests"""
94 def testFromFile(self):
95 """Test loading ACLs from a file"""
96 _, fname = self._getfile()
97 acl1 = posix1e.ACL(file=fname)
98 self.failUnless(acl1.valid(), "ACL read from file should be valid")
100 def testFromDir(self):
101 """Test loading ACLs from a directory"""
102 dname = self._getdir()
103 acl1 = posix1e.ACL(file=dname)
104 acl2 = posix1e.ACL(filedef=dname)
105 self.failUnless(acl1.valid(),
106 "ACL read from directory should be valid")
107 # default ACLs might or might not be valid; missing ones are
108 # not valid, so we don't test acl2 for validity
110 def testFromFd(self):
111 """Test loading ACLs from a file descriptor"""
112 fd, _ = self._getfile()
113 acl1 = posix1e.ACL(fd=fd)
114 self.failUnless(acl1.valid(), "ACL read from fd should be valid")
116 def testFromEmpty(self):
117 """Test creating an empty ACL"""
119 self.failIf(acl1.valid(), "Empty ACL should not be valid")
121 def testFromText(self):
122 """Test creating an ACL from text"""
123 acl1 = posix1e.ACL(text=BASIC_ACL_TEXT)
124 self.failUnless(acl1.valid(),
125 "ACL based on standard description should be valid")
127 class AclExtensions(aclTest, unittest.TestCase):
128 """ACL extensions checks"""
130 @has_ext(HAS_ACL_FROM_MODE)
131 def testFromMode(self):
132 """Test loading ACLs from an octal mode"""
133 acl1 = posix1e.ACL(mode=M0644)
134 self.failUnless(acl1.valid(),
135 "ACL created via octal mode shoule be valid")
137 @has_ext(HAS_ACL_CHECK)
138 def testAclCheck(self):
139 """Test the acl_check method"""
140 acl1 = posix1e.ACL(text=BASIC_ACL_TEXT)
141 self.failIf(acl1.check(), "ACL is not valid")
143 self.failUnless(acl2.check(), "Empty ACL should not be valid")
145 @has_ext(HAS_EXTENDED_CHECK)
146 def testExtended(self):
147 """Test the acl_extended function"""
148 fd, fname = self._getfile()
149 basic_acl = posix1e.ACL(text=BASIC_ACL_TEXT)
150 basic_acl.applyto(fd)
151 for item in fd, fname:
152 self.failIf(has_extended(item),
153 "A simple ACL should not be reported as extended")
154 enhanced_acl = posix1e.ACL(text="u::rw,g::-,o::-,u:root:rw,mask::r")
155 self.failUnless(enhanced_acl.valid(),
156 "Failure to build an extended ACL")
157 enhanced_acl.applyto(fd)
158 for item in fd, fname:
159 self.failUnless(has_extended(item),
160 "An extended ACL should be reported as such")
162 @has_ext(HAS_EQUIV_MODE)
163 def testEquivMode(self):
164 """Test the equiv_mode function"""
165 if HAS_ACL_FROM_MODE:
166 for mode in M0644, M0755:
167 acl = posix1e.ACL(mode=mode)
168 self.failUnlessEqual(acl.equiv_mode(), mode)
169 acl = posix1e.ACL(text="u::rw,g::r,o::r")
170 self.failUnlessEqual(acl.equiv_mode(), M0644)
171 acl = posix1e.ACL(text="u::rx,g::-,o::-")
172 self.failUnlessEqual(acl.equiv_mode(), M0500)
175 class WriteTests(aclTest, unittest.TestCase):
178 def testDeleteDefault(self):
179 """Test removing the default ACL"""
180 dname = self._getdir()
181 posix1e.delete_default(dname)
183 def testReapply(self):
184 """Test re-applying an ACL"""
185 fd, fname = self._getfile()
186 acl1 = posix1e.ACL(fd=fd)
189 dname = self._getdir()
190 acl2 = posix1e.ACL(file=fname)
194 class ModificationTests(aclTest, unittest.TestCase):
195 """ACL modification tests"""
197 @has_ext(HAS_ACL_ENTRY)
198 def testAppend(self):
199 """Test append a new Entry to the ACL"""
202 e.tag_type = posix1e.ACL_OTHER
205 @has_ext(HAS_ACL_ENTRY)
206 def testDelete(self):
207 """Test delete Entry from the ACL"""
210 e.tag_type = posix1e.ACL_OTHER
215 @has_ext(HAS_ACL_ENTRY)
216 def testDoubleEntries(self):
217 """Test double entries"""
218 acl = posix1e.ACL(text=BASIC_ACL_TEXT)
219 self.failUnless(acl.valid(), "ACL is not valid")
220 for tag_type in (posix1e.ACL_USER_OBJ, posix1e.ACL_GROUP_OBJ,
223 e.tag_type = tag_type
225 self.failIf(acl.valid(),
226 "ACL containing duplicate entries should not be valid")
229 @has_ext(HAS_ACL_ENTRY)
230 def testMultipleGoodEntries(self):
231 """Test multiple valid entries"""
232 acl = posix1e.ACL(text=BASIC_ACL_TEXT)
233 self.failUnless(acl.valid(), "ACL is not valid")
234 for tag_type in (posix1e.ACL_USER,
236 for obj_id in range(5):
238 e.tag_type = tag_type
242 self.failUnless(acl.valid(),
243 "ACL should be able to hold multiple"
244 " user/group entries")
246 @has_ext(HAS_ACL_ENTRY)
247 def testMultipleBadEntries(self):
248 """Test multiple invalid entries"""
249 acl = posix1e.ACL(text=BASIC_ACL_TEXT)
250 self.failUnless(acl.valid(), "ACL built from standard description"
252 for tag_type in (posix1e.ACL_USER,
255 e1.tag_type = tag_type
259 self.failUnless(acl.valid(), "ACL should be able to add a"
262 e2.tag_type = tag_type
266 self.failIf(acl.valid(), "ACL should not validate when"
267 " containing two duplicate entries")
271 @has_ext(HAS_ACL_ENTRY)
272 def testPermset(self):
273 """Test permissions"""
279 posix1e.ACL_READ: "read",
280 posix1e.ACL_WRITE: "write",
281 posix1e.ACL_EXECUTE: "execute",
284 self.failIf(ps.test(perm), "Empty permission set should not"
285 " have permission '%s'" % pmap[perm])
287 self.failUnless(ps.test(perm), "Permission '%s' should exist"
288 " after addition" % pmap[perm])
290 self.failIf(ps.test(perm), "Permission '%s' should not exist"
291 " after deletion" % pmap[perm])
294 if __name__ == "__main__":