From e24af61e2278cf1f58f8c56f5eca6269cf54b07e Mon Sep 17 00:00:00 2001 From: Victor Zacarias Date: Wed, 12 Aug 2026 21:25:05 -0300 Subject: [PATCH] Fix examples/config-sample.json and cover the example configs with a test (#4709) * Fix examples/config-sample.json to match the current config format The sample config has not been valid since the 2023 disk layout rework and currently fails to parse, so the file the README points users at cannot be used: - sector_size was null, but SectorSize became a required object - partitions were missing the dev_path key, which the parser reads - the /home size used the Percent unit, which no longer exists - /home started at 20 GiB while / ended at 20993 MiB, overlapping it - gfx_driver kept the old "All open-source (default)" value Sizes and keys now mirror what the installer itself writes when saving a configuration. * Cover the example configs with a parsing test Nothing in the test suite or CI reads examples/, which is how the sample config could stay broken for years while every other config surface kept working. Parse both example files through ArchConfigHandler, and check the partition entries directly since the parser only reaches them when the configured device exists on the machine, which is never true in CI. * Fail the partition test when the example config has none The loops in test_example_config_partitions would not execute if device_modifications or a device's partitions were empty, so the test could pass while checking nothing. --- examples/config-sample.json | 43 +++++++++++++++++++++------- tests/conftest.py | 10 +++++++ tests/test_args.py | 57 ++++++++++++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 12 deletions(-) diff --git a/examples/config-sample.json b/examples/config-sample.json index ac366b6c..be2769ce 100644 --- a/examples/config-sample.json +++ b/examples/config-sample.json @@ -17,12 +17,16 @@ "partitions": [ { "btrfs": [], + "dev_path": null, "flags": [ "boot" ], "fs_type": "fat32", "size": { - "sector_size": null, + "sector_size": { + "unit": "B", + "value": 512 + }, "unit": "MiB", "value": 512 }, @@ -30,7 +34,10 @@ "mountpoint": "/boot", "obj_id": "2c3fa2d5-2c79-4fab-86ec-22d0ea1543c0", "start": { - "sector_size": null, + "sector_size": { + "unit": "B", + "value": 512 + }, "unit": "MiB", "value": 1 }, @@ -39,10 +46,14 @@ }, { "btrfs": [], + "dev_path": null, "flags": [], "fs_type": "ext4", "size": { - "sector_size": null, + "sector_size": { + "unit": "B", + "value": 512 + }, "unit": "GiB", "value": 20 }, @@ -50,7 +61,10 @@ "mountpoint": "/", "obj_id": "3e7018a0-363b-4d05-ab83-8e82d13db208", "start": { - "sector_size": null, + "sector_size": { + "unit": "B", + "value": 512 + }, "unit": "MiB", "value": 513 }, @@ -59,20 +73,27 @@ }, { "btrfs": [], + "dev_path": null, "flags": [], "fs_type": "ext4", "size": { - "sector_size": null, - "unit": "Percent", - "value": 100 + "sector_size": { + "unit": "B", + "value": 512 + }, + "unit": "GiB", + "value": 10 }, "mount_options": [], "mountpoint": "/home", "obj_id": "ce58b139-f041-4a06-94da-1f8bad775d3f", "start": { - "sector_size": null, - "unit": "GiB", - "value": 20 + "sector_size": { + "unit": "B", + "value": 512 + }, + "unit": "MiB", + "value": 20993 }, "status": "create", "type": "primary" @@ -138,7 +159,7 @@ "parallel_downloads": 5 }, "profile_config": { - "gfx_driver": "All open-source (default)", + "gfx_driver": "All open-source", "greeter": "sddm", "profile": { "details": [ diff --git a/tests/conftest.py b/tests/conftest.py index 819c8397..d3f2bc7e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,6 +8,16 @@ def config_fixture() -> Path: return Path(__file__).parent / 'data' / 'test_config.json' +@pytest.fixture(scope='session') +def example_config_fixture() -> Path: + return Path(__file__).parent.parent / 'examples' / 'config-sample.json' + + +@pytest.fixture(scope='session') +def example_creds_fixture() -> Path: + return Path(__file__).parent.parent / 'examples' / 'creds-sample.json' + + @pytest.fixture(scope='session') def btrfs_config_fixture() -> Path: return Path(__file__).parent / 'data' / 'test_config_btrfs.json' diff --git a/tests/test_args.py b/tests/test_args.py index 324f5a11..685c01ff 100644 --- a/tests/test_args.py +++ b/tests/test_args.py @@ -1,3 +1,4 @@ +import json import os from importlib.metadata import version from pathlib import Path @@ -17,7 +18,7 @@ from archinstall.lib.models.application import ( ) from archinstall.lib.models.authentication import AuthenticationConfiguration, U2FLoginConfiguration, U2FLoginMethod from archinstall.lib.models.bootloader import Bootloader, BootloaderConfiguration -from archinstall.lib.models.device import DiskLayoutConfiguration, DiskLayoutType +from archinstall.lib.models.device import DiskLayoutConfiguration, DiskLayoutType, Size from archinstall.lib.models.locale import LocaleConfiguration from archinstall.lib.models.mirrors import CustomRepository, CustomServer, MirrorConfiguration, MirrorRegion, SignCheck, SignOption from archinstall.lib.models.network import NetworkConfiguration, Nic, NicType @@ -388,3 +389,57 @@ def test_encrypted_creds_with_env_var( groups=[], ), ] + + +def test_example_config_parsing( + monkeypatch: MonkeyPatch, + example_config_fixture: Path, + example_creds_fixture: Path, +) -> None: + monkeypatch.setattr( + 'sys.argv', + [ + 'archinstall', + '--config', + str(example_config_fixture), + '--creds', + str(example_creds_fixture), + ], + ) + + handler = ArchConfigHandler() + arch_config = handler.config + + assert arch_config.disk_config is not None + assert arch_config.profile_config is not None + assert arch_config.auth_config is not None + assert arch_config.auth_config.users + + +def test_example_config_partitions(example_config_fixture: Path) -> None: + # partition entries are only parsed when the configured device is present on + # the machine, which is never the case in CI, so read them here directly + config = json.loads(example_config_fixture.read_text()) + device_modifications = config['disk_config']['device_modifications'] + + assert device_modifications + + for device in device_modifications: + partitions = device['partitions'] + + assert partitions + + previous_end = None + + for partition in partitions: + assert 'dev_path' in partition + + start = Size.parse_args(partition['start']) + end = start + Size.parse_args(partition['size']) + + assert start.is_valid_start() + + if previous_end is not None: + assert start >= previous_end + + previous_end = end