From b840468cd579e49784fdce891b4fb37cf815c400 Mon Sep 17 00:00:00 2001 From: Rene Cannao Date: Fri, 1 May 2026 14:04:52 +0000 Subject: [PATCH] test(unit): align genai_plugin_load + register plugin_runtime_views MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two unit-test-side fixes uncovered by running unit-tests-g1 against the new ABI-3 / Phase-B plugin shape: # genai_plugin_load_unit-t * setup_admindb_schema was using a pre-Step-4.G shape for the mcp_auth_profiles / mcp_target_profiles tables — the new install_*_from_admin reads the full canonical column set (use_ssl, ssl_mode, comment for auth; description, comment for targets) and was failing with `no such column: use_ssl`. Fixture now mirrors the DDL in include/ProxySQL_Admin_Tables_Definitions.h and also creates mcp_query_rules + runtime_mcp_query_rules so the newly-added install_query_rules_from_admin path also has tables to read. * As of Step 4.G the genai plugin publishes its admin/config/stats table set via genai_register_schemas (Phase B), not init. The test was calling load → init_all → start_all and the table-count assertions saw zero rows because Phase B never fired. Add an explicit invoke_register_schemas_phase between load and init_all (matches the order ProxySQL itself uses at startup) and bump the plan from 25 to 26 to cover the new ok(). # Makefile UNIT_TESTS list plugin_runtime_views_unit-t.cpp lives in test/tap/tests/unit/ and exercises the chassis ABI-3 register_runtime_view dispatch surface that landed in PR #5688. It had a build rule but wasn't in UNIT_TESTS, so the runner reported "(not-found)" for it. Wire it in alongside the other plugin-chassis unit tests under PROXYSQL40. --- test/tap/tests/unit/Makefile | 1 + .../tests/unit/genai_plugin_load_unit-t.cpp | 39 +++++++++++++++---- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/test/tap/tests/unit/Makefile b/test/tap/tests/unit/Makefile index 7253f95c9..3bdabc861 100644 --- a/test/tap/tests/unit/Makefile +++ b/test/tap/tests/unit/Makefile @@ -381,6 +381,7 @@ UNIT_TESTS += \ plugin_query_hook_unit-t \ plugin_prometheus_unit-t \ plugin_lifecycle_unit-t \ + plugin_runtime_views_unit-t \ genai_plugin_load_unit-t \ genai_plugin_anomaly_unit-t \ genai_plugin_backend_client_unit-t \ diff --git a/test/tap/tests/unit/genai_plugin_load_unit-t.cpp b/test/tap/tests/unit/genai_plugin_load_unit-t.cpp index a443fb2c5..d446ca09b 100644 --- a/test/tap/tests/unit/genai_plugin_load_unit-t.cpp +++ b/test/tap/tests/unit/genai_plugin_load_unit-t.cpp @@ -29,21 +29,37 @@ SQLite3DB* g_statsdb = nullptr; void setup_admindb_schema(SQLite3DB* db) { // Minimal schema to satisfy mcp_load_variables_from_admindb / - // mcp_load_target_auth_map_from_admindb in the plugin. + // mcp_load_target_auth_map_from_admindb in the plugin. Column + // shapes mirror the canonical DDLs in + // include/ProxySQL_Admin_Tables_Definitions.h so the plugin's + // SELECTs (which name every column by name) succeed. db->execute("CREATE TABLE IF NOT EXISTS global_variables (" " variable_name TEXT PRIMARY KEY, variable_value TEXT)"); db->execute("CREATE TABLE IF NOT EXISTS mcp_auth_profiles (" - " auth_profile_id INTEGER PRIMARY KEY, db_username TEXT," - " db_password TEXT, default_schema TEXT)"); + " auth_profile_id TEXT PRIMARY KEY, db_username TEXT," + " db_password TEXT, default_schema TEXT DEFAULT ''," + " use_ssl INTEGER NOT NULL DEFAULT 0," + " ssl_mode TEXT DEFAULT ''," + " comment TEXT DEFAULT '')"); db->execute("CREATE TABLE IF NOT EXISTS mcp_target_profiles (" " target_id TEXT PRIMARY KEY, protocol TEXT, hostgroup_id INTEGER," - " auth_profile_id INTEGER, max_rows INTEGER, timeout_ms INTEGER," - " allow_explain INTEGER, allow_discovery INTEGER, description TEXT," - " active INTEGER DEFAULT 1)"); + " auth_profile_id TEXT, description TEXT DEFAULT ''," + " max_rows INTEGER DEFAULT 200, timeout_ms INTEGER DEFAULT 2000," + " allow_explain INTEGER DEFAULT 1, allow_discovery INTEGER DEFAULT 1," + " active INTEGER DEFAULT 1, comment TEXT DEFAULT '')"); db->execute("CREATE TABLE IF NOT EXISTS runtime_mcp_auth_profiles AS" " SELECT * FROM mcp_auth_profiles WHERE 0"); db->execute("CREATE TABLE IF NOT EXISTS runtime_mcp_target_profiles AS" " SELECT * FROM mcp_target_profiles WHERE 0"); + db->execute("CREATE TABLE IF NOT EXISTS mcp_query_rules (" + " rule_id INTEGER PRIMARY KEY, active INTEGER NOT NULL DEFAULT 0," + " username TEXT, target_id TEXT, schemaname TEXT, tool_name TEXT," + " match_pattern TEXT, negate_match_pattern INTEGER NOT NULL DEFAULT 0," + " re_modifiers TEXT, flagIN INTEGER NOT NULL DEFAULT 0, flagOUT INTEGER," + " replace_pattern TEXT, timeout_ms INTEGER, error_msg TEXT, OK_msg TEXT," + " log INTEGER, apply INTEGER NOT NULL DEFAULT 1, comment TEXT)"); + db->execute("CREATE TABLE IF NOT EXISTS runtime_mcp_query_rules AS" + " SELECT * FROM mcp_query_rules WHERE 0"); } } // namespace @@ -53,7 +69,7 @@ SQLite3DB* proxysql_plugin_get_configdb() { return g_configdb; } SQLite3DB* proxysql_plugin_get_statsdb() { return g_statsdb; } int main() { - plan(25); + plan(26); g_admindb = new SQLite3DB(); g_configdb = new SQLite3DB(); @@ -74,6 +90,15 @@ int main() { } ok(mgr.size() == 1, "exactly one plugin handle after load"); + // Phase B (chassis): every plugin's register_schemas callback runs + // here, BEFORE init_all. As of Step 4.G the genai plugin uses this + // callback to publish its admin/config/stats table set, so it MUST + // fire before the size assertions below or we'll see 0 tables in + // every kind. + ok(mgr.invoke_register_schemas_phase(err), + "invoke_register_schemas_phase succeeds"); + if (!err.empty()) diag("register_schemas error: %s", err.c_str()); + ok(mgr.init_all(err), "init_all succeeds"); if (!err.empty()) diag("init error: %s", err.c_str());