#!/usr/bin/env python3 """ Test utilities for deb-bootc-image-builder. This module provides common utilities for testing, including: - Test data generation - Mock objects - Helper functions """ import os import tempfile import shutil import json import yaml from typing import Dict, List, Any, Optional import logging # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class TestDataGenerator: """Generate test data for deb-bootc-image-builder tests.""" @staticmethod def create_debian_package_list() -> List[str]: """Create a list of Debian packages for testing.""" return [ "linux-image-amd64", "linux-headers-amd64", "systemd", "systemd-sysv", "dbus", "ostree", "grub-efi-amd64", "initramfs-tools", "util-linux", "parted", "e2fsprogs", "dosfstools", "efibootmgr", "sudo", "network-manager", "curl", "wget", "nano", "vim-tiny" ] @staticmethod def create_debian_repository_config() -> Dict[str, Any]: """Create Debian repository configuration for testing.""" return { "release": "trixie", "arch": "amd64", "repos": [ { "name": "debian", "baseurls": ["http://deb.debian.org/debian"], "enabled": True }, { "name": "debian-security", "baseurls": ["http://deb.debian.org/debian-security"], "enabled": True } ] } @staticmethod def create_ostree_config() -> Dict[str, Any]: """Create OSTree configuration for testing.""" return { "mode": "bare-user-only", "repo": "/var/lib/ostree/repo", "bootable": True, "deployment": { "osname": "debian", "ref": "debian/trixie/amd64" } } @staticmethod def create_grub_config() -> Dict[str, Any]: """Create GRUB configuration for testing.""" return { "uefi": True, "secure_boot": False, "timeout": 5, "default_entry": 0, "kernel_path": "/boot/vmlinuz", "initramfs_path": "/boot/initrd.img" } @staticmethod def create_filesystem_config() -> Dict[str, Any]: """Create filesystem configuration for testing.""" return { "rootfs_type": "ext4", "ostree_integration": True, "home_symlink": True, "users": [ { "name": "debian-user", "password": "debian", "groups": ["sudo", "users"] } ], "permissions": { "/etc/ostree": "755", "/var/lib/ostree": "755" } } class MockContainerImage: """Mock container image for testing.""" def __init__(self, labels: Optional[Dict[str, str]] = None): """Initialize mock container image.""" self.labels = labels or { "com.debian.bootc": "true", "ostree.bootable": "true", "org.debian.version": "13", "version": "1.0" } self.ref = "debian:trixie" self.arch = "amd64" self.os = "linux" def get_labels(self) -> Dict[str, str]: """Get image labels.""" return self.labels def get_ref(self) -> str: """Get image reference.""" return self.ref def get_arch(self) -> str: """Get image architecture.""" return self.arch def get_os(self) -> str: """Get image operating system.""" return self.os class MockOSTreeRepo: """Mock OSTree repository for testing.""" def __init__(self, path: str): """Initialize mock OSTree repository.""" self.path = path self.refs = ["debian/trixie/amd64"] self.deployments = [] def list_refs(self) -> List[str]: """List repository references.""" return self.refs def list_deployments(self) -> List[Dict[str, Any]]: """List repository deployments.""" return self.deployments def get_deployment_info(self, ref: str) -> Optional[Dict[str, Any]]: """Get deployment information.""" if ref in self.refs: return { "ref": ref, "osname": "debian", "bootable": True, "version": "13" } return None class TestEnvironment: """Test environment setup and teardown.""" def __init__(self, work_dir: str): """Initialize test environment.""" self.work_dir = work_dir self.original_cwd = os.getcwd() def setup(self): """Set up test environment.""" os.chdir(self.work_dir) # Create basic directory structure dirs = [ "etc", "var", "home", "boot", "usr", "usr/bin", "usr/lib", "usr/sbin", "var/lib", "var/lib/ostree", "var/home" ] for dir_path in dirs: full_path = os.path.join(self.work_dir, dir_path) os.makedirs(full_path, exist_ok=True) # Create /home -> /var/home symlink var_home = os.path.join(self.work_dir, "var", "home") home_link = os.path.join(self.work_dir, "home") if os.path.exists(home_link): os.remove(home_link) os.symlink(var_home, home_link) logger.info(f"Test environment set up in {self.work_dir}") def teardown(self): """Tear down test environment.""" os.chdir(self.original_cwd) logger.info("Test environment torn down") def create_test_file(self, path: str, content: str = ""): """Create a test file with specified content.""" full_path = os.path.join(self.work_dir, path.lstrip("/")) os.makedirs(os.path.dirname(full_path), exist_ok=True) with open(full_path, 'w') as f: f.write(content) return full_path def create_test_directory(self, path: str): """Create a test directory.""" full_path = os.path.join(self.work_dir, path.lstrip("/")) os.makedirs(full_path, exist_ok=True) return full_path def create_temp_manifest(manifest_data: Dict[str, Any]) -> str: """Create a temporary manifest file for testing.""" temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) try: json.dump(manifest_data, temp_file, indent=2) temp_file.close() return temp_file.name except Exception as e: temp_file.close() os.unlink(temp_file.name) raise e def cleanup_temp_files(*file_paths: str): """Clean up temporary files.""" for file_path in file_paths: try: if os.path.exists(file_path): os.unlink(file_path) except Exception as e: logger.warning(f"Failed to clean up {file_path}: {e}") def assert_filesystem_structure(work_dir: str, expected_dirs: List[str]): """Assert that expected filesystem structure exists.""" 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 found" assert os.path.isdir(full_path), f"{expected_dir} is not a directory" def assert_file_contents(file_path: str, expected_content: str): """Assert that file contains expected content.""" assert os.path.exists(file_path), f"File {file_path} not found" with open(file_path, 'r') as f: actual_content = f.read() assert actual_content == expected_content, \ f"File content mismatch in {file_path}" def create_mock_context(): """Create a mock osbuild context for testing.""" context = Mock() context.root = "/tmp/mock-root" def mock_run(cmd): mock_result = Mock() mock_result.returncode = 0 mock_result.stdout = b"mock output" mock_result.stderr = b"" return mock_result context.run = mock_run return context