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:
Johan Wikman 2019-06-26 09:46:05 +03:00
parent fa243a9ec4
commit 3424158b7c
4 changed files with 242 additions and 0 deletions

View File

@ -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 #
############################################

View 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

View File

@ -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);

View 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;
}