From 4d4bb9dec5f94a2a26f78329ed52a8fa25a92918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Jaramago=20Fern=C3=A1ndez?= Date: Mon, 26 Jan 2026 18:51:57 +0100 Subject: [PATCH] fix: Improved MCP rule testing and helpers --- .../mcp_rules_testing/mcp_test_helpers.sh | 12 ++- .../test_phase9_eval_okmsg.sh | 96 +++++++++++++------ 2 files changed, 74 insertions(+), 34 deletions(-) diff --git a/test/tap/tests/mcp_rules_testing/mcp_test_helpers.sh b/test/tap/tests/mcp_rules_testing/mcp_test_helpers.sh index 3b7bb7ba3..ceb5d51cf 100755 --- a/test/tap/tests/mcp_rules_testing/mcp_test_helpers.sh +++ b/test/tap/tests/mcp_rules_testing/mcp_test_helpers.sh @@ -51,15 +51,17 @@ exec_admin() { # Execute MySQL command via ProxySQL admin (silent mode) exec_admin_silent() { + set +e if [ -z "${PROXYSQL_ADMIN_PASSWORD}" ] || [ "${PROXYSQL_ADMIN_PASSWORD}" = "none" ]; then mysql -B -N -h "${PROXYSQL_ADMIN_HOST}" -P "${PROXYSQL_ADMIN_PORT}" \ -u "${PROXYSQL_ADMIN_USER}" \ - -e "$1" 2>/dev/null + -e "$1" 2>&1 | { grep -vP "^mysql: \[Warning\].* insecure.$" || true; } else mysql -B -N -h "${PROXYSQL_ADMIN_HOST}" -P "${PROXYSQL_ADMIN_PORT}" \ -u "${PROXYSQL_ADMIN_USER}" -p"${PROXYSQL_ADMIN_PASSWORD}" \ - -e "$1" 2>/dev/null + -e "$1" 2>&1 | { grep -vP "^mysql: \[Warning\].* insecure.$" || true; } fi + set -e } # Execute MySQL command directly on backend MySQL server @@ -82,6 +84,7 @@ exec_mysql() { # Execute MySQL command directly on backend MySQL server (silent mode) exec_mysql_silent() { + set +e local db_param="" if [ -n "${MYSQL_DATABASE}" ]; then db_param="-D ${MYSQL_DATABASE}" @@ -90,12 +93,13 @@ exec_mysql_silent() { if [ -z "${MYSQL_PASSWORD}" ] || [ "${MYSQL_PASSWORD}" = "none" ]; then mysql -B -N -h "${MYSQL_HOST}" -P "${MYSQL_PORT}" \ -u "${MYSQL_USER}" \ - ${db_param} -e "$1" 2>/dev/null + ${db_param} -e "$1" 2>&1 | { grep -vP "^mysql: \[Warning\].* insecure.$" || true; } else mysql -B -N -h "${MYSQL_HOST}" -P "${MYSQL_PORT}" \ -u "${MYSQL_USER}" -p"${MYSQL_PASSWORD}" \ - ${db_param} -e "$1" 2>/dev/null + ${db_param} -e "$1" 2>&1 | { grep -vP "^mysql: \[Warning\].* insecure.$" || true; } fi + set -e } # Get endpoint URL for MCP requests diff --git a/test/tap/tests/mcp_rules_testing/test_phase9_eval_okmsg.sh b/test/tap/tests/mcp_rules_testing/test_phase9_eval_okmsg.sh index 6bd9322b7..3c7045656 100755 --- a/test/tap/tests/mcp_rules_testing/test_phase9_eval_okmsg.sh +++ b/test/tap/tests/mcp_rules_testing/test_phase9_eval_okmsg.sh @@ -5,7 +5,7 @@ # Phase 9: Test rule evaluation for OK Message action # -set -e +set -eo pipefail # Get script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -204,55 +204,91 @@ main() { run_test "T9.1: Query with OK_msg - health_check returns status message" \ test_returns_okmsg "run_sql_readonly" "SELECT * FROM health_check;" "Status: OK" - # T9.2: Verify success response contains OK_msg - run_test "T9.2: Verify success response contains OK_msg - STATUS query" \ + # T9.1: Query with OK_msg - Verify success response contains OK_msg + run_test "T9.1: Verify success response contains OK_msg - STATUS query" \ test_returns_okmsg "run_sql_readonly" "SELECT STATUS FROM status_table;" "Custom Status Message" - # T9.1: Verify query with OK_msg is NOT actually executed - # Use a DELETE query that should NOT execute due to OK_msg - log_test "T9.1: Query with OK_msg - DELETE is NOT executed (data unchanged)" + # T9.1: Verify OK message response format is successful (not error) + log_test "T9.1: Verify OK message response is successful (not error)" TOTAL_TESTS=$((TOTAL_TESTS + 1)) - # Get initial count - initial_count=$(exec_mysql_silent "SELECT COUNT(*) FROM ${MYSQL_DATABASE}.status_table;") - log_verbose "Initial count: ${initial_count}" - - # Try to execute DELETE (should return OK_msg without executing) - payload='{"jsonrpc":"2.0","method":"tools/call","params":{"name":"run_sql","arguments":{"sql":"DELETE FROM status_table WHERE id = 999"}},"id":1}' + payload='{"jsonrpc":"2.0","method":"tools/call","params":{"name":"run_sql_readonly","arguments":{"sql":"PING"}},"id":1}' response=$(mcp_request "query" "$payload") + log_verbose "Response: ${response}" - # Get final count - final_count=$(exec_mysql_silent "SELECT COUNT(*) FROM ${MYSQL_DATABASE}.status_table;") - log_verbose "Final count: ${final_count}" - - # Verify count unchanged (DELETE was not executed) - if [ "$initial_count" -eq "$final_count" ]; then - log_info "✓ Test $TOTAL_TESTS passed - Data unchanged (count: ${initial_count})" - PASSED_TESTS=$((PASSED_TESTS + 1)) - else - log_error "✗ Test $TOTAL_TESTS failed - Count changed (initial: ${initial_count}, final: ${final_count})" + # Check that response does NOT contain isError:true + log_verbose "Checking response for isError has_error=\"false\"" + if echo "$response" | grep -q '"isError":true'; then + log_error "✗ Test $TOTAL_TESTS failed - Response contains isError:true response=\"${response}\"" FAILED_TESTS=$((FAILED_TESTS + 1)) + else + # Check that it contains PONG (the OK_msg) + log_verbose "Checking response contains expected OK_msg expected=\"PONG\" found=\"true\"" + if echo "$response" | grep -q 'PONG'; then + log_info "✓ Test $TOTAL_TESTS passed - Response contains PONG ok_msg=\"PONG\" response=\"${response}\"" + PASSED_TESTS=$((PASSED_TESTS + 1)) + else + log_error "✗ Test $TOTAL_TESTS failed - Response does not contain expected PONG response=\"${response}\"" + FAILED_TESTS=$((FAILED_TESTS + 1)) + fi fi - # T9.2: Verify OK message response format - log_test "T9.2: Verify OK message response is successful (not error)" + # T9.2: Verify queries with OK_msg are NOT tracked in stats_mcp_query_digest + # Since the rule exists from the beginning, intercepted queries should not create entries + log_test "T9.2: Queries with OK_msg - no entries in stats_mcp_query_digest (intercepted)" TOTAL_TESTS=$((TOTAL_TESTS + 1)) + # Execute a PING query (should be intercepted by OK_msg rule) payload='{"jsonrpc":"2.0","method":"tools/call","params":{"name":"run_sql_readonly","arguments":{"sql":"PING"}},"id":1}' response=$(mcp_request "query" "$payload") log_verbose "Response: ${response}" - # Check that response does NOT contain isError:true + # First, verify the response is successful and contains expected OK_msg if echo "$response" | grep -q '"isError":true'; then - log_error "✗ Test $TOTAL_TESTS failed - Response contains isError:true" + log_error "✗ Test $TOTAL_TESTS failed - Response contains isError:true response=\"${response}\"" + FAILED_TESTS=$((FAILED_TESTS + 1)) + elif ! echo "$response" | grep -q 'PONG'; then + log_error "✗ Test $TOTAL_TESTS failed - Response does not contain expected PONG response=\"${response}\"" FAILED_TESTS=$((FAILED_TESTS + 1)) else - # Check that it contains PONG (the OK_msg) - if echo "$response" | grep -q 'PONG'; then - log_info "✓ Test $TOTAL_TESTS passed - Response contains PONG: ${response}" + # Response is valid, now check that no entry exists in stats_mcp_query_digest for PING queries + ping_digest=$(exec_admin_silent "SELECT COUNT(*) FROM stats_mcp_query_digest WHERE digest_text LIKE '%PING%';") + log_verbose "PING digest count: ${ping_digest}" + + if [ "$ping_digest" = "0" ]; then + log_info "✓ Test $TOTAL_TESTS passed - stats_mcp_query_digest has no PING entries (queries intercepted) count=\"${ping_digest}\" response_valid=\"true\"" + PASSED_TESTS=$((PASSED_TESTS + 1)) + else + log_error "✗ Test $TOTAL_TESTS failed - stats_mcp_query_digest has PING entries (queries were not intercepted) count=\"${ping_digest}\"" + FAILED_TESTS=$((FAILED_TESTS + 1)) + fi + fi + + # Also verify other intercepted queries are not tracked + log_test "T9.2: Verify health_check queries are not tracked" + TOTAL_TESTS=$((TOTAL_TESTS + 1)) + + payload='{"jsonrpc":"2.0","method":"tools/call","params":{"name":"run_sql_readonly","arguments":{"sql":"SELECT * FROM health_check;"}},"id":1}' + response=$(mcp_request "query" "$payload") + log_verbose "Response: ${response}" + + # First, verify the response is successful and contains expected OK_msg + if echo "$response" | grep -q '"isError":true'; then + log_error "✗ Test $TOTAL_TESTS failed - Response contains isError:true response=\"${response}\"" + FAILED_TESTS=$((FAILED_TESTS + 1)) + elif ! echo "$response" | grep -q 'Status: OK'; then + log_error "✗ Test $TOTAL_TESTS failed - Response does not contain expected 'Status: OK' response=\"${response}\"" + FAILED_TESTS=$((FAILED_TESTS + 1)) + else + # Response is valid, now check that no entry exists in stats_mcp_query_digest for health_check queries + health_digest=$(exec_admin_silent "SELECT COUNT(*) FROM stats_mcp_query_digest WHERE digest_text LIKE '%health_check%';") + log_verbose "health_check digest count: ${health_digest}" + + if [ "$health_digest" = "0" ]; then + log_info "✓ Test $TOTAL_TESTS passed - stats_mcp_query_digest has no health_check entries count=\"${health_digest}\" response_valid=\"true\"" PASSED_TESTS=$((PASSED_TESTS + 1)) else - log_error "✗ Test $TOTAL_TESTS failed - Response does not contain expected PONG" + log_error "✗ Test $TOTAL_TESTS failed - stats_mcp_query_digest has health_check entries count=\"${health_digest}\"" FAILED_TESTS=$((FAILED_TESTS + 1)) fi fi