fix: Improved MCP rule testing and helpers

pull/5331/head
Javier Jaramago Fernández 4 months ago
parent 888eb24b14
commit 4d4bb9dec5

@ -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

@ -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

Loading…
Cancel
Save