Fix mm_mysqlmon test

Because of monitor changes, the test had wrong assumptions.
Renamed the test and updated it to use MaxCtrl for some queries.

Also, changed the type of the cycle container in the monitor to an
ordered map so that results are predictable.
This commit is contained in:
Esa Korhonen
2018-07-16 17:40:07 +03:00
parent d91710c640
commit 590df89dbc
5 changed files with 237 additions and 230 deletions

View File

@ -246,6 +246,12 @@ add_test_executable(encrypted_passwords.cpp encrypted_passwords replication LABE
# Basic MaxCtrl test
add_test_executable(maxctrl_basic.cpp maxctrl_basic replication LABELS maxctrl REPL_BACKEND)
# MySQL Monitor with Multi-master configurations
add_test_executable(mysqlmon_multimaster.cpp mysqlmon_multimaster mysqlmon_multimaster LABELS mysqlmon REPL_BACKEND BREAKS_REPL)
# MySQL Monitor crash safety
#add_test_executable(mysqlmon_backup.cpp mysqlmon_backup mysqlmon_backup LABELS mysqlmon REPL_BACKEND)
# MySQL Monitor Failover Test
add_test_executable(mysqlmon_detect_standalone_master.cpp mysqlmon_detect_standalone_master mysqlmon_detect_standalone_master LABELS mysqlmon REPL_BACKEND)
@ -382,12 +388,6 @@ add_test_executable(maxscale_process_user.cpp maxscale_process_user replication
# Test of multi master monitor
add_test_executable(mm.cpp mm mm LABELS mmmon BREAKS_REPL)
# MySQL Monitor with Multi-master configurations
add_test_executable(mm_mysqlmon.cpp mm_mysqlmon mm_mysqlmon LABELS mysqlmon REPL_BACKEND BREAKS_REPL)
# MySQL Monitor crash safety
#add_test_executable(mysqlmon_backup.cpp mysqlmon_backup mysqlmon_backup LABELS mysqlmon REPL_BACKEND)
# Regression case for the bug "Two monitors loaded at the same time result into not working installation"
add_test_executable(mxs118.cpp mxs118 mxs118 LABELS maxscale LIGHT REPL_BACKEND)

View File

@ -10,7 +10,6 @@ user=maxskysql
password= skysql
detect_stale_master=0
monitor_interval=1000
multimaster=true
[RW Split Router]
type=service

View File

@ -1,221 +0,0 @@
/**
* @file mm_mysqlmon.cpp MySQL Monitor Multi-master Test
* - Configure all servers into a multi-master ring with one slave
* - check status using Maxadmin 'show servers' and 'show monitor "MySQL Monitor"'
* - Set nodes 0 and 1 into read-only mode
* - repeat status check
* - Configure nodes 1 and 2 (server2 and server3) into a master-master pair, make node 0 a slave of node 1 and node 3 a slave of node 2
* - repeat status check
* - Set node 1 into read-only mode
* - repeat status check
* - Create two distinct groups (server1 and server2 are masters for eache others and same for server3 and server4)
* - repeat status check
* - Set nodes 1 and 3 (server2 and server4) into read-only mode
*/
#include <iostream>
#include "testconnections.h"
#include "maxadmin_operations.h"
#include "sql_t1.h"
void check_status(TestConnections *Test, const char *server, const char *status)
{
char cmd[256];
char maxadmin_result[1024];
sprintf(cmd, "show server %s", server);
Test->set_timeout(120);
Test->maxscales->get_maxadmin_param(0, cmd, (char *) "Status:", maxadmin_result);
if (maxadmin_result == NULL)
{
Test->add_result(1, "maxadmin execution error\n");
return;
}
if (strstr(maxadmin_result, status) == NULL )
{
Test->add_result(1, "Test failed, server '%s' status is '%s', expected '%s'\n", server, maxadmin_result,
status);
}
}
void check_group(TestConnections *Test, const char *server, const char *group)
{
int exit_code;
char *output = Test->maxscales->ssh_node_output(0, "maxadmin show monitor MySQL-Monitor", true, &exit_code);
if (output == NULL)
{
Test->add_result(1, "maxadmin execution error\n");
return;
}
char *start = strstr(output, server);
if (start == NULL)
{
Test->add_result(1, "maxadmin execution error\n");
return;
}
char *value = strstr(start, "Master group");
if (value == NULL)
{
Test->add_result(1, "maxadmin execution error\n");
return;
}
value = strchr(value, ':') + 1;
while (isspace(*value))
{
value++;
}
char *end = value;
while (!isspace(*end))
{
end++;
}
*end = '\0';
Test->add_result(strcmp(group, value), "Server '%s', expected group '%s', not '%s'", server, group, value);
}
void change_master(TestConnections *Test, int slave, int master)
{
execute_query(Test->repl->nodes[slave], "CHANGE MASTER TO master_host='%s', master_port=%d, "
"master_log_file='mar-bin.000001', master_log_pos=4, master_user='repl', master_password='repl';START SLAVE",
Test->repl->IP[master], Test->repl->port[master]);
}
int main(int argc, char *argv[])
{
TestConnections * Test = new TestConnections(argc, argv);
Test->tprintf("Test 1 - Configure all servers into a multi-master ring with one slave");
Test->set_timeout(120);
Test->repl->execute_query_all_nodes("STOP SLAVE; RESET SLAVE ALL; RESET MASTER; SET GLOBAL read_only='OFF'");
Test->repl->connect();
change_master(Test, 0, 1);
change_master(Test, 1, 2);
change_master(Test, 2, 0);
change_master(Test, 3, 2);
sleep(2);
check_status(Test, "server1", "Master, Running");
check_status(Test, "server2", "Master, Running");
check_status(Test, "server3", "Master, Running");
check_status(Test, "server4", "Slave, Running");
check_group(Test, "server1", "1");
check_group(Test, "server2", "1");
check_group(Test, "server3", "1");
check_group(Test, "server4", "0");
Test->tprintf("Test 2 - Set nodes 0 and 1 into read-only mode");
Test->set_timeout(120);
execute_query(Test->repl->nodes[0], "SET GLOBAL read_only='ON'");
execute_query(Test->repl->nodes[1], "SET GLOBAL read_only='ON'");
sleep(2);
check_status(Test, "server1", "Slave, Running");
check_status(Test, "server2", "Slave, Running");
check_status(Test, "server3", "Master, Running");
check_status(Test, "server4", "Slave, Running");
check_group(Test, "server1", "1");
check_group(Test, "server2", "1");
check_group(Test, "server3", "1");
check_group(Test, "server4", "0");
Test->tprintf("Test 3 - Configure nodes 1 and 2 into a master-master pair, make node 0 "
"a slave of node 1 and node 3 a slave of node 2");
Test->set_timeout(120);
Test->repl->execute_query_all_nodes("STOP SLAVE; RESET SLAVE ALL; RESET MASTER;SET GLOBAL read_only='OFF'");
Test->repl->connect();
change_master(Test, 0, 1);
change_master(Test, 1, 2);
change_master(Test, 2, 1);
change_master(Test, 3, 2);
sleep(2);
check_status(Test, "server1", "Slave, Running");
check_status(Test, "server2", "Master, Running");
check_status(Test, "server3", "Master, Running");
check_status(Test, "server4", "Slave, Running");
check_group(Test, "server1", "0");
check_group(Test, "server2", "1");
check_group(Test, "server3", "1");
check_group(Test, "server4", "0");
Test->tprintf("Test 4 - Set node 1 into read-only mode");
Test->set_timeout(120);
execute_query(Test->repl->nodes[1], "SET GLOBAL read_only='ON'");
sleep(2);
check_status(Test, "server1", "Slave, Running");
check_status(Test, "server2", "Slave, Running");
check_status(Test, "server3", "Master, Running");
check_status(Test, "server4", "Slave, Running");
check_group(Test, "server1", "0");
check_group(Test, "server2", "1");
check_group(Test, "server3", "1");
check_group(Test, "server4", "0");
Test->tprintf("Test 5 - Create two distinct groups");
Test->set_timeout(120);
Test->repl->execute_query_all_nodes("STOP SLAVE; RESET SLAVE ALL; RESET MASTER;SET GLOBAL read_only='OFF'");
Test->repl->connect();
change_master(Test, 0, 1);
change_master(Test, 1, 0);
change_master(Test, 2, 3);
change_master(Test, 3, 2);
sleep(2);
check_status(Test, "server1", "Master, Running");
check_status(Test, "server2", "Master, Running");
check_status(Test, "server3", "Master, Running");
check_status(Test, "server4", "Master, Running");
check_group(Test, "server1", "1");
check_group(Test, "server2", "1");
check_group(Test, "server3", "2");
check_group(Test, "server4", "2");
Test->tprintf("Test 6 - Set nodes 1 and 3 into read-only mode");
Test->set_timeout(120);
execute_query(Test->repl->nodes[1], "SET GLOBAL read_only='ON'");
execute_query(Test->repl->nodes[3], "SET GLOBAL read_only='ON'");
sleep(2);
check_status(Test, "server1", "Master, Running");
check_status(Test, "server2", "Slave, Running");
check_status(Test, "server3", "Master, Running");
check_status(Test, "server4", "Slave, Running");
check_group(Test, "server1", "1");
check_group(Test, "server2", "1");
check_group(Test, "server3", "2");
check_group(Test, "server4", "2");
Test->repl->execute_query_all_nodes("STOP SLAVE; RESET SLAVE ALL; RESET MASTER;SET GLOBAL read_only='OFF';");
Test->repl->connect();
change_master(Test, 1, 0);
change_master(Test, 2, 0);
change_master(Test, 3, 0);
Test->repl->fix_replication();
int rval = Test->global_result;
delete Test;
return rval;
}

View File

@ -0,0 +1,229 @@
/**
* @file mysqlmon_multimaster.cpp MySQL Monitor Multi-master Test
* - Configure all servers into a multi-master ring with one slave
* - check status using Maxadmin 'show servers' and 'show monitor "MySQL Monitor"'
* - Set nodes 0 and 1 into read-only mode
* - repeat status check
* - Configure nodes 1 and 2 (server2 and server3) into a master-master pair, make node 0 a slave of node 1 and node 3 a slave of node 2
* - repeat status check
* - Set node 1 into read-only mode
* - repeat status check
* - Create two distinct groups (server1 and server2 are masters for eache others and same for server3 and server4)
* - repeat status check
* - Set nodes 1 and 3 (server2 and server4) into read-only mode
*/
#include <iostream>
#include "testconnections.h"
#include "maxadmin_operations.h"
#include "sql_t1.h"
#include <jansson.h>
void check_status(TestConnections& test, const char *server, const char *status)
{
char cmd[256];
char maxadmin_result[1024];
sprintf(cmd, "show server %s", server);
test.set_timeout(120);
test.maxscales->get_maxadmin_param(0, cmd, (char *)"Status:", maxadmin_result);
if (maxadmin_result == NULL)
{
test.add_result(1, "maxadmin execution error\n");
return;
}
if (strstr(maxadmin_result, status) == NULL)
{
test.add_result(1, "Test failed, server '%s' status is '%s', expected '%s'\n",
server, maxadmin_result, status);
}
}
void check_group(TestConnections& test , const char *server, int expected_group)
{
int exit_code = 1;
char *output = test.maxscales->ssh_node_output(0, "maxctrl api get monitors/MySQL-Monitor",
true, &exit_code);
if (output == NULL)
{
test.add_result(1, "maxctrl execution error, no output\n");
return;
}
json_error_t error;
json_t* object_data = json_loads(output, 0, &error);
if (object_data == NULL)
{
test.add_result(1, "JSON decode error: %s\n", error.text);
return;
}
object_data = json_object_get(object_data, "data");
object_data = json_object_get(object_data, "attributes");
object_data = json_object_get(object_data, "monitor_diagnostics");
json_t* server_info = json_object_get(object_data, "server_info");
size_t arr_size = json_array_size(server_info);
json_int_t found_group = -1;
for (size_t i = 0; i < arr_size; i++)
{
json_t* arr_elem = json_array_get(server_info, i);
std::string server_name = json_string_value(json_object_get(arr_elem, "name"));
if (server_name == server)
{
found_group = json_integer_value(json_object_get(arr_elem, "master_group"));
}
}
test.assert(found_group == expected_group, "Server '%s', expected group '%d', not '%d'",
server, expected_group, (int)found_group);
}
void change_master(TestConnections& Test, int slave, int master)
{
const char query[] = "CHANGE MASTER TO master_host='%s', master_port=%d, "
"master_log_file='mar-bin.000001', master_log_pos=4, master_user='repl', master_password='repl'; "
"START SLAVE";
execute_query(Test.repl->nodes[slave], query, Test.repl->IP[master], Test.repl->port[master]);
}
int main(int argc, char *argv[])
{
const char mm_master_states[] = "Master, Running";
const char mm_slave_states[] = "Relay Master, Slave, Running";
const char slave_states[] = "Slave, Running";
const char running_state[] = "Running";
const char reset_query[] = "STOP SLAVE; RESET SLAVE ALL; RESET MASTER; SET GLOBAL read_only='OFF'";
const char readonly_on_query[] = "SET GLOBAL read_only='ON'";
TestConnections test(argc, argv);
test.tprintf("Test 1 - Configure all servers into a multi-master ring with one slave");
test.set_timeout(120);
test.repl->execute_query_all_nodes(reset_query);
test.repl->connect();
change_master(test, 0, 1);
change_master(test, 1, 2);
change_master(test, 2, 0);
change_master(test, 3, 2);
sleep(2);
check_status(test, "server1", mm_master_states);
check_status(test, "server2", mm_slave_states);
check_status(test, "server3", mm_slave_states);
check_status(test, "server4", slave_states);
check_group(test, "server1", 1);
check_group(test, "server2", 1);
check_group(test, "server3", 1);
check_group(test, "server4", 0);
test.tprintf("Test 2 - Set nodes 0 and 1 into read-only mode");
test.set_timeout(120);
execute_query(test.repl->nodes[0], readonly_on_query);
execute_query(test.repl->nodes[1], readonly_on_query);
sleep(2);
check_status(test, "server1", mm_slave_states);
check_status(test, "server2", mm_slave_states);
check_status(test, "server3", mm_master_states);
check_status(test, "server4", slave_states);
check_group(test, "server1", 1);
check_group(test, "server2", 1);
check_group(test, "server3", 1);
check_group(test, "server4", 0);
test.tprintf("Test 3 - Configure nodes 1 and 2 into a master-master pair, make node 0 "
"a slave of node 1 and node 3 a slave of node 2");
test.set_timeout(120);
test.repl->execute_query_all_nodes(reset_query);
test.repl->connect();
change_master(test, 0, 1);
change_master(test, 1, 2);
change_master(test, 2, 1);
change_master(test, 3, 2);
sleep(2);
check_status(test, "server1", slave_states);
check_status(test, "server2", mm_master_states);
check_status(test, "server3", mm_slave_states);
check_status(test, "server4", slave_states);
check_group(test, "server1", 0);
check_group(test, "server2", 1);
check_group(test, "server3", 1);
check_group(test, "server4", 0);
test.tprintf("Test 4 - Set node 1 into read-only mode");
test.set_timeout(120);
execute_query(test.repl->nodes[1], readonly_on_query);
sleep(2);
check_status(test, "server1", slave_states);
check_status(test, "server2", mm_slave_states);
check_status(test, "server3", mm_master_states);
check_status(test, "server4", slave_states);
check_group(test, "server1", 0);
check_group(test, "server2", 1);
check_group(test, "server3", 1);
check_group(test, "server4", 0);
test.tprintf("Test 5 - Create two distinct groups");
test.set_timeout(120);
test.repl->execute_query_all_nodes(reset_query);
test.repl->connect();
change_master(test, 0, 1);
change_master(test, 1, 0);
change_master(test, 2, 3);
change_master(test, 3, 2);
sleep(2);
// Even though the servers are in two distinct groups, only one of them
// contains a master and a slave. Only one master may exist in a cluster
// at once, since by definition this is the server to which routers may
// direct writes.
check_status(test, "server1", mm_master_states);
check_status(test, "server2", mm_slave_states);
check_status(test, "server3", running_state);
check_status(test, "server4", running_state);
check_group(test, "server1", 1);
check_group(test, "server2", 1);
check_group(test, "server3", 2);
check_group(test, "server4", 2);
test.tprintf("Test 6 - Set nodes 1 and 3 into read-only mode");
test.set_timeout(120);
execute_query(test.repl->nodes[1], readonly_on_query);
execute_query(test.repl->nodes[3], readonly_on_query);
sleep(2);
check_status(test, "server1", mm_master_states);
check_status(test, "server2", mm_slave_states);
check_status(test, "server3", running_state);
check_status(test, "server4", running_state);
check_group(test, "server1", 1);
check_group(test, "server2", 1);
check_group(test, "server3", 2);
check_group(test, "server4", 2);
test.repl->execute_query_all_nodes(reset_query);
test.repl->connect();
change_master(test, 1, 0);
change_master(test, 2, 0);
change_master(test, 3, 0);
test.repl->fix_replication();
return test.global_result;
}

View File

@ -32,8 +32,8 @@ extern const char * const CN_DEMOTION_SQL_FILE;
typedef std::unordered_map<MXS_MONITORED_SERVER*, MariaDBServer*> ServerInfoMap;
// Map of server id:s to MariaDBServer. Useful when constructing the replication graph.
typedef std::unordered_map<int64_t, MariaDBServer*> IdToServerMap;
// Map of cycle number to cycle members
typedef std::unordered_map<int, ServerArray> CycleMap;
// Map of cycle number to cycle members. The elements should be in order for predictability when iterating.
typedef std::map<int, ServerArray> CycleMap;
// MariaDB Monitor instance data
class MariaDBMonitor : public maxscale::MonitorInstance