]> git.k1024.org Git - pyxattr.git/blob - test/test_xattr.py
unittests: enhance symlink tests
[pyxattr.git] / test / test_xattr.py
1 #
2 #
3
4 import unittest
5 import tempfile
6 import os
7 import errno
8
9 import xattr
10 from xattr import NS_USER, XATTR_CREATE, XATTR_REPLACE
11
12 TEST_DIR = os.environ.get("TESTDIR", ".")
13
14
15 class xattrTest(unittest.TestCase):
16     USER_NN = "test"
17     USER_ATTR = "%s.%s" % (NS_USER, USER_NN)
18     USER_VAL = "abc"
19     MANYOPS_COUNT = 131072
20
21     def setUp(self):
22         """set up function"""
23         self.rmfiles = []
24         self.rmdirs = []
25
26     def tearDown(self):
27         """tear down function"""
28         for fname in self.rmfiles:
29             try:
30                 os.unlink(fname)
31             except EnvironmentError:
32                 continue
33         for dname in self.rmdirs:
34             try:
35                 os.rmdir(dname)
36             except EnvironmentError:
37                 continue
38
39     def _getfile(self):
40         """create a temp file"""
41         fh, fname = tempfile.mkstemp(".test", "xattr-", TEST_DIR)
42         self.rmfiles.append(fname)
43         return fh, fname
44
45     def _getdir(self):
46         """create a temp dir"""
47         dname = tempfile.mkdtemp(".test", "xattr-", TEST_DIR)
48         self.rmdirs.append(dname)
49         return dname
50
51     def _getsymlink(self, dangling=True):
52         """create a symlink"""
53         fh, fname = self._getfile()
54         os.close(fh)
55         if dangling:
56             os.unlink(fname)
57         sname = fname + ".symlink"
58         os.symlink(fname, sname)
59         self.rmfiles.append(sname)
60         return fname, sname
61
62     def _checkDeprecated(self, item, symlink=False):
63         """check deprecated list, set, get operations against an item"""
64         self.failUnlessEqual(xattr.listxattr(item, symlink), [])
65         self.failUnlessRaises(EnvironmentError, xattr.setxattr, item,
66                               self.USER_ATTR, self.USER_VAL,
67                               XATTR_REPLACE)
68         try:
69             xattr.setxattr(item, self.USER_ATTR, self.USER_VAL, 0, symlink)
70         except IOError, err:
71             if err.errno == errno.EPERM and symlink:
72                 # symlinks may fail, in which case we abort the rest
73                 # of the test for this case
74                 return
75             raise
76         self.failUnlessRaises(EnvironmentError, xattr.setxattr, item,
77                               self.USER_ATTR, self.USER_VAL,
78                               XATTR_CREATE)
79         self.failUnlessEqual(xattr.listxattr(item, symlink), [self.USER_ATTR])
80         self.failUnlessEqual(xattr.getxattr(item, self.USER_ATTR, symlink),
81                              self.USER_VAL)
82         self.failUnlessEqual(xattr.get_all(item, nofollow=symlink),
83                              [(self.USER_ATTR, self.USER_VAL)])
84         xattr.removexattr(item, self.USER_ATTR)
85         self.failUnlessEqual(xattr.listxattr(item, symlink), [])
86         self.failUnlessEqual(xattr.get_all(item, nofollow=symlink), [])
87         self.failUnlessRaises(EnvironmentError, xattr.removexattr,
88                               item, self.USER_ATTR)
89
90     def _checkListSetGet(self, item, symlink=False, use_ns=False):
91         """check list, set, get operations against an item"""
92         self.failUnlessEqual(xattr.list(item, symlink), [])
93         self.failUnlessRaises(EnvironmentError, xattr.set, item,
94                               self.USER_ATTR, self.USER_VAL,
95                               flags=XATTR_REPLACE)
96         self.failUnlessRaises(EnvironmentError, xattr.set, item,
97                               self.USER_NN, self.USER_VAL,
98                               flags=XATTR_REPLACE,
99                               namespace=NS_USER)
100         try:
101             if use_ns:
102                 xattr.set(item, self.USER_NN, self.USER_VAL,
103                           namespace=NS_USER,
104                           nofollow=symlink)
105             else:
106                 xattr.set(item, self.USER_ATTR, self.USER_VAL,
107                           nofollow=symlink)
108         except IOError, err:
109             if err.errno == errno.EPERM and symlink:
110                 # symlinks may fail, in which case we abort the rest
111                 # of the test for this case
112                 return
113             raise
114         self.failUnlessRaises(EnvironmentError, xattr.set, item,
115                               self.USER_ATTR, self.USER_VAL,
116                               flags=XATTR_CREATE)
117         self.failUnlessRaises(EnvironmentError, xattr.set, item,
118                               self.USER_NN, self.USER_VAL,
119                               flags=XATTR_CREATE,
120                               namespace=NS_USER)
121         self.failUnlessEqual(xattr.list(item, nofollow=symlink),
122                              [self.USER_ATTR])
123         self.failUnlessEqual(xattr.list(item, namespace=NS_USER,
124                                         nofollow=symlink),
125                              [self.USER_NN])
126         self.failUnlessEqual(xattr.get(item, self.USER_ATTR, nofollow=symlink),
127                              self.USER_VAL)
128         self.failUnlessEqual(xattr.get(item, self.USER_NN, nofollow=symlink,
129                                        namespace=NS_USER),
130                              self.USER_VAL)
131         self.failUnlessEqual(xattr.get_all(item, nofollow=symlink),
132                              [(self.USER_ATTR, self.USER_VAL)])
133         self.failUnlessEqual(xattr.get_all(item, nofollow=symlink,
134                                            namespace=NS_USER),
135                              [(self.USER_NN, self.USER_VAL)])
136         if use_ns:
137             xattr.remove(item, self.USER_NN, namespace=NS_USER)
138         else:
139             xattr.remove(item, self.USER_ATTR)
140         self.failUnlessEqual(xattr.list(item, symlink), [])
141         self.failUnlessEqual(xattr.get_all(item, nofollow=symlink), [])
142         self.failUnlessRaises(EnvironmentError, xattr.remove,
143                               item, self.USER_ATTR, nofollow=symlink)
144         self.failUnlessRaises(EnvironmentError, xattr.remove,
145                               item, self.USER_NN, namespace=NS_USER,
146                               nofollow=symlink)
147
148     def testNoXattrDeprecated(self):
149         """test no attributes (deprecated functions)"""
150         fh, fname = self._getfile()
151         self.failUnlessEqual(xattr.listxattr(fname), [])
152         self.failUnlessEqual(xattr.get_all(fname), [])
153         dname = self._getdir()
154         self.failUnlessEqual(xattr.listxattr(dname), [])
155         self.failUnlessEqual(xattr.get_all(dname), [])
156         _, sname = self._getsymlink()
157         self.failUnlessEqual(xattr.listxattr(sname, True), [])
158         self.failUnlessEqual(xattr.get_all(sname, nofollow=True), [])
159
160     def testNoXattr(self):
161         """test no attributes"""
162         fh, fname = self._getfile()
163         self.failUnlessEqual(xattr.list(fname), [])
164         self.failUnlessEqual(xattr.list(fname, namespace=NS_USER), [])
165         self.failUnlessEqual(xattr.get_all(fname), [])
166         self.failUnlessEqual(xattr.get_all(fname, namespace=NS_USER), [])
167         dname = self._getdir()
168         self.failUnlessEqual(xattr.list(dname), [])
169         self.failUnlessEqual(xattr.list(dname, namespace=NS_USER), [])
170         self.failUnlessEqual(xattr.get_all(dname), [])
171         self.failUnlessEqual(xattr.get_all(dname, namespace=NS_USER), [])
172         _, sname = self._getsymlink()
173         self.failUnlessEqual(xattr.list(sname, nofollow=True), [])
174         self.failUnlessEqual(xattr.list(sname, nofollow=True,
175                                         namespace=NS_USER), [])
176         self.failUnlessEqual(xattr.get_all(sname, nofollow=True), [])
177         self.failUnlessEqual(xattr.get_all(sname, nofollow=True,
178                                            namespace=NS_USER), [])
179
180     def testFileByNameDeprecated(self):
181         """test set and retrieve one attribute by file name (deprecated)"""
182         fh, fname = self._getfile()
183         self._checkDeprecated(fname)
184         os.close(fh)
185
186     def testFileByName(self):
187         """test set and retrieve one attribute by file name"""
188         fh, fname = self._getfile()
189         self._checkListSetGet(fname)
190         self._checkListSetGet(fname, use_ns=True)
191         os.close(fh)
192
193     def testFileByDescriptorDeprecated(self):
194         """test file descriptor operations (deprecated functions)"""
195         fh, fname = self._getfile()
196         self._checkDeprecated(fh)
197         os.close(fh)
198
199     def testFileByDescriptor(self):
200         """test file descriptor operations"""
201         fh, fname = self._getfile()
202         self._checkListSetGet(fh)
203         self._checkListSetGet(fh, use_ns=True)
204         os.close(fh)
205
206     def testFileByObjectDeprecated(self):
207         """test file descriptor operations (deprecated functions)"""
208         fh, fname = self._getfile()
209         fo = os.fdopen(fh)
210         self._checkDeprecated(fo)
211         fo.close()
212
213     def testFileByObject(self):
214         """test file descriptor operations"""
215         fh, fname = self._getfile()
216         fo = os.fdopen(fh)
217         self._checkListSetGet(fo)
218         self._checkListSetGet(fo, use_ns=True)
219         fo.close()
220
221     def testMixedAccessDeprecated(self):
222         """test mixed access to file (deprecated functions)"""
223         fh, fname = self._getfile()
224         fo = os.fdopen(fh)
225         self.failUnlessEqual(xattr.listxattr(fname), [])
226         xattr.setxattr(fname, self.USER_ATTR, self.USER_VAL)
227         self.failUnlessEqual(xattr.listxattr(fh), [self.USER_ATTR])
228         self.failUnlessEqual(xattr.getxattr(fo, self.USER_ATTR),
229                              self.USER_VAL)
230         self.failUnlessEqual(xattr.get_all(fo),
231                              [(self.USER_ATTR, self.USER_VAL)])
232         self.failUnlessEqual(xattr.get_all(fname),
233                              [(self.USER_ATTR, self.USER_VAL)])
234
235     def testMixedAccess(self):
236         """test mixed access to file"""
237         fh, fname = self._getfile()
238         fo = os.fdopen(fh)
239         self.failUnlessEqual(xattr.list(fname), [])
240         xattr.set(fname, self.USER_ATTR, self.USER_VAL)
241         self.failUnlessEqual(xattr.list(fh), [self.USER_ATTR])
242         self.failUnlessEqual(xattr.list(fh, namespace=NS_USER),
243                              [self.USER_NN])
244         self.failUnlessEqual(xattr.get(fo, self.USER_ATTR),
245                              self.USER_VAL)
246         self.failUnlessEqual(xattr.get(fo, self.USER_NN, namespace=NS_USER),
247                              self.USER_VAL)
248         self.failUnlessEqual(xattr.get_all(fo),
249                              [(self.USER_ATTR, self.USER_VAL)])
250         self.failUnlessEqual(xattr.get_all(fo, namespace=NS_USER),
251                              [(self.USER_NN, self.USER_VAL)])
252         self.failUnlessEqual(xattr.get_all(fname),
253                              [(self.USER_ATTR, self.USER_VAL)])
254         self.failUnlessEqual(xattr.get_all(fname, namespace=NS_USER),
255                              [(self.USER_NN, self.USER_VAL)])
256
257     def testDirOpsDeprecated(self):
258         """test attribute setting on directories (deprecated functions)"""
259         dname = self._getdir()
260         self._checkDeprecated(dname)
261
262     def testDirOps(self):
263         """test attribute setting on directories"""
264         dname = self._getdir()
265         self._checkListSetGet(dname)
266         self._checkListSetGet(dname, use_ns=True)
267
268     def testSymlinkOpsDeprecated(self):
269         """test symlink operations (deprecated functions)"""
270         _, sname = self._getsymlink()
271         self.failUnlessRaises(EnvironmentError, xattr.listxattr, sname)
272         self._checkDeprecated(sname, symlink=True)
273         target, sname = self._getsymlink(dangling=False)
274         xattr.setxattr(target, self.USER_ATTR, self.USER_VAL)
275         self.failUnlessEqual(xattr.listxattr(target), [self.USER_ATTR])
276         self.failUnlessEqual(xattr.listxattr(sname, True), [])
277         self.failUnlessRaises(EnvironmentError, xattr.removexattr, sname,
278                               self.USER_ATTR, True)
279         xattr.removexattr(sname, self.USER_ATTR, False)
280
281     def testSymlinkOps(self):
282         """test symlink operations"""
283         _, sname = self._getsymlink()
284         self.failUnlessRaises(EnvironmentError, xattr.list, sname)
285         self._checkListSetGet(sname, symlink=True)
286         self._checkListSetGet(sname, symlink=True, use_ns=True)
287         target, sname = self._getsymlink(dangling=False)
288         xattr.set(target, self.USER_ATTR, self.USER_VAL)
289         self.failUnlessEqual(xattr.list(target), [self.USER_ATTR])
290         self.failUnlessEqual(xattr.list(sname, nofollow=True), [])
291         self.failUnlessRaises(EnvironmentError, xattr.remove, sname,
292                               self.USER_ATTR, nofollow=True)
293         xattr.remove(sname, self.USER_ATTR, nofollow=False)
294
295     def testBinaryPayloadDeprecated(self):
296         """test binary values (deprecated functions)"""
297         fh, fname = self._getfile()
298         os.close(fh)
299         BINVAL = "abc" + '\0' + "def"
300         xattr.setxattr(fname, self.USER_ATTR, BINVAL)
301         self.failUnlessEqual(xattr.listxattr(fname), [self.USER_ATTR])
302         self.failUnlessEqual(xattr.getxattr(fname, self.USER_ATTR), BINVAL)
303         self.failUnlessEqual(xattr.get_all(fname), [(self.USER_ATTR, BINVAL)])
304         xattr.removexattr(fname, self.USER_ATTR)
305
306     def testBinaryPayload(self):
307         """test binary values"""
308         fh, fname = self._getfile()
309         os.close(fh)
310         BINVAL = "abc" + '\0' + "def"
311         xattr.set(fname, self.USER_ATTR, BINVAL)
312         self.failUnlessEqual(xattr.list(fname), [self.USER_ATTR])
313         self.failUnlessEqual(xattr.list(fname, namespace=NS_USER),
314                              [self.USER_NN])
315         self.failUnlessEqual(xattr.get(fname, self.USER_ATTR), BINVAL)
316         self.failUnlessEqual(xattr.get(fname, self.USER_NN,
317                                        namespace=NS_USER), BINVAL)
318         self.failUnlessEqual(xattr.get_all(fname), [(self.USER_ATTR, BINVAL)])
319         self.failUnlessEqual(xattr.get_all(fname, namespace=NS_USER),
320                              [(self.USER_NN, BINVAL)])
321         xattr.remove(fname, self.USER_ATTR)
322
323     def testManyOpsDeprecated(self):
324         """test many ops (deprecated functions)"""
325         fh, fname = self._getfile()
326         xattr.setxattr(fh, self.USER_ATTR, self.USER_VAL)
327         VL = [self.USER_ATTR]
328         for i in range(self.MANYOPS_COUNT):
329             self.failUnlessEqual(xattr.listxattr(fh), VL)
330         for i in range(self.MANYOPS_COUNT):
331             self.failUnlessEqual(xattr.getxattr(fh, self.USER_ATTR),
332                                  self.USER_VAL)
333         for i in range(self.MANYOPS_COUNT):
334             self.failUnlessEqual(xattr.get_all(fh),
335                                  [(self.USER_ATTR, self.USER_VAL)])
336
337     def testManyOps(self):
338         """test many ops"""
339         fh, fname = self._getfile()
340         xattr.set(fh, self.USER_ATTR, self.USER_VAL)
341         VL = [self.USER_ATTR]
342         VN = [self.USER_NN]
343         for i in range(self.MANYOPS_COUNT):
344             self.failUnlessEqual(xattr.list(fh), VL)
345             self.failUnlessEqual(xattr.list(fh, namespace=NS_USER), VN)
346         for i in range(self.MANYOPS_COUNT):
347             self.failUnlessEqual(xattr.get(fh, self.USER_ATTR),
348                                  self.USER_VAL)
349             self.failUnlessEqual(xattr.get(fh, self.USER_NN,
350                                            namespace=NS_USER),
351                                  self.USER_VAL)
352         for i in range(self.MANYOPS_COUNT):
353             self.failUnlessEqual(xattr.get_all(fh),
354                                  [(self.USER_ATTR, self.USER_VAL)])
355             self.failUnlessEqual(xattr.get_all(fh, namespace=NS_USER),
356                                  [(self.USER_NN, self.USER_VAL)])