MaxScale/maxscale-system-test/rwsplit_readonly.cpp
Markus Mäkelä dad8e5da59
Sync slaves after creating tables in rwsplit_readonly
The test should synchronize the replication to avoid replication lag from
breaking the tests.
2018-03-15 23:24:08 +02:00

282 lines
12 KiB
C++

/**
* @file rwsplit_readonly.cpp Test of the read-only mode for readwritesplit when master fails
* - check INSERTs via RWSplit
* - block Master
* - check SELECT and INSERT with -- fail_instantly, -- error_on_write, -- fail_on_write
*/
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <string>
#include "testconnections.h"
#include "maxadmin_operations.h"
void test_all_ok(TestConnections *Test)
{
/** Insert should work */
Test->set_timeout(30);
Test->tprintf("Testing that writes and reads to all services work\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_rwsplit[0],
"INSERT INTO test.readonly VALUES (1) -- fail_instantly"),
"Query to service with 'fail_instantly' should succeed\n");
Test->set_timeout(30);
Test->add_result(execute_query_silent(Test->maxscales->conn_master[0],
"INSERT INTO test.readonly VALUES (1) -- fail_on_write"),
"Query to service with 'fail_on_write' should succeed\n");
Test->set_timeout(30);
Test->add_result(execute_query_silent(Test->maxscales->conn_slave[0],
"INSERT INTO test.readonly VALUES (1) -- error_on_write"),
"Query to service with 'error_on_write' should succeed\n");
Test->set_timeout(30);
Test->add_result(execute_query_silent(Test->maxscales->conn_rwsplit[0],
"SELECT * FROM test.readonly -- fail_instantly"),
"Query to service with 'fail_instantly' should succeed\n");
Test->set_timeout(30);
Test->add_result(execute_query_silent(Test->maxscales->conn_master[0],
"SELECT * FROM test.readonly -- fail_on_write"),
"Query to service with 'fail_on_write' should succeed\n");
Test->set_timeout(30);
Test->add_result(execute_query_silent(Test->maxscales->conn_slave[0],
"SELECT * FROM test.readonly -- error_on_write"),
"Query to service with 'error_on_write' should succeed\n");
}
void test_basic(TestConnections *Test)
{
/** Check that everything is OK before blocking the master */
Test->maxscales->connect_maxscale(0);
test_all_ok(Test);
/** Block master */
Test->stop_timeout();
Test->repl->block_node(0);
sleep(10);
/** Select to service with 'fail_instantly' should close the connection */
Test->set_timeout(30);
Test->tprintf("SELECT to 'fail_instantly'\n");
Test->add_result(!execute_query_silent(Test->maxscales->conn_rwsplit[0],
"SELECT * FROM test.readonly -- fail_instantly"),
"SELECT to service with 'fail_instantly' should fail\n");
/** Other services should still work */
Test->set_timeout(30);
Test->tprintf("SELECT to 'fail_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_master[0],
"SELECT * FROM test.readonly -- fail_on_write"),
"SELECT to service with 'fail_on_write' should succeed\n");
Test->set_timeout(30);
Test->tprintf("SELECT to 'error_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_slave[0],
"SELECT * FROM test.readonly -- error_on_write"),
"SELECT to service with 'error_on_write' should succeed\n");
/** Insert to 'fail_on_write' should fail and close the connection */
Test->set_timeout(30);
Test->tprintf("INSERT to 'fail_on_write'\n");
Test->add_result(!execute_query_silent(Test->maxscales->conn_master[0],
"INSERT INTO test.readonly VALUES (1) -- fail_on_write"),
"INSERT to service with 'fail_on_write' should succeed\n");
Test->set_timeout(30);
Test->tprintf("SELECT to 'fail_on_write'\n");
Test->add_result(!execute_query_silent(Test->maxscales->conn_master[0],
"SELECT * FROM test.readonly -- fail_on_write"),
"SELECT to service with 'fail_on_write' should fail after an INSERT\n");
/** Insert to 'error_on_write' should fail but subsequent SELECTs should work */
Test->set_timeout(30);
Test->tprintf("INSERT to 'error_on_write'\n");
Test->add_result(!execute_query_silent(Test->maxscales->conn_slave[0],
"INSERT INTO test.readonly VALUES (1) -- error_on_write"),
"INSERT to service with 'error_on_write' should fail\n");
Test->tprintf("SELECT to 'error_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_slave[0],
"SELECT * FROM test.readonly -- error_on_write"),
"SELECT to service with 'fail_on_write' should succeed after an INSERT\n");
/** Close connections and try to create new ones */
Test->set_timeout(30);
Test->maxscales->close_maxscale_connections(0);
Test->tprintf("Opening connections while master is blocked\n");
Test->add_result(Test->maxscales->connect_rwsplit(0) == 0,
"Connection to 'fail_instantly' service should fail\n");
Test->add_result(Test->maxscales->connect_readconn_master(0) != 0,
"Connection to 'fail_on_write' service should succeed\n");
Test->add_result(Test->maxscales->connect_readconn_slave(0) != 0,
"Connection to 'error_on_write' service should succeed\n");
/** The {fail|error}_on_write services should work and allow reads */
Test->set_timeout(30);
Test->tprintf("SELECT to 'fail_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_master[0],
"SELECT * FROM test.readonly -- fail_on_write"),
"SELECT to service with 'fail_on_write' should succeed\n");
Test->set_timeout(30);
Test->tprintf("SELECT to 'error_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_slave[0],
"SELECT * FROM test.readonly -- error_on_write"),
"SELECT to service with 'error_on_write' should succeed\n");
Test->maxscales->close_maxscale_connections(0);
Test->stop_timeout();
Test->repl->unblock_node(0);
sleep(10);
/** Check that everything is OK after unblocking */
Test->maxscales->connect_maxscale(0);
test_all_ok(Test);
Test->maxscales->close_maxscale_connections(0);
}
void test_complex(TestConnections *Test)
{
/** Check that everything works before test */
Test->maxscales->connect_maxscale(0);
test_all_ok(Test);
/** Block master */
Test->stop_timeout();
Test->repl->block_node(0);
sleep(10);
/** Select to service with 'fail_instantly' should close the connection */
Test->set_timeout(30);
Test->tprintf("SELECT to 'fail_instantly'\n");
Test->add_result(!execute_query_silent(Test->maxscales->conn_rwsplit[0],
"SELECT * FROM test.readonly -- fail_instantly"),
"SELECT to service with 'fail_instantly' should fail\n");
/** The {fail|error}_on_write services should allow reads */
Test->set_timeout(30);
Test->tprintf("SELECT to 'fail_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_master[0],
"SELECT * FROM test.readonly -- fail_on_write"),
"SELECT to service with 'fail_on_write' should succeed\n");
Test->set_timeout(30);
Test->tprintf("SELECT to 'error_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_slave[0],
"SELECT * FROM test.readonly -- error_on_write"),
"SELECT to service with 'error_on_write' should succeed\n");
/** Unblock node and try to read */
Test->stop_timeout();
Test->repl->unblock_node(0);
sleep(10);
Test->set_timeout(30);
Test->tprintf("SELECT to 'fail_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_master[0],
"SELECT * FROM test.readonly -- fail_on_write"),
"SELECT to service with 'fail_on_write' should succeed\n");
Test->set_timeout(30);
Test->tprintf("SELECT to 'error_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_slave[0],
"SELECT * FROM test.readonly -- error_on_write"),
"SELECT to service with 'error_on_write' should succeed\n");
/** Block slaves */
Test->stop_timeout();
Test->maxscales->close_maxscale_connections(0);
Test->repl->block_node(1);
Test->repl->block_node(2);
Test->repl->block_node(3);
sleep(20);
/** Reconnect to MaxScale */
Test->set_timeout(30);
Test->maxscales->connect_maxscale(0);
Test->set_timeout(30);
Test->tprintf("SELECT to 'fail_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_master[0],
"SELECT * FROM test.readonly -- fail_on_write"),
"SELECT to service with 'fail_on_write' should succeed\n");
Test->set_timeout(30);
Test->tprintf("SELECT to 'error_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_slave[0],
"SELECT * FROM test.readonly -- error_on_write"),
"SELECT to service with 'error_on_write' should succeed\n");
Test->stop_timeout();
Test->repl->unblock_node(1);
Test->repl->unblock_node(2);
Test->repl->unblock_node(3);
sleep(10);
Test->set_timeout(30);
Test->tprintf("SELECT to 'fail_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_master[0],
"SELECT * FROM test.readonly -- fail_on_write"),
"SELECT to service with 'fail_on_write' should succeed\n");
Test->set_timeout(30);
Test->tprintf("SELECT to 'error_on_write'\n");
Test->add_result(execute_query_silent(Test->maxscales->conn_slave[0],
"SELECT * FROM test.readonly -- error_on_write"),
"SELECT to service with 'error_on_write' should succeed\n");
/** Block all nodes */
Test->stop_timeout();
Test->repl->block_node(0);
Test->repl->block_node(1);
Test->repl->block_node(2);
Test->repl->block_node(3);
sleep(10);
/** SELECTs should fail*/
Test->set_timeout(30);
Test->tprintf("SELECT to 'fail_on_write'\n");
Test->add_result(!execute_query_silent(Test->maxscales->conn_master[0],
"SELECT * FROM test.readonly -- fail_on_write"),
"SELECT to service with 'fail_on_write' should fail\n");
Test->set_timeout(30);
Test->tprintf("SELECT to 'error_on_write'\n");
Test->add_result(!execute_query_silent(Test->maxscales->conn_slave[0],
"SELECT * FROM test.readonly -- error_on_write"),
"SELECT to service with 'error_on_write' should fail\n");
Test->stop_timeout();
Test->repl->unblock_node(0);
Test->repl->unblock_node(1);
Test->repl->unblock_node(2);
Test->repl->unblock_node(3);
sleep(10);
/** Reconnect and check that everything works after the test */
Test->maxscales->close_maxscale_connections(0);
Test->maxscales->connect_maxscale(0);
test_all_ok(Test);
Test->maxscales->close_maxscale_connections(0);
}
int main(int argc, char *argv[])
{
TestConnections *Test = new TestConnections(argc, argv);
/** Prepare for tests */
Test->stop_timeout();
Test->maxscales->connect_maxscale(0);
execute_query_silent(Test->maxscales->conn_rwsplit[0], "DROP TABLE IF EXISTS test.readonly");
execute_query_silent(Test->maxscales->conn_rwsplit[0], "CREATE TABLE test.readonly(id int)");
Test->maxscales->close_maxscale_connections(0);
Test->repl->connect();
Test->repl->sync_slaves();
Test->repl->disconnect();
/** Basic tests */
test_basic(Test);
/** More complex tests */
test_complex(Test);
/** Clean up test environment */
Test->repl->flush_hosts();
int rval = Test->global_result;
delete Test;
return rval;
}