|
|
|
|
@ -17,6 +17,7 @@
|
|
|
|
|
#include <mysql.h>
|
|
|
|
|
#include <mysql/mysqld_error.h>
|
|
|
|
|
|
|
|
|
|
#include "proxysql_utils.h"
|
|
|
|
|
#include "tap.h"
|
|
|
|
|
#include "command_line.h"
|
|
|
|
|
#include "utils.h"
|
|
|
|
|
@ -38,22 +39,25 @@ size_t my_dummy_write(char*, size_t size, size_t nmemb, void*) {
|
|
|
|
|
*
|
|
|
|
|
* @param endpoint The endpoint to be exercised by the POST.
|
|
|
|
|
* @param post_params The post parameters to be supplied to the script.
|
|
|
|
|
* @param curl_out_err A uint64_t reference returning the result code of the
|
|
|
|
|
* query in case it has been performed. In case the query couldn't be
|
|
|
|
|
* performed, this value is never initialized.
|
|
|
|
|
* @param curl_out_err A string reference to collect the error as a string reported
|
|
|
|
|
* by 'libcurl' in case of failure.
|
|
|
|
|
*
|
|
|
|
|
* @return The response code of the query in case of the query.
|
|
|
|
|
*/
|
|
|
|
|
long perform_simple_post(const string& endpoint, const string& post_params, string& curl_out_err) {
|
|
|
|
|
CURLcode perform_simple_post(
|
|
|
|
|
const string& endpoint, const string& post_params, uint64_t& curl_res_code,
|
|
|
|
|
string& curl_out_err
|
|
|
|
|
) {
|
|
|
|
|
CURL *curl;
|
|
|
|
|
CURLcode res;
|
|
|
|
|
long response_code;
|
|
|
|
|
|
|
|
|
|
curl_global_init(CURL_GLOBAL_ALL);
|
|
|
|
|
|
|
|
|
|
curl = curl_easy_init();
|
|
|
|
|
if(curl) {
|
|
|
|
|
diag("endpoint: %s", endpoint.c_str());
|
|
|
|
|
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL, endpoint.c_str());
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_params.c_str());
|
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &my_dummy_write);
|
|
|
|
|
@ -63,13 +67,13 @@ long perform_simple_post(const string& endpoint, const string& post_params, stri
|
|
|
|
|
if(res != CURLE_OK) {
|
|
|
|
|
curl_out_err = std::string { curl_easy_strerror(res) };
|
|
|
|
|
} else {
|
|
|
|
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
|
|
|
|
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &curl_res_code);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response_code;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string base_address { "http://localhost:6070/sync/" };
|
|
|
|
|
@ -92,6 +96,49 @@ std::vector<std::tuple<std::string, std::string, long>> invalid_requests {
|
|
|
|
|
std::make_tuple( "valid_output_script", "", 400 )
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Waits until the provided endpoint is ready to be used or the
|
|
|
|
|
* timeout period expired. For this checks the return code of
|
|
|
|
|
* 'perform_simple_post' which only fails in case the 'CURL' request couldn't
|
|
|
|
|
* be performed, which is interpreted as endpoint not being yet ready.
|
|
|
|
|
*
|
|
|
|
|
* @param endpoint The endpoint to be queried.
|
|
|
|
|
* @param post_params The required params to be supplied for the 'POST' endpoint
|
|
|
|
|
* call.
|
|
|
|
|
* @param timeout The max time to wait before declaring a timeout, and
|
|
|
|
|
* returning '-1'.
|
|
|
|
|
* @param delay The delay specified in 'ms' to be waited between retries.
|
|
|
|
|
*
|
|
|
|
|
* @return '0' in case the endpoint became available before the timeout, or
|
|
|
|
|
* '-1' in case the timeout expired.
|
|
|
|
|
*/
|
|
|
|
|
int wait_until_enpoint_ready(
|
|
|
|
|
std::string endpoint, std::string post_params, uint32_t timeout, uint32_t delay=100
|
|
|
|
|
) {
|
|
|
|
|
double waited = 0;
|
|
|
|
|
int res = -1;
|
|
|
|
|
|
|
|
|
|
while (waited < timeout) {
|
|
|
|
|
std::string curl_str_err {};
|
|
|
|
|
uint64_t curl_res_code = 0;
|
|
|
|
|
int curl_err = perform_simple_post(endpoint, post_params, curl_res_code, curl_str_err);
|
|
|
|
|
|
|
|
|
|
if (curl_err != CURLE_OK) {
|
|
|
|
|
diag(
|
|
|
|
|
"'curl_err_code': %d, 'curl_err': '%s', waiting for '%d'ms...",
|
|
|
|
|
curl_err, curl_str_err.c_str(), delay
|
|
|
|
|
);
|
|
|
|
|
waited += static_cast<double>(delay) / 1000;
|
|
|
|
|
usleep(delay * 1000);
|
|
|
|
|
} else {
|
|
|
|
|
res = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
|
CommandLine cl;
|
|
|
|
|
|
|
|
|
|
@ -125,23 +172,33 @@ int main(int argc, char** argv) {
|
|
|
|
|
MYSQL_QUERY(proxysql_admin, "DELETE FROM restapi_routes");
|
|
|
|
|
|
|
|
|
|
// Configure restapi_routes to be used
|
|
|
|
|
std::string test_script_base_path {
|
|
|
|
|
std::string { cl.workdir } + "reg_test_3223_scripts"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Congigure routes for valid scripts
|
|
|
|
|
MYSQL_QUERY(
|
|
|
|
|
proxysql_admin,
|
|
|
|
|
std::vector<std::string> t_valid_scripts_inserts {
|
|
|
|
|
"INSERT INTO restapi_routes (active, timeout_ms, method, uri, script, comment) "
|
|
|
|
|
"VALUES (1,5000,'POST','large_output_script','../test/tap/tests/reg_test_3223_scripts/large_output_script.py','comm')"
|
|
|
|
|
);
|
|
|
|
|
MYSQL_QUERY(
|
|
|
|
|
proxysql_admin,
|
|
|
|
|
"VALUES (1,5000,'POST','large_output_script','%s/large_output_script.py','comm')",
|
|
|
|
|
"INSERT INTO restapi_routes (active, timeout_ms, method, uri, script, comment) "
|
|
|
|
|
"VALUES (1,5000,'POST','partial_output_flush_script','../test/tap/tests/reg_test_3223_scripts/partial_output_flush_script.py','comm')"
|
|
|
|
|
);
|
|
|
|
|
MYSQL_QUERY(
|
|
|
|
|
proxysql_admin,
|
|
|
|
|
"VALUES (1,5000,'POST','partial_output_flush_script','%s/partial_output_flush_script.py','comm')",
|
|
|
|
|
"INSERT INTO restapi_routes (active, timeout_ms, method, uri, script, comment) "
|
|
|
|
|
"VALUES (1,1000,'POST','valid_output_script','../test/tap/tests/reg_test_3223_scripts/valid_output_script.py','comm')"
|
|
|
|
|
);
|
|
|
|
|
"VALUES (1,1000,'POST','valid_output_script','%s/valid_output_script.py','comm')"
|
|
|
|
|
};
|
|
|
|
|
std::vector<std::string> valid_scripts_inserts {};
|
|
|
|
|
|
|
|
|
|
for (const auto& t_valid_script_insert : t_valid_scripts_inserts) {
|
|
|
|
|
std::string valid_script_insert {};
|
|
|
|
|
string_format(t_valid_script_insert, valid_script_insert, test_script_base_path.c_str());
|
|
|
|
|
valid_scripts_inserts.push_back(valid_script_insert);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Configure routes for valid scripts
|
|
|
|
|
for (const auto& valid_script_insert : valid_scripts_inserts) {
|
|
|
|
|
MYSQL_QUERY(
|
|
|
|
|
proxysql_admin,
|
|
|
|
|
valid_script_insert.c_str()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NOTE: Disable due to requiring python2 annotation in file
|
|
|
|
|
// MYSQL_QUERY(
|
|
|
|
|
@ -150,37 +207,67 @@ int main(int argc, char** argv) {
|
|
|
|
|
// "VALUES (1,1000,'POST','metrics','../scripts/metrics.py','comm')"
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// Congigure routes for invalid scripts
|
|
|
|
|
MYSQL_QUERY(
|
|
|
|
|
proxysql_admin,
|
|
|
|
|
std::vector<std::string> t_invalid_scripts_inserts {
|
|
|
|
|
"INSERT INTO restapi_routes (active, timeout_ms, method, uri, script, comment) "
|
|
|
|
|
"VALUES (1,1000,'POST','invalid_output_script','../test/tap/tests/reg_test_3223_scripts/invalid_output_script.py','comm')"
|
|
|
|
|
);
|
|
|
|
|
MYSQL_QUERY(
|
|
|
|
|
proxysql_admin,
|
|
|
|
|
"VALUES (1,1000,'POST','invalid_output_script','%s/invalid_output_script.py','comm')",
|
|
|
|
|
"INSERT INTO restapi_routes (active, timeout_ms, method, uri, script, comment) "
|
|
|
|
|
"VALUES (1,1000,'POST','timeout_script','../test/tap/tests/reg_test_3223_scripts/timeout_script.py','comm')"
|
|
|
|
|
);
|
|
|
|
|
MYSQL_QUERY(
|
|
|
|
|
proxysql_admin,
|
|
|
|
|
"VALUES (1,1000,'POST','timeout_script','%s/timeout_script.py','comm')",
|
|
|
|
|
"INSERT INTO restapi_routes (active, timeout_ms, method, uri, script, comment) "
|
|
|
|
|
"VALUES (1,1000,'POST','invalid_script','../test/tap/tests/reg_test_3223_scripts/invalid_script.py','comm')"
|
|
|
|
|
);
|
|
|
|
|
"VALUES (1,1000,'POST','invalid_script','%s/invalid_script.py','comm')"
|
|
|
|
|
};
|
|
|
|
|
std::vector<std::string> invalid_scripts_inserts {};
|
|
|
|
|
|
|
|
|
|
for (const auto& t_invalid_script_insert : t_invalid_scripts_inserts) {
|
|
|
|
|
std::string invalid_script_insert {};
|
|
|
|
|
string_format(t_invalid_script_insert, invalid_script_insert, test_script_base_path.c_str());
|
|
|
|
|
invalid_scripts_inserts.push_back(invalid_script_insert);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Configure routes for invalid scripts
|
|
|
|
|
for (const auto& invalid_script_insert : invalid_scripts_inserts) {
|
|
|
|
|
MYSQL_QUERY(
|
|
|
|
|
proxysql_admin,
|
|
|
|
|
invalid_script_insert.c_str()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MYSQL_QUERY(proxysql_admin, "LOAD restapi TO RUNTIME");
|
|
|
|
|
|
|
|
|
|
// Sensible wait until the new configured enpoints are ready.
|
|
|
|
|
// Use the first enpoint for the check
|
|
|
|
|
const auto& first_request_tuple { valid_endpoints.front() };
|
|
|
|
|
const std::string full_endpoint {
|
|
|
|
|
base_address + std::get<0>(first_request_tuple) + "/"
|
|
|
|
|
};
|
|
|
|
|
int endpoint_timeout = wait_until_enpoint_ready(
|
|
|
|
|
full_endpoint, std::get<1>(first_request_tuple), 10, 500
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (endpoint_timeout) {
|
|
|
|
|
diag(
|
|
|
|
|
"Timeout while trying to reach first valid enpoint."
|
|
|
|
|
" Test failed, skipping endpoint testing..."
|
|
|
|
|
);
|
|
|
|
|
goto skip_endpoints_testing;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto& valid_request_tuple : valid_endpoints) {
|
|
|
|
|
const std::string full_endpoint { base_address + std::get<0>(valid_request_tuple) + "/"};
|
|
|
|
|
std::string post_out_err { "" };
|
|
|
|
|
uint64_t curl_res_code = 0;
|
|
|
|
|
|
|
|
|
|
// perform the POST operation
|
|
|
|
|
int post_err = perform_simple_post(full_endpoint, std::get<1>(valid_request_tuple), post_out_err);
|
|
|
|
|
CURLcode post_err = perform_simple_post(
|
|
|
|
|
full_endpoint, std::get<1>(valid_request_tuple), curl_res_code, post_out_err
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
ok(
|
|
|
|
|
post_err == 200,
|
|
|
|
|
"Performing a POST over endpoint '%s' should result into a 200 response: (errcode: '%d', curlerr: '%s' )",
|
|
|
|
|
post_err == CURLE_OK && curl_res_code == 200,
|
|
|
|
|
"Performing a POST over endpoint '%s' should result into a 200 response:"
|
|
|
|
|
" (curl_err: '%d', response_errcode: '%ld', curlerr: '%s')",
|
|
|
|
|
full_endpoint.c_str(),
|
|
|
|
|
post_err,
|
|
|
|
|
curl_res_code,
|
|
|
|
|
post_out_err.c_str()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
@ -188,18 +275,24 @@ int main(int argc, char** argv) {
|
|
|
|
|
for (const auto& invalid_request_tuple : invalid_requests) {
|
|
|
|
|
const std::string full_endpoint { base_address + std::get<0>(invalid_request_tuple) + "/" };
|
|
|
|
|
std::string post_out_err { "" };
|
|
|
|
|
uint64_t curl_res_code = 0;
|
|
|
|
|
|
|
|
|
|
// perform the POST operation
|
|
|
|
|
int post_err = perform_simple_post(full_endpoint, std::get<1>(invalid_request_tuple), post_out_err);
|
|
|
|
|
CURLcode post_err = perform_simple_post(
|
|
|
|
|
full_endpoint, std::get<1>(invalid_request_tuple), curl_res_code, post_out_err);
|
|
|
|
|
|
|
|
|
|
ok(
|
|
|
|
|
post_err == std::get<2>(invalid_request_tuple),
|
|
|
|
|
"Performing a POST over endpoint '%s' shouldn't result into a 200 response: (errcode: '%d', curlerr: '%s' )",
|
|
|
|
|
post_err == CURLE_OK && curl_res_code == std::get<2>(invalid_request_tuple),
|
|
|
|
|
"Performing a POST over endpoint '%s' shouldn't result into a 200 response:"
|
|
|
|
|
" (curl_err: '%d', response_errcode: '%ld', curlerr: '%s')",
|
|
|
|
|
full_endpoint.c_str(),
|
|
|
|
|
post_err,
|
|
|
|
|
curl_res_code,
|
|
|
|
|
post_out_err.c_str()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
skip_endpoints_testing:
|
|
|
|
|
|
|
|
|
|
return exit_status();
|
|
|
|
|
}
|
|
|
|
|
|