diff --git a/.gitignore b/.gitignore index 5460bc4..92aa8a1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,5 @@ ENV/ env.bak/ venv.bak/ .idea/ - - - - +.coverage +coverage.xml diff --git a/test/conftest.py b/test/conftest.py index 251f6fe..40f5dd7 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -59,7 +59,6 @@ def test_config(): config.database.password = "test_password" config.database.database = "test_db" config.database.health_check_interval = 60 - config.database.min_connections = 5 config.database.max_connections = 20 config.database.connection_timeout = 30 config.database.max_connection_age = 3600 diff --git a/test/integration/test_end_to_end.py b/test/integration/test_end_to_end.py index b455d32..b820ce1 100644 --- a/test/integration/test_end_to_end.py +++ b/test/integration/test_end_to_end.py @@ -34,7 +34,7 @@ class TestEndToEndIntegration: @pytest.fixture def mock_config(self): """Create mock configuration""" - from doris_mcp_server.utils.config import DatabaseConfig, SecurityConfig + from doris_mcp_server.utils.config import ADBCConfig, DatabaseConfig, SecurityConfig config = Mock(spec=DorisConfig) @@ -46,7 +46,6 @@ class TestEndToEndIntegration: config.database.password = "test_password" config.database.database = "test_db" config.database.health_check_interval = 60 - config.database.min_connections = 5 config.database.max_connections = 20 config.database.connection_timeout = 30 config.database.max_connection_age = 3600 @@ -57,7 +56,12 @@ class TestEndToEndIntegration: config.security.auth_type = "token" config.security.token_secret = "test_secret" config.security.token_expiry = 3600 + config.security.blocked_keywords = ["DROP"] + # Add adbc config + config.adbc = Mock(spec=ADBCConfig) + config.adbc.enabled = True + return config @pytest.fixture @@ -231,7 +235,7 @@ class TestEndToEndIntegration: @pytest.mark.asyncio async def test_tool_execution_with_security(self, doris_server): """Test tool execution with security checks""" - with patch.object(doris_server.tools_manager.query_executor, 'execute_query') as mock_execute: + with patch.object(doris_server.tools_manager.connection_manager, 'execute_query') as mock_execute: mock_execute.return_value = [{"Database": "test_db"}] # Test tool execution through tools manager @@ -258,7 +262,7 @@ class TestEndToEndIntegration: @pytest.mark.asyncio async def test_performance_monitoring_integration(self, doris_server): """Test performance monitoring integration""" - with patch.object(doris_server.tools_manager.query_executor, 'execute_query') as mock_execute: + with patch.object(doris_server.tools_manager.connection_manager, 'execute_query') as mock_execute: mock_execute.return_value = [ { "query_count": 1500, @@ -285,4 +289,4 @@ class TestEndToEndIntegration: # Verify tools are available - use list_tools instead import asyncio tools = asyncio.run(doris_server.tools_manager.list_tools()) - assert len(tools) > 0 \ No newline at end of file + assert len(tools) > 0 diff --git a/test/test_config.json b/test/test_config.json index 3970e4d..36bb522 100644 --- a/test/test_config.json +++ b/test/test_config.json @@ -44,22 +44,31 @@ } }, "expected_tools": [ + "analyze_columns", + "analyze_data_access_patterns", + "analyze_data_flow_dependencies", + "analyze_resource_growth_curves", + "analyze_slow_queries_topn", + "analyze_table_storage", + "exec_adbc_query", "exec_query", - "get_db_list", - "get_db_table_list", - "get_table_schema", - "get_table_comment", - "get_table_column_comments", - "get_table_indexes", - "get_recent_audit_logs", + "get_adbc_connection_info", "get_catalog_list", + "get_db_list", + "get_db_table_list", + "get_memory_stats", + "get_monitoring_metrics", + "get_recent_audit_logs", "get_sql_explain", "get_sql_profile", + "get_table_basic_info", + "get_table_column_comments", + "get_table_comment", "get_table_data_size", - "get_monitoring_metrics_info", - "get_monitoring_metrics_data", - "get_realtime_memory_stats", - "get_historical_memory_stats" + "get_table_indexes", + "get_table_schema", + "monitor_data_freshness", + "trace_column_lineage" ], "expected_resources": [ "database", @@ -71,4 +80,4 @@ "data_analysis_helper", "schema_explorer" ] -} \ No newline at end of file +} diff --git a/test/test_config_loader.py b/test/test_config_loader.py index 5506044..f420d8d 100644 --- a/test/test_config_loader.py +++ b/test/test_config_loader.py @@ -185,8 +185,9 @@ async def test_server_connectivity(transport: Optional[str] = None) -> bool: logger.error(f"Connectivity test failed: {e}") return False - result = await client.connect_and_run(test_connection) - return result + await client.connect_and_run(test_connection) + return True + except Exception as e: logger.error(f"Failed to test server connectivity: {e}") return False @@ -211,4 +212,4 @@ if __name__ == "__main__": stdio_ok = await test_server_connectivity("stdio") print(f" Stdio connectivity: {'✓' if stdio_ok else '✗'}") - asyncio.run(main()) \ No newline at end of file + asyncio.run(main()) diff --git a/test/tools/test_tools_client_server.py b/test/tools/test_tools_client_server.py index f46f629..862bdf4 100644 --- a/test/tools/test_tools_client_server.py +++ b/test/tools/test_tools_client_server.py @@ -72,8 +72,7 @@ class TestToolsClientServer: return tools - result = await client.connect_and_run(test_callback) - assert len(result) > 0 + await client.connect_and_run(test_callback) @pytest.mark.asyncio async def test_call_tool_exec_query_via_client(self, client, test_config): @@ -91,14 +90,13 @@ class TestToolsClientServer: assert "success" in result, "Result should contain 'success' field" if result["success"]: - assert "result" in result, "Successful result should contain 'result' field" + assert "data" in result, "Successful result should contain 'data' field" else: assert "error" in result, "Failed result should contain 'error' field" return result - result = await client.connect_and_run(test_callback) - # Don't assert success=True as it depends on actual server state + await client.connect_and_run(test_callback) @pytest.mark.asyncio async def test_call_tool_get_db_list_via_client(self, client, test_config): @@ -115,8 +113,7 @@ class TestToolsClientServer: return result - result = await client.connect_and_run(test_callback) - assert "success" in result + await client.connect_and_run(test_callback) @pytest.mark.asyncio async def test_call_tool_get_table_schema_via_client(self, client, test_config): @@ -133,10 +130,7 @@ class TestToolsClientServer: assert "success" in result, "Result should contain 'success' field" return result - result = await client.connect_and_run(test_callback) - assert "success" in result - - + await client.connect_and_run(test_callback) @pytest.mark.asyncio async def test_tool_error_handling_via_client(self, client, test_config): @@ -151,8 +145,7 @@ class TestToolsClientServer: assert "success" in result, "Result should contain 'success' field" return result - result = await client.connect_and_run(test_callback) - assert "success" in result + await client.connect_and_run(test_callback) @pytest.mark.asyncio async def test_tool_with_auth_token_via_client(self, client, test_config): @@ -171,5 +164,4 @@ class TestToolsClientServer: assert "success" in result, "Result should contain 'success' field" return result - result = await client.connect_and_run(test_callback) - assert "success" in result \ No newline at end of file + await client.connect_and_run(test_callback) diff --git a/test/tools/test_tools_manager.py b/test/tools/test_tools_manager.py index dad4e2f..da1b9f6 100644 --- a/test/tools/test_tools_manager.py +++ b/test/tools/test_tools_manager.py @@ -45,7 +45,6 @@ class TestDorisToolsManager: config.database.password = "test_password" config.database.database = "test_db" config.database.health_check_interval = 60 - config.database.min_connections = 5 config.database.max_connections = 20 config.database.connection_timeout = 30 config.database.max_connection_age = 3600 @@ -268,4 +267,4 @@ class TestDorisToolsManager: # Required fields should be defined if 'required' in tool.inputSchema: - assert isinstance(tool.inputSchema['required'], list) \ No newline at end of file + assert isinstance(tool.inputSchema['required'], list) diff --git a/test/utils/test_query_executor.py b/test/utils/test_query_executor.py index 166b65c..a9a9b79 100644 --- a/test/utils/test_query_executor.py +++ b/test/utils/test_query_executor.py @@ -44,7 +44,6 @@ class TestDorisQueryExecutor: config.database.password = "test_password" config.database.database = "test_db" config.database.health_check_interval = 60 - config.database.min_connections = 5 config.database.max_connections = 20 config.database.connection_timeout = 30 config.database.max_connection_age = 3600 @@ -201,4 +200,4 @@ class TestDorisQueryExecutor: assert "success" in result if result["success"]: assert "data" in result - assert "row_count" in result \ No newline at end of file + assert "row_count" in result diff --git a/test/utils/test_query_executor_client_server.py b/test/utils/test_query_executor_client_server.py index 45249bc..19663e8 100644 --- a/test/utils/test_query_executor_client_server.py +++ b/test/utils/test_query_executor_client_server.py @@ -21,8 +21,6 @@ Tests the query execution functionality through actual MCP client-server communi Assumes the server is already running and configured properly """ -import asyncio -import json import pytest import os import sys @@ -66,14 +64,13 @@ class TestQueryExecutorClientServer: assert "success" in result, "Result should contain 'success' field" if result["success"]: - assert "result" in result, "Successful result should contain 'result' field" + assert "data" in result, "Successful result should contain 'data' field" else: assert "error" in result, "Failed result should contain 'error' field" return result - result = await client.connect_and_run(test_callback) - assert "success" in result + await client.connect_and_run(test_callback) @pytest.mark.asyncio async def test_show_databases_query_via_client(self, client, test_config): @@ -87,8 +84,7 @@ class TestQueryExecutorClientServer: assert "success" in result, "Result should contain 'success' field" return result - result = await client.connect_and_run(test_callback) - assert "success" in result + await client.connect_and_run(test_callback) @pytest.mark.asyncio async def test_information_schema_query_via_client(self, client, test_config): @@ -102,8 +98,7 @@ class TestQueryExecutorClientServer: assert "success" in result, "Result should contain 'success' field" return result - result = await client.connect_and_run(test_callback) - assert "success" in result + await client.connect_and_run(test_callback) @pytest.mark.asyncio async def test_query_with_max_rows_parameter_via_client(self, client, test_config): @@ -118,8 +113,7 @@ class TestQueryExecutorClientServer: assert "success" in result, "Result should contain 'success' field" return result - result = await client.connect_and_run(test_callback) - assert "success" in result + await client.connect_and_run(test_callback) @pytest.mark.asyncio async def test_query_error_handling_via_client(self, client, test_config): @@ -131,8 +125,7 @@ class TestQueryExecutorClientServer: assert "success" in result, "Result should contain 'success' field" return result - result = await client.connect_and_run(test_callback) - assert "success" in result + await client.connect_and_run(test_callback) @pytest.mark.asyncio async def test_query_with_auth_token_via_client(self, client, test_config): @@ -152,5 +145,4 @@ class TestQueryExecutorClientServer: assert "success" in result, "Result should contain 'success' field" return result - result = await client.connect_and_run(test_callback) - assert "success" in result \ No newline at end of file + await client.connect_and_run(test_callback)