You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
proxysql/test/tap/tests/reg_test_4300-dollar_quote_...

150 lines
4.6 KiB

/**
* @file reg_test_4300-dollar_quote_check-t.cpp
* @brief Checks that ProxySQL properly handles the query 'SELECT $$'.
* @details A check via 'SELECT $$' was introduced by MySQL client in version '8.1.0'. It's used for testing
* whether the server supports multiple '$$' signs or returns a syntax error (deprecated).
*/
#include <cassert>
#include <cstring>
#include <string>
#include <utility>
#include <vector>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include "mysql.h"
#include "mysqld_error.h"
#include "tap.h"
#include "utils.h"
#include "command_line.h"
using std::vector;
using std::string;
const vector<string> versions { "5.6", "5.7", "8.0", "8.1.0", "8.1", "8.1.4" };
int test_supports_dollar_quote(MYSQL* conn, int v_idx, int v8_1_0_idx) {
int rc = mysql_query_t(conn, "SELECT $$");
int exp_code = -1;
int act_code = mysql_errno(conn);
const char* exp_msg = "";
const char* act_msg = mysql_error(conn);
if (v_idx < v8_1_0_idx) {
exp_code = ER_BAD_FIELD_ERROR;
exp_msg = "Unknown column '$$' in 'field list'";
} else {
exp_code = ER_PARSE_ERROR;
exp_msg = "You have an error in your SQL syntax";
}
bool code_match = exp_code == act_code;
bool msg_match = strstr(act_msg, exp_msg) != nullptr;
ok(
rc && code_match && msg_match,
"Error code and message should match expected - exp:{%d,'%s'}, act:{%d,'%s'}",
exp_code, exp_msg, act_code, act_msg
);
const string rnd_str { random_string(30) };
rc = mysql_query_t(conn, ("SELECT '" + rnd_str + "'").c_str());
MYSQL_RES* myres = mysql_store_result(conn);
MYSQL_ROW myrow = mysql_fetch_row(myres);
string rnd_res { myrow[0] };
mysql_free_result(myres);
ok(
rc == 0 && rnd_str == rnd_res,
"Simple 'SELECT' is correctly executed after intercepted one - exp:'%s', act:'%s'",
rnd_str.c_str(), rnd_res.c_str()
);
return EXIT_SUCCESS;
}
int test_versions_mysql(MYSQL* admin, MYSQL* proxy, const vector<string>& versions) {
const int64_t v8_1_0_idx { get_elem_idx(string { "8.1.0" }, versions) };
assert(v8_1_0_idx != -1 && "Invalid test payload, no '8.1.0' present in tested versions");
for (size_t i = 0; i < versions.size(); i++) {
const string& v { versions[i] };
const string v_minor { v == "8.1.0" ? v : v + "." + std::to_string(rand()) };
MYSQL_QUERY_T(admin, ("UPDATE global_variables SET variable_value='" + v_minor + "' WHERE variable_name='mysql-server_version'").c_str());
MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME");
test_supports_dollar_quote(proxy, i, v8_1_0_idx);
}
return EXIT_SUCCESS;
}
int test_versions_admin(CommandLine& cl, MYSQL* admin, const vector<string>& versions) {
const int64_t v8_1_0_idx { get_elem_idx(string { "8.1.0" }, versions) };
assert(v8_1_0_idx != -1 && "Invalid test payload, no '8.1.0' present in tested versions");
for (size_t i = 0; i < versions.size(); i++) {
const string& v { versions[i] };
const string v_minor { v == "8.1.0" ? v : v + "." + std::to_string(rand()) };
MYSQL_QUERY_T(admin, ("UPDATE global_variables SET variable_value='" + v_minor + "' WHERE variable_name='mysql-server_version'").c_str());
MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME");
MYSQL* new_admin = mysql_init(NULL);
if (!mysql_real_connect(new_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(new_admin));
return EXIT_FAILURE;
}
test_supports_dollar_quote(new_admin, i, v8_1_0_idx);
mysql_close(new_admin);
}
return EXIT_SUCCESS;
}
int main(int argc, char** argv) {
CommandLine cl;
plan((versions.size()*2 + 1)*2);
if (cl.getEnv()) {
diag("Failed to get the required environmental variables.");
return EXIT_FAILURE;
}
MYSQL* proxy = mysql_init(NULL);
MYSQL* admin = mysql_init(NULL);
if (!mysql_real_connect(proxy, cl.host, cl.username, cl.password, NULL, cl.port, NULL, 0)) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxy));
return EXIT_FAILURE;
}
if (!mysql_real_connect(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(admin));
return EXIT_FAILURE;
}
int rc = test_versions_mysql(admin, proxy, versions);
ok(rc == EXIT_SUCCESS, "Multiple 'mysql-server_version' tested correctly against MySQL interface");
rc = test_versions_admin(cl, admin, versions);
ok(rc == EXIT_SUCCESS, "Multiple 'mysql-server_version' tested correctly against Admin interface");
mysql_close(proxy);
mysql_close(admin);
return exit_status();
}