11 from xattr import NS_USER, XATTR_CREATE, XATTR_REPLACE
13 if sys.hexversion >= 0x03000000:
20 TEST_DIR = os.environ.get("TEST_DIR", ".")
21 TEST_IGNORE_XATTRS = os.environ.get("TEST_IGNORE_XATTRS", "")
22 if TEST_IGNORE_XATTRS == "":
23 TEST_IGNORE_XATTRS = []
25 TEST_IGNORE_XATTRS = TEST_IGNORE_XATTRS.split(",")
26 # The following has to be a list comprehension, not a generator, to
27 # avoid weird consequences of lazy evaluation.
28 TEST_IGNORE_XATTRS.extend([a.encode() for a in TEST_IGNORE_XATTRS])
30 class xattrTest(unittest.TestCase):
32 USER_ATTR = NS_USER.decode() + "." + USER_NN
35 LARGE_VAL = "x" * 2048
36 MANYOPS_COUNT = 131072
39 USER_NN = USER_NN.encode()
40 USER_VAL = USER_VAL.encode()
41 USER_ATTR = USER_ATTR.encode()
42 EMPTY_VAL = EMPTY_VAL.encode()
43 LARGE_VAL = LARGE_VAL.encode()
46 def _ignore_tuples(attrs):
47 """Remove ignored attributes from the output of xattr.get_all."""
48 return [attr for attr in attrs
49 if attr[0] not in TEST_IGNORE_XATTRS]
53 """Remove ignored attributes from the output of xattr.list"""
54 return [attr for attr in attrs
55 if attr not in TEST_IGNORE_XATTRS]
57 def checkList(self, attrs, value):
58 """Helper to check list equivalence, skipping TEST_IGNORE_XATTRS."""
59 self.assertEqual(self._ignore(attrs), value)
61 def checkTuples(self, attrs, value):
62 """Helper to check list equivalence, skipping TEST_IGNORE_XATTRS."""
63 self.assertEqual(self._ignore_tuples(attrs), value)
71 """tear down function"""
72 for fname in self.rmfiles:
75 except EnvironmentError:
77 for dname in self.rmdirs:
80 except EnvironmentError:
84 """create a temp file"""
85 fh, fname = tempfile.mkstemp(".test", "xattr-", TEST_DIR)
86 self.rmfiles.append(fname)
90 """create a temp dir"""
91 dname = tempfile.mkdtemp(".test", "xattr-", TEST_DIR)
92 self.rmdirs.append(dname)
95 def _getsymlink(self, dangling=True):
96 """create a symlink"""
97 fh, fname = self._getfile()
101 sname = fname + ".symlink"
102 os.symlink(fname, sname)
103 self.rmfiles.append(sname)
106 def _checkDeprecated(self, item, symlink=False):
107 """check deprecated list, set, get operations against an item"""
108 self.checkList(xattr.listxattr(item, symlink), [])
109 self.assertRaises(EnvironmentError, xattr.setxattr, item,
110 self.USER_ATTR, self.USER_VAL,
113 xattr.setxattr(item, self.USER_ATTR, self.USER_VAL, 0, symlink)
115 err = sys.exc_info()[1]
116 if symlink and (err.errno == errno.EPERM or
117 err.errno == errno.ENOENT):
118 # symlinks may fail, in which case we abort the rest
119 # of the test for this case (Linux returns EPERM; OS X
123 self.assertRaises(EnvironmentError, xattr.setxattr, item,
124 self.USER_ATTR, self.USER_VAL, XATTR_CREATE)
125 self.checkList(xattr.listxattr(item, symlink), [self.USER_ATTR])
126 self.assertEqual(xattr.getxattr(item, self.USER_ATTR, symlink),
128 self.checkTuples(xattr.get_all(item, nofollow=symlink),
129 [(self.USER_ATTR, self.USER_VAL)])
130 xattr.removexattr(item, self.USER_ATTR)
131 self.checkList(xattr.listxattr(item, symlink), [])
132 self.checkTuples(xattr.get_all(item, nofollow=symlink),
134 self.assertRaises(EnvironmentError, xattr.removexattr,
135 item, self.USER_ATTR)
137 def _checkListSetGet(self, item, symlink=False, use_ns=False):
138 """check list, set, get operations against an item"""
139 self.checkList(xattr.list(item, symlink), [])
140 self.assertRaises(EnvironmentError, xattr.set, item,
141 self.USER_ATTR, self.USER_VAL, flags=XATTR_REPLACE)
142 self.assertRaises(EnvironmentError, xattr.set, item,
143 self.USER_NN, self.USER_VAL, flags=XATTR_REPLACE,
147 xattr.set(item, self.USER_NN, self.USER_VAL,
151 xattr.set(item, self.USER_ATTR, self.USER_VAL,
154 err = sys.exc_info()[1]
155 if symlink and (err.errno == errno.EPERM or
156 err.errno == errno.ENOENT):
157 # symlinks may fail, in which case we abort the rest
158 # of the test for this case (Linux returns EPERM; OS X
162 self.assertRaises(EnvironmentError, xattr.set, item,
163 self.USER_ATTR, self.USER_VAL, flags=XATTR_CREATE)
164 self.assertRaises(EnvironmentError, xattr.set, item,
165 self.USER_NN, self.USER_VAL,
166 flags=XATTR_CREATE, namespace=NS_USER)
167 self.checkList(xattr.list(item, nofollow=symlink), [self.USER_ATTR])
168 self.checkList(xattr.list(item, nofollow=symlink,
171 self.assertEqual(xattr.list(item, namespace=NS_USER, nofollow=symlink),
173 self.assertEqual(xattr.get(item, self.USER_ATTR, nofollow=symlink),
175 self.assertEqual(xattr.get(item, self.USER_NN, nofollow=symlink,
176 namespace=NS_USER), self.USER_VAL)
177 self.checkTuples(xattr.get_all(item, nofollow=symlink),
178 [(self.USER_ATTR, self.USER_VAL)])
179 self.assertEqual(xattr.get_all(item, nofollow=symlink,
181 [(self.USER_NN, self.USER_VAL)])
183 xattr.remove(item, self.USER_NN, namespace=NS_USER)
185 xattr.remove(item, self.USER_ATTR)
186 self.checkList(xattr.list(item, symlink), [])
187 self.checkTuples(xattr.get_all(item, nofollow=symlink),
189 self.assertRaises(EnvironmentError, xattr.remove,
190 item, self.USER_ATTR, nofollow=symlink)
191 self.assertRaises(EnvironmentError, xattr.remove, item,
192 self.USER_NN, namespace=NS_USER, nofollow=symlink)
194 def testNoXattrDeprecated(self):
195 """test no attributes (deprecated functions)"""
196 fh, fname = self._getfile()
197 self.checkList(xattr.listxattr(fname), [])
198 self.checkTuples(xattr.get_all(fname), [])
199 self.assertRaises(EnvironmentError, xattr.getxattr, fname,
201 dname = self._getdir()
202 self.checkList(xattr.listxattr(dname), [])
203 self.checkTuples(xattr.get_all(dname), [])
204 self.assertRaises(EnvironmentError, xattr.getxattr, dname,
206 _, sname = self._getsymlink()
207 self.checkList(xattr.listxattr(sname, True), [])
208 self.checkTuples(xattr.get_all(sname, nofollow=True), [])
209 self.assertRaises(EnvironmentError, xattr.getxattr, fname,
210 self.USER_ATTR, True)
213 def testNoXattr(self):
214 """test no attributes"""
215 fh, fname = self._getfile()
216 self.checkList(xattr.list(fname), [])
217 self.assertEqual(xattr.list(fname, namespace=NS_USER), [])
218 self.checkTuples(xattr.get_all(fname), [])
219 self.assertEqual(xattr.get_all(fname, namespace=NS_USER), [])
220 self.assertRaises(EnvironmentError, xattr.get, fname,
221 self.USER_NN, namespace=NS_USER)
222 dname = self._getdir()
223 self.checkList(xattr.list(dname), [])
224 self.assertEqual(xattr.list(dname, namespace=NS_USER), [])
225 self.checkTuples(xattr.get_all(dname), [])
226 self.assertEqual(xattr.get_all(dname, namespace=NS_USER), [])
227 self.assertRaises(EnvironmentError, xattr.get, dname,
228 self.USER_NN, namespace=NS_USER)
229 _, sname = self._getsymlink()
230 self.checkList(xattr.list(sname, nofollow=True), [])
231 self.assertEqual(xattr.list(sname, nofollow=True,
232 namespace=NS_USER), [])
233 self.checkTuples(xattr.get_all(sname, nofollow=True), [])
234 self.assertEqual(xattr.get_all(sname, nofollow=True,
235 namespace=NS_USER), [])
236 self.assertRaises(EnvironmentError, xattr.get, sname,
237 self.USER_NN, namespace=NS_USER, nofollow=True)
239 def testFileByNameDeprecated(self):
240 """test set and retrieve one attribute by file name (deprecated)"""
241 fh, fname = self._getfile()
242 self._checkDeprecated(fname)
245 def testFileByName(self):
246 """test set and retrieve one attribute by file name"""
247 fh, fname = self._getfile()
248 self._checkListSetGet(fname)
249 self._checkListSetGet(fname, use_ns=True)
252 def testFileByDescriptorDeprecated(self):
253 """test file descriptor operations (deprecated functions)"""
254 fh, fname = self._getfile()
255 self._checkDeprecated(fh)
258 def testFileByDescriptor(self):
259 """test file descriptor operations"""
260 fh, fname = self._getfile()
261 self._checkListSetGet(fh)
262 self._checkListSetGet(fh, use_ns=True)
265 def testFileByObjectDeprecated(self):
266 """test file descriptor operations (deprecated functions)"""
267 fh, fname = self._getfile()
269 self._checkDeprecated(fo)
272 def testFileByObject(self):
273 """test file descriptor operations"""
274 fh, fname = self._getfile()
276 self._checkListSetGet(fo)
277 self._checkListSetGet(fo, use_ns=True)
280 def testMixedAccessDeprecated(self):
281 """test mixed access to file (deprecated functions)"""
282 fh, fname = self._getfile()
284 self.checkList(xattr.listxattr(fname), [])
285 xattr.setxattr(fname, self.USER_ATTR, self.USER_VAL)
286 self.checkList(xattr.listxattr(fh), [self.USER_ATTR])
287 self.assertEqual(xattr.getxattr(fo, self.USER_ATTR), self.USER_VAL)
288 self.checkTuples(xattr.get_all(fo), [(self.USER_ATTR, self.USER_VAL)])
289 self.checkTuples(xattr.get_all(fname),
290 [(self.USER_ATTR, self.USER_VAL)])
293 def testMixedAccess(self):
294 """test mixed access to file"""
295 fh, fname = self._getfile()
297 self.checkList(xattr.list(fname), [])
298 xattr.set(fname, self.USER_ATTR, self.USER_VAL)
299 self.checkList(xattr.list(fh), [self.USER_ATTR])
300 self.assertEqual(xattr.list(fh, namespace=NS_USER), [self.USER_NN])
301 self.assertEqual(xattr.get(fo, self.USER_ATTR), self.USER_VAL)
302 self.assertEqual(xattr.get(fo, self.USER_NN, namespace=NS_USER),
304 self.checkTuples(xattr.get_all(fo),
305 [(self.USER_ATTR, self.USER_VAL)])
306 self.assertEqual(xattr.get_all(fo, namespace=NS_USER),
307 [(self.USER_NN, self.USER_VAL)])
308 self.checkTuples(xattr.get_all(fname),
309 [(self.USER_ATTR, self.USER_VAL)])
310 self.assertEqual(xattr.get_all(fname, namespace=NS_USER),
311 [(self.USER_NN, self.USER_VAL)])
314 def testDirOpsDeprecated(self):
315 """test attribute setting on directories (deprecated functions)"""
316 dname = self._getdir()
317 self._checkDeprecated(dname)
319 def testDirOps(self):
320 """test attribute setting on directories"""
321 dname = self._getdir()
322 self._checkListSetGet(dname)
323 self._checkListSetGet(dname, use_ns=True)
325 def testSymlinkOpsDeprecated(self):
326 """test symlink operations (deprecated functions)"""
327 _, sname = self._getsymlink()
328 self.assertRaises(EnvironmentError, xattr.listxattr, sname)
329 self._checkDeprecated(sname, symlink=True)
330 target, sname = self._getsymlink(dangling=False)
331 xattr.setxattr(target, self.USER_ATTR, self.USER_VAL)
332 self.checkList(xattr.listxattr(target), [self.USER_ATTR])
333 self.checkList(xattr.listxattr(sname, True), [])
334 self.assertRaises(EnvironmentError, xattr.removexattr, sname,
335 self.USER_ATTR, True)
336 xattr.removexattr(sname, self.USER_ATTR, False)
338 def testSymlinkOps(self):
339 """test symlink operations"""
340 _, sname = self._getsymlink()
341 self.assertRaises(EnvironmentError, xattr.list, sname)
342 self._checkListSetGet(sname, symlink=True)
343 self._checkListSetGet(sname, symlink=True, use_ns=True)
344 target, sname = self._getsymlink(dangling=False)
345 xattr.set(target, self.USER_ATTR, self.USER_VAL)
346 self.checkList(xattr.list(target), [self.USER_ATTR])
347 self.checkList(xattr.list(sname, nofollow=True), [])
348 self.assertRaises(EnvironmentError, xattr.remove, sname,
349 self.USER_ATTR, nofollow=True)
350 xattr.remove(sname, self.USER_ATTR, nofollow=False)
352 def testBinaryPayloadDeprecated(self):
353 """test binary values (deprecated functions)"""
354 fh, fname = self._getfile()
356 BINVAL = "abc" + '\0' + "def"
358 BINVAL = BINVAL.encode()
359 xattr.setxattr(fname, self.USER_ATTR, BINVAL)
360 self.checkList(xattr.listxattr(fname), [self.USER_ATTR])
361 self.assertEqual(xattr.getxattr(fname, self.USER_ATTR), BINVAL)
362 self.checkTuples(xattr.get_all(fname), [(self.USER_ATTR, BINVAL)])
363 xattr.removexattr(fname, self.USER_ATTR)
365 def testBinaryPayload(self):
366 """test binary values"""
367 fh, fname = self._getfile()
369 BINVAL = "abc" + '\0' + "def"
371 BINVAL = BINVAL.encode()
372 xattr.set(fname, self.USER_ATTR, BINVAL)
373 self.checkList(xattr.list(fname), [self.USER_ATTR])
374 self.assertEqual(xattr.list(fname, namespace=NS_USER), [self.USER_NN])
375 self.assertEqual(xattr.get(fname, self.USER_ATTR), BINVAL)
376 self.assertEqual(xattr.get(fname, self.USER_NN,
377 namespace=NS_USER), BINVAL)
378 self.checkTuples(xattr.get_all(fname), [(self.USER_ATTR, BINVAL)])
379 self.assertEqual(xattr.get_all(fname, namespace=NS_USER),
380 [(self.USER_NN, BINVAL)])
381 xattr.remove(fname, self.USER_ATTR)
383 def testManyOpsDeprecated(self):
384 """test many ops (deprecated functions)"""
385 fh, fname = self._getfile()
386 xattr.setxattr(fh, self.USER_ATTR, self.USER_VAL)
387 VL = [self.USER_ATTR]
388 for i in range(self.MANYOPS_COUNT):
389 self.checkList(xattr.listxattr(fh), VL)
390 for i in range(self.MANYOPS_COUNT):
391 self.assertEqual(xattr.getxattr(fh, self.USER_ATTR), self.USER_VAL)
392 for i in range(self.MANYOPS_COUNT):
393 self.checkTuples(xattr.get_all(fh),
394 [(self.USER_ATTR, self.USER_VAL)])
396 def testManyOps(self):
398 fh, fname = self._getfile()
399 xattr.set(fh, self.USER_ATTR, self.USER_VAL)
400 VL = [self.USER_ATTR]
402 for i in range(self.MANYOPS_COUNT):
403 self.checkList(xattr.list(fh), VL)
404 self.checkList(xattr.list(fh, namespace=EMPTY_NS), VL)
405 self.assertEqual(xattr.list(fh, namespace=NS_USER), VN)
406 for i in range(self.MANYOPS_COUNT):
407 self.assertEqual(xattr.get(fh, self.USER_ATTR), self.USER_VAL)
408 self.assertEqual(xattr.get(fh, self.USER_NN, namespace=NS_USER),
410 for i in range(self.MANYOPS_COUNT):
411 self.checkTuples(xattr.get_all(fh),
412 [(self.USER_ATTR, self.USER_VAL)])
413 self.assertEqual(xattr.get_all(fh, namespace=NS_USER),
414 [(self.USER_NN, self.USER_VAL)])
416 def testNoneNamespace(self):
417 fh, fname = self._getfile()
418 self.assertRaises(TypeError, xattr.get, fh, self.USER_ATTR,
421 def testEmptyValue(self):
422 fh, fname = self._getfile()
423 xattr.set(fh, self.USER_ATTR, self.EMPTY_VAL)
424 self.assertEqual(xattr.get(fh, self.USER_ATTR), self.EMPTY_VAL)
426 def testWrongCall(self):
427 for call in [xattr.get,
428 xattr.list, xattr.listxattr,
429 xattr.remove, xattr.removexattr,
430 xattr.set, xattr.setxattr,
431 xattr.get, xattr.getxattr]:
432 self.assertRaises(TypeError, call)
434 def testWrongType(self):
435 self.assertRaises(TypeError, xattr.get, object(), self.USER_ATTR)
436 for call in [xattr.listxattr, xattr.list]:
437 self.assertRaises(TypeError, call, object())
438 for call in [xattr.remove, xattr.removexattr,
439 xattr.get, xattr.getxattr]:
440 self.assertRaises(TypeError, call, object(), self.USER_ATTR)
441 for call in [xattr.set, xattr.setxattr]:
442 self.assertRaises(TypeError, call, object(), self.USER_ATTR, self.USER_VAL)
445 def testLargeAttribute(self):
446 fh, fname = self._getfile()
448 xattr.set(fh, self.USER_ATTR, self.LARGE_VAL)
449 self.assertEqual(xattr.get(fh, self.USER_ATTR), self.LARGE_VAL)
452 if __name__ == "__main__":