- Add MockAPIClient and MockEnvironment for external integration - Implement EnvironmentManager with full lifecycle support - Enhance plugin system with registry and BasePlugin class - Add comprehensive test suite and documentation - Include practical usage examples and plugin development guide
479 lines
18 KiB
Python
479 lines
18 KiB
Python
"""
|
|
Tests for deb-mock API
|
|
|
|
This module contains comprehensive tests for the deb-mock API to ensure
|
|
stability and reliability for external integrations.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import Mock, patch, MagicMock
|
|
|
|
# Add deb-mock to path
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
|
|
|
from deb_mock.api import MockAPIClient, MockEnvironment, MockConfigBuilder, create_client
|
|
from deb_mock.environment_manager import EnvironmentManager, EnvironmentInfo, BuildResult
|
|
from deb_mock.config import Config
|
|
from deb_mock.exceptions import ChrootError, ConfigurationError
|
|
|
|
|
|
class TestMockConfigBuilder(unittest.TestCase):
|
|
"""Test the MockConfigBuilder class"""
|
|
|
|
def setUp(self):
|
|
self.builder = MockConfigBuilder()
|
|
|
|
def test_basic_configuration(self):
|
|
"""Test basic configuration building"""
|
|
config = (self.builder
|
|
.environment("test-env")
|
|
.architecture("amd64")
|
|
.suite("trixie")
|
|
.mirror("http://test.debian.org/debian/")
|
|
.build())
|
|
|
|
self.assertEqual(config.chroot_name, "test-env")
|
|
self.assertEqual(config.architecture, "amd64")
|
|
self.assertEqual(config.suite, "trixie")
|
|
self.assertEqual(config.mirror, "http://test.debian.org/debian/")
|
|
|
|
def test_packages_configuration(self):
|
|
"""Test packages configuration"""
|
|
packages = ["build-essential", "devscripts", "cmake"]
|
|
config = self.builder.packages(packages).build()
|
|
|
|
self.assertEqual(config.chroot_additional_packages, packages)
|
|
|
|
def test_output_directory(self):
|
|
"""Test output directory configuration"""
|
|
output_dir = "/tmp/test-output"
|
|
config = self.builder.output_dir(output_dir).build()
|
|
|
|
self.assertEqual(config.output_dir, output_dir)
|
|
|
|
def test_cache_settings(self):
|
|
"""Test cache configuration"""
|
|
config = self.builder.cache_enabled(True).build()
|
|
self.assertTrue(config.use_root_cache)
|
|
|
|
config = self.builder.cache_enabled(False).build()
|
|
self.assertFalse(config.use_root_cache)
|
|
|
|
def test_parallel_jobs(self):
|
|
"""Test parallel jobs configuration"""
|
|
config = self.builder.parallel_jobs(8).build()
|
|
self.assertEqual(config.parallel_jobs, 8)
|
|
|
|
def test_verbose_debug(self):
|
|
"""Test verbose and debug configuration"""
|
|
config = (self.builder
|
|
.verbose(True)
|
|
.debug(True)
|
|
.build())
|
|
|
|
self.assertTrue(config.verbose)
|
|
self.assertTrue(config.debug)
|
|
|
|
|
|
class TestMockAPIClient(unittest.TestCase):
|
|
"""Test the MockAPIClient class"""
|
|
|
|
def setUp(self):
|
|
self.temp_dir = tempfile.mkdtemp()
|
|
self.config = Config(
|
|
chroot_dir=self.temp_dir,
|
|
output_dir=os.path.join(self.temp_dir, "output"),
|
|
chroot_config_dir=os.path.join(self.temp_dir, "config")
|
|
)
|
|
|
|
# Create necessary directories
|
|
os.makedirs(self.config.chroot_config_dir, exist_ok=True)
|
|
|
|
# Mock the DebMock class to avoid actual chroot operations
|
|
with patch('deb_mock.api.DebMock') as mock_deb_mock:
|
|
self.mock_deb_mock_instance = Mock()
|
|
mock_deb_mock.return_value = self.mock_deb_mock_instance
|
|
|
|
# Mock chroot manager
|
|
self.mock_chroot_manager = Mock()
|
|
self.mock_deb_mock_instance.chroot_manager = self.mock_chroot_manager
|
|
self.mock_chroot_manager.chroot_exists.return_value = False
|
|
self.mock_chroot_manager.get_chroot_info.return_value = {
|
|
'name': 'test-env',
|
|
'status': 'active',
|
|
'size': 1024,
|
|
'created': None,
|
|
'modified': None
|
|
}
|
|
|
|
# Mock other methods
|
|
self.mock_deb_mock_instance.init_chroot = Mock()
|
|
self.mock_deb_mock_instance.install_packages = Mock(return_value={'success': True})
|
|
self.mock_deb_mock_instance.clean_chroot = Mock()
|
|
self.mock_deb_mock_instance.list_chroots = Mock(return_value=[])
|
|
self.mock_deb_mock_instance.build = Mock(return_value={'success': True, 'artifacts': []})
|
|
self.mock_deb_mock_instance.build_parallel = Mock(return_value=[{'success': True}])
|
|
self.mock_deb_mock_instance.build_chain = Mock(return_value=[{'success': True}])
|
|
self.mock_deb_mock_instance.get_cache_stats = Mock(return_value={})
|
|
self.mock_deb_mock_instance.cleanup_caches = Mock(return_value={})
|
|
|
|
self.client = MockAPIClient(self.config)
|
|
|
|
def tearDown(self):
|
|
import shutil
|
|
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
|
|
|
def test_client_initialization(self):
|
|
"""Test client initialization"""
|
|
self.assertIsInstance(self.client, MockAPIClient)
|
|
self.assertEqual(self.client.config, self.config)
|
|
|
|
def test_create_environment(self):
|
|
"""Test environment creation"""
|
|
env = self.client.create_environment("test-env", "amd64", "trixie", ["build-essential"])
|
|
|
|
self.assertIsInstance(env, MockEnvironment)
|
|
self.assertEqual(env.name, "test-env")
|
|
self.mock_deb_mock_instance.init_chroot.assert_called_once_with("test-env", "amd64", "trixie")
|
|
self.mock_deb_mock_instance.install_packages.assert_called_once_with(["build-essential"])
|
|
|
|
def test_get_environment(self):
|
|
"""Test getting existing environment"""
|
|
# Mock existing environment
|
|
self.mock_chroot_manager.chroot_exists.return_value = True
|
|
|
|
env = self.client.get_environment("test-env")
|
|
|
|
self.assertIsInstance(env, MockEnvironment)
|
|
self.assertEqual(env.name, "test-env")
|
|
|
|
def test_get_nonexistent_environment(self):
|
|
"""Test getting non-existent environment"""
|
|
self.mock_chroot_manager.chroot_exists.return_value = False
|
|
|
|
with self.assertRaises(ValueError):
|
|
self.client.get_environment("nonexistent-env")
|
|
|
|
def test_list_environments(self):
|
|
"""Test listing environments"""
|
|
self.mock_deb_mock_instance.list_chroots.return_value = ["env1", "env2"]
|
|
|
|
environments = self.client.list_environments()
|
|
|
|
self.assertEqual(environments, ["env1", "env2"])
|
|
|
|
def test_remove_environment(self):
|
|
"""Test removing environment"""
|
|
self.client.remove_environment("test-env")
|
|
|
|
self.mock_deb_mock_instance.clean_chroot.assert_called_once_with("test-env")
|
|
|
|
def test_build_package(self):
|
|
"""Test building a package"""
|
|
result = self.client.build_package("/path/to/package.dsc", "test-env")
|
|
|
|
self.mock_deb_mock_instance.build.assert_called_once()
|
|
self.assertEqual(result['success'], True)
|
|
|
|
def test_build_parallel(self):
|
|
"""Test parallel building"""
|
|
packages = ["/path/to/pkg1.dsc", "/path/to/pkg2.dsc"]
|
|
results = self.client.build_parallel(packages, max_workers=2)
|
|
|
|
self.mock_deb_mock_instance.build_parallel.assert_called_once_with(packages, 2)
|
|
self.assertEqual(len(results), 1)
|
|
self.assertEqual(results[0]['success'], True)
|
|
|
|
def test_build_chain(self):
|
|
"""Test chain building"""
|
|
packages = ["/path/to/pkg1.dsc", "/path/to/pkg2.dsc"]
|
|
results = self.client.build_chain(packages)
|
|
|
|
self.mock_deb_mock_instance.build_chain.assert_called_once_with(packages)
|
|
self.assertEqual(len(results), 1)
|
|
self.assertEqual(results[0]['success'], True)
|
|
|
|
def test_environment_context_manager(self):
|
|
"""Test environment context manager"""
|
|
# Mock existing environment
|
|
self.mock_chroot_manager.chroot_exists.return_value = True
|
|
|
|
with self.client.environment("test-env") as env:
|
|
self.assertIsInstance(env, MockEnvironment)
|
|
self.assertEqual(env.name, "test-env")
|
|
self.assertTrue(env.is_active())
|
|
|
|
# Environment should be deactivated after context
|
|
self.assertFalse(env.is_active())
|
|
|
|
|
|
class TestMockEnvironment(unittest.TestCase):
|
|
"""Test the MockEnvironment class"""
|
|
|
|
def setUp(self):
|
|
self.mock_deb_mock = Mock()
|
|
self.mock_chroot_manager = Mock()
|
|
self.mock_deb_mock.chroot_manager = self.mock_chroot_manager
|
|
self.mock_chroot_manager.chroot_exists.return_value = True
|
|
self.mock_chroot_manager.execute_in_chroot.return_value = Mock(returncode=0, stdout="test output")
|
|
self.mock_chroot_manager.get_chroot_info.return_value = {'status': 'active'}
|
|
|
|
self.env = MockEnvironment("test-env", self.mock_deb_mock)
|
|
|
|
def test_environment_initialization(self):
|
|
"""Test environment initialization"""
|
|
self.assertEqual(self.env.name, "test-env")
|
|
self.assertFalse(self.env.is_active())
|
|
|
|
def test_activate_deactivate(self):
|
|
"""Test environment activation and deactivation"""
|
|
self.env.activate()
|
|
self.assertTrue(self.env.is_active())
|
|
|
|
self.env.deactivate()
|
|
self.assertFalse(self.env.is_active())
|
|
|
|
def test_activate_nonexistent_environment(self):
|
|
"""Test activating non-existent environment"""
|
|
self.mock_chroot_manager.chroot_exists.return_value = False
|
|
|
|
with self.assertRaises(ChrootError):
|
|
self.env.activate()
|
|
|
|
def test_execute_command(self):
|
|
"""Test command execution"""
|
|
self.env.activate()
|
|
|
|
result = self.env.execute(["ls", "-la"])
|
|
|
|
self.mock_chroot_manager.execute_in_chroot.assert_called_once_with(
|
|
"test-env", ["ls", "-la"], capture_output=True
|
|
)
|
|
self.assertEqual(result.returncode, 0)
|
|
|
|
def test_execute_command_string(self):
|
|
"""Test command execution with string command"""
|
|
self.env.activate()
|
|
|
|
result = self.env.execute("ls -la")
|
|
|
|
self.mock_chroot_manager.execute_in_chroot.assert_called_once_with(
|
|
"test-env", ["ls", "-la"], capture_output=True
|
|
)
|
|
|
|
def test_execute_command_inactive(self):
|
|
"""Test executing command on inactive environment"""
|
|
with self.assertRaises(RuntimeError):
|
|
self.env.execute(["ls"])
|
|
|
|
def test_install_packages(self):
|
|
"""Test package installation"""
|
|
self.env.activate()
|
|
|
|
result = self.env.install_packages(["build-essential"])
|
|
|
|
self.mock_deb_mock.install_packages.assert_called_once_with(["build-essential"])
|
|
self.assertEqual(result['success'], True)
|
|
|
|
def test_copy_in(self):
|
|
"""Test copying files into environment"""
|
|
self.env.activate()
|
|
|
|
self.env.copy_in("/local/file", "/chroot/file")
|
|
|
|
self.mock_chroot_manager.copy_to_chroot.assert_called_once_with(
|
|
"/local/file", "/chroot/file", "test-env"
|
|
)
|
|
|
|
def test_copy_out(self):
|
|
"""Test copying files out of environment"""
|
|
self.env.activate()
|
|
|
|
self.env.copy_out("/chroot/file", "/local/file")
|
|
|
|
self.mock_chroot_manager.copy_from_chroot.assert_called_once_with(
|
|
"/chroot/file", "/local/file", "test-env"
|
|
)
|
|
|
|
def test_get_info(self):
|
|
"""Test getting environment info"""
|
|
info = self.env.get_info()
|
|
|
|
self.mock_chroot_manager.get_chroot_info.assert_called_once_with("test-env")
|
|
self.assertEqual(info['status'], 'active')
|
|
|
|
|
|
class TestEnvironmentManager(unittest.TestCase):
|
|
"""Test the EnvironmentManager class"""
|
|
|
|
def setUp(self):
|
|
self.temp_dir = tempfile.mkdtemp()
|
|
self.config = Config(
|
|
chroot_dir=self.temp_dir,
|
|
output_dir=os.path.join(self.temp_dir, "output"),
|
|
chroot_config_dir=os.path.join(self.temp_dir, "config")
|
|
)
|
|
|
|
# Create necessary directories
|
|
os.makedirs(self.config.chroot_config_dir, exist_ok=True)
|
|
|
|
# Mock the DebMock class
|
|
with patch('deb_mock.environment_manager.DebMock') as mock_deb_mock:
|
|
self.mock_deb_mock_instance = Mock()
|
|
mock_deb_mock.return_value = self.mock_deb_mock_instance
|
|
|
|
# Mock chroot manager
|
|
self.mock_chroot_manager = Mock()
|
|
self.mock_deb_mock_instance.chroot_manager = self.mock_chroot_manager
|
|
self.mock_chroot_manager.chroot_exists.return_value = False
|
|
self.mock_chroot_manager.get_chroot_info.return_value = {
|
|
'name': 'test-env',
|
|
'status': 'active',
|
|
'size': 1024,
|
|
'created': None,
|
|
'modified': None
|
|
}
|
|
self.mock_chroot_manager.list_mounts.return_value = []
|
|
|
|
# Mock other methods
|
|
self.mock_deb_mock_instance.init_chroot = Mock()
|
|
self.mock_deb_mock_instance.install_packages = Mock(return_value={'success': True})
|
|
self.mock_deb_mock_instance.clean_chroot = Mock()
|
|
self.mock_deb_mock_instance.list_chroots = Mock(return_value=[])
|
|
self.mock_deb_mock_instance.build = Mock(return_value={'success': True, 'artifacts': []})
|
|
self.mock_deb_mock_instance.update_chroot = Mock()
|
|
|
|
self.manager = EnvironmentManager(self.config)
|
|
|
|
def tearDown(self):
|
|
import shutil
|
|
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
|
|
|
def test_manager_initialization(self):
|
|
"""Test manager initialization"""
|
|
self.assertIsInstance(self.manager, EnvironmentManager)
|
|
self.assertEqual(self.manager.config, self.config)
|
|
|
|
def test_create_environment(self):
|
|
"""Test environment creation"""
|
|
info = self.manager.create_environment("test-env", "amd64", "trixie", ["build-essential"])
|
|
|
|
self.assertIsInstance(info, EnvironmentInfo)
|
|
self.assertEqual(info.name, "test-env")
|
|
self.assertEqual(info.architecture, "amd64")
|
|
self.assertEqual(info.suite, "trixie")
|
|
self.mock_deb_mock_instance.init_chroot.assert_called_once_with("test-env", "amd64", "trixie")
|
|
|
|
def test_environment_exists(self):
|
|
"""Test checking if environment exists"""
|
|
self.mock_chroot_manager.chroot_exists.return_value = True
|
|
|
|
self.assertTrue(self.manager.environment_exists("test-env"))
|
|
|
|
self.mock_chroot_manager.chroot_exists.return_value = False
|
|
|
|
self.assertFalse(self.manager.environment_exists("test-env"))
|
|
|
|
def test_get_environment_info(self):
|
|
"""Test getting environment info"""
|
|
self.mock_chroot_manager.chroot_exists.return_value = True
|
|
|
|
info = self.manager.get_environment_info("test-env")
|
|
|
|
self.assertIsInstance(info, EnvironmentInfo)
|
|
self.assertEqual(info.name, "test-env")
|
|
|
|
def test_get_nonexistent_environment_info(self):
|
|
"""Test getting info for non-existent environment"""
|
|
self.mock_chroot_manager.chroot_exists.return_value = False
|
|
|
|
with self.assertRaises(ValueError):
|
|
self.manager.get_environment_info("nonexistent-env")
|
|
|
|
def test_list_environments(self):
|
|
"""Test listing environments"""
|
|
self.mock_deb_mock_instance.list_chroots.return_value = ["env1", "env2"]
|
|
self.mock_chroot_manager.chroot_exists.return_value = True
|
|
|
|
environments = self.manager.list_environments()
|
|
|
|
self.assertEqual(len(environments), 2)
|
|
self.assertIsInstance(environments[0], EnvironmentInfo)
|
|
|
|
def test_remove_environment(self):
|
|
"""Test removing environment"""
|
|
self.mock_chroot_manager.chroot_exists.return_value = True
|
|
|
|
self.manager.remove_environment("test-env")
|
|
|
|
self.mock_deb_mock_instance.clean_chroot.assert_called_once_with("test-env")
|
|
|
|
def test_execute_command(self):
|
|
"""Test command execution"""
|
|
self.mock_chroot_manager.chroot_exists.return_value = True
|
|
self.mock_chroot_manager.execute_in_chroot.return_value = Mock(returncode=0, stdout="test output")
|
|
|
|
result = self.manager.execute_command("test-env", ["ls", "-la"])
|
|
|
|
self.mock_chroot_manager.execute_in_chroot.assert_called_once_with(
|
|
"test-env", ["ls", "-la"], capture_output=True
|
|
)
|
|
self.assertEqual(result.returncode, 0)
|
|
|
|
def test_install_packages(self):
|
|
"""Test package installation"""
|
|
self.mock_chroot_manager.chroot_exists.return_value = True
|
|
|
|
result = self.manager.install_packages("test-env", ["build-essential"])
|
|
|
|
self.mock_deb_mock_instance.install_packages.assert_called_once_with(["build-essential"])
|
|
self.assertEqual(result['success'], True)
|
|
|
|
def test_build_package(self):
|
|
"""Test package building"""
|
|
self.mock_chroot_manager.chroot_exists.return_value = True
|
|
|
|
result = self.manager.build_package("test-env", "/path/to/package.dsc")
|
|
|
|
self.mock_deb_mock_instance.build.assert_called_once()
|
|
self.assertIsInstance(result, BuildResult)
|
|
self.assertTrue(result.success)
|
|
|
|
|
|
class TestIntegration(unittest.TestCase):
|
|
"""Integration tests for the API"""
|
|
|
|
def test_create_client_with_config_builder(self):
|
|
"""Test creating client with config builder"""
|
|
config = (MockConfigBuilder()
|
|
.environment("test-env")
|
|
.architecture("amd64")
|
|
.suite("trixie")
|
|
.build())
|
|
|
|
client = MockAPIClient(config)
|
|
|
|
self.assertIsInstance(client, MockAPIClient)
|
|
self.assertEqual(client.config.chroot_name, "test-env")
|
|
|
|
def test_quick_build_function(self):
|
|
"""Test the quick_build convenience function"""
|
|
from deb_mock.api import quick_build
|
|
|
|
with patch('deb_mock.api.MockAPIClient') as mock_client_class:
|
|
mock_client = Mock()
|
|
mock_client.build_package.return_value = {'success': True}
|
|
mock_client_class.return_value = mock_client
|
|
|
|
result = quick_build("/path/to/package.dsc")
|
|
|
|
self.assertEqual(result['success'], True)
|
|
mock_client.build_package.assert_called_once()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|