11 from xattr import NS_USER, XATTR_CREATE, XATTR_REPLACE
13 NAMESPACE = os.environ.get("NAMESPACE", NS_USER)
15 if sys.hexversion >= 0x03000000:
22 TEST_DIR = os.environ.get("TEST_DIR", ".")
23 TEST_IGNORE_XATTRS = os.environ.get("TEST_IGNORE_XATTRS", "")
24 if TEST_IGNORE_XATTRS == "":
25 TEST_IGNORE_XATTRS = []
27 TEST_IGNORE_XATTRS = TEST_IGNORE_XATTRS.split(",")
28 # The following has to be a list comprehension, not a generator, to
29 # avoid weird consequences of lazy evaluation.
30 TEST_IGNORE_XATTRS.extend([a.encode() for a in TEST_IGNORE_XATTRS])
33 USER_ATTR = NAMESPACE.decode() + "." + USER_NN
36 LARGE_VAL = "x" * 2048
37 MANYOPS_COUNT = 131072
40 USER_NN = USER_NN.encode()
41 USER_VAL = USER_VAL.encode()
42 USER_ATTR = USER_ATTR.encode()
43 EMPTY_VAL = EMPTY_VAL.encode()
44 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]
52 """Remove ignored attributes from the output of xattr.list"""
53 return [attr for attr in attrs
54 if attr not in TEST_IGNORE_XATTRS]
56 def lists_equal(attrs, value):
57 """Helper to check list equivalence, skipping TEST_IGNORE_XATTRS."""
58 assert ignore(attrs) == value
60 def tuples_equal(attrs, value):
61 """Helper to check list equivalence, skipping TEST_IGNORE_XATTRS."""
62 assert ignore_tuples(attrs) == value
65 class xattrTest(unittest.TestCase):
72 """tear down function"""
73 for fname in self.rmfiles:
76 except EnvironmentError:
78 for dname in self.rmdirs:
81 except EnvironmentError:
85 """create a temp file"""
86 fh, fname = tempfile.mkstemp(".test", "xattr-", TEST_DIR)
87 self.rmfiles.append(fname)
91 """create a temp dir"""
92 dname = tempfile.mkdtemp(".test", "xattr-", TEST_DIR)
93 self.rmdirs.append(dname)
96 def _getsymlink(self, dangling=True):
97 """create a symlink"""
98 fh, fname = self._getfile()
102 sname = fname + ".symlink"
103 os.symlink(fname, sname)
104 self.rmfiles.append(sname)
107 def _checkDeprecated(self, item, symlink=False):
108 """check deprecated list, set, get operations against an item"""
109 lists_equal(xattr.listxattr(item, symlink), [])
110 self.assertRaises(EnvironmentError, xattr.setxattr, item,
112 XATTR_REPLACE, symlink)
113 xattr.setxattr(item, USER_ATTR, USER_VAL, 0, symlink)
114 self.assertRaises(EnvironmentError, xattr.setxattr, item,
115 USER_ATTR, USER_VAL, XATTR_CREATE, symlink)
116 lists_equal(xattr.listxattr(item, symlink), [USER_ATTR])
117 self.assertEqual(xattr.getxattr(item, USER_ATTR, symlink),
119 tuples_equal(xattr.get_all(item, nofollow=symlink),
120 [(USER_ATTR, USER_VAL)])
121 xattr.removexattr(item, USER_ATTR, symlink)
122 lists_equal(xattr.listxattr(item, symlink), [])
123 tuples_equal(xattr.get_all(item, nofollow=symlink),
125 self.assertRaises(EnvironmentError, xattr.removexattr,
126 item, USER_ATTR, symlink)
128 def _checkListSetGet(self, item, symlink=False, use_ns=False):
129 """check list, set, get operations against an item"""
130 lists_equal(xattr.list(item, symlink), [])
131 self.assertRaises(EnvironmentError, xattr.set, item,
135 self.assertRaises(EnvironmentError, xattr.set, item,
141 xattr.set(item, USER_NN, USER_VAL,
145 xattr.set(item, USER_ATTR, USER_VAL,
147 self.assertRaises(EnvironmentError, xattr.set, item,
151 self.assertRaises(EnvironmentError, xattr.set, item,
156 lists_equal(xattr.list(item, nofollow=symlink), [USER_ATTR])
157 lists_equal(xattr.list(item, nofollow=symlink,
160 self.assertEqual(xattr.list(item, namespace=NAMESPACE, nofollow=symlink),
162 self.assertEqual(xattr.get(item, USER_ATTR, nofollow=symlink),
164 self.assertEqual(xattr.get(item, USER_NN, nofollow=symlink,
165 namespace=NAMESPACE), USER_VAL)
166 tuples_equal(xattr.get_all(item, nofollow=symlink),
167 [(USER_ATTR, USER_VAL)])
168 self.assertEqual(xattr.get_all(item, nofollow=symlink,
169 namespace=NAMESPACE),
170 [(USER_NN, USER_VAL)])
172 xattr.remove(item, USER_NN, namespace=NAMESPACE, nofollow=symlink)
174 xattr.remove(item, USER_ATTR, nofollow=symlink)
175 lists_equal(xattr.list(item, nofollow=symlink), [])
176 tuples_equal(xattr.get_all(item, nofollow=symlink),
178 self.assertRaises(EnvironmentError, xattr.remove,
179 item, USER_ATTR, nofollow=symlink)
180 self.assertRaises(EnvironmentError, xattr.remove, item,
181 USER_NN, namespace=NAMESPACE, nofollow=symlink)
183 def testNoXattrDeprecated(self):
184 """test no attributes (deprecated functions)"""
185 fh, fname = self._getfile()
186 lists_equal(xattr.listxattr(fname), [])
187 tuples_equal(xattr.get_all(fname), [])
188 self.assertRaises(EnvironmentError, xattr.getxattr, fname,
190 dname = self._getdir()
191 lists_equal(xattr.listxattr(dname), [])
192 tuples_equal(xattr.get_all(dname), [])
193 self.assertRaises(EnvironmentError, xattr.getxattr, dname,
195 _, sname = self._getsymlink()
196 lists_equal(xattr.listxattr(sname, True), [])
197 tuples_equal(xattr.get_all(sname, nofollow=True), [])
198 self.assertRaises(EnvironmentError, xattr.getxattr, fname,
202 def testNoXattr(self):
203 """test no attributes"""
204 fh, fname = self._getfile()
205 lists_equal(xattr.list(fname), [])
206 self.assertEqual(xattr.list(fname, namespace=NAMESPACE), [])
207 tuples_equal(xattr.get_all(fname), [])
208 self.assertEqual(xattr.get_all(fname, namespace=NAMESPACE), [])
209 self.assertRaises(EnvironmentError, xattr.get, fname,
210 USER_NN, namespace=NAMESPACE)
211 dname = self._getdir()
212 lists_equal(xattr.list(dname), [])
213 self.assertEqual(xattr.list(dname, namespace=NAMESPACE), [])
214 tuples_equal(xattr.get_all(dname), [])
215 self.assertEqual(xattr.get_all(dname, namespace=NAMESPACE), [])
216 self.assertRaises(EnvironmentError, xattr.get, dname,
217 USER_NN, namespace=NAMESPACE)
218 _, sname = self._getsymlink()
219 lists_equal(xattr.list(sname, nofollow=True), [])
220 self.assertEqual(xattr.list(sname, nofollow=True,
221 namespace=NAMESPACE), [])
222 tuples_equal(xattr.get_all(sname, nofollow=True), [])
223 self.assertEqual(xattr.get_all(sname, nofollow=True,
224 namespace=NAMESPACE), [])
225 self.assertRaises(EnvironmentError, xattr.get, sname,
226 USER_NN, namespace=NAMESPACE, nofollow=True)
228 def testFileByNameDeprecated(self):
229 """test set and retrieve one attribute by file name (deprecated)"""
230 fh, fname = self._getfile()
231 self._checkDeprecated(fname)
234 def testFileByName(self):
235 """test set and retrieve one attribute by file name"""
236 fh, fname = self._getfile()
237 self._checkListSetGet(fname)
238 self._checkListSetGet(fname, use_ns=True)
241 def testFileByDescriptorDeprecated(self):
242 """test file descriptor operations (deprecated functions)"""
243 fh, fname = self._getfile()
244 self._checkDeprecated(fh)
247 def testFileByDescriptor(self):
248 """test file descriptor operations"""
249 fh, fname = self._getfile()
250 self._checkListSetGet(fh)
251 self._checkListSetGet(fh, use_ns=True)
254 def testFileByObjectDeprecated(self):
255 """test file descriptor operations (deprecated functions)"""
256 fh, fname = self._getfile()
258 self._checkDeprecated(fo)
261 def testFileByObject(self):
262 """test file descriptor operations"""
263 fh, fname = self._getfile()
265 self._checkListSetGet(fo)
266 self._checkListSetGet(fo, use_ns=True)
269 def testMixedAccessDeprecated(self):
270 """test mixed access to file (deprecated functions)"""
271 fh, fname = self._getfile()
273 lists_equal(xattr.listxattr(fname), [])
274 xattr.setxattr(fname, USER_ATTR, USER_VAL)
275 lists_equal(xattr.listxattr(fh), [USER_ATTR])
276 self.assertEqual(xattr.getxattr(fo, USER_ATTR), USER_VAL)
277 tuples_equal(xattr.get_all(fo), [(USER_ATTR, USER_VAL)])
278 tuples_equal(xattr.get_all(fname),
279 [(USER_ATTR, USER_VAL)])
282 def testMixedAccess(self):
283 """test mixed access to file"""
284 fh, fname = self._getfile()
286 lists_equal(xattr.list(fname), [])
287 xattr.set(fname, USER_ATTR, USER_VAL)
288 lists_equal(xattr.list(fh), [USER_ATTR])
289 self.assertEqual(xattr.list(fh, namespace=NAMESPACE), [USER_NN])
290 self.assertEqual(xattr.get(fo, USER_ATTR), USER_VAL)
291 self.assertEqual(xattr.get(fo, USER_NN, namespace=NAMESPACE),
293 tuples_equal(xattr.get_all(fo),
294 [(USER_ATTR, USER_VAL)])
295 self.assertEqual(xattr.get_all(fo, namespace=NAMESPACE),
296 [(USER_NN, USER_VAL)])
297 tuples_equal(xattr.get_all(fname),
298 [(USER_ATTR, USER_VAL)])
299 self.assertEqual(xattr.get_all(fname, namespace=NAMESPACE),
300 [(USER_NN, USER_VAL)])
303 def testDirOpsDeprecated(self):
304 """test attribute setting on directories (deprecated functions)"""
305 dname = self._getdir()
306 self._checkDeprecated(dname)
308 def testDirOps(self):
309 """test attribute setting on directories"""
310 dname = self._getdir()
311 self._checkListSetGet(dname)
312 self._checkListSetGet(dname, use_ns=True)
314 def testBinaryPayloadDeprecated(self):
315 """test binary values (deprecated functions)"""
316 fh, fname = self._getfile()
318 BINVAL = "abc" + '\0' + "def"
320 BINVAL = BINVAL.encode()
321 xattr.setxattr(fname, USER_ATTR, BINVAL)
322 lists_equal(xattr.listxattr(fname), [USER_ATTR])
323 self.assertEqual(xattr.getxattr(fname, USER_ATTR), BINVAL)
324 tuples_equal(xattr.get_all(fname), [(USER_ATTR, BINVAL)])
325 xattr.removexattr(fname, USER_ATTR)
327 def testBinaryPayload(self):
328 """test binary values"""
329 fh, fname = self._getfile()
331 BINVAL = "abc" + '\0' + "def"
333 BINVAL = BINVAL.encode()
334 xattr.set(fname, USER_ATTR, BINVAL)
335 lists_equal(xattr.list(fname), [USER_ATTR])
336 self.assertEqual(xattr.list(fname, namespace=NAMESPACE), [USER_NN])
337 self.assertEqual(xattr.get(fname, USER_ATTR), BINVAL)
338 self.assertEqual(xattr.get(fname, USER_NN,
339 namespace=NAMESPACE), BINVAL)
340 tuples_equal(xattr.get_all(fname), [(USER_ATTR, BINVAL)])
341 self.assertEqual(xattr.get_all(fname, namespace=NAMESPACE),
343 xattr.remove(fname, USER_ATTR)
345 def testManyOpsDeprecated(self):
346 """test many ops (deprecated functions)"""
347 fh, fname = self._getfile()
348 xattr.setxattr(fh, USER_ATTR, USER_VAL)
350 for i in range(MANYOPS_COUNT):
351 lists_equal(xattr.listxattr(fh), VL)
352 for i in range(MANYOPS_COUNT):
353 self.assertEqual(xattr.getxattr(fh, USER_ATTR), USER_VAL)
354 for i in range(MANYOPS_COUNT):
355 tuples_equal(xattr.get_all(fh),
356 [(USER_ATTR, USER_VAL)])
358 def testManyOps(self):
360 fh, fname = self._getfile()
361 xattr.set(fh, USER_ATTR, USER_VAL)
364 for i in range(MANYOPS_COUNT):
365 lists_equal(xattr.list(fh), VL)
366 lists_equal(xattr.list(fh, namespace=EMPTY_NS), VL)
367 self.assertEqual(xattr.list(fh, namespace=NAMESPACE), VN)
368 for i in range(MANYOPS_COUNT):
369 self.assertEqual(xattr.get(fh, USER_ATTR), USER_VAL)
370 self.assertEqual(xattr.get(fh, USER_NN, namespace=NAMESPACE),
372 for i in range(MANYOPS_COUNT):
373 tuples_equal(xattr.get_all(fh),
374 [(USER_ATTR, USER_VAL)])
375 self.assertEqual(xattr.get_all(fh, namespace=NAMESPACE),
376 [(USER_NN, USER_VAL)])
378 def testNoneNamespace(self):
379 fh, fname = self._getfile()
380 self.assertRaises(TypeError, xattr.get, fh, USER_ATTR,
383 def testEmptyValue(self):
384 fh, fname = self._getfile()
385 xattr.set(fh, USER_ATTR, EMPTY_VAL)
386 self.assertEqual(xattr.get(fh, USER_ATTR), EMPTY_VAL)
388 def testWrongCall(self):
389 for call in [xattr.get,
390 xattr.list, xattr.listxattr,
391 xattr.remove, xattr.removexattr,
392 xattr.set, xattr.setxattr,
393 xattr.get, xattr.getxattr]:
394 self.assertRaises(TypeError, call)
396 def testWrongType(self):
397 self.assertRaises(TypeError, xattr.get, object(), USER_ATTR)
398 for call in [xattr.listxattr, xattr.list]:
399 self.assertRaises(TypeError, call, object())
400 for call in [xattr.remove, xattr.removexattr,
401 xattr.get, xattr.getxattr]:
402 self.assertRaises(TypeError, call, object(), USER_ATTR)
403 for call in [xattr.set, xattr.setxattr]:
404 self.assertRaises(TypeError, call, object(), USER_ATTR, USER_VAL)
407 def testLargeAttribute(self):
408 fh, fname = self._getfile()
410 xattr.set(fh, USER_ATTR, LARGE_VAL)
411 self.assertEqual(xattr.get(fh, USER_ATTR), LARGE_VAL)
414 if __name__ == "__main__":