Skip to main content
Glama
test_cli.py8.95 kB
import json import os import pytest import shutil import signal import subprocess import tempfile from pathlib import Path from unittest.mock import patch, mock_open, MagicMock from adminmcp.cli import ( is_server_running, start_server, stop_server, init_config, main ) class TestServerStatus: """Test server status checking functionality.""" @patch('adminmcp.cli.os.path.exists') def test_is_server_running_no_pid_file(self, mock_exists): """Test when PID file doesn't exist.""" mock_exists.return_value = False assert is_server_running() is False @patch('adminmcp.cli.os.path.exists') @patch('adminmcp.cli.open', new_callable=mock_open, read_data='1234\n') @patch('adminmcp.cli.os.kill') def test_is_server_running_process_alive(self, mock_kill, mock_file, mock_exists): """Test when PID file exists and process is alive.""" mock_exists.return_value = True mock_kill.return_value = None # Process exists assert is_server_running() is True @patch('adminmcp.cli.os.path.exists') @patch('adminmcp.cli.open', new_callable=mock_open, read_data='1234\n') @patch('adminmcp.cli.os.kill') def test_is_server_running_process_dead(self, mock_kill, mock_file, mock_exists): """Test when PID file exists but process is dead.""" mock_exists.return_value = True mock_kill.side_effect = OSError("No such process") assert is_server_running() is False class TestServerStart: """Test server starting functionality.""" @patch('adminmcp.cli.is_server_running') @patch('adminmcp.cli.subprocess.Popen') @patch('adminmcp.cli.open', new_callable=mock_open) @patch('adminmcp.cli.print') def test_start_server_success(self, mock_print, mock_file, mock_popen, mock_running): """Test successful server start.""" mock_running.return_value = False mock_process = MagicMock() mock_process.pid = 1234 mock_popen.return_value = mock_process start_server() mock_popen.assert_called_once_with( ['python', 'src/adminmcp/server/acp_server.py'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) mock_file.assert_called_once() mock_print.assert_called_with("Server started.") @patch('adminmcp.cli.is_server_running') @patch('adminmcp.cli.print') def test_start_server_already_running(self, mock_print, mock_running): """Test starting server when already running.""" mock_running.return_value = True start_server() mock_print.assert_called_with("Server is already running.") @patch('adminmcp.cli.is_server_running') @patch('adminmcp.cli.subprocess.Popen') @patch('adminmcp.cli.print') def test_start_server_failure(self, mock_print, mock_popen, mock_running): """Test server start failure.""" mock_running.return_value = False mock_popen.side_effect = Exception("Failed to start") start_server() mock_print.assert_called_with("Failed to start server: Failed to start") class TestServerStop: """Test server stopping functionality.""" @patch('adminmcp.cli.os.path.exists') @patch('adminmcp.cli.print') def test_stop_server_no_pid_file(self, mock_print, mock_exists): """Test stopping server when no PID file exists.""" mock_exists.return_value = False stop_server() mock_print.assert_called_with("Server is not running.") @patch('adminmcp.cli.os.path.exists') @patch('adminmcp.cli.open', new_callable=mock_open, read_data='1234\n') @patch('adminmcp.cli.os.kill') @patch('adminmcp.cli.os.remove') @patch('adminmcp.cli.print') def test_stop_server_success(self, mock_print, mock_remove, mock_kill, mock_file, mock_exists): """Test successful server stop.""" mock_exists.return_value = True stop_server() mock_kill.assert_called_once_with(1234, signal.SIGTERM) mock_remove.assert_called_once() mock_print.assert_called_with("Server stopped.") @patch('adminmcp.cli.os.path.exists') @patch('adminmcp.cli.open', new_callable=mock_open, read_data='1234\n') @patch('adminmcp.cli.os.kill') @patch('adminmcp.cli.os.remove') @patch('adminmcp.cli.print') def test_stop_server_process_not_running(self, mock_print, mock_remove, mock_kill, mock_file, mock_exists): """Test stopping server when process is not running.""" mock_exists.return_value = True mock_kill.side_effect = OSError("No such process") stop_server() mock_kill.assert_called_once_with(1234, signal.SIGTERM) mock_remove.assert_called_once() # Should still remove PID file mock_print.assert_called_with("Server was not running.") @patch('adminmcp.cli.os.path.exists') @patch('adminmcp.cli.open', new_callable=mock_open, read_data='1234\n') @patch('adminmcp.cli.os.kill') @patch('adminmcp.cli.print') def test_stop_server_kill_failure(self, mock_print, mock_kill, mock_file, mock_exists): """Test server stop failure.""" mock_exists.return_value = True mock_kill.side_effect = Exception("Kill failed") stop_server() mock_print.assert_called_with("Failed to stop server: Kill failed") class TestConfigInit: """Test configuration initialization functionality.""" @patch('adminmcp.cli.Path.home') @patch('adminmcp.cli.shutil.copy2') @patch('adminmcp.cli.open', new_callable=mock_open) @patch('adminmcp.cli.print') def test_init_config_success(self, mock_print, mock_file, mock_copy, mock_home): """Test successful config initialization.""" # Use a simpler approach with temporary directory import tempfile with tempfile.TemporaryDirectory() as temp_dir: mock_home.return_value = Path(temp_dir) init_config() # Should call copy2 and create settings file mock_copy.assert_called_once() mock_file.assert_called_once() assert mock_print.call_count >= 2 # At least config copied and settings created @patch('adminmcp.cli.Path.home') @patch('adminmcp.cli.shutil.copy2') @patch('adminmcp.cli.print') def test_init_config_files_exist(self, mock_print, mock_copy, mock_home): """Test config init when files already exist.""" # Mock home directory mock_home_dir = MagicMock() mock_home.return_value = mock_home_dir # Mock config directory mock_config_dir = MagicMock() mock_home_dir.__truediv__ = MagicMock(return_value=mock_config_dir) mock_config_dir.__truediv__ = MagicMock() # Mock files that already exist mock_dst_config = MagicMock() mock_dst_config.exists.return_value = True mock_settings_file = MagicMock() mock_settings_file.exists.return_value = True mock_config_dir.__truediv__.side_effect = [mock_dst_config, mock_settings_file] init_config() # Should not call copy2 or create files mock_copy.assert_not_called() mock_print.assert_called() # Should print that files exist class TestCLIMain: """Test CLI main function.""" @patch('adminmcp.cli.argparse.ArgumentParser.parse_args') @patch('adminmcp.cli.start_server') def test_main_server_start(self, mock_start, mock_parse): """Test main function with server start command.""" mock_args = MagicMock() mock_args.command = 'server' mock_args.action = 'start' mock_parse.return_value = mock_args main() mock_start.assert_called_once() @patch('adminmcp.cli.argparse.ArgumentParser.parse_args') @patch('adminmcp.cli.stop_server') def test_main_server_stop(self, mock_stop, mock_parse): """Test main function with server stop command.""" mock_args = MagicMock() mock_args.command = 'server' mock_args.action = 'stop' mock_parse.return_value = mock_args main() mock_stop.assert_called_once() @patch('adminmcp.cli.argparse.ArgumentParser.parse_args') @patch('adminmcp.cli.init_config') def test_main_init_config(self, mock_init, mock_parse): """Test main function with init config command.""" mock_args = MagicMock() mock_args.command = 'init' mock_parse.return_value = mock_args main() mock_init.assert_called_once() # Test fixtures @pytest.fixture def temp_config_dir(tmp_path): """Create a temporary config directory for testing.""" config_dir = tmp_path / ".config" / "adminmcp" config_dir.mkdir(parents=True) return config_dir @pytest.fixture def mock_pid_file(temp_config_dir): """Create a mock PID file.""" pid_file = temp_config_dir / "acp_server.pid" return pid_file

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/frankausberlin/adminmcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server