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 MANYOPS_COUNT = 131072
38 USER_NN = USER_NN.encode()
39 USER_VAL = USER_VAL.encode()
40 USER_ATTR = USER_ATTR.encode()
41 EMPTY_VAL = EMPTY_VAL.encode()
44 def _ignore_tuples(attrs):
45 """Remove ignored attributes from the output of xattr.get_all."""
46 return [attr for attr in attrs
47 if attr[0] not in TEST_IGNORE_XATTRS]
51 """Remove ignored attributes from the output of xattr.list"""
52 return [attr for attr in attrs
53 if attr not in TEST_IGNORE_XATTRS]
55 def checkList(self, attrs, value):
56 """Helper to check list equivalence, skipping TEST_IGNORE_XATTRS."""
57 self.assertEqual(self._ignore(attrs), value)
59 def checkTuples(self, attrs, value):
60 """Helper to check list equivalence, skipping TEST_IGNORE_XATTRS."""
61 self.assertEqual(self._ignore_tuples(attrs), value)
69 """tear down function"""
70 for fname in self.rmfiles:
73 except EnvironmentError:
75 for dname in self.rmdirs:
78 except EnvironmentError:
82 """create a temp file"""
83 fh, fname = tempfile.mkstemp(".test", "xattr-", TEST_DIR)
84 self.rmfiles.append(fname)
88 """create a temp dir"""
89 dname = tempfile.mkdtemp(".test", "xattr-", TEST_DIR)
90 self.rmdirs.append(dname)
93 def _getsymlink(self, dangling=True):
94 """create a symlink"""
95 fh, fname = self._getfile()
99 sname = fname + ".symlink"
100 os.symlink(fname, sname)
101 self.rmfiles.append(sname)
104 def _checkDeprecated(self, item, symlink=False):
105 """check deprecated list, set, get operations against an item"""
106 self.checkList(xattr.listxattr(item, symlink), [])
107 self.assertRaises(EnvironmentError, xattr.setxattr, item,
108 self.USER_ATTR, self.USER_VAL,
111 xattr.setxattr(item, self.USER_ATTR, self.USER_VAL, 0, symlink)
113 err = sys.exc_info()[1]
114 if symlink and (err.errno == errno.EPERM or
115 err.errno == errno.ENOENT):
116 # symlinks may fail, in which case we abort the rest
117 # of the test for this case (Linux returns EPERM; OS X
121 self.assertRaises(EnvironmentError, xattr.setxattr, item,
122 self.USER_ATTR, self.USER_VAL, XATTR_CREATE)
123 self.checkList(xattr.listxattr(item, symlink), [self.USER_ATTR])
124 self.assertEqual(xattr.getxattr(item, self.USER_ATTR, symlink),
126 self.checkTuples(xattr.get_all(item, nofollow=symlink),
127 [(self.USER_ATTR, self.USER_VAL)])
128 xattr.removexattr(item, self.USER_ATTR)
129 self.checkList(xattr.listxattr(item, symlink), [])
130 self.checkTuples(xattr.get_all(item, nofollow=symlink),
132 self.assertRaises(EnvironmentError, xattr.removexattr,
133 item, self.USER_ATTR)
135 def _checkListSetGet(self, item, symlink=False, use_ns=False):
136 """check list, set, get operations against an item"""
137 self.checkList(xattr.list(item, symlink), [])
138 self.assertRaises(EnvironmentError, xattr.set, item,
139 self.USER_ATTR, self.USER_VAL, flags=XATTR_REPLACE)
140 self.assertRaises(EnvironmentError, xattr.set, item,
141 self.USER_NN, self.USER_VAL, flags=XATTR_REPLACE,
145 xattr.set(item, self.USER_NN, self.USER_VAL,
149 xattr.set(item, self.USER_ATTR, self.USER_VAL,
152 err = sys.exc_info()[1]
153 if symlink and (err.errno == errno.EPERM or
154 err.errno == errno.ENOENT):
155 # symlinks may fail, in which case we abort the rest
156 # of the test for this case (Linux returns EPERM; OS X
160 self.assertRaises(EnvironmentError, xattr.set, item,
161 self.USER_ATTR, self.USER_VAL, flags=XATTR_CREATE)
162 self.assertRaises(EnvironmentError, xattr.set, item,
163 self.USER_NN, self.USER_VAL,
164 flags=XATTR_CREATE, namespace=NS_USER)
165 self.checkList(xattr.list(item, nofollow=symlink), [self.USER_ATTR])
166 self.checkList(xattr.list(item, nofollow=symlink,
169 self.assertEqual(xattr.list(item, namespace=NS_USER, nofollow=symlink),
171 self.assertEqual(xattr.get(item, self.USER_ATTR, nofollow=symlink),
173 self.assertEqual(xattr.get(item, self.USER_NN, nofollow=symlink,
174 namespace=NS_USER), self.USER_VAL)
175 self.checkTuples(xattr.get_all(item, nofollow=symlink),
176 [(self.USER_ATTR, self.USER_VAL)])
177 self.assertEqual(xattr.get_all(item, nofollow=symlink,
179 [(self.USER_NN, self.USER_VAL)])
181 xattr.remove(item, self.USER_NN, namespace=NS_USER)
183 xattr.remove(item, self.USER_ATTR)
184 self.checkList(xattr.list(item, symlink), [])
185 self.checkTuples(xattr.get_all(item, nofollow=symlink),
187 self.assertRaises(EnvironmentError, xattr.remove,
188 item, self.USER_ATTR, nofollow=symlink)
189 self.assertRaises(EnvironmentError, xattr.remove, item,
190 self.USER_NN, namespace=NS_USER, nofollow=symlink)
192 def testNoXattrDeprecated(self):
193 """test no attributes (deprecated functions)"""
194 fh, fname = self._getfile()
195 self.checkList(xattr.listxattr(fname), [])
196 self.checkTuples(xattr.get_all(fname), [])
197 self.assertRaises(EnvironmentError, xattr.getxattr, fname,
199 dname = self._getdir()
200 self.checkList(xattr.listxattr(dname), [])
201 self.checkTuples(xattr.get_all(dname), [])
202 self.assertRaises(EnvironmentError, xattr.getxattr, dname,
204 _, sname = self._getsymlink()
205 self.checkList(xattr.listxattr(sname, True), [])
206 self.checkTuples(xattr.get_all(sname, nofollow=True), [])
207 self.assertRaises(EnvironmentError, xattr.getxattr, fname,
208 self.USER_ATTR, True)
211 def testNoXattr(self):
212 """test no attributes"""
213 fh, fname = self._getfile()
214 self.checkList(xattr.list(fname), [])
215 self.assertEqual(xattr.list(fname, namespace=NS_USER), [])
216 self.checkTuples(xattr.get_all(fname), [])
217 self.assertEqual(xattr.get_all(fname, namespace=NS_USER), [])
218 self.assertRaises(EnvironmentError, xattr.get, fname,
219 self.USER_NN, namespace=NS_USER)
220 dname = self._getdir()
221 self.checkList(xattr.list(dname), [])
222 self.assertEqual(xattr.list(dname, namespace=NS_USER), [])
223 self.checkTuples(xattr.get_all(dname), [])
224 self.assertEqual(xattr.get_all(dname, namespace=NS_USER), [])
225 self.assertRaises(EnvironmentError, xattr.get, dname,
226 self.USER_NN, namespace=NS_USER)
227 _, sname = self._getsymlink()
228 self.checkList(xattr.list(sname, nofollow=True), [])
229 self.assertEqual(xattr.list(sname, nofollow=True,
230 namespace=NS_USER), [])
231 self.checkTuples(xattr.get_all(sname, nofollow=True), [])
232 self.assertEqual(xattr.get_all(sname, nofollow=True,
233 namespace=NS_USER), [])
234 self.assertRaises(EnvironmentError, xattr.get, sname,
235 self.USER_NN, namespace=NS_USER, nofollow=True)
237 def testFileByNameDeprecated(self):
238 """test set and retrieve one attribute by file name (deprecated)"""
239 fh, fname = self._getfile()
240 self._checkDeprecated(fname)
243 def testFileByName(self):
244 """test set and retrieve one attribute by file name"""
245 fh, fname = self._getfile()
246 self._checkListSetGet(fname)
247 self._checkListSetGet(fname, use_ns=True)
250 def testFileByDescriptorDeprecated(self):
251 """test file descriptor operations (deprecated functions)"""
252 fh, fname = self._getfile()
253 self._checkDeprecated(fh)
256 def testFileByDescriptor(self):
257 """test file descriptor operations"""
258 fh, fname = self._getfile()
259 self._checkListSetGet(fh)
260 self._checkListSetGet(fh, use_ns=True)
263 def testFileByObjectDeprecated(self):
264 """test file descriptor operations (deprecated functions)"""
265 fh, fname = self._getfile()
267 self._checkDeprecated(fo)
270 def testFileByObject(self):
271 """test file descriptor operations"""
272 fh, fname = self._getfile()
274 self._checkListSetGet(fo)
275 self._checkListSetGet(fo, use_ns=True)
278 def testMixedAccessDeprecated(self):
279 """test mixed access to file (deprecated functions)"""
280 fh, fname = self._getfile()
282 self.checkList(xattr.listxattr(fname), [])
283 xattr.setxattr(fname, self.USER_ATTR, self.USER_VAL)
284 self.checkList(xattr.listxattr(fh), [self.USER_ATTR])
285 self.assertEqual(xattr.getxattr(fo, self.USER_ATTR), self.USER_VAL)
286 self.checkTuples(xattr.get_all(fo), [(self.USER_ATTR, self.USER_VAL)])
287 self.checkTuples(xattr.get_all(fname),
288 [(self.USER_ATTR, self.USER_VAL)])
291 def testMixedAccess(self):
292 """test mixed access to file"""
293 fh, fname = self._getfile()
295 self.checkList(xattr.list(fname), [])
296 xattr.set(fname, self.USER_ATTR, self.USER_VAL)
297 self.checkList(xattr.list(fh), [self.USER_ATTR])
298 self.assertEqual(xattr.list(fh, namespace=NS_USER), [self.USER_NN])
299 self.assertEqual(xattr.get(fo, self.USER_ATTR), self.USER_VAL)
300 self.assertEqual(xattr.get(fo, self.USER_NN, namespace=NS_USER),
302 self.checkTuples(xattr.get_all(fo),
303 [(self.USER_ATTR, self.USER_VAL)])
304 self.assertEqual(xattr.get_all(fo, namespace=NS_USER),
305 [(self.USER_NN, self.USER_VAL)])
306 self.checkTuples(xattr.get_all(fname),
307 [(self.USER_ATTR, self.USER_VAL)])
308 self.assertEqual(xattr.get_all(fname, namespace=NS_USER),
309 [(self.USER_NN, self.USER_VAL)])
312 def testDirOpsDeprecated(self):
313 """test attribute setting on directories (deprecated functions)"""
314 dname = self._getdir()
315 self._checkDeprecated(dname)
317 def testDirOps(self):
318 """test attribute setting on directories"""
319 dname = self._getdir()
320 self._checkListSetGet(dname)
321 self._checkListSetGet(dname, use_ns=True)
323 def testSymlinkOpsDeprecated(self):
324 """test symlink operations (deprecated functions)"""
325 _, sname = self._getsymlink()
326 self.assertRaises(EnvironmentError, xattr.listxattr, sname)
327 self._checkDeprecated(sname, symlink=True)
328 target, sname = self._getsymlink(dangling=False)
329 xattr.setxattr(target, self.USER_ATTR, self.USER_VAL)
330 self.checkList(xattr.listxattr(target), [self.USER_ATTR])
331 self.checkList(xattr.listxattr(sname, True), [])
332 self.assertRaises(EnvironmentError, xattr.removexattr, sname,
333 self.USER_ATTR, True)
334 xattr.removexattr(sname, self.USER_ATTR, False)
336 def testSymlinkOps(self):
337 """test symlink operations"""
338 _, sname = self._getsymlink()
339 self.assertRaises(EnvironmentError, xattr.list, sname)
340 self._checkListSetGet(sname, symlink=True)
341 self._checkListSetGet(sname, symlink=True, use_ns=True)
342 target, sname = self._getsymlink(dangling=False)
343 xattr.set(target, self.USER_ATTR, self.USER_VAL)
344 self.checkList(xattr.list(target), [self.USER_ATTR])
345 self.checkList(xattr.list(sname, nofollow=True), [])
346 self.assertRaises(EnvironmentError, xattr.remove, sname,
347 self.USER_ATTR, nofollow=True)
348 xattr.remove(sname, self.USER_ATTR, nofollow=False)
350 def testBinaryPayloadDeprecated(self):
351 """test binary values (deprecated functions)"""
352 fh, fname = self._getfile()
354 BINVAL = "abc" + '\0' + "def"
356 BINVAL = BINVAL.encode()
357 xattr.setxattr(fname, self.USER_ATTR, BINVAL)
358 self.checkList(xattr.listxattr(fname), [self.USER_ATTR])
359 self.assertEqual(xattr.getxattr(fname, self.USER_ATTR), BINVAL)
360 self.checkTuples(xattr.get_all(fname), [(self.USER_ATTR, BINVAL)])
361 xattr.removexattr(fname, self.USER_ATTR)
363 def testBinaryPayload(self):
364 """test binary values"""
365 fh, fname = self._getfile()
367 BINVAL = "abc" + '\0' + "def"
369 BINVAL = BINVAL.encode()
370 xattr.set(fname, self.USER_ATTR, BINVAL)
371 self.checkList(xattr.list(fname), [self.USER_ATTR])
372 self.assertEqual(xattr.list(fname, namespace=NS_USER), [self.USER_NN])
373 self.assertEqual(xattr.get(fname, self.USER_ATTR), BINVAL)
374 self.assertEqual(xattr.get(fname, self.USER_NN,
375 namespace=NS_USER), BINVAL)
376 self.checkTuples(xattr.get_all(fname), [(self.USER_ATTR, BINVAL)])
377 self.assertEqual(xattr.get_all(fname, namespace=NS_USER),
378 [(self.USER_NN, BINVAL)])
379 xattr.remove(fname, self.USER_ATTR)
381 def testManyOpsDeprecated(self):
382 """test many ops (deprecated functions)"""
383 fh, fname = self._getfile()
384 xattr.setxattr(fh, self.USER_ATTR, self.USER_VAL)
385 VL = [self.USER_ATTR]
386 for i in range(self.MANYOPS_COUNT):
387 self.checkList(xattr.listxattr(fh), VL)
388 for i in range(self.MANYOPS_COUNT):
389 self.assertEqual(xattr.getxattr(fh, self.USER_ATTR), self.USER_VAL)
390 for i in range(self.MANYOPS_COUNT):
391 self.checkTuples(xattr.get_all(fh),
392 [(self.USER_ATTR, self.USER_VAL)])
394 def testManyOps(self):
396 fh, fname = self._getfile()
397 xattr.set(fh, self.USER_ATTR, self.USER_VAL)
398 VL = [self.USER_ATTR]
400 for i in range(self.MANYOPS_COUNT):
401 self.checkList(xattr.list(fh), VL)
402 self.checkList(xattr.list(fh, namespace=EMPTY_NS), VL)
403 self.assertEqual(xattr.list(fh, namespace=NS_USER), VN)
404 for i in range(self.MANYOPS_COUNT):
405 self.assertEqual(xattr.get(fh, self.USER_ATTR), self.USER_VAL)
406 self.assertEqual(xattr.get(fh, self.USER_NN, namespace=NS_USER),
408 for i in range(self.MANYOPS_COUNT):
409 self.checkTuples(xattr.get_all(fh),
410 [(self.USER_ATTR, self.USER_VAL)])
411 self.assertEqual(xattr.get_all(fh, namespace=NS_USER),
412 [(self.USER_NN, self.USER_VAL)])
414 def testNoneNamespace(self):
415 fh, fname = self._getfile()
416 self.assertRaises(TypeError, xattr.get, fh, self.USER_ATTR,
419 def testEmptyValue(self):
420 fh, fname = self._getfile()
421 xattr.set(fh, self.USER_ATTR, self.EMPTY_VAL)
422 self.assertEqual(xattr.get(fh, self.USER_ATTR), self.EMPTY_VAL)
424 def testWrongType(self):
425 self.assertRaises(TypeError, xattr.get, object(), self.USER_ATTR)
428 if __name__ == "__main__":