From 8c731be6f27ce6e06b17ec6c6d7a7b5605032ff0 Mon Sep 17 00:00:00 2001 From: Rahim Kanji Date: Tue, 14 Nov 2023 16:11:13 +0500 Subject: [PATCH] Updated TAP test --- test/tap/tests/test_warnings-t.cpp | 294 +++++++++++++++++++++-------- 1 file changed, 216 insertions(+), 78 deletions(-) diff --git a/test/tap/tests/test_warnings-t.cpp b/test/tap/tests/test_warnings-t.cpp index 6ddc148b9c..514b93ce4a 100644 --- a/test/tap/tests/test_warnings-t.cpp +++ b/test/tap/tests/test_warnings-t.cpp @@ -31,7 +31,13 @@ using MESSAGE = std::string; } \ } while(0) -#define MYSQL_CLEAR_RESULT(mysql) mysql_free_result(mysql_store_result(mysql)); +#define MYSQL_CLEAR_RESULT(mysql) mysql_free_result(mysql_store_result(mysql)); +#define MYSQL_CLEAR_STMT_RESULT(stmt) mysql_stmt_store_result(stmt); \ + mysql_stmt_free_result(stmt); + +#define INIT_QUERY_TEXT(QUERY, IS_SELECT) {QUERY, IS_SELECT, false} +#define INIT_QUERY_PREPARE_STMT(QUERY, IS_SELECT) {QUERY, IS_SELECT, true} + enum MultiplexStatus { kNotApplicable = 0, @@ -57,6 +63,7 @@ enum class WarningCheckType { struct QueryInfo { const char* query; bool is_select; + bool prepare_stmt; }; struct WarningCheckInfo { @@ -89,11 +96,50 @@ int execute_query(MYSQL* proxysql, const QueryInfo& query_info) { return EXIT_SUCCESS; } +int prepare_and_execute_stmt(MYSQL* mysql, const QueryInfo& query_info, MYSQL_STMT** stmt_out) { + assert(stmt_out); + MYSQL_STMT* stmt = mysql_stmt_init(mysql); + if (!stmt) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); + return EXIT_FAILURE; + } + if (mysql_stmt_prepare(stmt, query_info.query, strlen(query_info.query))) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_stmt_error(stmt)); + mysql_stmt_close(stmt); + return EXIT_FAILURE; + } + if (mysql_stmt_execute(stmt) != 0) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_stmt_error(stmt)); + mysql_stmt_close(stmt); + return EXIT_FAILURE; + } + if (query_info.is_select) { + //MYSQL_CLEAR_STMT_RESULT(stmt); + mysql_stmt_store_result(stmt); + mysql_stmt_free_result(stmt); + /*int status; + while(1) { + status = mysql_stmt_fetch(stmt); + if (status == 1 || status == MYSQL_NO_DATA) + break; + }*/ + } + //mysql_stmt_close(stmt); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + *stmt_out = stmt; + return EXIT_SUCCESS; +} + // get warning count from MySQL connection (MYSQL::warning_count) int get_warnings_count_from_connection(MYSQL* mysql) { return mysql_warning_count(mysql); } +// get warning count from statement (MYSQL_STMT::mysql_upsert_status::warning_count) +int get_warnings_count_from_statement(MYSQL_STMT* stmt) { + return mysql_stmt_warning_count(stmt); +} + // retrieve warning count through a query. This action does not clear the warning message list. int get_warnings_count(MYSQL* mysql) { MYSQL_QUERY(mysql, "SHOW COUNT(*) WARNINGS"); @@ -173,103 +219,177 @@ int check_proxysql_internal_session(MYSQL* proxysql, int exp_status) { } const std::vector mysql_variable_test = { - { ConnectionType::kAdmin, {"DELETE FROM mysql_query_rules", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL QUERY RULES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"SET mysql-handle_warnings=0", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kMySQL, {"DO 1/0", false}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kAdmin, {"SET mysql-handle_warnings=1", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, - { ConnectionType::kMySQL, {"SELECT 1" , true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kMySQL, {"DO 1/0", false}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, - { ConnectionType::kMySQL, {"DO 1", false}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) } + { ConnectionType::kAdmin, INIT_QUERY_TEXT("DELETE FROM mysql_query_rules", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL QUERY RULES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("DELETE FROM mysql_hostgroup_attributes", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL SERVERS TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("SET mysql-handle_warnings=0", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("SET mysql-handle_warnings=1", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1" , true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1" , true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) } }; const std::vector hostgroup_attributes_test = { - { ConnectionType::kAdmin, {"SET mysql-handle_warnings=1", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"DELETE FROM mysql_hostgroup_attributes", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"INSERT INTO mysql_hostgroup_attributes (hostgroup_id, hostgroup_settings) VALUES (0, '{\"handle_warnings\":0}')", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL SERVERS TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("SET mysql-handle_warnings=1", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("DELETE FROM mysql_hostgroup_attributes", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("INSERT INTO mysql_hostgroup_attributes (hostgroup_id, hostgroup_settings) VALUES (0, '{\"handle_warnings\":0}')", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL SERVERS TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, // Hostgroup attributes take precedence and should override the global variable value for the specified hostgroup. - { ConnectionType::kMySQL, {"DO 1/0", false}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)}, - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)}, - { ConnectionType::kMySQL, {"DO 1", false}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kMySQL, {"SELECT 1", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kAdmin, {"SET mysql-handle_warnings=0", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"DELETE FROM mysql_hostgroup_attributes", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"INSERT INTO mysql_hostgroup_attributes (hostgroup_id, hostgroup_settings) VALUES (0, '{\"handle_warnings\":1}')", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL SERVERS TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kMySQL, {"DO 1/0", false}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) } // intentional + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)}, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)}, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)}, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled)}, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("SET mysql-handle_warnings=0", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("DELETE FROM mysql_hostgroup_attributes", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("INSERT INTO mysql_hostgroup_attributes (hostgroup_id, hostgroup_settings) VALUES (0, '{\"handle_warnings\":1}')", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL SERVERS TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) } }; const std::vector select_test = { - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, - { ConnectionType::kMySQL, {"SELECT 1" , true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kMySQL, {"DO 1/0", false}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, - { ConnectionType::kMySQL, {"DO 1" , false}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) } + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1" , true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1" , false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1" , true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("DO 1" , false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) } }; const std::vector insert_test = { - { ConnectionType::kMySQL, {"SET sql_mode='ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kMySQL, {"DROP DATABASE IF EXISTS testdb", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kMySQL, {"CREATE DATABASE testdb", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kMySQL, {"CREATE TABLE testdb.t1 (a TINYINT NOT NULL, b CHAR(4))", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kMySQL, {"INSERT INTO testdb.t1 VALUES(10, 'mysql'), (NULL, 'test'), (300, 'xyz')", false}, {WarningCheckType::kAll, 3, {1265,1048,1264}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, - { ConnectionType::kMySQL, {"SELECT 1", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kMySQL, {"DROP DATABASE IF EXISTS testdb", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingDisabled) } + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SET sql_mode='ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DROP DATABASE IF EXISTS testdb", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("CREATE DATABASE testdb", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("CREATE TABLE testdb.t1 (a TINYINT NOT NULL, b CHAR(4))", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("INSERT INTO testdb.t1 VALUES(10, 'mysql'), (NULL, 'test'), (300, 'xyz')", false), {WarningCheckType::kAll, 3, {1265,1048,1264}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("INSERT INTO testdb.t1 VALUES(10, 'mysql'), (NULL, 'test'), (300, 'xyz')", false), {WarningCheckType::kAll, 3, {1265,1048,1264}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DROP DATABASE IF EXISTS testdb", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingDisabled) } }; const std::vector query_cache_test = { - { ConnectionType::kAdmin, {"SET mysql-query_cache_handle_warnings=0", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"DELETE FROM mysql_query_rules", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"INSERT INTO mysql_query_rules (rule_id,active,match_digest,cache_ttl,apply) VALUES (1,1,'SELECT ?/?',60000,1)", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL QUERY RULES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"PROXYSQL FLUSH QUERY CACHE", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("SET mysql-query_cache_handle_warnings=0", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("DELETE FROM mysql_query_rules", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("INSERT INTO mysql_query_rules (rule_id,active,match_digest,cache_ttl,apply) VALUES (1,1,'SELECT ?/?',60000,1)", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL QUERY RULES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("PROXYSQL FLUSH QUERY CACHE", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, // this entry should not be saved in cache - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, - { ConnectionType::kMySQL, {"SELECT 1", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kAdmin, {"SET mysql-query_cache_handle_warnings=1", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + //{ ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + // { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("SET mysql-query_cache_handle_warnings=1", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, // resultset will be retrived from cache, with warning count zero - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kAdmin, {"DELETE FROM mysql_query_rules", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL QUERY RULES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"PROXYSQL FLUSH QUERY CACHE", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) } + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + //{ ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("DELETE FROM mysql_query_rules", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL QUERY RULES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("PROXYSQL FLUSH QUERY CACHE", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) } }; const std::vector query_digest_test = { - { ConnectionType::kAdmin, {"SET mysql-query_digests='false'", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kAdmin, {"SET mysql-query_digests='true'", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) } + { ConnectionType::kAdmin, INIT_QUERY_TEXT("SET mysql-query_digests='false'", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("DO 1/0", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("SET mysql-query_digests='true'", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) } }; const std::vector warning_log_test = { - { ConnectionType::kAdmin, {"SET mysql-log_mysql_warnings_enabled='true'", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, - { ConnectionType::kMySQL, {"SELECT 1", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, - { ConnectionType::kAdmin, {"SET mysql-log_mysql_warnings_enabled='false'", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, - { ConnectionType::kAdmin, {"LOAD MYSQL VARIABLES TO RUNTIME", false}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) } + { ConnectionType::kAdmin, INIT_QUERY_TEXT("SET mysql-log_mysql_warnings_enabled='true'", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingDisabled) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("SET mysql-log_mysql_warnings_enabled='false'", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) }, + { ConnectionType::kAdmin, INIT_QUERY_TEXT("LOAD MYSQL VARIABLES TO RUNTIME", false), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kNotApplicable) } }; const std::vector multiplexing_test = { - { ConnectionType::kMySQL, {"SELECT @@sql_mode", true}, {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) }, - { ConnectionType::kMySQL, {"SELECT 1/0", true}, {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables | MultiplexStatus::kHasWarnings) }, - { ConnectionType::kMySQL, {"SELECT 1", true}, {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) } + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT @@sql_mode", true), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("SELECT @@sql_mode", true), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1/0", false), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_TEXT("DO 1", false), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT @@sql_mode", true), {WarningCheckType::kNotApplicable}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1/0", true), {WarningCheckType::kAll, 1, {1365}}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables | MultiplexStatus::kHasWarnings) }, + { ConnectionType::kMySQL, INIT_QUERY_PREPARE_STMT("SELECT 1", true), {WarningCheckType::kAll, 0}, (MultiplexStatus::kMultiplexingEnabled | MultiplexStatus::kUserVariables) } }; #define IS_BIT_MASK_SET(variable,flag) ((variable & static_cast(flag)) == static_cast(flag)) +// base case +size_t check_count() { return 0; } + +template +size_t check_count(First&& first, Rest&&... rest) { + + size_t count = 0; + + for (const auto& val : first) { + if (val.warning_check_info.type != WarningCheckType::kNotApplicable) { + if (val.warning_check_info.type == WarningCheckType::kAll) + count += 3; + else + count += 1; + count += val.warning_check_info.warning_codes.size(); + } + if (val.multiplex_status != 0) + count += 1; + } + return (count + check_count(rest...)); +} + +template +constexpr size_t test_size(Args&&... args) { + return sizeof...(args); +} + +#define TESTS_COMBINED mysql_variable_test, hostgroup_attributes_test, select_test, insert_test, query_digest_test, \ + query_cache_test, warning_log_test, multiplexing_test + int main(int argc, char** argv) { CommandLine cl; @@ -279,7 +399,9 @@ int main(int argc, char** argv) { return -1; } - plan((20 + 6) + // mysql variable test: 20 warning checks, 6 multiplex status checks + plan(check_count(TESTS_COMBINED)); + + /*plan((20 + 6) + // mysql variable test: 20 warning checks, 6 multiplex status checks (20 + 6) + // hostgroup attributes test: 20 warning checks, 6 multiplex status checks (14 + 4) + // select test: 14 warning checks, 4 multiplex status checks (9 + 4) + // insert test: 9 warning checks, 4 multiplex status checks @@ -287,6 +409,7 @@ int main(int argc, char** argv) { (18 + 5) + // query cache test: 18 warning checks, 5 multiplex status checks (7 + 2) + // warning log test: 7 warning checks, 2 multiplex status checks (7 + 3)); // multiplexing test: 7 warning checks, 3 multiplex status checks + */ // Initialize Admin connection MYSQL* proxysql_admin = mysql_init(NULL); @@ -313,11 +436,11 @@ int main(int argc, char** argv) { return exit_status(); } - std::vector>> all_tests(8); + std::vector>> all_tests(test_size(TESTS_COMBINED)); all_tests[0].first = "MYSQL VARIABLE (mysql-handle_warnings)"; all_tests[0].second.insert(all_tests[0].second.end(), mysql_variable_test.begin(), mysql_variable_test.end()); - + all_tests[1].first = "HOSTGROUP ATTRIBUTES (handle_warnings)"; all_tests[1].second.insert(all_tests[1].second.end(), hostgroup_attributes_test.begin(), hostgroup_attributes_test.end()); @@ -338,19 +461,28 @@ int main(int argc, char** argv) { all_tests[7].first = "MULTIPLEXING"; all_tests[7].second.insert(all_tests[7].second.end(), multiplexing_test.begin(), multiplexing_test.end()); - + for (const auto& test : all_tests) { diag("Executing [%s] test...", test.first); for (const auto& test_info : test.second) { MYSQL* mysql = (test_info.conn_type == ConnectionType::kMySQL ? proxysql : proxysql_admin); + MYSQL_STMT* stmt = nullptr; - if (execute_query(mysql, test_info.query_info) == EXIT_FAILURE) - goto __exit; + if (test_info.query_info.prepare_stmt) { + if (prepare_and_execute_stmt(mysql, test_info.query_info, &stmt) == EXIT_FAILURE) + goto __exit; + } else { + if (execute_query(mysql, test_info.query_info) == EXIT_FAILURE) + goto __exit; + } const int check_type = static_cast(test_info.warning_check_info.type); if (IS_BIT_MASK_SET(check_type, WarningCheckType::kConnection)) { - const int count = get_warnings_count_from_connection(mysql); + int count = get_warnings_count_from_connection(mysql); + if (test_info.query_info.prepare_stmt) { + count &= get_warnings_count_from_statement(stmt); + } ok((count == test_info.warning_check_info.warning_count), "Connection warning count should match. Expected count:'%d' Actual count:'%d'", test_info.warning_check_info.warning_count, count); } if (IS_BIT_MASK_SET(check_type, WarningCheckType::kCountQuery)) { @@ -379,9 +511,15 @@ int main(int argc, char** argv) { } if (test_info.multiplex_status != MultiplexStatus::kNotApplicable) { - if (check_proxysql_internal_session(mysql, test_info.multiplex_status) != EXIT_SUCCESS) + if (check_proxysql_internal_session(mysql, test_info.multiplex_status) != EXIT_SUCCESS) { + if (stmt) + mysql_stmt_close(stmt); goto __exit; + } } + + if (stmt) + mysql_stmt_close(stmt); } }