From 11fd6e24be10d4c8838d4fc63a14c8cf70d32771 Mon Sep 17 00:00:00 2001 From: MassimilianoPinto Date: Tue, 25 Aug 2015 16:27:37 +0200 Subject: [PATCH] Added test for CHANGE MASTER TO Added test for CHANGE MASTER TO: syntax parsing and rule/constraints checks --- server/modules/routing/test/CMakeLists.txt | 12 +- server/modules/routing/test/testbinlog.c | 594 +++++++++++++++++++++ 2 files changed, 600 insertions(+), 6 deletions(-) create mode 100644 server/modules/routing/test/testbinlog.c diff --git a/server/modules/routing/test/CMakeLists.txt b/server/modules/routing/test/CMakeLists.txt index 19c51b4a1..02ee34ebe 100644 --- a/server/modules/routing/test/CMakeLists.txt +++ b/server/modules/routing/test/CMakeLists.txt @@ -1,6 +1,6 @@ -if(MYSQLCLIENT_FOUND) - add_executable(testconnect testconnect.c) - message(STATUS "Linking against: ${MYSQLCLIENT_LIBRARIES}") - target_link_libraries(testconnect ${MYSQLCLIENT_LIBRARIES} ssl crypto dl z m rt pthread) - add_test(NAME ReadConnRouterAuthTest COMMAND $ 10000 ${TEST_HOST} ${MASTER_PORT} ${TEST_HOST} ${TEST_PORT} 1.10) -endif() \ No newline at end of file +if(BUILD_TESTS) + aux_source_directory(${CMAKE_SOURCE_DIR}/server/modules/routing/binlog BINLOG_SOURCE) + add_executable(testbinlogrouter testbinlog.c ${BINLOG_SOURCE}) + target_link_libraries(testbinlogrouter fullcore ssl pthread log_manager) + add_test(TestBinlogRouter ${CMAKE_CURRENT_BINARY_DIR}/testbinlogrouter) +endif() diff --git a/server/modules/routing/test/testbinlog.c b/server/modules/routing/test/testbinlog.c new file mode 100644 index 000000000..30062f329 --- /dev/null +++ b/server/modules/routing/test/testbinlog.c @@ -0,0 +1,594 @@ +/* + * GNU General Public License as published by the Free Software Foundation, + * version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright MariaDB Corporation Ab 2015 + */ + +/** + * @file testbinlog.c - The MaxScale CHANGE MASTER TO syntax test + * + * Revision History + * + * Date Who Description + * 24/08/2015 Massimiliano Pinto Initial implementation + * + * @endverbatim + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +extern int lm_enabled_logfiles_bitmask; +extern size_t log_ses_count[]; +extern __thread log_info_t tls_log_info; +static void printVersion(const char *progname); +static void printUsage(const char *progname); +extern int blr_test_parse_change_master_command(char *input, char *error_string, CHANGE_MASTER_OPTIONS *config); +extern char *blr_test_set_master_logfile(ROUTER_INSTANCE *router, char *filename, char *error); +extern int blr_test_handle_change_master(ROUTER_INSTANCE* router, char *command, char *error); + +static struct option long_options[] = { + {"debug", no_argument, 0, 'd'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {"fix", no_argument, 0, 'f'}, + {"help", no_argument, 0, '?'}, + {0, 0, 0, 0} +}; + +int main(int argc, char **argv) { + char** arg_vector; + ROUTER_INSTANCE *inst; + int ret; + int rc; + int arg_count = 4; + char error_string[BINLOG_ERROR_MSG_LEN + 1] = ""; + CHANGE_MASTER_OPTIONS change_master; + char query[255+1]=""; + char saved_query[255+1]=""; + int command_offset = strlen("CHANGE MASTER TO"); + char *master_log_file = NULL; + char *master_log_pos = NULL; + SERVICE *service; + char *roptions; + int tests = 1; + + roptions = strdup("server-id=3,heartbeat=200,binlogdir=/not_exists/my_dir,transaction_safety=1,master_version=5.6.99-common,master_hostname=common_server,master_uuid=xxx-fff-cccc-fff,master-id=999"); + + arg_vector = malloc(sizeof(char*)*(arg_count + 1)); + + if(arg_vector == NULL) + { + fprintf(stderr,"Error: Memory allocation failed for log manager arg_vector.\n"); + return 1; + } + + arg_vector[0] = "logmanager"; + arg_vector[1] = "-j"; + arg_vector[2] = "/tmp/maxbinlogcheck"; + arg_vector[3] = "-o"; + arg_vector[4] = NULL; + skygw_logmanager_init(arg_count,arg_vector); + free(arg_vector); + + skygw_log_disable(LOGFILE_DEBUG); + skygw_log_disable(LOGFILE_TRACE); + skygw_log_disable(LOGFILE_ERROR); + skygw_log_disable(LOGFILE_MESSAGE); + + service = service_alloc("test_service", "binlogrouter"); + service->credentials.name = strdup("foo"); + service->credentials.authdata = strdup("bar"); + + { + char *lasts; + SERVER *server; + char *s = strtok_r(roptions, ",", &lasts); + while (s) + { + serviceAddRouterOption(service, s); + s = strtok_r(NULL, ",", &lasts); + } + + server = server_alloc("_none_", "MySQLBackend", (int)3306); + if (server == NULL) { + if (service->users) { + users_free(service->users); + } + + return 1; + } + + server_set_unique_name(server, "binlog_router_master_host"); + serviceAddBackend(service, server); + } + + if ((inst = calloc(1, sizeof(ROUTER_INSTANCE))) == NULL) { + LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, + "Error: Memory allocation failed for ROUTER_INSTANCE"))); + + skygw_log_sync_all(); + skygw_logmanager_done(); + + return 1; + } + + inst->service = service; + inst->user = service->credentials.name; + inst->password = service->credentials.authdata; + + LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, "testbinlog v1.0"))); + + if (inst->fileroot == NULL) + inst->fileroot = strdup(BINLOG_NAME_ROOT); + if (!inst->current_pos) + inst->current_pos = 4; + + /******************************************** + * + * First test suite is about syntax parsing + * + ********************************************/ + + /** + * Test 1: no given options + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO" + command_offset); + /* Expected rc is 1, if 0 test fails */ + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: no options for [%s] failed\n", tests, query); + return 1; + } else printf("Test %d Passed, no given options for [%s]\n", tests, query); + + tests++; + + /** + * Test 2: 1 wrong option without value + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO X" + command_offset); + /* Expected rc is 1, if 0 test fails */ + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: 1 wrong option for [%s] failed\n", tests, query); + return 1; + } else printf("Test %d Passed, 1 wrong option for [%s]\n", tests, query); + + tests++; + + /** + * Test 3: 1 wrong option with missing value after = + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO X=" + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: 1 wrong option for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 1 wrong option for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 4: 1 wrong option with missing value after = + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO X =" + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: 1 wrong option for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 1 wrong option for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 5: 1 wrong option with missing value after = + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO X= " + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: 1 wrong option for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 1 wrong option for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 6: 1 wrong option with missing value after = + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO X = " + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: 1 wrong option for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 1 wrong option for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 7: 1 valid option with missing value + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO MasTER_hoST" + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: 1 wrong option for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 1 wrong option for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 8: 1 valid option with missing value + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO MasTER_hoST = " + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: 1 wrong option for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 1 wrong option for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 9: 1 valid option with value + * + * Expected rc is 0, if 1 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1'" + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 1) { + printf("Test %d: 1 valid option for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 1 valid option for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 10: 1 valid option and 2 invalid ones + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1', Y, X" + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: 1 valid option and 2 wrong ones for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 1 valid option and 2 wrong ones for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 11: 1 valid option and 1 with missing value + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1', MASTER_PORT=" + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: 1 valid option and 1 wrong for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 1 valid option and 1 wrong for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 12: 2 valid options + * + * Expected rc is 0, if 1 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1', MASTER_PORT=9999" + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 1) { + printf("Test %d: 2 valid options for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 2 valid options for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 13: 2 valid options and 1 invalid + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1', MASTER_PORT=9999, MASTER_PASSWD='massi'" + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: 2 valid options and 1 wrong for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 2 valid options and 1 wrong for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 14: 3 valid options + * + * Expected rc is 0, if 1 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1', MASTER_PORT=9999, MASTER_PASSWORD='massi'" + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 1) { + printf("Test %d: 3 valid options [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 3 valid options for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 15: 5 valid options and 1 invalid + * + * Expected rc is 1, if 0 test fails + */ + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1', MASTER_PORT=9999, MASTER_PASSWORD='massi', MAster_user='eee', master_log_fil= 'fffff', master_log_pos= 55" + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 0) { + printf("Test %d: 5 valid options and 1 wrong for [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 5 valid options and 1 wrong for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 16: 6 valid options + * + * Expected rc is 0, if 1 test fails + */ + strcpy(error_string, ""); + memset(&change_master, 0, sizeof(change_master)); + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1', MASTER_PORT=9999, MASTER_PASSWORD='massi', MAster_user='eee', master_log_file= 'fffff', master_log_pos= 55" + command_offset); + strcpy(saved_query, query); + rc = blr_test_parse_change_master_command(query, error_string, &change_master); + if (rc == 1) { + printf("Test %d: 6 valid options [%s] failed\n", tests, saved_query); + return 1; + } else printf("Test %d Passed, 6 valid options for [%s]\n", tests, saved_query); + + tests++; + + /** + * Test 17: use current binlog filename in master_state != BLRM_UNCONFIGURED + * and try to set a new filename with wront format from previous test + * + * Expected master_log_file is NULL and error_string is not empty + */ + inst->master_state = BLRM_SLAVE_STOPPED; + strcpy(error_string, ""); + + master_log_file = blr_test_set_master_logfile(inst, change_master.binlog_file, error_string); + + if (master_log_file == NULL) { + if (strlen(error_string)) { + printf("Test %d Passed, MASTER_LOG_FILE [%s]: [%s]\n", tests, change_master.binlog_file, error_string); + } else { + printf("Test %d: set MASTER_LOG_FILE [%s] failed, an error message was expected\n", tests, change_master.binlog_file); + return 1; + } + } else { + printf("Test %d: set MASTER_LOG_FILE [%s] failed, NULL was expected from blr_test_set_master_logfile()\n", tests, change_master.binlog_file); + return 1; + } + + tests++; + + /******************************************** + * + * Second aprt of test suite is for checking + * rules and constraints once syntax is OK + * + ********************************************/ + + /** + * Test 18: change master without MASTER_LOG_FILE in BLRM_UNCONFIGURED state + * + * Expected rc = -1 and master_state still set to BLRM_UNCONFIGURED + */ + inst->master_state = BLRM_UNCONFIGURED; + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1', MASTER_PORT=9999, MASTER_PASSWORD='massi', MAster_user='eee', master_log_pos= 55"); + + rc = blr_test_handle_change_master(inst, query, error_string); + + if (rc == -1 && inst->master_state == BLRM_UNCONFIGURED) { + printf("Test %d Passed, in BLRM_UNCONFIGURED state. Message [%s]\n", tests, error_string); + } else { + printf("Test %d: an error message was expected from blr_test_handle_change_master(), Master State is %s. Message [%s]\n", tests, blrm_states[inst->master_state], error_string); + return 1; + } + + tests++; + + /** + * Test 19: use selected binlog filename in BLRM_UNCONFIGURED state + * + * Expected rc = -1 and master_state still set to BLRM_UNCONFIGURED + */ + + inst->master_state = BLRM_UNCONFIGURED; + strcpy(error_string, ""); + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1', MASTER_PORT=9999, MASTER_PASSWORD='massi', MAster_user='eee', master_log_file= 'file.000053', master_log_pos= 1855"); + + rc = blr_test_handle_change_master(inst, query, error_string); + + if (rc == -1 && inst->master_state == BLRM_UNCONFIGURED) { + printf("Test %d Passed, cannot set MASTER_LOG_FILE in BLRM_UNCONFIGURED state for [%s]. Message [%s]\n", tests, query, error_string); + } else { + printf("Test %d: set MASTER_LOG_FILE in BLRM_UNCONFIGURED state failed, an error message was expected from blr_test_handle_change_master(), Master State is %s. Message [%s]\n", tests, blrm_states[inst->master_state], error_string); + return 1; + } + + tests++; + + /** + * Test 20: use selected binlog filename and pos in state != BLRM_UNCONFIGURED + * Current binlog and pos are same specified in the change master command + * + * Expected rc = 0 + */ + inst->master_state = BLRM_UNCONNECTED; + strcpy(error_string, ""); + strncpy(inst->binlog_name, "file-bin.00008", BINLOG_FNAMELEN); + inst->current_pos = 55; + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1', MASTER_PORT=9999, MASTER_PASSWORD='massi', MAster_user='eee', master_log_file= 'file-bin.00008', master_log_pos= 55"); + + rc = blr_test_handle_change_master(inst, query, error_string); + + if (rc == 0) { + printf("Test %d Passed, set MASTER_LOG_FILE and MASTER_LOG_POS for [%s]\n", tests, query); + } else { + printf("Test %d: set MASTER_LOG_FILE and MASTER_LOG_POS failed, Master State is %s. Message [%s]\n", tests, blrm_states[inst->master_state], error_string); + return 1; + } + + tests++; + + /** + * Test 21: use selected binlog filename and pos in state != BLRM_UNCONFIGURED + * Current binlog is not the one specified in the change master command + * + * Expected rc = -1 + */ + + strncpy(inst->binlog_name, "file.000006", BINLOG_FNAMELEN); + inst->current_pos = 10348; + strcpy(inst->fileroot, "file"); + strcpy(error_string, ""); + inst->master_state = BLRM_UNCONNECTED; + strcpy(query, "CHANGE MASTER TO MasTER_hoST = '127.0.0.1', MASTER_PORT=9999, MASTER_PASSWORD='massi', MAster_user='eee', MASTER_LOG_file ='mmmm.098777', master_log_pos= 55"); + + rc = blr_test_handle_change_master(inst, query, error_string); + + if (rc == -1) { + printf("Test %d Passed, cannot set MASTER_LOG_FILE for [%s], Message [%s]\n", tests, query, error_string); + } else { + printf("Test %d: set MASTER_LOG_FILE, Master State is %s Failed, Message [%s]\n", tests, blrm_states[inst->master_state], error_string); + return 1; + } + + tests++; + + /** + * Test 22: use selected binlog filename is next one in sequence and specified pos is 4 + * in state != BLRM_UNCONFIGURED + * + * Expected rc = 0 + */ + strcpy(error_string, ""); + strncpy(inst->binlog_name, "file.100506", BINLOG_FNAMELEN); + inst->current_pos = 1348; + strcpy(inst->fileroot, "file"); + strcpy(query, "CHANGE MASTER TO master_log_pos= 4 , master_log_file='file.100507'"); + + rc = blr_test_handle_change_master(inst, query, error_string); + + if (rc == 0) { + printf("Test %d Passed, set MASTER_LOG_FILE for [%s]\n", tests, query); + } else { + printf("Test %d: set MASTER_LOG_FILE failed, Master State is %s. Message [%s]\n", tests, blrm_states[inst->master_state], error_string); + return 1; + } + + tests++; + + /** + * Test 23: use selected pos that's not the current one + * in state != BLRM_UNCONFIGURED + * + * Expected rc = -1 + */ + strcpy(error_string, ""); + strncpy(inst->binlog_name, "file.100506", BINLOG_FNAMELEN); + inst->current_pos = 138; + strcpy(inst->fileroot, "file"); + strcpy(query, "CHANGE MASTER TO master_log_pos= 49 "); + + rc = blr_test_handle_change_master(inst, query, error_string); + + if (rc == -1) { + printf("Test %d Passed, cannot set MASTER_LOG_POS for [%s], Message [%s]\n", tests, query, error_string); + } else { + printf("Test %d: set MASTER_LOG_POS failed, Master State is %s. Message [%s]\n", tests, blrm_states[inst->master_state], error_string); + return 1; + } + + skygw_log_sync_all(); + skygw_logmanager_done(); + + free(inst); + + return 0; +}