From e2224bca2e936daf0d7649540f4eaaf19c53c2bb Mon Sep 17 00:00:00 2001 From: Iustin Pop Date: Mon, 25 Nov 2019 04:22:15 +0100 Subject: [PATCH] Convert test suite to pytest Much more parametrisation, which means: - more test cases covered (testing more/all object types in most functions) - more granular tests, which should help diagnose of failures --- .travis.yml | 13 +- Makefile | 10 +- test/test_xattr.py | 643 +++++++++++++++++++++------------------------ 3 files changed, 316 insertions(+), 350 deletions(-) diff --git a/.travis.yml b/.travis.yml index df6c50d..463cf4c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,8 @@ language: python +# enable caching of installed packages. +cache: pip + # let's test as many versions as we can! python: - "3.4" @@ -19,13 +22,17 @@ matrix: python: # install coverage helper: -install: gem install coveralls-lcov +install: + - gem install coveralls-lcov + - pip install pytest # the test command: script: - - python ./setup.py test + - python ./setup.py build_ext -i + - python -m pytest test - make clean - - CFLAGS="-coverage" python ./setup.py test + - CFLAGS="-coverage" python ./setup.py build_ext -i + - python -m pytest test # install lcov, platform-specific but clean: addons: diff --git a/Makefile b/Makefile index e8e685a..78e6818 100644 --- a/Makefile +++ b/Makefile @@ -47,13 +47,15 @@ test: for flavour in "" "-dbg"; do \ if type python$$ver$$flavour >/dev/null; then \ echo Testing with python$$ver$$flavour; \ - python$$ver$$flavour ./setup.py test -q; \ + python$$ver$$flavour setup.py build_ext -i; \ + python$$ver$$flavour -m pytest test; \ fi; \ done; \ done; - @if type pypy >/dev/null; then \ - echo Testing with pypy; \ - pypy ./setup.py test -q; \ + @if type pypy3 >/dev/null; then \ + echo Testing with pypy3; \ + pypy3 setup.py build_ext -i; \ + pypy3 -m pytest test; \ fi benchmark: $(MODNAME) diff --git a/test/test_xattr.py b/test/test_xattr.py index b477aa2..9dca8ac 100644 --- a/test/test_xattr.py +++ b/test/test_xattr.py @@ -2,10 +2,10 @@ # import sys -import unittest import tempfile import os import errno +import pytest import xattr from xattr import NS_USER, XATTR_CREATE, XATTR_REPLACE @@ -43,6 +43,8 @@ if PY3K: EMPTY_VAL = EMPTY_VAL.encode() LARGE_VAL = LARGE_VAL.encode() +# Helper functions + def ignore_tuples(attrs): """Remove ignored attributes from the output of xattr.get_all.""" return [attr for attr in attrs @@ -61,355 +63,310 @@ def tuples_equal(attrs, value): """Helper to check list equivalence, skipping TEST_IGNORE_XATTRS.""" assert ignore_tuples(attrs) == value - -class xattrTest(unittest.TestCase): - def setUp(self): - """set up function""" - self.rmfiles = [] - self.rmdirs = [] - - def tearDown(self): - """tear down function""" - for fname in self.rmfiles: - try: - os.unlink(fname) - except EnvironmentError: - continue - for dname in self.rmdirs: - try: - os.rmdir(dname) - except EnvironmentError: - continue - - def _getfile(self): - """create a temp file""" - fh, fname = tempfile.mkstemp(".test", "xattr-", TEST_DIR) - self.rmfiles.append(fname) - return fh, fname - - def _getdir(self): - """create a temp dir""" - dname = tempfile.mkdtemp(".test", "xattr-", TEST_DIR) - self.rmdirs.append(dname) - return dname - - def _getsymlink(self, dangling=True): - """create a symlink""" - fh, fname = self._getfile() - os.close(fh) - if dangling: - os.unlink(fname) - sname = fname + ".symlink" - os.symlink(fname, sname) - self.rmfiles.append(sname) - return fname, sname - - def _checkDeprecated(self, item, symlink=False): - """check deprecated list, set, get operations against an item""" - lists_equal(xattr.listxattr(item, symlink), []) - self.assertRaises(EnvironmentError, xattr.setxattr, item, - USER_ATTR, USER_VAL, - XATTR_REPLACE, symlink) - xattr.setxattr(item, USER_ATTR, USER_VAL, 0, symlink) - self.assertRaises(EnvironmentError, xattr.setxattr, item, - USER_ATTR, USER_VAL, XATTR_CREATE, symlink) - lists_equal(xattr.listxattr(item, symlink), [USER_ATTR]) - self.assertEqual(xattr.getxattr(item, USER_ATTR, symlink), - USER_VAL) - tuples_equal(xattr.get_all(item, nofollow=symlink), - [(USER_ATTR, USER_VAL)]) - xattr.removexattr(item, USER_ATTR, symlink) - lists_equal(xattr.listxattr(item, symlink), []) - tuples_equal(xattr.get_all(item, nofollow=symlink), - []) - self.assertRaises(EnvironmentError, xattr.removexattr, - item, USER_ATTR, symlink) - - def _checkListSetGet(self, item, symlink=False, use_ns=False): - """check list, set, get operations against an item""" - lists_equal(xattr.list(item, symlink), []) - self.assertRaises(EnvironmentError, xattr.set, item, - USER_ATTR, USER_VAL, - flags=XATTR_REPLACE, - nofollow=symlink) - self.assertRaises(EnvironmentError, xattr.set, item, - USER_NN, USER_VAL, - flags=XATTR_REPLACE, - namespace=NAMESPACE, - nofollow=symlink) - if use_ns: - xattr.set(item, USER_NN, USER_VAL, - namespace=NAMESPACE, - nofollow=symlink) - else: - xattr.set(item, USER_ATTR, USER_VAL, - nofollow=symlink) - self.assertRaises(EnvironmentError, xattr.set, item, - USER_ATTR, USER_VAL, - flags=XATTR_CREATE, - nofollow=symlink) - self.assertRaises(EnvironmentError, xattr.set, item, - USER_NN, USER_VAL, - flags=XATTR_CREATE, - namespace=NAMESPACE, - nofollow=symlink) - lists_equal(xattr.list(item, nofollow=symlink), [USER_ATTR]) - lists_equal(xattr.list(item, nofollow=symlink, - namespace=EMPTY_NS), - [USER_ATTR]) - self.assertEqual(xattr.list(item, namespace=NAMESPACE, nofollow=symlink), - [USER_NN]) - self.assertEqual(xattr.get(item, USER_ATTR, nofollow=symlink), - USER_VAL) - self.assertEqual(xattr.get(item, USER_NN, nofollow=symlink, - namespace=NAMESPACE), USER_VAL) - tuples_equal(xattr.get_all(item, nofollow=symlink), - [(USER_ATTR, USER_VAL)]) - self.assertEqual(xattr.get_all(item, nofollow=symlink, - namespace=NAMESPACE), - [(USER_NN, USER_VAL)]) - if use_ns: - xattr.remove(item, USER_NN, namespace=NAMESPACE, nofollow=symlink) - else: - xattr.remove(item, USER_ATTR, nofollow=symlink) - lists_equal(xattr.list(item, nofollow=symlink), []) - tuples_equal(xattr.get_all(item, nofollow=symlink), - []) - self.assertRaises(EnvironmentError, xattr.remove, - item, USER_ATTR, nofollow=symlink) - self.assertRaises(EnvironmentError, xattr.remove, item, - USER_NN, namespace=NAMESPACE, nofollow=symlink) - - def testNoXattrDeprecated(self): - """test no attributes (deprecated functions)""" - fh, fname = self._getfile() - lists_equal(xattr.listxattr(fname), []) - tuples_equal(xattr.get_all(fname), []) - self.assertRaises(EnvironmentError, xattr.getxattr, fname, - USER_ATTR) - dname = self._getdir() - lists_equal(xattr.listxattr(dname), []) - tuples_equal(xattr.get_all(dname), []) - self.assertRaises(EnvironmentError, xattr.getxattr, dname, - USER_ATTR) - _, sname = self._getsymlink() - lists_equal(xattr.listxattr(sname, True), []) - tuples_equal(xattr.get_all(sname, nofollow=True), []) - self.assertRaises(EnvironmentError, xattr.getxattr, fname, - USER_ATTR, True) - - - def testNoXattr(self): - """test no attributes""" - fh, fname = self._getfile() - lists_equal(xattr.list(fname), []) - self.assertEqual(xattr.list(fname, namespace=NAMESPACE), []) - tuples_equal(xattr.get_all(fname), []) - self.assertEqual(xattr.get_all(fname, namespace=NAMESPACE), []) - self.assertRaises(EnvironmentError, xattr.get, fname, - USER_NN, namespace=NAMESPACE) - dname = self._getdir() - lists_equal(xattr.list(dname), []) - self.assertEqual(xattr.list(dname, namespace=NAMESPACE), []) - tuples_equal(xattr.get_all(dname), []) - self.assertEqual(xattr.get_all(dname, namespace=NAMESPACE), []) - self.assertRaises(EnvironmentError, xattr.get, dname, - USER_NN, namespace=NAMESPACE) - _, sname = self._getsymlink() - lists_equal(xattr.list(sname, nofollow=True), []) - self.assertEqual(xattr.list(sname, nofollow=True, - namespace=NAMESPACE), []) - tuples_equal(xattr.get_all(sname, nofollow=True), []) - self.assertEqual(xattr.get_all(sname, nofollow=True, - namespace=NAMESPACE), []) - self.assertRaises(EnvironmentError, xattr.get, sname, - USER_NN, namespace=NAMESPACE, nofollow=True) - - def testFileByNameDeprecated(self): - """test set and retrieve one attribute by file name (deprecated)""" - fh, fname = self._getfile() - self._checkDeprecated(fname) - os.close(fh) - - def testFileByName(self): - """test set and retrieve one attribute by file name""" - fh, fname = self._getfile() - self._checkListSetGet(fname) - self._checkListSetGet(fname, use_ns=True) - os.close(fh) - - def testFileByDescriptorDeprecated(self): - """test file descriptor operations (deprecated functions)""" - fh, fname = self._getfile() - self._checkDeprecated(fh) - os.close(fh) - - def testFileByDescriptor(self): - """test file descriptor operations""" - fh, fname = self._getfile() - self._checkListSetGet(fh) - self._checkListSetGet(fh, use_ns=True) - os.close(fh) - - def testFileByObjectDeprecated(self): - """test file descriptor operations (deprecated functions)""" - fh, fname = self._getfile() - fo = os.fdopen(fh) - self._checkDeprecated(fo) - fo.close() - - def testFileByObject(self): - """test file descriptor operations""" - fh, fname = self._getfile() - fo = os.fdopen(fh) - self._checkListSetGet(fo) - self._checkListSetGet(fo, use_ns=True) - fo.close() - - def testMixedAccessDeprecated(self): - """test mixed access to file (deprecated functions)""" - fh, fname = self._getfile() - fo = os.fdopen(fh) +# Fixtures and helpers + +@pytest.fixture +def testdir(): + """per-test temp dir based in TEST_DIR""" + with tempfile.TemporaryDirectory(dir=TEST_DIR) as dname: + yield dname + +def get_file(path): + fh, fname = tempfile.mkstemp(".test", "xattr-", path) + return fh, fname + +def get_file_name(path): + fh, fname = get_file(path) + os.close(fh) + return fname + +def get_file_fd(path): + return get_file(path)[0] + +def get_file_object(path): + fd = get_file(path)[0] + return os.fdopen(fd) + +def get_dir(path): + return tempfile.mkdtemp(".test", "xattr-", path) + +def get_symlink(path, dangling=True): + """create a symlink""" + fh, fname = get_file(path) + os.close(fh) + if dangling: + os.unlink(fname) + sname = fname + ".symlink" + os.symlink(fname, sname) + return fname, sname + +def get_valid_symlink(path): + return get_symlink(path, dangling=False)[1] + +def get_dangling_symlink(path): + return get_symlink(path, dangling=True)[1] + +# Note: user attributes are only allowed on files and directories, so +# we have to skip the symlinks here. See xattr(7). +ITEMS_P = [ + (get_file_name, False), + (get_file_fd, False), + (get_file_object, False), + (get_dir, False), + (get_valid_symlink, False), +# (get_valid_symlink, True), +# (get_dangling_symlink, True), +] + +ITEMS_D = [ + "file name", + "file FD", + "file object", + "directory", + "file via symlink", +# "valid symlink", +# "dangling symlink", +] + +@pytest.fixture(params=ITEMS_P, ids=ITEMS_D) +def subject(testdir, request): + return request.param[0](testdir), request.param[1] + +@pytest.fixture(params=[True, False], ids=["with namespace", "no namespace"]) +def use_ns(request): + return request.param + +@pytest.fixture(params=[True, False], ids=["dangling", "valid"]) +def use_dangling(request): + return request.param + +### Test functions + +def test_empty_value(subject): + item, nofollow = subject + xattr.set(item, USER_ATTR, EMPTY_VAL, nofollow=nofollow) + assert xattr.get(item, USER_ATTR, nofollow=nofollow) == EMPTY_VAL + +def test_large_value(subject): + item, nofollow = subject + xattr.set(item, USER_ATTR, LARGE_VAL) + assert xattr.get(item, USER_ATTR, nofollow=nofollow) == LARGE_VAL + + +def test_file_mixed_access_deprecated(testdir): + """test mixed access to file (deprecated functions)""" + fh, fname = get_file(testdir) + with os.fdopen(fh) as fo: lists_equal(xattr.listxattr(fname), []) xattr.setxattr(fname, USER_ATTR, USER_VAL) lists_equal(xattr.listxattr(fh), [USER_ATTR]) - self.assertEqual(xattr.getxattr(fo, USER_ATTR), USER_VAL) + assert xattr.getxattr(fo, USER_ATTR) == USER_VAL tuples_equal(xattr.get_all(fo), [(USER_ATTR, USER_VAL)]) tuples_equal(xattr.get_all(fname), - [(USER_ATTR, USER_VAL)]) - fo.close() + [(USER_ATTR, USER_VAL)]) - def testMixedAccess(self): - """test mixed access to file""" - fh, fname = self._getfile() - fo = os.fdopen(fh) +def test_file_mixed_access(testdir): + """test mixed access to file""" + fh, fname = get_file(testdir) + with os.fdopen(fh) as fo: lists_equal(xattr.list(fname), []) xattr.set(fname, USER_ATTR, USER_VAL) lists_equal(xattr.list(fh), [USER_ATTR]) - self.assertEqual(xattr.list(fh, namespace=NAMESPACE), [USER_NN]) - self.assertEqual(xattr.get(fo, USER_ATTR), USER_VAL) - self.assertEqual(xattr.get(fo, USER_NN, namespace=NAMESPACE), - USER_VAL) + assert xattr.list(fh, namespace=NAMESPACE) == [USER_NN] + assert xattr.get(fo, USER_ATTR) == USER_VAL + assert xattr.get(fo, USER_NN, namespace=NAMESPACE) == USER_VAL tuples_equal(xattr.get_all(fo), - [(USER_ATTR, USER_VAL)]) - self.assertEqual(xattr.get_all(fo, namespace=NAMESPACE), - [(USER_NN, USER_VAL)]) - tuples_equal(xattr.get_all(fname), - [(USER_ATTR, USER_VAL)]) - self.assertEqual(xattr.get_all(fname, namespace=NAMESPACE), - [(USER_NN, USER_VAL)]) - fo.close() - - def testDirOpsDeprecated(self): - """test attribute setting on directories (deprecated functions)""" - dname = self._getdir() - self._checkDeprecated(dname) - - def testDirOps(self): - """test attribute setting on directories""" - dname = self._getdir() - self._checkListSetGet(dname) - self._checkListSetGet(dname, use_ns=True) - - def testBinaryPayloadDeprecated(self): - """test binary values (deprecated functions)""" - fh, fname = self._getfile() - os.close(fh) - BINVAL = "abc" + '\0' + "def" - if PY3K: - BINVAL = BINVAL.encode() - xattr.setxattr(fname, USER_ATTR, BINVAL) - lists_equal(xattr.listxattr(fname), [USER_ATTR]) - self.assertEqual(xattr.getxattr(fname, USER_ATTR), BINVAL) - tuples_equal(xattr.get_all(fname), [(USER_ATTR, BINVAL)]) - xattr.removexattr(fname, USER_ATTR) - - def testBinaryPayload(self): - """test binary values""" - fh, fname = self._getfile() - os.close(fh) - BINVAL = "abc" + '\0' + "def" - if PY3K: - BINVAL = BINVAL.encode() - xattr.set(fname, USER_ATTR, BINVAL) - lists_equal(xattr.list(fname), [USER_ATTR]) - self.assertEqual(xattr.list(fname, namespace=NAMESPACE), [USER_NN]) - self.assertEqual(xattr.get(fname, USER_ATTR), BINVAL) - self.assertEqual(xattr.get(fname, USER_NN, - namespace=NAMESPACE), BINVAL) - tuples_equal(xattr.get_all(fname), [(USER_ATTR, BINVAL)]) - self.assertEqual(xattr.get_all(fname, namespace=NAMESPACE), - [(USER_NN, BINVAL)]) - xattr.remove(fname, USER_ATTR) - - def testManyOpsDeprecated(self): - """test many ops (deprecated functions)""" - fh, fname = self._getfile() - xattr.setxattr(fh, USER_ATTR, USER_VAL) - VL = [USER_ATTR] - for i in range(MANYOPS_COUNT): - lists_equal(xattr.listxattr(fh), VL) - for i in range(MANYOPS_COUNT): - self.assertEqual(xattr.getxattr(fh, USER_ATTR), USER_VAL) - for i in range(MANYOPS_COUNT): - tuples_equal(xattr.get_all(fh), - [(USER_ATTR, USER_VAL)]) - - def testManyOps(self): - """test many ops""" - fh, fname = self._getfile() - xattr.set(fh, USER_ATTR, USER_VAL) - VL = [USER_ATTR] - VN = [USER_NN] - for i in range(MANYOPS_COUNT): - lists_equal(xattr.list(fh), VL) - lists_equal(xattr.list(fh, namespace=EMPTY_NS), VL) - self.assertEqual(xattr.list(fh, namespace=NAMESPACE), VN) - for i in range(MANYOPS_COUNT): - self.assertEqual(xattr.get(fh, USER_ATTR), USER_VAL) - self.assertEqual(xattr.get(fh, USER_NN, namespace=NAMESPACE), - USER_VAL) - for i in range(MANYOPS_COUNT): - tuples_equal(xattr.get_all(fh), - [(USER_ATTR, USER_VAL)]) - self.assertEqual(xattr.get_all(fh, namespace=NAMESPACE), - [(USER_NN, USER_VAL)]) - - def testNoneNamespace(self): - fh, fname = self._getfile() - self.assertRaises(TypeError, xattr.get, fh, USER_ATTR, - namespace=None) - - def testEmptyValue(self): - fh, fname = self._getfile() - xattr.set(fh, USER_ATTR, EMPTY_VAL) - self.assertEqual(xattr.get(fh, USER_ATTR), EMPTY_VAL) - - def testWrongCall(self): - for call in [xattr.get, - xattr.list, xattr.listxattr, - xattr.remove, xattr.removexattr, - xattr.set, xattr.setxattr, - xattr.get, xattr.getxattr]: - self.assertRaises(TypeError, call) - - def testWrongType(self): - self.assertRaises(TypeError, xattr.get, object(), USER_ATTR) - for call in [xattr.listxattr, xattr.list]: - self.assertRaises(TypeError, call, object()) - for call in [xattr.remove, xattr.removexattr, - xattr.get, xattr.getxattr]: - self.assertRaises(TypeError, call, object(), USER_ATTR) - for call in [xattr.set, xattr.setxattr]: - self.assertRaises(TypeError, call, object(), USER_ATTR, USER_VAL) - - - def testLargeAttribute(self): - fh, fname = self._getfile() - - xattr.set(fh, USER_ATTR, LARGE_VAL) - self.assertEqual(xattr.get(fh, USER_ATTR), LARGE_VAL) - - -if __name__ == "__main__": - unittest.main() + [(USER_ATTR, USER_VAL)]) + assert xattr.get_all(fo, namespace=NAMESPACE) == \ + [(USER_NN, USER_VAL)] + tuples_equal(xattr.get_all(fname), [(USER_ATTR, USER_VAL)]) + assert xattr.get_all(fname, namespace=NAMESPACE) == \ + [(USER_NN, USER_VAL)] + +def test_ListSetGet(subject, use_ns): + """check list, set, get operations against an item""" + item = subject[0] + lists_equal(xattr.list(item), []) + with pytest.raises(EnvironmentError): + if use_ns: + xattr.set(item, USER_NN, USER_VAL, flags=XATTR_REPLACE, + namespace=NAMESPACE) + else: + xattr.set(item, USER_ATTR, USER_VAL, flags=XATTR_REPLACE) + if use_ns: + xattr.set(item, USER_NN, USER_VAL, + namespace=NAMESPACE) + else: + xattr.set(item, USER_ATTR, USER_VAL) + with pytest.raises(EnvironmentError): + if use_ns: + xattr.set(item, USER_NN, USER_VAL, + flags=XATTR_CREATE, namespace=NAMESPACE) + else: + xattr.set(item, USER_ATTR, USER_VAL, flags=XATTR_CREATE) + if use_ns: + assert xattr.list(item, namespace=NAMESPACE) == [USER_NN] + else: + lists_equal(xattr.list(item), [USER_ATTR]) + lists_equal(xattr.list(item, namespace=EMPTY_NS), + [USER_ATTR]) + if use_ns: + assert xattr.get(item, USER_NN, namespace=NAMESPACE) == USER_VAL + else: + assert xattr.get(item, USER_ATTR) == USER_VAL + if use_ns: + assert xattr.get_all(item, namespace=NAMESPACE) == \ + [(USER_NN, USER_VAL)] + else: + tuples_equal(xattr.get_all(item), + [(USER_ATTR, USER_VAL)]) + if use_ns: + xattr.remove(item, USER_NN, namespace=NAMESPACE) + else: + xattr.remove(item, USER_ATTR) + lists_equal(xattr.list(item), []) + tuples_equal(xattr.get_all(item), []) + with pytest.raises(EnvironmentError): + if use_ns: + xattr.remove(item, USER_NN, namespace=NAMESPACE) + else: + xattr.remove(item, USER_ATTR) + +def test_ListSetGetDeprecated(subject): + """check deprecated list, set, get operations against an item""" + item = subject[0] + lists_equal(xattr.listxattr(item), []) + with pytest.raises(EnvironmentError): + xattr.setxattr(item, USER_ATTR, USER_VAL, XATTR_REPLACE) + xattr.setxattr(item, USER_ATTR, USER_VAL, 0) + with pytest.raises(EnvironmentError): + xattr.setxattr(item, USER_ATTR, USER_VAL, XATTR_CREATE) + lists_equal(xattr.listxattr(item), [USER_ATTR]) + assert xattr.getxattr(item, USER_ATTR) == USER_VAL + tuples_equal(xattr.get_all(item), [(USER_ATTR, USER_VAL)]) + xattr.removexattr(item, USER_ATTR) + lists_equal(xattr.listxattr(item), []) + tuples_equal(xattr.get_all(item), []) + with pytest.raises(EnvironmentError): + xattr.removexattr(item, USER_ATTR) + +def test_many_ops(subject): + """test many ops""" + item = subject[0] + xattr.set(item, USER_ATTR, USER_VAL) + VL = [USER_ATTR] + VN = [USER_NN] + for i in range(MANYOPS_COUNT): + lists_equal(xattr.list(item), VL) + lists_equal(xattr.list(item, namespace=EMPTY_NS), VL) + assert xattr.list(item, namespace=NAMESPACE) == VN + for i in range(MANYOPS_COUNT): + assert xattr.get(item, USER_ATTR) == USER_VAL + assert xattr.get(item, USER_NN, namespace=NAMESPACE) == USER_VAL + for i in range(MANYOPS_COUNT): + tuples_equal(xattr.get_all(item), + [(USER_ATTR, USER_VAL)]) + assert xattr.get_all(item, namespace=NAMESPACE) == \ + [(USER_NN, USER_VAL)] + +def test_many_ops_deprecated(subject): + """test many ops (deprecated functions)""" + item = subject[0] + xattr.setxattr(item, USER_ATTR, USER_VAL) + VL = [USER_ATTR] + for i in range(MANYOPS_COUNT): + lists_equal(xattr.listxattr(item), VL) + for i in range(MANYOPS_COUNT): + assert xattr.getxattr(item, USER_ATTR) == USER_VAL + for i in range(MANYOPS_COUNT): + tuples_equal(xattr.get_all(item), + [(USER_ATTR, USER_VAL)]) + +def test_no_attributes_deprecated(subject): + """test no attributes (deprecated functions)""" + item = subject[0] + lists_equal(xattr.listxattr(item), []) + tuples_equal(xattr.get_all(item), []) + with pytest.raises(EnvironmentError): + xattr.getxattr(item, USER_ATTR) + +def test_no_attributes_deprecated_symlinks(testdir, use_dangling): + """test no attributes on symlinks (deprecated functions)""" + _, sname = get_symlink(testdir, dangling=use_dangling) + lists_equal(xattr.listxattr(sname, True), []) + tuples_equal(xattr.get_all(sname, nofollow=True), []) + with pytest.raises(EnvironmentError): + xattr.getxattr(sname, USER_ATTR, True) + +def test_no_attributes(subject): + """test no attributes""" + item = subject[0] + lists_equal(xattr.list(item), []) + assert xattr.list(item, namespace=NAMESPACE) == [] + tuples_equal(xattr.get_all(item), []) + assert xattr.get_all(item, namespace=NAMESPACE) == [] + with pytest.raises(EnvironmentError): + xattr.get(item, USER_NN, namespace=NAMESPACE) + +def test_no_attributes_symlinks(testdir, use_dangling): + """test no attributes on symlinks""" + _, sname = get_symlink(testdir, dangling=use_dangling) + lists_equal(xattr.list(sname, nofollow=True), []) + assert xattr.list(sname, nofollow=True, + namespace=NAMESPACE) == [] + tuples_equal(xattr.get_all(sname, nofollow=True), []) + assert xattr.get_all(sname, nofollow=True, + namespace=NAMESPACE) == [] + with pytest.raises(EnvironmentError): + xattr.get(sname, USER_NN, namespace=NAMESPACE, nofollow=True) + +def test_binary_payload_deprecated(subject): + """test binary values (deprecated functions)""" + item = subject[0] + BINVAL = b"abc\0def" + xattr.setxattr(item, USER_ATTR, BINVAL) + lists_equal(xattr.listxattr(item), [USER_ATTR]) + assert xattr.getxattr(item, USER_ATTR) == BINVAL + tuples_equal(xattr.get_all(item), [(USER_ATTR, BINVAL)]) + xattr.removexattr(item, USER_ATTR) + +def test_binary_payload(subject): + """test binary values""" + item = subject[0] + BINVAL = b"abc\0def" + xattr.set(item, USER_ATTR, BINVAL) + lists_equal(xattr.list(item), [USER_ATTR]) + assert xattr.list(item, namespace=NAMESPACE) == [USER_NN] + assert xattr.get(item, USER_ATTR) == BINVAL + assert xattr.get(item, USER_NN, namespace=NAMESPACE) == BINVAL + tuples_equal(xattr.get_all(item), [(USER_ATTR, BINVAL)]) + assert xattr.get_all(item, namespace=NAMESPACE) == [(USER_NN, BINVAL)] + xattr.remove(item, USER_ATTR) + +def test_none_namespace(subject): + with pytest.raises(TypeError): + xattr.get(subject[0], USER_ATTR, namespace=None) + +@pytest.mark.parametrize( + "call", + [xattr.get, xattr.list, xattr.listxattr, + xattr.remove, xattr.removexattr, + xattr.set, xattr.setxattr, + xattr.get, xattr.getxattr]) +def test_wrong_call(call): + with pytest.raises(TypeError): + call() + +@pytest.mark.parametrize( + "call, args", [(xattr.get, [USER_ATTR]), + (xattr.listxattr, []), + (xattr.list, []), + (xattr.remove, [USER_ATTR]), + (xattr.removexattr, [USER_ATTR]), + (xattr.get, [USER_ATTR]), + (xattr.getxattr, [USER_ATTR]), + (xattr.set, [USER_ATTR, USER_VAL]), + (xattr.setxattr, [USER_ATTR, USER_VAL])]) +def test_wrong_argument_type(call, args): + with pytest.raises(TypeError): + call(object(), *args) -- 2.39.2