From c89ef580e0eaf3971973f7ff43b3838099e4cd20 Mon Sep 17 00:00:00 2001 From: Alex Pyrgiotis Date: Thu, 27 Jun 2024 21:52:42 +0300 Subject: [PATCH] tests: Properly skip tests for isolation providers The platform where we run our tests directly affects the isolation providers we can choose. For instance, we cannot run Qubes tests on a Windows/macOS platform, nor can we spawn containers in a Qubes platform, if the `QUBES_CONVERSION` envvar has been specified. This platform incompatibility was never an issue before, because Dangerzone is capable of selecting the proper isolation provider under the hood. However, with the addition of tests that target specific isolation providers, it's possible that we may run by mistake a test that does not apply to our platform. To counter this, we employed `pytest.skipif()` guards around classes, but we may omit those by mistake. Case in point, the `TestContainer` class does not have such a guard, which means that we attempt to run this test case on Qubes and it fails. Add module-level guards in our isolation provider tests using pytest's `pytest.skip("...", allow_module_level=True)` function, so that we make such restrictions more explicit, and less easy to forget when we add a new class. --- tests/isolation_provider/base.py | 1 - tests/isolation_provider/test_container.py | 13 ++++++------- tests/isolation_provider/test_dummy.py | 8 ++++---- tests/isolation_provider/test_qubes.py | 20 +++++++------------- 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/tests/isolation_provider/base.py b/tests/isolation_provider/base.py index 017a144..8e4a236 100644 --- a/tests/isolation_provider/base.py +++ b/tests/isolation_provider/base.py @@ -16,7 +16,6 @@ TIMEOUT_STARTUP = 60 # Timeout in seconds until the conversion sandbox starts. os.environ.get("DUMMY_CONVERSION", False), reason="dummy conversions not supported", ) -@pytest.mark.skipif(not running_on_qubes(), reason="Not on a Qubes system") class IsolationProviderTest: def test_max_pages_server_enforcement( self, diff --git a/tests/isolation_provider/test_container.py b/tests/isolation_provider/test_container.py index 18fa8bd..860cf9f 100644 --- a/tests/isolation_provider/test_container.py +++ b/tests/isolation_provider/test_container.py @@ -9,6 +9,12 @@ from dangerzone.isolation_provider.qubes import is_qubes_native_conversion from .base import IsolationProviderTermination, IsolationProviderTest +# Run the tests in this module only if we can spawn containers. +if is_qubes_native_conversion(): + pytest.skip("Qubes native conversion is enabled", allow_module_level=True) +elif os.environ.get("DUMMY_CONVERSION", False): + pytest.skip("Dummy conversion is enabled", allow_module_level=True) + @pytest.fixture def provider() -> Container: @@ -44,12 +50,5 @@ class TestContainer(IsolationProviderTest): pass -@pytest.mark.skipif( - os.environ.get("DUMMY_CONVERSION", False), - reason="cannot run for dummy conversions", -) -@pytest.mark.skipif( - is_qubes_native_conversion(), reason="Qubes native conversion is enabled" -) class TestContainerTermination(IsolationProviderTermination): pass diff --git a/tests/isolation_provider/test_dummy.py b/tests/isolation_provider/test_dummy.py index 9d4041b..e03a6ca 100644 --- a/tests/isolation_provider/test_dummy.py +++ b/tests/isolation_provider/test_dummy.py @@ -11,6 +11,10 @@ from dangerzone.isolation_provider.dummy import Dummy from .base import IsolationProviderTermination +# Run the tests in this module only if dummy conversion is enabled. +if not os.environ.get("DUMMY_CONVERSION", False): + pytest.skip("Dummy conversion is not enabled", allow_module_level=True) + class DummyWait(Dummy): """Dummy isolation provider that spawns a blocking process.""" @@ -34,10 +38,6 @@ def provider_wait() -> DummyWait: return DummyWait() -@pytest.mark.skipif( - os.environ.get("DUMMY_CONVERSION", False) is False, - reason="can only run for dummy conversions", -) class TestDummyTermination(IsolationProviderTermination): def test_failed( self, diff --git a/tests/isolation_provider/test_qubes.py b/tests/isolation_provider/test_qubes.py index 297fdd7..77ea939 100644 --- a/tests/isolation_provider/test_qubes.py +++ b/tests/isolation_provider/test_qubes.py @@ -9,14 +9,16 @@ from pytest_mock import MockerFixture from dangerzone.conversion import errors from dangerzone.document import Document -from dangerzone.isolation_provider.qubes import ( - Qubes, - is_qubes_native_conversion, - running_on_qubes, -) +from dangerzone.isolation_provider.qubes import Qubes, is_qubes_native_conversion from .base import IsolationProviderTermination, IsolationProviderTest +# Run the tests in this module only if we can spawn disposable qubes. +if not is_qubes_native_conversion(): + pytest.skip("Qubes native conversion is not enabled", allow_module_level=True) +elif os.environ.get("DUMMY_CONVERSION", False): + pytest.skip("Dummy conversion is enabled", allow_module_level=True) + @pytest.fixture def provider() -> Qubes: @@ -55,7 +57,6 @@ def provider_wait() -> QubesWait: return QubesWait() -@pytest.mark.skipif(not running_on_qubes(), reason="Not on a Qubes system") class TestQubes(IsolationProviderTest): def test_out_of_ram( self, @@ -82,12 +83,5 @@ class TestQubes(IsolationProviderTest): assert provider.get_proc_exception(proc) == errors.QubesQrexecFailed -@pytest.mark.skipif( - os.environ.get("DUMMY_CONVERSION", False), - reason="cannot run for dummy conversions", -) -@pytest.mark.skipif( - not is_qubes_native_conversion(), reason="Qubes native conversion is not enabled" -) class TestQubesTermination(IsolationProviderTermination): pass