Skip to main content
Glama

mcp-optimizer

test_assignment.pyโ€ข19.4 kB
"""Tests for assignment tools.""" from unittest.mock import MagicMock from mcp_optimizer.tools.assignment import ( register_assignment_tools, solve_assignment_problem, solve_transportation_problem, ) class TestAssignmentTools: """Tests for assignment problem solving tools.""" def test_solve_assignment_problem_success(self): """Test successful assignment problem solving.""" workers = ["Alice", "Bob", "Charlie"] tasks = ["Task1", "Task2", "Task3"] costs = [[4, 6, 3], [2, 5, 1], [3, 4, 2]] result = solve_assignment_problem(workers, tasks, costs) assert "status" in result assert "total_cost" in result assert "assignments" in result assert "execution_time" in result def test_solve_assignment_problem_maximize(self): """Test assignment problem with maximize objective.""" workers = ["Alice", "Bob"] tasks = ["Task1", "Task2"] costs = [[10, 5], [8, 12]] result = solve_assignment_problem(workers, tasks, costs, objective="maximize") assert "status" in result assert result["objective"] == "maximize" def test_solve_assignment_problem_with_constraints(self): """Test assignment problem with additional constraints.""" workers = ["Alice", "Bob", "Charlie"] tasks = ["Task1", "Task2", "Task3"] costs = [[4, 6, 3], [2, 5, 1], [3, 4, 2]] constraints = {"worker_limits": {"Alice": 1, "Bob": 2}, "task_requirements": {"Task1": 1}} result = solve_assignment_problem(workers, tasks, costs, constraints=constraints) assert "status" in result def test_solve_assignment_problem_empty_workers(self): """Test assignment problem with empty workers list.""" result = solve_assignment_problem([], ["Task1"], [[]]) assert result["status"] == "error" assert "No workers provided" in result["error_message"] def test_solve_assignment_problem_empty_tasks(self): """Test assignment problem with empty tasks list.""" result = solve_assignment_problem(["Alice"], [], [[]]) assert result["status"] == "error" assert "No tasks provided" in result["error_message"] def test_solve_assignment_problem_invalid_cost_matrix(self): """Test assignment problem with invalid cost matrix dimensions.""" workers = ["Alice", "Bob"] tasks = ["Task1", "Task2"] costs = [[4, 6]] # Missing row for Bob result = solve_assignment_problem(workers, tasks, costs) assert result["status"] == "error" assert "Cost matrix dimensions" in result["error_message"] def test_solve_assignment_problem_unbalanced(self): """Test assignment problem with unbalanced workers and tasks.""" workers = ["Alice", "Bob"] tasks = ["Task1", "Task2", "Task3"] costs = [[4, 6, 3], [2, 5, 1]] result = solve_assignment_problem(workers, tasks, costs) assert "status" in result # Should handle unbalanced assignment def test_solve_assignment_problem_infeasible_constraints(self): """Test assignment problem with worker limits constraint.""" workers = ["Alice"] tasks = ["Task1", "Task2"] costs = [[4, 6]] constraints = { "worker_limits": {"Alice": 0} # Alice can't be assigned to any task } result = solve_assignment_problem(workers, tasks, costs, constraints=constraints) # With max_tasks_per_worker=0, the problem should be infeasible assert result["status"] == "infeasible" def test_solve_assignment_problem_exception_handling(self): """Test assignment problem with invalid input causing real error.""" # Test with invalid cost matrix - non-numeric values should cause error workers = ["Alice"] tasks = ["Task1"] costs = [["invalid"]] # String instead of number result = solve_assignment_problem(workers, tasks, costs) assert result["status"] == "error" assert "error_message" in result def test_solve_transportation_problem_success(self): """Test successful transportation problem solving.""" suppliers = [{"name": "S1", "supply": 100}, {"name": "S2", "supply": 150}] consumers = [{"name": "C1", "demand": 80}, {"name": "C2", "demand": 170}] costs = [[5, 10], [8, 6]] result = solve_transportation_problem(suppliers, consumers, costs) assert "status" in result assert "total_cost" in result assert "shipments" in result assert "execution_time" in result def test_solve_transportation_problem_unbalanced(self): """Test transportation problem with unbalanced supply and demand.""" suppliers = [{"name": "S1", "supply": 100}] consumers = [{"name": "C1", "demand": 80}, {"name": "C2", "demand": 50}] costs = [[5, 10]] result = solve_transportation_problem(suppliers, consumers, costs) assert "status" in result # Should handle unbalanced transportation def test_solve_transportation_problem_empty_suppliers(self): """Test transportation problem with empty suppliers.""" result = solve_transportation_problem([], [{"name": "C1", "demand": 80}], [[]]) assert result["status"] == "error" assert "No suppliers provided" in result["error_message"] def test_solve_transportation_problem_empty_consumers(self): """Test transportation problem with empty consumers.""" result = solve_transportation_problem([{"name": "S1", "supply": 100}], [], [[]]) assert result["status"] == "error" assert "No consumers provided" in result["error_message"] def test_solve_transportation_problem_invalid_supplier_format(self): """Test transportation problem with invalid supplier format.""" suppliers = ["invalid_supplier"] consumers = [{"name": "C1", "demand": 80}] costs = [[5]] result = solve_transportation_problem(suppliers, consumers, costs) assert result["status"] == "error" assert ( "Supplier" in result["error_message"] and "must be a dictionary" in result["error_message"] ) def test_solve_transportation_problem_invalid_consumer_format(self): """Test transportation problem with invalid consumer format.""" suppliers = [{"name": "S1", "supply": 100}] consumers = ["invalid_consumer"] costs = [[5]] result = solve_transportation_problem(suppliers, consumers, costs) assert result["status"] == "error" assert ( "Consumer" in result["error_message"] and "must be a dictionary" in result["error_message"] ) def test_solve_transportation_problem_invalid_cost_matrix(self): """Test transportation problem with invalid cost matrix.""" suppliers = [{"name": "S1", "supply": 100}] consumers = [{"name": "C1", "demand": 80}] costs = [] # Empty cost matrix result = solve_transportation_problem(suppliers, consumers, costs) assert result["status"] == "error" assert "Cost matrix dimensions" in result["error_message"] def test_solve_transportation_problem_missing_supplier_fields(self): """Test transportation problem with missing supplier fields.""" suppliers = [{"name": "S1"}] # Missing supply consumers = [{"name": "C1", "demand": 80}] costs = [[5]] result = solve_transportation_problem(suppliers, consumers, costs) assert result["status"] == "error" assert "supply" in result["error_message"] def test_solve_transportation_problem_missing_consumer_fields(self): """Test transportation problem with missing consumer fields.""" suppliers = [{"name": "S1", "supply": 100}] consumers = [{"name": "C1"}] # Missing demand costs = [[5]] result = solve_transportation_problem(suppliers, consumers, costs) assert result["status"] == "error" assert "demand" in result["error_message"] def test_solve_transportation_problem_negative_supply(self): """Test transportation problem with negative supply.""" suppliers = [{"name": "S1", "supply": -100}] consumers = [{"name": "C1", "demand": 80}] costs = [[5]] result = solve_transportation_problem(suppliers, consumers, costs) assert result["status"] == "error" assert "Supply must be non-negative" in result["error_message"] def test_solve_transportation_problem_negative_demand(self): """Test transportation problem with negative demand.""" suppliers = [{"name": "S1", "supply": 100}] consumers = [{"name": "C1", "demand": -80}] costs = [[5]] result = solve_transportation_problem(suppliers, consumers, costs) assert result["status"] == "error" assert "Demand must be non-negative" in result["error_message"] def test_solve_transportation_problem_exception_handling(self): """Test transportation problem with invalid input causing real error.""" # Test with invalid cost matrix - non-numeric values should cause error suppliers = [{"name": "S1", "supply": 100}] consumers = [{"name": "C1", "demand": 100}] costs = [["invalid"]] # String instead of number result = solve_transportation_problem(suppliers, consumers, costs) assert result["status"] == "error" assert "error_message" in result class TestAssignmentToolsValidation: """Tests for assignment tools validation.""" def test_assignment_tool_empty_workers_validation(self): """Test assignment tool validation with empty workers.""" result = solve_assignment_problem([], ["Task1"], [[]]) assert result["status"] == "error" def test_assignment_tool_empty_tasks_validation(self): """Test assignment tool validation with empty tasks.""" result = solve_assignment_problem(["Alice"], [], [[]]) assert result["status"] == "error" def test_transportation_tool_empty_suppliers_validation(self): """Test transportation tool validation with empty suppliers.""" result = solve_transportation_problem([], [{"name": "C1", "demand": 80}], [[]]) assert result["status"] == "error" def test_transportation_tool_empty_consumers_validation(self): """Test transportation tool validation with empty consumers.""" result = solve_transportation_problem([{"name": "S1", "supply": 100}], [], [[]]) assert result["status"] == "error" def test_transportation_tool_unbalanced_validation(self): """Test transportation tool with unbalanced supply/demand.""" suppliers = [{"name": "S1", "supply": 100}] consumers = [{"name": "C1", "demand": 200}] # More demand than supply costs = [[5]] result = solve_transportation_problem(suppliers, consumers, costs) assert "status" in result # Should handle or warn about unbalanced problem class TestRegisterAssignmentTools: """Tests for assignment tools registration.""" def test_register_assignment_tools(self): """Test registration of assignment tools with MCP server.""" # Mock FastMCP instance mock_mcp = MagicMock() mock_tool_decorator = MagicMock() mock_mcp.tool.return_value = mock_tool_decorator # Register tools register_assignment_tools(mock_mcp) # Verify tool decorator was called (should be called twice: for assignment and transportation) assert mock_mcp.tool.call_count == 2 def test_assignment_tool_wrapper(self): """Test the wrapped assignment tool function with real solving.""" # Mock FastMCP instance and tool registration mock_mcp = MagicMock() tool_functions = [] def capture_tool_function(): def decorator(func): tool_functions.append(func) return func return decorator mock_mcp.tool.side_effect = capture_tool_function # Register tools register_assignment_tools(mock_mcp) # Get the assignment tool function assert len(tool_functions) == 2 assignment_tool = tool_functions[0] # First registered tool should be assignment # Test the wrapped function with real data workers = ["Alice", "Bob"] tasks = ["Task1", "Task2"] costs = [[4, 6], [2, 5]] result = assignment_tool(workers, tasks, costs) # Verify real solving occurred assert result["status"] == "optimal" assert "total_cost" in result assert "assignments" in result assert "execution_time" in result assert len(result["assignments"]) == 2 def test_transportation_tool_wrapper(self): """Test the wrapped transportation tool function with real solving.""" # Mock FastMCP instance and tool registration mock_mcp = MagicMock() tool_functions = [] def capture_tool_function(): def decorator(func): tool_functions.append(func) return func return decorator mock_mcp.tool.side_effect = capture_tool_function # Register tools register_assignment_tools(mock_mcp) # Get the transportation tool function assert len(tool_functions) == 2 transportation_tool = tool_functions[1] # Second registered tool should be transportation # Test the wrapped function with balanced supply/demand suppliers = [{"name": "S1", "supply": 100}] consumers = [{"name": "C1", "demand": 100}] # Balanced supply/demand costs = [[5]] result = transportation_tool(suppliers, consumers, costs) # Verify real solving occurred assert result["status"] == "optimal" assert "total_cost" in result assert "flows" in result or "shipments" in result assert "execution_time" in result class TestAssignmentEdgeCases: """Tests for assignment edge cases and error conditions.""" def test_large_assignment_problem(self): """Test assignment problem with many workers and tasks.""" num_workers = 20 num_tasks = 20 workers = [f"Worker{i}" for i in range(num_workers)] tasks = [f"Task{i}" for i in range(num_tasks)] costs = [[i + j for j in range(num_tasks)] for i in range(num_workers)] result = solve_assignment_problem(workers, tasks, costs) assert "status" in result def test_single_worker_single_task(self): """Test assignment problem with single worker and task.""" workers = ["Alice"] tasks = ["Task1"] costs = [[5]] result = solve_assignment_problem(workers, tasks, costs) assert "status" in result if result["status"] == "optimal": assert result["total_cost"] == 5 assert len(result["assignments"]) == 1 def test_zero_cost_assignment(self): """Test assignment problem with zero costs.""" workers = ["Alice", "Bob"] tasks = ["Task1", "Task2"] costs = [[0, 5], [3, 0]] result = solve_assignment_problem(workers, tasks, costs) assert "status" in result if result["status"] == "optimal": assert result["total_cost"] >= 0 def test_high_cost_assignment(self): """Test assignment problem with very high costs.""" workers = ["Alice", "Bob"] tasks = ["Task1", "Task2"] costs = [[1000000, 2000000], [1500000, 1800000]] result = solve_assignment_problem(workers, tasks, costs) assert "status" in result def test_fractional_costs(self): """Test assignment problem with fractional costs.""" workers = ["Alice", "Bob"] tasks = ["Task1", "Task2"] costs = [[4.5, 6.2], [2.1, 5.8]] result = solve_assignment_problem(workers, tasks, costs) assert "status" in result def test_transportation_large_supply_demand(self): """Test transportation problem with large supply and demand values.""" suppliers = [{"name": "S1", "supply": 1000000}] consumers = [{"name": "C1", "demand": 1000000}] costs = [[1.5]] result = solve_transportation_problem(suppliers, consumers, costs) assert "status" in result def test_transportation_zero_supply_demand(self): """Test transportation problem with zero supply and demand.""" suppliers = [{"name": "S1", "supply": 0}] consumers = [{"name": "C1", "demand": 0}] costs = [[5]] result = solve_transportation_problem(suppliers, consumers, costs) assert "status" in result if result["status"] == "optimal": assert result["total_cost"] == 0 def test_transportation_fractional_supply_demand(self): """Test transportation problem with fractional supply and demand.""" suppliers = [{"name": "S1", "supply": 100.5}] consumers = [{"name": "C1", "demand": 100.5}] costs = [[2.3]] result = solve_transportation_problem(suppliers, consumers, costs) assert "status" in result def test_assignment_with_complex_constraints(self): """Test assignment problem with complex constraint structure.""" workers = ["Alice", "Bob", "Charlie"] tasks = ["Task1", "Task2", "Task3"] costs = [[4, 6, 3], [2, 5, 1], [3, 4, 2]] # Test forbidden assignments constraint - should return error constraints = {"forbidden_assignments": [("Alice", "Task2"), ("Bob", "Task3")]} result = solve_assignment_problem(workers, tasks, costs, constraints=constraints) assert result["status"] == "error" assert ( "Forbidden assignments constraints are not currently supported" in result["error_message"] ) # Test task requirements constraint - should return error constraints = {"task_requirements": {"Task1": 1, "Task2": 1, "Task3": 1}} result = solve_assignment_problem(workers, tasks, costs, constraints=constraints) assert result["status"] == "error" assert ( "Task requirements constraints are not currently supported" in result["error_message"] ) # Test different worker limits - should return error constraints = {"worker_limits": {"Alice": 1, "Bob": 2, "Charlie": 1}} result = solve_assignment_problem(workers, tasks, costs, constraints=constraints) assert result["status"] == "error" assert ( "Individual worker limits with different values are not currently supported" in result["error_message"] ) def test_assignment_maximize_large_values(self): """Test assignment problem maximizing with large values.""" workers = ["Alice", "Bob"] tasks = ["Task1", "Task2"] costs = [[100000, 150000], [120000, 180000]] result = solve_assignment_problem(workers, tasks, costs, objective="maximize") assert "status" in result if result["status"] == "optimal": assert result["total_cost"] > 0

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/dmitryanchikov/mcp-optimizer'

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