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
34 MANYOPS_COUNT = 131072
37 USER_NN = USER_NN.encode()
38 USER_VAL = USER_VAL.encode()
39 USER_ATTR = USER_ATTR.encode()
42 def _ignore_tuples(attrs):
43 """Remove ignored attributes from the output of xattr.get_all."""
44 return [attr for attr in attrs
45 if attr[0] not in TEST_IGNORE_XATTRS]
49 """Remove ignored attributes from the output of xattr.list"""
50 return [attr for attr in attrs
51 if attr not in TEST_IGNORE_XATTRS]
53 def checkList(self, attrs, value):
54 """Helper to check attribute list equivalence, skipping TEST_IGNORE_XATTRS."""
55 self.assertEqual(self._ignore(attrs), value)
57 def checkTuples(self, attrs, value):
58 """Helper to check attribute list equivalence, skipping TEST_IGNORE_XATTRS."""
59 self.assertEqual(self._ignore_tuples(attrs), value)
67 """tear down function"""
68 for fname in self.rmfiles:
71 except EnvironmentError:
73 for dname in self.rmdirs:
76 except EnvironmentError:
80 """create a temp file"""
81 fh, fname = tempfile.mkstemp(".test", "xattr-", TEST_DIR)
82 self.rmfiles.append(fname)
86 """create a temp dir"""
87 dname = tempfile.mkdtemp(".test", "xattr-", TEST_DIR)
88 self.rmdirs.append(dname)
91 def _getsymlink(self, dangling=True):
92 """create a symlink"""
93 fh, fname = self._getfile()
97 sname = fname + ".symlink"
98 os.symlink(fname, sname)
99 self.rmfiles.append(sname)
102 def _checkDeprecated(self, item, symlink=False):
103 """check deprecated list, set, get operations against an item"""
104 self.checkList(xattr.listxattr(item, symlink), [])
105 self.assertRaises(EnvironmentError, xattr.setxattr, item,
106 self.USER_ATTR, self.USER_VAL,
109 xattr.setxattr(item, self.USER_ATTR, self.USER_VAL, 0, symlink)
111 err = sys.exc_info()[1]
112 if err.errno == errno.EPERM and symlink:
113 # symlinks may fail, in which case we abort the rest
114 # of the test for this case
117 self.assertRaises(EnvironmentError, xattr.setxattr, item,
118 self.USER_ATTR, self.USER_VAL, XATTR_CREATE)
119 self.checkList(xattr.listxattr(item, symlink), [self.USER_ATTR])
120 self.assertEqual(xattr.getxattr(item, self.USER_ATTR, symlink),
122 self.checkTuples(xattr.get_all(item, nofollow=symlink),
123 [(self.USER_ATTR, self.USER_VAL)])
124 xattr.removexattr(item, self.USER_ATTR)
125 self.checkList(xattr.listxattr(item, symlink), [])
126 self.checkTuples(xattr.get_all(item, nofollow=symlink),
128 self.assertRaises(EnvironmentError, xattr.removexattr,
129 item, self.USER_ATTR)
131 def _checkListSetGet(self, item, symlink=False, use_ns=False):
132 """check list, set, get operations against an item"""
133 self.checkList(xattr.list(item, symlink), [])
134 self.assertRaises(EnvironmentError, xattr.set, item,
135 self.USER_ATTR, self.USER_VAL, flags=XATTR_REPLACE)
136 self.assertRaises(EnvironmentError, xattr.set, item,
137 self.USER_NN, self.USER_VAL, flags=XATTR_REPLACE,
141 xattr.set(item, self.USER_NN, self.USER_VAL,
145 xattr.set(item, self.USER_ATTR, self.USER_VAL,
148 err = sys.exc_info()[1]
149 if err.errno == errno.EPERM and symlink:
150 # symlinks may fail, in which case we abort the rest
151 # of the test for this case
154 self.assertRaises(EnvironmentError, xattr.set, item,
155 self.USER_ATTR, self.USER_VAL, flags=XATTR_CREATE)
156 self.assertRaises(EnvironmentError, xattr.set, item,
157 self.USER_NN, self.USER_VAL,
158 flags=XATTR_CREATE, namespace=NS_USER)
159 self.checkList(xattr.list(item, nofollow=symlink), [self.USER_ATTR])
160 self.checkList(xattr.list(item, nofollow=symlink,
163 self.assertEqual(xattr.list(item, namespace=NS_USER, nofollow=symlink),
165 self.assertEqual(xattr.get(item, self.USER_ATTR, nofollow=symlink),
167 self.assertEqual(xattr.get(item, self.USER_NN, nofollow=symlink,
168 namespace=NS_USER), self.USER_VAL)
169 self.checkTuples(xattr.get_all(item, nofollow=symlink),
170 [(self.USER_ATTR, self.USER_VAL)])
171 self.assertEqual(xattr.get_all(item, nofollow=symlink,
173 [(self.USER_NN, self.USER_VAL)])
175 xattr.remove(item, self.USER_NN, namespace=NS_USER)
177 xattr.remove(item, self.USER_ATTR)
178 self.checkList(xattr.list(item, symlink), [])
179 self.checkTuples(xattr.get_all(item, nofollow=symlink),
181 self.assertRaises(EnvironmentError, xattr.remove,
182 item, self.USER_ATTR, nofollow=symlink)
183 self.assertRaises(EnvironmentError, xattr.remove, item,
184 self.USER_NN, namespace=NS_USER, nofollow=symlink)
186 def testNoXattrDeprecated(self):
187 """test no attributes (deprecated functions)"""
188 fh, fname = self._getfile()
189 self.checkList(xattr.listxattr(fname), [])
190 self.checkTuples(xattr.get_all(fname), [])
191 dname = self._getdir()
192 self.checkList(xattr.listxattr(dname), [])
193 self.checkTuples(xattr.get_all(dname), [])
194 _, sname = self._getsymlink()
195 self.checkList(xattr.listxattr(sname, True), [])
196 self.checkTuples(xattr.get_all(sname, nofollow=True), [])
198 def testNoXattr(self):
199 """test no attributes"""
200 fh, fname = self._getfile()
201 self.checkList(xattr.list(fname), [])
202 self.assertEqual(xattr.list(fname, namespace=NS_USER), [])
203 self.checkTuples(xattr.get_all(fname), [])
204 self.assertEqual(xattr.get_all(fname, namespace=NS_USER), [])
205 dname = self._getdir()
206 self.checkList(xattr.list(dname), [])
207 self.assertEqual(xattr.list(dname, namespace=NS_USER), [])
208 self.checkTuples(xattr.get_all(dname), [])
209 self.assertEqual(xattr.get_all(dname, namespace=NS_USER), [])
210 _, sname = self._getsymlink()
211 self.checkList(xattr.list(sname, nofollow=True), [])
212 self.assertEqual(xattr.list(sname, nofollow=True,
213 namespace=NS_USER), [])
214 self.checkTuples(xattr.get_all(sname, nofollow=True), [])
215 self.assertEqual(xattr.get_all(sname, nofollow=True,
216 namespace=NS_USER), [])
218 def testFileByNameDeprecated(self):
219 """test set and retrieve one attribute by file name (deprecated)"""
220 fh, fname = self._getfile()
221 self._checkDeprecated(fname)
224 def testFileByName(self):
225 """test set and retrieve one attribute by file name"""
226 fh, fname = self._getfile()
227 self._checkListSetGet(fname)
228 self._checkListSetGet(fname, use_ns=True)
231 def testFileByDescriptorDeprecated(self):
232 """test file descriptor operations (deprecated functions)"""
233 fh, fname = self._getfile()
234 self._checkDeprecated(fh)
237 def testFileByDescriptor(self):
238 """test file descriptor operations"""
239 fh, fname = self._getfile()
240 self._checkListSetGet(fh)
241 self._checkListSetGet(fh, use_ns=True)
244 def testFileByObjectDeprecated(self):
245 """test file descriptor operations (deprecated functions)"""
246 fh, fname = self._getfile()
248 self._checkDeprecated(fo)
251 def testFileByObject(self):
252 """test file descriptor operations"""
253 fh, fname = self._getfile()
255 self._checkListSetGet(fo)
256 self._checkListSetGet(fo, use_ns=True)
259 def testMixedAccessDeprecated(self):
260 """test mixed access to file (deprecated functions)"""
261 fh, fname = self._getfile()
263 self.checkList(xattr.listxattr(fname), [])
264 xattr.setxattr(fname, self.USER_ATTR, self.USER_VAL)
265 self.checkList(xattr.listxattr(fh), [self.USER_ATTR])
266 self.assertEqual(xattr.getxattr(fo, self.USER_ATTR), self.USER_VAL)
267 self.checkTuples(xattr.get_all(fo), [(self.USER_ATTR, self.USER_VAL)])
268 self.checkTuples(xattr.get_all(fname),
269 [(self.USER_ATTR, self.USER_VAL)])
272 def testMixedAccess(self):
273 """test mixed access to file"""
274 fh, fname = self._getfile()
276 self.checkList(xattr.list(fname), [])
277 xattr.set(fname, self.USER_ATTR, self.USER_VAL)
278 self.checkList(xattr.list(fh), [self.USER_ATTR])
279 self.assertEqual(xattr.list(fh, namespace=NS_USER), [self.USER_NN])
280 self.assertEqual(xattr.get(fo, self.USER_ATTR), self.USER_VAL)
281 self.assertEqual(xattr.get(fo, self.USER_NN, namespace=NS_USER),
283 self.checkTuples(xattr.get_all(fo),
284 [(self.USER_ATTR, self.USER_VAL)])
285 self.assertEqual(xattr.get_all(fo, namespace=NS_USER),
286 [(self.USER_NN, self.USER_VAL)])
287 self.checkTuples(xattr.get_all(fname),
288 [(self.USER_ATTR, self.USER_VAL)])
289 self.assertEqual(xattr.get_all(fname, namespace=NS_USER),
290 [(self.USER_NN, self.USER_VAL)])
293 def testDirOpsDeprecated(self):
294 """test attribute setting on directories (deprecated functions)"""
295 dname = self._getdir()
296 self._checkDeprecated(dname)
298 def testDirOps(self):
299 """test attribute setting on directories"""
300 dname = self._getdir()
301 self._checkListSetGet(dname)
302 self._checkListSetGet(dname, use_ns=True)
304 def testSymlinkOpsDeprecated(self):
305 """test symlink operations (deprecated functions)"""
306 _, sname = self._getsymlink()
307 self.assertRaises(EnvironmentError, xattr.listxattr, sname)
308 self._checkDeprecated(sname, symlink=True)
309 target, sname = self._getsymlink(dangling=False)
310 xattr.setxattr(target, self.USER_ATTR, self.USER_VAL)
311 self.checkList(xattr.listxattr(target), [self.USER_ATTR])
312 self.checkList(xattr.listxattr(sname, True), [])
313 self.assertRaises(EnvironmentError, xattr.removexattr, sname,
314 self.USER_ATTR, True)
315 xattr.removexattr(sname, self.USER_ATTR, False)
317 def testSymlinkOps(self):
318 """test symlink operations"""
319 _, sname = self._getsymlink()
320 self.assertRaises(EnvironmentError, xattr.list, sname)
321 self._checkListSetGet(sname, symlink=True)
322 self._checkListSetGet(sname, symlink=True, use_ns=True)
323 target, sname = self._getsymlink(dangling=False)
324 xattr.set(target, self.USER_ATTR, self.USER_VAL)
325 self.checkList(xattr.list(target), [self.USER_ATTR])
326 self.checkList(xattr.list(sname, nofollow=True), [])
327 self.assertRaises(EnvironmentError, xattr.remove, sname,
328 self.USER_ATTR, nofollow=True)
329 xattr.remove(sname, self.USER_ATTR, nofollow=False)
331 def testBinaryPayloadDeprecated(self):
332 """test binary values (deprecated functions)"""
333 fh, fname = self._getfile()
335 BINVAL = "abc" + '\0' + "def"
337 BINVAL = BINVAL.encode()
338 xattr.setxattr(fname, self.USER_ATTR, BINVAL)
339 self.checkList(xattr.listxattr(fname), [self.USER_ATTR])
340 self.assertEqual(xattr.getxattr(fname, self.USER_ATTR), BINVAL)
341 self.checkTuples(xattr.get_all(fname), [(self.USER_ATTR, BINVAL)])
342 xattr.removexattr(fname, self.USER_ATTR)
344 def testBinaryPayload(self):
345 """test binary values"""
346 fh, fname = self._getfile()
348 BINVAL = "abc" + '\0' + "def"
350 BINVAL = BINVAL.encode()
351 xattr.set(fname, self.USER_ATTR, BINVAL)
352 self.checkList(xattr.list(fname), [self.USER_ATTR])
353 self.assertEqual(xattr.list(fname, namespace=NS_USER), [self.USER_NN])
354 self.assertEqual(xattr.get(fname, self.USER_ATTR), BINVAL)
355 self.assertEqual(xattr.get(fname, self.USER_NN,
356 namespace=NS_USER), BINVAL)
357 self.checkTuples(xattr.get_all(fname), [(self.USER_ATTR, BINVAL)])
358 self.assertEqual(xattr.get_all(fname, namespace=NS_USER),
359 [(self.USER_NN, BINVAL)])
360 xattr.remove(fname, self.USER_ATTR)
362 def testManyOpsDeprecated(self):
363 """test many ops (deprecated functions)"""
364 fh, fname = self._getfile()
365 xattr.setxattr(fh, self.USER_ATTR, self.USER_VAL)
366 VL = [self.USER_ATTR]
367 for i in range(self.MANYOPS_COUNT):
368 self.checkList(xattr.listxattr(fh), VL)
369 for i in range(self.MANYOPS_COUNT):
370 self.assertEqual(xattr.getxattr(fh, self.USER_ATTR), self.USER_VAL)
371 for i in range(self.MANYOPS_COUNT):
372 self.checkTuples(xattr.get_all(fh),
373 [(self.USER_ATTR, self.USER_VAL)])
375 def testManyOps(self):
377 fh, fname = self._getfile()
378 xattr.set(fh, self.USER_ATTR, self.USER_VAL)
379 VL = [self.USER_ATTR]
381 for i in range(self.MANYOPS_COUNT):
382 self.checkList(xattr.list(fh), VL)
383 self.checkList(xattr.list(fh, namespace=EMPTY_NS), VL)
384 self.assertEqual(xattr.list(fh, namespace=NS_USER), VN)
385 for i in range(self.MANYOPS_COUNT):
386 self.assertEqual(xattr.get(fh, self.USER_ATTR), self.USER_VAL)
387 self.assertEqual(xattr.get(fh, self.USER_NN, namespace=NS_USER),
389 for i in range(self.MANYOPS_COUNT):
390 self.checkTuples(xattr.get_all(fh),
391 [(self.USER_ATTR, self.USER_VAL)])
392 self.assertEqual(xattr.get_all(fh, namespace=NS_USER),
393 [(self.USER_NN, self.USER_VAL)])
395 def testNoneNamespace(self):
396 fh, fname = self._getfile()
397 self.assertRaises(TypeError, xattr.get, fh, self.USER_ATTR,
401 if __name__ == "__main__":