From: Daan De Meyer Date: Tue, 31 Jan 2023 18:56:18 +0000 (+0100) Subject: tests: Drop config parser tests X-Git-Tag: v15~344^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f49d742f195a5b679716ca7c1e68b2ebc12f9bca;p=thirdparty%2Fmkosi.git tests: Drop config parser tests These have never caught anything useful and are understood by nobody, let's just drop them. --- diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index 36229c323..000000000 --- a/tests/conftest.py +++ /dev/null @@ -1,66 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -from typing import Any, List, Mapping, Set - -from tests.test_config_parser import MkosiConfig - - -class DictDiffer: - def __init__(self, expected_dict: Mapping[str, Any], current_dict: Mapping[str, Any]) -> None: - self.current_dict = current_dict - self.expected_dict = expected_dict - self.set_current, self.set_past = set(current_dict.keys()), set(expected_dict.keys()) - self.intersect = self.set_current.intersection(self.set_past) - - @property - def unexpected(self) -> List[str]: - return [f"{k}={self.current_dict[k]}" for k in self.set_current - self.intersect] - - @property - def missing(self) -> List[str]: - return [str(k) for k in self.set_past - self.intersect] - - @property - def invalid(self) -> List[str]: - inva = {o for o in self.intersect if self.expected_dict[o] != self.current_dict[o]} - return [f"{k}={self.current_dict[k]} (exp: {self.expected_dict[k]})" for k in inva] - - @property - def valid(self) -> Set[str]: - return {o for o in self.intersect if self.expected_dict[o] == self.current_dict[o]} - - -def pytest_assertrepr_compare(op: str, left: MkosiConfig, right: Any) -> List[str]: - if not isinstance(right, dict): - return [] - for r in right.values(): - if not isinstance(vars(r), dict): - return ["Invalid datatype"] - if op == "==": - - def compare_job_args(job: str, l_a: Mapping[str, Any], r_a: Mapping[str, Any]) -> None: - ddiff = DictDiffer(l_a, r_a) - ret.append(f'Comparing parsed configuration {job} against expected configuration:') - ret.append("unexpected:") - ret.extend([f'- {i}' for i in ddiff.unexpected]) - ret.append("missing:") - ret.extend([f'- {i}' for i in ddiff.missing]) - ret.append("invalid:") - ret.extend([f'- {i}' for i in ddiff.invalid]) - - verified_keys = [] - ret = ["MkosiConfig is not equal to parsed args"] - for right_job, right_args in right.items(): - try: - left_args = left.reference_config[right_job] - except KeyError: - ret.append(f'Unexpected job: {right_job}') - continue - r_v = vars(right_args) - compare_job_args(right_job, left_args, r_v) - verified_keys.append(right_job) - for left_job in left.reference_config: - if not left_job in verified_keys: - ret.append(f'Missing job: {left_job}') - return ret - return [] diff --git a/tests/test_config_parser.py b/tests/test_config_parser.py deleted file mode 100644 index a1dd18267..000000000 --- a/tests/test_config_parser.py +++ /dev/null @@ -1,985 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -import configparser -import contextlib -import copy -import importlib -import os -import platform -import shutil -from pathlib import Path -from typing import Any, Dict, Generator, List, Mapping, Optional - -import pytest - -import mkosi -import mkosi.backend -from mkosi.backend import MkosiException, OutputFormat, SourceFileTransfer, Verb - - -@contextlib.contextmanager -def change_cwd(path: Path) -> Generator[None, None, None]: - """Change working directory temporarily""" - old = Path.cwd() - os.chdir(path) - try: - yield - finally: - os.chdir(old) - - -DEFAULT_JOB_NAME = "default" - - -class MkosiConfig: - """Base class for mkosi test and reference configuration generators""" - cli_arguments: List[str] - reference_config: Dict[str, Any] - - def __init__(self) -> None: - self.cli_arguments = [] - self.reference_config = {} - - def local_sign_expected_pcr_default(self) -> bool: - try: - importlib.import_module("cryptography") - return True if shutil.which('systemd-measure') else False - except ImportError: - return False - - def add_reference_config(self, job_name: str = DEFAULT_JOB_NAME) -> None: - """create one initial reference configuration - - This default reference configuration is equal to the configuration returned by parse_args - function without default files and without any command line arguments. - """ - self.reference_config[job_name] = { - "all": False, - "all_directory": None, - "architecture": platform.machine(), - "bmap": False, - "bootable": False, - "build_dir": None, - "build_packages": [], - "clean_package_metadata": "auto", - "remove_files": [], - "remove_packages": [], - "build_script": None, - "environment": [], - "build_sources": None, - "cache_path": None, - "checksum": False, - "cmdline": [], - "compress_output": None, - "debug": [], - "config_path": None, - "directory": None, - "distribution": None, - "extra_search_paths": [], - "extra_trees": [], - "finalize_script": None, - "force": 0, - "hostname": None, - "include_dir": None, - "incremental": False, - "install_dir": None, - "kernel_command_line": [], - "key": None, - "local_mirror": None, - "manifest_format": None, - "mirror": None, - "repository_key_check": True, - "chown": True, - "idmap": True, - "nspawn_settings": None, - "output": None, - "output_dir": None, - "output_format": None, - "base_packages": True, - "packages": [], - "machine_id": None, - "password": None, - "password_is_hashed": False, - "autologin": False, - "skip_final_phase": False, - "tar_strip_selinux_context": False, - "prepare_script": None, - "postinst_script": None, - "qcow2": False, - "release": None, - "repositories": [], - "repo_dirs": [], - "base_image": None, - "secure_boot": False, - "secure_boot_certificate": Path("mkosi.secure-boot.crt"), - "secure_boot_key": Path("mkosi.secure-boot.key"), - "secure_boot_common_name": "mkosi of %u", - "secure_boot_valid_days": "730", - "sign": False, - "skeleton_trees": [], - "source_resolve_symlinks": False, - "source_resolve_symlinks_final": False, - "source_file_transfer": None, - "source_file_transfer_final": None, - "verb": Verb.build, - "sign_expected_pcr": self.local_sign_expected_pcr_default(), - "with_docs": False, - "with_network": False, - "with_tests": True, - "qemu_headless": False, - "qemu_smp": "1", - "qemu_mem": "1G", - "qemu_kvm": mkosi.qemu_check_kvm_support(), - "qemu_args": [], - "nspawn_keep_unit": False, - "netdev": False, - "ephemeral": False, - "cache_initrd": False, - "ssh": False, - "ssh_key": None, - "ssh_timeout": 0, - "ssh_agent": None, - "ssh_port": 22, - "credentials": [], - "split_artifacts": False, - "image_id": None, - "image_version": None, - "auto_bump": False, - "workspace_dir": None, - "repart_dir": None, - } - - def __eq__(self, other: Mapping[str, Any]) -> bool: # type: ignore - """Compare the configuration returned by parse_args against self.reference_config""" - if len(self.reference_config) != len(other): - return False - - is_eq = True - for other_job, other_args in other.items(): - try: - this_args = self.reference_config[other_job] - except KeyError: - return False - other_args_v = vars(other_args) - if this_args != other_args_v: - is_eq = False - return is_eq - - def _append_list(self, ref_entry: str, new_args: Any, job_name: str = DEFAULT_JOB_NAME, separator: str = ",", with_duplicates: bool = False) -> None: - """Helper function handling comma separated list as supported by mkosi""" - args_list = [] - if isinstance(new_args, str): - args_list = new_args.split(separator) - else: - for arg in new_args: - if isinstance(arg, str): - args_list.extend(arg.split(separator)) - else: - args_list.append(arg) - for arg in args_list: - if isinstance(arg, str) and arg.startswith("!"): - if arg[1:] in self.reference_config[job_name][ref_entry]: - self.reference_config[job_name][ref_entry].remove(arg[1:]) - elif with_duplicates or arg not in self.reference_config[job_name][ref_entry]: - self.reference_config[job_name][ref_entry].append(arg) - - @staticmethod - def write_ini(dname: str, fname: str, config: Dict[str, Any], prio: int = 1000) -> None: - """Write mkosi.conf(.d/*) files""" - if not os.path.exists(dname): - os.makedirs(dname) - if prio < 1000: - fname = f"{prio:03d}_{fname}" - config_parser = configparser.RawConfigParser() - # This is still an open issue on: https://github.com/python/mypy/issues/2427 - config_parser.optionxform = str # type: ignore - - # Replace lists in dict before calling config_parser write file - config_all_normalized = copy.deepcopy(config) - for section, key_val in config_all_normalized.items(): - for key, val in key_val.items(): - if isinstance(val, list): - config_all_normalized[section][key] = os.linesep.join(str(item) for item in val) - - config_parser.read_dict(config_all_normalized) - with open(os.path.join(dname, fname), "w") as f_ini: - config_parser.write(f_ini) - - def _update_ref_from_file(self, mk_config: Dict[str, Any], job_name: str = DEFAULT_JOB_NAME) -> None: - """Update reference_config from a dict as needed to write an ini file using configparser - - This is basically a conversion from snake case to - separated format. - """ - if "Distribution" in mk_config: - mk_config_distro = mk_config["Distribution"] - if "Distribution" in mk_config_distro: - self.reference_config[job_name]["distribution"] = mk_config_distro["Distribution"] - if "Release" in mk_config_distro: - self.reference_config[job_name]["release"] = mk_config_distro["Release"] - if "Repositories" in mk_config_distro: - self._append_list("repositories", mk_config_distro["Repositories"], job_name) - if "Mirror" in mk_config_distro: - self.reference_config[job_name]["mirror"] = mk_config_distro["Mirror"] - if "Architecture" in mk_config_distro: - self.reference_config[job_name]["architecture"] = mk_config_distro["Architecture"] - if "Output" in mk_config: - mk_config_output = mk_config["Output"] - if "Format" in mk_config_output: - self.reference_config[job_name]["output_format"] = OutputFormat.from_string( - mk_config_output["Format"] - ) - if "ManifestFormat" in mk_config_output: - self.reference_config[job_name]["manifest_format"] = mk_config_output["ManifestFormat"] - if "Output" in mk_config_output: - self.reference_config[job_name]["output"] = Path(mk_config_output["Output"]) - if "Force" in mk_config_output: - self.reference_config[job_name]["force"] += 1 - if "Bootable" in mk_config_output: - self.reference_config[job_name]["bootable"] = mk_config_output["Bootable"] - if "KernelCommandLine" in mk_config_output: - self._append_list("kernel_command_line", mk_config_output["KernelCommandLine"], job_name, " ") - if "SecureBoot" in mk_config_output: - self.reference_config[job_name]["secure_boot"] = mk_config_output["SecureBoot"] - if "SecureBootKey" in mk_config_output: - self.reference_config[job_name]["secure_boot_key"] = Path(mk_config_output["SecureBootKey"]) - if "SecureBootCertificate" in mk_config_output: - self.reference_config[job_name]["secure_boot_certificate"] = Path(mk_config_output["SecureBootCertificate"]) - if "SecureBootCommonName" in mk_config_output: - self.reference_config[job_name]["secure_boot_common_name"] = mk_config_output["SecureBootCommonName"] - if "SecureBootValidDays" in mk_config_output: - self.reference_config[job_name]["secure_boot_valid_days"] = mk_config_output["SecureBootValidDays"] - if "CompressOutput" in mk_config_output: - self.reference_config[job_name]["compress_output"] = mk_config_output["CompressOutput"] - if "QCow2" in mk_config_output: - self.reference_config[job_name]["qcow2"] = mk_config_output["QCow2"] - if "TarStripSELinuxContext" in mk_config_output: - self.reference_config[job_name]["tar_strip_selinux_context"] = mk_config_output[ - "TarStripSELinuxContext" - ] - if "Hostname" in mk_config_output: - self.reference_config[job_name]["hostname"] = mk_config_output["Hostname"] - if "CacheInitrd" in mk_config_output: - self.reference_config[job_name]["cache_initrd"] = mk_config_output["CacheInitrd"] - if "MachineID" in mk_config_output: - self.reference_config[job_name]["MachineID"] = mk_config_output["MachineID"] - if "Packages" in mk_config: - mk_config_packages = mk_config["Packages"] - if "Packages" in mk_config_packages: - self._append_list("packages", mk_config_packages["Packages"], job_name) - if "WithDocs" in mk_config_packages: - self.reference_config[job_name]["with_docs"] = mk_config_packages["WithDocs"] - if "WithTests" in mk_config_packages: - self.reference_config[job_name]["with_tests"] = mk_config_packages["WithTests"] - if "Cache" in mk_config_packages: - self.reference_config[job_name]["cache_path"] = Path(mk_config_packages["Cache"]) - if "ExtraTrees" in mk_config_packages: - self._append_list("extra_trees", [Path(mk_config_packages["ExtraTrees"])], job_name) - if "SkeletonTrees" in mk_config_packages: - self._append_list("skeleton_trees", [Path(mk_config_packages["SkeletonTrees"])], job_name) - if "CleanupPackageMetadata" in mk_config_packages: - self.reference_config[job_name]["clean_package_metadata"] = mk_config_packages["CleanPackageMetadata"] - if "RemoveFiles" in mk_config_packages: - self.reference_config[job_name]["remove_files"] = mk_config_packages["RemoveFiles"] - if "RemovePackages" in mk_config_packages: - self.reference_config[job_name]["remove_packages"] = mk_config_packages["RemovePackages"] - if "BuildScript" in mk_config_packages: - self.reference_config[job_name]["build_script"] = Path(mk_config_packages["BuildScript"]) - if "BuildEnvironment" in mk_config_packages: - self.reference_config["environment"] = mk_config_packages["Environment"] - if "BuildSources" in mk_config_packages: - self.reference_config[job_name]["build_sources"] = Path(mk_config_packages["BuildSources"]) - if "SourceFileTransfer" in mk_config_packages: - self.reference_config[job_name]["source_file_transfer"] = mk_config_packages["SourceFileTransfer"] - if "SourceFileTransferFinal" in mk_config_packages: - self.reference_config[job_name]["source_file_transfer_final"] = mk_config_packages[ - "SourceFileTransferFinal" - ] - if "BuildDirectory" in mk_config_packages: - self.reference_config[job_name]["build_dir"] = Path(mk_config_packages["BuildDirectory"]) - if "IncludeDirectory" in mk_config_packages: - self.reference_config[job_name]["include_dir"] = Path(mk_config_packages["IncludeDirectory"]) - if "InstallDirectory" in mk_config_packages: - self.reference_config[job_name]["install_dir"] = Path(mk_config_packages["InstallDirectory"]) - if "BuildPackages" in mk_config_packages: - self._append_list("build_packages", mk_config_packages["BuildPackages"], job_name) - if "PostInstallationScript" in mk_config_packages: - self.reference_config[job_name]["postinst_script"] = Path(mk_config_packages["PostInstallationScript"]) - if "FinalizeScript" in mk_config_packages: - self.reference_config[job_name]["finalize_script"] = Path(mk_config_packages["FinalizeScript"]) - if "WithNetwork" in mk_config_packages: - self.reference_config[job_name]["with_network"] = mk_config_packages["WithNetwork"] - if "NSpawnSettings" in mk_config_packages: - self.reference_config[job_name]["nspawn_settings"] = Path(mk_config_packages["NSpawnSettings"]) - if "Partitions" in mk_config: - mk_config_partitions = mk_config["Partitions"] - if "BaseImage" in mk_config_partitions: - self.reference_config[job_name]["base_image"] = mk_config_partitions["BaseImage"] - if "Validation" in mk_config: - mk_config_validation = mk_config["Validation"] - if "CheckSum" in mk_config_validation: - self.reference_config[job_name]["checksum"] = mk_config_validation["CheckSum"] - if "Sign" in mk_config_validation: - self.reference_config[job_name]["sign"] = mk_config_validation["Sign"] - if "Key" in mk_config_validation: - self.reference_config[job_name]["key"] = mk_config_validation["Key"] - if "BMap" in mk_config_validation: - self.reference_config[job_name]["bmap"] = mk_config_validation["BMap"] - if "Password" in mk_config_validation: - self.reference_config[job_name]["password"] = mk_config_validation["Password"] - if "PasswordIsHashed" in mk_config_validation: - self.reference_config[job_name]["password_is_hashed"] = mk_config_validation["PasswordIsHashed"] - if "Autologin" in mk_config_validation: - self.reference_config[job_name]["autologin"] = mk_config_validation["Autologin"] - - if "Host" in mk_config: - mk_config_host = mk_config["Host"] - if "ExtraSearchPaths" in mk_config_host: - self._append_list("extra_search_paths", mk_config_host["ExtraSearchPaths"], job_name, ":") - if "QemuHeadless" in mk_config_host: - self.reference_config[job_name]["qemu_headless"] = mk_config_host["QemuHeadless"] - if "QemuArgs" in mk_config_host: - self._append_list("qemu_args", mk_config_host["QemuArgs"], job_name, " ", with_duplicates=True) - if "Netdev" in mk_config_host: - self.reference_config[job_name]["netdev"] = mk_config_host["Netdev"] - if "Ephemeral" in mk_config_host: - self.reference_config[job_name]["ephemeral"] = mk_config_host["Ephemeral"] - if "Ssh" in mk_config_host: - self.reference_config[job_name]["ssh"] = mk_config_host["Ssh"] - - -class MkosiConfigOne(MkosiConfig): - """Classes derived from this class are magically instantiated by pytest - - Each test_ function with a parameter named "tested_config" gets - called by pytest for each class derived from this class. These test cases - verify the parse_args function in single image (not --all) mode. - This class implements four functions: - - prepare_mkosi_conf - - prepare_mkosi_conf_d_1 - - prepare_mkosi_conf_d_2 - - prepare_args or prepare_args_short - - The purpose of these function is to generate configuration files and sets of command line - arguments processed by the parse_args function of mkosi. Additionally each of these four functions - alters the reference_config to be consistent with the expected values returned by the parse_args - function under test. - - This allows to write test cases with four steps. The first step generates a reference configuration - consisting of mkosi.conf file only. Therefore prepare_mkosi_conf function is is called to - generate the test configuration. Finally parse_args is called and the configuration returned by - parse_args is compared against the reference_config. The second test step generates a test - configuration by calling prepare_mkosi_conf and prepare_mkosi_conf_d_1. This verifies the - behavior of parse_args is fine for mkosi.conf plus one override file. The third test case verifies - that mkosi.conf with two files in mkosi.conf.d folder works as expected. The fourth test case - additionally overrides some default values with command line arguments. - - Classes derived from this base class should override the mentioned functions to implement specific - test cases. - """ - - def __init__(self) -> None: - """Add the default mkosi.conf config""" - super().__init__() - self.add_reference_config() - - def _prepare_mkosi_conf(self, directory: str, config: Dict[str, Any]) -> None: - MkosiConfig.write_ini(directory, "mkosi.conf", config) - - def _prepare_mkosi_conf_d(self, directory: str, config: Dict[str, Any], prio: int = 1000, fname: str = "mkosi.conf") -> None: - MkosiConfig.write_ini(os.path.join(directory, "mkosi.conf.d"), fname, config, prio) - - def prepare_mkosi_conf(self, directory: str) -> None: - """Generate a mkosi.conf config file in the working directory""" - pass - - def prepare_mkosi_conf_d_1(self, directory: str) -> None: - """Generate a prio 1 config file in mkosi.conf.d - - The file name should be prefixed with 001_. - """ - pass - - def prepare_mkosi_conf_d_2(self, directory: str) -> None: - """Generate a prio 2 config file in mkosi.conf.d - - The file name should be prefixed with 002_. - """ - pass - - def prepare_args(self) -> None: - """Add some command line arguments to this test run""" - pass - - def prepare_args_short(self) -> None: - """Add some command line arguments to this test run, in short form""" - pass - - -class MkosiConfigSummary(MkosiConfigOne): - """Test configuration for mkosi summary - - This test checks if the default parameter set of these tests is in sync - with the default parameters implemented in mkosi. No config files or command - line arguments are in place. - """ - - def __init__(self) -> None: - super().__init__() - for ref_c in self.reference_config.values(): - ref_c["verb"] = Verb.summary - self.cli_arguments = ["summary"] - - -class MkosiConfigDistro(MkosiConfigOne): - """Minimal test configuration for the distribution parameter - - This tests defines the distribution parameter on several configuration priorities: - - mkosi.conf - - mkosi.conf.d/001_mkosi.conf - - mkosi.conf.d/002_mkosi.conf - - --distribution - """ - - def __init__(self, subdir_name: str = "", alldir_name: str = "") -> None: - super().__init__() - self.subdir_name = subdir_name - if subdir_name: - for ref_c in self.reference_config.values(): - ref_c["directory"] = self.subdir_name - self.cli_arguments = ["--directory", self.subdir_name, "summary"] - - def prepare_mkosi_conf(self, directory: str) -> None: - mk_config = {"Distribution": {"Distribution": "fedora"}} - self._prepare_mkosi_conf(directory, mk_config) - for ref_c in self.reference_config.values(): - ref_c["distribution"] = "fedora" - if self.subdir_name: - ref_c["directory"] = self.subdir_name - if self.subdir_name: - self.cli_arguments = ["--directory", self.subdir_name, "summary"] - - def prepare_mkosi_conf_d_1(self, directory: str) -> None: - mk_config = {"Distribution": {"Distribution": "ubuntu"}} - self._prepare_mkosi_conf_d(directory, mk_config, 1) - for ref_c in self.reference_config.values(): - ref_c["distribution"] = "ubuntu" - - def prepare_mkosi_conf_d_2(self, directory: str) -> None: - mk_config = {"Distribution": {"Distribution": "debian"}} - self._prepare_mkosi_conf_d(directory, mk_config, 2) - for ref_c in self.reference_config.values(): - ref_c["distribution"] = "debian" - - def prepare_args(self) -> None: - if not self.cli_arguments: - self.cli_arguments = ["build"] - self.cli_arguments[0:0] = ["--distribution", "arch"] - for ref_c in self.reference_config.values(): - ref_c["distribution"] = "arch" - - def prepare_args_short(self) -> None: - if not self.cli_arguments: - self.cli_arguments = ["build"] - self.cli_arguments[0:0] = ["-d", "arch"] - for ref_c in self.reference_config.values(): - ref_c["distribution"] = "arch" - - -class MkosiConfigDistroDir(MkosiConfigDistro): - """Same as Distro, but gets --directory passed and sets verb to summary""" - - def __init__(self) -> None: - super().__init__("a_sub_dir") - for ref_c in self.reference_config.values(): - ref_c["verb"] = Verb.summary - - -class MkosiConfigManyParams(MkosiConfigOne): - """Test configuration for most parameters""" - - def prepare_mkosi_conf(self, directory: str) -> None: - mk_config = { - "Distribution": { - "Distribution": "fedora", - "Release": "28", - "Repositories": "http://fedora/repos", - "Mirror": "http://fedora/mirror", - "Architecture": "i386", - }, - "Output": { - "Format": "disk", - "Output": "test_image.raw", - "ManifestFormat": [mkosi.backend.ManifestFormat.json], - # # 'OutputDirectory': '', - "Bootable": False, - "KernelCommandLine": ["console=ttyS0"], - "SecureBoot": False, - "SecureBootKey": "/foo.pem", - "SecureBootCertificate": "bar.crt", - "SecureBootCommonName": "mkosi for %u", - "SecureBootValidDays": "730", - "CompressOutput": "lz4", - "QCow2": False, - "Hostname": "myhost1", - }, - "Packages": { - "Packages": ["pkg-foo", "pkg-bar", "pkg-foo1,pkg-bar1"], - "WithDocs": False, - "WithTests": True, - "Cache": "the/cache/dir", - "ExtraTrees": "another/tree", - "SkeletonTrees": "a/skeleton", - "BuildScript": "fancy_build.sh", - "BuildSources": "src", - "SourceFileTransfer": SourceFileTransfer.copy_all, - "BuildDirectory": "here/we/build", - "BuildPackages": ["build-me", "build-me2"], - "PostInstallationScript": "post-script.sh", - "FinalizeScript": "final.sh", - "WithNetwork": False, - "NSpawnSettings": "foo.nspawn", - }, - "Partitions": {}, - "Validation": { - "CheckSum": True, - "Sign": False, - "Key": "mykey.gpg", - "BMap": False, - "Password": "secret1234", - "Autologin": True, - }, - "Host": { - "ExtraSearchPaths": "search/here:search/there", - "QemuHeadless": True, - "QemuArgs": "-device virtio-vga-gl -vga none", - "Netdev": True, - }, - } - self._prepare_mkosi_conf(directory, mk_config) - for j in self.reference_config: - self._update_ref_from_file(mk_config, j) - - def prepare_mkosi_conf_d_1(self, directory: str) -> None: - mk_config = { - "Distribution": { - "Distribution": "ubuntu", - "Release": "18.04", - "Repositories": "http://ubuntu/repos", - "Mirror": "http://ubuntu/mirror", - "Architecture": platform.machine(), - }, - "Output": { - "Format": "disk", - "Output": "test_image.raw.xz", - # # 'OutputDirectory': '', - "Bootable": True, - "KernelCommandLine": ["console=ttyS1"], - "SecureBoot": True, - "SecureBootKey": "/foo-ubu.pem", - "SecureBootCertificate": "bar-bub.crt", - "CompressOutput": "zstd", - "QCow2": True, - "Hostname": "myubuhost1", - }, - "Packages": { - "Packages": ["add-ubu-1", "add-ubu-2"], - "WithDocs": True, - "WithTests": False, - "Cache": "the/cache/dir/ubu", - "ExtraTrees": "another/tree/ubu", - "SkeletonTrees": "a/skeleton/ubu", - "BuildScript": "ubu_build.sh", - "BuildSources": "src/ubu", - "SourceFileTransfer": SourceFileTransfer.copy_git_cached, - "BuildDirectory": "here/we/build/ubu", - "BuildPackages": ["build-me", "build-me2-ubu"], - "PostInstallationScript": "post-ubu-script.sh", - "FinalizeScript": "final-ubu.sh", - "WithNetwork": True, - "NSpawnSettings": "foo-ubu.nspawn", - }, - "Partitions": {}, - "Validation": { - "CheckSum": False, - "Sign": True, - "Key": "mykey-ubu.gpg", - "BMap": True, - "Password": "secret12345", - "Autologin": True, - }, - "Host": { - "ExtraSearchPaths": "search/ubu", - "QemuHeadless": True, - "QemuArgs": "-vga virtio -device usb-kbd -device usb-mouse", - "Netdev": True, - }, - } - self._prepare_mkosi_conf_d(directory, mk_config, 1) - for j in self.reference_config: - self._update_ref_from_file(mk_config, j) - - def prepare_mkosi_conf_d_2(self, directory: str) -> None: - mk_config = { - "Distribution": { - "Distribution": "debian", - "Release": "unstable", - "Repositories": "http://debian/repos", - "Mirror": "http://ubuntu/mirror", - "Architecture": platform.machine(), - }, - "Output": { - "Format": "disk", - "Output": "test_image.raw.xz", - # # 'OutputDirectory': '', - "Bootable": True, - "KernelCommandLine": ["console=ttyS1"], - "SecureBoot": True, - "SecureBootKey": "/foo-debi.pem", - "SecureBootCertificate": "bar-bub.crt", - "CompressOutput": "zstd", - "QCow2": True, - "Hostname": "mydebihost1", - }, - "Packages": { - "Packages": ["!add-ubu-1", "!add-ubu-2", "add-debi-1", "add-debi-2"], - "WithDocs": True, - "WithTests": False, - "Cache": "the/cache/dir/debi", - "ExtraTrees": "another/tree/debi", - "SkeletonTrees": "a/skeleton/debi", - "BuildScript": "debi_build.sh", - "BuildSources": "src/debi", - "SourceFileTransfer": SourceFileTransfer.copy_git_cached, - "BuildDirectory": "here/we/build/debi", - "BuildPackages": ["build-me", "build-me2-debi"], - "PostInstallationScript": "post-debi-script.sh", - "FinalizeScript": "final-debi.sh", - "WithNetwork": True, - "NSpawnSettings": "foo-debi.nspawn", - }, - "Partitions": {}, - "Validation": { - "CheckSum": False, - "Sign": True, - "Key": "mykey-debi.gpg", - "BMap": True, - "Password": "secret12345", - "Autologin": True, - }, - "Host": { - "ExtraSearchPaths": "search/debi", - "QemuHeadless": True, - "QemuArgs": "-device virtio-vga-gl,xres=1920,yres=1080 -display sdl,gl=on", - "Netdev": True, - }, - } - self._prepare_mkosi_conf_d(directory, mk_config, 2) - for j in self.reference_config: - self._update_ref_from_file(mk_config, j) - - def prepare_args(self) -> None: - if not self.cli_arguments: - self.cli_arguments = ["build"] - self.cli_arguments[0:0] = ["--distribution", "arch"] - self.cli_arguments[0:0] = ["--release", "7"] - self.cli_arguments[0:0] = ["--repositories", "centos/repos"] - self.cli_arguments[0:0] = ["--force"] - self.cli_arguments[0:0] = ["--incremental"] - - for j, ref_c in self.reference_config.items(): - ref_c["distribution"] = "arch" - ref_c["release"] = "7" - self._append_list("repositories", "centos/repos", j) - ref_c["force"] += 1 - ref_c["incremental"] = True - - def prepare_args_short(self) -> None: - if not self.cli_arguments: - self.cli_arguments = ["build"] - self.cli_arguments[0:0] = ["-d", "centos"] - for ref_c in self.reference_config.values(): - ref_c["distribution"] = "centos" - - -class MkosiConfigIniLists1(MkosiConfigOne): - """Manually written ini files with advanced list syntax.""" - - def prepare_mkosi_conf(self, directory: str) -> None: - ini_lines = [ - "[Distribution]", - "Distribution=fedora", - "", - "[Content]", - "Packages=openssh-clients", - " httpd", - " tar", - ] - with open(os.path.join(directory, "mkosi.conf"), "w") as f_ini: - f_ini.write(os.linesep.join(ini_lines)) - self.reference_config[DEFAULT_JOB_NAME]["distribution"] = "fedora" - self.reference_config[DEFAULT_JOB_NAME]["packages"] = ["openssh-clients", "httpd", "tar"] - - def prepare_mkosi_conf_d_1(self, directory: str) -> None: - ini_lines = [ - "[Distribution]", - "Distribution=ubuntu", - "", - "[Content]", - "Packages= ", - " !httpd", - " apache2", - "", - "[Output]", - "KernelCommandLine=console=ttyS0", - ] - dname = os.path.join(directory, "mkosi.conf.d") - if not os.path.exists(dname): - os.makedirs(dname) - with open(os.path.join(dname, "1_ubuntu.conf"), "w") as f_ini: - f_ini.write(os.linesep.join(ini_lines)) - self.reference_config[DEFAULT_JOB_NAME]["distribution"] = "ubuntu" - if "httpd" in self.reference_config[DEFAULT_JOB_NAME]["packages"]: - self.reference_config[DEFAULT_JOB_NAME]["packages"].remove("httpd") - self.reference_config[DEFAULT_JOB_NAME]["packages"].append("apache2") - self.reference_config[DEFAULT_JOB_NAME]["kernel_command_line"].extend(["console=ttyS0"]) - - def prepare_mkosi_conf_d_2(self, directory: str) -> None: - ini_lines = [ - "[Content]", - "Packages=[ vim,!vi", - " ca-certificates, bzip ] ", - "[Output]", - "KernelCommandLine=console=ttyS1", - " driver.feature=1", - ] - dname = os.path.join(directory, "mkosi.conf.d") - if not os.path.exists(dname): - os.makedirs(dname) - with open(os.path.join(dname, "2_additional_stuff.conf"), "w") as f_ini: - f_ini.write(os.linesep.join(ini_lines)) - if "vi" in self.reference_config[DEFAULT_JOB_NAME]["packages"]: - self.reference_config[DEFAULT_JOB_NAME]["packages"].remove("vi") - self.reference_config[DEFAULT_JOB_NAME]["packages"].extend(["vim", "ca-certificates", "bzip"]) - self.reference_config[DEFAULT_JOB_NAME]["kernel_command_line"].extend(["console=ttyS1", "driver.feature=1"]) - - -class MkosiConfigIniLists2(MkosiConfigIniLists1): - """Same as MkosiConfigIniLists2 but with clean KernelCommandLine""" - - def prepare_mkosi_conf(self, directory: str) -> None: - ini_lines = ["[Output]", "KernelCommandLine=!*"] - with open(os.path.join(directory, "mkosi.conf"), "w") as f_ini: - f_ini.write(os.linesep.join(ini_lines)) - self.reference_config[DEFAULT_JOB_NAME]["kernel_command_line"] = [] - - -# pytest magic: run each test function with each class derived from MkosiConfigOne -@pytest.fixture(params=MkosiConfigOne.__subclasses__()) -def tested_config(request: Any) -> Any: - return request.param() - - -def test_verb_none(tmpdir: Path) -> None: - with change_cwd(tmpdir): - args = mkosi.parse_args([]) - assert args["default"].verb == Verb.build - - -def test_verb_build(tmpdir: Path) -> None: - with change_cwd(tmpdir): - args = mkosi.parse_args(["build"]) - assert args["default"].verb == Verb.build - - -def test_verb_boot_no_cli_args1(tmpdir: Path) -> None: - with change_cwd(tmpdir): - cmdline_ref = ["boot", "--par-for-sub", "--pom", "--for_sub", "1234"] - args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == Verb.boot - assert args["default"].cmdline == cmdline_ref[1:] - - -def test_verb_boot_no_cli_args2(tmpdir: Path) -> None: - with change_cwd(tmpdir): - cmdline_ref = ["-pa-package", "boot", "--par-for-sub", "--popenssl", "--for_sub", "1234"] - args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == Verb.boot - assert "a-package" in args["default"].packages - assert args["default"].cmdline == cmdline_ref[2:] - - -def test_verb_boot_no_cli_args3(tmpdir: Path) -> None: - with change_cwd(tmpdir): - cmdline_ref = ["-pa-package", "-p", "another-package", "build"] - args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == Verb.build - assert args["default"].packages == ["a-package", "another-package"] - - -def test_verb_summary_no_cli_args4(tmpdir: Path) -> None: - with change_cwd(tmpdir): - cmdline_ref = ["-pa-package", "-p", "another-package", "summary"] - args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == Verb.summary - assert args["default"].packages == ["a-package", "another-package"] - - -def test_verb_shell_cli_args5(tmpdir: Path) -> None: - with change_cwd(tmpdir): - cmdline_ref = ["-pa-package", "-p", "another-package", "shell", "python3 -foo -bar;", "ls --inode"] - args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == Verb.shell - assert args["default"].packages == ["a-package", "another-package"] - assert args["default"].cmdline == cmdline_ref[4:] - - -def test_verb_shell_cli_args6(tmpdir: Path) -> None: - with change_cwd(tmpdir): - cmdline_ref = ["-i", "yes", "summary"] - args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == Verb.summary - assert args["default"].incremental == True - - -def test_verb_shell_cli_args7(tmpdir: Path) -> None: - with change_cwd(tmpdir): - cmdline_ref = ["-i", "summary"] - args = mkosi.parse_args(cmdline_ref) - assert args["default"].verb == Verb.summary - assert args["default"].incremental == True - - -def test_builtin(tested_config: Any, tmpdir: Path) -> None: - """Test if builtin config and reference config match""" - with change_cwd(tmpdir): - if "--all" in tested_config.cli_arguments: - with pytest.raises(MkosiException): - mkosi.parse_args(tested_config.cli_arguments) - else: - args = mkosi.parse_args(tested_config.cli_arguments) - assert tested_config == args - - -def test_def(tested_config: Any, tmpdir: Path) -> None: - """Generate the mkosi.conf file only""" - with change_cwd(tmpdir): - tested_config.prepare_mkosi_conf(tmpdir) - args = mkosi.parse_args(tested_config.cli_arguments) - assert tested_config == args - - -def test_def_1(tested_config: Any, tmpdir: Path) -> None: - """Generate the mkosi.conf file plus one config file""" - with change_cwd(tmpdir): - tested_config.prepare_mkosi_conf(tmpdir) - tested_config.prepare_mkosi_conf_d_1(tmpdir) - args = mkosi.parse_args(tested_config.cli_arguments) - assert tested_config == args - - -def test_def_2(tested_config: Any, tmpdir: Path) -> None: - """Generate the mkosi.conf file plus another config file""" - with change_cwd(tmpdir): - tested_config.prepare_mkosi_conf(tmpdir) - tested_config.prepare_mkosi_conf_d_2(tmpdir) - args = mkosi.parse_args(tested_config.cli_arguments) - assert tested_config == args - - -def test_def_1_2(tested_config: Any, tmpdir: Path) -> None: - """Generate the mkosi.conf file plus two config files""" - with change_cwd(tmpdir): - tested_config.prepare_mkosi_conf(tmpdir) - tested_config.prepare_mkosi_conf_d_1(tmpdir) - tested_config.prepare_mkosi_conf_d_2(tmpdir) - args = mkosi.parse_args(tested_config.cli_arguments) - assert tested_config == args - - -def test_def_args(tested_config: Any, tmpdir: Path) -> None: - """Generate the mkosi.conf plus command line arguments""" - with change_cwd(tmpdir): - tested_config.prepare_args() - args = mkosi.parse_args(tested_config.cli_arguments) - assert tested_config == args - - -def test_def_1_args(tested_config: Any, tmpdir: Path) -> None: - """Generate the mkosi.conf plus a config file plus command line arguments""" - with change_cwd(tmpdir): - tested_config.prepare_mkosi_conf(tmpdir) - tested_config.prepare_mkosi_conf_d_1(tmpdir) - tested_config.prepare_args() - args = mkosi.parse_args(tested_config.cli_arguments) - assert tested_config == args - - -def test_def_1_2_args(tested_config: Any, tmpdir: Path) -> None: - """Generate the mkosi.conf plus two config files plus command line arguments""" - with change_cwd(tmpdir): - tested_config.prepare_mkosi_conf(tmpdir) - tested_config.prepare_mkosi_conf_d_1(tmpdir) - tested_config.prepare_mkosi_conf_d_2(tmpdir) - tested_config.prepare_args() - args = mkosi.parse_args(tested_config.cli_arguments) - assert tested_config == args - - -def test_def_1_2_argssh(tested_config: Any, tmpdir: Path) -> None: - """Generate the mkosi.conf plus two config files plus short command line arguments""" - with change_cwd(tmpdir): - tested_config.prepare_mkosi_conf(tmpdir) - tested_config.prepare_mkosi_conf_d_1(tmpdir) - tested_config.prepare_mkosi_conf_d_2(tmpdir) - tested_config.prepare_args_short() - args = mkosi.parse_args(tested_config.cli_arguments) - assert tested_config == args - - -class MkosiConfigAll(MkosiConfig): - """Classes derived from this class are magically instantiated by pytest - - Each test_ function with a parameter named "tested_config_all" gets - called by pytest for each class derived from this class. - """ - - -class MkosiConfigAllHost(MkosiConfigAll): - """Test --all option with two simple configs""" - - def __init__(self) -> None: - """Add two default mkosi.conf configs""" - super().__init__() - for hostname in ["test1.example.org", "test2.example.org"]: - job_name = "mkosi." + hostname - self.add_reference_config(job_name) - self.reference_config[job_name]["all"] = True - self.reference_config[job_name]["hostname"] = hostname - self.cli_arguments = ["--all", "build"] - - def prepare_mkosi_files(self, directory: str, all_directory: Optional[Path] = None) -> None: - if all_directory is None: - all_dir = os.path.abspath("mkosi.files") - else: - all_dir = os.path.join(directory, all_directory) - - for job_name, config in self.reference_config.items(): - mk_config = {"Output": {"Hostname": config["hostname"]}} - MkosiConfig.write_ini(all_dir, job_name, mk_config) - - if all_directory: - self.cli_arguments[0:0] = ["--all-directory", "all_dir"] - - -# pytest magic: run each test function with each class derived from MkosiConfigAll -@pytest.fixture(params=MkosiConfigAll.__subclasses__()) -def tested_config_all(request: Any) -> Any: - return request.param() - - -def test_all_1(tested_config_all: Any, tmpdir: Path) -> None: - """Generate the mkosi.conf plus two config files plus short command line arguments""" - with change_cwd(tmpdir): - tested_config_all.prepare_mkosi_files(tmpdir) - args = mkosi.parse_args(tested_config_all.cli_arguments) - assert tested_config_all == args