""" Tests for the enhanced exception handling system """ import pytest from deb_mock.exceptions import ( BuildError, CacheError, ChrootError, ConfigurationError, DebMockError, DependencyError, NetworkError, PermissionError, SbuildError, ValidationError, format_error_context, handle_exception, ) class TestDebMockError: """Test the base DebMockError class""" def test_basic_error(self): """Test basic error creation""" error = DebMockError("Test error message") assert str(error) == "Error: Test error message" assert error.exit_code == 1 assert error.context == {} assert error.suggestions == [] def test_error_with_context(self): """Test error with context information""" context = {"file": "/path/to/file", "operation": "read"} error = DebMockError("File operation failed", context=context) expected = """Error: File operation failed Context: file: /path/to/file operation: read""" assert str(error) == expected def test_error_with_suggestions(self): """Test error with suggestions""" suggestions = ["Try again", "Check permissions", "Contact admin"] error = DebMockError("Operation failed", suggestions=suggestions) expected = """Error: Operation failed Suggestions: 1. Try again 2. Check permissions 3. Contact admin""" assert str(error) == expected def test_error_with_context_and_suggestions(self): """Test error with both context and suggestions""" context = {"config_file": "/etc/deb-mock.conf"} suggestions = ["Check config syntax", "Verify file exists"] error = DebMockError("Invalid configuration", context=context, suggestions=suggestions) expected = """Error: Invalid configuration Context: config_file: /etc/deb-mock.conf Suggestions: 1. Check config syntax 2. Verify file exists""" assert str(error) == expected def test_print_error(self, capsys): """Test error printing to stderr""" error = DebMockError("Test error") # Just test that print_error doesn't crash error.print_error() # If we get here, the method executed successfully assert True def test_get_exit_code(self): """Test exit code retrieval""" error = DebMockError("Test error", exit_code=42) assert error.get_exit_code() == 42 class TestSpecificExceptions: """Test specific exception types""" def test_configuration_error(self): """Test ConfigurationError with file and section context""" error = ConfigurationError( "Invalid configuration", config_file="/etc/deb-mock.conf", config_section="chroot", ) assert "config_file: /etc/deb-mock.conf" in str(error) assert "config_section: chroot" in str(error) assert error.exit_code == 2 assert len(error.suggestions) > 0 def test_chroot_error(self): """Test ChrootError with operation context""" error = ChrootError( "Failed to create chroot", chroot_name="bookworm-amd64", operation="create", chroot_path="/var/lib/deb-mock/chroots/bookworm-amd64", ) assert "chroot_name: bookworm-amd64" in str(error) assert "operation: create" in str(error) assert error.exit_code == 3 assert "clean-chroot" in str(error.suggestions[3]) def test_sbuild_error(self): """Test SbuildError with build context""" error = SbuildError( "Build failed", sbuild_config="/etc/sbuild/sbuild.conf", build_log="/var/log/sbuild.log", return_code=1, ) assert "sbuild_config: /etc/sbuild/sbuild.conf" in str(error) assert "build_log: /var/log/sbuild.log" in str(error) assert "return_code: 1" in str(error) assert error.exit_code == 4 def test_build_error(self): """Test BuildError with source package context""" error = BuildError( "Package build failed", source_package="hello_1.0.dsc", build_log="/tmp/build.log", artifacts=["hello_1.0-1_amd64.deb"], ) assert "source_package: hello_1.0.dsc" in str(error) assert "build_log: /tmp/build.log" in str(error) assert "artifacts: ['hello_1.0-1_amd64.deb']" in str(error) assert error.exit_code == 5 def test_dependency_error(self): """Test DependencyError with missing packages""" error = DependencyError( "Missing build dependencies", missing_packages=["build-essential", "devscripts"], conflicting_packages=["old-package"], ) assert "missing_packages: ['build-essential', 'devscripts']" in str(error) assert "conflicting_packages: ['old-package']" in str(error) assert error.exit_code == 6 def test_cache_error(self): """Test CacheError with cache context""" error = CacheError( "Cache operation failed", cache_type="root_cache", cache_path="/var/cache/deb-mock/root-cache", operation="restore", ) assert "cache_type: root_cache" in str(error) assert "cache_path: /var/cache/deb-mock/root-cache" in str(error) assert "operation: restore" in str(error) assert error.exit_code == 8 def test_network_error(self): """Test NetworkError with network context""" error = NetworkError( "Repository access failed", url="http://deb.debian.org/debian/", proxy="http://proxy.example.com:3128", timeout=30, ) assert "url: http://deb.debian.org/debian/" in str(error) assert "proxy: http://proxy.example.com:3128" in str(error) assert "timeout: 30" in str(error) assert error.exit_code == 10 def test_permission_error(self): """Test PermissionError with permission context""" error = PermissionError( "Insufficient privileges", operation="create_chroot", path="/var/lib/deb-mock", required_privileges="root", ) assert "operation: create_chroot" in str(error) assert "path: /var/lib/deb-mock" in str(error) assert "required_privileges: root" in str(error) assert error.exit_code == 11 def test_validation_error(self): """Test ValidationError with validation context""" error = ValidationError( "Invalid architecture", field="architecture", value="invalid-arch", expected_format="amd64, i386, arm64, etc.", ) assert "field: architecture" in str(error) assert "value: invalid-arch" in str(error) assert "expected_format: amd64, i386, arm64, etc." in str(error) assert error.exit_code == 12 class TestHelperFunctions: """Test helper functions""" def test_format_error_context(self): """Test format_error_context helper""" context = format_error_context(file="/path/to/file", operation="read", user="testuser", none_value=None) expected = {"file": "/path/to/file", "operation": "read", "user": "testuser"} assert context == expected assert "none_value" not in context def test_handle_exception_decorator_success(self): """Test handle_exception decorator with successful function""" @handle_exception def successful_function(): return "success" result = successful_function() assert result == "success" def test_handle_exception_decorator_debmock_error(self, capsys): """Test handle_exception decorator with DebMockError""" @handle_exception def failing_function(): raise ConfigurationError("Config error", config_file="/etc/config") with pytest.raises(SystemExit) as exc_info: failing_function() # Test that the decorator exits with the correct code assert exc_info.value.code == 2 # The error message was printed (we can see it in the test output) # Just verify the decorator handled the exception correctly assert True def test_handle_exception_decorator_unexpected_error(self, capsys): """Test handle_exception decorator with unexpected error""" @handle_exception def unexpected_error_function(): raise ValueError("Unexpected value error") with pytest.raises(SystemExit) as exc_info: unexpected_error_function() # Test that the decorator exits with the correct code assert exc_info.value.code == 1 # The error message was printed (we can see it in the test output) # Just verify the decorator handled the exception correctly assert True class TestExceptionIntegration: """Test exception integration scenarios""" def test_chroot_creation_error_scenario(self): """Test realistic chroot creation error scenario""" error = ChrootError( "Failed to create chroot environment", chroot_name="bookworm-amd64", operation="debootstrap", chroot_path="/var/lib/deb-mock/chroots/bookworm-amd64", ) error_str = str(error) # Check that all context information is present assert "chroot_name: bookworm-amd64" in error_str assert "operation: debootstrap" in error_str assert "chroot_path: /var/lib/deb-mock/chroots/bookworm-amd64" in error_str # Check that helpful suggestions are provided assert "sufficient disk space" in error_str assert "root privileges" in error_str assert "clean-chroot" in error_str # Check exit code assert error.exit_code == 3 def test_build_failure_scenario(self): """Test realistic build failure scenario""" error = BuildError( "Package build failed due to compilation errors", source_package="myapp_1.0.dsc", build_log="/tmp/build_myapp.log", artifacts=[], ) error_str = str(error) # Check context information assert "source_package: myapp_1.0.dsc" in error_str assert "build_log: /tmp/build_myapp.log" in error_str # Check helpful suggestions assert "build log" in error_str assert "build dependencies" in error_str assert "verbose output" in error_str # Check exit code assert error.exit_code == 5 def test_dependency_resolution_scenario(self): """Test realistic dependency resolution scenario""" error = DependencyError( "Unable to resolve build dependencies", missing_packages=["libssl-dev", "libcurl4-openssl-dev"], conflicting_packages=["libssl1.0-dev"], ) error_str = str(error) # Check context information assert "libssl-dev" in error_str assert "libcurl4-openssl-dev" in error_str assert "libssl1.0-dev" in error_str # Check helpful suggestions assert "Install missing build dependencies" in error_str assert "Resolve package conflicts" in error_str assert "update-chroot" in error_str # Check exit code assert error.exit_code == 6