MaxScale/maxscale-system-test/sanity_check.cpp
Markus Mäkelä ee069ac45c
MXS-2131: Add sanity check test
The sanity check replaces several old regression tests and provides a
quick test for checking mainly the readwritesplit routing behavior. It
also checks some of the connection counts and runs queries that once
caused a crash.

The set of tests that the sanity check obsoletes is:

    bug422
    bug469
    bug448
    bug507
    bug509
    bug634
    bug694
    bug669
    bug711
    mxs127
    mxs47
    mxs682_cyrillic
    mxs957
    mxs1786_statistics
    rwsplit_read_only_trx
2018-11-01 11:45:49 +02:00

132 lines
4.4 KiB
C++

/**
* Sanity check for basic functionality
*
* Combines several old regression tests into one quick test.
*/
#include "testconnections.h"
void test_rwsplit(TestConnections& test)
{
test.set_timeout(300);
test.repl->connect();
std::string master_id = test.repl->get_server_id_str(0);
test.repl->disconnect();
auto c = test.maxscales->rwsplit();
test.expect(c.connect(), "Connection to readwritesplit should succeed");
// Transactions to master
c.query("START TRANSACTION");
test.expect(c.field("SELECT @@server_id") == master_id,
"START TRANSACTION should go to the master");
c.query("COMMIT");
// Read-only transactions to slave
c.query("START TRANSACTION READ ONLY");
test.expect(c.field("SELECT @@server_id") != master_id,
"START TRANSACTION READ ONLY should go to a slave");
c.query("COMMIT");
// @@last_insert_id routed to master
test.expect(c.field("SELECT @@server_id, @@last_insert_id") == master_id,
"@@last_insert_id should go to the master");
test.expect(c.field("SELECT last_insert_id(), @@server_id", 1) == master_id,
"@@last_insert_id should go to the master");
// Replication related queries
test.expect(!c.row("SHOW SLAVE STATUS").empty(),
"SHOW SLAVE STATUS should go to a slave");
// User variable modification in SELECT
test.expect(!c.query("SELECT @a:=@a+1 as a, user FROM mysql"),
"Query with variable modification should fail");
// Repeated session commands
for (int i = 0; i < 10000; i++)
{
test.expect(c.query("set @test=" + std::to_string(i)), "SET should work: %s", c.error());
}
// Large result sets
for (int i = 1; i < 5000; i += 7)
{
c.query("SELECT REPEAT('a'," + std::to_string(i) + ")");
}
// Non ASCII characters
c.query("CREATE OR REPLACE TABLE test.t1 AS SELECT 'Кот'");
c.query("BEGIN");
c.check("SELECT * FROM test.t1", "Кот");
c.query("COMMIT");
c.query("DROP TABLE test.t1");
// Temporary tables
for (auto a : {
"USE test",
"CREATE OR REPLACE TABLE t1(`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY)",
"CREATE OR REPLACE TABLE t2(`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY)",
"CREATE TEMPORARY TABLE temp1(`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY)",
"INSERT INTO temp1 values (1), (2), (3)",
"INSERT INTO t1 values (1), (2), (3)",
"INSERT INTO t2 values (1), (2), (3)",
"CREATE TEMPORARY TABLE temp2 SELECT DISTINCT p.id FROM temp1 p JOIN t1 t "
" ON (t.id = p.id) LEFT JOIN t2 ON (t.id = t2.id) WHERE p.id IS NOT NULL "
" AND @@server_id IS NOT NULL",
"SELECT * FROM temp2",
"DROP TABLE t1",
"DROP TABLE t2"
})
{
test.expect(c.query(a), "Temp table query failed");
}
// Temporary and real table overlap
c.query("CREATE OR REPLACE TABLE test.t1 AS SELECT 1 AS id");
c.query("CREATE TEMPORARY TABLE test.t1 AS SELECT 2 AS id");
c.check("SELECT id FROM test.t1", "2");
c.query("DROP TABLE test.t1");
c.query("DROP TABLE test.t1");
// COM_STATISTICS
test.maxscales->connect();
for (int i = 0; i < 10; i++)
{
mysql_stat(test.maxscales->conn_rwsplit[0]);
test.try_query(test.maxscales->conn_rwsplit[0], "SELECT 1");
}
test.maxscales->disconnect();
}
int main(int argc, char** argv)
{
TestConnections test(argc, argv);
auto connections = [&]() {
return test.maxctrl("api get servers/server1 data.attributes.statistics.connections").second;
};
test.expect(connections()[0] == '0', "The master should have no connections");
test.maxscales->connect();
test.expect(connections()[0] == '2', "The master should have two connections");
test.maxscales->disconnect();
test.expect(connections()[0] == '0', "The master should have no connections");
test.maxscales->connect();
for (auto a : {"show status", "show variables", "show global status"})
{
for (int i = 0; i < 10; i++)
{
test.try_query(test.maxscales->conn_rwsplit[0], "%s", a);
test.try_query(test.maxscales->conn_master[0], "%s", a);
}
}
test.maxscales->disconnect();
// Readwritesplit sanity checks
test_rwsplit(test);
return test.global_result;
}