MXS-1507: Add basic functional test
Added functional tests that cover the basic cases.
This commit is contained in:
@ -613,6 +613,10 @@ add_test_executable(mxs1506_delayed_retry.cpp mxs1506_delayed_retry mxs1506_dela
|
|||||||
# https://jira.mariadb.org/browse/MXS-1506
|
# https://jira.mariadb.org/browse/MXS-1506
|
||||||
add_test_executable(mxs1506_no_master.cpp mxs1506_no_master mxs1506_delayed_retry LABELS readwritesplit REPL_BACKEND)
|
add_test_executable(mxs1506_no_master.cpp mxs1506_no_master mxs1506_delayed_retry LABELS readwritesplit REPL_BACKEND)
|
||||||
|
|
||||||
|
# MXS-1507: Transaction replay
|
||||||
|
# https://jira.mariadb.org/browse/MXS-1507
|
||||||
|
add_test_executable(mxs1507_trx_replay.cpp mxs1507_trx_replay mxs1507_trx_replay LABELS readwritesplit REPL_BACKEND)
|
||||||
|
|
||||||
# MXS-1509: Show correct server state for multisource replication
|
# MXS-1509: Show correct server state for multisource replication
|
||||||
# https://jira.mariadb.org/browse/MXS-1509
|
# https://jira.mariadb.org/browse/MXS-1509
|
||||||
add_test_executable(mxs1509.cpp mxs1509 mxs1509 LABELS mysqlmon REPL_BACKEND)
|
add_test_executable(mxs1509.cpp mxs1509 mxs1509 LABELS mysqlmon REPL_BACKEND)
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
[maxscale]
|
||||||
|
threads=###threads###
|
||||||
|
log_info=1
|
||||||
|
|
||||||
|
[MySQL Monitor]
|
||||||
|
type=monitor
|
||||||
|
module=mysqlmon
|
||||||
|
###repl51###
|
||||||
|
servers=server1,server2,server3,server4
|
||||||
|
user=maxskysql
|
||||||
|
passwd=skysql
|
||||||
|
monitor_interval=1000
|
||||||
|
|
||||||
|
[RW Split Router]
|
||||||
|
type=service
|
||||||
|
router=readwritesplit
|
||||||
|
servers=server1,server2,server3,server4
|
||||||
|
user=maxskysql
|
||||||
|
passwd=skysql
|
||||||
|
transaction_replay=true
|
||||||
|
|
||||||
|
[RW Split Listener]
|
||||||
|
type=listener
|
||||||
|
service=RW Split Router
|
||||||
|
protocol=MySQLClient
|
||||||
|
port=4006
|
||||||
|
|
||||||
|
[CLI]
|
||||||
|
type=service
|
||||||
|
router=cli
|
||||||
|
|
||||||
|
[CLI Listener]
|
||||||
|
type=listener
|
||||||
|
service=CLI
|
||||||
|
protocol=maxscaled
|
||||||
|
socket=default
|
||||||
|
|
||||||
|
[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
|
188
maxscale-system-test/mxs1507_trx_replay.cpp
Normal file
188
maxscale-system-test/mxs1507_trx_replay.cpp
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
/**
|
||||||
|
* MXS-1507: Transaction replay tests
|
||||||
|
*
|
||||||
|
* https://jira.mariadb.org/browse/MXS-1507
|
||||||
|
*/
|
||||||
|
#include "testconnections.h"
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
TestConnections test(argc, argv);
|
||||||
|
|
||||||
|
auto query = [&](string q)
|
||||||
|
{
|
||||||
|
return execute_query_silent(test.maxscales->conn_rwsplit[0], q.c_str()) == 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto ok = [&](string q)
|
||||||
|
{
|
||||||
|
test.assert(query(q), "Query '%s' should work: %s", q.c_str(), mysql_error(test.maxscales->conn_rwsplit[0]));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto err = [&](string q)
|
||||||
|
{
|
||||||
|
test.assert(!query(q), "Query should not work: %s", q.c_str());
|
||||||
|
};
|
||||||
|
|
||||||
|
auto check = [&](string q)
|
||||||
|
{
|
||||||
|
Row row = get_row(test.maxscales->conn_rwsplit[0], q.c_str());
|
||||||
|
test.assert(!row.empty() && row[0] == "1", "Query should return 1: %s", q.c_str());
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TrxTest
|
||||||
|
{
|
||||||
|
string description;
|
||||||
|
vector<function<void ()>> pre;
|
||||||
|
vector<function<void ()>> post;
|
||||||
|
vector<function<void ()>> check;
|
||||||
|
}
|
||||||
|
tests[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"Basic transaction",
|
||||||
|
{
|
||||||
|
bind(ok, "BEGIN"),
|
||||||
|
bind(ok, "SELECT 1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bind(ok, "SELECT 2"),
|
||||||
|
bind(ok, "COMMIT"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Transaction with a write",
|
||||||
|
{
|
||||||
|
bind(ok, "BEGIN"),
|
||||||
|
bind(ok, "INSERT INTO test.t1 VALUES (1)"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bind(ok, "INSERT INTO test.t1 VALUES (2)"),
|
||||||
|
bind(ok, "COMMIT"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bind(check, "SELECT COUNT(*) = 2 FROM test.t1 WHERE id IN (1, 2)"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Read-only transaction",
|
||||||
|
{
|
||||||
|
bind(ok, "START TRANSACTION READ ONLY"),
|
||||||
|
bind(ok, "SELECT 1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bind(ok, "SELECT 2"),
|
||||||
|
bind(ok, "COMMIT"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Trx started, no queries",
|
||||||
|
{
|
||||||
|
bind(ok, "BEGIN"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bind(ok, "SELECT 1"),
|
||||||
|
bind(ok, "COMMIT"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Trx waiting on commit",
|
||||||
|
{
|
||||||
|
bind(ok, "BEGIN"),
|
||||||
|
bind(ok, "SELECT 1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bind(ok, "COMMIT"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Trx with NOW()",
|
||||||
|
{
|
||||||
|
bind(ok, "BEGIN"),
|
||||||
|
bind(ok, "SELECT NOW(), SLEEP(1)"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bind(err, "SELECT 1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Commit trx with NOW()",
|
||||||
|
{
|
||||||
|
bind(ok, "BEGIN"),
|
||||||
|
bind(ok, "SELECT NOW(), SLEEP(1)"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bind(err, "COMMIT"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"NOW() used after replay",
|
||||||
|
{
|
||||||
|
bind(ok, "BEGIN"),
|
||||||
|
bind(ok, "SELECT 1"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bind(ok, "SELECT NOW()"),
|
||||||
|
bind(ok, "COMMIT"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a table for testing
|
||||||
|
test.maxscales->connect();
|
||||||
|
test.try_query(test.maxscales->conn_rwsplit[0], "CREATE OR REPLACE TABLE test.t1(id INT)");
|
||||||
|
test.maxscales->disconnect();
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
for (auto& a : tests)
|
||||||
|
{
|
||||||
|
cout << i++ << ": " << a.description << endl;
|
||||||
|
|
||||||
|
test.maxscales->connect();
|
||||||
|
for (auto& f : a.pre)
|
||||||
|
{
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block and unblock the master
|
||||||
|
test.repl->block_node(0);
|
||||||
|
sleep(8);
|
||||||
|
test.repl->unblock_node(0);
|
||||||
|
sleep(8);
|
||||||
|
|
||||||
|
for (auto& f : a.post)
|
||||||
|
{
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
test.maxscales->disconnect();
|
||||||
|
|
||||||
|
test.repl->connect();
|
||||||
|
test.repl->sync_slaves();
|
||||||
|
test.repl->disconnect();
|
||||||
|
|
||||||
|
test.maxscales->connect();
|
||||||
|
for (auto& f : a.check)
|
||||||
|
{
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
test.maxscales->disconnect();
|
||||||
|
|
||||||
|
// Clear the table at the end of the test
|
||||||
|
test.maxscales->connect();
|
||||||
|
test.try_query(test.maxscales->conn_rwsplit[0], "TRUNCATE TABLE test.t1");
|
||||||
|
test.maxscales->disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
test.maxscales->connect();
|
||||||
|
test.try_query(test.maxscales->conn_rwsplit[0], "DROP TABLE test.t1");
|
||||||
|
test.maxscales->disconnect();
|
||||||
|
|
||||||
|
return test.global_result;
|
||||||
|
}
|
Reference in New Issue
Block a user