[PATCH 13/23] rteval MCP: Add integration tests and remove hardcoded examples

John Kacur <[email protected]>
Newsgroups org.kernel.vger.linux-rt-users
Message-ID <[email protected]>
Replace hardcoded example scripts with a proper integration test that
validates MCP server tools through the actual MCP interface.

Removed files (had hardcoded paths to deleted test data):
- test_server.py: Basic sanity check, too minimal
- test_comparison.py: Redundant with compare_results tool
- test_logs.py: Redundant with list_logs/read_log tools
- test_tools.py: Replaced by test_mcp_integration.py

Added file:
- tests/test_mcp_integration.py: End-to-end integration test
  - Tests 8 MCP tools through the MCP interface
  - Dynamically finds available rteval result directories
  - No hardcoded paths - works with any rteval data
  - Works from rteval/, rteval/mcp-server/, or rteval/mcp-server/tests/
  - Discovered bugs in filter_results, find_best_worst, compare_to_baseline

Test coverage:
- list_tools, list_results, parse_result, list_logs
- get_percentiles, extract_histogram (new histogram features)
- filter_results, find_best_worst (query/filter tools)

All tests pass after server.py glob pattern fixes.

Assisted-by: Claude:claude-sonnet-4-5
Signed-off-by: John Kacur <[email protected]>
---
 mcp-server/tests/test_mcp_integration.py | 195 +++++++++++++++++++++++
 1 file changed, 195 insertions(+)
 create mode 100644 mcp-server/tests/test_mcp_integration.py

diff --git a/mcp-server/tests/test_mcp_integration.py b/mcp-server/tests/test_mcp_integration.py
new file mode 100644
index 000000000000..30f7700786fa
--- /dev/null
+++ b/mcp-server/tests/test_mcp_integration.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python3
+"""Integration tests for rteval MCP server.
+
+Tests the MCP server tools through the actual MCP interface,
+validating end-to-end functionality.
+"""
+
+import sys
+import asyncio
+from pathlib import Path
+
+# Add parent directory to path to import server module
+sys.path.insert(0, str(Path(__file__).parent.parent))
+from server import call_tool, list_tools
+
+
+def find_test_data():
+    """Find available rteval result directories for testing."""
+    # From tests/ -> mcp-server/ -> rteval/
+    rteval_dir = Path(__file__).parent.parent.parent
+
+    # Find rteval result directories (not rteval-build)
+    result_dirs = sorted([
+        d for d in rteval_dir.glob("rteval-*/")
+        if d.is_dir() and d.name != "rteval-build" and (d / "summary.xml").exists()
+    ])
+
+    if not result_dirs:
+        raise RuntimeError("No rteval result directories found for testing")
+
+    return result_dirs
+
+
+async def main():
+    print("MCP Server Integration Tests")
+    print("=" * 60)
+
+    # Find test data
+    try:
+        result_dirs = find_test_data()
+        test_dir = result_dirs[0]
+        test_file = test_dir / "summary.xml"
+        rteval_parent = test_dir.parent
+
+        print(f"\nUsing test data: {test_dir.name}")
+        print(f"Total result directories available: {len(result_dirs)}")
+        print()
+    except RuntimeError as e:
+        print(f"✗ {e}")
+        sys.exit(1)
+
+    # Test 1: List available tools
+    print("1. Testing list_tools()...")
+    try:
+        tools = await list_tools()
+        print(f"✓ Found {len(tools)} tools:")
+        for tool in tools:
+            print(f"  - {tool.name}: {tool.description[:60]}...")
+    except Exception as e:
+        print(f"✗ Failed: {e}")
+        sys.exit(1)
+
+    # Test 2: List results
+    print("\n2. Testing list_results...")
+    try:
+        result = await call_tool("list_results", {
+            "directory": str(rteval_parent),
+            "pattern": "rteval-*/summary.xml"
+        })
+        output = result[0].text
+        if "Found" in output and "file" in output:
+            lines = output.split('\n')[:5]
+            print("✓ " + '\n  '.join(lines))
+        else:
+            print(f"✗ Unexpected output: {output[:200]}")
+            sys.exit(1)
+    except Exception as e:
+        print(f"✗ Failed: {e}")
+        sys.exit(1)
+
+    # Test 3: Parse a result
+    print("\n3. Testing parse_result...")
+    try:
+        result = await call_tool("parse_result", {
+            "file_path": str(test_file)
+        })
+        output = result[0].text
+        if "rteval version" in output and "System Information" in output:
+            lines = output.split('\n')[:10]
+            print("✓ " + '\n  '.join(lines))
+        else:
+            print(f"✗ Unexpected output: {output[:200]}")
+            sys.exit(1)
+    except Exception as e:
+        print(f"✗ Failed: {e}")
+        sys.exit(1)
+
+    # Test 4: List logs
+    print("\n4. Testing list_logs...")
+    try:
+        result = await call_tool("list_logs", {
+            "result_dir": str(test_dir)
+        })
+        output = result[0].text
+        if "Log files" in output or "logs" in output.lower():
+            lines = output.split('\n')[:8]
+            print("✓ " + '\n  '.join(lines))
+        else:
+            print(f"✗ Unexpected output: {output[:200]}")
+            sys.exit(1)
+    except Exception as e:
+        print(f"✗ Failed: {e}")
+        sys.exit(1)
+
+    # Test 5: Get percentiles (new histogram feature)
+    print("\n5. Testing get_percentiles...")
+    try:
+        result = await call_tool("get_percentiles", {
+            "file_path": str(test_file),
+            "percentiles": [50, 95, 99, 99.9]
+        })
+        output = result[0].text
+        if "Percentiles" in output and "P50" in output:
+            lines = output.split('\n')[:12]
+            print("✓ " + '\n  '.join(lines))
+        else:
+            print(f"✗ Unexpected output: {output[:200]}")
+            sys.exit(1)
+    except Exception as e:
+        print(f"✗ Failed: {e}")
+        sys.exit(1)
+
+    # Test 6: Extract histogram (new feature)
+    print("\n6. Testing extract_histogram...")
+    try:
+        result = await call_tool("extract_histogram", {
+            "file_path": str(test_file),
+            "include_per_cpu": False  # Keep output brief
+        })
+        output = result[0].text
+        if "Histogram Data" in output and "Total Samples" in output:
+            lines = output.split('\n')[:12]
+            print("✓ " + '\n  '.join(lines))
+        else:
+            print(f"✗ Unexpected output: {output[:200]}")
+            sys.exit(1)
+    except Exception as e:
+        print(f"✗ Failed: {e}")
+        sys.exit(1)
+
+    # Test 7: Filter results (query tools)
+    print("\n7. Testing filter_results...")
+    try:
+        result = await call_tool("filter_results", {
+            "directory": str(rteval_parent),
+            "is_rt": False
+        })
+        output = result[0].text
+        if "Filtered Results" in output or "files matched" in output:
+            lines = output.split('\n')[:8]
+            print("✓ " + '\n  '.join(lines))
+        else:
+            print(f"✗ Unexpected output: {output[:200]}")
+            sys.exit(1)
+    except Exception as e:
+        print(f"✗ Failed: {e}")
+        sys.exit(1)
+
+    # Test 8: Find best/worst
+    print("\n8. Testing find_best_worst...")
+    try:
+        result = await call_tool("find_best_worst", {
+            "directory": str(rteval_parent),
+            "metric": "maximum",
+            "count": 3
+        })
+        output = result[0].text
+        if ("BEST" in output and "WORST" in output) or "No results" in output:
+            lines = output.split('\n')[:10]
+            print("✓ " + '\n  '.join(lines))
+        else:
+            print(f"✗ Unexpected output: {output[:200]}")
+            sys.exit(1)
+    except Exception as e:
+        print(f"✗ Failed: {e}")
+        sys.exit(1)
+
+    print("\n" + "=" * 60)
+    print("✓ All MCP server integration tests passed!")
+    print(f"\nTested with: {test_dir.name}")
+    print(f"Total tools tested: 8")
+
+
+if __name__ == "__main__":
+    asyncio.run(main())
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.