diff --git a/test/tap/tests/test_unsupported_queries-t.cpp b/test/tap/tests/test_unsupported_queries-t.cpp index 5794fca8c..1ede58a8b 100755 --- a/test/tap/tests/test_unsupported_queries-t.cpp +++ b/test/tap/tests/test_unsupported_queries-t.cpp @@ -22,9 +22,6 @@ #include "tap.h" #include "utils.h" -using std::string; -using std::vector; - /** * @brief List of the pairs holding the unsupported queries to be executed by ProxySQL * together with the error code that they should return. @@ -68,13 +65,22 @@ using query_test_info = std::function >; +// "SET mysql-enable_load_data_local_infile='true'", + /** * @brief Enable the query based using the information supplied in the * 'query_info' parameter, and verifies that the value of the query has properly * change at runtime. + * + * @param proxysql_admin An already oppened connection to ProxySQL Admin. + * @param query_info Information about the query to be enabled. + * + * @return True if the query was properly enabled, false if not. */ bool enable_query(MYSQL* proxysql_admin, const query_test_info& query_info, bool enable=true) { std::string exp_var_value {}; + + // In case of false, we choose the value for disabling the variable if (enable == true) { exp_var_value = std::get<2>(query_info); } else { @@ -86,17 +92,59 @@ bool enable_query(MYSQL* proxysql_admin, const query_test_info& query_info, bool "LOAD MYSQL VARIABLES TO RUNTIME" }; - bool success = true; + bool query_enabling_succeed = true; + for (const auto& query : enabling_queries) { - diag("Admin Query: %s", query.c_str()); - if (mysql_query(proxysql_admin, query.c_str())) { - diag("ERROR: ProxySQL Admin Error: %s", mysql_error(proxysql_admin)); - success = false; - break; + int query_res = mysql_query(proxysql_admin, query.c_str()); + if (query_res) { + diag( + "Query '%s' for enabling query '%s' enabling at line '%d', with error: '%s'", + query.c_str(), std::get<0>(query_info).c_str(), __LINE__, + mysql_error(proxysql_admin) + ); + query_enabling_succeed = false; + goto exit; + } + } + + { + std::string variable_value {}; + int var_err = get_variable_value( + proxysql_admin, std::get<1>(query_info), variable_value, true + ); + + if (var_err) { + diag( + "Getting value for variable '%s', failed with error: '%d'", + std::get<1>(query_info).c_str(), var_err + ); + query_enabling_succeed = false; + goto exit; + } + + // perform a final conversion in case it's required for the exp value + std::string f_exp_var_value {}; + if (exp_var_value == "'true'") { + f_exp_var_value = "true"; + } else if (exp_var_value == "'false'") { + f_exp_var_value = "false"; + } else { + f_exp_var_value = exp_var_value; + } + + if (variable_value != f_exp_var_value) { + query_enabling_succeed = false; + diag( + "Variable value doesn't match expected: (Exp: '%s', Act: '%s')", + exp_var_value.c_str(), variable_value.c_str() + ); + goto exit; } } - ok(success, "%s query '%s' should succeed.", (enable ? "Enabling" : "Disabling"), std::get<0>(query_info).c_str()); - return success; + +exit: + + return query_enabling_succeed; } // ******************* QUERIES TESTING FUNCTIONS ******************** // @@ -112,188 +160,464 @@ using mysql_res_row = std::vector; /** * @brief Helper function that performs the actual check for 'test_load_data_local_infile'. + * + * @param cl CommandLine parameters required for the test. + * @param proxysql An already oppened connection to ProxySQL. + * @param exp_err The expected error code in case we are testing for failure, + * '0' by default. + * @param test_for_success Select the operation mode of the test, 'true' for + * testing for success, 'false' for failure. It's 'true' by default. */ void helper_test_load_data_local_infile( const CommandLine& cl, MYSQL* proxysql, int exp_err=0, bool test_for_success=true ) { - // PROVISIONING: Create shared directory and data file in /var/lib/proxysql - // This ensures the server container can see the local file we want to load. - string script_dst = "/var/lib/proxysql/load_data_local_datadir"; - string datafile = script_dst + "/insert_data.txt"; - - diag("Step: Provisioning LOAD DATA test files..."); - diag(" - Target directory: %s", script_dst.c_str()); - string cmd = "mkdir -p " + script_dst + " && printf '1,\"a string\",100.20\n2,\"a string containing a , comma\",102.20\n3,\"a string containing a \\\" quote\",102.20\n4,\"a string containing a \\\", quote and comma\",102.20\n' > " + datafile + " && chmod -R 777 " + script_dst; - - if (system(cmd.c_str()) != 0) { - diag("WARNING: Failed to provision test files to %s. Test may fail.", script_dst.c_str()); - } + // Provision test data to shared volume + std::string script_dst = "/var/lib/proxysql/load_data_local_datadir"; + std::string datafile_ci = script_dst + "/insert_data.txt"; + std::string cmd = "mkdir -p " + script_dst + " && printf '1,\"a string\",100.20\n2,\"a string containing a , comma\",102.20\n3,\"a string containing a \\\" quote\",102.20\n4,\"a string containing a \\\", quote and comma\",102.20\n' > " + datafile_ci + " && chmod -R 777 " + script_dst; + system(cmd.c_str()); + + const char* d_env = getenv("REGULAR_INFRA_DATADIR"); + + std::string datafile = (d_env ? std::string(d_env) + "/load_data_local_datadir/insert_data.txt" + : std::string(cl.workdir) + "load_data_local_datadir/insert_data.txt"); + diag("Data file path: %s", datafile.c_str()); + + bool table_prep_success = true; - diag("Step: Preparing test table..."); for (const auto& query : prepare_table_queries) { - diag(" - Query: %s", query.c_str()); - if (mysql_query(proxysql, query.c_str())) { - diag(" - ERROR: %s", mysql_error(proxysql)); + int query_res = mysql_query(proxysql, query.c_str()); + if (query_res) { + diag( + "Query '%s' for table preparation failed at line '%d', with error: '%s'", + query.c_str(), __LINE__, mysql_error(proxysql) + ); + table_prep_success = false; + break; } } - std::string t_load_data_command { - "LOAD DATA LOCAL INFILE \"%s\" INTO TABLE test.load_data_local" - " FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n'" - }; - std::string load_data_command {}; - string_format(t_load_data_command, load_data_command, datafile.c_str()); + if (table_prep_success) { + std::string t_load_data_command { + "LOAD DATA LOCAL INFILE \"%s\" INTO TABLE test.load_data_local" + " FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\\n'" + }; + std::string load_data_command {}; + string_format(t_load_data_command, load_data_command, datafile.c_str()); - diag("Step: Executing LOAD DATA LOCAL INFILE..."); - diag(" - Query: %s", load_data_command.c_str()); - int load_data_res = mysql_query(proxysql, load_data_command.c_str()); + int load_data_res = + mysql_query(proxysql, load_data_command.c_str()); - if (test_for_success) { - if (load_data_res == EXIT_SUCCESS) { - diag(" - SUCCESS: Query returned no error."); - } else { - diag(" - FAILURE: Query failed. Error: %s", mysql_error(proxysql)); - } + if (test_for_success) { + if (load_data_res) { + diag( + load_data_command.c_str(), __LINE__, mysql_error(proxysql) + ); + } - diag("Step: Verifying data integrity via SELECT..."); - mysql_query(proxysql, "SELECT * /* ;hostgroup=0 */ FROM test.load_data_local"); - MYSQL_RES* result = mysql_store_result(proxysql); - std::vector rows_res { extract_mysql_rows(result) }; - std::vector exp_rows { - { "1","a string","100.20" }, - { "2","a string containing a , comma","102.20" }, - { "3","a string containing a \" quote","102.20" }, - { "4","a string containing a \", quote and comma","102.20" } - }; + if (load_data_res == EXIT_SUCCESS) { + diag( + "Supplied query '%s' succeeded, performing check on data...", + load_data_command.c_str() + ); + } else { + diag( + "Supplied query '%s' failed, check not going to be performed. Error was: '%s'.", + load_data_command.c_str(), mysql_error(proxysql) + ); + } - // Detailed row comparison output - diag(" - Rows found: %zu, Expected: %zu", rows_res.size(), exp_rows.size()); - if (rows_res.size() != exp_rows.size()) { - diag(" - ERROR: Row count mismatch!"); - } + // Check that the data has actually been loaded to the database + // NOTE: Specifically target 'hostgroup=0' to avoid replication lag. + int myerr = mysql_query(proxysql, "SELECT * /* ;hostgroup=0 */ FROM test.load_data_local"); + if (myerr) { + diag( + "Query 'SELECT * FROM test.load_data_local' for table preparation failed" + " at line '%d', with error: '%s'", __LINE__, mysql_error(proxysql) + ); + } else { + MYSQL_RES* result = mysql_store_result(proxysql); + std::vector rows_res { extract_mysql_rows(result) }; + std::vector exp_rows { + { "1","a string","100.20" }, + { "2","a string containing a , comma","102.20" }, + { "3","a string containing a \" quote","102.20" }, + { "4","a string containing a \", quote and comma","102.20" } + }; + + std::string exp_rows_str { "{\n" }; + for (const auto& exp_row : exp_rows) { + std::string exp_row_str { nlohmann::json(exp_row).dump() }; + exp_rows_str += " " + exp_row_str + ",\n"; + } + exp_rows_str += "}\n"; - bool equal = (rows_res.size() == exp_rows.size()); - if (equal) equal = std::equal(exp_rows.begin(), exp_rows.end(), rows_res.begin()); - - ok(equal, "The selected ROWS were equal to the expected ones"); - if (result) mysql_free_result(result); - } else { - int my_errno = mysql_errno(proxysql); - diag(" - Expected error: %d, Actual error: %d", exp_err, my_errno); - ok(my_errno == exp_err, "Query should fail with error %d. Actual: %d (%s)", exp_err, my_errno, mysql_error(proxysql)); + diag("Expected values for rows were: \n%s", exp_rows_str.c_str()); + + std::string act_rows_str { "{\n" }; + for (const auto& act_row : rows_res) { + std::string act_row_str { nlohmann::json(act_row).dump() }; + act_rows_str += " " + act_row_str + ",\n"; + } + act_rows_str += "}\n"; + + diag("Actual values for found rows were: \n%s", act_rows_str.c_str()); + + bool equal = false; + if (!rows_res.empty()) { + equal = std::equal(exp_rows.begin(), exp_rows.end(), rows_res.begin()); + } + + ok(equal, "The selected ROWS were equal to the expected ones"); + } + } else { + if (load_data_res) { + diag( + load_data_command.c_str(), __LINE__, mysql_error(proxysql) + ); + } + + int my_errno = mysql_errno(proxysql); + ok( + my_errno == exp_err, + "Query '%s' should fail. ErrCode: '%d', and error: '%s'", + load_data_command.c_str(), my_errno, mysql_error(proxysql) + ); + } } } +/** + * @brief Perform the same test as 'test_load_data_local_infile', but with + * 'mysql-verbose_query_error' set to 'true'. This test only purpose is + * to exercise the code performing the additional extra logging. + */ void test_verbose_error_load_data_local_infile( const CommandLine& cl, MYSQL* proxysql, int exp_err=0, bool test_for_success=true ) { - diag("Sub-Test: Testing with mysql-verbose_query_error=true"); - MYSQL* admin = mysql_init(NULL); - if (mysql_real_connect(admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) { - mysql_query(admin, "SET mysql-verbose_query_error='true'"); - mysql_query(admin, "LOAD MYSQL VARIABLES TO RUNTIME"); - helper_test_load_data_local_infile(cl, proxysql, exp_err, test_for_success); - mysql_query(admin, "SET mysql-verbose_query_error='false'"); - mysql_query(admin, "LOAD MYSQL VARIABLES TO RUNTIME"); - mysql_close(admin); + MYSQL* proxysql_admin = mysql_init(NULL); + + if ( + !mysql_real_connect( + proxysql_admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0 + ) + ) { + diag("File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); + return; + } + + std::vector verbose_query_error_true { + "SET mysql-verbose_query_error='true'", + "LOAD MYSQL VARIABLES TO RUNTIME" + }; + for (const auto& query : verbose_query_error_true) { + int query_err = mysql_query(proxysql_admin, query.c_str()); + if (query_err) { + diag("File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); + return; + } + } + + helper_test_load_data_local_infile(cl, proxysql, exp_err, test_for_success); + + std::vector verbose_query_error_false { + "SET mysql-verbose_query_error='false'", + "LOAD MYSQL VARIABLES TO RUNTIME" + }; + for (const auto& query : verbose_query_error_false) { + int query_err = mysql_query(proxysql_admin, query.c_str()); + if (query_err) { + diag("File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); + return; + } } + + mysql_close(proxysql_admin); } +/** + * @brief Test that the query 'LOAD DATA LOCAL INFILE' performs correctly when + * enabled, and returns the proper error code when disabled. Performs one + * 'ok()' call in case everything went as expected, and several 'diag()' call + * in case of errors. + * + * @param cl CommandLine parameters required for the test. + * @param proxysql An already oppened connection to ProxySQL. + * @param exp_err The expected error code in case we are testing for failure, + * '0' by default. + * @param test_for_success Select the operation mode of the test, 'true' for + * testing for success, 'false' for failure. It's 'true' by default. + */ void test_load_data_local_infile( const CommandLine& cl, MYSQL* proxysql, int exp_err=0, bool test_for_success=true ) { - diag("Sub-Test: Standard LOAD DATA LOCAL INFILE test"); helper_test_load_data_local_infile(cl, proxysql, exp_err, test_for_success); } +/** + * @brief Analogous function to 'test_load_data_local_infile' but it + * deliberately provides a non-existing file as an argument to make the query + * fail. + * + * @details This way we make sure that ProxySQL is exhibiting proper behavior + * for this unsupported query that can be misused. + * @param cl CommandLine parameters required for the test. + * @param proxysql An already oppened connection to ProxySQL. + * @param exp_err The expected error code in case we are testing for failure, + * '0' by default. + * @param test_for_success Select the operation mode of the test, 'true' for + * testing for success, 'false' for failure. It's 'true' by default. + */ void test_failing_load_data_local_infile( const CommandLine& cl, MYSQL* proxysql, int exp_err=0, bool test_for_success=true ) { - diag("Sub-Test: Testing failure with non-existing file"); - std::string datafile = "/var/lib/proxysql/load_data_local_datadir/non_existing_file.txt"; - diag(" - Using invalid path: %s", datafile.c_str()); + // Supply an invalid file + const char* d_env = getenv("REGULAR_INFRA_DATADIR"); + std::string datafile = (d_env ? std::string(d_env) + "/load_data_local_datadir/non_existing_file.txt" + : std::string(cl.workdir) + "load_data_local_datadir/non_existing_file.txt"); + diag("Data file path: %s", datafile.c_str()); + + bool table_prep_success = true; for (const auto& query : prepare_table_queries) { - mysql_query(proxysql, query.c_str()); + int query_res = mysql_query(proxysql, query.c_str()); + if (query_res) { + diag( + "Query '%s' for table preparation failed at line '%d', with error: '%s'", + query.c_str(), __LINE__, mysql_error(proxysql) + ); + table_prep_success = false; + break; + } } - std::string load_data_command = "LOAD DATA LOCAL INFILE \"" + datafile + "\" INTO TABLE test.load_data_local"; - int load_data_res = mysql_query(proxysql, load_data_command.c_str()); + if (table_prep_success) { + std::string t_load_data_command { + "LOAD DATA LOCAL INFILE \"%s\" INTO TABLE test.load_data_local" + }; + std::string load_data_command {}; + string_format(t_load_data_command, load_data_command, datafile.c_str()); - if (test_for_success) { - int my_errno = mysql_errno(proxysql); - diag(" - Actual error returned: %d (%s)", my_errno, mysql_error(proxysql)); - ok((load_data_res != EXIT_SUCCESS) && my_errno == 2, "Query should fail with Errcode 2 (File not found)"); - } else { - int my_errno = mysql_errno(proxysql); - diag(" - Expected error: %d, Actual: %d", exp_err, my_errno); - ok(my_errno == exp_err, "Query should fail with error %d. Actual: %d", exp_err, my_errno); + int load_data_res = + mysql_query(proxysql, load_data_command.c_str()); + + if (test_for_success) { + if (load_data_res) { + diag( + load_data_command.c_str(), __LINE__, mysql_error(proxysql) + ); + } + + int my_errno = mysql_errno(proxysql); + ok( + (load_data_res != EXIT_SUCCESS) && my_errno == 2, + "Query '%s' should fail. ErrCode: '%d', and error: '%s'", + load_data_command.c_str(), mysql_errno(proxysql), mysql_error(proxysql) + ); + } else { + if (load_data_res) { + diag( + load_data_command.c_str(), __LINE__, mysql_error(proxysql) + ); + } + + int my_errno = mysql_errno(proxysql); + ok( + my_errno == exp_err, + "Query '%s' should fail. ErrCode: '%d', and error: '%s'", + load_data_command.c_str(), my_errno, mysql_error(proxysql) + ); + } } } +// ****************************************************************** // + + +// ********************* QUERIES TESTS INFO ************************ // + /** * @brief List of queries which need to be check before performing the * 'unsupported' checks. */ std::vector queries_tests_info { - std::make_tuple>("LOAD DATA LOCAL INFILE", "mysql-enable_load_data_local_infile", "'true'", "'false'", 1047, test_load_data_local_infile), - std::make_tuple>("LOAD DATA LOCAL INFILE", "mysql-enable_load_data_local_infile", "'true'", "'false'", 1047, test_failing_load_data_local_infile), - std::make_tuple>("LOAD DATA LOCAL INFILE", "mysql-enable_load_data_local_infile", "'true'", "'false'", 1047, test_verbose_error_load_data_local_infile), + std::make_tuple< + std::string, std::string, std::string, std::string, int, + std::function + >( + // Query to be tested + "LOAD DATA LOCAL INFILE", + // Variable name enabling / disabling the query + "mysql-enable_load_data_local_infile", + // Value for enabling the query + "'true'", + // Value for diabling the query + "'false'", + // Expected error code in case of failure + 1047, + // Function performing an internal 'ok' test checking that the + // enabled / disabled query responds as expected + test_load_data_local_infile + ), + std::make_tuple< + std::string, std::string, std::string, std::string, int, + std::function + >( + // Query to be tested + "LOAD DATA LOCAL INFILE", + // Variable name enabling / disabling the query + "mysql-enable_load_data_local_infile", + // Value for enabling the query + "'true'", + // Value for diabling the query + "'false'", + // Expected error code in case of failure + 1047, + // Function performing an internal 'ok' test checking that the + // enabled / disabled query responds as expected + test_failing_load_data_local_infile + ), + std::make_tuple< + std::string, std::string, std::string, std::string, int, + std::function + >( + // Query to be tested + "LOAD DATA LOCAL INFILE", + // Variable name enabling / disabling the query + "mysql-enable_load_data_local_infile", + // Value for enabling the query + "'true'", + // Value for diabling the query + "'false'", + // Expected error code in case of failure + 1047, + // Function performing an internal 'ok' test checking that the + // enabled / disabled query responds as expected + test_verbose_error_load_data_local_infile + ), }; +// ****************************************************************** // + int main(int argc, char** argv) { CommandLine cl; - if (cl.getEnv()) return -1; diag("================================================================================"); diag("TEST DESCRIPTION: ProxySQL Unsupported and Conditional Query Validation"); diag("This test verifies that ProxySQL handles unsupported commands (like LOAD DATA LOCAL)"); diag("correctly by returning error 1047, and that these commands can be enabled"); diag("conditionally via global variables."); + diag("================================================================================"); + + + // plan as many tests as queries + plan(unsupported_queries.size() + 4 * queries_tests_info.size()); + + if (cl.getEnv()) { + diag("Failed to get the required environmental variables."); + return -1; + } + + // Verbose test header + diag("================================================================================"); + diag("Test: test_unsupported_queries-t"); + diag("================================================================================"); + diag("This test verifies that unsupported queries return the expected error codes,"); + diag("and that conditionally-enabled queries work correctly when enabled/disabled."); + diag(""); + diag("Test scenarios:"); + diag(" - Unsupported queries (LOAD DATA LOCAL INFILE) should fail with error 1047"); + diag(" - Conditionally enabled queries should work when enabled"); + diag(" - Conditionally enabled queries should fail when disabled"); diag(""); - diag("Connection Context:"); + diag("Connection parameters:"); diag(" - Host: %s", cl.host); diag(" - Port: %d", cl.port); diag(" - Admin Port: %d", cl.admin_port); diag("================================================================================"); + diag(""); - plan(unsupported_queries.size() + 4 * queries_tests_info.size()); - - diag("Phase 1: Testing naturally unsupported queries (Expecting 1047)"); + // perform a different connection per query for (const auto& unsupported_query : unsupported_queries) { - MYSQL* mysql = mysql_init(NULL); - if (mysql_real_connect(mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) { - string q = std::get<0>(unsupported_query); - diag(" - Executing: %s", q.c_str()); - int query_err = mysql_query(mysql, q.c_str()); - int m_errno = mysql_errno(mysql); - ok(query_err && (m_errno == std::get<1>(unsupported_query)), "Unsupported query failed as expected"); - mysql_close(mysql); + MYSQL* proxysql_mysql = mysql_init(NULL); + + // extract the tuple elements + const std::string query = std::get<0>(unsupported_query); + const int exp_err_code = std::get<1>(unsupported_query); + const std::string exp_err_msg = std::get<2>(unsupported_query); + + if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql)); + return EXIT_FAILURE; } + + int query_err = mysql_query(proxysql_mysql, query.c_str()); + int m_errno = mysql_errno(proxysql_mysql); + const char* m_error = mysql_error(proxysql_mysql); + + ok( + query_err && ( m_errno == exp_err_code ) && ( exp_err_msg == std::string { m_error } ), + "Unsupported query '%s' should fail. Error code: (Expected: '%d' == Actual:'%d'), Error msg: (Expected: '%s' == Actual:'%s')", + query.c_str(), + exp_err_code, + m_errno, + exp_err_msg.c_str(), + m_error + ); + + mysql_close(proxysql_mysql); } - diag("Phase 2: Testing conditionally-enabled queries via ProxySQL Admin"); - MYSQL* admin = mysql_init(NULL); - if (mysql_real_connect(admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) { - for (const auto& query_test_info : queries_tests_info) { - MYSQL* mysql = mysql_init(NULL); - if (mysql_real_connect(mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) { - diag("Scenario: Testing %s", std::get<0>(query_test_info).c_str()); - // 1. Enable - if (enable_query(admin, query_test_info, true)) { - // 2. Test Enabled (performs 1 ok) - std::get<5>(query_test_info)(cl, mysql, 0, true); - } - // 3. Disable - if (enable_query(admin, query_test_info, false)) { - // 4. Test Disabled (performs 1 ok) - std::get<5>(query_test_info)(cl, mysql, std::get<4>(query_test_info), false); - } - mysql_close(mysql); - } + // Create required connection to ProxySQL admin required to perform the + // tests for conditionally enabled queries. + MYSQL* proxysql_admin = mysql_init(NULL); + + if ( + !mysql_real_connect( + proxysql_admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0 + ) + ) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); + return EXIT_FAILURE; + } + + // Enable and test the queries that can be conditionally enabled + for (const auto& query_test_info : queries_tests_info) { + MYSQL* proxysql_mysql = mysql_init(NULL); + + // extract the tuple elements + const std::string query = std::get<0>(query_test_info); + const std::string variable_name = std::get<1>(query_test_info); + int exp_err = std::get<4>(query_test_info); + const auto& testing_fn = std::get<5>(query_test_info); + + if (!mysql_real_connect(proxysql_mysql, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_mysql)); + return EXIT_FAILURE; } - mysql_close(admin); + + bool query_enabling_succeed = enable_query(proxysql_admin, query_test_info, true); + ok( + query_enabling_succeed, "Enabling query '%s' should succeed.", + std::get<0>(query_test_info).c_str() + ); + + // Check that the query is now properly supported + testing_fn(cl, proxysql_mysql, 0, true); + + bool query_disabling_succeed = enable_query(proxysql_admin, query_test_info, false); + ok( + query_disabling_succeed, "Disabling query '%s' should succeed.", + std::get<0>(query_test_info).c_str() + ); + + // Check that the query is now failing + testing_fn(cl, proxysql_mysql, exp_err, false); + + mysql_close(proxysql_mysql); } + mysql_close(proxysql_admin); + return exit_status(); }