Merge branch '2.3' into develop
This commit is contained in:
@ -28,6 +28,50 @@ void init(TestConnections& test)
|
||||
test.try_query(pMysql, "INSERT INTO masking_auto_firewall VALUES ('hello', 'world')");
|
||||
}
|
||||
|
||||
enum class Expect
|
||||
{
|
||||
FAILURE,
|
||||
SUCCESS
|
||||
};
|
||||
|
||||
void test_one(TestConnections& test, const char* zQuery, Expect expect)
|
||||
{
|
||||
MYSQL* pMysql = test.maxscales->conn_rwsplit[0];
|
||||
|
||||
const char* zExpect = (expect == Expect::SUCCESS ? "SHOULD" : "should NOT");
|
||||
|
||||
test.tprintf("Executing '%s', %s succeed.", zQuery, zExpect);
|
||||
int rv = execute_query_silent(pMysql, zQuery);
|
||||
|
||||
if (expect == Expect::SUCCESS)
|
||||
{
|
||||
test.add_result(rv, "Could NOT execute query '%s'.", zQuery);
|
||||
}
|
||||
else
|
||||
{
|
||||
test.add_result(rv == 0, "COULD execute query '%s'.", zQuery);
|
||||
}
|
||||
}
|
||||
|
||||
void test_one_ps(TestConnections& test, const char* zQuery, Expect expect)
|
||||
{
|
||||
MYSQL* pMysql = test.maxscales->conn_rwsplit[0];
|
||||
|
||||
MYSQL_STMT* pPs = mysql_stmt_init(pMysql);
|
||||
int rv = mysql_stmt_prepare(pPs, zQuery, strlen(zQuery));
|
||||
|
||||
if (expect == Expect::SUCCESS)
|
||||
{
|
||||
test.add_result(rv, "Could NOT prepare statement.");
|
||||
}
|
||||
else
|
||||
{
|
||||
test.add_result(rv == 0, "COULD prepare statement.");
|
||||
}
|
||||
|
||||
mysql_stmt_close(pPs);
|
||||
}
|
||||
|
||||
void run(TestConnections& test)
|
||||
{
|
||||
init(test);
|
||||
@ -36,18 +80,38 @@ void run(TestConnections& test)
|
||||
|
||||
int rv;
|
||||
|
||||
// This should go through, a is simply masked.
|
||||
static const char* zMasked_query = "SELECT a, b FROM masking_auto_firewall";
|
||||
test.tprintf("Executing '%s', SHOULD succeed.", zMasked_query);
|
||||
rv = execute_query(pMysql, "%s", zMasked_query);
|
||||
test.add_result(rv, "Could NOT execute query '%s'.", zMasked_query);
|
||||
// This SHOULD go through, a is simply masked.
|
||||
test_one(test, "SELECT a, b FROM masking_auto_firewall", Expect::SUCCESS);
|
||||
|
||||
// This should NOT go through as a function is used with a masked column.
|
||||
static const char* zRejected_query = "SELECT LENGTH(a), b FROM masking_auto_firewall";
|
||||
test.tprintf("Executing '%s', should NOT succeed.", zRejected_query);
|
||||
rv = execute_query_silent(pMysql, zRejected_query);
|
||||
test.add_result(rv == 0, "COULD execute query '%s'.", zRejected_query);
|
||||
test_one(test, "SELECT LENGTH(a), b FROM masking_auto_firewall", Expect::FAILURE);
|
||||
|
||||
// This SHOULD go through as a function is NOT used with a masked column
|
||||
// in a prepared statement.
|
||||
test_one(test, "PREPARE ps1 FROM 'SELECT a, LENGTH(b) FROM masking_auto_firewall'", Expect::SUCCESS);
|
||||
|
||||
// This should NOT go through as a function is used with a masked column
|
||||
// in a prepared statement.
|
||||
test_one(test, "PREPARE ps2 FROM 'SELECT LENGTH(a), b FROM masking_auto_firewall'", Expect::FAILURE);
|
||||
|
||||
rv = execute_query_silent(pMysql, "set @a = 'SELECT LENGTH(a), b FROM masking_auto_firewall'");
|
||||
test.add_result(rv, "Could NOT set variable.");
|
||||
// This should NOT go through as a prepared statement is prepared from a variable.
|
||||
test_one(test, "PREPARE ps3 FROM @a", Expect::FAILURE);
|
||||
|
||||
// This SHOULD succeed as a function is NOT used with a masked column
|
||||
// in a binary prepared statement.
|
||||
test_one_ps(test, "SELECT a, LENGTH(b) FROM masking_auto_firewall", Expect::SUCCESS);
|
||||
|
||||
// This should NOT succeed as a function is used with a masked column
|
||||
// in a binary prepared statement.
|
||||
test_one_ps(test, "SELECT LENGTH(a), b FROM masking_auto_firewall", Expect::FAILURE);
|
||||
|
||||
// This should NOT succeed as a masked column is used in a statement
|
||||
// defining a variable.
|
||||
test_one(test, "set @a = (SELECT a, b FROM masking_auto_firewall)", Expect::FAILURE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
|
||||
@ -22,6 +22,12 @@ const char EVENT_SHCEDULER[] = "SET GLOBAL event_scheduler = %s;";
|
||||
const char USE_TEST[] = "USE test;";
|
||||
const char DELETE_EVENT[] = "DROP EVENT %s;";
|
||||
|
||||
const char EV_STATE_ENABLED[] = "ENABLED";
|
||||
const char EV_STATE_DISABLED[] = "DISABLED";
|
||||
const char EV_STATE_SLAVE_DISABLED[] = "SLAVESIDE_DISABLED";
|
||||
|
||||
const char WRONG_MASTER_FMT[] = "%s is not master as expected. Current master id: %i.";
|
||||
|
||||
int read_incremented_field(TestConnections& test)
|
||||
{
|
||||
int rval = -1;
|
||||
@ -137,12 +143,57 @@ bool check_event_status(TestConnections& test, int node,
|
||||
else
|
||||
{
|
||||
rval = true;
|
||||
cout << "Event '" << event_name << "' is '" << status << "' as it should.\n";
|
||||
cout << "Event '" << event_name << "' is '" << status << "' on node " << node <<
|
||||
" as it should.\n";
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
void set_event_state(TestConnections& test, const string& event_name, const string& new_state)
|
||||
{
|
||||
bool success = false;
|
||||
test.maxscales->connect_maxscale(0);
|
||||
MYSQL* conn = test.maxscales->conn_rwsplit[0];
|
||||
const char query_fmt[] = "ALTER EVENT %s %s;";
|
||||
|
||||
if ((test.try_query(conn, USE_TEST) == 0)
|
||||
&& (test.try_query(conn, query_fmt, event_name.c_str(), new_state.c_str()) == 0))
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
test.expect(success, "ALTER EVENT failed: %s", mysql_error(conn));
|
||||
if (success)
|
||||
{
|
||||
cout << "Event '" << event_name << "' set to '" << new_state << "'.\n";
|
||||
}
|
||||
}
|
||||
|
||||
void switchover(TestConnections& test, const string& new_master)
|
||||
{
|
||||
string switch_cmd = "call command mysqlmon switchover MySQL-Monitor " + new_master;
|
||||
test.maxscales->execute_maxadmin_command_print(0, switch_cmd.c_str());
|
||||
test.maxscales->wait_for_monitor(2);
|
||||
// Check success.
|
||||
auto new_master_status = test.get_server_status(new_master.c_str());
|
||||
auto new_master_id = test.get_master_server_id();
|
||||
string status_string;
|
||||
for (auto elem : new_master_status)
|
||||
{
|
||||
status_string += elem + ", ";
|
||||
}
|
||||
|
||||
bool success = (new_master_status.count("Master") == 1);
|
||||
test.expect(success,
|
||||
"%s is not master as expected. Status: %s. Current master id: %i",
|
||||
new_master.c_str(), status_string.c_str(), new_master_id);
|
||||
|
||||
if (success)
|
||||
{
|
||||
cout << "Switchover success, " + new_master + " is new master.\n";
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
Mariadb_nodes::require_gtid(true);
|
||||
@ -154,10 +205,17 @@ int main(int argc, char** argv)
|
||||
// Schedule a repeating event.
|
||||
create_event(test);
|
||||
|
||||
int server1_ind = 0;
|
||||
int server2_ind = 1;
|
||||
int server1_id = test.repl->get_server_id(server1_ind);
|
||||
|
||||
const char* server_names[] = {"server1", "server2", "server3", "server4"};
|
||||
auto server1_name = server_names[server1_ind];
|
||||
auto server2_name = server_names[server2_ind];
|
||||
|
||||
int master_id_begin = test.get_master_server_id();
|
||||
int node0_id = test.repl->get_server_id(0);
|
||||
test.expect(master_id_begin == node0_id,
|
||||
"First server is not the master: master id: %i", master_id_begin);
|
||||
|
||||
test.expect(master_id_begin == server1_id, WRONG_MASTER_FMT, server1_name, master_id_begin);
|
||||
|
||||
// If initialisation failed, fail the test immediately.
|
||||
if (test.global_result != 0)
|
||||
@ -167,8 +225,8 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
// Part 1: Do a failover
|
||||
cout << "Step 1: Stop master and wait for failover. Check that another server is promoted.\n";
|
||||
test.repl->stop_node(0);
|
||||
cout << "\nStep 1: Stop master and wait for failover. Check that another server is promoted.\n";
|
||||
test.repl->stop_node(server1_ind);
|
||||
test.maxscales->wait_for_monitor(3);
|
||||
get_output(test);
|
||||
int master_id_failover = test.get_master_server_id();
|
||||
@ -187,21 +245,21 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
// Part 2: Start node 0, let it join the cluster and check that the event is properly disabled.
|
||||
cout << "Step 2: Restart node 0. It should join the cluster.\n";
|
||||
test.repl->start_node(0);
|
||||
cout << "\nStep 2: Restart " << server1_name << ". It should join the cluster.\n";
|
||||
test.repl->start_node(server1_ind);
|
||||
test.maxscales->wait_for_monitor(4);
|
||||
get_output(test);
|
||||
const char server_name[] = "server1";
|
||||
auto states = test.get_server_status(server_name);
|
||||
|
||||
auto states = test.get_server_status(server1_name);
|
||||
if (states.count("Slave") < 1)
|
||||
{
|
||||
test.expect(false, "%s is not a slave as expected. Status: %s",
|
||||
server_name, string_set_to_string(states).c_str());
|
||||
server1_name, string_set_to_string(states).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Old master joined as slave, check that event is disabled.
|
||||
check_event_status(test, 0, EVENT_NAME, "SLAVESIDE_DISABLED");
|
||||
check_event_status(test, server1_ind, EVENT_NAME, EV_STATE_SLAVE_DISABLED);
|
||||
}
|
||||
|
||||
if (test.global_result != 0)
|
||||
@ -212,29 +270,49 @@ int main(int argc, char** argv)
|
||||
|
||||
// Part 3: Switchover back to server1 as master. The event will most likely not run because the old
|
||||
// master doesn't have event scheduler on anymore.
|
||||
cout << "Step 3: Switchover back to server1. Check that event is enabled. Don't check that the "
|
||||
"event is running since the scheduler process is likely off.\n";
|
||||
string switch_cmd = "call command mysqlmon switchover MySQL-Monitor server1";
|
||||
test.maxscales->execute_maxadmin_command_print(0, switch_cmd.c_str());
|
||||
test.maxscales->wait_for_monitor(1);
|
||||
get_output(test);
|
||||
// Check success.
|
||||
int master_id_switchover = test.get_master_server_id();
|
||||
test.expect(master_id_switchover == node0_id,
|
||||
"server1 is not master as expected. Current master: %i.", master_id_switchover);
|
||||
check_event_status(test, 0, EVENT_NAME, "ENABLED");
|
||||
if (test.global_result != 0)
|
||||
cout << "\nStep 3: Switchover back to " << server1_name << ". Check that event is enabled. "
|
||||
"Don't check that the event is running since the scheduler process is likely off.\n";
|
||||
switchover(test, server1_name);
|
||||
if (test.ok())
|
||||
{
|
||||
try_delete_event(test);
|
||||
return test.global_result;
|
||||
check_event_status(test, server1_ind, EVENT_NAME, EV_STATE_ENABLED);
|
||||
}
|
||||
|
||||
// Check that all other nodes are slaves.
|
||||
for (int i = 1; i < test.repl->N; i++)
|
||||
// Part 4: Disable the event on master. The event should still be "SLAVESIDE_DISABLED" on slaves.
|
||||
// Check that after switchover, the event is not enabled.
|
||||
cout << "\nStep 4: Disable event on master, switchover to " << server2_name << ". "
|
||||
"Check that event is still disabled.\n";
|
||||
if (test.ok())
|
||||
{
|
||||
string server_name = "server" + std::to_string(i + 1);
|
||||
auto states = test.maxscales->get_server_status(server_name.c_str());
|
||||
test.expect(states.count("Slave") == 1, "%s is not a slave.", server_name.c_str());
|
||||
set_event_state(test, EVENT_NAME, "DISABLE");
|
||||
test.maxscales->wait_for_monitor(); // Wait for the monitor to detect the change.
|
||||
check_event_status(test, server1_ind, EVENT_NAME, EV_STATE_DISABLED);
|
||||
check_event_status(test, server2_ind, EVENT_NAME, EV_STATE_SLAVE_DISABLED);
|
||||
|
||||
if (test.ok())
|
||||
{
|
||||
cout << "Event is disabled on master and slaveside-disabled on slave.\n";
|
||||
switchover(test, server2_name);
|
||||
if (test.ok())
|
||||
{
|
||||
// Event should not have been touched.
|
||||
check_event_status(test, server2_ind, EVENT_NAME, EV_STATE_SLAVE_DISABLED);
|
||||
}
|
||||
|
||||
// Switchover back.
|
||||
switchover(test, server1_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (test.ok())
|
||||
{
|
||||
// Check that all other nodes are slaves.
|
||||
for (int i = 1; i < test.repl->N; i++)
|
||||
{
|
||||
string server_name = server_names[i];
|
||||
auto states = test.maxscales->get_server_status(server_name.c_str());
|
||||
test.expect(states.count("Slave") == 1, "%s is not a slave.", server_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
try_delete_event(test);
|
||||
|
||||
@ -816,11 +816,16 @@ void TestConnections::copy_one_mariadb_log(int i, std::string filename)
|
||||
|
||||
for (auto cmd : log_retrive_commands)
|
||||
{
|
||||
std::ofstream outfile(filename + std::to_string(j++));
|
||||
auto output = repl->ssh_output(cmd, i).second;
|
||||
|
||||
if (outfile)
|
||||
if (!output.empty())
|
||||
{
|
||||
outfile << repl->ssh_output(cmd, i).second;
|
||||
std::ofstream outfile(filename + std::to_string(j++));
|
||||
|
||||
if (outfile)
|
||||
{
|
||||
outfile << output;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user