#!/usr/bin/env python3 """ Test disk image building functionality for deb-bootc-image-builder. This module tests the disk image building pipeline, including: - Manifest validation - Package installation - Filesystem creation - Bootloader configuration """ import pytest import os import tempfile import shutil import json from unittest.mock import Mock, patch import logging # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class TestDiskImageBuilding: """Test cases for disk image building functionality.""" def test_manifest_validation(self, work_dir): """Test manifest validation for Debian images.""" # Create a test manifest manifest = { "pipeline": { "build": { "name": "org.osbuild.debian-filesystem", "options": { "rootfs_type": "ext4", "ostree_integration": True } }, "stages": [ { "name": "org.osbuild.apt", "options": { "packages": ["linux-image-amd64", "systemd"], "release": "trixie", "arch": "amd64" } } ] } } # Validate manifest structure assert "pipeline" in manifest assert "build" in manifest["pipeline"] assert "stages" in manifest["pipeline"] # Validate Debian-specific options build_stage = manifest["pipeline"]["build"] assert build_stage["name"] == "org.osbuild.debian-filesystem" assert build_stage["options"]["ostree_integration"] is True # Validate APT stage apt_stage = manifest["pipeline"]["stages"][0] assert apt_stage["name"] == "org.osbuild.apt" assert apt_stage["options"]["release"] == "trixie" assert "linux-image-amd64" in apt_stage["options"]["packages"] def test_debian_package_installation(self, work_dir): """Test Debian package installation pipeline.""" # Mock package installation with patch('subprocess.run') as mock_run: mock_run.return_value.returncode = 0 # Test package installation packages = ["linux-image-amd64", "systemd", "ostree"] result = self._install_packages(packages, work_dir) assert result is True mock_run.assert_called() def test_filesystem_creation(self, work_dir): """Test Debian filesystem creation.""" # Test filesystem structure fs_structure = self._create_filesystem_structure(work_dir) expected_dirs = ["/etc", "/var", "/home", "/boot", "/usr"] for expected_dir in expected_dirs: full_path = os.path.join(work_dir, expected_dir.lstrip("/")) assert os.path.exists(full_path), f"Directory {expected_dir} not created" # Test /home -> /var/home symlink home_link = os.path.join(work_dir, "home") var_home = os.path.join(work_dir, "var", "home") assert os.path.islink(home_link), "/home symlink not created" assert os.path.realpath(home_link) == var_home def test_ostree_integration(self, work_dir): """Test OSTree integration setup.""" # Test OSTree configuration ostree_config = self._setup_ostree_integration(work_dir) assert ostree_config["mode"] == "bare-user-only" assert ostree_config["repo"] == "/var/lib/ostree/repo" # Test OSTree repository creation repo_path = os.path.join(work_dir, "var", "lib", "ostree", "repo") assert os.path.exists(repo_path), "OSTree repository not created" def test_bootloader_configuration(self, work_dir): """Test GRUB bootloader configuration for Debian.""" # Test GRUB configuration grub_config = self._configure_grub(work_dir) assert "GRUB_DEFAULT" in grub_config assert "GRUB_TIMEOUT" in grub_config assert "GRUB_CMDLINE_LINUX" in grub_config # Test UEFI boot configuration uefi_config = self._configure_uefi_boot(work_dir) assert uefi_config["uefi_enabled"] is True assert uefi_config["secure_boot"] is False def _install_packages(self, packages, work_dir): """Mock package installation.""" # This would integrate with the actual APT stage logger.info(f"Installing packages: {packages}") return True def _create_filesystem_structure(self, work_dir): """Create basic filesystem structure.""" dirs = ["etc", "var", "home", "boot", "usr", "usr/bin", "usr/lib", "usr/sbin"] for dir_path in dirs: full_path = os.path.join(work_dir, dir_path) os.makedirs(full_path, exist_ok=True) # Create /home -> /var/home symlink var_home = os.path.join(work_dir, "var", "home") os.makedirs(var_home, exist_ok=True) home_link = os.path.join(work_dir, "home") if os.path.exists(home_link): os.remove(home_link) os.symlink(var_home, home_link) return {"status": "created", "directories": dirs} def _setup_ostree_integration(self, work_dir): """Set up OSTree integration.""" ostree_dir = os.path.join(work_dir, "var", "lib", "ostree", "repo") os.makedirs(ostree_dir, exist_ok=True) config = { "mode": "bare-user-only", "repo": "/var/lib/ostree/repo" } # Write OSTree configuration config_file = os.path.join(work_dir, "etc", "ostree", "ostree.conf") os.makedirs(os.path.dirname(config_file), exist_ok=True) with open(config_file, 'w') as f: f.write("[core]\n") f.write(f"mode={config['mode']}\n") f.write(f"repo={config['repo']}\n") return config def _configure_grub(self, work_dir): """Configure GRUB bootloader.""" grub_config = { "GRUB_DEFAULT": "0", "GRUB_TIMEOUT": "5", "GRUB_CMDLINE_LINUX": "console=ttyS0,115200n8 console=tty0" } # Write GRUB configuration grub_dir = os.path.join(work_dir, "etc", "default") os.makedirs(grub_dir, exist_ok=True) grub_file = os.path.join(grub_dir, "grub") with open(grub_file, 'w') as f: for key, value in grub_config.items(): f.write(f'{key}="{value}"\n') return grub_config def _configure_uefi_boot(self, work_dir): """Configure UEFI boot.""" uefi_config = { "uefi_enabled": True, "secure_boot": False, "boot_entries": ["debian", "debian-fallback"] } # Create UEFI boot directory efi_dir = os.path.join(work_dir, "boot", "efi", "EFI", "debian") os.makedirs(efi_dir, exist_ok=True) return uefi_config if __name__ == "__main__": pytest.main([__file__])