mirror of https://github.com/sysown/proxysql
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.
204 lines
5.3 KiB
204 lines
5.3 KiB
/**
|
|
* @file reg_test_3690-admin_large_pkts-t.cpp
|
|
* @brief This test is a regression test for issue #3690.
|
|
* @details The test performs the following operations:
|
|
* 1. Creates a table in ProxySQL internal SQLite using an admin connection.
|
|
* 2. Fills this table with random length strings, varying from small to higher than 0xFFFFFF size.
|
|
* 3. Queries the generated rows, and checks that the received rows length matches the previously inserted
|
|
* rows length.
|
|
*
|
|
* @date 2021-12-01
|
|
*/
|
|
|
|
#include <tuple>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <random>
|
|
|
|
#include <mysql.h>
|
|
|
|
#include "json.hpp"
|
|
#include "tap.h"
|
|
#include "command_line.h"
|
|
#include "utils.h"
|
|
|
|
using std::string;
|
|
using std::vector;
|
|
|
|
string create_testing_table_query(int col_num) {
|
|
string test_table_query { "CREATE TABLE reg_test_3690_table (id INT" };
|
|
|
|
for (int i = 0; i < col_num; i++) {
|
|
test_table_query += ", v" + std::to_string(i) + " TEXT";
|
|
}
|
|
|
|
test_table_query += ")";
|
|
|
|
return test_table_query;
|
|
}
|
|
|
|
uint32_t TESTING_TABLE_COLUMNS = 10;
|
|
|
|
vector<uint32_t> generate_random_row_lens(int cols_num) {
|
|
std::random_device rd;
|
|
std::default_random_engine gen(rd());
|
|
std::uniform_int_distribution<> elem_type_dst(0, 4);
|
|
std::uniform_int_distribution<> small_value_dst(1, 30);
|
|
vector<uint32_t> row_lens {};
|
|
|
|
for (int i = 0; i < cols_num; i++) {
|
|
int elem_type = elem_type_dst(gen);
|
|
|
|
if (elem_type == 0) {
|
|
row_lens.push_back(0);
|
|
} else if (elem_type == 1) {
|
|
row_lens.push_back(small_value_dst(gen));
|
|
} else if (elem_type == 2) {
|
|
row_lens.push_back(small_value_dst(gen) + 0xFFFFFF*2);
|
|
} else {
|
|
row_lens.push_back(small_value_dst(gen) + 0xFFFFFF);
|
|
}
|
|
}
|
|
|
|
return row_lens;
|
|
}
|
|
|
|
string generate_insert_query(const vector<uint32_t>& cols_lens) {
|
|
string random_insert_query { "INSERT INTO reg_test_3690_table (" };
|
|
|
|
for (uint32_t i = 0; i < cols_lens.size(); i++) {
|
|
random_insert_query += "v" + std::to_string(i);
|
|
|
|
if (i != cols_lens.size() - 1) {
|
|
random_insert_query += ",";
|
|
}
|
|
}
|
|
|
|
random_insert_query += ") VALUES (";
|
|
|
|
for (vector<uint32_t>::const_iterator it = cols_lens.begin(); it != cols_lens.end(); it++) {
|
|
if (*it == 0) {
|
|
random_insert_query += "\"\"";
|
|
} else {
|
|
random_insert_query += "printf('%.' || " + std::to_string(*it) + " || 'c', '*')";
|
|
}
|
|
|
|
if (std::next(it) != cols_lens.end()) {
|
|
random_insert_query += ",";
|
|
}
|
|
}
|
|
|
|
random_insert_query += ")";
|
|
|
|
return random_insert_query;
|
|
}
|
|
|
|
using row_act_exp_lens = std::tuple<uint32_t, vector<uint32_t>, vector<uint32_t>>;
|
|
|
|
/**
|
|
* @brief Returns a vector holding the length of all the elements found for each row in the resulset.
|
|
*/
|
|
vector<vector<uint32_t>> fetch_rows_lens(MYSQL_RES* res) {
|
|
vector<vector<uint32_t>> rows {};
|
|
|
|
if (res == NULL) {
|
|
return rows;
|
|
}
|
|
|
|
MYSQL_ROW row = nullptr;
|
|
int num_fields = mysql_num_fields(res);
|
|
|
|
while ((row = mysql_fetch_row(res))) {
|
|
vector<uint32_t> row_vals {};
|
|
|
|
unsigned long *lengths;
|
|
lengths = mysql_fetch_lengths(res);
|
|
|
|
for(int i = 1; i < num_fields; i++) {
|
|
if (row[i]) {
|
|
row_vals.push_back(lengths[i]);
|
|
} else {
|
|
row_vals.push_back(0);
|
|
}
|
|
}
|
|
|
|
rows.push_back(row_vals);
|
|
}
|
|
|
|
return rows;
|
|
}
|
|
|
|
void match_row_lens(MYSQL_RES* t1_rows, const vector<vector<uint32_t>>& exp_rows_lens) {
|
|
vector<vector<uint32_t>> act_rows_lens { fetch_rows_lens(t1_rows) };
|
|
vector<row_act_exp_lens> result {};
|
|
|
|
for (uint32_t row_id = 0; row_id < exp_rows_lens.size(); row_id++) {
|
|
nlohmann::json j_exp_row_lens(exp_rows_lens[row_id]);
|
|
nlohmann::json j_act_row_lens(act_rows_lens[row_id]);
|
|
|
|
ok(
|
|
exp_rows_lens[row_id] == act_rows_lens[row_id],
|
|
"Actual rows lengths should match expected ones:\n"
|
|
" - Expected: '%s'\n - Actual: '%s'",
|
|
j_exp_row_lens.dump().c_str(), j_act_row_lens.dump().c_str()
|
|
);
|
|
}
|
|
}
|
|
|
|
uint32_t COLUMN_NUM = 10;
|
|
uint32_t ROW_NUM = 10;
|
|
|
|
int main(int argc, char** argv) {
|
|
CommandLine cl;
|
|
|
|
if (cl.getEnv()) {
|
|
diag("Failed to get the required environmental variables.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
MYSQL* proxysql_admin = mysql_init(NULL);
|
|
|
|
// Initialize connections
|
|
if (!proxysql_admin) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin));
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
// Connnect to local proxysql
|
|
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;
|
|
}
|
|
|
|
// There should be a test for each inserted row
|
|
plan(ROW_NUM);
|
|
|
|
// Drop the testing table if exists
|
|
MYSQL_QUERY(proxysql_admin, "DROP TABLE IF EXISTS reg_test_3690_table");
|
|
|
|
// Create the testing table
|
|
std::string testing_table_query { create_testing_table_query(COLUMN_NUM) };
|
|
MYSQL_QUERY(proxysql_admin, testing_table_query.c_str());
|
|
|
|
// Insert the randomly sized rows
|
|
vector<vector<uint32_t>> inserted_rows {};
|
|
for (int i = 0; i < ROW_NUM; i++) {
|
|
auto row = generate_random_row_lens(COLUMN_NUM);
|
|
string insert_query = generate_insert_query(row);
|
|
MYSQL_QUERY(proxysql_admin, insert_query.c_str());
|
|
|
|
inserted_rows.push_back(row);
|
|
}
|
|
|
|
// Get the rows
|
|
MYSQL_QUERY(proxysql_admin, "SELECT * FROM reg_test_3690_table");
|
|
MYSQL_RES* select_res = mysql_store_result(proxysql_admin);
|
|
match_row_lens(select_res, inserted_rows);
|
|
|
|
// Cleanup the used table
|
|
MYSQL_QUERY(proxysql_admin, "DROP TABLE IF EXISTS reg_test_3690_table");
|
|
|
|
return exit_status();
|
|
}
|