deb-bootc-image-builder/test/test_opts.py

290 lines
11 KiB
Python

#!/usr/bin/env python3
"""
Test command line options for deb-bootc-image-builder.
This module tests command line argument parsing and validation,
including:
- Required arguments
- Optional arguments
- Argument validation
- Debian-specific options
"""
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 TestCommandLineOptions:
"""Test cases for command line options."""
def test_required_arguments(self, work_dir):
"""Test required command line arguments."""
# Test minimum required arguments
required_args = {
"container": "debian:trixie",
"output": work_dir
}
# Validate required arguments
for arg_name, arg_value in required_args.items():
assert arg_value is not None, f"Required argument {arg_name} is None"
if arg_name == "output":
assert os.path.exists(arg_value), f"Output directory {arg_value} does not exist"
def test_optional_arguments(self, work_dir):
"""Test optional command line arguments."""
# Test optional arguments with default values
optional_args = {
"release": "trixie",
"arch": "amd64",
"image_type": "qcow2",
"verbose": False,
"clean": False
}
# Validate optional arguments
for arg_name, arg_value in optional_args.items():
assert arg_name in optional_args, f"Optional argument {arg_name} not found"
assert arg_value is not None, f"Optional argument {arg_name} has no default value"
def test_debian_specific_options(self, work_dir):
"""Test Debian-specific command line options."""
# Test Debian-specific options
debian_options = {
"release": "trixie",
"arch": "amd64",
"package_manager": "apt",
"initramfs_tools": True,
"grub_efi": True
}
# Validate Debian-specific options
assert debian_options["release"] in ["trixie", "bookworm", "bullseye"], \
f"Invalid Debian release: {debian_options['release']}"
assert debian_options["arch"] in ["amd64", "arm64", "i386"], \
f"Invalid architecture: {debian_options['arch']}"
assert debian_options["package_manager"] == "apt", \
f"Invalid package manager: {debian_options['package_manager']}"
assert debian_options["initramfs_tools"] is True, \
"initramfs-tools should be enabled for Debian"
assert debian_options["grub_efi"] is True, \
"GRUB EFI should be enabled for Debian"
def test_argument_validation(self, work_dir):
"""Test argument validation logic."""
# Test valid arguments
valid_args = {
"container": "debian:trixie",
"output": work_dir,
"release": "trixie",
"arch": "amd64"
}
validation_result = self._validate_arguments(valid_args)
assert validation_result["valid"] is True, \
f"Valid arguments failed validation: {validation_result.get('error', 'Unknown error')}"
# Test invalid arguments
invalid_args = {
"container": "invalid:image",
"output": "/nonexistent/path",
"release": "invalid-release",
"arch": "invalid-arch"
}
validation_result = self._validate_arguments(invalid_args)
assert validation_result["valid"] is False, \
"Invalid arguments should fail validation"
def test_output_directory_handling(self, work_dir):
"""Test output directory handling."""
# Test existing directory
existing_dir = work_dir
result = self._handle_output_directory(existing_dir)
assert result["success"] is True, \
f"Existing directory handling failed: {result.get('error', 'Unknown error')}"
# Test non-existent directory creation
new_dir = os.path.join(work_dir, "new_output")
result = self._handle_output_directory(new_dir)
assert result["success"] is True, \
f"New directory creation failed: {result.get('error', 'Unknown error')}"
assert os.path.exists(new_dir), "New directory was not created"
# Test invalid directory path
invalid_dir = "/invalid/path/with/permissions/issue"
result = self._handle_output_directory(invalid_dir)
assert result["success"] is False, "Invalid directory should fail"
def test_container_image_validation(self, work_dir):
"""Test container image validation."""
# Test valid Debian image
valid_image = "debian:trixie"
result = self._validate_container_image(valid_image)
assert result["valid"] is True, \
f"Valid Debian image failed validation: {result.get('error', 'Unknown error')}"
# Test invalid image
invalid_image = "invalid:image"
result = self._validate_container_image(invalid_image)
assert result["valid"] is False, "Invalid image should fail validation"
# Test image with specific architecture
arch_image = "debian:trixie-amd64"
result = self._validate_container_image(arch_image)
assert result["valid"] is True, \
f"Architecture-specific image failed validation: {result.get('error', 'Unknown error')}"
def test_package_list_validation(self, work_dir):
"""Test package list validation."""
# Test valid Debian packages
valid_packages = [
"linux-image-amd64",
"systemd",
"ostree",
"grub-efi-amd64",
"initramfs-tools"
]
result = self._validate_package_list(valid_packages)
assert result["valid"] is True, \
f"Valid packages failed validation: {result.get('error', 'Unknown error')}"
# Test invalid packages
invalid_packages = [
"invalid-package",
"nonexistent-package"
]
result = self._validate_package_list(invalid_packages)
assert result["valid"] is False, "Invalid packages should fail validation"
def test_manifest_generation(self, work_dir):
"""Test manifest generation from command line options."""
# Test manifest generation
options = {
"container": "debian:trixie",
"release": "trixie",
"arch": "amd64",
"image_type": "qcow2",
"packages": ["linux-image-amd64", "systemd", "ostree"]
}
manifest = self._generate_manifest(options)
# Validate generated manifest
assert "pipeline" in manifest
assert "build" in manifest["pipeline"]
assert "stages" in manifest["pipeline"]
# Validate Debian-specific content
build_stage = manifest["pipeline"]["build"]
assert build_stage["name"] == "org.osbuild.debian-filesystem"
# Validate APT stage
apt_stage = next((s for s in manifest["pipeline"]["stages"]
if s["name"] == "org.osbuild.apt"), None)
assert apt_stage is not None
assert apt_stage["options"]["release"] == "trixie"
assert apt_stage["options"]["arch"] == "amd64"
def _validate_arguments(self, args):
"""Mock argument validation."""
# Check required arguments
if "container" not in args or not args["container"]:
return {"valid": False, "error": "Container image is required"}
if "output" not in args or not args["output"]:
return {"valid": False, "error": "Output directory is required"}
# Check Debian-specific validation
if "release" in args:
valid_releases = ["trixie", "bookworm", "bullseye"]
if args["release"] not in valid_releases:
return {"valid": False, "error": f"Invalid Debian release: {args['release']}"}
if "arch" in args:
valid_archs = ["amd64", "arm64", "i386"]
if args["arch"] not in valid_archs:
return {"valid": False, "error": f"Invalid architecture: {args['arch']}"}
return {"valid": True}
def _handle_output_directory(self, output_dir):
"""Mock output directory handling."""
try:
if not os.path.exists(output_dir):
os.makedirs(output_dir, exist_ok=True)
# Test if directory is writable
test_file = os.path.join(output_dir, "test_write")
with open(test_file, 'w') as f:
f.write("test")
os.remove(test_file)
return {"success": True}
except Exception as e:
return {"success": False, "error": str(e)}
def _validate_container_image(self, image):
"""Mock container image validation."""
# Check if it's a valid Debian image
if image.startswith("debian:"):
return {"valid": True, "type": "debian"}
else:
return {"valid": False, "error": "Not a valid Debian image"}
def _validate_package_list(self, packages):
"""Mock package list validation."""
# Check if packages look like valid Debian packages
valid_packages = [
"linux-image-amd64", "systemd", "ostree", "grub-efi-amd64",
"initramfs-tools", "util-linux", "parted", "e2fsprogs"
]
for pkg in packages:
if pkg not in valid_packages:
return {"valid": False, "error": f"Invalid package: {pkg}"}
return {"valid": True}
def _generate_manifest(self, options):
"""Mock manifest generation."""
return {
"pipeline": {
"build": {
"name": "org.osbuild.debian-filesystem",
"options": {
"rootfs_type": "ext4",
"ostree_integration": True
}
},
"stages": [
{
"name": "org.osbuild.apt",
"options": {
"packages": options.get("packages", []),
"release": options.get("release", "trixie"),
"arch": options.get("arch", "amd64")
}
}
]
}
}
if __name__ == "__main__":
pytest.main([__file__])