mirror of https://github.com/sysown/proxysql
Added regression test for #3223 major changes for 'RESTAPI'
+ Added generic test for checking script execution through 'RESTAPI'. + Added multiple new scripts fails to be executed through the 'RESTAPI'.pull/3337/head
parent
a4324f4944
commit
ee86afed85
@ -0,0 +1,199 @@
|
||||
/**
|
||||
* @file reg_test_3223-restapi_return_codes-t.cpp
|
||||
* @brief This test ensures that RESTAPI is able to execute scripts returning the proper error
|
||||
* codes in case of success or failure.
|
||||
* @date 2021-03-10
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include <mysql.h>
|
||||
#include <mysql/mysqld_error.h>
|
||||
|
||||
#include "tap.h"
|
||||
#include "command_line.h"
|
||||
#include "utils.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Dummy write function to avoid CURL to write received output to stdout.
|
||||
* @return Returns the size presented.
|
||||
*/
|
||||
size_t my_dummy_write(char*, size_t size, size_t nmemb, void*) {
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform a simple POST query to the specified endpoint using the supplied
|
||||
* 'post_params'.
|
||||
*
|
||||
* @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 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) {
|
||||
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);
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
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_cleanup(curl);
|
||||
}
|
||||
|
||||
return response_code;
|
||||
}
|
||||
|
||||
const std::string base_address { "http://localhost:6070/sync/" };
|
||||
|
||||
std::vector<std::tuple<std::string, std::string, long>> valid_endpoints {
|
||||
std::make_tuple( "large_output_script", "{}", 200 ),
|
||||
std::make_tuple( "partial_output_flush_script", "{}", 200 ),
|
||||
std::make_tuple( "valid_output_script", "{}", 200 ),
|
||||
// check scripts remain operational
|
||||
// NOTE: Disable due to requiring python2 annotation in file
|
||||
// std::make_tuple( "metrics", "{\"user\":\"admin\", \"password\":\"admin\", \"host\":\"127.0.0.1\", \"port\":\"6032\"}", 200 )
|
||||
};
|
||||
|
||||
std::vector<std::tuple<std::string, std::string, long>> invalid_requests {
|
||||
std::make_tuple( "invalid_output_script", "{}", 424 ),
|
||||
std::make_tuple( "timeout_script", "{}", 424 ),
|
||||
std::make_tuple( "invalid_script", "{}", 424 ),
|
||||
std::make_tuple( "non_existing_script", "{}", 400 ),
|
||||
// supplied with invalid params
|
||||
std::make_tuple( "valid_output_script", "", 400 )
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
CommandLine cl;
|
||||
|
||||
if (cl.getEnv()) {
|
||||
diag("Failed to get the required environmental variables.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
plan(valid_endpoints.size() + invalid_requests.size());
|
||||
|
||||
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 -1;
|
||||
}
|
||||
|
||||
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 -1;
|
||||
}
|
||||
|
||||
// Clean current 'restapi_routes' if any
|
||||
MYSQL_QUERY(proxysql_admin, "DELETE FROM restapi_routes");
|
||||
|
||||
// Configure restapi_routes to be used
|
||||
|
||||
// Congigure routes for valid scripts
|
||||
MYSQL_QUERY(
|
||||
proxysql_admin,
|
||||
"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,
|
||||
"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,
|
||||
"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')"
|
||||
);
|
||||
|
||||
// NOTE: Disable due to requiring python2 annotation in file
|
||||
// MYSQL_QUERY(
|
||||
// proxysql_admin,
|
||||
// "INSERT INTO restapi_routes (active, timeout_ms, method, uri, script, comment) "
|
||||
// "VALUES (1,1000,'POST','metrics','../scripts/metrics.py','comm')"
|
||||
// );
|
||||
|
||||
// Congigure routes for invalid scripts
|
||||
MYSQL_QUERY(
|
||||
proxysql_admin,
|
||||
"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,
|
||||
"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,
|
||||
"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')"
|
||||
);
|
||||
|
||||
MYSQL_QUERY(proxysql_admin, "LOAD restapi TO RUNTIME");
|
||||
|
||||
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 { "" };
|
||||
|
||||
// perform the POST operation
|
||||
int post_err = perform_simple_post(full_endpoint, std::get<1>(valid_request_tuple), post_out_err);
|
||||
|
||||
ok(
|
||||
post_err == 200,
|
||||
"Performing a POST over endpoint '%s' should result into a 200 response: (errcode: '%d', curlerr: '%s' )",
|
||||
full_endpoint.c_str(),
|
||||
post_err,
|
||||
post_out_err.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
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 { "" };
|
||||
|
||||
// perform the POST operation
|
||||
int post_err = perform_simple_post(full_endpoint, std::get<1>(invalid_request_tuple), 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' )",
|
||||
full_endpoint.c_str(),
|
||||
post_err,
|
||||
post_out_err.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
return exit_status();
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Simple script that should fail to execute to check RESTAPI result code."""
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("{invalid_json}")
|
||||
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Simple script that should fail to execute to check RESTAPI result code."""
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(non_valid_variable)
|
||||
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Simple script to produce a 1MB output to be processed by the RESTAPI."""
|
||||
|
||||
import json
|
||||
|
||||
random_dic = {}
|
||||
|
||||
##
|
||||
# @brief Return the length of the encoded string, output gives an stimation
|
||||
# of string size in bytes.
|
||||
# @param s The string which size is to be measured.
|
||||
# @return The length of the result of encoding the supplied string in 'utf-8'
|
||||
def utf8len(s):
|
||||
return len(s.encode('utf-8'))
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Return big random JSON
|
||||
for i in range(0, 40000):
|
||||
random_dic["id_" + str(i)] = "0000000000"
|
||||
|
||||
j_random_dic = json.dumps(random_dic)
|
||||
|
||||
# print(utf8len(j_random_dic))
|
||||
print(j_random_dic)
|
||||
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Simple script to produce a 1MB output flushed in two times to be processed by the RESTAPI."""
|
||||
|
||||
import json
|
||||
import time
|
||||
|
||||
random_dic = {}
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Generate 1MB empty JSON
|
||||
for i in range(0, 40000):
|
||||
random_dic["id_" + str(i)] = "0000000000"
|
||||
|
||||
j_random_dic = json.dumps(random_dic)
|
||||
|
||||
# Split the string in half
|
||||
firstpart, secondpart = j_random_dic[:len(j_random_dic)//2], j_random_dic[len(j_random_dic)//2:]
|
||||
|
||||
# Partial flush script
|
||||
print(firstpart, end='', flush=True)
|
||||
time.sleep(1)
|
||||
print(secondpart, end='', flush=True)
|
||||
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Simple script to force a timeout failure in RESTAPI."""
|
||||
|
||||
import time
|
||||
import json
|
||||
|
||||
random_dic = {}
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Forcing the timeout
|
||||
time.sleep(10)
|
||||
|
||||
# Return random JSON
|
||||
for i in range(0, 20):
|
||||
random_dic["id_" + str(i)] = "0000000000"
|
||||
|
||||
j_random_dic = json.dumps(random_dic)
|
||||
|
||||
print(j_random_dic)
|
||||
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Simple script returning a valid empty result for RESTAPI."""
|
||||
|
||||
random_dic = {}
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Return minimal JSON
|
||||
print('{}')
|
||||
Loading…
Reference in new issue