MXS-2572 Add basic smartrouter test
Very simple, creates 10 threads that concurrently starts making simple INSERTs and SELECTs. The purpose is to test that the basic router to router mechanism of smartrouter works.
This commit is contained in:
parent
fa243a9ec4
commit
3424158b7c
@ -991,6 +991,9 @@ add_test_executable(mxs2563_concurrent_slave_failure.cpp mxs2563_concurrent_slav
|
||||
# MXS-2521: COM_STMT_EXECUTE maybe return empty result
|
||||
add_test_executable(mxs2521_double_exec.cpp mxs2521_double_exec mxs2521_double_exec LABELS REPL_BACKEND readwritesplit)
|
||||
|
||||
# MXS-2572: Add smartrouter tests.
|
||||
add_test_executable(sr_basics.cpp sr_basics sr_basics LABELS REPL_BACKEND)
|
||||
|
||||
############################################
|
||||
# BEGIN: binlogrouter and avrorouter tests #
|
||||
############################################
|
||||
|
87
maxscale-system-test/cnf/maxscale.cnf.template.sr_basics
Normal file
87
maxscale-system-test/cnf/maxscale.cnf.template.sr_basics
Normal file
@ -0,0 +1,87 @@
|
||||
[maxscale]
|
||||
threads=###threads###
|
||||
log_warning=1
|
||||
|
||||
[server1]
|
||||
type=server
|
||||
address=###node_server_IP_1###
|
||||
port=###node_server_port_1###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server2]
|
||||
type=server
|
||||
address=###node_server_IP_2###
|
||||
port=###node_server_port_2###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server3]
|
||||
type=server
|
||||
address=###node_server_IP_3###
|
||||
port=###node_server_port_3###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server4]
|
||||
type=server
|
||||
address=###node_server_IP_4###
|
||||
port=###node_server_port_4###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[The-Monitor]
|
||||
type=monitor
|
||||
module=mysqlmon
|
||||
servers=server1, server2, server3, server4
|
||||
user=maxskysql
|
||||
password=skysql
|
||||
monitor_interval=1000
|
||||
|
||||
[RWS1]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1, server2, server3, server4
|
||||
user=maxskysql
|
||||
password=skysql
|
||||
slave_selection_criteria=LEAST_ROUTER_CONNECTIONS
|
||||
|
||||
[RWS1-Listener]
|
||||
type=listener
|
||||
service=RWS1
|
||||
protocol=mariadbclient
|
||||
socket=/tmp/rws1.sock
|
||||
|
||||
[RWS1-As-Server]
|
||||
type=server
|
||||
protocol=mariadbbackend
|
||||
socket=/tmp/rws1.sock
|
||||
|
||||
[RWS2]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1, server2, server3, server4
|
||||
user=maxskysql
|
||||
password=skysql
|
||||
slave_selection_criteria=LEAST_ROUTER_CONNECTIONS
|
||||
|
||||
[RWS2-Listener]
|
||||
type=listener
|
||||
service=RWS2
|
||||
protocol=MySQLClient
|
||||
socket=/tmp/rws2.sock
|
||||
|
||||
[RWS2-As-Server]
|
||||
type=server
|
||||
protocol=mariadbbackend
|
||||
socket=/tmp/rws2.sock
|
||||
|
||||
[SQ]
|
||||
type=service
|
||||
router=smartrouter
|
||||
servers=RWS1-As-Server, RWS2-As-Server
|
||||
master=RWS1-As-Server
|
||||
user=maxskysql
|
||||
password=skysql
|
||||
|
||||
[SQ-Listener]
|
||||
type=listener
|
||||
service=SQ
|
||||
protocol=mariadbclient
|
||||
port=4006
|
@ -321,6 +321,11 @@ public:
|
||||
return get_row(m_conn, q);
|
||||
}
|
||||
|
||||
Result rows(const std::string& q) const
|
||||
{
|
||||
return get_result(m_conn, q);
|
||||
}
|
||||
|
||||
std::string field(std::string q, int idx = 0)
|
||||
{
|
||||
Row r = get_row(m_conn, q);
|
||||
|
147
maxscale-system-test/sr_basics.cpp
Normal file
147
maxscale-system-test/sr_basics.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||
*
|
||||
* Change Date: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <maxbase/assert.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void init(TestConnections& test, Connection& c)
|
||||
{
|
||||
test.expect(c.query("DROP TABLE IF EXISTS sq"), "Could not drop table.");
|
||||
test.expect(c.query("CREATE TABLE sq (id INT, value INT)"), "Could not create table.");
|
||||
sleep(2);
|
||||
}
|
||||
|
||||
void finish(TestConnections& test, Connection& c)
|
||||
{
|
||||
test.expect(c.query("DROP TABLE IF EXISTS sq"), "Could not drop table.");
|
||||
}
|
||||
|
||||
const size_t N_THREADS = 10;
|
||||
const size_t N_INSERTS = 100;
|
||||
const size_t N_SELECTS = 10;
|
||||
|
||||
void thread_stress(TestConnections* pTest, int id)
|
||||
{
|
||||
string greeting("Hello from thread ");
|
||||
greeting += std::to_string(id);
|
||||
greeting += "\n";
|
||||
|
||||
cout << greeting << flush;
|
||||
|
||||
Connection c = pTest->maxscales->rwsplit();
|
||||
|
||||
c.connect();
|
||||
|
||||
string preamble("INSERT INTO sq VALUES (");
|
||||
preamble += std::to_string(id);
|
||||
preamble += ", ";
|
||||
|
||||
for (size_t i = 0; i < N_INSERTS; ++i)
|
||||
{
|
||||
string query = preamble + std::to_string(i) + ")";
|
||||
|
||||
c.query(query);
|
||||
|
||||
for (size_t i = 0; i < N_SELECTS; ++i)
|
||||
{
|
||||
c.query("SELECT * FROM sq");
|
||||
}
|
||||
}
|
||||
|
||||
string goodbye("Goodbye from thread ");
|
||||
goodbye += std::to_string(id);
|
||||
goodbye += "\n";
|
||||
|
||||
cout << goodbye << flush;
|
||||
}
|
||||
|
||||
void test_stress(TestConnections& test)
|
||||
{
|
||||
vector<thread> threads;
|
||||
|
||||
for (size_t i = 0; i < N_THREADS; ++i)
|
||||
{
|
||||
thread t(thread_stress, &test, i);
|
||||
|
||||
threads.emplace_back(std::move(t));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < threads.size(); ++i)
|
||||
{
|
||||
threads[i].join();
|
||||
}
|
||||
|
||||
Connection c = test.maxscales->rwsplit();
|
||||
c.connect();
|
||||
|
||||
Result rows = c.rows("SELECT * FROM sq");
|
||||
test.expect(rows.size() == N_THREADS * N_INSERTS,
|
||||
"Expected %lu inserts in total, but found %lu.", N_THREADS * N_INSERTS, rows.size());
|
||||
|
||||
map<string, vector<string>> found_results;
|
||||
|
||||
for (const auto& row : rows)
|
||||
{
|
||||
mxb_assert(row.size() == 2);
|
||||
|
||||
string tid { row[0] };
|
||||
string f { row[1] };
|
||||
|
||||
found_results[tid].push_back(f);
|
||||
}
|
||||
|
||||
test.expect(found_results.size() == N_THREADS,
|
||||
"Expected results from %lu threads, but found %lu.", N_THREADS, found_results.size());
|
||||
|
||||
for (const auto& kv : found_results)
|
||||
{
|
||||
const string& tid { kv.first };
|
||||
const vector<string>& fields { kv.second };
|
||||
|
||||
test.expect(fields.size() == N_INSERTS,
|
||||
"Expected %lu inserts for thread %s, but found only %lu.",
|
||||
N_INSERTS, tid.c_str(), fields.size());
|
||||
}
|
||||
}
|
||||
|
||||
void run_tests(TestConnections& test)
|
||||
{
|
||||
test_stress(test);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
TestConnections test(argc, argv);
|
||||
|
||||
Connection c = test.maxscales->rwsplit();
|
||||
|
||||
test.expect(c.connect(), "Could not connect to MaxScale.");
|
||||
|
||||
init(test, c);
|
||||
|
||||
run_tests(test);
|
||||
|
||||
finish(test, c);
|
||||
|
||||
return test.global_result;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user