diff --git a/tests/conftest.py b/tests/conftest.py index 50b813d..e7fb6ef 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,10 @@ import pytest +from tests.mocked_plugins import MockedDistribution +from tests.mocked_plugins import MockedEntryPoint +from tests.mocked_plugins import MockedPluginA +from tests.mocked_plugins import MockedPluginB +from tests.mocked_plugins import MockedPluginC from variantlib.loader import PluginLoader @@ -7,3 +12,28 @@ def flush_caches(): yield PluginLoader.flush_cache() + + +@pytest.fixture +def mocked_plugin_loader(session_mocker): + session_mocker.patch("variantlib.loader.entry_points")().select.return_value = [ + MockedEntryPoint( + name="test_namespace", + value="tests.test_plugins:MockedPluginA", + dist=MockedDistribution(name="test-plugin", version="1.2.3"), + plugin=MockedPluginA, + ), + MockedEntryPoint( + name="second_namespace", + value="tests.test_plugins:MockedPluginB", + dist=MockedDistribution(name="second-plugin", version="4.5.6"), + plugin=MockedPluginB, + ), + MockedEntryPoint( + name="incompatible_namespace", + value="tests.test_plugins:MockedPluginC", + plugin=MockedPluginC, + ), + ] + + return PluginLoader diff --git a/tests/mocked_plugins.py b/tests/mocked_plugins.py new file mode 100644 index 0000000..3e91158 --- /dev/null +++ b/tests/mocked_plugins.py @@ -0,0 +1,115 @@ +from __future__ import annotations + +from collections import namedtuple +from dataclasses import dataclass +from typing import Any + +from variantlib.base import PluginType +from variantlib.base import VariantFeatureConfigType +from variantlib.base import VariantPropertyType +from variantlib.models.provider import VariantFeatureConfig + + +@dataclass +class MockedDistribution: + name: str + version: str + + +@dataclass +class MockedEntryPoint: + name: str | None + value: str + plugin: Any + group: str | None = None + dist: MockedDistribution | None = None + + def load(self) -> Any: + return self.plugin + + +class MockedPluginA(PluginType): + namespace = "test_namespace" + + def get_all_configs(self) -> list[VariantFeatureConfigType]: + return [ + VariantFeatureConfig("name1", ["val1a", "val1b", "val1c", "val1d"]), + VariantFeatureConfig("name2", ["val2a", "val2b", "val2c"]), + ] + + def get_supported_configs(self) -> list[VariantFeatureConfigType]: + return [ + VariantFeatureConfig("name1", ["val1a", "val1b"]), + VariantFeatureConfig("name2", ["val2a", "val2b", "val2c"]), + ] + + def get_build_setup( + self, properties: list[VariantPropertyType] + ) -> dict[str, list[str]]: + for prop in properties: + assert prop.namespace == self.namespace + if prop.feature == "name1": + return { + "cflags": [f"-march={prop.value}"], + "cxxflags": [f"-march={prop.value}"], + "ldflags": ["-Wl,--test-flag"], + } + return {} + + +MyVariantFeatureConfig = namedtuple("MyVariantFeatureConfig", ("name", "values")) + + +# NB: this plugin deliberately does not inherit from PluginType +# to test that we don't rely on that inheritance +class MockedPluginB: + namespace = "second_namespace" + + def get_all_configs(self) -> list[MyVariantFeatureConfig]: + return [ + MyVariantFeatureConfig("name3", ["val3a", "val3b", "val3c"]), + ] + + def get_supported_configs(self) -> list[MyVariantFeatureConfig]: + return [ + MyVariantFeatureConfig("name3", ["val3a"]), + ] + + +class MyFlag: + name: str + values: list[str] + + def __init__(self, name: str) -> None: + self.name = name + self.values = ["on"] + + +class MockedPluginC(PluginType): + namespace = "incompatible_namespace" + + def get_all_configs(self) -> list[VariantFeatureConfigType]: + return [ + MyFlag("flag1"), + MyFlag("flag2"), + MyFlag("flag3"), + MyFlag("flag4"), + ] + + def get_supported_configs(self) -> list[VariantFeatureConfigType]: + return [] + + def get_build_setup( + self, properties: list[VariantPropertyType] + ) -> dict[str, list[str]]: + flag_opts = [] + + for prop in properties: + assert prop.namespace == self.namespace + assert prop.value == "on" + flag_opts.append(f"-m{prop.feature}") + + return { + "cflags": flag_opts, + "cxxflags": flag_opts, + } diff --git a/tests/test_api.py b/tests/test_api.py index 19b86a9..4f00016 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -12,7 +12,6 @@ from hypothesis import settings from hypothesis import strategies as st -from tests.test_plugins import mocked_plugin_loader # noqa: F401 from tests.utils import get_combinations from variantlib.api import ProviderConfig from variantlib.api import VariantDescription @@ -42,7 +41,7 @@ def test_api_accessible(): @pytest.fixture -def configs(mocked_plugin_loader: type[PluginLoader]): # noqa: F811 +def configs(mocked_plugin_loader: type[PluginLoader]): return list(PluginLoader.get_supported_configs().values()) @@ -205,7 +204,7 @@ def test_validation_result_properties(): ] -def test_validate_variant(mocked_plugin_loader: type[PluginLoader]): # noqa: F811 +def test_validate_variant(mocked_plugin_loader: type[PluginLoader]): res = validate_variant( VariantDescription( [ @@ -253,7 +252,7 @@ def metadata() -> EmailMessage: @pytest.mark.parametrize("replace", [False, True]) def test_set_variant_metadata( - mocked_plugin_loader: type[PluginLoader], # noqa: F811 + mocked_plugin_loader: type[PluginLoader], metadata: EmailMessage, replace: bool, ): diff --git a/tests/test_plugins.py b/tests/test_plugins.py index be865dd..7694937 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -2,15 +2,15 @@ import re import sys -from collections import namedtuple -from dataclasses import dataclass from typing import Any import pytest +from tests.mocked_plugins import MockedDistribution +from tests.mocked_plugins import MockedEntryPoint +from tests.mocked_plugins import MockedPluginA from variantlib.base import PluginType from variantlib.base import VariantFeatureConfigType -from variantlib.base import VariantPropertyType from variantlib.errors import PluginError from variantlib.errors import PluginMissingError from variantlib.loader import PluginLoader @@ -25,93 +25,6 @@ from importlib_metadata import EntryPoint -class MockedPluginA(PluginType): - namespace = "test_namespace" - - def get_all_configs(self) -> list[VariantFeatureConfigType]: - return [ - VariantFeatureConfig("name1", ["val1a", "val1b", "val1c", "val1d"]), - VariantFeatureConfig("name2", ["val2a", "val2b", "val2c"]), - ] - - def get_supported_configs(self) -> list[VariantFeatureConfigType]: - return [ - VariantFeatureConfig("name1", ["val1a", "val1b"]), - VariantFeatureConfig("name2", ["val2a", "val2b", "val2c"]), - ] - - def get_build_setup( - self, properties: list[VariantPropertyType] - ) -> dict[str, list[str]]: - for prop in properties: - assert prop.namespace == self.namespace - if prop.feature == "name1": - return { - "cflags": [f"-march={prop.value}"], - "cxxflags": [f"-march={prop.value}"], - "ldflags": ["-Wl,--test-flag"], - } - return {} - - -MyVariantFeatureConfig = namedtuple("MyVariantFeatureConfig", ("name", "values")) - - -# NB: this plugin deliberately does not inherit from PluginType -# to test that we don't rely on that inheritance -class MockedPluginB: - namespace = "second_namespace" - - def get_all_configs(self) -> list[MyVariantFeatureConfig]: - return [ - MyVariantFeatureConfig("name3", ["val3a", "val3b", "val3c"]), - ] - - def get_supported_configs(self) -> list[MyVariantFeatureConfig]: - return [ - MyVariantFeatureConfig("name3", ["val3a"]), - ] - - -class MyFlag: - name: str - values: list[str] - - def __init__(self, name: str) -> None: - self.name = name - self.values = ["on"] - - -class MockedPluginC(PluginType): - namespace = "incompatible_namespace" - - def get_all_configs(self) -> list[VariantFeatureConfigType]: - return [ - MyFlag("flag1"), - MyFlag("flag2"), - MyFlag("flag3"), - MyFlag("flag4"), - ] - - def get_supported_configs(self) -> list[VariantFeatureConfigType]: - return [] - - def get_build_setup( - self, properties: list[VariantPropertyType] - ) -> dict[str, list[str]]: - flag_opts = [] - - for prop in properties: - assert prop.namespace == self.namespace - assert prop.value == "on" - flag_opts.append(f"-m{prop.feature}") - - return { - "cflags": flag_opts, - "cxxflags": flag_opts, - } - - class ClashingPlugin(PluginType): namespace = "test_namespace" @@ -141,49 +54,6 @@ def __call__(self) -> ExceptionTestingPlugin: return self -@dataclass -class MockedDistribution: - name: str - version: str - - -@dataclass -class MockedEntryPoint: - name: str | None - value: str - plugin: Any - group: str | None = None - dist: MockedDistribution | None = None - - def load(self) -> Any: - return self.plugin - - -@pytest.fixture -def mocked_plugin_loader(session_mocker): - session_mocker.patch("variantlib.loader.entry_points")().select.return_value = [ - MockedEntryPoint( - name="test_namespace", - value="tests.test_plugins:MockedPluginA", - dist=MockedDistribution(name="test-plugin", version="1.2.3"), - plugin=MockedPluginA, - ), - MockedEntryPoint( - name="second_namespace", - value="tests.test_plugins:MockedPluginB", - dist=MockedDistribution(name="second-plugin", version="4.5.6"), - plugin=MockedPluginB, - ), - MockedEntryPoint( - name="incompatible_namespace", - value="tests.test_plugins:MockedPluginC", - plugin=MockedPluginC, - ), - ] - - return PluginLoader - - def test_get_all_configs(mocked_plugin_loader: type[PluginLoader]): assert mocked_plugin_loader.get_all_configs() == { "incompatible_namespace": ProviderConfig( diff --git a/tests/test_utils.py b/tests/test_utils.py index 30d4222..81714d4 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -4,7 +4,6 @@ import pytest -from tests.test_plugins import mocked_plugin_loader # noqa: F401 from tests.utils import get_combinations from variantlib.api import VariantDescription from variantlib.api import VariantProperty @@ -16,7 +15,7 @@ @pytest.fixture -def configs(mocked_plugin_loader: type[PluginLoader]) -> list[ProviderConfig]: # noqa: F811 +def configs(mocked_plugin_loader: type[PluginLoader]) -> list[ProviderConfig]: return list(PluginLoader.get_supported_configs().values())