]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
tests: add pytest CLI args for distribution and release
authorJoerg Behrmann <behrmann@physik.fu-berlin.de>
Fri, 1 Dec 2023 13:30:05 +0000 (14:30 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 18 Dec 2023 11:18:53 +0000 (12:18 +0100)
Pass them to test functions via a fixture and the new Config subclass
of Image.

Also move pytest.ini into pyproject.toml while we're at it.

.github/workflows/ci.yml
pyproject.toml
pytest.ini [deleted file]
tests/__init__.py
tests/conftest.py [new file with mode: 0644]
tests/test_boot.py
tests/test_initrd.py
tests/test_sysext.py

index 9c5f8fb5e2e50eb4eadb237e7fd00cfe85332b84..5cd11f0e5d3c95fa4ccc91073ece9f1852c40377 100644 (file)
@@ -133,6 +133,4 @@ jobs:
         EOF
 
     - name: Run integration tests
-      run: sudo --preserve-env timeout -k 30 1h python3 -m pytest --tb=no -sv -m integration tests/
-      env:
-        MKOSI_TEST_DISTRIBUTION: ${{ matrix.distro }}
+      run: sudo --preserve-env timeout -k 30 1h python3 -m pytest --tb=no -sv -m integration -D ${{ matrix.distro }} tests/
index 8f46a9ebd635b2c24885afe4ced418a364014a5c..2c93e8a6e22793fc02553d6f774e1f57828fafcf 100644 (file)
@@ -73,3 +73,9 @@ ignore_missing_imports = true
 target-version = "py39"
 line-length = 119
 select = ["E", "F", "I", "UP"]
+
+[tool.pytest.ini_options]
+markers = [
+    "integration: mark a test as an integration test."
+]
+addopts = "-m \"not integration\""
diff --git a/pytest.ini b/pytest.ini
deleted file mode 100644 (file)
index c24ad46..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-[pytest]
-markers =
-    integration: mark a test as an integration test.
-addopts = -m "not integration"
index 74de5c4bc395d9ccd26a2aa7cb6226e92937c923..df9bd345d872cf6c0eb88568234ee6dc4d500496 100644 (file)
@@ -6,32 +6,24 @@ import sys
 import tempfile
 from collections.abc import Iterator, Sequence
 from types import TracebackType
-from typing import Any, Optional
+from typing import Any, NamedTuple, Optional
 
 import pytest
 
-from mkosi.distributions import Distribution, detect_distribution
-from mkosi.log import die
+from mkosi.distributions import Distribution
 from mkosi.run import run
 from mkosi.types import _FILE, CompletedProcess, PathString
 from mkosi.util import INVOKING_USER
 
 
 class Image:
-    def __init__(self, options: Sequence[PathString] = []) -> None:
-        self.options = options
-
-        if d := os.getenv("MKOSI_TEST_DISTRIBUTION"):
-            self.distribution = Distribution(d)
-        elif detected := detect_distribution()[0]:
-            self.distribution = detected
-        else:
-            die("Cannot detect host distribution, please set $MKOSI_TEST_DISTRIBUTION to be able to run the tests")
+    class Config(NamedTuple):
+        distribution: Distribution
+        release: str
 
-        if r := os.getenv("MKOSI_TEST_RELEASE"):
-            self.release = r
-        else:
-            self.release = self.distribution.default_release()
+    def __init__(self, config: Config, options: Sequence[PathString] = []) -> None:
+        self.options = options
+        self.config = config
 
     def __enter__(self) -> "Image":
         self.output_dir = tempfile.TemporaryDirectory(dir="/var/tmp")
@@ -71,8 +63,8 @@ class Image:
 
         return run([
             "python3", "-m", "mkosi",
-            "--distribution", str(self.distribution),
-            "--release", self.release,
+            "--distribution", str(self.config.distribution),
+            "--release", self.config.release,
             *self.options,
             *options,
             "--output-dir", self.output_dir.name,
@@ -118,7 +110,10 @@ class Image:
             check=False,
         )
 
-        rc = 0 if self.distribution == Distribution.ubuntu or self.distribution.is_centos_variant() else 123
+        if self.config.distribution == Distribution.ubuntu or self.config.distribution.is_centos_variant():
+            rc = 0
+        else:
+            rc = 123
 
         if result.returncode != rc:
             raise subprocess.CalledProcessError(result.returncode, result.args, result.stdout, result.stderr)
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644 (file)
index 0000000..22d3741
--- /dev/null
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: LGPL-2.1+
+from typing import Any, Optional, cast
+
+import pytest
+
+from mkosi.distributions import Distribution, detect_distribution
+
+from . import Image
+
+
+def pytest_addoption(parser: Any) -> None:
+    parser.addoption(
+        "-D",
+        "--distribution",
+        metavar="DISTRIBUTION",
+        help="Run the integration tests for the given distribution.",
+        default=detect_distribution()[0],
+        type=Distribution,
+        choices=[Distribution(d) for d in Distribution.values()],
+    )
+    parser.addoption(
+        "-R",
+        "--release",
+        metavar="RELEASE",
+        help="Run the integration tests for the given release.",
+    )
+
+
+@pytest.fixture(scope="session")
+def config(request: Any) -> Image.Config:
+    distribution = cast(Distribution, request.config.getoption("--distribution"))
+    release = cast(Optional[str], request.config.getoption("--release"))
+    if release is None:
+        release = distribution.default_release()
+
+    return Image.Config(distribution=distribution, release=release)
index 61f481af476b57fb4fad1b9eaf8acb5a2be68be4..66f0027792c4113c1d9ffde7fee4b94746b9b6f4 100644 (file)
@@ -14,15 +14,16 @@ pytestmark = pytest.mark.integration
 
 
 @pytest.mark.parametrize("format", OutputFormat)
-def test_boot(format: OutputFormat) -> None:
+def test_boot(config: Image.Config, format: OutputFormat) -> None:
     with Image(
+        config,
         options=[
             "--kernel-command-line=systemd.unit=mkosi-check-and-shutdown.service",
             "--incremental",
             "--ephemeral",
         ],
     ) as image:
-        if image.distribution == Distribution.rhel_ubi and format in (OutputFormat.esp, OutputFormat.uki):
+        if image.config.distribution == Distribution.rhel_ubi and format in (OutputFormat.esp, OutputFormat.uki):
             pytest.skip("Cannot build RHEL-UBI images with format 'esp' or 'uki'")
 
         options = ["--format", str(format)]
@@ -40,13 +41,13 @@ def test_boot(format: OutputFormat) -> None:
             image.boot(options=options, args=args)
 
         if (
-            image.distribution == Distribution.ubuntu and
+            image.config.distribution == Distribution.ubuntu and
             format in (OutputFormat.cpio, OutputFormat.uki, OutputFormat.esp)
         ):
             # https://bugs.launchpad.net/ubuntu/+source/linux-kvm/+bug/2045561
             pytest.skip("Cannot boot Ubuntu UKI/cpio images in qemu until we switch back to linux-kvm")
 
-        if image.distribution == Distribution.rhel_ubi:
+        if image.config.distribution == Distribution.rhel_ubi:
             return
 
         if format in (OutputFormat.tar, OutputFormat.none) or format.is_extension_image():
index f2730ce27a940480719b6570eec0987a47a6925a..cc53ac9facff1abf0c48bfc7c66affc193b60860 100644 (file)
@@ -35,15 +35,16 @@ def passphrase() -> Iterator[Path]:
 
 
 @pytest.fixture(scope="module")
-def initrd(passphrase: Path) -> Iterator[Image]:
+def initrd(config: Image.Config, passphrase: Path) -> Iterator[Image]:
     with Image(
+        config,
         options=[
             "--directory", "",
             "--include=mkosi-initrd/",
             "--extra-tree", passphrase,
         ],
     ) as initrd:
-        if initrd.distribution == Distribution.rhel_ubi:
+        if initrd.config.distribution == Distribution.rhel_ubi:
             pytest.skip("Cannot build RHEL-UBI initrds")
 
         initrd.build()
@@ -52,6 +53,7 @@ def initrd(passphrase: Path) -> Iterator[Image]:
 
 def test_initrd(initrd: Image) -> None:
     with Image(
+        initrd.config,
         options=[
             "--initrd", Path(initrd.output_dir.name) / "initrd",
             "--kernel-command-line=systemd.unit=mkosi-check-and-shutdown.service",
@@ -67,6 +69,7 @@ def test_initrd(initrd: Image) -> None:
 @pytest.mark.skipif(os.getuid() != 0, reason="mkosi-initrd LVM test can only be executed as root")
 def test_initrd_lvm(initrd: Image) -> None:
     with Image(
+        initrd.config,
         options=[
             "--initrd", Path(initrd.output_dir.name) / "initrd",
             "--kernel-command-line=systemd.unit=mkosi-check-and-shutdown.service",
@@ -95,7 +98,7 @@ def test_initrd_lvm(initrd: Image) -> None:
         run(["lvm", "lvcreate", "-l", "100%FREE", "-n", "lv0", "vg_mkosi"])
         run(["lvm", "lvs"])
         run(["udevadm", "wait", "/dev/vg_mkosi/lv0"])
-        run([f"mkfs.{image.distribution.filesystem()}", "-L", "root", "/dev/vg_mkosi/lv0"])
+        run([f"mkfs.{image.config.distribution.filesystem()}", "-L", "root", "/dev/vg_mkosi/lv0"])
 
         with tempfile.TemporaryDirectory() as mnt, mount(Path("/dev/vg_mkosi/lv0"), Path(mnt)):
             # The image might have been built unprivileged so we need to fix the file ownership. Making all the
@@ -143,7 +146,7 @@ def test_initrd_luks(initrd: Image, passphrase: Path) -> None:
                 f"""\
                 [Partition]
                 Type=root
-                Format={initrd.distribution.filesystem()}
+                Format={initrd.config.distribution.filesystem()}
                 Minimize=guess
                 Encrypt=key-file
                 CopyFiles=/
@@ -152,6 +155,7 @@ def test_initrd_luks(initrd: Image, passphrase: Path) -> None:
         )
 
         with Image(
+            initrd.config,
             options=[
                 "--initrd", Path(initrd.output_dir.name) / "initrd",
                 "--repart-dir", repartd,
@@ -168,8 +172,9 @@ def test_initrd_luks(initrd: Image, passphrase: Path) -> None:
 
 
 @pytest.mark.skipif(os.getuid() != 0, reason="mkosi-initrd LUKS+LVM test can only be executed as root")
-def test_initrd_luks_lvm(initrd: Image, passphrase: Path) -> None:
+def test_initrd_luks_lvm(config: Image.Config, initrd: Image, passphrase: Path) -> None:
     with Image(
+        config,
         options=[
             "--initrd", Path(initrd.output_dir.name) / "initrd",
             "--kernel-command-line=systemd.unit=mkosi-check-and-shutdown.service",
@@ -213,7 +218,7 @@ def test_initrd_luks_lvm(initrd: Image, passphrase: Path) -> None:
         run(["lvm", "lvcreate", "-l", "100%FREE", "-n", "lv0", "vg_mkosi"])
         run(["lvm", "lvs"])
         run(["udevadm", "wait", "/dev/vg_mkosi/lv0"])
-        run([f"mkfs.{image.distribution.filesystem()}", "-L", "root", "/dev/vg_mkosi/lv0"])
+        run([f"mkfs.{image.config.distribution.filesystem()}", "-L", "root", "/dev/vg_mkosi/lv0"])
 
         with tempfile.TemporaryDirectory() as mnt, mount(Path("/dev/vg_mkosi/lv0"), Path(mnt)):
             # The image might have been built unprivileged so we need to fix the file ownership. Making all the
@@ -236,6 +241,6 @@ def test_initrd_size(initrd: Image) -> None:
         Distribution.ubuntu: 32,
         Distribution.arch: 47,
         Distribution.opensuse: 36,
-    }.get(initrd.distribution, 48)
+    }.get(initrd.config.distribution, 48)
 
     assert (Path(initrd.output_dir.name) / "initrd").stat().st_size <= maxsize
index b7f3cf6aadbb93ca7c41b0652660021f0d80edc3..39ecec0363386a60c056581a01a900ae4974fd40 100644 (file)
@@ -9,8 +9,9 @@ from . import Image
 pytestmark = pytest.mark.integration
 
 
-def test_sysext() -> None:
+def test_sysext(config: Image.Config) -> None:
     with Image(
+        config,
         options=[
             "--incremental",
             "--clean-package-metadata=no",
@@ -20,6 +21,7 @@ def test_sysext() -> None:
         image.build()
 
         with Image(
+            image.config,
             options=[
                 "--directory", "",
                 "--base-tree", Path(image.output_dir.name) / "image",