]> git.k1024.org Git - pylibacl.git/blob - test/test_acls.py
Fix MANIFEST.in after os_linux.c removal
[pylibacl.git] / test / test_acls.py
1 #
2 #
3
4 import unittest
5 import os
6 import tempfile
7
8 import posix1e
9 from posix1e import *
10
11 TEST_DIR=os.environ.get("TESTDIR", ".")
12
13 BASIC_ACL_TEXT="u::rw,g::r,o::-"
14
15 def _skip_test(fn):
16     """Wrapper to skip a test"""
17     new_fn = lambda x: None
18     new_fn.__doc__ = "SKIPPED %s" % fn.__doc__
19     return new_fn
20
21
22 def has_ext(extension):
23     """Decorator to skip tests based on platform support"""
24     if not extension:
25         return _skip_test
26     else:
27         return lambda x: x
28
29
30 class aclTest:
31     """Support functions ACLs"""
32
33     def setUp(self):
34         """set up function"""
35         self.rmfiles = []
36         self.rmdirs = []
37
38     def tearDown(self):
39         """tear down function"""
40         for fname in self.rmfiles:
41             os.unlink(fname)
42         for dname in self.rmdirs:
43             os.rmdir(dname)
44
45     def _getfile(self):
46         """create a temp file"""
47         fh, fname = tempfile.mkstemp(".test", "xattr-", TEST_DIR)
48         self.rmfiles.append(fname)
49         return fh, fname
50
51     def _getdir(self):
52         """create a temp dir"""
53         dname = tempfile.mkdtemp(".test", "xattr-", TEST_DIR)
54         self.rmdirs.append(dname)
55         return dname
56
57     def _getsymlink(self):
58         """create a symlink"""
59         fh, fname = self._getfile()
60         os.close(fh)
61         os.unlink(fname)
62         os.symlink(fname + ".non-existent", fname)
63         return fname
64
65
66 class LoadTests(aclTest, unittest.TestCase):
67     """Load/create tests"""
68     def testFromFile(self):
69         """Test loading ACLs from a file"""
70         _, fname = self._getfile()
71         acl1 = posix1e.ACL(file=fname)
72         self.failUnless(acl1.valid(), "ACL read from file should be valid")
73
74     def testFromDir(self):
75         """Test loading ACLs from a directory"""
76         dname = self._getdir()
77         acl1 = posix1e.ACL(file=dname)
78         acl2 = posix1e.ACL(filedef=dname)
79         self.failUnless(acl1.valid(),
80                         "ACL read from directory should be valid")
81         # default ACLs might or might not be valid; missing ones are
82         # not valid, so we don't test acl2 for validity
83
84     def testFromFd(self):
85         """Test loading ACLs from a file descriptor"""
86         fd, _ = self._getfile()
87         acl1 = posix1e.ACL(fd=fd)
88         self.failUnless(acl1.valid(), "ACL read from fd should be valid")
89
90     def testFromEmpty(self):
91         """Test creating an empty ACL"""
92         acl1 = posix1e.ACL()
93         self.failIf(acl1.valid(), "Empty ACL should not be valid")
94
95     def testFromText(self):
96         """Test creating an ACL from text"""
97         acl1 = posix1e.ACL(text=BASIC_ACL_TEXT)
98         self.failUnless(acl1.valid(),
99                         "ACL based on standard description should be valid")
100
101 class AclExtensions(aclTest, unittest.TestCase):
102     """ACL extensions checks"""
103
104     @has_ext(HAS_ACL_FROM_MODE)
105     def testFromMode(self):
106         """Test loading ACLs from an octal mode"""
107         acl1 = posix1e.ACL(mode=0644)
108         self.failUnless(acl1.valid(),
109                         "ACL created via octal mode shoule be valid")
110
111     @has_ext(HAS_ACL_CHECK)
112     def testAclCheck(self):
113         """Test the acl_check method"""
114         acl1 = posix1e.ACL(text=BASIC_ACL_TEXT)
115         self.failIf(acl1.check(), "ACL is not valid")
116         acl2 = posix1e.ACL()
117         self.failUnless(acl2.check(), "Empty ACL should not be valid")
118
119     @has_ext(HAS_EXTENDED_CHECK)
120     def testExtended(self):
121         """Test the acl_extended function"""
122         fd, fname = self._getfile()
123         basic_acl = posix1e.ACL(text=BASIC_ACL_TEXT)
124         basic_acl.applyto(fd)
125         for item in fd, fname:
126             self.failIf(has_extended(item),
127                         "A simple ACL should not be reported as extended")
128         enhanced_acl = posix1e.ACL(text="u::rw,g::-,o::-,u:root:rw,mask::r")
129         self.failUnless(enhanced_acl.valid(),
130                         "Failure to build an extended ACL")
131         enhanced_acl.applyto(fd)
132         for item in fd, fname:
133             self.failUnless(has_extended(item),
134                         "An extended ACL should be reported as such")
135
136     @has_ext(HAS_EQUIV_MODE)
137     def testEquivMode(self):
138         """Test the equiv_mode function"""
139         if HAS_ACL_FROM_MODE:
140             for mode in 0644, 0755:
141                 acl = posix1e.ACL(mode=mode)
142                 self.failUnlessEqual(acl.equiv_mode(), mode)
143         acl = posix1e.ACL(text="u::rw,g::r,o::r")
144         self.failUnlessEqual(acl.equiv_mode(), 0644)
145         acl = posix1e.ACL(text="u::rx,g::-,o::-")
146         self.failUnlessEqual(acl.equiv_mode(), 0500)
147
148
149 class WriteTests(aclTest, unittest.TestCase):
150     """Write tests"""
151
152     def testDeleteDefault(self):
153         """Test removing the default ACL"""
154         dname = self._getdir()
155         posix1e.delete_default(dname)
156
157     def testReapply(self):
158         """Test re-applying an ACL"""
159         fd, fname = self._getfile()
160         acl1 = posix1e.ACL(fd=fd)
161         acl1.applyto(fd)
162         acl1.applyto(fname)
163         dname = self._getdir()
164         acl2 = posix1e.ACL(file=fname)
165         acl2.applyto(dname)
166
167
168 class ModificationTests(aclTest, unittest.TestCase):
169     """ACL modification tests"""
170
171     @has_ext(HAS_ACL_ENTRY)
172     def testAppend(self):
173         """Test append a new Entry to the ACL"""
174         acl = posix1e.ACL()
175         e = acl.append()
176         e.tag_type = posix1e.ACL_OTHER
177         acl.calc_mask()
178
179     @has_ext(HAS_ACL_ENTRY)
180     def testDelete(self):
181         """Test delete Entry from the ACL"""
182         acl = posix1e.ACL()
183         e = acl.append()
184         e.tag_type = posix1e.ACL_OTHER
185         acl.calc_mask()
186         acl.delete_entry(e)
187         acl.calc_mask()
188
189     @has_ext(HAS_ACL_ENTRY)
190     def testDoubleEntries(self):
191         """Test double entries"""
192         acl = posix1e.ACL(text=BASIC_ACL_TEXT)
193         self.failUnless(acl.valid(), "ACL is not valid")
194         for tag_type in (posix1e.ACL_USER_OBJ, posix1e.ACL_GROUP_OBJ,
195                          posix1e.ACL_OTHER):
196             e = acl.append()
197             e.tag_type = tag_type
198             e.permset.clear()
199             self.failIf(acl.valid(),
200                         "ACL containing duplicate entries should not be valid")
201             acl.delete_entry(e)
202
203     @has_ext(HAS_ACL_ENTRY)
204     def testMultipleGoodEntries(self):
205         """Test multiple valid entries"""
206         acl = posix1e.ACL(text=BASIC_ACL_TEXT)
207         self.failUnless(acl.valid(), "ACL is not valid")
208         for tag_type in (posix1e.ACL_USER,
209                          posix1e.ACL_GROUP):
210             for obj_id in range(5):
211                 e = acl.append()
212                 e.tag_type = tag_type
213                 e.qualifier = obj_id
214                 e.permset.clear()
215                 acl.calc_mask()
216                 self.failUnless(acl.valid(),
217                                "ACL should be able to hold multiple"
218                                 " user/group entries")
219
220     @has_ext(HAS_ACL_ENTRY)
221     def testMultipleBadEntries(self):
222         """Test multiple invalid entries"""
223         acl = posix1e.ACL(text=BASIC_ACL_TEXT)
224         self.failUnless(acl.valid(), "ACL built from standard description"
225                         " should be valid")
226         for tag_type in (posix1e.ACL_USER,
227                          posix1e.ACL_GROUP):
228             e1 = acl.append()
229             e1.tag_type = tag_type
230             e1.qualifier = 0
231             e1.permset.clear()
232             acl.calc_mask()
233             self.failUnless(acl.valid(), "ACL should be able to add a"
234                             " user/group entry")
235             e2 = acl.append()
236             e2.tag_type = tag_type
237             e2.qualifier = 0
238             e2.permset.clear()
239             acl.calc_mask()
240             self.failIf(acl.valid(), "ACL should not validate when"
241                         " containing two duplicate entries")
242             acl.delete_entry(e1)
243             acl.delete_entry(e2)
244
245     @has_ext(HAS_ACL_ENTRY)
246     def testPermset(self):
247         """Test permissions"""
248         acl = posix1e.ACL()
249         e = acl.append()
250         ps = e.permset
251         ps.clear()
252         pmap = {
253             posix1e.ACL_READ: "read",
254             posix1e.ACL_WRITE: "write",
255             posix1e.ACL_EXECUTE: "execute",
256             }
257         for perm in pmap:
258             self.failIf(ps.test(perm), "Empty permission set should not"
259                         " have permission '%s'" % pmap[perm])
260             ps.add(perm)
261             self.failUnless(ps.test(perm), "Permission '%s' should exist"
262                         " after addition" % pmap[perm])
263             ps.delete(perm)
264             self.failIf(ps.test(perm), "Permission '%s' should not exist"
265                         " after deletion" % pmap[perm])
266
267
268 if __name__ == "__main__":
269     unittest.main()