Blame SOURCES/0003-gating-tests-changes.patch

b3f87c
From 3a513b4d7f14406d94614643327ce2d8ab35f7eb Mon Sep 17 00:00:00 2001
b3f87c
From: Vojtech Trefny <vtrefny@redhat.com>
b3f87c
Date: Thu, 14 Mar 2019 09:34:02 +0100
b3f87c
Subject: [PATCH 01/10] Add a decorator for "tagging" tests
b3f87c
b3f87c
Tests function (or classes) can be tagged with one or more tags.
b3f87c
This provides easier way to skip slow/unstable/dangerous tests
b3f87c
and/or or some subset of the tests (e.g. run only unstable tests
b3f87c
to check if the test is still failing).
b3f87c
---
b3f87c
 tests/utils.py | 26 ++++++++++++++++++++++++++
b3f87c
 1 file changed, 26 insertions(+)
b3f87c
b3f87c
diff --git a/tests/utils.py b/tests/utils.py
b3f87c
index a9eb430..82b5494 100644
b3f87c
--- a/tests/utils.py
b3f87c
+++ b/tests/utils.py
b3f87c
@@ -10,6 +10,7 @@ import unittest
b3f87c
 import time
b3f87c
 import sys
b3f87c
 from contextlib import contextmanager
b3f87c
+from enum import Enum
b3f87c
 from itertools import chain
b3f87c
 
b3f87c
 from gi.repository import GLib
b3f87c
@@ -342,6 +343,31 @@ def unstable_test(test):
b3f87c
     return decorated_test
b3f87c
 
b3f87c
 
b3f87c
+class TestTags(Enum):
b3f87c
+    SLOW = 1        # slow tests
b3f87c
+    UNSTABLE = 2    # randomly failing tests
b3f87c
+    UNSAFE = 3      # tests that change system configuration
b3f87c
+    CORE = 4        # tests covering core functionality
b3f87c
+    NOSTORAGE = 5   # tests that don't work with storage
b3f87c
+    EXTRADEPS = 6   # tests that require special configuration and/or device to run
b3f87c
+    REGRESSION = 7  # regression tests
b3f87c
+
b3f87c
+
b3f87c
+def tag_test(*tags):
b3f87c
+    def decorator(func):
b3f87c
+        func.slow = TestTags.SLOW in tags
b3f87c
+        func.unstable = TestTags.UNSTABLE in tags
b3f87c
+        func.unsafe = TestTags.UNSAFE in tags
b3f87c
+        func.core = TestTags.CORE in tags
b3f87c
+        func.nostorage = TestTags.NOSTORAGE in tags
b3f87c
+        func.extradeps = TestTags.EXTRADEPS in tags
b3f87c
+        func.regression = TestTags.REGRESSION in tags
b3f87c
+
b3f87c
+        return func
b3f87c
+
b3f87c
+    return decorator
b3f87c
+
b3f87c
+
b3f87c
 def run(cmd_string):
b3f87c
     """
b3f87c
     Run the a command with file descriptors closed as lvm is trying to
b3f87c
-- 
b3f87c
2.20.1
b3f87c
b3f87c
b3f87c
From f3648fed9c98e779c9f265262a4a77a905689fe7 Mon Sep 17 00:00:00 2001
b3f87c
From: Vojtech Trefny <vtrefny@redhat.com>
b3f87c
Date: Thu, 14 Mar 2019 09:37:18 +0100
b3f87c
Subject: [PATCH 02/10] Use test tags for skipping tests
b3f87c
b3f87c
This loads all individual test functions from the suite and checks
b3f87c
the tags to decide whether the test should be skippend or not.
b3f87c
We are abusing some unittest internal API to do this, but all
b3f87c
private functions works with Python 2 and Python 3 and general
b3f87c
looks like "stable enough" API.
b3f87c
---
b3f87c
 tests/run_tests.py | 130 ++++++++++++++++++++++++++++++++++++++++++---
b3f87c
 1 file changed, 124 insertions(+), 6 deletions(-)
b3f87c
b3f87c
diff --git a/tests/run_tests.py b/tests/run_tests.py
b3f87c
index 6f74430..5301d07 100644
b3f87c
--- a/tests/run_tests.py
b3f87c
+++ b/tests/run_tests.py
b3f87c
@@ -16,6 +16,82 @@ LIBDIRS = 'src/utils/.libs:src/plugins/.libs:src/plugins/fs/.libs:src/lib/.libs'
b3f87c
 GIDIR = 'src/lib'
b3f87c
 
b3f87c
 
b3f87c
+def _get_tests_from_suite(suite, tests):
b3f87c
+    """ Extract tests from the test suite """
b3f87c
+    # 'tests' we get from 'unittest.defaultTestLoader.discover' are "wrapped"
b3f87c
+    # in multiple 'unittest.suite.TestSuite' classes/lists so we need to "unpack"
b3f87c
+    # the indivudual test cases
b3f87c
+    for test in suite:
b3f87c
+        if isinstance(test, unittest.suite.TestSuite):
b3f87c
+            _get_tests_from_suite(test, tests)
b3f87c
+
b3f87c
+        if isinstance(test, unittest.TestCase):
b3f87c
+            tests.append(test)
b3f87c
+
b3f87c
+    return tests
b3f87c
+
b3f87c
+
b3f87c
+def _get_test_tags(test):
b3f87c
+    """ Get test tags for single test case """
b3f87c
+
b3f87c
+    tags = []
b3f87c
+
b3f87c
+    # test failed to load, usually some ImportError or something really broken
b3f87c
+    # in the test file, just return empty list and let it fail
b3f87c
+    # with python2 the loader will raise an exception directly without returning
b3f87c
+    # a "fake" FailedTest test case
b3f87c
+    if six.PY3 and isinstance(test, unittest.loader._FailedTest):
b3f87c
+        return tags
b3f87c
+
b3f87c
+    test_fn = getattr(test, test._testMethodName)
b3f87c
+
b3f87c
+    # it is possible to either tag a test funcion or the class so we need to
b3f87c
+    # check both for the tag
b3f87c
+    if getattr(test_fn, "slow", False) or getattr(test_fn.__self__, "slow", False):
b3f87c
+        tags.append(TestTags.SLOW)
b3f87c
+    if getattr(test_fn, "unstable", False) or getattr(test_fn.__self__, "unstable", False):
b3f87c
+        tags.append(TestTags.UNSTABLE)
b3f87c
+    if getattr(test_fn, "unsafe", False) or getattr(test_fn.__self__, "unsafe", False):
b3f87c
+        tags.append(TestTags.UNSAFE)
b3f87c
+    if getattr(test_fn, "core", False) or getattr(test_fn.__self__, "core", False):
b3f87c
+        tags.append(TestTags.CORE)
b3f87c
+    if getattr(test_fn, "nostorage", False) or getattr(test_fn.__self__, "nostorage", False):
b3f87c
+        tags.append(TestTags.NOSTORAGE)
b3f87c
+    if getattr(test_fn, "extradeps", False) or getattr(test_fn.__self__, "extradeps", False):
b3f87c
+        tags.append(TestTags.EXTRADEPS)
b3f87c
+    if getattr(test_fn, "regression", False) or getattr(test_fn.__self__, "regression", False):
b3f87c
+        tags.append(TestTags.REGRESSION)
b3f87c
+
b3f87c
+    return tags
b3f87c
+
b3f87c
+
b3f87c
+def _print_skip_message(test, skip_tag):
b3f87c
+
b3f87c
+    # test.id() looks like 'crypto_test.CryptoTestResize.test_luks2_resize'
b3f87c
+    # and we want to print 'test_luks2_resize (crypto_test.CryptoTestResize)'
b3f87c
+    test_desc = test.id().split(".")
b3f87c
+    test_name = test_desc[-1]
b3f87c
+    test_module = ".".join(test_desc[:-1])
b3f87c
+
b3f87c
+    if skip_tag == TestTags.SLOW:
b3f87c
+        reason = "skipping slow tests"
b3f87c
+    elif skip_tag == TestTags.UNSTABLE:
b3f87c
+        reason = "skipping unstable tests"
b3f87c
+    elif skip_tag == TestTags.UNSAFE:
b3f87c
+        reason = "skipping test that modifies system configuration"
b3f87c
+    elif skip_tag == TestTags.EXTRADEPS:
b3f87c
+        reason = "skipping test that requires special configuration"
b3f87c
+    elif skip_tag == TestTags.CORE:
b3f87c
+        reason = "skipping non-core test"
b3f87c
+    else:
b3f87c
+        reason = "unknown reason"  # just to be sure there is some default value
b3f87c
+
b3f87c
+    if test._testMethodDoc:
b3f87c
+        print("%s (%s)\n%s ... skipped '%s'" % (test_name, test_module, test._testMethodDoc, reason))
b3f87c
+    else:
b3f87c
+        print("%s (%s) ... skipped '%s'" % (test_name, test_module, reason))
b3f87c
+
b3f87c
+
b3f87c
 if __name__ == '__main__':
b3f87c
 
b3f87c
     testdir = os.path.abspath(os.path.dirname(__file__))
b3f87c
@@ -45,6 +121,9 @@ if __name__ == '__main__':
b3f87c
     argparser.add_argument('-j', '--jenkins', dest='jenkins',
b3f87c
                            help='run also tests that should run only in a CI environment',
b3f87c
                            action='store_true')
b3f87c
+    argparser.add_argument('-c', '--core', dest='core',
b3f87c
+                           help='run tests that cover basic functionality of the library and regression tests',
b3f87c
+                           action='store_true')
b3f87c
     argparser.add_argument('-s', '--stop', dest='stop',
b3f87c
                            help='stop executing after first failed test',
b3f87c
                            action='store_true')
b3f87c
@@ -57,21 +136,60 @@ if __name__ == '__main__':
b3f87c
     if args.jenkins:
b3f87c
         os.environ['JENKINS_HOME'] = ''
b3f87c
 
b3f87c
+    # read the environmental variables for backwards compatibility
b3f87c
+    if 'JENKINS_HOME' in os.environ:
b3f87c
+        args.jenkins = True
b3f87c
+    if 'SKIP_SLOW' in os.environ:
b3f87c
+        args.fast = True
b3f87c
+    if 'FEELINGLUCKY' in os.environ:
b3f87c
+        args.lucky = True
b3f87c
+
b3f87c
     sys.path.append(testdir)
b3f87c
     sys.path.append(projdir)
b3f87c
     sys.path.append(os.path.join(projdir, 'src/python'))
b3f87c
 
b3f87c
     start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
b3f87c
 
b3f87c
+    loader = unittest.defaultTestLoader
b3f87c
     suite = unittest.TestSuite()
b3f87c
+
b3f87c
     if args.testname:
b3f87c
-        loader = unittest.TestLoader()
b3f87c
-        tests = loader.loadTestsFromNames(args.testname)
b3f87c
-        suite.addTests(tests)
b3f87c
+        test_cases = loader.loadTestsFromNames(args.testname)
b3f87c
     else:
b3f87c
-        loader = unittest.TestLoader()
b3f87c
-        tests = loader.discover(start_dir=testdir, pattern='*_test*.py')
b3f87c
-        suite.addTests(tests)
b3f87c
+        test_cases = loader.discover(start_dir=testdir, pattern='*_test*.py')
b3f87c
+
b3f87c
+    # extract list of test classes so we can check/run them manually one by one
b3f87c
+    tests = []
b3f87c
+    tests = _get_tests_from_suite(test_cases, tests)
b3f87c
+
b3f87c
+    # for some reason overrides_hack will fail if we import this at the start
b3f87c
+    # of the file
b3f87c
+    from utils import TestTags
b3f87c
+
b3f87c
+    for test in tests:
b3f87c
+        # get tags and (possibly) skip the test
b3f87c
+        tags = _get_test_tags(test)
b3f87c
+
b3f87c
+        if TestTags.SLOW in tags and args.fast:
b3f87c
+            _print_skip_message(test, TestTags.SLOW)
b3f87c
+            continue
b3f87c
+        if TestTags.UNSTABLE in tags and not args.lucky:
b3f87c
+            _print_skip_message(test, TestTags.UNSTABLE)
b3f87c
+            continue
b3f87c
+        if TestTags.UNSAFE in tags or TestTags.EXTRADEPS in tags and not args.jenkins:
b3f87c
+            _print_skip_message(test, TestTags.UNSAFE)
b3f87c
+            continue
b3f87c
+        if TestTags.EXTRADEPS in tags and not args.jenkins:
b3f87c
+            _print_skip_message(test, TestTags.EXTRADEPS)
b3f87c
+            continue
b3f87c
+
b3f87c
+        if args.core and TestTags.CORE not in tags and TestTags.REGRESSION not in tags:
b3f87c
+            _print_skip_message(test, TestTags.CORE)
b3f87c
+            continue
b3f87c
+
b3f87c
+        # finally add the test to the suite
b3f87c
+        suite.addTest(test)
b3f87c
+
b3f87c
     result = unittest.TextTestRunner(verbosity=2, failfast=args.stop).run(suite)
b3f87c
 
b3f87c
     # dump cropped journal to log file
b3f87c
-- 
b3f87c
2.20.1
b3f87c
b3f87c
b3f87c
From f4dd0bfff61d117096c1802ab793b3ab9a31dae3 Mon Sep 17 00:00:00 2001
b3f87c
From: Vojtech Trefny <vtrefny@redhat.com>
b3f87c
Date: Thu, 14 Mar 2019 09:43:37 +0100
b3f87c
Subject: [PATCH 03/10] Use the new test tags in tests
b3f87c
b3f87c
---
b3f87c
 tests/btrfs_test.py     | 14 ++++++--
b3f87c
 tests/crypto_test.py    | 73 +++++++++++++++++++++--------------------
b3f87c
 tests/dm_test.py        |  5 ++-
b3f87c
 tests/fs_test.py        | 18 +++++++---
b3f87c
 tests/kbd_test.py       | 24 +++++++-------
b3f87c
 tests/library_test.py   | 13 +++++---
b3f87c
 tests/loop_test.py      |  5 ++-
b3f87c
 tests/lvm_dbus_tests.py | 44 ++++++++++++++++---------
b3f87c
 tests/lvm_test.py       | 44 ++++++++++++++++---------
b3f87c
 tests/mdraid_test.py    | 38 ++++++++++++---------
b3f87c
 tests/mpath_test.py     |  5 ++-
b3f87c
 tests/nvdimm_test.py    |  9 +++--
b3f87c
 tests/overrides_test.py |  5 +++
b3f87c
 tests/part_test.py      | 11 ++++++-
b3f87c
 tests/s390_test.py      |  6 +++-
b3f87c
 tests/swap_test.py      |  7 +++-
b3f87c
 tests/utils_test.py     | 10 ++++--
b3f87c
 tests/vdo_test.py       | 13 ++++++--
b3f87c
 18 files changed, 227 insertions(+), 117 deletions(-)
b3f87c
b3f87c
diff --git a/tests/btrfs_test.py b/tests/btrfs_test.py
b3f87c
index ac1594f..eab25db 100644
b3f87c
--- a/tests/btrfs_test.py
b3f87c
+++ b/tests/btrfs_test.py
b3f87c
@@ -10,7 +10,7 @@ from distutils.version import LooseVersion
b3f87c
 from distutils.spawn import find_executable
b3f87c
 
b3f87c
 import overrides_hack
b3f87c
-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, skip_on, mount, umount, run_command
b3f87c
+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, mount, umount, run_command, TestTags, tag_test
b3f87c
 from gi.repository import GLib, BlockDev
b3f87c
 
b3f87c
 TEST_MNT = "/tmp/libblockdev_test_mnt"
b3f87c
@@ -74,6 +74,7 @@ class BtrfsTestCase(unittest.TestCase):
b3f87c
         return LooseVersion(m.groups()[0])
b3f87c
 
b3f87c
 class BtrfsTestCreateQuerySimple(BtrfsTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_create_and_query_volume(self):
b3f87c
         """Verify that btrfs volume creation and querying works"""
b3f87c
 
b3f87c
@@ -180,6 +181,7 @@ class BtrfsTestAddRemoveDevice(BtrfsTestCase):
b3f87c
         self.assertEqual(len(devs), 1)
b3f87c
 
b3f87c
 class BtrfsTestCreateDeleteSubvolume(BtrfsTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_create_delete_subvolume(self):
b3f87c
         """Verify that it is possible to create/delete subvolume"""
b3f87c
 
b3f87c
@@ -306,6 +308,7 @@ class BtrfsTestSetDefaultSubvolumeID(BtrfsTestCase):
b3f87c
         self.assertEqual(ret, 5)
b3f87c
 
b3f87c
 class BtrfsTestListDevices(BtrfsTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_list_devices(self):
b3f87c
         """Verify that it is possible to get info about devices"""
b3f87c
 
b3f87c
@@ -324,6 +327,7 @@ class BtrfsTestListDevices(BtrfsTestCase):
b3f87c
         self.assertTrue(devs[1].used >= 0)
b3f87c
 
b3f87c
 class BtrfsTestListSubvolumes(BtrfsTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_list_subvolumes(self):
b3f87c
         """Verify that it is possible to get info about subvolumes"""
b3f87c
 
b3f87c
@@ -344,6 +348,7 @@ class BtrfsTestListSubvolumes(BtrfsTestCase):
b3f87c
         self.assertEqual(subvols[0].path, "subvol1")
b3f87c
 
b3f87c
 class BtrfsTestFilesystemInfo(BtrfsTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_filesystem_info(self):
b3f87c
         """Verify that it is possible to get filesystem info"""
b3f87c
 
b3f87c
@@ -376,6 +381,7 @@ class BtrfsTestFilesystemInfoNoLabel(BtrfsTestCase):
b3f87c
         self.assertTrue(info.used >= 0)
b3f87c
 
b3f87c
 class BtrfsTestMkfs(BtrfsTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_mkfs(self):
b3f87c
         """Verify that it is possible to create a btrfs filesystem"""
b3f87c
 
b3f87c
@@ -489,7 +495,6 @@ class BtrfsTooSmallTestCase (BtrfsTestCase):
b3f87c
             pass
b3f87c
         os.unlink(self.dev_file2)
b3f87c
 
b3f87c
-    @skip_on("fedora", "25", reason="Min sizes for Btrfs are different on F25")
b3f87c
     def test_create_too_small(self):
b3f87c
         """Verify that an attempt to create BTRFS on a too small device fails"""
b3f87c
 
b3f87c
@@ -527,7 +532,6 @@ class BtrfsJustBigEnoughTestCase (BtrfsTestCase):
b3f87c
             pass
b3f87c
         os.unlink(self.dev_file2)
b3f87c
 
b3f87c
-    @skip_on("fedora", "25", reason="Min sizes for Btrfs are different on F25")
b3f87c
     def test_create_just_enough(self):
b3f87c
         """Verify that creating BTRFS on a just big enough devices works"""
b3f87c
 
b3f87c
@@ -541,6 +545,7 @@ class FakeBtrfsUtilsTestCase(BtrfsTestCase):
b3f87c
     def setUp(self):
b3f87c
         pass
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_list_subvols_weird_docker_data(self):
b3f87c
         """Verify that list_subvolumes works as expected on weird data from one Docker use case"""
b3f87c
 
b3f87c
@@ -562,6 +567,7 @@ class BTRFSUnloadTest(BtrfsTestCase):
b3f87c
         # tests
b3f87c
         self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_low_version(self):
b3f87c
         """Verify that checking the minimum BTRFS version works as expected"""
b3f87c
 
b3f87c
@@ -579,6 +585,7 @@ class BTRFSUnloadTest(BtrfsTestCase):
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
         self.assertIn("btrfs", BlockDev.get_available_plugin_names())
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_new_version_format(self):
b3f87c
         """Verify that checking the minimum BTRFS version works as expected with the new format"""
b3f87c
 
b3f87c
@@ -594,6 +601,7 @@ class BTRFSUnloadTest(BtrfsTestCase):
b3f87c
         BlockDev.reinit(self.requested_plugins, True, None)
b3f87c
         self.assertIn("btrfs", BlockDev.get_available_plugin_names())
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_no_btrfs(self):
b3f87c
         """Verify that checking btrfs tool availability works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/crypto_test.py b/tests/crypto_test.py
b3f87c
index 7320e74..b062505 100644
b3f87c
--- a/tests/crypto_test.py
b3f87c
+++ b/tests/crypto_test.py
b3f87c
@@ -9,7 +9,7 @@ import locale
b3f87c
 import re
b3f87c
 import tarfile
b3f87c
 
b3f87c
-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, skip_on, get_avail_locales, requires_locales, run_command, read_file
b3f87c
+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, skip_on, get_avail_locales, requires_locales, run_command, read_file, TestTags, tag_test
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
 PASSWD = "myshinylittlepassword"
b3f87c
@@ -92,6 +92,7 @@ class CryptoTestGenerateBackupPassphrase(CryptoTestCase):
b3f87c
         # we don't need block devices for this test
b3f87c
         pass
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_generate_backup_passhprase(self):
b3f87c
         """Verify that backup passphrase generation works as expected"""
b3f87c
 
b3f87c
@@ -101,7 +102,7 @@ class CryptoTestGenerateBackupPassphrase(CryptoTestCase):
b3f87c
             six.assertRegex(self, bp, exp)
b3f87c
 
b3f87c
 class CryptoTestFormat(CryptoTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
     def test_luks_format(self):
b3f87c
         """Verify that formating device as LUKS works"""
b3f87c
 
b3f87c
@@ -121,7 +122,7 @@ class CryptoTestFormat(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_format_blob(self.loop_dev, "aes-cbc-essiv:sha256", 0, [ord(c) for c in PASSWD], 0)
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_format(self):
b3f87c
         """Verify that formating device as LUKS 2 works"""
b3f87c
@@ -222,7 +223,7 @@ class CryptoTestFormat(CryptoTestCase):
b3f87c
         self.assertEqual(int(m.group(1)), 5)
b3f87c
 
b3f87c
 class CryptoTestResize(CryptoTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_luks_resize(self):
b3f87c
         """Verify that resizing LUKS device works"""
b3f87c
 
b3f87c
@@ -244,7 +245,7 @@ class CryptoTestResize(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_close("libblockdevTestLUKS")
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_resize(self):
b3f87c
         """Verify that resizing LUKS 2 device works"""
b3f87c
@@ -304,11 +305,11 @@ class CryptoTestOpenClose(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_close("libblockdevTestLUKS")
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
     def test_luks_open_close(self):
b3f87c
         self._luks_open_close(self._luks_format)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_open_close(self):
b3f87c
         self._luks_open_close(self._luks2_format)
b3f87c
@@ -329,11 +330,11 @@ class CryptoTestAddKey(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_add_key_blob(self.loop_dev, [ord(c) for c in PASSWD2], [ord(c) for c in PASSWD3])
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_luks_add_key(self):
b3f87c
         self._add_key(self._luks_format)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_add_key(self):
b3f87c
         self._add_key(self._luks2_format)
b3f87c
@@ -360,11 +361,11 @@ class CryptoTestRemoveKey(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_remove_key_blob(self.loop_dev, [ord(c) for c in PASSWD2])
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_luks_remove_key(self):
b3f87c
         self._remove_key(self._luks_format)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_remove_key(self):
b3f87c
         self._remove_key(self._luks2_format)
b3f87c
@@ -380,7 +381,7 @@ class CryptoTestErrorLocale(CryptoTestCase):
b3f87c
         if self._orig_loc:
b3f87c
             locale.setlocale(locale.LC_ALL, self._orig_loc)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @requires_locales({"cs_CZ.UTF-8"})
b3f87c
     def test_error_locale_key(self):
b3f87c
         """Verify that the error msg is locale agnostic"""
b3f87c
@@ -407,11 +408,11 @@ class CryptoTestChangeKey(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_change_key_blob(self.loop_dev, [ord(c) for c in PASSWD2], [ord(c) for c in PASSWD3])
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_luks_change_key(self):
b3f87c
         self._change_key(self._luks_format)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_change_key(self):
b3f87c
         self._change_key(self._luks2_format)
b3f87c
@@ -432,11 +433,11 @@ class CryptoTestIsLuks(CryptoTestCase):
b3f87c
         is_luks = BlockDev.crypto_device_is_luks(self.loop_dev2)
b3f87c
         self.assertFalse(is_luks)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_is_luks(self):
b3f87c
         self._is_luks(self._luks_format)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_is_luks2(self):
b3f87c
         self._is_luks(self._luks2_format)
b3f87c
@@ -468,11 +469,11 @@ class CryptoTestLuksStatus(CryptoTestCase):
b3f87c
         with self.assertRaises(GLib.GError):
b3f87c
             BlockDev.crypto_luks_status("libblockdevTestLUKS")
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_luks_status(self):
b3f87c
         self._luks_status(self._luks_format)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_status(self):
b3f87c
         self._luks_status(self._luks2_format)
b3f87c
@@ -490,18 +491,18 @@ class CryptoTestGetUUID(CryptoTestCase):
b3f87c
         with self.assertRaises(GLib.GError):
b3f87c
             uuid = BlockDev.crypto_luks_uuid(self.loop_dev2)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_luks_get_uuid(self):
b3f87c
         self._get_uuid(self._luks_format)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_get_uuid(self):
b3f87c
         self._get_uuid(self._luks2_format)
b3f87c
 
b3f87c
 class CryptoTestGetMetadataSize(CryptoTestCase):
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_get_metadata_size(self):
b3f87c
         """Verify that getting LUKS 2 device metadata size works"""
b3f87c
@@ -521,7 +522,7 @@ class CryptoTestGetMetadataSize(CryptoTestCase):
b3f87c
         offset = int(m.group(1))
b3f87c
         self.assertEquals(meta_size, offset, "LUKS 2 metadata sizes differ")
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_luks_get_metadata_size(self):
b3f87c
         """Verify that getting LUKS device metadata size works"""
b3f87c
 
b3f87c
@@ -570,11 +571,11 @@ class CryptoTestLuksOpenRW(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_close("libblockdevTestLUKS")
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_luks_open_rw(self):
b3f87c
         self._luks_open_rw(self._luks_format)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_open_rw(self):
b3f87c
         self._luks_open_rw(self._luks2_format)
b3f87c
@@ -609,7 +610,7 @@ class CryptoTestEscrow(CryptoTestCase):
b3f87c
             '-a', '-o', self.public_cert])
b3f87c
         self.addCleanup(os.unlink, self.public_cert)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @skip_on(("centos", "enterprise_linux"), "7", reason="volume_key asks for password in non-interactive mode on this release")
b3f87c
     @skip_on("debian", reason="volume_key asks for password in non-interactive mode on this release")
b3f87c
     def test_escrow_packet(self):
b3f87c
@@ -654,7 +655,7 @@ class CryptoTestEscrow(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_open(self.loop_dev, 'libblockdevTestLUKS', PASSWD3, None)
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_backup_passphrase(self):
b3f87c
         """Verify that a backup passphrase can be created for a device"""
b3f87c
         succ = BlockDev.crypto_luks_format(self.loop_dev, None, 0, PASSWD, None, 0)
b3f87c
@@ -735,12 +736,12 @@ class CryptoTestSuspendResume(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_close("libblockdevTestLUKS")
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_luks_suspend_resume(self):
b3f87c
         """Verify that suspending/resuming LUKS device works"""
b3f87c
         self._luks_suspend_resume(self._luks_format)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_suspend_resume(self):
b3f87c
         """Verify that suspending/resuming LUKS 2 device works"""
b3f87c
@@ -781,12 +782,12 @@ class CryptoTestKillSlot(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_close("libblockdevTestLUKS")
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_luks_kill_slot(self):
b3f87c
         """Verify that killing a key slot on LUKS device works"""
b3f87c
         self._luks_kill_slot(self._luks_format)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_kill_slot(self):
b3f87c
         """Verify that killing a key slot on LUKS 2 device works"""
b3f87c
@@ -836,19 +837,19 @@ class CryptoTestHeaderBackupRestore(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_close("libblockdevTestLUKS")
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_luks_header_backup_restore(self):
b3f87c
         """Verify that header backup/restore with LUKS works"""
b3f87c
         self._luks_header_backup_restore(self._luks_format)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_header_backup_restore(self):
b3f87c
         """Verify that header backup/restore with LUKS2 works"""
b3f87c
         self._luks_header_backup_restore(self._luks2_format)
b3f87c
 
b3f87c
 class CryptoTestInfo(CryptoTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
     def test_luks_format(self):
b3f87c
         """Verify that we can get information about a LUKS device"""
b3f87c
 
b3f87c
@@ -872,7 +873,7 @@ class CryptoTestInfo(CryptoTestCase):
b3f87c
         succ = BlockDev.crypto_luks_close("libblockdevTestLUKS")
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_format(self):
b3f87c
         """Verify that we can get information about a LUKS 2 device"""
b3f87c
@@ -903,7 +904,7 @@ class CryptoTestInfo(CryptoTestCase):
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
 class CryptoTestIntegrity(CryptoTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported")
b3f87c
     def test_luks2_integrity(self):
b3f87c
         """Verify that we can get create a LUKS 2 device with integrity"""
b3f87c
@@ -983,6 +984,7 @@ class CryptoTestTrueCrypt(CryptoTestCase):
b3f87c
         if not succ:
b3f87c
             raise RuntimeError("Failed to tear down loop device used for testing")
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_truecrypt_open_close(self):
b3f87c
         """Verify that opening/closing TrueCrypt device works"""
b3f87c
 
b3f87c
@@ -1003,6 +1005,7 @@ class CryptoTestTrueCrypt(CryptoTestCase):
b3f87c
         self.assertTrue(succ)
b3f87c
         self.assertFalse(os.path.exists("/dev/mapper/libblockdevTestTC"))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_veracrypt_open_close(self):
b3f87c
         """Verify that opening/closing VeraCrypt device works"""
b3f87c
 
b3f87c
diff --git a/tests/dm_test.py b/tests/dm_test.py
b3f87c
index 0dd1861..936e305 100644
b3f87c
--- a/tests/dm_test.py
b3f87c
+++ b/tests/dm_test.py
b3f87c
@@ -2,7 +2,7 @@ import unittest
b3f87c
 import os
b3f87c
 import overrides_hack
b3f87c
 
b3f87c
-from utils import run, create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path
b3f87c
+from utils import run, create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
 
b3f87c
@@ -65,6 +65,7 @@ class DevMapperGetSubsystemFromName(DevMapperTestCase):
b3f87c
         self.assertEqual(subsystem, "CRYPT")
b3f87c
 
b3f87c
 class DevMapperCreateRemoveLinear(DevMapperTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_create_remove_linear(self):
b3f87c
         """Verify that it is possible to create new linear mapping and remove it"""
b3f87c
 
b3f87c
@@ -120,6 +121,7 @@ class DMUnloadTest(DevMapperTestCase):
b3f87c
         # tests
b3f87c
         self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_low_version(self):
b3f87c
         """Verify that checking the minimum dmsetup version works as expected"""
b3f87c
 
b3f87c
@@ -137,6 +139,7 @@ class DMUnloadTest(DevMapperTestCase):
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
         self.assertIn("dm", BlockDev.get_available_plugin_names())
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_no_dm(self):
b3f87c
         """Verify that checking dmsetup tool availability works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/fs_test.py b/tests/fs_test.py
b3f87c
index d3f3353..adcf312 100644
b3f87c
--- a/tests/fs_test.py
b3f87c
+++ b/tests/fs_test.py
b3f87c
@@ -5,7 +5,7 @@ import subprocess
b3f87c
 import tempfile
b3f87c
 from contextlib import contextmanager
b3f87c
 import utils
b3f87c
-from utils import run, create_sparse_tempfile, mount, umount, unstable_test
b3f87c
+from utils import run, create_sparse_tempfile, mount, umount, TestTags, tag_test
b3f87c
 import six
b3f87c
 import overrides_hack
b3f87c
 
b3f87c
@@ -97,6 +97,7 @@ class FSTestCase(unittest.TestCase):
b3f87c
             self.fail("Failed to set %s read-write" % device)
b3f87c
 
b3f87c
 class TestGenericWipe(FSTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_generic_wipe(self):
b3f87c
         """Verify that generic signature wipe works as expected"""
b3f87c
 
b3f87c
@@ -210,16 +211,19 @@ class ExtTestMkfs(FSTestCase):
b3f87c
 
b3f87c
         BlockDev.fs_wipe(self.loop_dev, True)
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_ext2_mkfs(self):
b3f87c
         """Verify that it is possible to create a new ext2 file system"""
b3f87c
         self._test_ext_mkfs(mkfs_function=BlockDev.fs_ext2_mkfs,
b3f87c
                             ext_version="ext2")
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_ext3_mkfs(self):
b3f87c
         """Verify that it is possible to create a new ext3 file system"""
b3f87c
         self._test_ext_mkfs(mkfs_function=BlockDev.fs_ext3_mkfs,
b3f87c
                             ext_version="ext3")
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_ext4_mkfs(self):
b3f87c
         """Verify that it is possible to create a new ext4 file system"""
b3f87c
         self._test_ext_mkfs(mkfs_function=BlockDev.fs_ext4_mkfs,
b3f87c
@@ -385,16 +389,19 @@ class ExtGetInfo(FSTestCase):
b3f87c
             self.assertTrue(fi.uuid)
b3f87c
             self.assertTrue(fi.state, "clean")
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_ext2_get_info(self):
b3f87c
         """Verify that it is possible to get info about an ext2 file system"""
b3f87c
         self._test_ext_get_info(mkfs_function=BlockDev.fs_ext2_mkfs,
b3f87c
                                 info_function=BlockDev.fs_ext2_get_info)
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_ext3_get_info(self):
b3f87c
         """Verify that it is possible to get info about an ext3 file system"""
b3f87c
         self._test_ext_get_info(mkfs_function=BlockDev.fs_ext3_mkfs,
b3f87c
                                 info_function=BlockDev.fs_ext3_get_info)
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_ext4_get_info(self):
b3f87c
         """Verify that it is possible to get info about an ext4 file system"""
b3f87c
         self._test_ext_get_info(mkfs_function=BlockDev.fs_ext4_mkfs,
b3f87c
@@ -511,6 +518,7 @@ class ExtResize(FSTestCase):
b3f87c
                               resize_function=BlockDev.fs_ext4_resize)
b3f87c
 
b3f87c
 class XfsTestMkfs(FSTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_xfs_mkfs(self):
b3f87c
         """Verify that it is possible to create a new xfs file system"""
b3f87c
 
b3f87c
@@ -597,6 +605,7 @@ class XfsTestRepair(FSTestCase):
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
 class XfsGetInfo(FSTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_xfs_get_info(self):
b3f87c
         """Verify that it is possible to get info about an xfs file system"""
b3f87c
 
b3f87c
@@ -970,6 +979,7 @@ class MountTest(FSTestCase):
b3f87c
         if ret != 0:
b3f87c
             self.fail("Failed to remove user user '%s': %s" % (self.username, err))
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_mount(self):
b3f87c
         """ Test basic mounting and unmounting """
b3f87c
 
b3f87c
@@ -1053,7 +1063,7 @@ class MountTest(FSTestCase):
b3f87c
             BlockDev.fs_mount(loop_dev, tmp_dir, None, "rw", None)
b3f87c
         self.assertFalse(os.path.ismount(tmp_dir))
b3f87c
 
b3f87c
-    @unittest.skipUnless("JENKINS_HOME" in os.environ, "skipping test that modifies system configuration")
b3f87c
+    @tag_test(TestTags.UNSAFE)
b3f87c
     def test_mount_fstab(self):
b3f87c
         """ Test mounting and unmounting devices in /etc/fstab """
b3f87c
         # this test will change /etc/fstab, we want to revert the changes when it finishes
b3f87c
@@ -1088,7 +1098,7 @@ class MountTest(FSTestCase):
b3f87c
         self.assertTrue(succ)
b3f87c
         self.assertFalse(os.path.ismount(tmp))
b3f87c
 
b3f87c
-    @unittest.skipUnless("JENKINS_HOME" in os.environ, "skipping test that modifies system configuration")
b3f87c
+    @tag_test(TestTags.UNSAFE)
b3f87c
     def test_mount_fstab_user(self):
b3f87c
         """ Test mounting and unmounting devices in /etc/fstab as non-root user """
b3f87c
         # this test will change /etc/fstab, we want to revert the changes when it finishes
b3f87c
@@ -1360,7 +1370,7 @@ class GenericResize(FSTestCase):
b3f87c
                                   fs_info_func=info_prepare,
b3f87c
                                   info_size_func=expected_size)
b3f87c
 
b3f87c
-    @unstable_test
b3f87c
+    @tag_test(TestTags.UNSTABLE)
b3f87c
     def test_vfat_generic_resize(self):
b3f87c
         """Test generic resize function with a vfat file system"""
b3f87c
         self._test_generic_resize(mkfs_function=BlockDev.fs_vfat_mkfs)
b3f87c
diff --git a/tests/kbd_test.py b/tests/kbd_test.py
b3f87c
index b6cfb3c..5e872c4 100644
b3f87c
--- a/tests/kbd_test.py
b3f87c
+++ b/tests/kbd_test.py
b3f87c
@@ -4,7 +4,7 @@ import re
b3f87c
 import time
b3f87c
 from contextlib import contextmanager
b3f87c
 from distutils.version import LooseVersion
b3f87c
-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, wipe_all, fake_path, read_file, skip_on, unstable_test
b3f87c
+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, wipe_all, fake_path, read_file, skip_on, TestTags, tag_test
b3f87c
 from bytesize import bytesize
b3f87c
 import overrides_hack
b3f87c
 
b3f87c
@@ -66,7 +66,7 @@ class KbdZRAMTestCase(unittest.TestCase):
b3f87c
 
b3f87c
 class KbdZRAMDevicesTestCase(KbdZRAMTestCase):
b3f87c
     @unittest.skipUnless(_can_load_zram(), "cannot load the 'zram' module")
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_create_destroy_devices(self):
b3f87c
         # the easiest case
b3f87c
         with _track_module_load(self, "zram", "_loaded_zram_module"):
b3f87c
@@ -113,7 +113,7 @@ class KbdZRAMDevicesTestCase(KbdZRAMTestCase):
b3f87c
             time.sleep(1)
b3f87c
 
b3f87c
     @unittest.skipUnless(_can_load_zram(), "cannot load the 'zram' module")
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_zram_add_remove_device(self):
b3f87c
         """Verify that it is possible to add and remove a zram device"""
b3f87c
 
b3f87c
@@ -268,6 +268,7 @@ class KbdBcacheNodevTestCase(unittest.TestCase):
b3f87c
             BlockDev.reinit(cls.requested_plugins, True, None)
b3f87c
 
b3f87c
     @skip_on(("centos", "enterprise_linux"))
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_bcache_mode_str_bijection(self):
b3f87c
         """Verify that it's possible to transform between cache modes and their string representations"""
b3f87c
 
b3f87c
@@ -333,7 +334,7 @@ class KbdBcacheTestCase(unittest.TestCase):
b3f87c
 
b3f87c
 class KbdTestBcacheCreate(KbdBcacheTestCase):
b3f87c
     @skip_on(("centos", "enterprise_linux"))
b3f87c
-    @unstable_test
b3f87c
+    @tag_test(TestTags.UNSTABLE)
b3f87c
     def test_bcache_create_destroy(self):
b3f87c
         """Verify that it's possible to create and destroy a bcache device"""
b3f87c
 
b3f87c
@@ -352,7 +353,7 @@ class KbdTestBcacheCreate(KbdBcacheTestCase):
b3f87c
         wipe_all(self.loop_dev, self.loop_dev2)
b3f87c
 
b3f87c
     @skip_on(("centos", "enterprise_linux"))
b3f87c
-    @unstable_test
b3f87c
+    @tag_test(TestTags.UNSTABLE)
b3f87c
     def test_bcache_create_destroy_full_path(self):
b3f87c
         """Verify that it's possible to create and destroy a bcache device with full device path"""
b3f87c
 
b3f87c
@@ -372,7 +373,7 @@ class KbdTestBcacheCreate(KbdBcacheTestCase):
b3f87c
 
b3f87c
 class KbdTestBcacheAttachDetach(KbdBcacheTestCase):
b3f87c
     @skip_on(("centos", "enterprise_linux"))
b3f87c
-    @unstable_test
b3f87c
+    @tag_test(TestTags.UNSTABLE)
b3f87c
     def test_bcache_attach_detach(self):
b3f87c
         """Verify that it's possible to detach/attach a cache from/to a bcache device"""
b3f87c
 
b3f87c
@@ -398,7 +399,7 @@ class KbdTestBcacheAttachDetach(KbdBcacheTestCase):
b3f87c
         wipe_all(self.loop_dev, self.loop_dev2)
b3f87c
 
b3f87c
     @skip_on(("centos", "enterprise_linux"))
b3f87c
-    @unstable_test
b3f87c
+    @tag_test(TestTags.UNSTABLE)
b3f87c
     def test_bcache_attach_detach_full_path(self):
b3f87c
         """Verify that it's possible to detach/attach a cache from/to a bcache device with full device path"""
b3f87c
 
b3f87c
@@ -424,7 +425,7 @@ class KbdTestBcacheAttachDetach(KbdBcacheTestCase):
b3f87c
         wipe_all(self.loop_dev, self.loop_dev2)
b3f87c
 
b3f87c
     @skip_on(("centos", "enterprise_linux"))
b3f87c
-    @unstable_test
b3f87c
+    @tag_test(TestTags.UNSTABLE)
b3f87c
     def test_bcache_detach_destroy(self):
b3f87c
         """Verify that it's possible to destroy a bcache device with no cache attached"""
b3f87c
 
b3f87c
@@ -448,7 +449,7 @@ class KbdTestBcacheAttachDetach(KbdBcacheTestCase):
b3f87c
 
b3f87c
 class KbdTestBcacheGetSetMode(KbdBcacheTestCase):
b3f87c
     @skip_on(("centos", "enterprise_linux"))
b3f87c
-    @unstable_test
b3f87c
+    @tag_test(TestTags.UNSTABLE)
b3f87c
     def test_bcache_get_set_mode(self):
b3f87c
         """Verify that it is possible to get and set Bcache mode"""
b3f87c
 
b3f87c
@@ -505,7 +506,7 @@ class KbdTestBcacheStatusTest(KbdBcacheTestCase):
b3f87c
         return sum(int(read_file(os.path.realpath(c) + '/../size')) for c in caches)
b3f87c
 
b3f87c
     @skip_on(("centos", "enterprise_linux"))
b3f87c
-    @unstable_test
b3f87c
+    @tag_test(TestTags.UNSTABLE)
b3f87c
     def test_bcache_status(self):
b3f87c
         succ, dev = BlockDev.kbd_bcache_create(self.loop_dev, self.loop_dev2, None)
b3f87c
         self.assertTrue(succ)
b3f87c
@@ -538,7 +539,7 @@ class KbdTestBcacheStatusTest(KbdBcacheTestCase):
b3f87c
 
b3f87c
 class KbdTestBcacheBackingCacheDevTest(KbdBcacheTestCase):
b3f87c
     @skip_on(("centos", "enterprise_linux"))
b3f87c
-    @unstable_test
b3f87c
+    @tag_test(TestTags.UNSTABLE)
b3f87c
     def test_bcache_backing_cache_dev(self):
b3f87c
         """Verify that is is possible to get the backing and cache devices for a Bcache"""
b3f87c
 
b3f87c
@@ -566,6 +567,7 @@ class KbdUnloadTest(KbdBcacheTestCase):
b3f87c
         self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
b3f87c
 
b3f87c
     @skip_on(("centos", "enterprise_linux"))
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_no_bcache_progs(self):
b3f87c
         """Verify that checking the availability of make-bcache works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/library_test.py b/tests/library_test.py
b3f87c
index 159031a..fa33b53 100644
b3f87c
--- a/tests/library_test.py
b3f87c
+++ b/tests/library_test.py
b3f87c
@@ -2,7 +2,7 @@ import os
b3f87c
 import unittest
b3f87c
 import re
b3f87c
 import overrides_hack
b3f87c
-from utils import fake_path
b3f87c
+from utils import fake_path, TestTags, tag_test
b3f87c
 
b3f87c
 from gi.repository import GLib, BlockDev
b3f87c
 
b3f87c
@@ -40,7 +40,7 @@ class LibraryOpsTestCase(unittest.TestCase):
b3f87c
         BlockDev.reinit(self.requested_plugins, True, None)
b3f87c
 
b3f87c
     # recompiles the LVM plugin
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
     def test_reload(self):
b3f87c
         """Verify that reloading plugins works as expected"""
b3f87c
 
b3f87c
@@ -72,7 +72,7 @@ class LibraryOpsTestCase(unittest.TestCase):
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
 
b3f87c
     # recompiles the LVM plugin
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_force_plugin(self):
b3f87c
         """Verify that forcing plugin to be used works as expected"""
b3f87c
 
b3f87c
@@ -118,7 +118,7 @@ class LibraryOpsTestCase(unittest.TestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_get_max_lv_size(), orig_max_size)
b3f87c
 
b3f87c
     # recompiles the LVM plugin
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_plugin_priority(self):
b3f87c
         """Verify that preferring plugin to be used works as expected"""
b3f87c
 
b3f87c
@@ -181,7 +181,7 @@ class LibraryOpsTestCase(unittest.TestCase):
b3f87c
         os.system ("rm -f src/plugins/.libs/libbd_lvm2.so")
b3f87c
 
b3f87c
     # recompiles the LVM plugin
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_plugin_fallback(self):
b3f87c
         """Verify that fallback when loading plugins works as expected"""
b3f87c
 
b3f87c
@@ -250,6 +250,7 @@ class LibraryOpsTestCase(unittest.TestCase):
b3f87c
 
b3f87c
         self.log += msg + "\n"
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_logging_setup(self):
b3f87c
         """Verify that setting up logging works as expected"""
b3f87c
 
b3f87c
@@ -280,6 +281,7 @@ class LibraryOpsTestCase(unittest.TestCase):
b3f87c
         self.assertIn("stderr[%s]:" % task_id2, self.log)
b3f87c
         self.assertIn("...done [%s] (exit code: 0)" % task_id2, self.log)
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_require_plugins(self):
b3f87c
         """Verify that loading only required plugins works as expected"""
b3f87c
 
b3f87c
@@ -290,6 +292,7 @@ class LibraryOpsTestCase(unittest.TestCase):
b3f87c
         self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"])
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_not_implemented(self):
b3f87c
         """Verify that unloaded/unimplemented functions report errors"""
b3f87c
 
b3f87c
diff --git a/tests/loop_test.py b/tests/loop_test.py
b3f87c
index 9e9d9ac..5aaf928 100644
b3f87c
--- a/tests/loop_test.py
b3f87c
+++ b/tests/loop_test.py
b3f87c
@@ -3,7 +3,7 @@ import unittest
b3f87c
 import time
b3f87c
 import overrides_hack
b3f87c
 
b3f87c
-from utils import create_sparse_tempfile
b3f87c
+from utils import create_sparse_tempfile, TestTags, tag_test
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
 
b3f87c
@@ -31,6 +31,7 @@ class LoopTestCase(unittest.TestCase):
b3f87c
         os.unlink(self.dev_file)
b3f87c
 
b3f87c
 class LoopTestSetupBasic(LoopTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def testLoop_setup_teardown_basic(self):
b3f87c
         """Verify that basic loop_setup and loop_teardown work as expected"""
b3f87c
 
b3f87c
@@ -97,6 +98,7 @@ class LoopTestSetupReadOnly(LoopTestCase):
b3f87c
 # XXX: any sane way how to test part_probe=True/False?
b3f87c
 
b3f87c
 class LoopTestGetLoopName(LoopTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def testLoop_get_loop_name(self):
b3f87c
         """Verify that loop_get_loop_name works as expected"""
b3f87c
 
b3f87c
@@ -107,6 +109,7 @@ class LoopTestGetLoopName(LoopTestCase):
b3f87c
         self.assertEqual(ret_loop, self.loop)
b3f87c
 
b3f87c
 class LoopTestGetBackingFile(LoopTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def testLoop_get_backing_file(self):
b3f87c
         """Verify that loop_get_backing_file works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py
b3f87c
index 7c3b4cc..625a392 100644
b3f87c
--- a/tests/lvm_dbus_tests.py
b3f87c
+++ b/tests/lvm_dbus_tests.py
b3f87c
@@ -8,7 +8,7 @@ import re
b3f87c
 import subprocess
b3f87c
 from itertools import chain
b3f87c
 
b3f87c
-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, skip_on, run_command
b3f87c
+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, run_command, TestTags, tag_test
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
 import dbus
b3f87c
@@ -38,6 +38,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         super(LvmNoDevTestCase, self).__init__(*args, **kwargs)
b3f87c
         self._log = ""
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_is_supported_pe_size(self):
b3f87c
         """Verify that lvm_is_supported_pe_size works as expected"""
b3f87c
 
b3f87c
@@ -53,12 +54,14 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertFalse(BlockDev.lvm_is_supported_pe_size(65535))
b3f87c
         self.assertFalse(BlockDev.lvm_is_supported_pe_size(32 * 1024**3))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_supported_pe_sizes(self):
b3f87c
         """Verify that supported PE sizes are really supported"""
b3f87c
 
b3f87c
         for size in BlockDev.lvm_get_supported_pe_sizes():
b3f87c
             self.assertTrue(BlockDev.lvm_is_supported_pe_size(size))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_max_lv_size(self):
b3f87c
         """Verify that max LV size is correctly determined"""
b3f87c
 
b3f87c
@@ -71,6 +74,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
 
b3f87c
         self.assertEqual(BlockDev.lvm_get_max_lv_size(), expected)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_round_size_to_pe(self):
b3f87c
         """Verify that round_size_to_pe works as expected"""
b3f87c
 
b3f87c
@@ -95,6 +99,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_round_size_to_pe(biggest_multiple - (2 * 4 * 1024**2) + 1, 4 * 1024**2, False),
b3f87c
                          biggest_multiple - (2 * 4 * 1024**2))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_lv_physical_size(self):
b3f87c
         """Verify that get_lv_physical_size works as expected"""
b3f87c
 
b3f87c
@@ -108,6 +113,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_get_lv_physical_size(11 * 1024**2, 4 * 1024**2),
b3f87c
                          12 * 1024**2)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_thpool_padding(self):
b3f87c
         """Verify that get_thpool_padding works as expected"""
b3f87c
 
b3f87c
@@ -121,6 +127,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_get_thpool_padding(11 * 1024**2, 4 * 1024**2, True),
b3f87c
                          expected_padding)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_thpool_meta_size(self):
b3f87c
         """Verify that getting recommended thin pool metadata size works as expected"""
b3f87c
 
b3f87c
@@ -139,6 +146,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_get_thpool_meta_size (100 * 1024**2, 128 * 1024, 100),
b3f87c
                          BlockDev.LVM_MIN_THPOOL_MD_SIZE)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_is_valid_thpool_md_size(self):
b3f87c
         """Verify that is_valid_thpool_md_size works as expected"""
b3f87c
 
b3f87c
@@ -149,6 +157,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(1 * 1024**2))
b3f87c
         self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(17 * 1024**3))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_is_valid_thpool_chunk_size(self):
b3f87c
         """Verify that is_valid_thpool_chunk_size works as expected"""
b3f87c
 
b3f87c
@@ -167,6 +176,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
     def _store_log(self, lvl, msg):
b3f87c
         self._log += str((lvl, msg))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_set_global_config(self):
b3f87c
         """Verify that getting and setting global config works as expected"""
b3f87c
 
b3f87c
@@ -207,6 +217,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         succ = BlockDev.lvm_set_global_config(None)
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_cache_get_default_md_size(self):
b3f87c
         """Verify that default cache metadata size is calculated properly"""
b3f87c
 
b3f87c
@@ -215,6 +226,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_cache_get_default_md_size(80 * 1024**3), (80 * 1024**3) // 1000)
b3f87c
         self.assertEqual(BlockDev.lvm_cache_get_default_md_size(6 * 1024**3), 8 * 1024**2)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_cache_mode_bijection(self):
b3f87c
         """Verify that cache modes and their string representations map to each other"""
b3f87c
 
b3f87c
@@ -275,6 +287,7 @@ class LvmPVonlyTestCase(LVMTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmTestPVcreateRemove(LvmPVonlyTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_pvcreate_and_pvremove(self):
b3f87c
         """Verify that it's possible to create and destroy a PV"""
b3f87c
 
b3f87c
@@ -380,6 +393,7 @@ class LvmPVVGTestCase(LvmPVonlyTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmTestVGcreateRemove(LvmPVVGTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_vgcreate_vgremove(self):
b3f87c
         """Verify that it is possible to create and destroy a VG"""
b3f87c
 
b3f87c
@@ -406,6 +420,7 @@ class LvmTestVGcreateRemove(LvmPVVGTestCase):
b3f87c
         with self.assertRaises(GLib.GError):
b3f87c
             BlockDev.lvm_vgremove("testVG", None)
b3f87c
 
b3f87c
+@unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmTestVGrename(LvmPVVGTestCase):
b3f87c
     def test_vgrename(self):
b3f87c
         """Verify that it is possible to rename a VG"""
b3f87c
@@ -465,7 +480,6 @@ class LvmTestVGactivateDeactivate(LvmPVVGTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmTestVGextendReduce(LvmPVVGTestCase):
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
     def test_vgextend_vgreduce(self):
b3f87c
         """Verify that it is possible to extend/reduce a VG"""
b3f87c
 
b3f87c
@@ -571,6 +585,7 @@ class LvmPVVGLVTestCase(LvmPVVGTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmTestLVcreateRemove(LvmPVVGLVTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_lvcreate_lvremove(self):
b3f87c
         """Verify that it's possible to create/destroy an LV"""
b3f87c
 
b3f87c
@@ -619,6 +634,7 @@ class LvmTestLVcreateRemove(LvmPVVGLVTestCase):
b3f87c
         with self.assertRaises(GLib.GError):
b3f87c
             BlockDev.lvm_lvremove("testVG", "testLV", True, None)
b3f87c
 
b3f87c
+@unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmTestLVcreateWithExtra(LvmPVVGLVTestCase):
b3f87c
     def __init__(self, *args, **kwargs):
b3f87c
         LvmPVVGLVTestCase.__init__(self, *args, **kwargs)
b3f87c
@@ -669,7 +685,6 @@ class LvmTestLVcreateWithExtra(LvmPVVGLVTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmTestLVcreateType(LvmPVVGLVTestCase):
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
     def test_lvcreate_type(self):
b3f87c
         """Verify it's possible to create LVs with various types"""
b3f87c
 
b3f87c
@@ -842,7 +857,7 @@ class LvmTestLVrename(LvmPVVGLVTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmTestLVsnapshots(LvmPVVGLVTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_snapshotcreate_lvorigin_snapshotmerge(self):
b3f87c
         """Verify that LV snapshot support works"""
b3f87c
 
b3f87c
@@ -957,6 +972,7 @@ class LvmTestLVsAll(LvmPVVGthpoolTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmTestThpoolCreate(LvmPVVGthpoolTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_thpoolcreate(self):
b3f87c
         """Verify that it is possible to create a thin pool"""
b3f87c
 
b3f87c
@@ -1056,6 +1072,7 @@ class LvmPVVGLVthLVTestCase(LvmPVVGthpoolTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmTestThLVcreate(LvmPVVGLVthLVTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_thlvcreate_thpoolname(self):
b3f87c
         """Verify that it is possible to create a thin LV and get its pool name"""
b3f87c
 
b3f87c
@@ -1142,8 +1159,7 @@ class LvmPVVGLVcachePoolTestCase(LvmPVVGLVTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmPVVGLVcachePoolCreateRemoveTestCase(LvmPVVGLVcachePoolTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_cache_pool_create_remove(self):
b3f87c
         """Verify that is it possible to create and remove a cache pool"""
b3f87c
 
b3f87c
@@ -1169,8 +1185,7 @@ class LvmPVVGLVcachePoolCreateRemoveTestCase(LvmPVVGLVcachePoolTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmTestCachePoolConvert(LvmPVVGLVcachePoolTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_cache_pool_convert(self):
b3f87c
         """Verify that it is possible to create a cache pool by conversion"""
b3f87c
 
b3f87c
@@ -1193,8 +1208,7 @@ class LvmTestCachePoolConvert(LvmPVVGLVcachePoolTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmPVVGLVcachePoolAttachDetachTestCase(LvmPVVGLVcachePoolTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_cache_pool_attach_detach(self):
b3f87c
         """Verify that is it possible to attach and detach a cache pool"""
b3f87c
 
b3f87c
@@ -1235,8 +1249,7 @@ class LvmPVVGLVcachePoolAttachDetachTestCase(LvmPVVGLVcachePoolTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmPVVGcachedLVTestCase(LvmPVVGLVTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_create_cached_lv(self):
b3f87c
         """Verify that it is possible to create a cached LV in a single step"""
b3f87c
 
b3f87c
@@ -1256,8 +1269,7 @@ class LvmPVVGcachedLVTestCase(LvmPVVGLVTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmPVVGcachedLVpoolTestCase(LvmPVVGLVTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_cache_get_pool_name(self):
b3f87c
         """Verify that it is possible to get the name of the cache pool"""
b3f87c
 
b3f87c
@@ -1283,8 +1295,7 @@ class LvmPVVGcachedLVpoolTestCase(LvmPVVGLVTestCase):
b3f87c
 
b3f87c
 @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running")
b3f87c
 class LvmPVVGcachedLVstatsTestCase(LvmPVVGLVTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_cache_get_stats(self):
b3f87c
         """Verify that it is possible to get stats for a cached LV"""
b3f87c
 
b3f87c
@@ -1323,6 +1334,7 @@ class LVMTechTest(LVMTestCase):
b3f87c
         self.addCleanup(BlockDev.switch_init_checks, True)
b3f87c
         self.addCleanup(BlockDev.reinit, [self.ps, self.ps2], True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_tech_available(self):
b3f87c
         """Verify that checking lvm dbus availability by technology works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/lvm_test.py b/tests/lvm_test.py
b3f87c
index 4f1640f..28a4b05 100644
b3f87c
--- a/tests/lvm_test.py
b3f87c
+++ b/tests/lvm_test.py
b3f87c
@@ -7,7 +7,7 @@ import six
b3f87c
 import re
b3f87c
 import subprocess
b3f87c
 
b3f87c
-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, skip_on
b3f87c
+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, skip_on, TestTags, tag_test
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
 
b3f87c
@@ -27,6 +27,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         super(LvmNoDevTestCase, self).__init__(*args, **kwargs)
b3f87c
         self._log = ""
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_is_supported_pe_size(self):
b3f87c
         """Verify that lvm_is_supported_pe_size works as expected"""
b3f87c
 
b3f87c
@@ -42,12 +43,14 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertFalse(BlockDev.lvm_is_supported_pe_size(65535))
b3f87c
         self.assertFalse(BlockDev.lvm_is_supported_pe_size(32 * 1024**3))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_supported_pe_sizes(self):
b3f87c
         """Verify that supported PE sizes are really supported"""
b3f87c
 
b3f87c
         for size in BlockDev.lvm_get_supported_pe_sizes():
b3f87c
             self.assertTrue(BlockDev.lvm_is_supported_pe_size(size))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_max_lv_size(self):
b3f87c
         """Verify that max LV size is correctly determined"""
b3f87c
 
b3f87c
@@ -60,6 +63,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
 
b3f87c
         self.assertEqual(BlockDev.lvm_get_max_lv_size(), expected)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_round_size_to_pe(self):
b3f87c
         """Verify that round_size_to_pe works as expected"""
b3f87c
 
b3f87c
@@ -84,6 +88,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_round_size_to_pe(biggest_multiple - (2 * 4 * 1024**2) + 1, 4 * 1024**2, False),
b3f87c
                          biggest_multiple - (2 * 4 * 1024**2))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_lv_physical_size(self):
b3f87c
         """Verify that get_lv_physical_size works as expected"""
b3f87c
 
b3f87c
@@ -97,6 +102,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_get_lv_physical_size(11 * 1024**2, 4 * 1024**2),
b3f87c
                          12 * 1024**2)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_thpool_padding(self):
b3f87c
         """Verify that get_thpool_padding works as expected"""
b3f87c
 
b3f87c
@@ -110,6 +116,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_get_thpool_padding(11 * 1024**2, 4 * 1024**2, True),
b3f87c
                          expected_padding)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_thpool_meta_size(self):
b3f87c
         """Verify that getting recommended thin pool metadata size works as expected"""
b3f87c
 
b3f87c
@@ -128,6 +135,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_get_thpool_meta_size (100 * 1024**2, 128 * 1024, 100),
b3f87c
                          BlockDev.LVM_MIN_THPOOL_MD_SIZE)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_is_valid_thpool_md_size(self):
b3f87c
         """Verify that is_valid_thpool_md_size works as expected"""
b3f87c
 
b3f87c
@@ -138,6 +146,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(1 * 1024**2))
b3f87c
         self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(17 * 1024**3))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_is_valid_thpool_chunk_size(self):
b3f87c
         """Verify that is_valid_thpool_chunk_size works as expected"""
b3f87c
 
b3f87c
@@ -156,6 +165,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
     def _store_log(self, lvl, msg):
b3f87c
         self._log += str((lvl, msg))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_set_global_config(self):
b3f87c
         """Verify that getting and setting global config works as expected"""
b3f87c
 
b3f87c
@@ -192,6 +202,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         succ = BlockDev.lvm_set_global_config(None)
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_cache_get_default_md_size(self):
b3f87c
         """Verify that default cache metadata size is calculated properly"""
b3f87c
 
b3f87c
@@ -200,6 +211,7 @@ class LvmNoDevTestCase(LVMTestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_cache_get_default_md_size(80 * 1024**3), (80 * 1024**3) // 1000)
b3f87c
         self.assertEqual(BlockDev.lvm_cache_get_default_md_size(6 * 1024**3), 8 * 1024**2)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_cache_mode_bijection(self):
b3f87c
         """Verify that cache modes and their string representations map to each other"""
b3f87c
 
b3f87c
@@ -258,6 +270,7 @@ class LvmPVonlyTestCase(LVMTestCase):
b3f87c
         os.unlink(self.dev_file2)
b3f87c
 
b3f87c
 class LvmTestPVcreateRemove(LvmPVonlyTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_pvcreate_and_pvremove(self):
b3f87c
         """Verify that it's possible to create and destroy a PV"""
b3f87c
 
b3f87c
@@ -357,7 +370,8 @@ class LvmPVVGTestCase(LvmPVonlyTestCase):
b3f87c
         LvmPVonlyTestCase._clean_up(self)
b3f87c
 
b3f87c
 class LvmTestVGcreateRemove(LvmPVVGTestCase):
b3f87c
-    @skip_on("debian", skip_on_arch="i686", reason="vgremove is broken on 32bit Debian")
b3f87c
+    @skip_on("debian", skip_on_version="9", skip_on_arch="i686", reason="vgremove is broken on 32bit Debian stable")
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_vgcreate_vgremove(self):
b3f87c
         """Verify that it is possible to create and destroy a VG"""
b3f87c
 
b3f87c
@@ -543,6 +557,7 @@ class LvmPVVGLVTestCase(LvmPVVGTestCase):
b3f87c
         LvmPVVGTestCase._clean_up(self)
b3f87c
 
b3f87c
 class LvmTestLVcreateRemove(LvmPVVGLVTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_lvcreate_lvremove(self):
b3f87c
         """Verify that it's possible to create/destroy an LV"""
b3f87c
 
b3f87c
@@ -810,7 +825,7 @@ class LvmTestLVrename(LvmPVVGLVTestCase):
b3f87c
             BlockDev.lvm_lvrename("testVG", "testLV", "testLV", None)
b3f87c
 
b3f87c
 class LvmTestLVsnapshots(LvmPVVGLVTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_snapshotcreate_lvorigin_snapshotmerge(self):
b3f87c
         """Verify that LV snapshot support works"""
b3f87c
 
b3f87c
@@ -920,6 +935,7 @@ class LvmTestLVsAll(LvmPVVGthpoolTestCase):
b3f87c
         self.assertGreater(len(lvs), 3)
b3f87c
 
b3f87c
 class LvmTestThpoolCreate(LvmPVVGthpoolTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_thpoolcreate(self):
b3f87c
         """Verify that it is possible to create a thin pool"""
b3f87c
 
b3f87c
@@ -1016,6 +1032,7 @@ class LvmPVVGLVthLVTestCase(LvmPVVGthpoolTestCase):
b3f87c
         LvmPVVGthpoolTestCase._clean_up(self)
b3f87c
 
b3f87c
 class LvmTestThLVcreate(LvmPVVGLVthLVTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_thlvcreate_thpoolname(self):
b3f87c
         """Verify that it is possible to create a thin LV and get its pool name"""
b3f87c
 
b3f87c
@@ -1098,8 +1115,7 @@ class LvmPVVGLVcachePoolTestCase(LvmPVVGLVTestCase):
b3f87c
         LvmPVVGLVTestCase._clean_up(self)
b3f87c
 
b3f87c
 class LvmPVVGLVcachePoolCreateRemoveTestCase(LvmPVVGLVcachePoolTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     @skip_on(("centos", "enterprise_linux"), "7")
b3f87c
     def test_cache_pool_create_remove(self):
b3f87c
         """Verify that is it possible to create and remove a cache pool"""
b3f87c
@@ -1125,8 +1141,7 @@ class LvmPVVGLVcachePoolCreateRemoveTestCase(LvmPVVGLVcachePoolTestCase):
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
 class LvmTestCachePoolConvert(LvmPVVGLVcachePoolTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_cache_pool_convert(self):
b3f87c
         """Verify that it is possible to create a cache pool by conversion"""
b3f87c
 
b3f87c
@@ -1149,8 +1164,7 @@ class LvmTestCachePoolConvert(LvmPVVGLVcachePoolTestCase):
b3f87c
 
b3f87c
 
b3f87c
 class LvmPVVGLVcachePoolAttachDetachTestCase(LvmPVVGLVcachePoolTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_cache_pool_attach_detach(self):
b3f87c
         """Verify that is it possible to attach and detach a cache pool"""
b3f87c
 
b3f87c
@@ -1190,8 +1204,7 @@ class LvmPVVGLVcachePoolAttachDetachTestCase(LvmPVVGLVcachePoolTestCase):
b3f87c
         self.assertTrue(any(info.lv_name == "testCache" for info in lvs))
b3f87c
 
b3f87c
 class LvmPVVGcachedLVTestCase(LvmPVVGLVTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_create_cached_lv(self):
b3f87c
         """Verify that it is possible to create a cached LV in a single step"""
b3f87c
 
b3f87c
@@ -1210,8 +1223,7 @@ class LvmPVVGcachedLVTestCase(LvmPVVGLVTestCase):
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
 class LvmPVVGcachedLVpoolTestCase(LvmPVVGLVTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_cache_get_pool_name(self):
b3f87c
         """Verify that it is possible to get the name of the cache pool"""
b3f87c
 
b3f87c
@@ -1236,8 +1248,7 @@ class LvmPVVGcachedLVpoolTestCase(LvmPVVGLVTestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_cache_pool_name("testVG", "testLV"), "testCache")
b3f87c
 
b3f87c
 class LvmPVVGcachedLVstatsTestCase(LvmPVVGLVTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @skip_on("fedora", "27", reason="LVM is broken in many ways on rawhide")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_cache_get_stats(self):
b3f87c
         """Verify that it is possible to get stats for a cached LV"""
b3f87c
 
b3f87c
@@ -1271,6 +1282,7 @@ class LVMUnloadTest(LVMTestCase):
b3f87c
         # tests
b3f87c
         self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_low_version(self):
b3f87c
         """Verify that checking the minimum LVM version works as expected"""
b3f87c
 
b3f87c
@@ -1288,6 +1300,7 @@ class LVMUnloadTest(LVMTestCase):
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
         self.assertIn("lvm", BlockDev.get_available_plugin_names())
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_no_lvm(self):
b3f87c
         """Verify that checking lvm tool availability works as expected"""
b3f87c
 
b3f87c
@@ -1315,6 +1328,7 @@ class LVMTechTest(LVMTestCase):
b3f87c
         self.addCleanup(BlockDev.switch_init_checks, True)
b3f87c
         self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_tech_available(self):
b3f87c
         """Verify that checking lvm tool availability by technology works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/mdraid_test.py b/tests/mdraid_test.py
b3f87c
index ea182b2..ea489db 100644
b3f87c
--- a/tests/mdraid_test.py
b3f87c
+++ b/tests/mdraid_test.py
b3f87c
@@ -6,7 +6,7 @@ from contextlib import contextmanager
b3f87c
 import overrides_hack
b3f87c
 import six
b3f87c
 
b3f87c
-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path
b3f87c
+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, skip_on, TestTags, tag_test
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
 
b3f87c
@@ -46,6 +46,7 @@ class MDNoDevTestCase(MDTest):
b3f87c
         else:
b3f87c
             BlockDev.reinit(cls.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_superblock_size(self):
b3f87c
         """Verify that superblock size si calculated properly"""
b3f87c
 
b3f87c
@@ -67,6 +68,7 @@ class MDNoDevTestCase(MDTest):
b3f87c
         self.assertEqual(BlockDev.md_get_superblock_size(257 * 1024**2, version="unknown version"),
b3f87c
                          2 * 1024**2)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_canonicalize_uuid(self):
b3f87c
         """Verify that UUID canonicalization works as expected"""
b3f87c
 
b3f87c
@@ -76,6 +78,7 @@ class MDNoDevTestCase(MDTest):
b3f87c
         with six.assertRaisesRegex(self, GLib.GError, r'malformed or invalid'):
b3f87c
             BlockDev.md_canonicalize_uuid("malformed-uuid-example")
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_get_md_uuid(self):
b3f87c
         """Verify that getting UUID in MD RAID format works as expected"""
b3f87c
 
b3f87c
@@ -162,7 +165,7 @@ class MDTestCase(MDTest):
b3f87c
 
b3f87c
 
b3f87c
 class MDTestCreateDeactivateDestroy(MDTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
     def test_create_deactivate_destroy(self):
b3f87c
         """Verify that it is possible to create, deactivate and destroy an MD RAID"""
b3f87c
 
b3f87c
@@ -192,7 +195,7 @@ class MDTestCreateDeactivateDestroy(MDTestCase):
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
 class MDTestCreateWithChunkSize(MDTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_create_with_chunk_size(self):
b3f87c
         """Verify that it is possible to create and MD RAID with specific chunk size """
b3f87c
 
b3f87c
@@ -216,7 +219,7 @@ class MDTestCreateWithChunkSize(MDTestCase):
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
 class MDTestActivateDeactivate(MDTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
     def test_activate_deactivate(self):
b3f87c
         """Verify that it is possible to activate and deactivate an MD RAID"""
b3f87c
 
b3f87c
@@ -255,7 +258,7 @@ class MDTestActivateDeactivate(MDTestCase):
b3f87c
             self.assertTrue(succ)
b3f87c
 
b3f87c
 class MDTestActivateWithUUID(MDTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_activate_with_uuid(self):
b3f87c
         """Verify that it is possible to activate an MD RAID with UUID"""
b3f87c
 
b3f87c
@@ -277,7 +280,7 @@ class MDTestActivateWithUUID(MDTestCase):
b3f87c
             succ = BlockDev.md_activate("bd_test_md", [self.loop_dev, self.loop_dev2, self.loop_dev3], md_info.uuid)
b3f87c
 
b3f87c
 class MDTestActivateByUUID(MDTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_activate_by_uuid(self):
b3f87c
         """Verify that it is possible to activate an MD RAID by UUID"""
b3f87c
 
b3f87c
@@ -309,7 +312,7 @@ class MDTestActivateByUUID(MDTestCase):
b3f87c
 
b3f87c
 
b3f87c
 class MDTestNominateDenominate(MDTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_nominate_denominate(self):
b3f87c
         """Verify that it is possible to nominate and denominate an MD RAID device"""
b3f87c
 
b3f87c
@@ -342,9 +345,7 @@ class MDTestNominateDenominate(MDTestCase):
b3f87c
 class MDTestNominateDenominateActive(MDTestCase):
b3f87c
     # slow and leaking an MD array because with a nominated spare device, it
b3f87c
     # cannot be deactivated in the end (don't ask me why)
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
-    @unittest.skipIf("JENKINS_HOME" in os.environ, "skipping leaky test in jenkins")
b3f87c
-    @unittest.skipUnless("FEELINGLUCKY" in os.environ, "skipping, not feeling lucky")
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.UNSAFE, TestTags.UNSTABLE)
b3f87c
     def test_nominate_denominate_active(self):
b3f87c
         """Verify that nominate and denominate deivice works as expected on (de)activated MD RAID"""
b3f87c
 
b3f87c
@@ -371,7 +372,8 @@ class MDTestNominateDenominateActive(MDTestCase):
b3f87c
             self.assertTrue(succ)
b3f87c
 
b3f87c
 class MDTestAddRemove(MDTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
+    @skip_on("debian", reason="Removing spare disks from an array is broken on Debian")
b3f87c
     def test_add_remove(self):
b3f87c
         """Verify that it is possible to add a device to and remove from an MD RAID"""
b3f87c
 
b3f87c
@@ -431,7 +433,7 @@ class MDTestAddRemove(MDTestCase):
b3f87c
 
b3f87c
 class MDTestExamineDetail(MDTestCase):
b3f87c
     # sleeps to let MD RAID sync things
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_examine_detail(self):
b3f87c
         """Verify that it is possible to get info about an MD RAID"""
b3f87c
 
b3f87c
@@ -487,7 +489,7 @@ class MDTestExamineDetail(MDTestCase):
b3f87c
         self.assertTrue(de_data)
b3f87c
 
b3f87c
 class MDTestNameNodeBijection(MDTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_name_node_bijection(self):
b3f87c
         """Verify that MD RAID node and name match each other"""
b3f87c
 
b3f87c
@@ -518,7 +520,7 @@ class MDTestNameNodeBijection(MDTestCase):
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
 class MDTestSetBitmapLocation(MDTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_set_bitmap_location(self):
b3f87c
         """Verify we can change bitmap location for an existing MD array"""
b3f87c
 
b3f87c
@@ -567,7 +569,7 @@ class MDTestSetBitmapLocation(MDTestCase):
b3f87c
 
b3f87c
 
b3f87c
 class MDTestRequestSyncAction(MDTestCase):
b3f87c
-    @unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_request_sync_action(self):
b3f87c
         """Verify we can request sync action on an existing MD array"""
b3f87c
 
b3f87c
@@ -587,6 +589,7 @@ class MDTestRequestSyncAction(MDTestCase):
b3f87c
 
b3f87c
 class FakeMDADMutilTest(MDTest):
b3f87c
     # no setUp nor tearDown needed, we are gonna use fake utils
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_fw_raid_uppercase_examine(self):
b3f87c
         """Verify that md_examine works with output using "RAID" instead of "Raid" and other quirks """
b3f87c
 
b3f87c
@@ -598,6 +601,7 @@ class FakeMDADMutilTest(MDTest):
b3f87c
         self.assertEqual(ex_data.uuid, "b42756a2-37e4-3e47-674b-d1dd6e822145")
b3f87c
         self.assertEqual(ex_data.device, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_no_metadata_examine(self):
b3f87c
         """Verify that md_examine works as expected with no metadata spec"""
b3f87c
 
b3f87c
@@ -607,6 +611,7 @@ class FakeMDADMutilTest(MDTest):
b3f87c
 
b3f87c
         self.assertIs(ex_data.metadata, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_fw_raid_migrating(self):
b3f87c
         """Verify that md_examine works when array is migrating ("foo <-- bar" values in output) """
b3f87c
 
b3f87c
@@ -615,6 +620,7 @@ class FakeMDADMutilTest(MDTest):
b3f87c
 
b3f87c
         self.assertEqual(ex_data.chunk_size, 128 * 1024)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_mdadm_name_extra_info(self):
b3f87c
         """Verify that md_examine and md_detail work with extra MD RAID name info"""
b3f87c
 
b3f87c
@@ -632,6 +638,7 @@ class MDUnloadTest(MDTestCase):
b3f87c
         # tests
b3f87c
         self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_low_version(self):
b3f87c
         """Verify that checking the minimum mdsetup version works as expected"""
b3f87c
 
b3f87c
@@ -649,6 +656,7 @@ class MDUnloadTest(MDTestCase):
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
         self.assertIn("mdraid", BlockDev.get_available_plugin_names())
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_no_md(self):
b3f87c
         """Verify that checking mdsetup tool availability works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/mpath_test.py b/tests/mpath_test.py
b3f87c
index e9d1e42..acd3053 100644
b3f87c
--- a/tests/mpath_test.py
b3f87c
+++ b/tests/mpath_test.py
b3f87c
@@ -2,7 +2,7 @@ import unittest
b3f87c
 import os
b3f87c
 import overrides_hack
b3f87c
 
b3f87c
-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, skip_on, get_version
b3f87c
+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, skip_on, get_version, TestTags, tag_test
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
 class MpathTest(unittest.TestCase):
b3f87c
@@ -56,6 +56,7 @@ class MpathUnloadTest(MpathTest):
b3f87c
         # tests
b3f87c
         self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_low_version(self):
b3f87c
         """Verify that checking the minimum dmsetup version works as expected"""
b3f87c
 
b3f87c
@@ -74,6 +75,7 @@ class MpathUnloadTest(MpathTest):
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
         self.assertIn("mpath", BlockDev.get_available_plugin_names())
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_no_multipath(self):
b3f87c
         """Verify that checking multipath tool availability works as expected"""
b3f87c
 
b3f87c
@@ -91,6 +93,7 @@ class MpathUnloadTest(MpathTest):
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
         self.assertIn("mpath", BlockDev.get_available_plugin_names())
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_no_mpathconf(self):
b3f87c
         """Verify that checking mpathconf tool availability works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/nvdimm_test.py b/tests/nvdimm_test.py
b3f87c
index a4e6854..1c2fb3c 100644
b3f87c
--- a/tests/nvdimm_test.py
b3f87c
+++ b/tests/nvdimm_test.py
b3f87c
@@ -6,7 +6,7 @@ import overrides_hack
b3f87c
 
b3f87c
 from distutils.version import LooseVersion
b3f87c
 
b3f87c
-from utils import run_command, read_file, skip_on, fake_path
b3f87c
+from utils import run_command, read_file, skip_on, fake_path, TestTags, tag_test
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
 
b3f87c
@@ -80,6 +80,7 @@ class NVDIMMNamespaceTestCase(NVDIMMTestCase):
b3f87c
             # even for modes where sector size doesn't make sense
b3f87c
             self.assertEqual(bd_info.sector_size, 512)
b3f87c
 
b3f87c
+    @tag_test(TestTags.EXTRADEPS, TestTags.CORE)
b3f87c
     def test_namespace_info(self):
b3f87c
         # get info about our 'testing' namespace
b3f87c
         info = BlockDev.nvdimm_namespace_info(self.sys_info["dev"])
b3f87c
@@ -96,14 +97,15 @@ class NVDIMMNamespaceTestCase(NVDIMMTestCase):
b3f87c
         info = BlockDev.nvdimm_namespace_info("definitely-not-a-namespace")
b3f87c
         self.assertIsNone(info)
b3f87c
 
b3f87c
+    @tag_test(TestTags.EXTRADEPS, TestTags.CORE)
b3f87c
     def test_list_namespaces(self):
b3f87c
         bd_namespaces = BlockDev.nvdimm_list_namespaces()
b3f87c
         self.assertEqual(len(bd_namespaces), 1)
b3f87c
 
b3f87c
         self._check_namespace_info(bd_namespaces[0])
b3f87c
 
b3f87c
-    @unittest.skipUnless("JENKINS_HOME" in os.environ, "skipping test that modifies system configuration")
b3f87c
     @skip_on("fedora", "29", reason="Disabling is broken on rawhide and makes the 'fake' NVDIMM unusable.")
b3f87c
+    @tag_test(TestTags.EXTRADEPS, TestTags.UNSAFE)
b3f87c
     def test_enable_disable(self):
b3f87c
         # non-existing/unknow namespace
b3f87c
         with self.assertRaises(GLib.GError):
b3f87c
@@ -130,8 +132,8 @@ class NVDIMMNamespaceTestCase(NVDIMMTestCase):
b3f87c
         info = BlockDev.nvdimm_namespace_info(self.sys_info["dev"])
b3f87c
         self.assertTrue(info.enabled)
b3f87c
 
b3f87c
-    @unittest.skipUnless("JENKINS_HOME" in os.environ, "skipping test that modifies system configuration")
b3f87c
     @skip_on("fedora", "29", reason="Disabling is broken on rawhide and makes the 'fake' NVDIMM unusable.")
b3f87c
+    @tag_test(TestTags.EXTRADEPS, TestTags.UNSAFE)
b3f87c
     def test_namespace_reconfigure(self):
b3f87c
         # active namespace -- reconfigure doesn't work without force
b3f87c
         with self.assertRaises(GLib.GError):
b3f87c
@@ -188,6 +190,7 @@ class NVDIMMUnloadTest(NVDIMMTestCase):
b3f87c
         # tests
b3f87c
         self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_no_ndctl(self):
b3f87c
         """Verify that checking ndctl tool availability works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/overrides_test.py b/tests/overrides_test.py
b3f87c
index 53c65b5..8e7f5a5 100644
b3f87c
--- a/tests/overrides_test.py
b3f87c
+++ b/tests/overrides_test.py
b3f87c
@@ -3,6 +3,8 @@ import math
b3f87c
 import overrides_hack
b3f87c
 from gi.repository import BlockDev
b3f87c
 
b3f87c
+from utils import TestTags, tag_test
b3f87c
+
b3f87c
 
b3f87c
 class OverridesTest(unittest.TestCase):
b3f87c
     # all plugins except for 'btrfs', 'fs' and 'mpath' -- these don't have all
b3f87c
@@ -19,6 +21,7 @@ class OverridesTest(unittest.TestCase):
b3f87c
             BlockDev.reinit(cls.requested_plugins, True, None)
b3f87c
 
b3f87c
 class OverridesTestCase(OverridesTest):
b3f87c
+    @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
b3f87c
     def test_error_proxy(self):
b3f87c
         """Verify that the error proxy works as expected"""
b3f87c
 
b3f87c
@@ -68,6 +71,7 @@ class OverridesUnloadTestCase(OverridesTest):
b3f87c
         # tests
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
b3f87c
     def test_xrules(self):
b3f87c
         """Verify that regexp-based transformation rules work as expected"""
b3f87c
 
b3f87c
@@ -81,6 +85,7 @@ class OverridesUnloadTestCase(OverridesTest):
b3f87c
         # load the plugins back
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
b3f87c
     def test_exception_inheritance(self):
b3f87c
         # unload all plugins first
b3f87c
         self.assertTrue(BlockDev.reinit([], True, None))
b3f87c
diff --git a/tests/part_test.py b/tests/part_test.py
b3f87c
index adbaa9a..9e58cc6 100644
b3f87c
--- a/tests/part_test.py
b3f87c
+++ b/tests/part_test.py
b3f87c
@@ -1,6 +1,6 @@
b3f87c
 import unittest
b3f87c
 import os
b3f87c
-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, skip_on
b3f87c
+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, skip_on, TestTags, tag_test
b3f87c
 import overrides_hack
b3f87c
 
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
@@ -46,6 +46,7 @@ class PartTestCase(unittest.TestCase):
b3f87c
         os.unlink(self.dev_file2)
b3f87c
 
b3f87c
 class PartCreateTableCase(PartTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_create_table(self):
b3f87c
         """Verify that it is possible to create a new partition table"""
b3f87c
 
b3f87c
@@ -78,6 +79,7 @@ class PartCreateTableCase(PartTestCase):
b3f87c
 
b3f87c
 
b3f87c
 class PartGetDiskSpecCase(PartTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_get_disk_spec(self):
b3f87c
         """Verify that it is possible to get information about disk"""
b3f87c
 
b3f87c
@@ -115,6 +117,7 @@ class PartGetDiskSpecCase(PartTestCase):
b3f87c
         self.assertEqual(ps.flags, 0)
b3f87c
 
b3f87c
 class PartCreatePartCase(PartTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_create_part_simple(self):
b3f87c
         """Verify that it is possible to create a parition"""
b3f87c
 
b3f87c
@@ -221,6 +224,7 @@ class PartCreatePartCase(PartTestCase):
b3f87c
         self.assertEqual(ps.flags, ps3.flags)
b3f87c
 
b3f87c
 class PartCreatePartFullCase(PartTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_full_device_partition(self):
b3f87c
         # we first need a partition table
b3f87c
         succ = BlockDev.part_create_table (self.loop_dev, BlockDev.PartTableType.GPT, True)
b3f87c
@@ -362,6 +366,7 @@ class PartCreatePartFullCase(PartTestCase):
b3f87c
             BlockDev.part_create_part (self.loop_dev, BlockDev.PartTypeReq.EXTENDED, ps4.start + ps4.size + 1,
b3f87c
                                        10 * 1024**2, BlockDev.PartAlign.OPTIMAL)
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_create_part_with_extended_logical(self):
b3f87c
         """Verify that partition creation works as expected with primary, extended and logical parts"""
b3f87c
 
b3f87c
@@ -502,6 +507,7 @@ class PartCreatePartFullCase(PartTestCase):
b3f87c
             BlockDev.part_create_part (self.loop_dev, BlockDev.PartTypeReq.LOGICAL, ps3.start + ps3.size + 1,
b3f87c
                                          10 * 1024**2, BlockDev.PartAlign.OPTIMAL)
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_create_part_next(self):
b3f87c
         """Verify that partition creation works as expected with the NEXT (auto) type"""
b3f87c
 
b3f87c
@@ -589,6 +595,7 @@ class PartCreatePartFullCase(PartTestCase):
b3f87c
             BlockDev.part_create_part (self.loop_dev, BlockDev.PartTypeReq.EXTENDED, ps4.start + ps4.size + 1,
b3f87c
                                        10 * 1024**2, BlockDev.PartAlign.OPTIMAL)
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_create_part_next_gpt(self):
b3f87c
         """Verify that partition creation works as expected with the NEXT (auto) type on GPT"""
b3f87c
 
b3f87c
@@ -664,6 +671,7 @@ class PartGetDiskPartsCase(PartTestCase):
b3f87c
 class PartGetDiskFreeRegions(PartTestCase):
b3f87c
     @skip_on(("centos", "enterprise_linux"), "7", reason="libparted provides weird values here")
b3f87c
     @skip_on("debian", reason="libparted provides weird values here")
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_get_disk_free_regions(self):
b3f87c
         """Verify that it is possible to get info about free regions on a disk"""
b3f87c
 
b3f87c
@@ -1057,6 +1065,7 @@ class PartCreateResizePartCase(PartTestCase):
b3f87c
         self.assertGreaterEqual(ps.size, initial_size) # at least the requested size
b3f87c
 
b3f87c
 class PartCreateDeletePartCase(PartTestCase):
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_create_delete_part_simple(self):
b3f87c
         """Verify that it is possible to create and delete a parition"""
b3f87c
 
b3f87c
diff --git a/tests/s390_test.py b/tests/s390_test.py
b3f87c
index 98c6b1b..da23a55 100644
b3f87c
--- a/tests/s390_test.py
b3f87c
+++ b/tests/s390_test.py
b3f87c
@@ -2,7 +2,7 @@ import unittest
b3f87c
 import os
b3f87c
 import overrides_hack
b3f87c
 
b3f87c
-from utils import fake_path
b3f87c
+from utils import fake_path, TestTags, tag_test
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
 @unittest.skipUnless(os.uname()[4].startswith('s390'), "s390x architecture required")
b3f87c
@@ -18,6 +18,7 @@ class S390TestCase(unittest.TestCase):
b3f87c
         else:
b3f87c
             BlockDev.reinit(cls.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.EXTRADEPS, TestTags.NOSTORAGE)
b3f87c
     def test_device_input(self):
b3f87c
         """Verify that s390_sanitize_dev_input works as expected"""
b3f87c
         dev = "1234"
b3f87c
@@ -42,6 +43,7 @@ class S390TestCase(unittest.TestCase):
b3f87c
         dev = "0.0.abcdefgh"
b3f87c
         self.assertEqual(BlockDev.s390_sanitize_dev_input(dev), dev)
b3f87c
 
b3f87c
+    @tag_test(TestTags.EXTRADEPS, TestTags.NOSTORAGE)
b3f87c
     def test_wwpn_input(self):
b3f87c
         """Verify that s390_zfcp_sanitize_wwpn_input works as expected"""
b3f87c
         # missing "0x" from beginning of wwpn; this should be added by fx
b3f87c
@@ -56,6 +58,7 @@ class S390TestCase(unittest.TestCase):
b3f87c
         with self.assertRaises(GLib.GError):
b3f87c
             BlockDev.s390_zfcp_sanitize_wwpn_input(wwpn)
b3f87c
 
b3f87c
+    @tag_test(TestTags.EXTRADEPS, TestTags.NOSTORAGE)
b3f87c
     def test_lun_input(self):
b3f87c
         """Verify that s390_zfcp_sanitize_lun_input works as expected"""
b3f87c
         # user does not prepend lun with "0x"; this should get added
b3f87c
@@ -91,6 +94,7 @@ class S390UnloadTest(unittest.TestCase):
b3f87c
         else:
b3f87c
             BlockDev.reinit(cls.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.EXTRADEPS, TestTags.NOSTORAGE)
b3f87c
     def test_check_no_dasdfmt(self):
b3f87c
         """Verify that checking dasdfmt tool availability works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/swap_test.py b/tests/swap_test.py
b3f87c
index 05d0c19..66b5eb2 100644
b3f87c
--- a/tests/swap_test.py
b3f87c
+++ b/tests/swap_test.py
b3f87c
@@ -2,7 +2,7 @@ import unittest
b3f87c
 import os
b3f87c
 import overrides_hack
b3f87c
 
b3f87c
-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, run_command
b3f87c
+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, run_command, run, TestTags, tag_test
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
 
b3f87c
@@ -38,6 +38,7 @@ class SwapTestCase(SwapTest):
b3f87c
             pass
b3f87c
         os.unlink(self.dev_file)
b3f87c
 
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_all(self):
b3f87c
         """Verify that swap_* functions work as expected"""
b3f87c
 
b3f87c
@@ -103,6 +104,7 @@ class SwapUnloadTest(SwapTest):
b3f87c
         # tests
b3f87c
         self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_low_version(self):
b3f87c
         """Verify that checking the minimum swap utils versions works as expected"""
b3f87c
 
b3f87c
@@ -120,6 +122,7 @@ class SwapUnloadTest(SwapTest):
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
         self.assertIn("swap", BlockDev.get_available_plugin_names())
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_no_mkswap(self):
b3f87c
         """Verify that checking mkswap and swaplabel tools availability
b3f87c
            works as expected
b3f87c
@@ -146,6 +149,7 @@ class SwapUnloadTest(SwapTest):
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
         self.assertIn("swap", BlockDev.get_available_plugin_names())
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_no_mkswap_runtime(self):
b3f87c
         """Verify that runtime checking mkswap tool availability works as expected"""
b3f87c
 
b3f87c
@@ -172,6 +176,7 @@ class SwapTechAvailable(SwapTest):
b3f87c
         self.addCleanup(BlockDev.switch_init_checks, True)
b3f87c
         self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_tech_available(self):
b3f87c
         """Verify that runtime checking mkswap and swaplabel tools availability
b3f87c
            works as expected
b3f87c
diff --git a/tests/utils_test.py b/tests/utils_test.py
b3f87c
index 02b0203..66d8a32 100644
b3f87c
--- a/tests/utils_test.py
b3f87c
+++ b/tests/utils_test.py
b3f87c
@@ -2,7 +2,7 @@ import unittest
b3f87c
 import re
b3f87c
 import os
b3f87c
 import overrides_hack
b3f87c
-from utils import fake_utils, create_sparse_tempfile, create_lio_device, delete_lio_device, run_command
b3f87c
+from utils import fake_utils, create_sparse_tempfile, create_lio_device, delete_lio_device, run_command, TestTags, tag_test
b3f87c
 
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
@@ -25,6 +25,7 @@ class UtilsExecProgressTest(UtilsTestCase):
b3f87c
         self.assertTrue(isinstance(completion, int))
b3f87c
         self.log.append(completion)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
b3f87c
     def test_initialization(self):
b3f87c
         """ Verify that progress report can (de)initialized"""
b3f87c
 
b3f87c
@@ -54,6 +55,7 @@ class UtilsExecLoggingTest(UtilsTestCase):
b3f87c
 
b3f87c
         self.log += msg + "\n"
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
b3f87c
     def test_logging(self):
b3f87c
         """Verify that setting up and using exec logging works as expected"""
b3f87c
 
b3f87c
@@ -91,6 +93,7 @@ class UtilsExecLoggingTest(UtilsTestCase):
b3f87c
         self.assertTrue(succ)
b3f87c
         self.assertEqual(old_log, self.log)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
b3f87c
     def test_version_cmp(self):
b3f87c
         """Verify that version comparison works as expected"""
b3f87c
 
b3f87c
@@ -124,6 +127,7 @@ class UtilsExecLoggingTest(UtilsTestCase):
b3f87c
         self.assertEqual(BlockDev.utils_version_cmp("1.1.1", "1.1.1-1"), -1)
b3f87c
         self.assertEqual(BlockDev.utils_version_cmp("1.1.2", "1.2"), -1)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
b3f87c
     def test_util_version(self):
b3f87c
         """Verify that checking utility availability works as expected"""
b3f87c
 
b3f87c
@@ -167,6 +171,7 @@ class UtilsExecLoggingTest(UtilsTestCase):
b3f87c
             self.assertTrue(BlockDev.utils_check_util_version("libblockdev-fake-util-fail", "1.1", "version", "Version:\\s(.*)"))
b3f87c
 
b3f87c
 class UtilsDevUtilsTestCase(UtilsTestCase):
b3f87c
+    @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
b3f87c
     def test_resolve_device(self):
b3f87c
         """Verify that resolving device spec works as expected"""
b3f87c
 
b3f87c
@@ -199,6 +204,7 @@ class UtilsDevUtilsTestCase(UtilsTestCase):
b3f87c
         self.assertEqual(BlockDev.utils_resolve_device(dev_link[5:]), dev)
b3f87c
 
b3f87c
 class UtilsDevUtilsTestCase(UtilsTestCase):
b3f87c
+    @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
b3f87c
     def test_resolve_device(self):
b3f87c
         """Verify that resolving device spec works as expected"""
b3f87c
 
b3f87c
@@ -248,7 +254,7 @@ class UtilsDevUtilsSymlinksTestCase(UtilsTestCase):
b3f87c
             pass
b3f87c
         os.unlink(self.dev_file)
b3f87c
 
b3f87c
-
b3f87c
+    @tag_test(TestTags.CORE)
b3f87c
     def test_get_device_symlinks(self):
b3f87c
         """Verify that getting device symlinks works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/vdo_test.py b/tests/vdo_test.py
b3f87c
index be8103a..f20ccd5 100644
b3f87c
--- a/tests/vdo_test.py
b3f87c
+++ b/tests/vdo_test.py
b3f87c
@@ -6,7 +6,7 @@ import unittest
b3f87c
 import overrides_hack
b3f87c
 import six
b3f87c
 
b3f87c
-from utils import run_command, read_file, skip_on, fake_path, create_sparse_tempfile, create_lio_device, delete_lio_device
b3f87c
+from utils import run_command, read_file, skip_on, fake_path, create_sparse_tempfile, create_lio_device, delete_lio_device, TestTags, tag_test
b3f87c
 from gi.repository import BlockDev, GLib
b3f87c
 from bytesize import bytesize
b3f87c
 from distutils.spawn import find_executable
b3f87c
@@ -48,7 +48,6 @@ class VDOTestCase(unittest.TestCase):
b3f87c
         os.unlink(self.dev_file)
b3f87c
 
b3f87c
 
b3f87c
-@unittest.skipIf("SKIP_SLOW" in os.environ, "skipping slow tests")
b3f87c
 class VDOTest(VDOTestCase):
b3f87c
 
b3f87c
     vdo_name = "bd-test-vdo"
b3f87c
@@ -56,6 +55,7 @@ class VDOTest(VDOTestCase):
b3f87c
     def _remove_vdo(self, name):
b3f87c
         run_command("vdo remove --force -n %s" % name)
b3f87c
 
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
     def test_create_remove(self):
b3f87c
         """Verify that it is possible to create and remove a VDO volume"""
b3f87c
 
b3f87c
@@ -85,6 +85,7 @@ class VDOTest(VDOTestCase):
b3f87c
 
b3f87c
         self.assertFalse(os.path.exists("/dev/mapper/%s" % self.vdo_name))
b3f87c
 
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_enable_disable_compression(self):
b3f87c
         """Verify that it is possible to enable/disable compression on an existing VDO volume"""
b3f87c
 
b3f87c
@@ -110,6 +111,7 @@ class VDOTest(VDOTestCase):
b3f87c
         info = BlockDev.vdo_info(self.vdo_name)
b3f87c
         self.assertTrue(info.compression)
b3f87c
 
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_enable_disable_deduplication(self):
b3f87c
         """Verify that it is possible to enable/disable deduplication on an existing VDO volume"""
b3f87c
 
b3f87c
@@ -135,6 +137,7 @@ class VDOTest(VDOTestCase):
b3f87c
         info = BlockDev.vdo_info(self.vdo_name)
b3f87c
         self.assertTrue(info.deduplication)
b3f87c
 
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_activate_deactivate(self):
b3f87c
         """Verify that it is possible to activate/deactivate an existing VDO volume"""
b3f87c
 
b3f87c
@@ -172,6 +175,7 @@ class VDOTest(VDOTestCase):
b3f87c
 
b3f87c
         self.assertTrue(os.path.exists("/dev/mapper/%s" % self.vdo_name))
b3f87c
 
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_change_write_policy(self):
b3f87c
 
b3f87c
         ret = BlockDev.vdo_create(self.vdo_name, self.loop_dev, 3 * self.loop_size, 0,
b3f87c
@@ -203,6 +207,7 @@ class VDOTest(VDOTestCase):
b3f87c
 
b3f87c
         return info["VDOs"][name]
b3f87c
 
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
     def test_get_info(self):
b3f87c
         """Verify that it is possible to get information about an existing VDO volume"""
b3f87c
 
b3f87c
@@ -229,6 +234,7 @@ class VDOTest(VDOTestCase):
b3f87c
         self.assertEqual(bd_info.physical_size, bytesize.Size(sys_info["Physical size"]))
b3f87c
         self.assertEqual(bd_info.logical_size, bytesize.Size(sys_info["Logical size"]))
b3f87c
 
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_grow_logical(self):
b3f87c
         """Verify that it is possible to grow logical size of an existing VDO volume"""
b3f87c
 
b3f87c
@@ -249,6 +255,7 @@ class VDOTest(VDOTestCase):
b3f87c
 
b3f87c
         self.assertEqual(info.logical_size, new_size)
b3f87c
 
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.UNSTABLE)
b3f87c
     def test_grow_physical(self):
b3f87c
         """Verify that it is possible to grow physical size of an existing VDO volume"""
b3f87c
 
b3f87c
@@ -284,6 +291,7 @@ class VDOTest(VDOTestCase):
b3f87c
         self.assertEqual(info_before.logical_size, info_after.logical_size)
b3f87c
         self.assertGreater(info_after.physical_size, info_before.physical_size)
b3f87c
 
b3f87c
+    @tag_test(TestTags.SLOW)
b3f87c
     def test_statistics(self):
b3f87c
         """Verify that it is possible to retrieve statistics of an existing VDO volume"""
b3f87c
 
b3f87c
@@ -311,6 +319,7 @@ class VDOUnloadTest(VDOTestCase):
b3f87c
         # tests
b3f87c
         self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None)
b3f87c
 
b3f87c
+    @tag_test(TestTags.NOSTORAGE)
b3f87c
     def test_check_no_vdo(self):
b3f87c
         """Verify that checking vdo tool availability works as expected"""
b3f87c
 
b3f87c
-- 
b3f87c
2.20.1
b3f87c
b3f87c
b3f87c
From c709805db97621889c4354f9771db47916dbc2e5 Mon Sep 17 00:00:00 2001
b3f87c
From: Vojtech Trefny <vtrefny@redhat.com>
b3f87c
Date: Thu, 4 Apr 2019 10:39:21 +0200
b3f87c
Subject: [PATCH 04/10] Remove duplicate test case
b3f87c
b3f87c
UtilsDevUtilsTestCase was defined twice, probably because of some
b3f87c
copy paste or merging mistake.
b3f87c
---
b3f87c
 tests/utils_test.py | 32 --------------------------------
b3f87c
 1 file changed, 32 deletions(-)
b3f87c
b3f87c
diff --git a/tests/utils_test.py b/tests/utils_test.py
b3f87c
index 66d8a32..e268409 100644
b3f87c
--- a/tests/utils_test.py
b3f87c
+++ b/tests/utils_test.py
b3f87c
@@ -170,38 +170,6 @@ class UtilsExecLoggingTest(UtilsTestCase):
b3f87c
             # exit code != 0
b3f87c
             self.assertTrue(BlockDev.utils_check_util_version("libblockdev-fake-util-fail", "1.1", "version", "Version:\\s(.*)"))
b3f87c
 
b3f87c
-class UtilsDevUtilsTestCase(UtilsTestCase):
b3f87c
-    @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
b3f87c
-    def test_resolve_device(self):
b3f87c
-        """Verify that resolving device spec works as expected"""
b3f87c
-
b3f87c
-        with self.assertRaises(GLib.GError):
b3f87c
-            BlockDev.utils_resolve_device("no_such_device")
b3f87c
-
b3f87c
-        dev = "/dev/libblockdev-test-dev"
b3f87c
-        with open(dev, "w"):
b3f87c
-            pass
b3f87c
-        self.addCleanup(os.unlink, dev)
b3f87c
-
b3f87c
-        # full path, no symlink, should just return the same
b3f87c
-        self.assertEqual(BlockDev.utils_resolve_device(dev), dev)
b3f87c
-
b3f87c
-        # just the name of the device, should return the full path
b3f87c
-        self.assertEqual(BlockDev.utils_resolve_device(dev[5:]), dev)
b3f87c
-
b3f87c
-        dev_dir = "/dev/libblockdev-test-dir"
b3f87c
-        os.mkdir(dev_dir)
b3f87c
-        self.addCleanup(os.rmdir, dev_dir)
b3f87c
-
b3f87c
-        dev_link = dev_dir + "/test-dev-link"
b3f87c
-        os.symlink("../" + dev[5:], dev_link)
b3f87c
-        self.addCleanup(os.unlink, dev_link)
b3f87c
-
b3f87c
-        # should resolve the symlink
b3f87c
-        self.assertEqual(BlockDev.utils_resolve_device(dev_link), dev)
b3f87c
-
b3f87c
-        # should resolve the symlink even without the "/dev" prefix
b3f87c
-        self.assertEqual(BlockDev.utils_resolve_device(dev_link[5:]), dev)
b3f87c
 
b3f87c
 class UtilsDevUtilsTestCase(UtilsTestCase):
b3f87c
     @tag_test(TestTags.NOSTORAGE, TestTags.CORE)
b3f87c
-- 
b3f87c
2.20.1
b3f87c
b3f87c
b3f87c
From 09cee5780854f92b28aaeb7c67ea76c6fc853e30 Mon Sep 17 00:00:00 2001
b3f87c
From: Vojtech Trefny <vtrefny@redhat.com>
b3f87c
Date: Thu, 4 Apr 2019 11:23:12 +0200
b3f87c
Subject: [PATCH 05/10] Allow running tests against installed libblockdev
b3f87c
b3f87c
---
b3f87c
 tests/overrides_hack.py |   5 +-
b3f87c
 tests/run_tests.py      | 106 +++++++++++++++++++++++-----------------
b3f87c
 2 files changed, 64 insertions(+), 47 deletions(-)
b3f87c
b3f87c
diff --git a/tests/overrides_hack.py b/tests/overrides_hack.py
b3f87c
index 0f10ee5..509a961 100644
b3f87c
--- a/tests/overrides_hack.py
b3f87c
+++ b/tests/overrides_hack.py
b3f87c
@@ -1,5 +1,8 @@
b3f87c
+import os
b3f87c
 import gi.overrides
b3f87c
-if not gi.overrides.__path__[0].endswith("src/python/gi/overrides"):
b3f87c
+
b3f87c
+if 'LIBBLOCKDEV_TESTS_SKIP_OVERRIDE' not in os.environ and \
b3f87c
+   not gi.overrides.__path__[0].endswith("src/python/gi/overrides"):
b3f87c
     local_overrides = None
b3f87c
     # our overrides don't take precedence, let's fix it
b3f87c
     for i, path in enumerate(gi.overrides.__path__):
b3f87c
diff --git a/tests/run_tests.py b/tests/run_tests.py
b3f87c
index 5301d07..b67c2e7 100644
b3f87c
--- a/tests/run_tests.py
b3f87c
+++ b/tests/run_tests.py
b3f87c
@@ -65,49 +65,8 @@ def _get_test_tags(test):
b3f87c
     return tags
b3f87c
 
b3f87c
 
b3f87c
-def _print_skip_message(test, skip_tag):
b3f87c
-
b3f87c
-    # test.id() looks like 'crypto_test.CryptoTestResize.test_luks2_resize'
b3f87c
-    # and we want to print 'test_luks2_resize (crypto_test.CryptoTestResize)'
b3f87c
-    test_desc = test.id().split(".")
b3f87c
-    test_name = test_desc[-1]
b3f87c
-    test_module = ".".join(test_desc[:-1])
b3f87c
-
b3f87c
-    if skip_tag == TestTags.SLOW:
b3f87c
-        reason = "skipping slow tests"
b3f87c
-    elif skip_tag == TestTags.UNSTABLE:
b3f87c
-        reason = "skipping unstable tests"
b3f87c
-    elif skip_tag == TestTags.UNSAFE:
b3f87c
-        reason = "skipping test that modifies system configuration"
b3f87c
-    elif skip_tag == TestTags.EXTRADEPS:
b3f87c
-        reason = "skipping test that requires special configuration"
b3f87c
-    elif skip_tag == TestTags.CORE:
b3f87c
-        reason = "skipping non-core test"
b3f87c
-    else:
b3f87c
-        reason = "unknown reason"  # just to be sure there is some default value
b3f87c
-
b3f87c
-    if test._testMethodDoc:
b3f87c
-        print("%s (%s)\n%s ... skipped '%s'" % (test_name, test_module, test._testMethodDoc, reason))
b3f87c
-    else:
b3f87c
-        print("%s (%s) ... skipped '%s'" % (test_name, test_module, reason))
b3f87c
-
b3f87c
-
b3f87c
-if __name__ == '__main__':
b3f87c
-
b3f87c
-    testdir = os.path.abspath(os.path.dirname(__file__))
b3f87c
-    projdir = os.path.abspath(os.path.normpath(os.path.join(testdir, '..')))
b3f87c
-
b3f87c
-    if 'LD_LIBRARY_PATH' not in os.environ and 'GI_TYPELIB_PATH' not in os.environ:
b3f87c
-        os.environ['LD_LIBRARY_PATH'] = LIBDIRS
b3f87c
-        os.environ['GI_TYPELIB_PATH'] = GIDIR
b3f87c
-        os.environ['LIBBLOCKDEV_CONFIG_DIR'] = os.path.join(testdir, 'default_config')
b3f87c
-
b3f87c
-        try:
b3f87c
-            pyver = 'python3' if six.PY3 else 'python'
b3f87c
-            os.execv(sys.executable, [pyver] + sys.argv)
b3f87c
-        except OSError as e:
b3f87c
-            print('Failed re-exec with a new LD_LIBRARY_PATH and GI_TYPELIB_PATH: %s' % str(e))
b3f87c
-            sys.exit(1)
b3f87c
+def parse_args():
b3f87c
+    """ Parse cmdline arguments """
b3f87c
 
b3f87c
     argparser = argparse.ArgumentParser(description='libblockdev test suite')
b3f87c
     argparser.add_argument('testname', nargs='*', help='name of test class or '
b3f87c
@@ -127,6 +86,9 @@ if __name__ == '__main__':
b3f87c
     argparser.add_argument('-s', '--stop', dest='stop',
b3f87c
                            help='stop executing after first failed test',
b3f87c
                            action='store_true')
b3f87c
+    argparser.add_argument('-i', '--installed', dest='installed',
b3f87c
+                           help='run tests against installed version of libblockdev',
b3f87c
+                           action='store_true')
b3f87c
     args = argparser.parse_args()
b3f87c
 
b3f87c
     if args.fast:
b3f87c
@@ -144,9 +106,61 @@ if __name__ == '__main__':
b3f87c
     if 'FEELINGLUCKY' in os.environ:
b3f87c
         args.lucky = True
b3f87c
 
b3f87c
-    sys.path.append(testdir)
b3f87c
-    sys.path.append(projdir)
b3f87c
-    sys.path.append(os.path.join(projdir, 'src/python'))
b3f87c
+    return args
b3f87c
+
b3f87c
+
b3f87c
+def _print_skip_message(test, skip_tag):
b3f87c
+
b3f87c
+    # test.id() looks like 'crypto_test.CryptoTestResize.test_luks2_resize'
b3f87c
+    # and we want to print 'test_luks2_resize (crypto_test.CryptoTestResize)'
b3f87c
+    test_desc = test.id().split(".")
b3f87c
+    test_name = test_desc[-1]
b3f87c
+    test_module = ".".join(test_desc[:-1])
b3f87c
+
b3f87c
+    if skip_tag == TestTags.SLOW:
b3f87c
+        reason = "skipping slow tests"
b3f87c
+    elif skip_tag == TestTags.UNSTABLE:
b3f87c
+        reason = "skipping unstable tests"
b3f87c
+    elif skip_tag == TestTags.UNSAFE:
b3f87c
+        reason = "skipping test that modifies system configuration"
b3f87c
+    elif skip_tag == TestTags.EXTRADEPS:
b3f87c
+        reason = "skipping test that requires special configuration"
b3f87c
+    elif skip_tag == TestTags.CORE:
b3f87c
+        reason = "skipping non-core test"
b3f87c
+    else:
b3f87c
+        reason = "unknown reason"  # just to be sure there is some default value
b3f87c
+
b3f87c
+    if test._testMethodDoc:
b3f87c
+        print("%s (%s)\n%s ... skipped '%s'" % (test_name, test_module, test._testMethodDoc, reason))
b3f87c
+    else:
b3f87c
+        print("%s (%s) ... skipped '%s'" % (test_name, test_module, reason))
b3f87c
+
b3f87c
+
b3f87c
+if __name__ == '__main__':
b3f87c
+
b3f87c
+    testdir = os.path.abspath(os.path.dirname(__file__))
b3f87c
+    projdir = os.path.abspath(os.path.normpath(os.path.join(testdir, '..')))
b3f87c
+
b3f87c
+    args = parse_args()
b3f87c
+    if args.installed:
b3f87c
+        os.environ['LIBBLOCKDEV_TESTS_SKIP_OVERRIDE'] = ''
b3f87c
+        os.environ['LIBBLOCKDEV_CONFIG_DIR'] = '/etc/libblockdev/conf.d/'
b3f87c
+    else:
b3f87c
+        if 'LD_LIBRARY_PATH' not in os.environ and 'GI_TYPELIB_PATH' not in os.environ:
b3f87c
+            os.environ['LD_LIBRARY_PATH'] = LIBDIRS
b3f87c
+            os.environ['GI_TYPELIB_PATH'] = GIDIR
b3f87c
+            os.environ['LIBBLOCKDEV_CONFIG_DIR'] = os.path.join(testdir, 'default_config')
b3f87c
+
b3f87c
+            try:
b3f87c
+                pyver = 'python3' if six.PY3 else 'python'
b3f87c
+                os.execv(sys.executable, [pyver] + sys.argv)
b3f87c
+            except OSError as e:
b3f87c
+                print('Failed re-exec with a new LD_LIBRARY_PATH and GI_TYPELIB_PATH: %s' % str(e))
b3f87c
+                sys.exit(1)
b3f87c
+
b3f87c
+        sys.path.append(testdir)
b3f87c
+        sys.path.append(projdir)
b3f87c
+        sys.path.append(os.path.join(projdir, 'src/python'))
b3f87c
 
b3f87c
     start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
b3f87c
 
b3f87c
-- 
b3f87c
2.20.1
b3f87c
b3f87c
b3f87c
From df65462618e72602b7760f6c750085094b2bddff Mon Sep 17 00:00:00 2001
b3f87c
From: Vojtech Trefny <vtrefny@redhat.com>
b3f87c
Date: Thu, 4 Apr 2019 11:50:04 +0200
b3f87c
Subject: [PATCH 06/10] Add a special test tag for library tests that recompile
b3f87c
 plugins
b3f87c
b3f87c
We have some tests that changes lvm plugin and recompile it to
b3f87c
test loading of plugins. We can't run these tests against
b3f87c
installed library, so we need a special tag to skip them.
b3f87c
---
b3f87c
 tests/library_test.py | 8 ++++----
b3f87c
 tests/run_tests.py    | 2 ++
b3f87c
 tests/utils.py        | 2 ++
b3f87c
 3 files changed, 8 insertions(+), 4 deletions(-)
b3f87c
b3f87c
diff --git a/tests/library_test.py b/tests/library_test.py
b3f87c
index fa33b53..e8bb175 100644
b3f87c
--- a/tests/library_test.py
b3f87c
+++ b/tests/library_test.py
b3f87c
@@ -40,7 +40,7 @@ class LibraryOpsTestCase(unittest.TestCase):
b3f87c
         BlockDev.reinit(self.requested_plugins, True, None)
b3f87c
 
b3f87c
     # recompiles the LVM plugin
b3f87c
-    @tag_test(TestTags.SLOW, TestTags.CORE)
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.CORE, TestTags.SOURCEONLY)
b3f87c
     def test_reload(self):
b3f87c
         """Verify that reloading plugins works as expected"""
b3f87c
 
b3f87c
@@ -72,7 +72,7 @@ class LibraryOpsTestCase(unittest.TestCase):
b3f87c
         self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None))
b3f87c
 
b3f87c
     # recompiles the LVM plugin
b3f87c
-    @tag_test(TestTags.SLOW)
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.SOURCEONLY)
b3f87c
     def test_force_plugin(self):
b3f87c
         """Verify that forcing plugin to be used works as expected"""
b3f87c
 
b3f87c
@@ -118,7 +118,7 @@ class LibraryOpsTestCase(unittest.TestCase):
b3f87c
         self.assertEqual(BlockDev.lvm_get_max_lv_size(), orig_max_size)
b3f87c
 
b3f87c
     # recompiles the LVM plugin
b3f87c
-    @tag_test(TestTags.SLOW)
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.SOURCEONLY)
b3f87c
     def test_plugin_priority(self):
b3f87c
         """Verify that preferring plugin to be used works as expected"""
b3f87c
 
b3f87c
@@ -181,7 +181,7 @@ class LibraryOpsTestCase(unittest.TestCase):
b3f87c
         os.system ("rm -f src/plugins/.libs/libbd_lvm2.so")
b3f87c
 
b3f87c
     # recompiles the LVM plugin
b3f87c
-    @tag_test(TestTags.SLOW)
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.SOURCEONLY)
b3f87c
     def test_plugin_fallback(self):
b3f87c
         """Verify that fallback when loading plugins works as expected"""
b3f87c
 
b3f87c
diff --git a/tests/run_tests.py b/tests/run_tests.py
b3f87c
index b67c2e7..7df9e7d 100644
b3f87c
--- a/tests/run_tests.py
b3f87c
+++ b/tests/run_tests.py
b3f87c
@@ -61,6 +61,8 @@ def _get_test_tags(test):
b3f87c
         tags.append(TestTags.EXTRADEPS)
b3f87c
     if getattr(test_fn, "regression", False) or getattr(test_fn.__self__, "regression", False):
b3f87c
         tags.append(TestTags.REGRESSION)
b3f87c
+    if getattr(test_fn, "sourceonly", False) or getattr(test_fn.__self__, "sourceonly", False):
b3f87c
+        tags.append(TestTags.SOURCEONLY)
b3f87c
 
b3f87c
     return tags
b3f87c
 
b3f87c
diff --git a/tests/utils.py b/tests/utils.py
b3f87c
index 82b5494..df8e787 100644
b3f87c
--- a/tests/utils.py
b3f87c
+++ b/tests/utils.py
b3f87c
@@ -351,6 +351,7 @@ class TestTags(Enum):
b3f87c
     NOSTORAGE = 5   # tests that don't work with storage
b3f87c
     EXTRADEPS = 6   # tests that require special configuration and/or device to run
b3f87c
     REGRESSION = 7  # regression tests
b3f87c
+    SOURCEONLY = 8  # tests that can't run against installed library
b3f87c
 
b3f87c
 
b3f87c
 def tag_test(*tags):
b3f87c
@@ -362,6 +363,7 @@ def tag_test(*tags):
b3f87c
         func.nostorage = TestTags.NOSTORAGE in tags
b3f87c
         func.extradeps = TestTags.EXTRADEPS in tags
b3f87c
         func.regression = TestTags.REGRESSION in tags
b3f87c
+        func.sourceonly = TestTags.SOURCEONLY in tags
b3f87c
 
b3f87c
         return func
b3f87c
 
b3f87c
-- 
b3f87c
2.20.1
b3f87c
b3f87c
b3f87c
From 74a6630db44bd141b76aec80c4eb81fa15dea593 Mon Sep 17 00:00:00 2001
b3f87c
From: Vojtech Trefny <vtrefny@redhat.com>
b3f87c
Date: Thu, 4 Apr 2019 11:55:32 +0200
b3f87c
Subject: [PATCH 07/10] Skip "source only" tests when running against installed
b3f87c
 version
b3f87c
b3f87c
---
b3f87c
 tests/run_tests.py | 5 +++++
b3f87c
 1 file changed, 5 insertions(+)
b3f87c
b3f87c
diff --git a/tests/run_tests.py b/tests/run_tests.py
b3f87c
index 7df9e7d..4244c06 100644
b3f87c
--- a/tests/run_tests.py
b3f87c
+++ b/tests/run_tests.py
b3f87c
@@ -129,6 +129,8 @@ def _print_skip_message(test, skip_tag):
b3f87c
         reason = "skipping test that requires special configuration"
b3f87c
     elif skip_tag == TestTags.CORE:
b3f87c
         reason = "skipping non-core test"
b3f87c
+    elif skip_tag == TestTags.SOURCEONLY:
b3f87c
+        reason = "skipping test that can run only against library compiled from source"
b3f87c
     else:
b3f87c
         reason = "unknown reason"  # just to be sure there is some default value
b3f87c
 
b3f87c
@@ -198,6 +200,9 @@ if __name__ == '__main__':
b3f87c
         if TestTags.EXTRADEPS in tags and not args.jenkins:
b3f87c
             _print_skip_message(test, TestTags.EXTRADEPS)
b3f87c
             continue
b3f87c
+        if TestTags.SOURCEONLY in tags and args.installed:
b3f87c
+            _print_skip_message(test, TestTags.SOURCEONLY)
b3f87c
+            continue
b3f87c
 
b3f87c
         if args.core and TestTags.CORE not in tags and TestTags.REGRESSION not in tags:
b3f87c
             _print_skip_message(test, TestTags.CORE)
b3f87c
-- 
b3f87c
2.20.1
b3f87c
b3f87c
b3f87c
From d19f2508dbfb00473b21ab1bd6f5603aec66bf4e Mon Sep 17 00:00:00 2001
b3f87c
From: Vojtech Trefny <vtrefny@redhat.com>
b3f87c
Date: Thu, 4 Apr 2019 14:26:22 +0200
b3f87c
Subject: [PATCH 08/10] Force LVM cli plugin in lvm_test
b3f87c
b3f87c
We can't rely on LVM cli plugin being default in config when
b3f87c
running against installed library.
b3f87c
---
b3f87c
 tests/lvm_test.py | 6 +++++-
b3f87c
 1 file changed, 5 insertions(+), 1 deletion(-)
b3f87c
b3f87c
diff --git a/tests/lvm_test.py b/tests/lvm_test.py
b3f87c
index 28a4b05..0b2c5ad 100644
b3f87c
--- a/tests/lvm_test.py
b3f87c
+++ b/tests/lvm_test.py
b3f87c
@@ -12,10 +12,14 @@ from gi.repository import BlockDev, GLib
b3f87c
 
b3f87c
 
b3f87c
 class LVMTestCase(unittest.TestCase):
b3f87c
-    requested_plugins = BlockDev.plugin_specs_from_names(("lvm",))
b3f87c
 
b3f87c
     @classmethod
b3f87c
     def setUpClass(cls):
b3f87c
+        ps = BlockDev.PluginSpec()
b3f87c
+        ps.name = BlockDev.Plugin.LVM
b3f87c
+        ps.so_name = "libbd_lvm.so"
b3f87c
+        cls.requested_plugins = [ps]
b3f87c
+
b3f87c
         if not BlockDev.is_initialized():
b3f87c
             BlockDev.init(cls.requested_plugins, None)
b3f87c
         else:
b3f87c
-- 
b3f87c
2.20.1
b3f87c
b3f87c
b3f87c
From f15a7428382d5ee086ed13755b3ba1f8705b79cf Mon Sep 17 00:00:00 2001
b3f87c
From: Vojtech Trefny <vtrefny@redhat.com>
b3f87c
Date: Thu, 6 Sep 2018 10:27:52 +0200
b3f87c
Subject: [PATCH 09/10] Fix how we check zram stats from /sys/block/zram0/stat
b3f87c
b3f87c
There are four new stats since kernel 4.19. Checking if we read
b3f87c
more than 11 values should be enough to be sure that the file
b3f87c
has the stats we want.
b3f87c
---
b3f87c
 tests/kbd_test.py | 2 +-
b3f87c
 1 file changed, 1 insertion(+), 1 deletion(-)
b3f87c
b3f87c
diff --git a/tests/kbd_test.py b/tests/kbd_test.py
b3f87c
index 5e872c4..23b63c9 100644
b3f87c
--- a/tests/kbd_test.py
b3f87c
+++ b/tests/kbd_test.py
b3f87c
@@ -192,7 +192,7 @@ class KbdZRAMStatsTestCase(KbdZRAMTestCase):
b3f87c
 
b3f87c
         # read 'num_reads' and 'num_writes' from '/sys/block/zram0/stat'
b3f87c
         sys_stats = read_file("/sys/block/zram0/stat").strip().split()
b3f87c
-        self.assertEqual(len(sys_stats), 11)
b3f87c
+        self.assertGreaterEqual(len(sys_stats), 11)  # 15 stats since 4.19
b3f87c
         num_reads = int(sys_stats[0])
b3f87c
         num_writes = int(sys_stats[4])
b3f87c
         self.assertEqual(stats.num_reads, num_reads)
b3f87c
-- 
b3f87c
2.20.1
b3f87c
b3f87c
b3f87c
From 7e8f6ef031fe3e5e0b117d910cbf8de36f5bd75e Mon Sep 17 00:00:00 2001
b3f87c
From: Vojtech Trefny <vtrefny@redhat.com>
b3f87c
Date: Wed, 10 Apr 2019 07:51:48 +0200
b3f87c
Subject: [PATCH 10/10] Mark 'test_set_bitmap_location' as unstable
b3f87c
b3f87c
This test randomly fails with error message from mdadm:
b3f87c
"mdadm: failed to remove internal bitmap".
b3f87c
---
b3f87c
 tests/mdraid_test.py | 2 +-
b3f87c
 1 file changed, 1 insertion(+), 1 deletion(-)
b3f87c
b3f87c
diff --git a/tests/mdraid_test.py b/tests/mdraid_test.py
b3f87c
index ea489db..14d0bd4 100644
b3f87c
--- a/tests/mdraid_test.py
b3f87c
+++ b/tests/mdraid_test.py
b3f87c
@@ -520,7 +520,7 @@ class MDTestNameNodeBijection(MDTestCase):
b3f87c
         self.assertTrue(succ)
b3f87c
 
b3f87c
 class MDTestSetBitmapLocation(MDTestCase):
b3f87c
-    @tag_test(TestTags.SLOW)
b3f87c
+    @tag_test(TestTags.SLOW, TestTags.UNSTABLE)
b3f87c
     def test_set_bitmap_location(self):
b3f87c
         """Verify we can change bitmap location for an existing MD array"""
b3f87c
 
b3f87c
-- 
b3f87c
2.20.1
b3f87c