add tests
This commit is contained in:
parent
dbfd631fed
commit
8c6ca38a8a
9
.gitignore
vendored
9
.gitignore
vendored
@ -32,6 +32,7 @@ depend.mk
|
||||
.#*
|
||||
._*
|
||||
|
||||
|
||||
# Vi swap files
|
||||
.*.swp
|
||||
/build/
|
||||
@ -51,3 +52,11 @@ CMakeFiles/*
|
||||
*/*/*/*/CMakeFiles/*
|
||||
Makefile
|
||||
/.DS_Store
|
||||
|
||||
# Netbeans Project files
|
||||
nbproject/
|
||||
/build/
|
||||
|
||||
# RBCommons
|
||||
.reviewboardrc
|
||||
|
||||
|
702
maxscale-system-test/CMakeLists.txt
Normal file
702
maxscale-system-test/CMakeLists.txt
Normal file
@ -0,0 +1,702 @@
|
||||
# Building test package:
|
||||
#
|
||||
# apt-get install libssl-dev libmariadbclient-dev php5 perl \
|
||||
# coreutils realpath libjansson-dev openjdk-7-jdk
|
||||
# pip install JayDeBeApi
|
||||
|
||||
|
||||
# Backend labes:
|
||||
# REPL_BACKEND
|
||||
# GALERA_BACKEND
|
||||
# EXTERN_BACKEND
|
||||
# BREAKS_REPL
|
||||
# BREAKS_GALERA
|
||||
|
||||
project(maxscale_system_test)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
include_directories("/usr/include/mysql/")
|
||||
set(CTEST_BUILD_NAME "${BUILDNAME}")
|
||||
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of
|
||||
build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug
|
||||
Release RelWithDebInfo MinSizeRel.")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "-std=c++11 -ggdb")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-std=c++11 -ggdb")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-std=c++11 -ggdb")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-std=c++11 -ggdb")
|
||||
|
||||
enable_testing()
|
||||
|
||||
# utilities.cmake contains all helper functions and extra tools
|
||||
include(utilities.cmake)
|
||||
|
||||
# Is this needed?
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cnf/maxscale.cnf.template.setup_binlog.in ${CMAKE_BINARY_DIR}/cnf/maxscale.cnf.template.setup_binlog @ONLY)
|
||||
|
||||
# Enable Java
|
||||
find_package(Java)
|
||||
if(EXISTS ${Java_JAVA_EXECUTABLE} ${JAVA_JAVAC_EXECUTABLE} ${JAVA_JAR_EXECUTABLE})
|
||||
include(UseJava)
|
||||
if(Java_FOUND)
|
||||
add_subdirectory(maxscale/java/)
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Java not found, Java based tests are not run.")
|
||||
endif()
|
||||
|
||||
# The core library
|
||||
add_library(testcore SHARED testconnections.cpp mariadb_nodes.cpp
|
||||
mariadb_func.cpp get_com_select_insert.cpp maxadmin_operations.cpp big_transaction.cpp
|
||||
sql_t1.cpp test_binlog_fnc.cpp get_my_ip.cpp big_load.cpp get_com_select_insert.cpp
|
||||
different_size.cpp fw_copy_rules maxinfo_func.cpp config_operations.cpp rds_vpc.cpp execute_cmd.cpp
|
||||
blob_test.cpp cdc_connector.cpp)
|
||||
target_link_libraries(testcore ${MYSQL_CLIENT} z crypt nsl m pthread ssl crypto dl rt jansson)
|
||||
install(TARGETS testcore DESTINATION system-test)
|
||||
add_dependencies(testcore connector-c)
|
||||
|
||||
# Tool used to check backend state
|
||||
add_test_executable_notest(check_backend.cpp check_backend check_backend LABELS CONFIG)
|
||||
|
||||
# Configuration tests
|
||||
add_template(bug359 bug359)
|
||||
add_template(bug495 bug495)
|
||||
add_template(bug526 bug526)
|
||||
add_template(bug479 bug479)
|
||||
add_template(bug493 bug493)
|
||||
add_template(bug643_1 bug643_1)
|
||||
add_template(mxs652_bad_ssl bad_ssl)
|
||||
add_template(mxs710_bad_socket mxs710_bad_socket)
|
||||
add_template(mxs710_bad_socket mxs711_two_ports)
|
||||
add_template(mxs720_line_with_no_equal mxs720_line_with_no_equal)
|
||||
add_template(mxs720_wierd_line mxs720_wierd_line)
|
||||
add_template(mxs710_bad_socket mxs799)
|
||||
add_test_executable(config_test.cpp config_test replication LABELS CONFIG)
|
||||
|
||||
add_subdirectory(cdc_datatypes)
|
||||
|
||||
# Repeatedly connect to maxscale while the backends reject all connections, expect no crash
|
||||
add_test_executable(backend_auth_fail.cpp backend_auth_fail replication LABELS readconnroute REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "MaxScale ignores host in user authentication"
|
||||
add_test_executable(bug143.cpp bug143 replication LABELS MySQLAuth REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Executing '\s' doesn't always produce complete result set"
|
||||
add_test_executable(bug422.cpp bug422 replication LABELS readwritesplit readconnroute maxscale REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Wildcard in host column of mysql.user table don't work properly"
|
||||
add_test_executable(bug448.cpp bug448 replication LABELS MySQLAuth LIGHT REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "rwsplit counts every connection twice in master - counnection counts leak"
|
||||
add_test_executable(bug469.cpp bug469 replication LABELS readwritesplit LIGHT REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Routing Hints route to server sometimes doesn't work"
|
||||
add_test_executable(bug471.cpp bug471 bug471 LABELS readwritesplit hintfilter REPL_BACKEND)
|
||||
|
||||
# Regression case for the bugs "malformed hints cause crash"
|
||||
add_test_executable(bug473.cpp bug473 hints LABELS readwritesplit hintfilter REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "The end comment tag in hints isn't properly detected"
|
||||
add_test_executable(bug475.cpp bug475 hints LABELS readwritesplit hintfilter REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "SHOW VARIABLES randomly failing with "Lost connection to MySQL server"
|
||||
add_test_executable(bug488.cpp bug488 galera LABELS readwritesplit readconnroute maxscale GALERA_BACKEND)
|
||||
|
||||
# Regression case for the bug "rw-split router does not send last_insert_id() to master"
|
||||
add_test_executable(bug507.cpp bug507 replication LABELS readwritesplit LIGHT REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Referring to a nonexisting server in servers=... doesn't even raise a warning"
|
||||
add_test_executable(bug509.cpp bug509 galera LABELS readwritesplit GALERA_BACKEND)
|
||||
|
||||
# Checks "SELECT * INTO OUTFILE" and "LOAD DATA LOCAL INFILE"
|
||||
add_test_executable(bug519.cpp bug519 replication LABELS readwritesplit HEAVY REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "'Current no. of conns' not going down"
|
||||
add_test_executable(bug529.cpp bug529 replication LABELS readwritesplit readconnroute maxscale REPL_BACKEND)
|
||||
|
||||
# Regression case for the bugs "get_dcb fails if slaves are not available" and "Maxscale fails to start without anything in the logs if there is no slave available"
|
||||
add_test_executable(bug547.cpp bug547 replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "crash if max_slave_connections=10% and 4 or less backends are configured"
|
||||
add_test_executable(bug681.cpp bug681 galera.bug681 LABELS readwritesplit GALERA_BACKEND)
|
||||
|
||||
# Regression case for the bug "crash with tee filter"
|
||||
add_test_executable(bug643.cpp bug643 bug643 LABELS tee REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug ""Different error messages from MariaDB and Maxscale"
|
||||
add_test_script(bug561.sh bug561.sh replication LABELS MySQLAuth REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Wrong error message for Access denied error"
|
||||
add_test_script(bug562.sh bug562.sh replication LABELS MySQLAuth REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Wrong charset settings"
|
||||
add_test_script(bug564.sh bug564.sh replication LABELS MySQLProtocol REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Clients CLIENT_FOUND_ROWS setting is ignored by maxscale"
|
||||
add_test_executable(bug565.cpp bug565 replication LABELS MySQLProtocol REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Crash if files from /dev/shm/ removed"
|
||||
add_test_script(bug567.sh bug567.sh bug567 LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Using regex filter hangs MaxScale"
|
||||
add_test_executable(bug571.cpp bug571 bug571 LABELS regexfilter REPL_BACKEND)
|
||||
|
||||
# Attempt to use GRANT with wrong IP, expect no crash or hangs
|
||||
add_test_executable(bug572.cpp bug572 replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Regression cases for the bug "Hint filter don't work if listed before regex filter in configuration file"
|
||||
# (different filter sequence and configuration, but the same test, see .cnf for details)
|
||||
add_test_script(bug585 bug587 bug585 LABELS regexfilter REPL_BACKEND)
|
||||
add_test_executable(bug587.cpp bug587 bug587 LABELS regexfilter hintfilter REPL_BACKEND)
|
||||
add_test_script(bug587_1 bug587 bug587_1 LABELS regexfilter hintfilter REPL_BACKEND)
|
||||
|
||||
# Tries to connect Maxscale when all slaves stopped
|
||||
add_test_executable(bug592.cpp bug592 replication LABELS MySQLAuth readwritesplit REPL_BACKEND)
|
||||
|
||||
# Tries to do change user in the loop, checks that autorization is still ok
|
||||
add_test_executable(bug601.cpp bug601 bug601 LABELS MySQLAuth MySQLProtocol REPL_BACKEND)
|
||||
|
||||
# Simple test with enable_root_user=true
|
||||
add_test_executable(bug620.cpp bug620 bug620 LABELS MySQLAuth MySQLProtocol REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Crash when user define with old password style (before 4.1 protocol)"
|
||||
add_test_executable(bug626.cpp bug626 replication LABELS MySQLAuth MySQLProtocol REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug 634 "SHOW SLAVE STATUS in RW SPLITTER is send to master"
|
||||
add_test_executable(bug634.cpp bug634 replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Regression cases for several TEE filter hangs
|
||||
add_test_executable(bug645.cpp bug645 bug645 LABELS tee REPL_BACKEND)
|
||||
add_test_executable(bug645_1.cpp bug645_1 bug645_1 LABELS tee REPL_BACKEND)
|
||||
add_test_executable(bug649.cpp bug649 bug645 LABELS tee)
|
||||
add_test_executable(bug650.cpp bug650 bug650 LABELS tee REPL_BACKEND)
|
||||
|
||||
# Heavy test for TEE filter
|
||||
add_test_script(bug648 sql_queries bug648 LABELS tee UNSTABLE HEAVY REPL_BACKEND)
|
||||
|
||||
# Crash when host name for some user in mysql.user is very long
|
||||
add_test_executable(bug653.cpp bug653 replication LABELS MySQLAuth MySQLProtocol REPL_BACKEND)
|
||||
|
||||
# Crash with malformed Maxadmin command
|
||||
add_test_executable(bug654.cpp bug654 replication LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Tee filter: closing child session causes MaxScale to fail"
|
||||
add_test_executable(bug657.cpp bug657 bug657 LABELS tee REPL_BACKEND)
|
||||
|
||||
# Block backends (master or all slaves) and tries to connect Maxscale
|
||||
add_test_executable(bug658.cpp bug658 replication LABELS readwritesplit readconnroute maxscale REPL_BACKEND)
|
||||
|
||||
# Block all backends
|
||||
add_test_executable(bug662.cpp bug662 replication LABELS readwritesplit readconnroute maxscale REPL_BACKEND)
|
||||
|
||||
# Bad TEE filter configuration
|
||||
add_test_executable(bug664.cpp bug664 bug664 LABELS MySQLAuth MySQLProtocol)
|
||||
|
||||
# TEE fileter: execute long sequence of queries ans session commands in the loop
|
||||
add_test_executable(bug670.cpp bug670 bug670 LABELS tee REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "MaxScale crashes if "Users table data" is empty and "show dbusers" is executed in maxadmin"
|
||||
add_test_executable(bug673.cpp bug673 bug673 LABELS MySQLAuth REPL_BACKEND)
|
||||
|
||||
# Crash in case of backend node in Galera cluster stopping and then reconnect to Maxscale
|
||||
add_test_executable(bug676.cpp bug676 galera LABELS galeramon GALERA_BACKEND)
|
||||
|
||||
# Rgression test for th bug "RWSplit: 'SELECT @a:=@a+1 as a, test.b FROM test' breaks client session"
|
||||
add_test_executable(bug694.cpp bug694 bug694 LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Compare @@hostname from "select @@wsrep_node_name, @@hostname" and from "select @@hostname, @@wsrep_node_name"
|
||||
add_test_executable(bug699.cpp bug699 galera LABELS readwritesplit LIGHT GALERA_BACKEND)
|
||||
|
||||
# Wrong processing of 'SET GLOBAL sql_mode="ANSI"'
|
||||
add_test_executable(bug705.cpp bug705 bug705 LABELS MySQLAuth REPL_BACKEND)
|
||||
|
||||
# Try SHOW GLOBAL STATUS via Maxscale
|
||||
add_test_executable(bug711.cpp bug711 bug711 LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Prepared statement from PHP application
|
||||
add_test_executable(bug729.cpp bug729 replication LABELS readwritesplit LIGHT REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Regex filter and shorter than original replacement queries MaxScale" (crash)
|
||||
add_test_executable(bug730.cpp bug730 bug730 LABELS regexfilter REPL_BACKEND)
|
||||
|
||||
# Test MariaDB 10.2 bulk inserts
|
||||
add_test_executable(bulk_insert.cpp bulk_insert bulk_insert LABELS MySQLProtocol REPL_BACKEND 10.2)
|
||||
|
||||
# Tests for the CCRFilter module
|
||||
add_test_executable(ccrfilter.cpp ccrfilter ccrfilter LABELS ccrfilter LIGHT REPL_BACKEND)
|
||||
|
||||
# Tries to reconfigure replication setup to use another node as a Master
|
||||
add_test_executable(change_master_during_session.cpp change_master_during_session replication LABELS readwritesplit mysqlmon REPL_BACKEND)
|
||||
|
||||
# Executes change_user command in the loop
|
||||
add_test_executable(change_user.cpp change_user replication LABELS MySQLAuth MySQLProtocol LIGHT REPL_BACKEND)
|
||||
|
||||
# Tries to connect to non existing DB, expects no crash
|
||||
add_test_executable(connect_to_nonexisting_db.cpp connect_to_nonexisting_db replication LABELS MySQLAuth MySQLProtoco LIGHT REPL_BACKEND)
|
||||
|
||||
# check if max_connections parameter works
|
||||
add_test_executable(connection_limit.cpp connection_limit connection_limit LABELS maxscale LIGHT REPL_BACKEND)
|
||||
|
||||
# Tries to open to many connections, expect no crash
|
||||
add_test_executable(crash_out_of_files.cpp crash_out_of_files load LABELS maxscale HEAVY REPL_BACKEND)
|
||||
|
||||
# Tries to open to many connections, expect no crash, with Galera backend
|
||||
add_test_executable(crash_out_of_files_galera.cpp crash_out_of_files_galera galera LABELS maxscale HEAVY GALERA_BACKEND)
|
||||
|
||||
# Tries INSERTs with size close to 0x0ffffff * N
|
||||
add_test_executable(different_size_rwsplit.cpp different_size_rwsplit replication LABELS readwritesplit HEAVY REPL_BACKEND)
|
||||
|
||||
# Tries to use 'maxkeys', 'maxpasswrd'
|
||||
add_test_executable(encrypted_passwords.cpp encrypted_passwords replication LABELS maxscale LIGHT REPL_BACKEND)
|
||||
|
||||
# MySQL Monitor Failover Test
|
||||
add_test_executable(failover_mysqlmon.cpp failover_mysqlmon failover_mysqlmon LABELS mysqlmon REPL_BACKEND)
|
||||
|
||||
# Test monitor state change events when manually clearing server bits
|
||||
add_test_executable(false_monitor_state_change.cpp false_monitor_state_change replication LABELS mysqlmon REPL_BACKEND)
|
||||
|
||||
# A set of tests for Firewall filter
|
||||
add_test_executable(fwf.cpp fwf fwf LABELS dbfwfilter REPL_BACKEND)
|
||||
add_test_executable(fwf2.cpp fwf2 fwf LABELS dbfwfilter REPL_BACKEND)
|
||||
add_test_executable(fwf_duplicate_rules.cpp fwf_duplicate_rules fwf LABELS dbfwfilter REPL_BACKEND)
|
||||
add_test_executable(fwf_prepared_stmt.cpp fwf_prepared_stmt fwf LABELS dbfwfilter REPL_BACKEND)
|
||||
add_test_executable(fwf_actions.cpp fwf_actions fwf_action LABELS dbfwfilter REPL_BACKEND)
|
||||
add_test_executable(fwf_logging.cpp fwf_logging fwf_logging LABELS dbfwfilter REPL_BACKEND)
|
||||
add_test_executable(fwf_reload.cpp fwf_reload fwf LABELS dbfwfilter REPL_BACKEND)
|
||||
add_test_executable(fwf_syntax.cpp fwf_syntax fwf_syntax LABELS dbfwfilter REPL_BACKEND)
|
||||
add_test_executable(fwf_com_ping.cpp fwf_com_ping fwf_com_ping LABELS dbfwfilter REPL_BACKEND)
|
||||
|
||||
# Galera node priority test
|
||||
add_test_executable(galera_priority.cpp galera_priority galera_priority LABELS galeramon LIGHT GALERA_BACKEND)
|
||||
|
||||
# Block and unblock Master and check that Maxscale survived
|
||||
add_test_executable(kill_master.cpp kill_master replication LABELS readwritesplit LIGHT REPL_BACKEND)
|
||||
|
||||
# Test insertstream filter
|
||||
add_test_script(insertstream insertstream.sh insertstream LABELS insertstream REPL_BACKEND)
|
||||
|
||||
# Check load balancing
|
||||
add_test_executable(load_balancing.cpp load_balancing load LABELS readwritesplit LIGHT REPL_BACKEND)
|
||||
|
||||
# Check load balancing with Galera backend
|
||||
add_test_executable(load_balancing_galera.cpp load_balancing_galera load_galera LABELS readwritesplit GALERA_BACKEND)
|
||||
|
||||
# Check load balancing parameters with Galera backend and 1 persistent connection
|
||||
add_test_script(load_balancing_galera_pers1 load_balancing_galera load_galera_pers1 LABELS readwritesplit HEAVY GALERA_BACKEND)
|
||||
|
||||
# Check load balancing parameters with Galera backend and 10 persistent connections
|
||||
add_test_script(load_balancing_galera_pers10 load_balancing_galera load_galera_pers10 LABELS readwritesplit HEAVY GALERA_BACKEND)
|
||||
|
||||
# Check load balancing parameters with 1 persistent connection
|
||||
add_test_script(load_balancing_pers1 load_balancing load_pers1 LABELS readwritesplit HEAVY REPL_BACKEND)
|
||||
|
||||
# Check load balancing parameters with 10 persistent connections
|
||||
add_test_script(load_balancing_pers10 load_balancing load_pers10 LABELS readwritesplit HEAVY REPL_BACKEND)
|
||||
|
||||
# Test with extremely big blob inserting
|
||||
add_test_executable(longblob.cpp longblob longblob LABELS readwritesplit readconnroute UNSTABLE HEAVY REPL_BACKEND)
|
||||
|
||||
# Test with extremely big blob inserting/selecting with > 16 mb data blocks
|
||||
add_test_executable(mxs1110_16mb.cpp mxs1110_16mb longblob_filters LABELS readwritesplit readconnroute HEAVY REPL_BACKEND)
|
||||
|
||||
# INSERT extremelly big number of rows
|
||||
add_test_executable(lots_of_rows.cpp lots_of_rows galera LABELS readwritesplit HEAVY GALERA_BACKEND)
|
||||
|
||||
# A set of MariaDB server tests executed against Maxscale RWSplit
|
||||
add_test_script(mariadb_tests_hartmut mariadb_tests_hartmut.sh replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# A set of MariaDB server tests executed against Maxscale RWSplit (Galera backend)
|
||||
add_test_script(mariadb_tests_hartmut_galera mariadb_tests_hartmut.sh galera LABELS readwritesplit GALERA_BACKEND)
|
||||
|
||||
# Creates a number of connections > max_connections setting
|
||||
add_test_executable(max_connections.cpp max_connections replication LABELS MySQLAuth MySQLProtocol UNSTABLE HEAVY REPL_BACKEND)
|
||||
|
||||
# Test of Maxinfo interface (http)
|
||||
#add_test_executable(maxinfo.cpp maxinfocpp maxinfo LABELS maxinfo UNSTABLE HEAVY REPL_BACKEND)
|
||||
|
||||
# Test of Maxinfo interface (http), python impelemntation
|
||||
add_test_script(maxinfo.py maxinfo.py maxinfo LABELS maxinfo LIGHT REPL_BACKEND)
|
||||
|
||||
# Checks tha Maxscale processis running as 'maxscale' user
|
||||
add_test_executable(maxscale_process_user.cpp maxscale_process_user replication LABELS maxscale LIGHT REPL_BACKEND)
|
||||
|
||||
# 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)
|
||||
|
||||
# Regression case for the bug "disable_sescmd_history causes MaxScale to crash under load"
|
||||
add_test_executable(mxs127.cpp mxs127 mxs127 LABELS readwritesplit LIGHT REPL_BACKEND)
|
||||
|
||||
# Prepearing and execution statements in the loop
|
||||
add_test_executable(mxs244_prepared_stmt_loop.cpp mxs244_prepared_stmt_loop galera LABELS readwritesplit readconnroute LIGHT GALERA_BACKEND)
|
||||
|
||||
# Regression case for the bug "SELECT INTO OUTFILE query succeeds even if backed fails"
|
||||
add_test_executable(mxs280_select_outfile.cpp mxs280_select_outfile replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Tries prepared stmt 'SELECT 1,1,1,1...." with different nu,ber of '1'
|
||||
add_test_executable(mxs314.cpp mxs314 galera LABELS MySQLProtocol LIGHT GALERA_BACKEND)
|
||||
|
||||
# Creates and closes a lot of connections, checks that 'maxadmin list servers' shows 0 connections at the end
|
||||
add_test_executable(mxs321.cpp mxs321 replication LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Crash with Galera and backend restart when persistant cfonnections are in use
|
||||
add_test_script(mxs361 pers_02 mxs361 mxs361 LABELS maxscale GALERA_BACKEND)
|
||||
|
||||
# Load huge file with 'LOAD DATA LOCAL INFILE'
|
||||
add_test_executable(mxs365.cpp mxs365 replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Connect to Maxscale with user with only 'SELECT' priveledge
|
||||
add_test_executable(mxs37_table_privilege.cpp mxs37_table_privilege replication LABELS MySQLAuth LIGHT REPL_BACKEND)
|
||||
|
||||
# Connect to Maxscale with user with only 'SELECT' priveledge (Galera backend)
|
||||
add_test_script(mxs37_table_privilege_galera mxs37_table_privilege galera LABELS MySQLAuth GALERA_BACKEND)
|
||||
|
||||
# Connect repeatedly to Schema router and execute simple query, check if auth is ok
|
||||
add_test_executable(mxs431.cpp mxs431 sharding LABELS schemarouter REPL_BACKEND BREAKS_REPL)
|
||||
|
||||
# execute SELECT REPEAT('a',i), where 'i' is changing from 1 to 50000 (bug "Session freeze when small tail packet")
|
||||
add_test_executable(mxs47.cpp mxs47 replication LABELS MySQLProtocol LIGHT REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "USE <db> hangs when Tee filter uses matching"
|
||||
add_test_executable(mxs501_tee_usedb.cpp mxs501_tee_usedb mxs501 LABELS tee REPL_BACKEND)
|
||||
|
||||
# Open connection, execute 'change user', close connection in the loop
|
||||
add_test_executable(mxs548_short_session_change_user.cpp mxs548_short_session_change_user mxs548 LABELS MySQLProtocol REPL_BACKEND)
|
||||
|
||||
# Playing with blocking and unblocking Master under load
|
||||
add_test_executable(mxs559_block_master.cpp mxs559_block_master mxs559 LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Playing with blocking and unblocking nodes under INSERT load
|
||||
add_test_executable(mxs564_big_dump.cpp mxs564_big_dump galera_mxs564 LABELS readwritesplit readconnroute GALERA_BACKEND)
|
||||
|
||||
# Executes simple queries from python script in the loop
|
||||
add_test_script(mxs585.py mxs585.py replication LABELS readwritesplit readconnroute UNSTABLE HEAVY REPL_BACKEND)
|
||||
|
||||
# Simple transactions in the loop from python script with client SSL on
|
||||
add_test_script(mxs598.py mxs598.py ssl LABELS MySQLProtocol UNSTABLE HEAVY REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "MaxScale fails to start silently if config file is not readable"
|
||||
add_test_executable(mxs621_unreadable_cnf.cpp mxs621_unreadable_cnf replication LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# playing with 'restart service' and restart Maxscale under load
|
||||
add_test_executable(mxs657_restart.cpp mxs657_restart replication LABELS maxscale HEAVY REPL_BACKEND)
|
||||
add_test_executable(mxs657_restart_service.cpp mxs657_restart_service replication LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# put cyrillic letters to the table and check from backend
|
||||
add_test_executable(mxs682_cyrillic.cpp mxs682_cyrillic replication LABELS maxscale LIGHT REPL_BACKEND)
|
||||
|
||||
# put cyrillic letters to the table and check from backend (Galera backend)
|
||||
add_test_script(mxs682_cyrillic_galera mxs682_cyrillic galera LABELS maxscale GALERA_BACKEND)
|
||||
|
||||
# Connect using different default database using user with database and table level grants
|
||||
add_test_executable(mxs716.cpp mxs716 replication LABELS MySQLAuth LIGHT REPL_BACKEND)
|
||||
|
||||
# MaxScale configuration check functionality test (maxscale -c)
|
||||
add_test_executable(mxs722.cpp mxs722 mxs722 LABELS maxscale LIGHT REPL_BACKEND)
|
||||
|
||||
# Test of 'maxadmin' user Unix accounts enable/disable
|
||||
add_test_executable(mxs729_maxadmin.cpp mxs729_maxadmin replication LABELS MaxAdminAuth LIGHT REPL_BACKEND)
|
||||
|
||||
# Simple connect test in bash, checks that defined in cmd line DB is selected
|
||||
add_test_script(mxs791.sh mxs791.sh replication LABELS UNSTABLE HEAVY REPL_BACKEND)
|
||||
|
||||
# Simple connect test in bash, checks that defined in cmd line DB is selected (Galera backend)
|
||||
add_test_script(mxs791_galera.sh mxs791_galera.sh galera LABELS UNSTABLE HEAVY GALERA_BACKEND)
|
||||
|
||||
# Checks "Current no. of conns" maxadmin output after long blob inserting
|
||||
add_test_executable(mxs812_1.cpp mxs812_1 longblob LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Checks "Current no. of conns" maxadmin output after long blob inserting
|
||||
add_test_executable(mxs812_2.cpp mxs812_2 longblob LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Execute prepared statements while master is blocked, checks "Current no. of conns" after the test
|
||||
add_test_executable(mxs822_maxpasswd.cpp mxs822_maxpasswd maxpasswd LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Do only SELECTS during time > wait_timeout and then do INSERT
|
||||
# This test will fail because the functionality hasn't been implemented
|
||||
add_test_executable(mxs827_write_timeout.cpp mxs827_write_timeout mxs827_write_timeout LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Block and unblock first and second slaves and check that they are recovered
|
||||
add_test_executable(mxs874_slave_recovery.cpp mxs874_slave_recovery mxs874 LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# A set of dynamic configuration tests
|
||||
# Server removal test
|
||||
add_test_executable(mxs922_bad_server.cpp mxs922_bad_server mxs922 LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Server creation test
|
||||
add_test_executable(mxs922_server.cpp mxs922_server mxs922_base LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Monitor creation test
|
||||
add_test_executable(mxs922_monitor.cpp mxs922_monitor mxs922_base LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Double creation of listeners, expect no crash
|
||||
add_test_executable(mxs922_double_listener.cpp mxs922_double_listener mxs922_base LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Test persisting of configuration changes
|
||||
add_test_executable(mxs922_restart.cpp mxs922_restart mxs922 LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Server scaling test
|
||||
add_test_executable(mxs922_scaling.cpp mxs922_scaling mxs922_base LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Dynamic listener SSL test
|
||||
add_test_executable(mxs922_listener_ssl.cpp mxs922_listener_ssl mxs922_base LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Test of MaxRows filter
|
||||
add_test_executable(mxs1071_maxrows.cpp mxs1071_maxrows maxrows LABELS maxrowsfilter REPL_BACKEND)
|
||||
|
||||
# Test of Masking filter
|
||||
add_test_script(masking_mysqltest masking_mysqltest_driver.sh masking_mysqltest LABELS maskingfilter REPL_BACKEND)
|
||||
|
||||
add_test_script(masking_user masking_user.sh masking_mysqltest LABELS maskingfilter REPL_BACKEND)
|
||||
|
||||
# Test of Cache filter
|
||||
add_test_script(cache_basic cache_basic.sh cache_basic LABELS cachefilter REPL_BACKEND)
|
||||
|
||||
# Set utf8mb4 in the backend and restart Maxscale
|
||||
add_test_executable(mxs951_utfmb4.cpp mxs951_utfmb4 replication LABELS REPL_BACKEND)
|
||||
|
||||
# Execute given SQL through readwritesplit (with temporary tables usage)
|
||||
add_test_executable(mxs957.cpp mxs957 replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Regression case for the bug "Defunct processes after maxscale have executed script during failover"
|
||||
add_test_executable(mxs1045.cpp mxs1045 mxs1045 LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# MXS-1123: connect_timeout setting causes frequent disconnects
|
||||
# https://jira.mariadb.org/browse/MXS-1123
|
||||
add_test_executable(mxs1123.cpp mxs1123 mxs1123 LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# 'namedserverfilter' test
|
||||
add_test_executable(namedserverfilter.cpp namedserverfilter namedserverfilter LABELS namedserverfilter LIGHT REPL_BACKEND)
|
||||
|
||||
# Authentication error testing
|
||||
add_test_executable(no_password.cpp no_password replication LABELS MySQLAuth LIGHT REPL_BACKEND)
|
||||
|
||||
# Open and immediatelly close a big number of connections
|
||||
add_test_executable(open_close_connections.cpp open_close_connections replication LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Open and immediatelly close a big number of connections, ssl is in use
|
||||
#
|
||||
# The test is broken due to some problem in the connector. It crashes with a
|
||||
# double free error somewhere deep inside the connector/SSL libraries.
|
||||
#
|
||||
# add_test_script(open_close_connections_ssl open_close_connections ssl LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Persistant connection test
|
||||
add_test_executable(pers_01.cpp pers_01 pers_01 LABELS maxscale REPL_BACKEND GALERA_BACKEND)
|
||||
|
||||
# Test with persistant connections configured and big number iof opened connections ,expect no crash
|
||||
add_test_executable(pers_02.cpp pers_02 pers_01 LABELS maxscale REPL_BACKEND GALERA_BACKEND)
|
||||
|
||||
# Check if prepared statement works via Maxscale (via RWSplit)
|
||||
add_test_executable(prepared_statement.cpp prepared_statement replication LABELS readwritesplit LIGHT REPL_BACKEND)
|
||||
|
||||
# Connect to ReadConn in master mode and check if there is only one backend connection to master
|
||||
add_test_executable(readconnrouter_master.cpp readconnrouter_master replication LABELS readconnroute LIGHT REPL_BACKEND)
|
||||
|
||||
# Creates 100 connections to ReadConn in slave mode and check if connections are distributed among all slaves
|
||||
add_test_executable(readconnrouter_slave.cpp readconnrouter_slave replication LABELS readconnroute LIGHT REPL_BACKEND)
|
||||
|
||||
# Regex filter test
|
||||
add_test_executable(regexfilter1.cpp regexfilter1 regexfilter1 LABELS regexfilter LIGHT REPL_BACKEND)
|
||||
|
||||
# check that Maxscale is reacting correctly on ctrc+c signal and termination does not take ages
|
||||
add_test_script(run_ctrl_c.sh run_ctrl_c.sh replication LABELS maxscale LIGHT REPL_BACKEND)
|
||||
|
||||
# run a set of queries in the loop (see setmix.sql) using Perl client
|
||||
add_test_script(run_session_hang.sh run_session_hang.sh replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Checks changes of COM_SELECT and COM_INSERT after queris to check if RWSplit sends queries to master or to slave depending on if it is write or read only query
|
||||
add_test_executable(rw_select_insert.cpp rw_select_insert replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Checks connections are distributed equaly among backends
|
||||
add_test_executable(rwsplit_conn_num.cpp rwsplit_conn_num repl_lgc LABELS readwritesplit LIGHT REPL_BACKEND)
|
||||
|
||||
# Check that there is one connection to Master and one connection to one of slaves
|
||||
add_test_executable(rwsplit_connect.cpp rwsplit_connect replication LABELS readwritesplit LIGHT REPL_BACKEND)
|
||||
|
||||
# Test of the read-only mode for readwritesplit when master fails (blocked)
|
||||
add_test_executable(rwsplit_readonly.cpp rwsplit_readonly rwsplit_readonly LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Test of the read-only mode for readwritesplit when master fails (blocked), under load
|
||||
add_test_executable(rwsplit_readonly_stress.cpp rwsplit_readonly_stress rwsplit_readonly LABELS readwritesplit HEAVY REPL_BACKEND)
|
||||
|
||||
# Test readwritesplit multi-statement handling
|
||||
add_test_executable(rwsplit_multi_stmt.cpp rwsplit_multi_stmt rwsplit_multi_stmt LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Test readwritesplit multi-statement handling
|
||||
add_test_executable(rwsplit_read_only_trx.cpp rwsplit_read_only_trx rwsplit_read_only_trx LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Test replication-manager with MaxScale
|
||||
add_test_executable(replication_manager.cpp replication_manager replication_manager LABELS maxscale REPL_BACKEND)
|
||||
add_test_executable_notest(replication_manager_2nodes.cpp replication_manager_2nodes replication_manager_2nodes LABELS maxscale REPL_BACKEND)
|
||||
add_test_executable_notest(replication_manager_3nodes.cpp replication_manager_3nodes replication_manager_3nodes LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Schemarouter duplicate database detection test: create DB on all nodes and then try query againt schema router
|
||||
add_test_executable(schemarouter_duplicate_db.cpp schemarouter_duplicate_db schemarouter_duplicate_db LABELS schemarouter REPL_BACKEND)
|
||||
|
||||
# Test of external script execution
|
||||
add_test_executable(script.cpp script script LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# Check if 'weightby' parameter works
|
||||
add_test_executable(server_weight.cpp server_weight galera.weight LABELS readwritesplit readconnroute LIGHT GALERA_BACKEND)
|
||||
|
||||
# Executes a lot of session commands with "disable_sescmd_history=true" and check that memory consumption is not increasing
|
||||
add_test_executable(ses_bigmem.cpp ses_bigmem no_ses_cmd_store LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# test for 'max_sescmd_history' and 'connection_timeout' parameters
|
||||
add_test_executable(session_limits.cpp session_limits session_limits LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Test of schema router
|
||||
add_test_executable(sharding.cpp sharding sharding LABELS schemarouter BREAKS_REPL)
|
||||
|
||||
# MXS-1160: LOAD DATA LOCAL INFILE with schemarouter
|
||||
add_test_executable(sharding_load_data.cpp sharding_load_data sharding LABELS schemarouter BREAKS_REPL)
|
||||
|
||||
# Do short sessions (open conn, short query, close conn) in the loop
|
||||
add_test_executable(short_sessions.cpp short_sessions replication LABELS readwritesplit readconnroute REPL_BACKEND)
|
||||
|
||||
# Do short sessions (open conn, short query, close conn) in the loop, client ssl is ON
|
||||
add_test_script(short_sessions_ssl short_sessions ssl LABELS readwritesplit readconnroute REPL_BACKEND)
|
||||
|
||||
# Regression case for crash if maxadmin 'show monitors' command is issued, but no monitor is not running
|
||||
add_test_executable(show_monitor_crash.cpp show_monitor_crash show_monitor_crash LABELS maxscale)
|
||||
|
||||
# Check how Maxscale works in case of one slave failure, only one slave is configured
|
||||
add_test_executable(slave_failover.cpp slave_failover replication.one_slave LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Execute queries of different size, check data is the same when accessing via Maxscale and directly to backend
|
||||
add_test_executable(sql_queries.cpp sql_queries replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Execute queries of different size, check data is the same when accessing via Maxscale and directly to backend, one persistant connection configured
|
||||
add_test_script(sql_queries_pers1 sql_queries sql_queries_pers1 LABELS maxscale readwritesplit HEAVY REPL_BACKEND)
|
||||
|
||||
# Execute queries of different size, check data is the same when accessing via Maxscale and directly to backend, 10 persistant connections configured
|
||||
add_test_script(sql_queries_pers10 sql_queries sql_queries_pers10 LABELS maxscale readwritesplit HEAVY REPL_BACKEND)
|
||||
|
||||
# Execute queries of different size, check data is the same when accessing via Maxscale and directly to backend, client ssl is ON
|
||||
add_test_script(ssl sql_queries ssl LABELS maxscale readwritesplit REPL_BACKEND)
|
||||
|
||||
# Check load balancing, client ssl is ON
|
||||
add_test_script(ssl_load load_balancing ssl_load LABELS maxscale readwritesplit REPL_BACKEND)
|
||||
|
||||
# Check load balancing, client ssl is ON, Galera backend
|
||||
add_test_script(ssl_load_galera load_balancing_galera ssl_load_galera LABELS maxscale readwritesplit GALERA_BACKEND)
|
||||
|
||||
# Testing slaves who have lost their master and how MaxScale works with them
|
||||
add_test_executable(stale_slaves.cpp stale_slaves replication LABELS mysqlmon REPL_BACKEND)
|
||||
|
||||
# Run sysbech test and block one slave during test execution
|
||||
add_test_executable(sysbench_kill_slave.cpp sysbench_kill_slave replication LABELS UNSTABLE HEAVY REPL_BACKEND)
|
||||
|
||||
# Check temporal tables commands functionality
|
||||
add_test_executable(temporal_tables.cpp temporal_tables replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
# Test routing hints
|
||||
add_test_executable(test_hints.cpp test_hints hints2 LABELS hintfilter LIGHT REPL_BACKEND)
|
||||
|
||||
# Binlogrouter tests, these heavily alter the replication so they are run last
|
||||
add_test_executable(avro.cpp avro avro LABELS avrorouter binlogrouter LIGHT BREAKS_REPL)
|
||||
|
||||
# Test avrorouter file compression
|
||||
add_test_script(avro_compression avro avro_compression LABELS avrorouter binlogrouter LIGHT BREAKS_REPL)
|
||||
|
||||
# In the binlog router setup stop Master and promote one of the Slaves to be new Master
|
||||
add_test_executable(binlog_change_master.cpp binlog_change_master setup_binlog_tx_safe LABELS binlogrouter BREAKS_REPL)
|
||||
|
||||
# trying to start binlog setup with incomplete Maxscale.cnf
|
||||
add_test_executable(binlog_incompl.cpp binlog_incompl binlog_incompl LABELS binlogrouter BREAKS_REPL)
|
||||
|
||||
# configure binlog router setup, execute queries and transactions, check data; install semysync plugin, router options semisync=1,transaction_safety=1
|
||||
add_test_executable(binlog_semisync.cpp binlog_semisync setup_binlog_semisync LABELS binlogrouter HEAVY BREAKS_REPL)
|
||||
|
||||
# configure binlog router setup, execute queries and transactions, check data; install semysync plugin, router options semisync=0,transaction_safety=0
|
||||
add_test_script(binlog_semisync_txs0_ss0 binlog_semisync setup_binlog_semisync_txs0_ss0 LABELS binlogrouter HEAVY BREAKS_REPL)
|
||||
|
||||
# configure binlog router setup, execute queries and transactions, check data; install semysync plugin, router options semisync=0,transaction_safety=1
|
||||
add_test_script(binlog_semisync_txs0_ss1 binlog_semisync setup_binlog_semisync_txs0_ss1 LABELS binlogrouter HEAVY BREAKS_REPL)
|
||||
|
||||
# configure binlog router setup, execute queries and transactions, check data; install semysync plugin, router options semisync=1,transaction_safety=0
|
||||
add_test_script(binlog_semisync_txs1_ss0 binlog_semisync setup_binlog_semisync_txs1_ss0 LABELS binlogrouter HEAVY BREAKS_REPL)
|
||||
|
||||
set_tests_properties(binlog_semisync PROPERTIES TIMEOUT 3600)
|
||||
set_tests_properties(binlog_semisync_txs0_ss0 PROPERTIES TIMEOUT 3600)
|
||||
set_tests_properties(binlog_semisync_txs0_ss1 PROPERTIES TIMEOUT 3600)
|
||||
set_tests_properties(binlog_semisync_txs1_ss0 PROPERTIES TIMEOUT 3600)
|
||||
|
||||
#
|
||||
# The encryption tests don't work as they require the file key management plugin
|
||||
#
|
||||
# Binlog encription test (aes_cbr encryption)
|
||||
#add_test_executable(mxs1073_binlog_enc.cpp mxs1073_binlog_enc binlog_enc_aes_cbc LABELS binlogrouter 10.1 BREAKS_REPL)
|
||||
# Binlog encription test (aes_ctr encryption)
|
||||
#add_test_script(mxs1073_binlog_enc_aes_ctr mxs1073_binlog_enc binlog_enc_aes_ctr LABELS binlogrouter 10.1 BREAKS_REPL)
|
||||
|
||||
# Test of CDC protocol (avro listener)
|
||||
add_test_executable(cdc_client.cpp cdc_client avro LABELS avrorouter binlogrouter BREAKS_REPL)
|
||||
|
||||
# Tries INSERTs with size close to 0x0ffffff * N (with binlog backend)
|
||||
add_test_executable(different_size_binlog.cpp different_size_binlog setup_binlog LABELS binlogrouter HEAVY BREAKS_REPL)
|
||||
|
||||
# Try to configure binlog router to use wrong password for Master and check 'slave status' on binlog
|
||||
add_test_executable(mxs781_binlog_wrong_passwrd.cpp mxs781_binlog_wrong_passwrd setup_binlog LABELS binlogrouter BREAKS_REPL)
|
||||
|
||||
# Regression case for crash if long host name is used for binlog router (in 'change master to ...')
|
||||
add_test_executable(mxs813_long_hostname.cpp mxs813_long_hostname setup_binlog LABELS binlogrouter BREAKS_REPL)
|
||||
|
||||
# configure binlog rouer setup, execute queries and transactions, check data;
|
||||
add_test_executable(setup_binlog.cpp setup_binlog setup_binlog LABELS binlogrouter BREAKS_REPL)
|
||||
|
||||
# configure binlog rouer setup, execute queries and transactions, check data; install semysync plugin, backends started with --binlog-checksum=CRC32 option
|
||||
# disabled because it is included into setup_binlog test, separate test was created for debugging
|
||||
# add_test_executable(setup_binlog_crc_32.cpp setup_binlog_crc_32 setup_binlog LABELS binlogrouter BREAKS_REPL)
|
||||
|
||||
# configure binlog rouer setup, execute queries and transactions, check data; install semysync plugin, backends started with --binlog-checksum=NONE option
|
||||
# disabled because it is included into setup_binlog test, separate test was created for debugging
|
||||
# add_test_executable(setup_binlog_crc_none.cpp setup_binlog_crc_none setup_binlog LABELS binlogrouter LIGHT BREAKS_REPL)
|
||||
|
||||
|
||||
# Creates KDC and tries authrization via GSSAPI (both client and backend)
|
||||
# works only with yum-based distributions
|
||||
# TODO: make it working with zypper and apt, move part of KDC setup to MDBCI
|
||||
add_test_executable(kerberos_setup.cpp kerberos_setup kerberos LABELS HEAVY gssapi REPL_BACKEND)
|
||||
|
||||
|
||||
# enable after fixing MXS-419
|
||||
# add_test_executable(mxs419_lots_of_connections.cpp mxs419_lots_of_connections replication LABELS REPL_BACKEND)
|
||||
|
||||
# TODO: Alter the user_cache test
|
||||
# add_test_executable(user_cache.cpp user_cache user_cache LABELS REPL_BACKEND)
|
||||
|
||||
# https://mariadb.atlassian.net/browse/MXS-576 - it is possible to set negative value for
|
||||
# 'persistpoolmax' without any warning
|
||||
#add_test_executable(bad_pers.cpp bad_pers bad_pers LABELS REPL_BACKEND)
|
||||
|
||||
# Test Aurora RDS monitor
|
||||
add_test_executable(auroramon.cpp auroramon auroramon LABELS HEAVY EXTERNAL_BACKEND)
|
||||
|
||||
# Disabled for the time being
|
||||
# add_test_executable(gatekeeper.cpp gatekeeper gatekeeper LABELS gatekeeper)
|
||||
|
||||
# not implemented, just template
|
||||
#add_test_executable(rw_galera_select_insert.cpp rw_galera_select_insert galera LABELS readwritesplit GALERA_BACKEND)
|
||||
|
||||
# a tool to delete RDS Aurora cluster
|
||||
add_test_executable_notest(delete_rds.cpp delete_rds replication LABELS EXTERN_BACKEND)
|
||||
|
||||
# a tool to create RDS Aurora cluster
|
||||
add_test_executable_notest(create_rds.cpp create_rds replication LABELS EXTERN_BACKEND)
|
||||
|
||||
# start sysbench ageints RWSplit for infinite execution
|
||||
add_test_executable_notest(long_sysbench.cpp long_sysbench replication LABELS readwritesplit REPL_BACKEND)
|
||||
|
||||
configure_file(templates.h.in templates.h @ONLY)
|
||||
|
||||
include(CTest)
|
15
maxscale-system-test/CTestConfig.cmake
Normal file
15
maxscale-system-test/CTestConfig.cmake
Normal file
@ -0,0 +1,15 @@
|
||||
## This file should be placed in the root directory of your project.
|
||||
## Then modify the CMakeLists.txt file in the root directory of your
|
||||
## project to incorporate the testing dashboard.
|
||||
##
|
||||
## # The following are required to submit to the CDash dashboard:
|
||||
## ENABLE_TESTING()
|
||||
## INCLUDE(CTest)
|
||||
|
||||
set(CTEST_PROJECT_NAME "MaxScale")
|
||||
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
|
||||
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "jenkins.engskysql.com")
|
||||
set(CTEST_DROP_LOCATION "/CDash/submit.php?project=MaxScale")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
289
maxscale-system-test/ENV_SETUP.md
Normal file
289
maxscale-system-test/ENV_SETUP.md
Normal file
@ -0,0 +1,289 @@
|
||||
# Build and test environment setup
|
||||
|
||||
### Full build and test environment setup
|
||||
|
||||
<pre>
|
||||
# install ruby
|
||||
sudo apt-get install ruby
|
||||
|
||||
# install all needed libraries
|
||||
sudo apt-get install libxslt-dev libxml2-dev libvirt-dev zlib1g-dev
|
||||
|
||||
# install vagrant
|
||||
# it is also possible to install Vagrant from distribution repository, but in case of problems please use 1.7.2
|
||||
wget https://dl.bintray.com/mitchellh/vagrant/vagrant_1.7.2_x86_64.deb
|
||||
sudo dpkg -i vagrant_1.7.2_x86_64.deb
|
||||
|
||||
# install Vagrant plugins
|
||||
vagrant plugin install vagrant-aws vagrant-libvirt vagrant-mutate
|
||||
|
||||
# get MDBCI, build scripts, descriptions of MDBCI boxes and keys from GitHub
|
||||
git clone https://github.com/OSLL/mdbci.git
|
||||
git clone git@github.com:mariadb-corporation/mdbci-repository-config.git
|
||||
git clone git@github.com:mariadb-corporation/build-scripts-vagrant.git
|
||||
git clone git@github.com:mariadb-corporation/mdbci-boxes
|
||||
|
||||
# Copy scripts and boxes to proper places
|
||||
mv build-scripts-vagrant build-scripts
|
||||
scp -r mdbci-boxes/* mdbci/
|
||||
|
||||
# set proper access rights for ssh keys (for ppc64 machines)
|
||||
chmod 400 mdbci/KEYS/*
|
||||
|
||||
# install all the stuff for test package build
|
||||
sudo apt-get install cmake gcc g++ libssl-dev
|
||||
sudo apt-get install mariadb-client shellcheck
|
||||
|
||||
# install MariaDB development library
|
||||
sudo apt-get install libmariadbclient-dev
|
||||
# Ubuntu repos can contain the sa,e package with different name 'libmariadb-client-lgpl-dev'
|
||||
# but it can not be used to build maxscale-system-test; please use mariadb.org repositories
|
||||
# https://downloads.mariadb.org/mariadb/repositories/
|
||||
# Do not forget to remove all other MariaDB and MySQL packages!
|
||||
|
||||
# install qemu (more info https://en.wikibooks.org/wiki/QEMU/Installing_QEMU)
|
||||
sudo apt-get install qemu qemu-kvm libvirt-bin
|
||||
|
||||
# install virt-manager (if you prefer UI)
|
||||
sudo apt-get install virt-manager
|
||||
|
||||
# install docker (if needed) - see https://docs.docker.com/engine/installation/
|
||||
|
||||
# if cmake from distribution repository is too old it is recommended to build it from latest sources
|
||||
wget https://cmake.org/files/v3.4/cmake-3.4.1.tar.gz # replace 3.4.1 to latest version
|
||||
tar xzvf cmake-3.4.1.tar.gz
|
||||
cd cmake-3.4.1
|
||||
./bootstrap
|
||||
make
|
||||
sudo make install
|
||||
cd
|
||||
|
||||
# sysbench 0.5 should be in sysbench_deb7 directory; it can be built from source:
|
||||
git clone https://github.com/akopytov/sysbench.git
|
||||
cd sysbench
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
cd ..
|
||||
mv sysbench sysbench_deb7
|
||||
|
||||
# for OVH servers it is needed to move 'docker' and 'libvirt' working directories to /home
|
||||
# (replace 'vagrant' to your home directory name)
|
||||
cd /var/lib/
|
||||
sudo mv docker /home/vagrant/
|
||||
sudo ln -s /home/vagrant/docker docker
|
||||
cd libvirt
|
||||
sudo mv images /home/vagrant/
|
||||
sudo ln -s /home/vagrant/images images
|
||||
cd
|
||||
|
||||
# (HACK) in case of problem with building sysbench:
|
||||
scp -r vagrant@maxscale-jenkins.mariadb.com:/home/vagrant/sysbench_deb7 .
|
||||
|
||||
# (HACK) in case of problem with 'dummy' box (problem is caused by MDBCI bug):
|
||||
scp -r vagrant@maxscale-jenkins.mariadb.com:/home/vagrant/.vagrant.d/boxes/dummy .vagrant.d/boxes/
|
||||
|
||||
# MariaDBManager-GPG* files are needed for Maxscale builds in the home directory
|
||||
|
||||
# put AWS keys to aws-config.yml (see https://github.com/OSLL/mdbci/blob/master/aws-config.yml.template)
|
||||
|
||||
# add curent user to the group 'libvirtd'
|
||||
sudo usermod -a -G user_name libvirtd
|
||||
|
||||
# start libvirt default pool
|
||||
virsh pool-start default
|
||||
|
||||
</pre>
|
||||
|
||||
### Setup VMs manually
|
||||
|
||||
#### Empty virtual machine
|
||||
|
||||
Following template can be used to create empty VM (for qemu machines):
|
||||
<pre>
|
||||
{
|
||||
"cookbook_path" : "../recipes/cookbooks/",
|
||||
"build" :
|
||||
{
|
||||
"hostname" : "default",
|
||||
"box" : "###box###",
|
||||
"product" : {
|
||||
"name" : "packages"
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
for AWS machines:
|
||||
<pre>
|
||||
{
|
||||
"cookbook_path" : "../recipes/cookbooks/",
|
||||
"aws_config" : "../aws-config.yml",
|
||||
"build" :
|
||||
{
|
||||
"hostname" : "build",
|
||||
"box" : "###box###"
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
Following boxes are availabe:
|
||||
* qemu: debian_7.5_libvirt, ubuntu_trusty_libvirt, centos_7.0_libvirt, centos_6.5_libvirt
|
||||
* AWS: rhel5, rhel6, rhel7, sles11, sles12, fedora20, fedora21, fediora22, ubuntu_wily, ubuntu_vivid, centos7, deb_jessie
|
||||
|
||||
#### Maxscale and backend machines creation
|
||||
|
||||
* Generation of Maxscale repository description
|
||||
It is necessary to generate descriptions of MariaDB and Maxscale repositories before bringin up Maxscale machine with Vagrant
|
||||
<pre>
|
||||
export ci_url="http://my_repository_site.com/repostory/"
|
||||
~/mdbci-repository-config/generate_all.sh $repo_dir
|
||||
~/mdbci-repository-config/maxscale-ci.sh $target $repo_dir
|
||||
</pre>
|
||||
where
|
||||
<pre>
|
||||
$repo_dir - directory where repository descriptions will be created
|
||||
$target - directory with MaxScale packages in the repositoy
|
||||
</pre>
|
||||
example:
|
||||
<pre>
|
||||
export ci_url="http://max-tst-01.mariadb.com/ci-repository/"
|
||||
~/mdbci-repository-config/generate_all.sh repo.d
|
||||
~/mdbci-repository-config/maxscale-ci.sh develop repo.d
|
||||
</pre>
|
||||
More information can be found in the [MDBCI documentation](https://github.com/OSLL/mdbci#repod-files) and in the [mdbci-repository-config documentaion](https://github.com/mariadb-corporation/mdbci-repository-config#mdbci-repository-config)
|
||||
|
||||
* Preparing configuration description
|
||||
Virtual machines should be described in JSON format. Example template can be found in the [build-scripts package](https://github.com/mariadb-corporation/build-scripts-vagrant/blob/master/test/template.libvirt.json).
|
||||
|
||||
MariaDB machine description example:
|
||||
<pre>
|
||||
"node0" :
|
||||
{
|
||||
"hostname" : "node0",
|
||||
"box" : "centos_7.0_libvirt",
|
||||
"product" : {
|
||||
"name": "mariadb",
|
||||
"version": "10.0",
|
||||
"cnf_template" : "server1.cnf",
|
||||
"cnf_template_path": "~/build-scripts/test-setup-scripts/cnf"
|
||||
}
|
||||
|
||||
}
|
||||
</pre>
|
||||
|
||||
"cnf_template" defines .cnf file which will be places into MariaDB machine. [build-scripts package](https://github.com/mariadb-corporation/build-scripts-vagrant/tree/master/test-setup-scripts/cnf) contains examples of .cnf files.
|
||||
|
||||
MariaDB Galera machine description example:
|
||||
<pre>
|
||||
"galera0" :
|
||||
{
|
||||
"hostname" : "galera0",
|
||||
"box" : "centos_7.0_libvirt",
|
||||
"product" : {
|
||||
"name": "galera",
|
||||
"version": "10.0",
|
||||
"cnf_template" : "galera_server1.cnf",
|
||||
"cnf_template_path": "~/build-scripts/test-setup-scripts/cnf"
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
For Galera machines MDBCI automatically puts following information into .cnf file:
|
||||
|
||||
|field|description|
|
||||
|------|----|
|
||||
|###NODE-ADDRESS###|IP address of the node (for AWS - private IP)|
|
||||
|###NODE-NAME###|Replaces by node name ("node0" in this example)|
|
||||
|###GALERA-LIB-PATH###|Path to the Galera library file (.so file)|
|
||||
|
||||
Example of Maxscale machine description:
|
||||
<pre>
|
||||
"maxscale" :
|
||||
{
|
||||
"hostname" : "maxscale",
|
||||
"box" : "centos_7.0_libvirt",
|
||||
"product" : {
|
||||
"name": "maxscale"
|
||||
}
|
||||
|
||||
}
|
||||
</pre>
|
||||
|
||||
#### Generation configuration and bringing machines up
|
||||
|
||||
After creation machines description JSON two steps are needed.
|
||||
|
||||
1. Generate configuration
|
||||
<pre>
|
||||
./mdbci --override --template $template_name.json --repo-dir $repo_dir generate $name
|
||||
</pre>
|
||||
|
||||
where
|
||||
|
||||
|variable|description|
|
||||
|----|----|
|
||||
|$template_name|name of machines descripiton JSON file|
|
||||
|$repo_dir|directory with repositories description generated by mdbci-repository-config (repo.d)|
|
||||
|$name|name of test configuration; will be used as directory name for Vagrant files|
|
||||
|
||||
2. Bringing machines up
|
||||
<pre>
|
||||
./mdbci up $name
|
||||
</pre>
|
||||
|
||||
#### Configuring DB users
|
||||
|
||||
Automatic DB users is not implemented yet, so it have to be done manually. See [setup_repl.sh](https://github.com/mariadb-corporation/build-scripts-vagrant/blob/master/test-setup-scripts/setup_repl.sh) and [setup_galera.sh](https://github.com/mariadb-corporation/build-scripts-vagrant/blob/master/test-setup-scripts/galera/setup_galera.sh) for details.
|
||||
|
||||
Any test from 'maxscale-system-test' checks Master/Slave and Galera configurations and restores them if they are broken, but it works only if DB users are created.
|
||||
|
||||
TODO: add it into 'maxscale-system-test'
|
||||
|
||||
### Access VMs
|
||||
|
||||
MDBCI provides a number of commands to get information about running vrtial machines. See [MDBCI documentation](https://github.com/OSLL/mdbci#mdbci-syntax) for details.
|
||||
|
||||
[set_env_vagrant.sh script](https://github.com/mariadb-corporation/build-scripts-vagrant/blob/master/test/set_env_vagrant.sh) defines environmental variables needed by 'maxscale-system-test'. The same variables can be used to access VMs manually.
|
||||
|
||||
Script have to be executed fro 'mbdci' directory. Do not forget '.':
|
||||
<pre>
|
||||
cd ~/mdbci/
|
||||
. ../build-scripts/test/set_env_vagrant.sh $name
|
||||
</pre>
|
||||
|
||||
After it virual machines can be accessed via ssh, for example:
|
||||
<pre>
|
||||
ssh -i $maxscale_sshkey $maxscale_access_user@$maxscale_IP
|
||||
</pre>
|
||||
|
||||
Another way is to use 'vagrant ssh':
|
||||
<pre>
|
||||
cd ~/mdbci/$name/
|
||||
vagrant ssh <node_name>
|
||||
</pre>
|
||||
|
||||
MDBCI can give IP address, path to ssh key:
|
||||
<pre>
|
||||
./mdbci show network <configuration_name>/<node_name> --silent
|
||||
./mdbci show keyfile <configuration_name>/<node_name> --silent
|
||||
./mdbci ssh --command 'whoami' <configuration_name>/<node_name> --silent
|
||||
</pre>
|
||||
|
||||
Node name for build machine is 'build'
|
||||
|
||||
Nodes names for typical test setup are node0, ..., node3, galera0, ..., galera3, maxscale
|
||||
|
||||
Example:
|
||||
<pre>
|
||||
./mdbci show network centos6_vm01/build --silent
|
||||
./mdbci show keyfile centos6_vm01/build --silent
|
||||
./mdbci ssh --command 'whoami' centos6_vm01/build --silent
|
||||
</pre>
|
||||
|
||||
### Destroying configuration
|
||||
|
||||
<pre>
|
||||
cd ~/mdbci/$name
|
||||
vagrant destroy -f
|
||||
</pre>
|
204
maxscale-system-test/HOW_TO_WRITE_TEST.md
Normal file
204
maxscale-system-test/HOW_TO_WRITE_TEST.md
Normal file
@ -0,0 +1,204 @@
|
||||
# Creating a test case
|
||||
|
||||
This document describes basic principles of test case creation and provides list of basic usefull functions and properties.
|
||||
For detailed function and properties description and thier full list please see documetation generated by Doxygen.
|
||||
|
||||
## Test case basics
|
||||
|
||||
For every test case following should be created:
|
||||
- test executable
|
||||
- record in the 'templates' file
|
||||
- Maxscale configuration template (if test requires special Maxscale configuration)
|
||||
- [CMakeLists.txt](CMakeLists.txt) record:
|
||||
- add_test_executable(<source.cpp> <binary_name> <cnf_template_name>)
|
||||
- 'set_tests_properties' if test should be added to the group or bigger timeout should be defined (> default 1800s)
|
||||
|
||||
## 'templates' file
|
||||
|
||||
'templates' file contains information about Maxscale configuration template for every test in plain text format:
|
||||
|
||||
\<test_executable_name\> \<suffix_of_cnf_template\>
|
||||
|
||||
Template itself should be:
|
||||
|
||||
cnf/maxscale.cnf.template.\<suffix_of_cnf_template\>
|
||||
|
||||
## Maxscale configuration template
|
||||
|
||||
All templates are in cnf/ directory:
|
||||
|
||||
cnf/maxscale.cnf.template.\<suffix_of_cnf_template\>
|
||||
|
||||
Template can contain following varables:
|
||||
|
||||
|Variable|Maeaning|
|
||||
|--------|--------|
|
||||
|###threads###| Number of Maxscale treads|
|
||||
|###node_server_IP_N###|IP of Master/Slave node N|
|
||||
|###node_server_port_N###|port of Master/Slave node N|
|
||||
|###galera_server_IP_N###|IP of Galera node N|
|
||||
|###galera_server_port_N###|port of Galera node N|
|
||||
|
||||
## Test creation principles
|
||||
|
||||
* start from initializing of an object of TestConnections class
|
||||
* set timeout before every operation which can got stuck, do not forget to disable timeout before long sleep()
|
||||
* use TestConnections::tprintf function to print test log
|
||||
* use TestConnections::add_result() to idicate test failure and print explanation message
|
||||
* execute TestConnections::copy_all_logs at the end of test
|
||||
* return TestConnections::global_result value
|
||||
* do not leave any node blocked by firewall
|
||||
|
||||
## Class TestConnections
|
||||
|
||||
This class contains all information about Maxscale node and about all backend nodes as well as a set of functions
|
||||
to handle Maxscale and backends, interact with Maxscale routers and Maxadmin.
|
||||
Here is only list of main functions, for all details see Doxygen comments in [testconnections.h](testconnections.h)
|
||||
|
||||
Currently two backend sets are supported (represented by Mariadb_nodes class objects): 'repl' and 'galera'
|
||||
- contains all info and operations for Master/Slave and Galera setups
|
||||
(see Doxygen comments in [mariadb_nodes.h](mariadb_nodes.h) )
|
||||
|
||||
It is assumed that following routers+listers are configured
|
||||
|
||||
|Router|Port|
|
||||
|------|----|
|
||||
|RWSplit|4006|
|
||||
|ReadConn master|4008|
|
||||
|ReadConn Slave|4009|
|
||||
|binlog|5306|
|
||||
|test case -specific|4016|
|
||||
|
||||
### Most important fuctions and variables
|
||||
|
||||
Please check Doxygen comments for details
|
||||
|
||||
#### TestConnections(int argc, char *argv[]);
|
||||
|
||||
* reads all information from environmental variables
|
||||
* checks backends, if broken - does one attempt to restore
|
||||
* create maxscale.cnf out of template and copy it to Maxscale node
|
||||
* create needed directories, set access righs for them, cleanup logs, coredumps
|
||||
* start Maxscale
|
||||
* initialize internal structures
|
||||
|
||||
#### Timeout functions
|
||||
|
||||
int set_timeout(int timeout_seconds)
|
||||
stop_timeout()
|
||||
|
||||
If after set_timeout() a new call of set_timeout() or stop_timeout() is not done the test execution terminated,
|
||||
logs from Maxscale are copied to host.
|
||||
|
||||
#### Open connection functions
|
||||
|Function|Short description|
|
||||
|----|---|
|
||||
| int connect_maxscale();<br> int connect_rwsplit();<br> int connect_readconn_master();<br> int connect_maxscale_slave();|store MYSQL handler in TestConnections object (only one cnnection can be created by them, second call leads to MYSQL handler leak)|
|
||||
|MYSQL * open_rwsplit_connection() <br> MYSQL * open_readconn_master_connection() <br> MYSQL * open_readconn_slave_connection() |returns MYSQL handler (can be used to create a number of connections to each router)|
|
||||
| int create_connections(int conn_N) |- open and then close N connections to each router|
|
||||
|
||||
A number of useful wrappers for mysql_real_connect() are not included into TestConnections class, but
|
||||
they are availve from [mariadb_func.h](mariadb_func.h)
|
||||
|
||||
#### Backend check and setup functions
|
||||
|Function|Short description|
|
||||
|----|---|
|
||||
|start_replication()|Configure nodes from 'repl' object as Master/Slave|
|
||||
|start_galera()|Configure nodes from 'galera'|
|
||||
|start_binlog()|Configure nodes from 'repl' in following way: node0 - Master, node1 - slave of node0, all others - slaves of Maxscale binlog router|
|
||||
|start_mm()|Configure nodes from 'repl' in multimuster setup|
|
||||
|
||||
#### Result reporting functions
|
||||
|Function|Short description|
|
||||
|----|---|
|
||||
|add_result()|failure printing, increase global_result|
|
||||
|tprint()| printing with timestamp|
|
||||
|copy_logs()|copy Maxscale log, maxscale.cnf file and core dump from Maxscale machine to current directory|
|
||||
|
||||
#### Different checks functions
|
||||
|Function|Short description|
|
||||
|----|---|
|
||||
|try_query()|try SQL query and print error message in case of failure, increase global_result|
|
||||
|check_t1_table()|check if t1 present in give DB|
|
||||
|test_maxscale_connections|check status of connections to RWSplit, ReadConn master, ReadConn slave routers|
|
||||
|check_maxscale_alive()|Check if RWSplit, ReadConn master, ReadConn slave routers are alive|
|
||||
|check_log_err()|Check Maxscale log for presence of absence of specific string|
|
||||
|find_connected_slave|find first slave that have connections from Maxscale|
|
||||
|
||||
#### Maxscale machine control functions
|
||||
|Function|Short description|
|
||||
|----|---|
|
||||
|start_maxscale()||
|
||||
|stop_maxscale()||
|
||||
|restart_maxscale()||
|
||||
|execute_ssh_maxscale()|execute command on Maxscale node via ssh|
|
||||
|
||||
#### Properties
|
||||
|Name|Short description|Corresponding env variable|
|
||||
|----|-----|----|
|
||||
|global_result|0 if there is not single failure during the test| - |
|
||||
|repl|Mariadb_nodes object for Master/Slave nodes| - |
|
||||
|galera|Mariadb_nodes object for Galera nodes| - |
|
||||
|smoke|do short tests if TRUE|smoke|
|
||||
|maxscale_IP|IP address of Maxscale machine|maxscale_IP|
|
||||
|maxscale_user|DB user name to access via Maxscale|maxscale_user|
|
||||
|maxscale_password|password for MaxscaleDB user|maxscale_password|
|
||||
|maxadmin_password|password for MaxAdmin interface (user name is hard coded 'admin')|maxadmin_password|
|
||||
|conn_rwsplit|MYSQL handler of connections to RWSplit router| - |
|
||||
|conn_master|MYSQL handler of connections to ReadConn router in master mode| - |
|
||||
|conn_slave|MYSQL handler of connections to ReadConn router in master mode| - |
|
||||
|
||||
### Mariadb_nodes class
|
||||
|
||||
#### Master/Slave and Galera setup and check
|
||||
|Function|Short description|
|
||||
|----|---|
|
||||
|start_replication()|Configure nodes from 'repl' object as Master/Slave|
|
||||
|start_galera()|Configure nodes from 'galera'|
|
||||
|set_slave()|execute CHANGE MASTER TO agains the node|
|
||||
|check_replication()|Check if 'repl' nodes are properly configured as Master/Slave|
|
||||
|check_galera()|Check if 'galera' nodes are are properly configured as Galera cluster|
|
||||
|change_master|Make another node to be a master|
|
||||
|
||||
#### Connections functions
|
||||
|Function|Short description|
|
||||
|----|---|
|
||||
|connect()|open connections to all nodes, store MYSQL handlers in internal variable, second call leads to handlers leak|
|
||||
|close_connections()|close connections to all nodes|
|
||||
|
||||
#### Nodes control functions
|
||||
|Function|Short description|
|
||||
|----|---|
|
||||
|block_node()|block MariaDB server on the node by firawall|
|
||||
|unblock_node()|unblock MariaDB server on the node by firawall|
|
||||
|unblock_all_nodes()|unblock MariaDB server on all nodes by firawall|
|
||||
|stop_node()|stop MariaDB server on the node|
|
||||
|start node()|start MariaDB server on the node|
|
||||
|restart_node()|stop and restart MariaDB server on the node|
|
||||
|check_node()|check if MariaDB server on the node is alive|
|
||||
|check_and_restart_node()|check if MariaDB server on the node is alive and restart it if it is not alive|
|
||||
|stop_nodes()|stop MariaDB server on all nodes|
|
||||
|ssh_node()|Execute command on the node via ssh, return error code|
|
||||
|ssh_node_output()|Same as ssh_nodE(), but return command output|
|
||||
|flush_hosts()|Execute 'mysqladmin flush-hosts' on all nodes|
|
||||
|execute_query_all_nodes()|Execute same query on all nodes|
|
||||
|
||||
#### Properties
|
||||
|Name|Short description|Corresponding env variable|
|
||||
|----|-----|----|
|
||||
|N|Number of nodes|node_N <br> galera_N|
|
||||
|user_name|DB user name|node_user <br> galera_user|
|
||||
|password|password for DB user|node_password <br> galera_password|
|
||||
|IP[ ]|IP address of the node|node_XXX <br> galera_XXX|
|
||||
|IP_private[ ]|private IP of the node (for AWS nodes)|node_private_XXX <br> galera_private_XXX|
|
||||
|port[ ]|MariaDB port for the node|node_port_XXX <br> galera_port_XXX|
|
||||
|nodes[ ]|MYSQL handler| - |
|
||||
|
||||
### Maxadmin operations functions
|
||||
[maxadmin_operations.h](maxadmin_operations.h) contains fuctions to communicate to Maxscale via MaxAdmin interface
|
||||
|
||||
|Function|Short description|
|
||||
|----|---|
|
||||
|execute_maxadmin_command()|send MaxAdmin command to Maxscale|
|
||||
|execute_maxadmin_command_print()|send MaxAdmin command to Maxscale and print reply|
|
||||
|get_maxadmin_param()|send MaxAdmin command to Maxscale and try to find the value of given parameter in output|
|
@ -0,0 +1,6 @@
|
||||
BEGIN;
|
||||
SELECT (@@server_id) INTO @a;
|
||||
SELECT @a;
|
||||
@a
|
||||
####server_id####
|
||||
COMMIT;
|
@ -0,0 +1,8 @@
|
||||
USE test;
|
||||
drop table if exists t1;
|
||||
create table t1 (id integer);
|
||||
set autocommit=0;
|
||||
begin;
|
||||
insert into t1 values(1);
|
||||
commit;
|
||||
drop table t1;
|
@ -0,0 +1,4 @@
|
||||
USE test;
|
||||
SELECT IF(@@server_id <> @TMASTER_ID,'OK (slave)','FAIL (master)') AS result;
|
||||
result
|
||||
OK (slave)
|
@ -0,0 +1,9 @@
|
||||
USE test;
|
||||
drop table if exists t1;
|
||||
create table t1 (id integer);
|
||||
set autocommit=0;
|
||||
insert into t1 values(1);
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
1
|
||||
drop table t1;
|
@ -0,0 +1,9 @@
|
||||
USE test;
|
||||
drop table if exists t1;
|
||||
create table t1 (id integer);
|
||||
set autocommit=OFF;
|
||||
insert into t1 values(1);
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
1
|
||||
drop table t1;
|
@ -0,0 +1,11 @@
|
||||
USE test;
|
||||
drop table if exists t1;
|
||||
create table t1 (id integer);
|
||||
set autocommit=0;
|
||||
begin;
|
||||
insert into t1 values(1);
|
||||
commit;
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
1
|
||||
drop table t1;
|
@ -0,0 +1,11 @@
|
||||
USE test;
|
||||
drop table if exists t1;
|
||||
create table t1 (id integer);
|
||||
set autocommit=0;
|
||||
begin;
|
||||
insert into t1 values(1);
|
||||
commit;
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
1
|
||||
drop table t1;
|
@ -0,0 +1,11 @@
|
||||
USE test;
|
||||
DROP DATABASE If EXISTS FOO;
|
||||
SET autocommit=1;
|
||||
BEGIN;
|
||||
CREATE DATABASE FOO;
|
||||
SELECT (@@server_id) INTO @a;
|
||||
SELECT IF(@a <> @TMASTER_ID,'OK (slave)','FAIL (master)') AS result;
|
||||
result
|
||||
OK (slave)
|
||||
DROP DATABASE FOO;
|
||||
COMMIT;
|
@ -0,0 +1,17 @@
|
||||
USE test;
|
||||
DROP TABLE IF EXISTS T1;
|
||||
DROP EVENT IF EXISTS myevent;
|
||||
SET autocommit=1;
|
||||
BEGIN;
|
||||
CREATE TABLE T1 (id integer);
|
||||
CREATE EVENT myevent
|
||||
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
|
||||
DO
|
||||
UPDATE t1 SET id = id + 1;
|
||||
SELECT (@@server_id) INTO @a;
|
||||
SELECT IF(@a <> @TMASTER_ID,'OK (slave)','FAIL (master)') AS result;
|
||||
result
|
||||
OK (slave)
|
||||
DROP TABLE T1;
|
||||
DROP EVENT myevent;
|
||||
COMMIT;
|
@ -0,0 +1,11 @@
|
||||
USE test;
|
||||
DROP TABLE IF EXISTS T1;
|
||||
SET autocommit=1;
|
||||
BEGIN;
|
||||
CREATE TABLE T1 (id integer);
|
||||
SELECT (@@server_id) INTO @a;
|
||||
SELECT IF(@a <> @TMASTER_ID,'OK (slave)','FAIL (master)') AS result;
|
||||
result
|
||||
OK (slave)
|
||||
DROP TABLE T1;
|
||||
COMMIT;
|
@ -0,0 +1,14 @@
|
||||
USE test;
|
||||
DROP PROCEDURE IF EXISTS simpleproc;
|
||||
SET autocommit=1;
|
||||
BEGIN;
|
||||
CREATE PROCEDURE simpleproc (OUT param1 INT)
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO param1 FROM t;
|
||||
END //
|
||||
SELECT (@@server_id) INTO @a;
|
||||
SELECT IF(@a <> @TMASTER_ID,'OK (slave)','FAIL (master)') AS result;
|
||||
result
|
||||
OK (slave)
|
||||
DROP PROCEDURE simpleproc;
|
||||
COMMIT;
|
@ -0,0 +1,13 @@
|
||||
USE test;
|
||||
DROP FUNCTION IF EXISTS hello;
|
||||
SET autocommit=1;
|
||||
BEGIN;
|
||||
CREATE FUNCTION hello (s CHAR(20))
|
||||
RETURNS CHAR(50) DETERMINISTIC
|
||||
RETURN CONCAT('Hello, ',s,'!');
|
||||
SELECT (@@server_id) INTO @a;
|
||||
SELECT IF(@a <> @TMASTER_ID,'OK (slave)','FAIL (master)') AS result;
|
||||
result
|
||||
OK (slave)
|
||||
DROP FUNCTION hello;
|
||||
COMMIT;
|
@ -0,0 +1,12 @@
|
||||
USE test;
|
||||
DROP TABLE IF EXISTS T1;
|
||||
CREATE TABLE T1 (id integer);
|
||||
SET autocommit=1;
|
||||
BEGIN;
|
||||
CREATE INDEX foo_t1 on T1 (id);
|
||||
SELECT (@@server_id) INTO @a;
|
||||
SELECT IF(@a <> @TMASTER_ID,'OK (slave)','FAIL (master)') AS result;
|
||||
result
|
||||
OK (slave)
|
||||
DROP TABLE T1;
|
||||
COMMIT;
|
@ -0,0 +1,6 @@
|
||||
use test;
|
||||
set autocommit=1;
|
||||
use mysql;
|
||||
select count(*) from user where user='skysql';
|
||||
count(*)
|
||||
2
|
@ -0,0 +1,15 @@
|
||||
USE test;
|
||||
DROP TABLE IF EXISTS myCity;
|
||||
SET autocommit = 0;
|
||||
START TRANSACTION;
|
||||
CREATE TABLE myCity (a int, b char(20));
|
||||
INSERT INTO myCity VALUES (1, 'Milan');
|
||||
INSERT INTO myCity VALUES (2, 'London');
|
||||
COMMIT;
|
||||
START TRANSACTION;
|
||||
DELETE FROM myCity;
|
||||
SELECT COUNT(*) FROM myCity;
|
||||
COUNT(*)
|
||||
0
|
||||
COMMIT;
|
||||
DROP TABLE myCity;
|
@ -0,0 +1,15 @@
|
||||
USE test;
|
||||
DROP TABLE IF EXISTS myCity;
|
||||
SET autocommit = Off;
|
||||
START TRANSACTION;
|
||||
CREATE TABLE myCity (a int, b char(20));
|
||||
INSERT INTO myCity VALUES (1, 'Milan');
|
||||
INSERT INTO myCity VALUES (2, 'London');
|
||||
COMMIT;
|
||||
START TRANSACTION;
|
||||
DELETE FROM myCity;
|
||||
SELECT COUNT(*) FROM myCity;
|
||||
COUNT(*)
|
||||
0
|
||||
COMMIT;
|
||||
DROP TABLE myCity;
|
@ -0,0 +1,13 @@
|
||||
USE test;
|
||||
DROP TABLE IF EXISTS myCity;
|
||||
SET autocommit = 0;
|
||||
CREATE TABLE myCity (a int, b char(20));
|
||||
INSERT INTO myCity VALUES (1, 'Milan');
|
||||
INSERT INTO myCity VALUES (2, 'London');
|
||||
COMMIT;
|
||||
DELETE FROM myCity;
|
||||
SELECT COUNT(*) FROM myCity;
|
||||
COUNT(*)
|
||||
0
|
||||
COMMIT;
|
||||
DROP TABLE myCity;
|
@ -0,0 +1,13 @@
|
||||
USE test;
|
||||
DROP TABLE IF EXISTS myCity;
|
||||
SET autocommit = oFf;
|
||||
CREATE TABLE myCity (a int, b char(20));
|
||||
INSERT INTO myCity VALUES (1, 'Milan');
|
||||
INSERT INTO myCity VALUES (2, 'London');
|
||||
COMMIT;
|
||||
DELETE FROM myCity;
|
||||
SELECT COUNT(*) FROM myCity;
|
||||
COUNT(*)
|
||||
0
|
||||
COMMIT;
|
||||
DROP TABLE myCity;
|
@ -0,0 +1,5 @@
|
||||
--disable_query_log
|
||||
--disable_result_log
|
||||
SELECT SLEEP(5);
|
||||
--enable_result_log
|
||||
--enable_query_log
|
@ -0,0 +1,11 @@
|
||||
--source testconf.inc
|
||||
USE test;
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
create table t1 (id integer);
|
||||
set autocommit=0; # open transaction
|
||||
begin;
|
||||
insert into t1 values(1); # write to master
|
||||
commit;
|
||||
drop table t1;
|
@ -0,0 +1,3 @@
|
||||
--source testconf.inc
|
||||
USE test;
|
||||
SELECT IF(@@server_id <> @TMASTER_ID,'OK (slave)','FAIL (master)') AS result;
|
@ -0,0 +1,11 @@
|
||||
--source testconf.inc
|
||||
USE test;
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
create table t1 (id integer);
|
||||
set autocommit=0; # open transaction
|
||||
insert into t1 values(1); # write to master
|
||||
select count(*) from t1; # read from master
|
||||
drop table t1;
|
@ -0,0 +1,11 @@
|
||||
--source testconf.inc
|
||||
USE test;
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
create table t1 (id integer);
|
||||
set autocommit=OFF; # open transaction
|
||||
insert into t1 values(1); # write to master
|
||||
select count(*) from t1; # read from master
|
||||
drop table t1;
|
@ -0,0 +1,13 @@
|
||||
--source testconf.inc
|
||||
USE test;
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
create table t1 (id integer);
|
||||
set autocommit=0; # open transaction
|
||||
begin;
|
||||
insert into t1 values(1); # write to master
|
||||
commit;
|
||||
select count(*) from t1; # read from master since autocommit is disabled
|
||||
drop table t1;
|
@ -0,0 +1,13 @@
|
||||
--source testconf.inc
|
||||
USE test;
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
create table t1 (id integer);
|
||||
set autocommit=0; # open transaction
|
||||
begin;
|
||||
insert into t1 values(1); # write to master
|
||||
commit;
|
||||
select count(*) from t1; # read from master since autocommit is disabled
|
||||
drop table t1;
|
@ -0,0 +1,4 @@
|
||||
use test;
|
||||
set autocommit=1;
|
||||
use mysql;
|
||||
select count(*) from user where user='skysql';
|
@ -0,0 +1,16 @@
|
||||
--source testconf.inc
|
||||
USE test;
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS myCity;
|
||||
--enable_warnings
|
||||
SET autocommit = 0;
|
||||
START TRANSACTION;
|
||||
CREATE TABLE myCity (a int, b char(20));
|
||||
INSERT INTO myCity VALUES (1, 'Milan');
|
||||
INSERT INTO myCity VALUES (2, 'London');
|
||||
COMMIT;
|
||||
START TRANSACTION;
|
||||
DELETE FROM myCity;
|
||||
SELECT COUNT(*) FROM myCity; # read transaction's modifications from master
|
||||
COMMIT;
|
||||
DROP TABLE myCity;
|
@ -0,0 +1,16 @@
|
||||
--source testconf.inc
|
||||
USE test;
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS myCity;
|
||||
--enable_warnings
|
||||
SET autocommit = Off;
|
||||
START TRANSACTION;
|
||||
CREATE TABLE myCity (a int, b char(20));
|
||||
INSERT INTO myCity VALUES (1, 'Milan');
|
||||
INSERT INTO myCity VALUES (2, 'London');
|
||||
COMMIT;
|
||||
START TRANSACTION;
|
||||
DELETE FROM myCity;
|
||||
SELECT COUNT(*) FROM myCity; # read transaction's modifications from master
|
||||
COMMIT;
|
||||
DROP TABLE myCity;
|
@ -0,0 +1,16 @@
|
||||
--source testconf.inc
|
||||
USE test;
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS myCity;
|
||||
--enable_warnings
|
||||
|
||||
SET autocommit = 0;
|
||||
CREATE TABLE myCity (a int, b char(20));
|
||||
INSERT INTO myCity VALUES (1, 'Milan');
|
||||
INSERT INTO myCity VALUES (2, 'London');
|
||||
COMMIT;
|
||||
DELETE FROM myCity; # implicit transaction started
|
||||
SELECT COUNT(*) FROM myCity; # read transaction's modifications from master
|
||||
COMMIT;
|
||||
|
||||
DROP TABLE myCity;
|
@ -0,0 +1,16 @@
|
||||
--source testconf.inc
|
||||
USE test;
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS myCity;
|
||||
--enable_warnings
|
||||
|
||||
SET autocommit = oFf;
|
||||
CREATE TABLE myCity (a int, b char(20));
|
||||
INSERT INTO myCity VALUES (1, 'Milan');
|
||||
INSERT INTO myCity VALUES (2, 'London');
|
||||
COMMIT;
|
||||
DELETE FROM myCity; # implicit transaction started
|
||||
SELECT COUNT(*) FROM myCity; # read transaction's modifications from master
|
||||
COMMIT;
|
||||
|
||||
DROP TABLE myCity;
|
127
maxscale-system-test/JENKINS.md
Normal file
127
maxscale-system-test/JENKINS.md
Normal file
@ -0,0 +1,127 @@
|
||||
# Jenkins
|
||||
|
||||
## List of Jenkins installations
|
||||
|
||||
| URL | Description |
|
||||
|----|----|
|
||||
|[max-tst-01.mariadb.com:8089](http://max-tst-01.mariadb.com:8089)|AWS, qemu; Regular testing for different MariaDB versions, different Linux distributions, Developers testing|
|
||||
|[maxscale-jenkins.mariadb.com:8089/](http://maxscale-jenkins.mariadb.com:8089/)|AWS, VBox; Regular builds for all distributions, build for Coverity, regular test VBox+CentOS6+MariaDB5.5|
|
||||
|[maxscale-jenkins.mariadb.com:8090](http://maxscale-jenkins.mariadb.com:8090/)|MDBCI testing and debugging, Jenkins experiments|
|
||||
|
||||
## Basic Jenkins jobs
|
||||
|
||||
### [max-tst-01.mariadb.com:8089](http://max-tst-01.mariadb.com:8089)
|
||||
|
||||
| Job | Description |
|
||||
|----|----|
|
||||
|[build_and_test](http://max-tst-01.mariadb.com:8089/view/test/job/build_and_test/)|Build Maxscale and run systems tests|
|
||||
|[run_test](http://max-tst-01.mariadb.com:8089/view/test/job/run_test/)|Run system tests, Maxscale package should be in the repository|
|
||||
|[build](http://max-tst-01.mariadb.com:8089/job/build/build)|Build Maxscale, create repository and publish it to [http://max-tst-01.mariadb.com/ci-repository/](http://max-tst-01.mariadb.com/ci-repository/)|
|
||||
|[run_test_no_env_rebuild](http://max-tst-01.mariadb.com:8089/view/test/job/run_test_no_env_rebuild/)|Run system tests without creating a new set of VMs|
|
||||
|[create_env](http://max-tst-01.mariadb.com:8089/view/env/job/create_env/)|Create VMs, install build environment to Maxscale machine, build Maxscale on Maxscale machine|
|
||||
|[destroy](http://max-tst-01.mariadb.com:8089/view/axilary/job/destroy/)|Destroy VMs created by [run_test](http://max-tst-01.mariadb.com:8089/view/test/job/run_test/) or [create_env](http://max-tst-01.mariadb.com:8089/view/env/job/create_env/)|
|
||||
|[remove_lock](http://max-tst-01.mariadb.com:8089/view/axilary/job/remove_lock/)|Remove Vagrant lock set by [run_test](http://max-tst-01.mariadb.com:8089/view/test/job/run_test/) or [create_env](http://max-tst-01.mariadb.com:8089/view/env/job/create_env/)|
|
||||
|
||||
Every test run should have unique name (parameter 'name'). This name is used as a name of MDBCI configuration.
|
||||
If parameter 'do_not_destroy' is set to 'yes' virtual machines (VM) are not destroyed after tests execution and can be laters used
|
||||
for debugging or new test runs (see [run_test_no_env_rebuild](http://max-tst-01.mariadb.com:8089/view/test/job/run_test_no_env_rebuild/))
|
||||
VMs can be accessed from vagrant@max-tst-01.mariadb.com machine using 'mdbci ssh' or 'vagrant ssh' as well as direct ssh
|
||||
access using environmental variables provided by
|
||||
[set_env_vagrant.sh](https://github.com/mariadb-corporation/maxscale-system-test/blob/master/ENV_SETUP.md#access-vms)
|
||||
script.
|
||||
|
||||
Parameter 'box' defines type of VM and Linux distribution to be used for tests.
|
||||
|
||||
Test results go to [CDash](http://jenkins.engskysql.com/CDash/index.php?project=MaxScale), logs and core dumps are
|
||||
stored [here](http://max-tst-01.mariadb.com/LOGS/).
|
||||
|
||||
[create_env](http://max-tst-01.mariadb.com:8089/view/env/job/create_env/) job allows to create a set of VMs
|
||||
(for backend and Maxscale) and does Maxscale build on the Maxscale VM. After execution this job Maxscale machine
|
||||
contains Maxscale source and binaries. *NOTE:* to properly configure Maxscale init scripts it is necessary to
|
||||
use rpm/dpkg tool to install Maxscale package (package can be found in the Maxscale build directory).
|
||||
|
||||
[run_test](http://max-tst-01.mariadb.com:8089/view/test/job/run_test/) and
|
||||
[create_env](http://max-tst-01.mariadb.com:8089/view/env/job/create_env/)
|
||||
jobs create Vagrant lock which prevents running two Vagrant instances in parallel (such parallel execution can
|
||||
cause Vagrant of VM provider failures). In case of job crash or interruption by user Vagrant lock stays in locked state
|
||||
and prevents any new VM creation. To remove lock job
|
||||
[remove_lock](http://max-tst-01.mariadb.com:8089/view/axilary/job/remove_lock/)
|
||||
should be used.
|
||||
|
||||
## Process examples
|
||||
|
||||
### Running regression test against a branch
|
||||
|
||||
Execute [build_and_test](http://max-tst-01.mariadb.com:8089/view/test/job/build_and_test/)
|
||||
|
||||
Recommendations regarding parameters:
|
||||
|
||||
* 'name' - unique name: it can be any text string, but as a good practice rule: 'name' should refer to branch,
|
||||
Linux distribution, date/time of testing, MariaDB version
|
||||
* 'box' - most recommended boxes are 'centos_7.0_libvirt' (QEMU box) and 'centos7' (Amazon Web Services box)
|
||||
* 'source' - which type of source to use. BRANCH for git branch, TAG for a git tag and COMMIT for a commit ID.
|
||||
* 'value' - name of the branch (if 'source' is BRANCH), name of the GIT tag (if 'source' is TAG) or commint ID (if 'source' is COMMIT)
|
||||
|
||||
### Build MaxScale
|
||||
|
||||
Execute [build](http://max-tst-01.mariadb.com:8089/job/build/build) job.
|
||||
|
||||
Parameter 'target' means a name of repository to put packages:
|
||||
e.g. if 'target' is 'develop' packages are going to
|
||||
[http://max-tst-01.mariadb.com/ci-repository/develop/](http://max-tst-01.mariadb.com/ci-repository/develop)
|
||||
|
||||
NOTE: building is executed only for selected distribution ('box' parameter). Be careful with other distributions: if build is not executed for same distribution old version can be in the repository (from some old builds). Later tests have to be executed against the same distribution otherwise they can be run against old version of MaxScale. It is recommended to use unique name for 'target'.
|
||||
|
||||
To debug failed build:
|
||||
* set 'do_not_destroy_vm' parameter to 'yes'
|
||||
* after the build:
|
||||
<pre>
|
||||
ssh -i vagrant.pem vagrant@max-tst-01.mariadb.com
|
||||
cd ~/mdbci/build-<box>-<date><time>
|
||||
vagrant ssh
|
||||
</pre>
|
||||
|
||||
For example:
|
||||
<pre>
|
||||
ssh -i vagrant.pem vagrant@max-tst-01.mariadb.com
|
||||
cd ~/mdbci/build_centos6-20160119-0935
|
||||
vagrant ssh
|
||||
</pre>
|
||||
|
||||
### Create set of Master/Slave and Galera nodes and setup build environment for Maxscale on one more node
|
||||
|
||||
Execute [create_env](http://max-tst-01.mariadb.com:8089/view/env/job/create_env/) job.
|
||||
|
||||
Login to Maxscale machine (see [environment documentation](ENV_SETUP.md#access-vms)).
|
||||
MaxScale source code, binaries and packages can be found in the ~/workspace/ directory.
|
||||
All build tools are installed. GIT can be used to go trough source code.
|
||||
It is not recommended to commit anything from virtual machine to GitHub.
|
||||
|
||||
Please use 'rpm' or 'dpkg' to properly install Maxscale package (/etc/init.d/maxscale script will not be
|
||||
installed without execution of 'rpm' or 'dpkg')
|
||||
|
||||
### Running test agains exiting version of Maxscale
|
||||
|
||||
Execute [run_test](http://max-tst-01.mariadb.com:8089/view/test/job/run_test/) job.
|
||||
|
||||
Be sure Maxscale binary repository is present on the
|
||||
[http://max-tst-01.mariadb.com/ci-repository/](http://max-tst-01.mariadb.com/ci-repository/)
|
||||
server. Please check:
|
||||
* there is a directory with the name equal to 'target' parameter
|
||||
* there is sub-directory for selected distribution ('box' parameter)
|
||||
|
||||
e.g. if 'target' is 'develop' and distribution is CentOS7 (boxes 'centos7' or 'centos_7.0_libvirt') the directory [http://max-tst-01.mariadb.com/ci-repository/develop/mariadb-maxscale/centos/7/x86_64/](http://max-tst-01.mariadb.com/ci-repository/develop/mariadb-maxscale/centos/7/x86_64/) have to contain Maxscale RPM packages.
|
||||
|
||||
If parameter 'do_not_destroy' set to 'yes' after the test virtual machine will not be destroyed and
|
||||
can be used for debugging. See [environment documentation](ENV_SETUP.md#access-vms) to get know how to access virtual machines.
|
||||
|
||||
### Maintenance operations
|
||||
|
||||
If test run was executed with parameter 'do_not_destroy' set yo 'yes' please do not forget to execute
|
||||
[destroy](http://max-tst-01.mariadb.com:8089/view/axilary/job/destroy/) against your 'target'
|
||||
|
||||
This job also have to be executed if test run job crashed or it was interrupted.
|
||||
|
||||
In case of build or test job crash, interruption, Jenkins crash during Vagrant operation it is possible that Vagrant lock
|
||||
stays in locked state and no other job can progress (job can be started, but it is waiting for Vagrant lock -
|
||||
'/home/vagrant/vagrant_lock' can be seen in the job log). In this case lock can be removed by [remove_lock](http://max-tst-01.mariadb.com:8089/view/axilary/job/remove_lock/) job.
|
340
maxscale-system-test/LICENSE
Normal file
340
maxscale-system-test/LICENSE
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
0
maxscale-system-test/README
Normal file
0
maxscale-system-test/README
Normal file
67
maxscale-system-test/README.md
Normal file
67
maxscale-system-test/README.md
Normal file
@ -0,0 +1,67 @@
|
||||
# maxscale-system-test
|
||||
System level tests for MaxScale
|
||||
|
||||
## Basics
|
||||
- every test is separate executable file
|
||||
- backend for test:
|
||||
- 1 machine for Maxscale
|
||||
- >= 4 machines for Master/Slave
|
||||
- >= 4 machines for Galera cluster
|
||||
- environmental variables contains all information about backend: IPs, user names, passwords, paths to tools, etc
|
||||
- backed can be created with help of [MDBCI tool](https://github.com/OSLL/mdbci)
|
||||
- configuring of Master/Slave and Galera can be done with help of [build scripts package](https://github.com/mariadb-corporation/build-scripts-vagrant)
|
||||
|
||||
## Manuals
|
||||
|
||||
[How to run tests](https://github.com/mariadb-corporation/build-scripts-vagrant/blob/master/RUN_TEST.md)
|
||||
|
||||
[Hints: How to write a test](HOW_TO_WRITE_TEST.md)
|
||||
|
||||
[Build and test environment setup (if you want to play with MDBCI and Vagrant on your local machine](ENV_SETUP.md)
|
||||
|
||||
[Jenkins instructions](JENKINS.md)
|
||||
|
||||
## Environmental variables
|
||||
|variable|meaning|
|
||||
|--------|-------|
|
||||
|node_N|Number of machines for Master/Slave|
|
||||
|node_XXX_network|IP address of Master/Slave machine number XXX|
|
||||
|node_XXX_private_ip|private IP address of Master/Slave machine XXX for AWS machines (for everything else - same as node_XXX|
|
||||
|node_XXX_port|MariaDB port of Master/Slave machine XXX|
|
||||
|node_XXX_whoami|user name to access Master/Slave machine XXX via ssh|
|
||||
|node_XXX_access_sudo|'sudo ' if node_access_user_XXX does not have root rights, empty string if node_access_user_XXX has root rights|
|
||||
|node_XXX_keyfile|full name of secret key to access Master/Slave machine XXX via ssh|
|
||||
|node_XXX_start_db_command|bash command to start DB server on Master/Slave machine XXX|
|
||||
|node_XXX_stop_db_command|bash command to stop DB server on Master/Slave machine XXX|
|
||||
|node_user|DB user name to access Master/Slave nodes (have to have all priveligies with GRANT option)|
|
||||
|node_password|password for node_user|
|
||||
|galera_N|Number of machines for Galera|
|
||||
|galera_XXX_network|IP address of Galera machine number XXX|
|
||||
|galera_XXX_private|private IP address of Galera machine XXX for AWS machines (for everything else - same as node_XXX|
|
||||
|galera_XXX_port|MariaDB port of Galera machine XXX|
|
||||
|galera_XXX_whoami|user name to access Galera machine XXX via ssh|
|
||||
|galera_XXX_access|'sudo ' if node_access_user_XXX does not have root rights, empty string if node_access_user_XXX has root rights|
|
||||
|galera_XXX_keyfile|full name of secret key to access Galera machine XXX via ssh|
|
||||
|galera_XXX_start_db_command|bash command to start DB server on Galera machine XXX|
|
||||
|galera_XXX_stop_db_command|bash command to stop DB server on Galera machine XXX|
|
||||
|galera_user|DB user name to access Galera nodes (have to have all priveligies with GRANT option)|
|
||||
|galera_password|password for node_user|
|
||||
|maxscale_cnf|full name of Maxscale configuration file (maxscale.cnf)|
|
||||
|maxscale_log_dir|directory for Maxscale log files|
|
||||
|maxscale_IP|IP address of Maxscale machine|
|
||||
|maxscale_sshkey|full name of secret key to access Maxscale machine via ssh|
|
||||
|maxscale_access_user|user name to access Maxscale machine via ssh|
|
||||
|maxscale_access_sudo|'sudo ' if maxscale_access_user does not have root rights, empty string if maxscale_access_user has root rights|
|
||||
|maxscale_user|DB user to access via Maxscale|
|
||||
|maxscale_password|password for maxscale_user|
|
||||
|maxscale_hostname|hostname of Maxscale machine|
|
||||
|sysbench_dir|directory where Sysbanch is installed|
|
||||
|ssl|'yes' if tests should try to use ssl to connect to Maxscale and to backends (obsolete, now should be 'yes' in all cases)|
|
||||
|smoke|if 'yes' all tests are executed in 'quick' mode (less iterations, skip heavy operations)|
|
||||
|backend_ssl|if 'yes' ssl config will be added to all servers definition in maxscale.cnf|
|
||||
|use_snapshots|if TRUE every test is trying to revert snapshot before running the test|
|
||||
|take_snapshot_command|revert_snapshot_command|
|
||||
|revert_snapshot_command|Command line to revert a snapshot of all VMs|
|
||||
|no_nodes_check|if yes backend checks are not executed (needed in case of RDS or similar backend)|
|
||||
|no_backend_log_copy|if yes logs from backend nodes are not copied (needed in case of RDS or similar backend)|
|
||||
|no_maxscale_start|Do not start Maxscale automatically|
|
32
maxscale-system-test/TEST_RUSULTS.md
Normal file
32
maxscale-system-test/TEST_RUSULTS.md
Normal file
@ -0,0 +1,32 @@
|
||||
# Results locations
|
||||
|
||||
| Location | Description |
|
||||
|----------|-------------|
|
||||
|[run_test](http://max-tst-01.mariadb.com:8089/view/test/job/run_test/) Jenkins job log|Vagrant and test application outputs|
|
||||
|[CDash](jenkins.engskysql.com/CDash/index.php?project=MaxScale)|CTest reports|
|
||||
|[http://max-tst-01.mariadb.com/LOGS/](http://max-tst-01.mariadb.com/LOGS/)|MaxScale logs and core dumps|
|
||||
|/home/vagrant/LOGS|Same as [http://max-tst-01.mariadb.com/LOGS/](http://max-tst-01.mariadb.com/LOGS/)|
|
||||
|Maxscale VM /var/log/maxscale|MaxScale log from latest test case|
|
||||
|Maxscale VM /tpm/core*|Core dump from latest test case|
|
||||
|Maxscale VM home directory|QLA filter files (if enabled in MaxScale test configuration|
|
||||
|nodeN, galeraN VMs|MariaDB/MySQL logs (see MariaDB/MySQL documentation for details)|
|
||||
|
||||
For access to VMs see [environment documentation](ENV_SETUP.md#access-vms)
|
||||
|
||||
Jenkins job log consists of following parts:
|
||||
* Vagrant output: VMs creation priocess, MariaDB Master/Slave and MariaDB Galera stuff installation, MaxScale installation
|
||||
* [set_env_vagrant.sh](https://github.com/mariadb-corporation/build-scripts-vagrant/blob/master/test/set_env_vagrant.sh) output: retrieval of all VM parameters
|
||||
* setup scripts output: MariaDB initialisation on backend nodes, DB users setup, enabling core dump on MaxScale VM
|
||||
* test application output for all tests: eevry line starts from test case number and ':' (can be grepped)
|
||||
* CTest final printing: N of M tests passed, CTest warnings, email sending logs
|
||||
|
||||
To check presence of core dumps:
|
||||
<pre>
|
||||
find /home/vagrant/LOGS/<last_test_results_dir> | grep core
|
||||
</pre>
|
||||
|
||||
where 'last_test_results_dir' - automatically generated name of logs directory (based on date and time of test run)
|
||||
|
||||
To understand test case output please see test case description in Doxygen comments in every test case source file.
|
||||
|
||||
VMs are alive after the test run only if test run is done with 'do_not_destroy' parameter.
|
14
maxscale-system-test/astylerc
Normal file
14
maxscale-system-test/astylerc
Normal file
@ -0,0 +1,14 @@
|
||||
--style=allman
|
||||
--indent=spaces=4
|
||||
--indent-switches
|
||||
--indent-labels
|
||||
--min-conditional-indent=0
|
||||
--pad-oper
|
||||
--pad-header
|
||||
--add-brackets
|
||||
--convert-tabs
|
||||
--max-code-length=110
|
||||
--break-after-logical
|
||||
--mode=c
|
||||
--suffix=none
|
||||
--max-instatement-indent=110
|
157
maxscale-system-test/auroramon.cpp
Normal file
157
maxscale-system-test/auroramon.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
/**
|
||||
* @file auroramon.cpp test of Aurora RDS monitor
|
||||
* - create RDS cluster
|
||||
* - find 'writer' node and uses 'maxadmin' to check that this node is "Master, Running"
|
||||
* - do forced failover
|
||||
* - find 'writer' again and repeat check
|
||||
* - destroy RDS cluster
|
||||
*/
|
||||
|
||||
|
||||
#include "testconnections.h"
|
||||
#include "execute_cmd.h"
|
||||
#include "rds_vpc.h"
|
||||
|
||||
int set_endspoints(RDS * cluster)
|
||||
{
|
||||
|
||||
json_t *endpoint;
|
||||
long long int port;
|
||||
const char * IP;
|
||||
char p[64];
|
||||
size_t i;
|
||||
char cmd[1024];
|
||||
|
||||
json_t * endpoints = cluster->get_endpoints();
|
||||
if (endpoints == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
json_array_foreach(endpoints, i, endpoint)
|
||||
{
|
||||
port = json_integer_value(json_object_get(endpoint, "Port"));
|
||||
IP = json_string_value(json_object_get(endpoint, "Address"));
|
||||
printf("host: %s \t port: %lld\n", IP, port);
|
||||
sprintf(cmd, "node_%03d_network", (int) i);
|
||||
setenv(cmd, IP, 1);
|
||||
sprintf(cmd, "node_%03d_port", (int) i);
|
||||
sprintf(p, "%lld", port);
|
||||
setenv(cmd, p, 1);
|
||||
}
|
||||
|
||||
setenv("node_password", "skysqlrds", 1);
|
||||
setenv("maxscale_user", "skysql", 1);
|
||||
setenv("maxscale_password", "skysqlrds", 1);
|
||||
setenv("no_nodes_check", "yes", 1);
|
||||
setenv("no_backend_log_copy", "yes", 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void compare_masters(TestConnections* Test, RDS * cluster)
|
||||
{
|
||||
const char * aurora_master;
|
||||
cluster->get_writer(&aurora_master);
|
||||
Test->tprintf("Aurora writer node: %s\n", aurora_master);
|
||||
char maxadmin_status[1024];
|
||||
int i;
|
||||
char cmd[1024];
|
||||
for (i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
sprintf(cmd, "show server server%d", i + 1);
|
||||
Test->get_maxadmin_param(cmd, (char *) "Status:", &maxadmin_status[0]);
|
||||
Test->tprintf("Server%d status %s\n", i + 1, maxadmin_status);
|
||||
sprintf(cmd, "node%03d", i);
|
||||
if (strcmp(aurora_master, cmd) == 0)
|
||||
{
|
||||
if (strcmp(maxadmin_status, "Master, Running"))
|
||||
{
|
||||
Test->tprintf("Maxadmin reports node%03d is a Master as expected", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->add_result(1, "Server node%03d status is not 'Master, Running'', it is '%s'", i, maxadmin_status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp(maxadmin_status, "Slave, Running"))
|
||||
{
|
||||
Test->tprintf("Maxadmin reports node%03d is a Slave as expected", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->add_result(1, "Server node%03d status is not 'Slave, Running'', it is '%s'", i, maxadmin_status);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
RDS * cluster = new RDS((char *) "auroratest");
|
||||
|
||||
if (cluster->create_rds_db(4) != 0)
|
||||
{
|
||||
printf("Error RDS creation\n");
|
||||
return 1;
|
||||
}
|
||||
cluster->wait_for_nodes(4);
|
||||
|
||||
|
||||
if (set_endspoints(cluster) != 0)
|
||||
{
|
||||
printf("Error getting RDS endpoints\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(30);
|
||||
|
||||
compare_masters(Test, cluster);
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->tprintf("Executing a query through readwritesplit before failover");
|
||||
Test->connect_rwsplit();
|
||||
Test->try_query(Test->conn_rwsplit, "show processlist");
|
||||
char server_id[1024];
|
||||
Test->tprintf("Get aurora_server_id\n");
|
||||
find_field(Test->conn_rwsplit, "select @@aurora_server_id;", "server_id", &server_id[0]);
|
||||
Test->close_rwsplit();
|
||||
Test->tprintf("server_id before failover: %s\n", server_id);
|
||||
|
||||
Test->stop_timeout();
|
||||
Test->tprintf("Performing cluster failover\n");
|
||||
|
||||
Test->add_result(cluster->do_failover(), "Failover failed\n");
|
||||
|
||||
Test->tprintf("Failover done\n");
|
||||
|
||||
// Do the failover here and wait until it is over
|
||||
//sleep(10);
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->tprintf("Executing a query through readwritesplit after failover");
|
||||
Test->connect_rwsplit();
|
||||
Test->try_query(Test->conn_rwsplit, "show processlist");
|
||||
Test->tprintf("Get aurora_server_id\n");
|
||||
find_field(Test->conn_rwsplit, "select @@aurora_server_id;", "server_id", &server_id[0]);
|
||||
Test->close_rwsplit();
|
||||
Test->tprintf("server_id after failover: %s\n", server_id);
|
||||
|
||||
compare_masters(Test, cluster);
|
||||
|
||||
|
||||
//Test->check_maxscale_alive();
|
||||
|
||||
|
||||
Test->stop_timeout();
|
||||
cluster->delete_rds_cluster();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
107
maxscale-system-test/avro.cpp
Normal file
107
maxscale-system-test/avro.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @file avro.cpp test of avro
|
||||
* - setup binlog and avro
|
||||
* - put some data to t1
|
||||
* - check avro file with "maxavrocheck -vv /var/lib/maxscale/avro/test.t1.000001.avro"
|
||||
* - check that data in avro file is correct
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "maxadmin_operations.h"
|
||||
#include "sql_t1.h"
|
||||
|
||||
#include "test_binlog_fnc.h"
|
||||
#include <jansson.h>
|
||||
#include "maxinfo_func.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(600);
|
||||
Test->stop_maxscale();
|
||||
Test->ssh_maxscale(true, (char *) "rm -rf /var/lib/maxscale/avro");
|
||||
|
||||
Test->repl->connect();
|
||||
execute_query(Test->repl->nodes[0], "DROP TABLE IF EXISTS t1");
|
||||
Test->repl->close_connections();
|
||||
sleep(5);
|
||||
|
||||
|
||||
Test->start_binlog();
|
||||
|
||||
Test->set_timeout(120);
|
||||
|
||||
Test->stop_maxscale();
|
||||
|
||||
Test->ssh_maxscale(true, "rm -rf /var/lib/maxscale/avro");
|
||||
|
||||
Test->set_timeout(120);
|
||||
|
||||
Test->start_maxscale();
|
||||
|
||||
Test->set_timeout(60);
|
||||
|
||||
Test->repl->connect();
|
||||
create_t1(Test->repl->nodes[0]);
|
||||
insert_into_t1(Test->repl->nodes[0], 3);
|
||||
execute_query(Test->repl->nodes[0], "FLUSH LOGS");
|
||||
|
||||
Test->repl->close_connections();
|
||||
|
||||
Test->set_timeout(120);
|
||||
|
||||
sleep(10);
|
||||
|
||||
char * avro_check = Test->ssh_maxscale_output(true,
|
||||
"maxavrocheck -vv /var/lib/maxscale/avro/test.t1.000001.avro | grep \"{\"");
|
||||
char * output = Test->ssh_maxscale_output(true, "maxavrocheck -d /var/lib/maxscale/avro/test.t1.000001.avro");
|
||||
|
||||
std::istringstream iss;
|
||||
iss.str(output);
|
||||
int x1_exp = 0;
|
||||
int fl_exp = 0;
|
||||
int x = 16;
|
||||
|
||||
for (std::string line; std::getline(iss, line);)
|
||||
{
|
||||
long long int x1, fl;
|
||||
Test->set_timeout(20);
|
||||
get_x_fl_from_json((char*)line.c_str(), &x1, &fl);
|
||||
|
||||
if (x1 != x1_exp || fl != fl_exp)
|
||||
{
|
||||
Test->add_result(1, "Output:x1 %lld, fl %lld, Expected: x1 %d, fl %d",
|
||||
x1, fl, x1_exp, fl_exp);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((++x1_exp) >= x)
|
||||
{
|
||||
x1_exp = 0;
|
||||
x = x * 16;
|
||||
fl_exp++;
|
||||
Test->tprintf("fl = %d", fl_exp);
|
||||
}
|
||||
}
|
||||
|
||||
if (fl_exp != 3)
|
||||
{
|
||||
Test->add_result(1, "not enough lines in avrocheck output\n");
|
||||
}
|
||||
|
||||
Test->set_timeout(120);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
60
maxscale-system-test/avro_long.cpp
Normal file
60
maxscale-system-test/avro_long.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @file avro_long.cpp test of avro
|
||||
* - setup binlog and avro
|
||||
* - put some data to t1 in the loop
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "maxadmin_operations.h"
|
||||
#include "sql_t1.h"
|
||||
|
||||
#include "test_binlog_fnc.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(600);
|
||||
Test->stop_maxscale();
|
||||
Test->ssh_maxscale(true, (char *) "rm -rf /var/lib/maxscale/avro");
|
||||
|
||||
//Test->ssh_maxscale(true, (char *) "mkdir /var/lib/maxscale/avro; chown -R maxscale:maxscale /var/lib/maxscale/avro");
|
||||
|
||||
Test->repl->connect();
|
||||
execute_query(Test->repl->nodes[0], (char *) "DROP TABLE IF EXISTS t1;");
|
||||
Test->repl->close_connections();
|
||||
sleep(5);
|
||||
|
||||
|
||||
Test->start_binlog();
|
||||
|
||||
Test->set_timeout(120);
|
||||
|
||||
Test->stop_maxscale();
|
||||
|
||||
Test->ssh_maxscale(true, (char *) "rm -rf /var/lib/maxscale/avro");
|
||||
|
||||
Test->set_timeout(120);
|
||||
|
||||
Test->start_maxscale();
|
||||
|
||||
Test->set_timeout(60);
|
||||
|
||||
Test->repl->connect();
|
||||
create_t1(Test->repl->nodes[0]);
|
||||
|
||||
for (int i = 0; i < 1000000; i++)
|
||||
{
|
||||
Test->set_timeout(60);
|
||||
insert_into_t1(Test->repl->nodes[0], 3);
|
||||
Test->tprintf("i=%d\n", i);
|
||||
}
|
||||
|
||||
Test->repl->close_connections();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
40
maxscale-system-test/backend_auth_fail.cpp
Normal file
40
maxscale-system-test/backend_auth_fail.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @backend_auth_fail.cpp Repeatedly connect to maxscale while the backends reject all connections
|
||||
*
|
||||
* MaxScale should not crash
|
||||
*/
|
||||
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
MYSQL *mysql[1000];
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->stop_timeout();
|
||||
Test->repl->execute_query_all_nodes((char *) "set global max_connections = 10;");
|
||||
|
||||
for (int x = 0; x < 3; x++)
|
||||
{
|
||||
Test->tprintf("Creating 100 connections...\n");
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
Test->set_timeout(30);
|
||||
mysql[i] = Test->open_readconn_master_connection();
|
||||
execute_query_silent(mysql[i], "select 1");
|
||||
}
|
||||
Test->stop_timeout();
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
Test->set_timeout(30);
|
||||
mysql_close(mysql[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Test->stop_timeout();
|
||||
Test->check_maxscale_alive();
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
|
||||
}
|
27
maxscale-system-test/bad_pers.cpp
Normal file
27
maxscale-system-test/bad_pers.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @file bad_pres.cpp check that Maxscale prints warning if persistpoolmax=-1 for all backends (bug MXS-576)
|
||||
*
|
||||
* - Maxscale.cnf contains persistpoolmax=-1 for all servers
|
||||
* - check log warning about it
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
Test->connect_maxscale();
|
||||
Test->check_log_err((char *) "warning -1", true);
|
||||
Test->check_maxscale_alive();
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
228
maxscale-system-test/big_load.cpp
Normal file
228
maxscale-system-test/big_load.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
#include "big_load.h"
|
||||
#include <pthread.h>
|
||||
|
||||
void load(long int *new_inserts, long int *new_selects, long int *selects, long int *inserts, int threads_num,
|
||||
TestConnections * Test, long int *i1, long int *i2, int rwsplit_only, bool galera, bool report_errors)
|
||||
{
|
||||
char sql[1000000];
|
||||
thread_data data;
|
||||
Mariadb_nodes * nodes;
|
||||
if (galera)
|
||||
{
|
||||
nodes = Test->galera;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes = Test->repl;
|
||||
}
|
||||
|
||||
int sql_l = 20000;
|
||||
int run_time = 100;
|
||||
if (Test->smoke)
|
||||
{
|
||||
sql_l = 500;
|
||||
run_time = 10;
|
||||
}
|
||||
|
||||
nodes->connect();
|
||||
Test->connect_rwsplit();
|
||||
|
||||
data.i1 = 0;
|
||||
data.i2 = 0;
|
||||
data.exit_flag = 0;
|
||||
data.Test = Test;
|
||||
data.rwsplit_only = rwsplit_only;
|
||||
// connect to the MaxScale server (rwsplit)
|
||||
|
||||
if (Test->conn_rwsplit == NULL )
|
||||
{
|
||||
if (report_errors)
|
||||
{
|
||||
Test->add_result(1, "Can't connect to MaxScale\n");
|
||||
}
|
||||
//Test->copy_all_logs();
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
create_t1(Test->conn_rwsplit);
|
||||
create_insert_string(sql, sql_l, 1);
|
||||
|
||||
if ((execute_query(Test->conn_rwsplit, sql) != 0) && (report_errors))
|
||||
{
|
||||
Test->add_result(1, "Query %s failed\n", sql);
|
||||
}
|
||||
// close connections
|
||||
Test->close_rwsplit();
|
||||
|
||||
Test->tprintf("Waiting for the table to replicate\n");
|
||||
Test->repl->sync_slaves();
|
||||
|
||||
pthread_t thread1[threads_num];
|
||||
pthread_t thread2[threads_num];
|
||||
int iret1[threads_num];
|
||||
int iret2[threads_num];
|
||||
|
||||
Test->tprintf("COM_INSERT and COM_SELECT before executing test\n");
|
||||
|
||||
Test->add_result(get_global_status_allnodes(&selects[0], &inserts[0], nodes, 0),
|
||||
"get_global_status_allnodes failed\n");
|
||||
|
||||
data.exit_flag = 0;
|
||||
/* Create independent threads each of them will execute function */
|
||||
for (int i = 0; i < threads_num; i++)
|
||||
{
|
||||
iret1[i] = pthread_create(&thread1[i], NULL, query_thread1, &data);
|
||||
iret2[i] = pthread_create(&thread2[i], NULL, query_thread2, &data);
|
||||
}
|
||||
Test->tprintf("Threads are running %d seconds \n", run_time);
|
||||
sleep(run_time);
|
||||
data.exit_flag = 1;
|
||||
Test->tprintf("Waiting for all threads to exit\n");
|
||||
Test->set_timeout(100);
|
||||
for (int i = 0; i < threads_num; i++)
|
||||
{
|
||||
pthread_join(thread1[i], NULL);
|
||||
pthread_join(thread2[i], NULL);
|
||||
}
|
||||
sleep(1);
|
||||
|
||||
Test->tprintf("COM_INSERT and COM_SELECT after executing test\n");
|
||||
get_global_status_allnodes(&new_selects[0], &new_inserts[0], nodes, 0);
|
||||
print_delta(&new_selects[0], &new_inserts[0], &selects[0], &inserts[0], nodes->N);
|
||||
Test->tprintf("First group of threads did %d queries, second - %d \n", data.i1, data.i2);
|
||||
}
|
||||
nodes->close_connections();
|
||||
*i1 = data.i1;
|
||||
*i2 = data.i2;
|
||||
}
|
||||
|
||||
void *query_thread1( void *ptr )
|
||||
{
|
||||
MYSQL * conn1;
|
||||
MYSQL * conn2;
|
||||
MYSQL * conn3;
|
||||
int conn_err = 0;
|
||||
thread_data * data = (thread_data *) ptr;
|
||||
conn1 = open_conn_db_timeout(data->Test->rwsplit_port,
|
||||
data->Test->maxscale_IP,
|
||||
(char *) "test",
|
||||
data->Test->maxscale_user,
|
||||
data->Test->maxscale_password,
|
||||
20,
|
||||
data->Test->ssl);
|
||||
//conn1 = data->Test->open_rwsplit_connection();
|
||||
if (mysql_errno(conn1) != 0)
|
||||
{
|
||||
conn_err++;
|
||||
}
|
||||
if (data->rwsplit_only == 0)
|
||||
{
|
||||
//conn2 = data->Test->open_readconn_master_connection();
|
||||
conn2 = open_conn_db_timeout(data->Test->readconn_master_port,
|
||||
data->Test->maxscale_IP,
|
||||
(char *) "test",
|
||||
data->Test->maxscale_user,
|
||||
data->Test->maxscale_password,
|
||||
20,
|
||||
data->Test->ssl);
|
||||
if (mysql_errno(conn2) != 0)
|
||||
{
|
||||
conn_err++;
|
||||
}
|
||||
//conn3 = data->Test->open_readconn_slave_connection();
|
||||
conn3 = open_conn_db_timeout(data->Test->readconn_slave_port,
|
||||
data->Test->maxscale_IP,
|
||||
(char *) "test",
|
||||
data->Test->maxscale_user,
|
||||
data->Test->maxscale_password,
|
||||
20,
|
||||
data->Test->ssl);
|
||||
if (mysql_errno(conn3) != 0)
|
||||
{
|
||||
conn_err++;
|
||||
}
|
||||
}
|
||||
if (conn_err == 0)
|
||||
{
|
||||
while (data->exit_flag == 0)
|
||||
{
|
||||
if (execute_query_silent(conn1, (char *) "SELECT * FROM t1;") == 0)
|
||||
{
|
||||
__sync_fetch_and_add(&data->i1, 1);
|
||||
}
|
||||
|
||||
if (data->rwsplit_only == 0)
|
||||
{
|
||||
execute_query_silent(conn2, (char *) "SELECT * FROM t1;");
|
||||
execute_query_silent(conn3, (char *) "SELECT * FROM t1;");
|
||||
}
|
||||
|
||||
}
|
||||
mysql_close(conn1);
|
||||
if (data->rwsplit_only == 0)
|
||||
{
|
||||
mysql_close(conn2);
|
||||
mysql_close(conn3);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *query_thread2(void *ptr )
|
||||
{
|
||||
MYSQL * conn1;
|
||||
MYSQL * conn2;
|
||||
MYSQL * conn3;
|
||||
thread_data * data = (thread_data *) ptr;
|
||||
//conn1 = data->Test->open_rwsplit_connection();
|
||||
conn1 = open_conn_db_timeout(data->Test->rwsplit_port,
|
||||
data->Test->maxscale_IP,
|
||||
(char *) "test",
|
||||
data->Test->maxscale_user,
|
||||
data->Test->maxscale_password,
|
||||
20,
|
||||
data->Test->ssl);
|
||||
if (data->rwsplit_only == 0)
|
||||
{
|
||||
//conn2 = data->Test->open_readconn_master_connection();
|
||||
//conn3 = data->Test->open_readconn_slave_connection();
|
||||
|
||||
conn2 = open_conn_db_timeout(data->Test->readconn_master_port,
|
||||
data->Test->maxscale_IP,
|
||||
(char *) "test",
|
||||
data->Test->maxscale_user,
|
||||
data->Test->maxscale_password,
|
||||
20,
|
||||
data->Test->ssl);
|
||||
//if (mysql_errno(conn2) != 0) { conn_err++; }
|
||||
conn3 = open_conn_db_timeout(data->Test->readconn_slave_port,
|
||||
data->Test->maxscale_IP,
|
||||
(char *) "test",
|
||||
data->Test->maxscale_user,
|
||||
data->Test->maxscale_password,
|
||||
20,
|
||||
data->Test->ssl);
|
||||
//if (mysql_errno(conn3) != 0) { conn_err++; }
|
||||
}
|
||||
while (data->exit_flag == 0)
|
||||
{
|
||||
sleep(1);
|
||||
if (execute_query_silent(conn1, (char *) "SELECT * FROM t1;") == 0)
|
||||
{
|
||||
__sync_fetch_and_add(&data->i2, 1);
|
||||
}
|
||||
if (data->rwsplit_only == 0)
|
||||
{
|
||||
execute_query_silent(conn2, (char *) "SELECT * FROM t1;");
|
||||
execute_query_silent(conn3, (char *) "SELECT * FROM t1;");
|
||||
}
|
||||
}
|
||||
mysql_close(conn1);
|
||||
if (data->rwsplit_only == 0)
|
||||
{
|
||||
mysql_close(conn2);
|
||||
mysql_close(conn3);
|
||||
}
|
||||
return NULL;
|
||||
}
|
39
maxscale-system-test/big_load.h
Normal file
39
maxscale-system-test/big_load.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef BIG_LOAD_H
|
||||
#define BIG_LOAD_H
|
||||
|
||||
|
||||
#include "testconnections.h"
|
||||
#include "sql_t1.h"
|
||||
#include "get_com_select_insert.h"
|
||||
|
||||
//pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
|
||||
typedef struct
|
||||
{
|
||||
int exit_flag;
|
||||
long i1;
|
||||
long i2;
|
||||
int rwsplit_only;
|
||||
TestConnections * Test;
|
||||
} thread_data;
|
||||
|
||||
void *query_thread1(void *ptr );
|
||||
void *query_thread2(void *ptr );
|
||||
|
||||
/**
|
||||
* @brief load Creates load on Maxscale routers
|
||||
* @param new_inserts COM_INSERT variable values array for all nodes after test
|
||||
* @param new_selects COM_SELECT variable values array for all nodes after test
|
||||
* @param selects COM_SELECT variable values array for all nodes before test
|
||||
* @param inserts COM_INSERT variable values array for all nodes before test
|
||||
* @param threads_num Number of load threads
|
||||
* @param Test TestConnections object
|
||||
* @param i1 Number of queries executed by "fast" threads (no wating between queries)
|
||||
* @param i2 Number of queries executed by "slow" threads (sleep 1 second between queries)
|
||||
* @param rwsplit_only if 1 create load only on RWSplit router, do not load ReadConn router
|
||||
* @param galera if true use Galera backend (Test->galera instead of Test->repl)
|
||||
* @param report_errors if true call add_result() in case of query failure
|
||||
*/
|
||||
void load(long *new_inserts, long *new_selects, long *selects, long *inserts, int threads_num,
|
||||
TestConnections *Test, long *i1, long *i2, int rwsplit_only, bool galera, bool report_errors);
|
||||
|
||||
#endif // BIG_LOAD_H
|
23
maxscale-system-test/big_transaction.cpp
Normal file
23
maxscale-system-test/big_transaction.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "big_transaction.h"
|
||||
|
||||
int big_transaction(MYSQL * conn, int N)
|
||||
{
|
||||
int local_result = 0;
|
||||
char sql[1000000];
|
||||
local_result += create_t1(conn);
|
||||
local_result += execute_query(conn, (char *) "START TRANSACTION");
|
||||
local_result += execute_query(conn, (char *) "SET autocommit = 0");
|
||||
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
create_insert_string(sql, 10000, i);
|
||||
local_result += execute_query(conn, sql);
|
||||
local_result += execute_query(conn, "CREATE TABLE t2(id int);");
|
||||
local_result += execute_query(conn, sql);
|
||||
local_result += execute_query(conn, "DROP TABLE t2;");
|
||||
local_result += execute_query(conn, sql);
|
||||
}
|
||||
|
||||
local_result += execute_query(conn, (char *) "COMMIT");
|
||||
return local_result;
|
||||
}
|
17
maxscale-system-test/big_transaction.h
Normal file
17
maxscale-system-test/big_transaction.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef BIG_TRANSACTION_H
|
||||
#define BIG_TRANSACTION_H
|
||||
|
||||
#include <mariadb/mysql.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "sql_t1.h"
|
||||
|
||||
/**
|
||||
* @brief big_transaction Executes big transaction (includes N INSERTs of 10000 rows)
|
||||
* @param conn MYSQL connection handler
|
||||
* @param N Number of INSERTs
|
||||
* @return 0 if success
|
||||
*/
|
||||
int big_transaction(MYSQL * conn, int N);
|
||||
|
||||
#endif // BIG_TRANSACTION_H
|
72
maxscale-system-test/binlog_big_transaction.cpp
Normal file
72
maxscale-system-test/binlog_big_transaction.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @file binlog_big_transaction.cpp test of simple binlog router setup and execute a number of big transactions
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "maxadmin_operations.h"
|
||||
#include "sql_t1.h"
|
||||
#include "test_binlog_fnc.h"
|
||||
#include "big_transaction.h"
|
||||
|
||||
void *disconnect_thread( void *ptr );
|
||||
TestConnections * Test ;
|
||||
int exit_flag;
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(3000);
|
||||
Test->set_log_copy_interval(300);
|
||||
|
||||
Test->repl->connect();
|
||||
execute_query(Test->repl->nodes[0], (char *) "DROP TABLE IF EXISTS t1;");
|
||||
Test->repl->close_connections();
|
||||
sleep(5);
|
||||
|
||||
Test->start_binlog();
|
||||
|
||||
pthread_t threads;
|
||||
int iret;
|
||||
exit_flag = 0;
|
||||
iret = pthread_create( &threads, NULL, disconnect_thread, NULL);
|
||||
|
||||
Test->repl->connect();
|
||||
for (int i = 0; i < 100000; i++)
|
||||
{
|
||||
Test->set_timeout(3000);
|
||||
Test->tprintf("Trying transactions: %d\n", i);
|
||||
Test->add_result(big_transaction(Test->repl->nodes[0], 7), "Transaction %d failed!\n", i);
|
||||
}
|
||||
Test->repl->close_connections();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
||||
void *disconnect_thread( void *ptr )
|
||||
{
|
||||
MYSQL * conn;
|
||||
char cmd[256];
|
||||
int i;
|
||||
conn = open_conn(Test->binlog_port, Test->maxscale_IP, Test->repl->user_name, Test->repl->password,
|
||||
Test->repl->ssl);
|
||||
Test->add_result(mysql_errno(conn), "Error connecting to Binlog router, error: %s\n", mysql_error(conn));
|
||||
i = 3;
|
||||
while (exit_flag == 0)
|
||||
{
|
||||
sprintf(cmd, "DISCONNECT SERVER %d", i);
|
||||
execute_query(conn, cmd);
|
||||
i++;
|
||||
if (i > Test->repl->N)
|
||||
{
|
||||
i = 3;
|
||||
sleep(30);
|
||||
execute_query(conn, (char *) "DISCONNECT SERVER ALL");
|
||||
}
|
||||
sleep(5);
|
||||
}
|
||||
return NULL;
|
||||
}
|
322
maxscale-system-test/binlog_change_master.cpp
Normal file
322
maxscale-system-test/binlog_change_master.cpp
Normal file
@ -0,0 +1,322 @@
|
||||
/**
|
||||
* @file binlog_change_master.cpp In the binlog router setup stop Master and promote one of the Slaves to be new Master
|
||||
* - setup binlog
|
||||
* - start thread wich executes transactions
|
||||
* - block master
|
||||
* - transaction thread tries to elect a new master a continue with new master
|
||||
* - continue transaction with new master
|
||||
* - stop transactions
|
||||
* - wait
|
||||
* - chack data on all nodes
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "maxadmin_operations.h"
|
||||
#include "sql_t1.h"
|
||||
#include "test_binlog_fnc.h"
|
||||
#include "big_transaction.h"
|
||||
|
||||
void *disconnect_thread( void *ptr );
|
||||
void *transaction_thread( void *ptr );
|
||||
|
||||
TestConnections * Test ;
|
||||
int exit_flag;
|
||||
int master = 0;
|
||||
int i_trans = 0;
|
||||
int failed_transaction_num = 0;
|
||||
|
||||
/** The amount of rows each transaction inserts */
|
||||
const int N_INSERTS = 100;
|
||||
|
||||
int transaction(MYSQL * conn, int N)
|
||||
{
|
||||
int local_result = 0;
|
||||
char sql[1000000];
|
||||
|
||||
Test->tprintf("START TRANSACTION\n");
|
||||
local_result += execute_query(conn, (char *) "START TRANSACTION");
|
||||
if (local_result != 0)
|
||||
{
|
||||
Test->tprintf("START TRANSACTION Failed\n");
|
||||
return local_result;
|
||||
}
|
||||
Test->tprintf("SET autocommit = 0\n");
|
||||
local_result += execute_query(conn, (char *) "SET autocommit = 0");
|
||||
if (local_result != 0)
|
||||
{
|
||||
Test->tprintf("SET Failed\n");
|
||||
return local_result;
|
||||
}
|
||||
|
||||
create_insert_string(sql, N_INSERTS, N);
|
||||
Test->tprintf("INSERT\n");
|
||||
local_result += execute_query(conn, sql);
|
||||
if (local_result != 0)
|
||||
{
|
||||
Test->tprintf("Insert Failed\n");
|
||||
return local_result;
|
||||
}
|
||||
|
||||
Test->tprintf("COMMIT\n");
|
||||
local_result += execute_query(conn, (char *) "COMMIT");
|
||||
if (local_result != 0)
|
||||
{
|
||||
Test->tprintf("Commit Failed\n");
|
||||
return local_result;
|
||||
}
|
||||
return local_result;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int j;
|
||||
|
||||
Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(3000);
|
||||
|
||||
Test->repl->connect();
|
||||
execute_query(Test->repl->nodes[0], (char *) "DROP TABLE IF EXISTS t1;");
|
||||
Test->repl->close_connections();
|
||||
sleep(5);
|
||||
|
||||
Test->repl->connect();
|
||||
Test->repl->execute_query_all_nodes((char *) "STOP SLAVE");
|
||||
Test->repl->execute_query_all_nodes((char *) "RESET SLAVE ALL");
|
||||
Test->repl->execute_query_all_nodes((char *) "RESET MASTER");
|
||||
|
||||
Test->tprintf("Starting binlog configuration\n");
|
||||
Test->start_binlog();
|
||||
|
||||
pthread_t disconnec_thread_t;
|
||||
int disconnect_iret;
|
||||
pthread_t transaction_thread_t;
|
||||
int transaction_iret;
|
||||
|
||||
exit_flag = 0;
|
||||
Test->tprintf("Starting query thread\n");
|
||||
|
||||
transaction_iret = pthread_create(&transaction_thread_t, NULL, transaction_thread, NULL);
|
||||
|
||||
Test->tprintf("Sleeping\n");
|
||||
Test->stop_timeout();
|
||||
|
||||
Test->repl->connect();
|
||||
int flushes = Test->smoke ? 2 : 5;
|
||||
for (j = 0; j < flushes; j++)
|
||||
{
|
||||
Test->tprintf("Flush logs on master\n");
|
||||
execute_query(Test->repl->nodes[0], (char *) "flush logs");
|
||||
sleep(15);
|
||||
}
|
||||
|
||||
sleep(15);
|
||||
|
||||
Test->tprintf("Blocking master\n");
|
||||
Test->repl->block_node(0);
|
||||
Test->stop_timeout();
|
||||
|
||||
sleep(30);
|
||||
|
||||
Test->tprintf("Done! Waiting for thread\n");
|
||||
exit_flag = 1;
|
||||
pthread_join(transaction_thread_t, NULL );
|
||||
Test->tprintf("Done!\n");
|
||||
|
||||
Test->tprintf("Checking data on the node3 (slave)\n");
|
||||
char sql[256];
|
||||
char rep[256];
|
||||
int rep_d;
|
||||
|
||||
Test->tprintf("Sleeping to let replication happen\n");
|
||||
sleep(30);
|
||||
|
||||
Test->repl->connect();
|
||||
|
||||
for (int i_n = 3; i_n < Test->repl->N; i_n++)
|
||||
{
|
||||
for (j = 0; j < i_trans; j++)
|
||||
{
|
||||
sprintf(sql, "select count(*) from t1 where fl=%d;", j);
|
||||
find_field(Test->repl->nodes[i_n], sql, (char *) "count(*)", rep);
|
||||
Test->tprintf("Transaction %d put %s rows\n", j, rep);
|
||||
sscanf(rep, "%d", &rep_d);
|
||||
if ((rep_d != N_INSERTS) && (j != (failed_transaction_num - 1)))
|
||||
{
|
||||
Test->add_result(1, "Transaction %d did not put data into slave\n", j);
|
||||
}
|
||||
if ((j == (failed_transaction_num - 1)) && (rep_d != 0) && (rep_d != N_INSERTS))
|
||||
{
|
||||
Test->add_result(1, "Incomplete transaction detected - %d\n", j);
|
||||
}
|
||||
if ((j == (failed_transaction_num - 1) && rep_d == 0))
|
||||
{
|
||||
Test->tprintf("Transaction %d was rejected, OK\n", j);
|
||||
}
|
||||
}
|
||||
}
|
||||
Test->repl->close_connections();
|
||||
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
const char * setup_slave1 =
|
||||
"change master to MASTER_HOST='%s',\
|
||||
MASTER_USER='repl',\
|
||||
MASTER_PASSWORD='repl',\
|
||||
MASTER_LOG_FILE='%s',\
|
||||
MASTER_LOG_POS=%s,\
|
||||
MASTER_PORT=%d";
|
||||
|
||||
|
||||
int select_new_master(TestConnections * test)
|
||||
{
|
||||
char log_file[256];
|
||||
char log_file_new[256];
|
||||
char log_pos[256];
|
||||
|
||||
char maxscale_log_file[256];
|
||||
char maxscale_log_file_new[256];
|
||||
char maxscale_log_pos[256];
|
||||
|
||||
// Stopping slave
|
||||
test->tprintf("Connection to backend\n");
|
||||
test->repl->connect();
|
||||
test->tprintf("'stop slave' to node2\n");
|
||||
test->try_query(Test->repl->nodes[2], (char *) "stop slave;");
|
||||
test->tprintf("'reset slave all' to node2\n");
|
||||
test->try_query(Test->repl->nodes[2], (char *) "RESET slave all;");
|
||||
//execute_query(Test->repl->nodes[2], (char *) "reset master;");
|
||||
|
||||
// Get master status
|
||||
test->tprintf("show master status\n");
|
||||
find_field(test->repl->nodes[2], (char *) "show master status", (char *) "File", &log_file[0]);
|
||||
find_field(test->repl->nodes[2], (char *) "show master status", (char *) "Position", &log_pos[0]);
|
||||
test->tprintf("Real master file: %s\n", log_file);
|
||||
test->tprintf("Real master pos : %s\n", log_pos);
|
||||
|
||||
test->tprintf("Connecting to MaxScale binlog router (with any DB)\n");
|
||||
MYSQL * binlog = open_conn_no_db(test->binlog_port, test->maxscale_IP, test->repl->user_name,
|
||||
test->repl->password, test->ssl);
|
||||
test->add_result(mysql_errno(binlog), "Error connection to binlog router %s\n", mysql_error(binlog));
|
||||
|
||||
test->tprintf("show master status on maxscale\n");
|
||||
find_field(binlog, (char *) "show master status", (char *) "File", &maxscale_log_file[0]);
|
||||
find_field(binlog, (char *) "show master status", (char *) "Position", &maxscale_log_pos[0]);
|
||||
|
||||
if (!maxscale_log_file[0] || !maxscale_log_pos[0])
|
||||
{
|
||||
test->add_result(1, "Failed to query for master status");
|
||||
return 1;
|
||||
}
|
||||
|
||||
test->tprintf("Real master file: %s\n", maxscale_log_file);
|
||||
test->tprintf("Real master pos : %s\n", maxscale_log_pos);
|
||||
|
||||
char * p = strchr(maxscale_log_file, '.') + 1;
|
||||
test->tprintf("log file num %s\n", p);
|
||||
int pd;
|
||||
sscanf(p, "%d", &pd);
|
||||
test->tprintf("log file num (d) %d\n", pd);
|
||||
p[0] = '\0';
|
||||
test->tprintf("log file name %s\n", maxscale_log_file);
|
||||
sprintf(maxscale_log_file_new, "%s%06d", maxscale_log_file, pd + 1);
|
||||
|
||||
test->try_query(test->repl->nodes[2], (char *) "reset master");
|
||||
test->tprintf("Flush logs %d times\n", pd + 1);
|
||||
for (int k = 0; k < pd + 1; k++)
|
||||
{
|
||||
test->try_query(test->repl->nodes[2], (char *) "flush logs");
|
||||
}
|
||||
|
||||
// Set Maxscale to new master
|
||||
test->try_query(binlog, "stop slave");
|
||||
test->tprintf("configuring Maxscale binlog router\n");
|
||||
|
||||
|
||||
test->tprintf("reconnect to binlog\n");
|
||||
mysql_close(binlog);
|
||||
binlog = open_conn_no_db(test->binlog_port, test->maxscale_IP, test->repl->user_name, test->repl->password,
|
||||
test->ssl);
|
||||
test->add_result(mysql_errno(binlog), "Error connection to binlog router %s\n", mysql_error(binlog));
|
||||
|
||||
char str[1024];
|
||||
//sprintf(str, setup_slave1, test->repl->IP[2], log_file_new, test->repl->port[2]);
|
||||
sprintf(str, setup_slave1, test->repl->IP[2], maxscale_log_file_new, "4", test->repl->port[2]);
|
||||
test->tprintf("change master query: %s\n", str);
|
||||
test->try_query(binlog, str);
|
||||
|
||||
test->try_query(binlog, "start slave");
|
||||
|
||||
test->repl->close_connections();
|
||||
|
||||
}
|
||||
|
||||
void *disconnect_thread( void *ptr )
|
||||
{
|
||||
MYSQL * conn;
|
||||
char cmd[256];
|
||||
int i;
|
||||
conn = open_conn(Test->binlog_port, Test->maxscale_IP, Test->repl->user_name, Test->repl->password,
|
||||
Test->repl->ssl);
|
||||
Test->add_result(mysql_errno(conn), "Error connecting to Binlog router, error: %s\n", mysql_error(conn));
|
||||
i = 3;
|
||||
while (exit_flag == 0)
|
||||
{
|
||||
sprintf(cmd, "DISCONNECT SERVER %d", i);
|
||||
execute_query(conn, cmd);
|
||||
i++;
|
||||
if (i > Test->repl->N)
|
||||
{
|
||||
i = 3;
|
||||
sleep(30);
|
||||
execute_query(conn, (char *) "DISCONNECT SERVER ALL");
|
||||
}
|
||||
sleep(5);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void *transaction_thread( void *ptr )
|
||||
{
|
||||
MYSQL * conn;
|
||||
int trans_result = 0;
|
||||
|
||||
conn = open_conn_db_timeout(Test->repl->port[master], Test->repl->IP[master], (char *) "test",
|
||||
Test->repl->user_name, Test->repl->password, 20, Test->repl->ssl);
|
||||
Test->add_result(mysql_errno(conn), "Error connecting to Binlog router, error: %s\n", mysql_error(conn));
|
||||
create_t1(conn);
|
||||
|
||||
while ((exit_flag == 0))
|
||||
{
|
||||
Test->tprintf("Transaction %d\n", i_trans);
|
||||
trans_result = transaction(conn, i_trans);
|
||||
if (trans_result != 0)
|
||||
{
|
||||
Test->tprintf("Transaction %d failed, doing master failover\n", i_trans);
|
||||
failed_transaction_num = i_trans;
|
||||
Test->tprintf("Closing connection\n");
|
||||
mysql_close(conn);
|
||||
Test->tprintf("Calling select_new_master()\n");
|
||||
select_new_master(Test);
|
||||
master = 2;
|
||||
|
||||
conn = open_conn_db_timeout(Test->repl->port[master], Test->repl->IP[master], (char *) "test",
|
||||
Test->repl->user_name, Test->repl->password, 20, Test->repl->ssl);
|
||||
Test->add_result(mysql_errno(conn), "Error connecting to Binlog router, error: %s\n", mysql_error(conn));
|
||||
Test->tprintf("Retrying transaction %d\n", i_trans);
|
||||
i_trans--;
|
||||
}
|
||||
i_trans++;
|
||||
}
|
||||
i_trans--;
|
||||
|
||||
return NULL;
|
||||
}
|
12
maxscale-system-test/binlog_enc_aes_cbc.cnf
Normal file
12
maxscale-system-test/binlog_enc_aes_cbc.cnf
Normal file
@ -0,0 +1,12 @@
|
||||
[mysqld]
|
||||
plugin-load-add=file_key_management.so
|
||||
file_key_management_encryption_algorithm=aes_cbc
|
||||
file_key_management_filename = /etc/mariadb_binlog_keys.txt
|
||||
encrypt-binlog=1
|
||||
|
||||
# Enable checksum
|
||||
binlog_checksum=CRC32
|
||||
|
||||
#Enable large packets handling
|
||||
max_allowed_packet=1042M
|
||||
innodb_log_file_size=142M
|
12
maxscale-system-test/binlog_enc_aes_ctr.cnf
Normal file
12
maxscale-system-test/binlog_enc_aes_ctr.cnf
Normal file
@ -0,0 +1,12 @@
|
||||
[mysqld]
|
||||
plugin-load-add=file_key_management.so
|
||||
file_key_management_encryption_algorithm=aes_ctr
|
||||
file_key_management_filename = /etc/mariadb_binlog_keys.txt
|
||||
encrypt-binlog=1
|
||||
|
||||
# Enable checksum
|
||||
binlog_checksum=CRC32
|
||||
|
||||
#Enable large packets handling
|
||||
max_allowed_packet=1042M
|
||||
innodb_log_file_size=142M
|
16
maxscale-system-test/binlog_failover.cpp
Normal file
16
maxscale-system-test/binlog_failover.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @file binlog_failover.cpp binlog_failover Test of failover scenarion for binlog router
|
||||
*
|
||||
* - setup following configuration:
|
||||
* - one master
|
||||
* - two maxscale binlog machines
|
||||
* - two slaves connected to each maxscale binlog mashine
|
||||
* - put some date via master
|
||||
* - block master
|
||||
* - stop all Maxscale machines with STOP SLAVE command
|
||||
* - check which Maxscale machine contains most recent data (let's call this machine 'most_recent_maxscale')
|
||||
* - use CHANGE MASETER on the second Maxscale machine to point it to the Maxscale machine from the previous step ('most_recent_maxscale')
|
||||
* - wait until second Maxscale is in sync with 'most_recent_maxscale' (use SHOW MASTER STATUS)
|
||||
* - select new master (HOW??)
|
||||
* - set all Maxscale machines to be a slaves of new master
|
||||
*/
|
26
maxscale-system-test/binlog_incompl.cpp
Normal file
26
maxscale-system-test/binlog_incompl.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @file setup_incompl trying to start binlog setup with incomplete Maxscale.cnf
|
||||
* check for crash
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "maxadmin_operations.h"
|
||||
#include "sql_t1.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
|
||||
Test->set_timeout(60);
|
||||
Test->connect_maxscale();
|
||||
Test->close_maxscale_connections();
|
||||
sleep(10);
|
||||
Test->check_log_err("fatal signal 11", false);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
91
maxscale-system-test/binlog_semisync.cpp
Normal file
91
maxscale-system-test/binlog_semisync.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @file binlog_semisync.cpp Same test as setup_binlog, but with semisync enabled
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "maxadmin_operations.h"
|
||||
#include "sql_t1.h"
|
||||
|
||||
#include "test_binlog_fnc.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->tprintf("Test object initialized\n");
|
||||
Test->set_timeout(3000);
|
||||
int options_set = 3;
|
||||
if (Test->smoke)
|
||||
{
|
||||
options_set = 1;
|
||||
}
|
||||
Test->tprintf("Trying to connect to backend\n");
|
||||
if (Test->repl->connect() == 0)
|
||||
{
|
||||
Test->tprintf("DROP TABLE t1\n");
|
||||
execute_query(Test->repl->nodes[0], (char *) "DROP TABLE IF EXISTS t1;");
|
||||
|
||||
//Test->tprintf("SET GLOBAL rpl_semi_sync_master_enabled = 1;\n");
|
||||
//execute_query(Test->repl->nodes[0], (char *) "SET GLOBAL rpl_semi_sync_master_enabled = 1;");
|
||||
Test->repl->close_connections();
|
||||
sleep(5);
|
||||
|
||||
|
||||
for (int option = 0; option < options_set; option++)
|
||||
{
|
||||
Test->binlog_cmd_option = option;
|
||||
Test->start_binlog();
|
||||
Test->repl->connect();
|
||||
Test->tprintf("install semisync plugin\n");
|
||||
execute_query(Test->repl->nodes[0],
|
||||
(char *) "INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';");
|
||||
//sleep(10);
|
||||
Test->tprintf("Reconnect\n");
|
||||
Test->repl->close_connections();
|
||||
Test->repl->connect();
|
||||
Test->tprintf("SET GLOBAL rpl_semi_sync_master_enabled = 1;\n");
|
||||
execute_query(Test->repl->nodes[0], (char *) "SET GLOBAL rpl_semi_sync_master_enabled = 1;");
|
||||
//sleep(10);
|
||||
Test->repl->close_connections();
|
||||
test_binlog(Test);
|
||||
|
||||
Test->repl->connect();
|
||||
Test->tprintf("SET GLOBAL rpl_semi_sync_master_enabled = 0;\n");
|
||||
execute_query(Test->repl->nodes[0], (char *) "SET GLOBAL rpl_semi_sync_master_enabled = 0;");
|
||||
//sleep(10);
|
||||
Test->repl->close_connections();
|
||||
test_binlog(Test);
|
||||
|
||||
Test->repl->connect();
|
||||
Test->tprintf("uninstall semisync plugin\n");
|
||||
execute_query(Test->repl->nodes[0], (char *) "UNINSTALL PLUGIN rpl_semi_sync_master;");
|
||||
Test->tprintf("Reconnect\n");
|
||||
Test->repl->close_connections();
|
||||
Test->repl->connect();
|
||||
Test->tprintf("SET GLOBAL rpl_semi_sync_master_enabled = 1;\n");
|
||||
execute_query(Test->repl->nodes[0], (char *) "SET GLOBAL rpl_semi_sync_master_enabled = 1;");
|
||||
//sleep(10);
|
||||
Test->repl->close_connections();
|
||||
test_binlog(Test);
|
||||
|
||||
Test->repl->connect();
|
||||
Test->tprintf("SET GLOBAL rpl_semi_sync_master_enabled = 0;\n");
|
||||
execute_query(Test->repl->nodes[0], (char *) "SET GLOBAL rpl_semi_sync_master_enabled = 0;");
|
||||
sleep(10);
|
||||
Test->repl->close_connections();
|
||||
test_binlog(Test);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->add_result(1, "Can't connect to backend\n");
|
||||
}
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
193
maxscale-system-test/blob_test.cpp
Normal file
193
maxscale-system-test/blob_test.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
#include "blob_test.h"
|
||||
|
||||
int test_longblob(TestConnections* Test, MYSQL * conn, char * blob_name, unsigned long chunk_size, int chunks,
|
||||
int rows)
|
||||
{
|
||||
unsigned long size = chunk_size;
|
||||
unsigned long * data;
|
||||
unsigned long i, j;
|
||||
MYSQL_BIND param[1];
|
||||
char sql[256];
|
||||
int global_res = Test->global_result;
|
||||
//Test->tprintf("chunk size %lu chunks %d inserts %d\n", chunk_size, chunks, rows);
|
||||
|
||||
char *insert_stmt = (char *) "INSERT INTO long_blob_table(x, b) VALUES(1, ?)";
|
||||
|
||||
Test->tprintf("Creating table with %s\n", blob_name);
|
||||
Test->try_query(conn, (char *) "DROP TABLE IF EXISTS long_blob_table");
|
||||
sprintf(sql, "CREATE TABLE long_blob_table(id int NOT NULL AUTO_INCREMENT, x INT, b %s, PRIMARY KEY (id))",
|
||||
blob_name);
|
||||
Test->try_query(conn, sql);
|
||||
|
||||
for (int k = 0; k < rows; k++)
|
||||
{
|
||||
Test->tprintf("Preparintg INSERT stmt\n");
|
||||
MYSQL_STMT * stmt = mysql_stmt_init(conn);
|
||||
if (stmt == NULL)
|
||||
{
|
||||
Test->add_result(1, "stmt init error: %s\n", mysql_error(conn));
|
||||
}
|
||||
|
||||
Test->add_result(mysql_stmt_prepare(stmt, insert_stmt, strlen(insert_stmt)), "Error preparing stmt: %s\n",
|
||||
mysql_stmt_error(stmt));
|
||||
|
||||
param[0].buffer_type = MYSQL_TYPE_STRING;
|
||||
param[0].is_null = 0;
|
||||
|
||||
Test->tprintf("Binding parameter\n");
|
||||
Test->add_result(mysql_stmt_bind_param(stmt, param), "Error parameter binding: %s\n", mysql_stmt_error(stmt));
|
||||
|
||||
Test->tprintf("Filling buffer\n");
|
||||
data = (unsigned long *) malloc(size * sizeof(long int));
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
Test->add_result(1, "Memory allocation error\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Test->tprintf("Sending data in %d bytes chunks, total size is %d\n", size * sizeof(unsigned long),
|
||||
(size * sizeof(unsigned long)) * chunks);
|
||||
for (i = 0; i < chunks; i++)
|
||||
{
|
||||
for (j = 0; j < size; j++)
|
||||
{
|
||||
data[j] = j + i * size;
|
||||
}
|
||||
Test->set_timeout(300);
|
||||
Test->tprintf("Chunk #%d\n", i);
|
||||
if (mysql_stmt_send_long_data(stmt, 0, (char *) data, size * sizeof(unsigned long)) != 0)
|
||||
{
|
||||
Test->add_result(1, "Error inserting data, iteration %d, error %s\n", i, mysql_stmt_error(stmt));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
//for (int k = 0; k < rows; k++)
|
||||
//{
|
||||
Test->tprintf("Executing statement: %02d\n", k);
|
||||
Test->set_timeout(3000);
|
||||
Test->add_result(mysql_stmt_execute(stmt), "INSERT Statement with %s failed, error is %s\n", blob_name,
|
||||
mysql_stmt_error(stmt));
|
||||
//}
|
||||
Test->add_result(mysql_stmt_close(stmt), "Error closing stmt\n");
|
||||
}
|
||||
|
||||
if (global_res == Test->global_result)
|
||||
{
|
||||
Test->tprintf("%s is OK\n", blob_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->tprintf("%s FAILED\n", blob_name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_longblob_data(TestConnections* Test, MYSQL * conn, unsigned long chunk_size, int chunks,
|
||||
int rows)
|
||||
{
|
||||
//char *select_stmt = (char *) "SELECT id, x, b FROM long_blob_table WHERE id = ?";
|
||||
char *select_stmt = (char *) "SELECT id, x, b FROM long_blob_table ";
|
||||
MYSQL_STMT * stmt = mysql_stmt_init(Test->conn_rwsplit);
|
||||
if (stmt == NULL)
|
||||
{
|
||||
Test->add_result(1, "stmt init error: %s\n", mysql_error(Test->conn_rwsplit));
|
||||
}
|
||||
|
||||
Test->add_result(mysql_stmt_prepare(stmt, select_stmt, strlen(select_stmt)), "Error preparing stmt: %s\n",
|
||||
mysql_stmt_error(stmt));
|
||||
|
||||
MYSQL_BIND param[1], result[3];
|
||||
int id = 1;
|
||||
|
||||
memset(param, 0, sizeof(param));
|
||||
memset(result, 0, sizeof(result));
|
||||
|
||||
param[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
param[0].buffer = &id;
|
||||
|
||||
unsigned long * data = (unsigned long *) malloc(chunk_size * chunks * sizeof(long int));
|
||||
|
||||
|
||||
int r_id;
|
||||
int r_x;
|
||||
unsigned long l_id;
|
||||
unsigned long l_x;
|
||||
my_bool b_id;
|
||||
my_bool b_x;
|
||||
my_bool e_id;
|
||||
my_bool e_x;
|
||||
|
||||
result[0].buffer_type = MYSQL_TYPE_LONG;
|
||||
result[0].buffer = &r_id;
|
||||
result[0].buffer_length = 0;
|
||||
result[0].length = &l_id;
|
||||
result[0].is_null = &b_id;
|
||||
result[0].error = &e_id;
|
||||
|
||||
result[1].buffer_type = MYSQL_TYPE_LONG;
|
||||
result[1].buffer = &r_x;
|
||||
result[1].buffer_length = 0;
|
||||
result[1].length = &l_x;
|
||||
result[1].is_null = &b_x;
|
||||
result[1].error = &e_x;
|
||||
|
||||
result[2].buffer_type = MYSQL_TYPE_LONG_BLOB;
|
||||
result[2].buffer = data;
|
||||
result[2].buffer_length = chunk_size * chunks * sizeof(long int);
|
||||
|
||||
/*
|
||||
if (mysql_stmt_bind_param(stmt, param) != 0)
|
||||
{
|
||||
printf("Could not bind parameters\n");
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
if (mysql_stmt_bind_result(stmt, result) != 0)
|
||||
{
|
||||
printf("Could not bind results\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mysql_stmt_execute(stmt) != 0)
|
||||
{
|
||||
Test->tprintf("Error executing stmt %s\n", mysql_error(Test->conn_rwsplit));
|
||||
}
|
||||
|
||||
if (mysql_stmt_store_result(stmt) != 0)
|
||||
{
|
||||
printf("Could not buffer result set\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int row = 0;
|
||||
while (!mysql_stmt_fetch(stmt))
|
||||
{
|
||||
Test->tprintf("id=%d\tx=%d\n", r_id, r_x);
|
||||
if (r_id != row + 1)
|
||||
{
|
||||
Test->add_result(1, "id field is wrong! Expected %d, but it is %d\n", row + 1, r_id);
|
||||
}
|
||||
for (int y = 0; y < chunk_size * chunks; y++)
|
||||
{
|
||||
if (data[y] != y)
|
||||
{
|
||||
Test->add_result(1, "Data is wrong!\n");
|
||||
}
|
||||
//printf("y = %d \t%lu\tid=%d\tx=%d\n", y, data[y], r_id, r_x);
|
||||
}
|
||||
row++;
|
||||
}
|
||||
if (row != rows)
|
||||
{
|
||||
Test->add_result(1, "Wrong number of rows in the table! Expected %d, but it is %d\n", rows, row);
|
||||
}
|
||||
mysql_stmt_free_result(stmt);
|
||||
|
||||
mysql_stmt_close(stmt);
|
||||
}
|
||||
|
||||
|
32
maxscale-system-test/blob_test.h
Normal file
32
maxscale-system-test/blob_test.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef BLOB_TEST_H
|
||||
#define BLOB_TEST_H
|
||||
|
||||
#include "testconnections.h"
|
||||
|
||||
/**
|
||||
* @brief test_longblob INSERT big amount of data into lobg_blob_table
|
||||
* @param Test TestConnection object
|
||||
* @param conn MYSQL connection handler
|
||||
* @param blob_name blob type (LONGBLOB; MEDIUMBLOB or BLOB)
|
||||
* @param chunk_size size of one data chunk (in sizeof(long usingned))
|
||||
* @param chunks number of chunks to INSERT
|
||||
* @param rows number of rows to INSERT (executes INSERT stetament 'rows' times)
|
||||
* @return 0 in case of success
|
||||
*/
|
||||
int test_longblob(TestConnections* Test, MYSQL * conn, char * blob_name, unsigned long chunk_size, int chunks,
|
||||
int rows);
|
||||
|
||||
|
||||
/**
|
||||
* @brief check_longblob_data Does SELECT against table created by test_longblob() and cheks that data are correct
|
||||
* @param Test TestConnection object
|
||||
* @param conn MYSQL connection handler
|
||||
* @param chunk_size size of one data chunk (in sizeof(long usingned))
|
||||
* @param chunks number of chunks in the table
|
||||
* @param rows number of rows in the table
|
||||
* @return 0 in case of success
|
||||
*/
|
||||
int check_longblob_data(TestConnections* Test, MYSQL * conn, unsigned long chunk_size, int chunks,
|
||||
int rows);
|
||||
|
||||
#endif // BLOB_TEST_H
|
68
maxscale-system-test/bug143.cpp
Normal file
68
maxscale-system-test/bug143.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @file bug143.cpp bug143 regression case (MaxScale ignores host in user authentication)
|
||||
*
|
||||
* - create user@'non_existing_host1', user@'%', user@'non_existing_host2' identified by different passwords.
|
||||
* - try to connect using RWSplit. First and third are expected to fail, second should succeed.
|
||||
*/
|
||||
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
|
||||
Test->tprintf("Creating user 'user' with 3 different passwords for different hosts\n");
|
||||
Test->connect_maxscale();
|
||||
execute_query(Test->conn_rwsplit, "CREATE USER 'user'@'non_existing_host1' IDENTIFIED BY 'pass1'");
|
||||
execute_query(Test->conn_rwsplit, "CREATE USER 'user'@'%%' IDENTIFIED BY 'pass2'");
|
||||
execute_query(Test->conn_rwsplit, "CREATE USER 'user'@'non_existing_host2' IDENTIFIED BY 'pass3'");
|
||||
execute_query(Test->conn_rwsplit, "GRANT ALL PRIVILEGES ON *.* TO 'user'@'non_existing_host1'");
|
||||
execute_query(Test->conn_rwsplit, "GRANT ALL PRIVILEGES ON *.* TO 'user'@'%%'");
|
||||
execute_query(Test->conn_rwsplit, "GRANT ALL PRIVILEGES ON *.* TO 'user'@'non_existing_host2'");
|
||||
|
||||
Test->tprintf("Synchronizing slaves");
|
||||
Test->set_timeout(50);
|
||||
Test->repl->sync_slaves();
|
||||
|
||||
Test->tprintf("Trying first hostname, expecting failure");
|
||||
Test->set_timeout(15);
|
||||
MYSQL * conn = open_conn(Test->rwsplit_port, Test->maxscale_IP, (char *) "user", (char *) "pass1", Test->ssl);
|
||||
if (mysql_errno(conn) == 0)
|
||||
{
|
||||
Test->add_result(1, "MaxScale ignores host in authentication\n");
|
||||
}
|
||||
if (conn != NULL)
|
||||
{
|
||||
mysql_close(conn);
|
||||
}
|
||||
|
||||
Test->tprintf("Trying second hostname, expecting success");
|
||||
Test->set_timeout(15);
|
||||
conn = open_conn(Test->rwsplit_port, Test->maxscale_IP, (char *) "user", (char *) "pass2", Test->ssl);
|
||||
Test->add_result(mysql_errno(conn), "MaxScale can't connect: %s\n", mysql_error(conn));
|
||||
if (conn != NULL)
|
||||
{
|
||||
mysql_close(conn);
|
||||
}
|
||||
|
||||
Test->tprintf("Trying third hostname, expecting failure");
|
||||
Test->set_timeout(15);
|
||||
conn = open_conn(Test->rwsplit_port, Test->maxscale_IP, (char *) "user", (char *) "pass3", Test->ssl);
|
||||
if (mysql_errno(conn) == 0)
|
||||
{
|
||||
Test->add_result(1, "MaxScale ignores host in authentication\n");
|
||||
}
|
||||
if (conn != NULL)
|
||||
{
|
||||
mysql_close(conn);
|
||||
}
|
||||
|
||||
execute_query(Test->conn_rwsplit, "DROP USER 'user'@'non_existing_host1'");
|
||||
execute_query(Test->conn_rwsplit, "DROP USER 'user'@'%%'");
|
||||
execute_query(Test->conn_rwsplit, "DROP USER 'user'@'non_existing_host2'");
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
51
maxscale-system-test/bug359.cpp
Normal file
51
maxscale-system-test/bug359.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file bug359.cpp bug359 regression case (router_options in readwritesplit causes errors in error log)
|
||||
*
|
||||
* - Maxscale.cnf contains RWSplit router definition with router_option=slave.
|
||||
* - error is expected in the log. Maxscale should not start.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Massimiliano 2013-11-22 09:45:13 UTC
|
||||
Setting router_options=slave in readwritesplit causes:
|
||||
|
||||
in the error log
|
||||
|
||||
2013 11/22 10:35:43 Error : Couldn't find suitable Master from 3 candidates.
|
||||
2013 11/22 10:35:43 Error : Failed to create router client session. Freeing allocated resources.
|
||||
|
||||
|
||||
If no options are allowed here, it could be better to log this and/or unload the module
|
||||
|
||||
|
||||
This is something could happen doing copy paste from readconnrouter as an example
|
||||
Comment 1 Mark Riddoch 2014-02-05 11:35:57 UTC
|
||||
I makes no sense for the read/write splitter to look at the slave and master router options.
|
||||
|
||||
Vilho Raatikka 2014-05-22 07:02:50 UTC
|
||||
Added check for router option 'synced' which accepts only that, and warns the user of other unsupported options ('master'|'slave' for example). If router option is specified for read write split router, only a node in 'joined' state will be accepted as eligible backend candidate.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
Test->check_log_err((char *) "Unsupported router option \"slave\"", true);
|
||||
Test->check_log_err((char *) "Failed to start all MaxScale services. Exiting", true);
|
||||
Test->check_log_err((char *) "Couldn't find suitable Master", false);
|
||||
//Test->check_maxscale_alive();
|
||||
Test->check_maxscale_processes(0);
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
122
maxscale-system-test/bug422.cpp
Normal file
122
maxscale-system-test/bug422.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/**
|
||||
* @file bug422.cpp bug422 regression case ( Executing '\s' doesn't always produce complete result set)
|
||||
*
|
||||
* Test executes "show status" 1000 times against all Maxscale services and checks Maxscale is alive after it.
|
||||
*/
|
||||
|
||||
/*
|
||||
Vilho Raatikka 2014-04-15 07:03:03 UTC
|
||||
Read/write split router
|
||||
-------------------------
|
||||
|
||||
Login to MaxScale & read/write split router, for example
|
||||
|
||||
mysql --host=127.0.0.1 -P 4006 -u maxuser -pmaxpwd
|
||||
|
||||
Complete result :
|
||||
|
||||
MySQL [(none)]> \s
|
||||
--------------
|
||||
mysql Ver 15.1 Distrib 5.5.33-MariaDB, for Linux (x86_64) using readline 5.1
|
||||
|
||||
Connection id: 4051
|
||||
Current database:
|
||||
Current user: maxuser@localhost
|
||||
SSL: Not in use
|
||||
Current pager: less
|
||||
Using outfile: ''
|
||||
Using delimiter: ;
|
||||
Server: MySQL
|
||||
Server version: MaxScale 0.5.0 Source distribution
|
||||
Protocol version: 10
|
||||
Connection: 127.0.0.1 via TCP/IP
|
||||
Server characterset: latin1
|
||||
Db characterset: latin1
|
||||
Client characterset: latin1
|
||||
Conn. characterset: latin1
|
||||
TCP port: 4006
|
||||
Uptime: 34 min 23 sec
|
||||
|
||||
Threads: 5 Questions: 206 Slow queries: 0 Opens: 0 Flush tables: 2 Open tables: 26 Queries per second avg: 0.099
|
||||
--------------
|
||||
|
||||
|
||||
By running same a few time in a row, an incomplete result set arrives, like the following:
|
||||
|
||||
MySQL [(none)]> \s
|
||||
--------------
|
||||
mysql Ver 15.1 Distrib 5.5.33-MariaDB, for Linux (x86_64) using readline 5.1
|
||||
|
||||
Connection id: 4051
|
||||
Current database:
|
||||
Current user: maxuser@localhost
|
||||
SSL: Not in use
|
||||
Current pager: less
|
||||
Using outfile: ''
|
||||
Using delimiter: ;
|
||||
Server: MySQL
|
||||
Server version: MaxScale 0.5.0 Source distribution
|
||||
Protocol version: 10
|
||||
Connection: 127.0.0.1 via TCP/IP
|
||||
Server characterset: latin1
|
||||
Db characterset: latin1
|
||||
Client characterset: latin1
|
||||
Conn. characterset: latin1
|
||||
TCP port: 4006
|
||||
--------------
|
||||
|
||||
MySQL [(none)]>
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
int i;
|
||||
int iterations = 1000;
|
||||
if (Test->smoke)
|
||||
{
|
||||
iterations = 100;
|
||||
}
|
||||
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->tprintf("Connecting to all MaxScale services\n");
|
||||
Test->add_result(Test->connect_maxscale(), "Can not connect to Maxscale\n");
|
||||
|
||||
Test->tprintf("executing show status %d times\n", iterations);
|
||||
|
||||
|
||||
for (i = 0; i < iterations; i++)
|
||||
{
|
||||
Test->set_timeout(5);
|
||||
Test->add_result(execute_query(Test->conn_rwsplit, (char *) "show status"),
|
||||
"Query %d agains RWSplit failed\n", i);
|
||||
}
|
||||
for (i = 0; i < iterations; i++)
|
||||
{
|
||||
Test->set_timeout(5);
|
||||
Test->add_result(execute_query(Test->conn_slave, (char *) "show status"),
|
||||
"Query %d agains ReadConn Slave failed\n", i);
|
||||
}
|
||||
for (i = 0; i < iterations; i++)
|
||||
{
|
||||
Test->set_timeout(5);
|
||||
Test->add_result(execute_query(Test->conn_master, (char *) "show status"),
|
||||
"Query %d agains ReadConn Master failed\n", i);
|
||||
}
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->close_maxscale_connections();
|
||||
Test->check_maxscale_alive();
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
71
maxscale-system-test/bug448.cpp
Normal file
71
maxscale-system-test/bug448.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @file bug448.cpp bug448 regression case ("Wildcard in host column of mysql.user table don't work properly")
|
||||
*
|
||||
* Test creates user1@xxx.%.%.% and tries to use it to connect
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "get_my_ip.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char my_ip[1024];
|
||||
char my_ip_db[1024];
|
||||
char sql[1024];
|
||||
char * first_dot;
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
|
||||
Test->set_timeout(20);
|
||||
Test->repl->connect();
|
||||
|
||||
get_my_ip(Test->maxscale_IP, my_ip);
|
||||
Test->tprintf("Test machine IP (got via network request) %s\n", my_ip);
|
||||
|
||||
Test->add_result(Test->get_client_ip(my_ip_db), "Unable to get IP using connection to DB\n");
|
||||
|
||||
Test->tprintf("Test machine IP (got via Show processlist) %s\n", my_ip);
|
||||
|
||||
first_dot = strstr(my_ip, ".");
|
||||
strcpy(first_dot, ".%.%.%");
|
||||
|
||||
Test->tprintf("Test machine IP with %% %s\n", my_ip);
|
||||
|
||||
Test->tprintf("Connecting to Maxscale\n");
|
||||
Test->add_result(Test->connect_maxscale(), "Error connecting to Maxscale\n");
|
||||
Test->tprintf("Creating user 'user1' for %s host\n", my_ip);
|
||||
Test->set_timeout(30);
|
||||
|
||||
Test->add_result(execute_query(Test->conn_rwsplit, "CREATE USER user1@'%s';", my_ip),
|
||||
"Failed to create user");
|
||||
Test->add_result(execute_query(Test->conn_rwsplit,
|
||||
"GRANT ALL PRIVILEGES ON *.* TO user1@'%s' identified by 'pass1'; FLUSH PRIVILEGES;", my_ip),
|
||||
"Failed to grant privileges.");
|
||||
|
||||
Test->tprintf("Trying to open connection using user1\n");
|
||||
|
||||
MYSQL * conn = open_conn(Test->rwsplit_port, Test->maxscale_IP, (char *) "user1", (char *) "pass1",
|
||||
Test->ssl);
|
||||
if (mysql_errno(conn) != 0)
|
||||
{
|
||||
Test->add_result(1, "TEST_FAILED! Authentification failed! error: %s\n", mysql_error(conn));
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->tprintf("Authentification for user@'%s' is ok", my_ip);
|
||||
if (conn != NULL)
|
||||
{
|
||||
mysql_close(conn);
|
||||
}
|
||||
}
|
||||
|
||||
Test->add_result(execute_query(Test->conn_rwsplit, "DROP USER user1@'%s'; FLUSH PRIVILEGES;", my_ip),
|
||||
"Query Failed\n");
|
||||
|
||||
Test->close_maxscale_connections();
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
34
maxscale-system-test/bug466.cpp
Normal file
34
maxscale-system-test/bug466.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
int global_result = 0;
|
||||
|
||||
Test->ReadEnv();
|
||||
Test->PrintIP();
|
||||
|
||||
Test->ConnectMaxscale();
|
||||
|
||||
|
||||
execute_query(Test->conn_rwsplit, (char *) "select @@server_id; -- max_slave_replication_lag=120");
|
||||
|
||||
|
||||
|
||||
|
||||
Test->CloseMaxscaleConn();
|
||||
|
||||
|
||||
global_result += CheckMaxscaleAlive();
|
||||
|
||||
Test->Copy_all_logs();
|
||||
return global_result;
|
||||
}
|
||||
|
||||
|
89
maxscale-system-test/bug469.cpp
Normal file
89
maxscale-system-test/bug469.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @file bug469 bug469 regression test case ("rwsplit counts every connection twice in master - counnection counts leak")
|
||||
* - use maxadmin command "show server server1" and check "Current no. of conns" and "Number of connections" - both should be 0
|
||||
* - execute simple query against RWSplit
|
||||
* - use maxadmin command "show server server1" and check "Current no. of conns" (should be 0) and "Number of connections" (should be 1)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Vilho Raatikka 2014-08-05 12:28:21 UTC
|
||||
Every connection is counted twice in master and decremented only once. As a result master seems always to have active connections after first connection is established.
|
||||
|
||||
Server 0x21706e0 (server1)
|
||||
Server: 127.0.0.1
|
||||
Status: Master, Running
|
||||
Protocol: MySQLBackend
|
||||
Port: 3000
|
||||
Server Version: 5.5.37-MariaDB-debug-log
|
||||
Node Id: 3000
|
||||
Master Id: -1
|
||||
Slave Ids: 3001, 3002 , 3003
|
||||
Repl Depth: 0
|
||||
Number of connections: 6
|
||||
Current no. of conns: 3
|
||||
Current no. of operations: 0
|
||||
Server 0x21705e0 (server2)
|
||||
Server: 127.0.0.1
|
||||
Status: Slave, Running
|
||||
Protocol: MySQLBackend
|
||||
Port: 3001
|
||||
Server Version: 5.5.37-MariaDB-debug-log
|
||||
Node Id: 3001
|
||||
Master Id: 3000
|
||||
Slave Ids:
|
||||
Repl Depth: 1
|
||||
Number of connections: 3
|
||||
Current no. of conns: 0
|
||||
Current no. of operations: 0
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "maxadmin_operations.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
char res[1024];
|
||||
int res_d;
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->get_maxadmin_param((char *) "show server server1", (char *) "Current no. of conns:", res);
|
||||
sscanf(res, "%d", &res_d);
|
||||
Test->tprintf("Before: Current num of conn %d\n", res_d);
|
||||
Test->add_result(res_d, "curr num of conn is not 0\n");
|
||||
Test->get_maxadmin_param((char *) "show server server1", (char *) "Number of connections:", res);
|
||||
sscanf(res, "%d", &res_d);
|
||||
Test->tprintf("Before: num of conn %d\n", res_d);
|
||||
Test->add_result(res_d, "num of conn is not 0");
|
||||
|
||||
Test->connect_rwsplit();
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select 1");
|
||||
Test->close_rwsplit();
|
||||
|
||||
Test->stop_timeout();
|
||||
sleep(10);
|
||||
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->get_maxadmin_param((char *) "show server server1", (char *) "Current no. of conns:", res);
|
||||
sscanf(res, "%d", &res_d);
|
||||
Test->tprintf("After: Current num of conn %d\n", res_d);
|
||||
Test->add_result(res_d, "curr num of conn is not 0\n");
|
||||
Test->get_maxadmin_param((char *) "show server server1", (char *) "Number of connections:", res);
|
||||
sscanf(res, "%d", &res_d);
|
||||
Test->tprintf("After: num of conn %d\n", res_d);
|
||||
if (res_d != 1)
|
||||
{
|
||||
Test->add_result(1, "num of conn is not 1");
|
||||
}
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
193
maxscale-system-test/bug471.cpp
Normal file
193
maxscale-system-test/bug471.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
/**
|
||||
* @file bug471.cpp bug471 regression case ( Routing Hints route to server sometimes doesn't work )
|
||||
*
|
||||
* - try "select @@server_id; -- maxscale route to server server%d" (where %d - server number) and compares result
|
||||
* with "select @@server_id;" sent directly to backend node.
|
||||
* - do it 25 times.
|
||||
*/
|
||||
|
||||
/*
|
||||
Massimiliano 2014-08-06 13:27:05 UTC
|
||||
I found using basic routing hints such as:
|
||||
|
||||
select @@server_id; -- maxscale route to server server4
|
||||
select @@server_id; -- maxscale route to server server3
|
||||
select @@server_id; -- maxscale route to server server2
|
||||
|
||||
server3 is the current master
|
||||
|
||||
and server4 server_id is 4
|
||||
server3 server_id is 3
|
||||
server2 server_id is 2
|
||||
|
||||
sometimes I cannot get the expected results that are:
|
||||
|
||||
4
|
||||
3
|
||||
2
|
||||
|
||||
|
||||
Sometimes I got:
|
||||
|
||||
2
|
||||
3
|
||||
2
|
||||
|
||||
or
|
||||
|
||||
4
|
||||
3
|
||||
4
|
||||
|
||||
In maxScale configuration 5 servers defined:
|
||||
|
||||
server1 is not monitored but listed in [RW Split Service]
|
||||
server5 is always stopped
|
||||
|
||||
|
||||
|
||||
MaxScale configuration:
|
||||
|
||||
[gateway]
|
||||
threads=4
|
||||
|
||||
[RW Split Service]
|
||||
#Please note server1 is not monitored n MySQL Monitor section
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1,server2,server3,server5,server4
|
||||
max_slave_connections=100%
|
||||
max_slave_replication_lag=21
|
||||
user=massi
|
||||
passwd=massi
|
||||
enable_root_user=0
|
||||
filters=Hint
|
||||
|
||||
# Definition of the servers
|
||||
[server1]
|
||||
#not monitored
|
||||
type=server
|
||||
address=127.0.0.1
|
||||
port=3306
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server2]
|
||||
type=server
|
||||
address=127.0.0.1
|
||||
port=3307
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server3]
|
||||
type=server
|
||||
address=127.0.0.1
|
||||
port=3308
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server4]
|
||||
type=server
|
||||
address=127.0.0.1
|
||||
port=3309
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server5]
|
||||
#always stopped
|
||||
type=server
|
||||
address=127.0.0.1
|
||||
port=3310
|
||||
protocol=MySQLBackend
|
||||
|
||||
|
||||
[RW Split Listener]
|
||||
type=listener
|
||||
service=RW Split Service
|
||||
protocol=MySQLClient
|
||||
port=4606
|
||||
|
||||
[Hint]
|
||||
type=filter
|
||||
module=hintfilter
|
||||
|
||||
[MySQL Monitor]
|
||||
# Please note server1 is not monitored
|
||||
type=monitor
|
||||
module=mysqlmon
|
||||
servers=server4,server2,server3,server5
|
||||
user=massi
|
||||
passwd=massi
|
||||
detect_replication_lag=1
|
||||
monitor_interval=10001
|
||||
|
||||
|
||||
|
||||
Removing server1 from the service section gives right results for server_id selection
|
||||
|
||||
|
||||
|
||||
# mysql -c -h 127.0.0.1 -P 4606 -umassi -pmassi
|
||||
MariaDB> select @@server_id; -- maxscale route to server server4
|
||||
|
||||
|
||||
|
||||
Please not -c option that allows comments to be sent
|
||||
|
||||
|
||||
Vilho Raatikka 2014-08-08 08:13:42 UTC
|
||||
After further consideration we decided that the behavior is invalid. Routing hints should be followed if they don't violate database consistency nor cluster setup.
|
||||
Comment 11 Vilho Raatikka 2014-08-08 17:26:25 UTC
|
||||
Pushed fix in commit d4de582e1622908cc95396f57878f8691289c35b to Z2.
|
||||
Replication lag is not checked if routing hint is used.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->repl->connect();
|
||||
Test->add_result(Test->connect_maxscale(), "Failed to connect to MaxScale\n");
|
||||
|
||||
char server_id[256];
|
||||
char server_id_d[256];
|
||||
|
||||
char hint_sql[64];
|
||||
|
||||
for (int i = 1; i < 25; i++)
|
||||
{
|
||||
for (int j = 0; j < Test->repl->N; j++)
|
||||
{
|
||||
if (j != 1 )
|
||||
{
|
||||
Test->set_timeout(5);
|
||||
sprintf(hint_sql, "select @@server_id; -- maxscale route to server server%d", j + 1);
|
||||
|
||||
find_field(Test->conn_rwsplit, hint_sql, (char *) "@@server_id", &server_id[0]);
|
||||
find_field(Test->repl->nodes[j], (char *) "select @@server_id;", (char *) "@@server_id", &server_id_d[0]);
|
||||
|
||||
Test->tprintf("server%d ID from Maxscale: \t%s\n", j + 1, server_id);
|
||||
Test->tprintf("server%d ID directly from node: \t%s\n", j + 1, server_id_d);
|
||||
|
||||
Test->add_result(strcmp(server_id, server_id_d), "Hints does not work!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->close_maxscale_connections();
|
||||
Test->repl->close_connections();
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
98
maxscale-system-test/bug473.cpp
Normal file
98
maxscale-system-test/bug473.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @file bug473.cpp bug470, 472, 473 regression cases ( malformed hints cause crash )
|
||||
*
|
||||
* Test tries different hints with syntax errors (see source for details)
|
||||
*/
|
||||
|
||||
/*
|
||||
Markus Mäkelä 2014-08-07 09:21:44 UTC
|
||||
All of the following queries cause a segmentation fault:
|
||||
|
||||
select @@server_id; -- maxscale route to server =(
|
||||
select @@server_id; -- maxscale route to server =)
|
||||
select @@server_id; -- maxscale route to server =:
|
||||
select @@server_id; -- maxscale route to server =a
|
||||
select @@server_id; -- maxscale route to server = a
|
||||
|
||||
Most likely all variatios with the equals sign and a character after it cause the crash.
|
||||
|
||||
Call stack:
|
||||
|
||||
#0 __strncasecmp_l_sse2 () at ../sysdeps/x86_64/strcmp.S:209
|
||||
#1 0x00007fffdd0e9d0d in get_route_target (qtype=QUERY_TYPE_READ, trx_active=false, hint=0x74b830) at readwritesplit.c:1116
|
||||
#2 0x00007fffdd0ea494 in routeQuery (instance=0x72f960, router_session=0x73dbf0, querybuf=0x74b7a0) at readwritesplit.c:1346
|
||||
#3 0x00007fffd7191ed8 in routeQuery (instance=0x74b670, session=0x74b6b0, queue=0x74b7a0) at hintfilter.c:236
|
||||
#4 0x00007fffdc2a0b3d in route_by_statement (session=0x744ae0, readbuf=0x0) at mysql_client.c:1442
|
||||
#5 0x00007fffdc29f22c in gw_read_client_event (dcb=0x7446b0) at mysql_client.c:786
|
||||
#6 0x00000000004165da in poll_waitevents (arg=0x0) at poll.c:424
|
||||
#7 0x000000000040a72c in main (argc=4, argv=0x7fffffffe2e8) at gateway.c:1379
|
||||
|
||||
Failing point:
|
||||
|
||||
1114 else if (hint->type == HINT_PARAMETER)
|
||||
1115 {
|
||||
1116 if (strncasecmp(
|
||||
1117 (char *)hint->data,
|
||||
1118 "max_slave_replication_lag",
|
||||
1119 strlen("max_slave_replication_lag")) == 0)
|
||||
1120 {
|
||||
|
||||
|
||||
Value of hint:
|
||||
|
||||
$6 = {type = HINT_PARAMETER, data = 0x0, value = 0x743a60, dsize = 0, next = 0x0}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->add_result(Test->connect_maxscale(), "Can not connect to Maxscale\n");
|
||||
|
||||
|
||||
Test->tprintf("Trying queries that caused crashes before fix: bug473\n");
|
||||
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select @@server_id; -- maxscale route to server =(");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select @@server_id; -- maxscale route to server =)");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select @@server_id; -- maxscale route to server =:");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select @@server_id; -- maxscale route to server =a");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select @@server_id; -- maxscale route to server = a");
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "select @@server_id; -- maxscale route to server = кириллица åäö");
|
||||
|
||||
// bug472
|
||||
Test->tprintf("Trying queries that caused crashes before fix: bug472\n");
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "select @@server_id; -- maxscale s1 begin route to server server3");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select @@server_id; -- maxscale end");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select @@server_id; -- maxscale s1 begin");
|
||||
|
||||
// bug470
|
||||
Test->tprintf("Trying queries that caused crashes before fix: bug470\n");
|
||||
fflush(stdout);
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select @@server_id; -- maxscale named begin route to master");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select @@server_id;");
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "select @@server_id; -- maxscale named begin route to master; select @@server_id;");
|
||||
|
||||
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
Test->tprintf("Checking if Maxscale is alive\n");
|
||||
fflush(stdout);
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
51
maxscale-system-test/bug475.cpp
Normal file
51
maxscale-system-test/bug475.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file bug475.cpp regression case for bug 475 (The end comment tag in hints isn't properly detected)
|
||||
*
|
||||
* Test tries different hints with comments syntax and then checks log and checks if MaxScale is alive
|
||||
*/
|
||||
|
||||
//
|
||||
//Markus Mäkelä 2014-08-08 10:09:48 UTC
|
||||
//The closing tag isn't properly detected when using inline comments.
|
||||
//Multiple commands cause this behaviour. The following commands cause these messages in the error log:
|
||||
|
||||
//select /* maxscale hintname prepare route to master */ @@server_id;
|
||||
//2014 08/08 13:01:09 Error : Syntax error in hint. Expected 'master', 'slave', or 'server' instead of '*/'. Hint ignored.
|
||||
|
||||
//select /* maxscale hintname begin */ @@server_id;
|
||||
//2014 08/08 13:02:45 Error : Syntax error in hint. Expected '=', 'prepare', or 'start' instead of '@@server_id'. Hint ignored.
|
||||
|
||||
//The following only happens when no whitespace is used after 'master' and '*/':
|
||||
//select /* maxscale route to master*/ @@server_id;
|
||||
//2014 08/08 13:04:38 Error : Syntax error in hint. Expected 'master', 'slave', or 'server' instead of 'master*/'. Hint ignored.
|
||||
|
||||
//All other forms of '/* maxscale route to [slave|server <server name>]*/' work even without the whitespace before the closing tag.
|
||||
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->connect_maxscale();
|
||||
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "select /* maxscale hintname prepare route to master */ @@server_id;");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select /* maxscale hintname begin */ @@server_id;");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select /* maxscale route to master*/ @@server_id;");
|
||||
|
||||
Test->check_log_err((char *) "Syntax error in hint", false);
|
||||
Test->check_maxscale_alive();
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
35
maxscale-system-test/bug479.cpp
Normal file
35
maxscale-system-test/bug479.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @file bug479.cpp regression case for bug 479 ( Undefined filter reference in MaxScale.cnf causes a crash)
|
||||
*
|
||||
* - Maxscale.cnf with "filters=non existing filter | не существуюший фильтер", cheks error log for warnings and
|
||||
* - check if Maxscale is alive
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Markus Mäkelä 2014-08-15 17:38:06 UTC
|
||||
Undefined filters in services cause a crash when the service is accessed.
|
||||
|
||||
How to reproduce:
|
||||
Define a service with a filter not defined in the MaxScale.cnf file, start MaxScale and access the service.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
Test->check_log_err((char *) "Unable to find filter 'non existing filter", true);
|
||||
//global_result =Test->check_log_err((char *) "не существуюший фильтер", true);
|
||||
//global_result +=Test->check_maxscale_alive();
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
125
maxscale-system-test/bug488.cpp
Normal file
125
maxscale-system-test/bug488.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/**
|
||||
* @file bug488.cpp regression case for bug 488 ("SHOW VARIABLES randomly failing with "Lost connection to MySQL server")
|
||||
*
|
||||
* - try "SHOW VARIABLES;" 100 times against all Maxscale services
|
||||
* First round: 100 iterations for RWSplit, then ReadConn Master, then ReadConn Slave
|
||||
* Second round: 100 iteration and in every iterations all three Maxscale services are in use.
|
||||
* - check if Maxscale is alive.
|
||||
*/
|
||||
|
||||
/*
|
||||
Kolbe Kegel 2014-08-27 18:37:14 UTC
|
||||
Created attachment 138 [details]
|
||||
good.txt and bad.txt
|
||||
|
||||
Sending "SHOW VARIABLES" to MaxScale seems to sometimes result in "ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query". It appears to be random. It seems to be sending the query to the same backend server, so I'm not sure what is happening. I'm including the debug log for both the "good" and "bad" queries.
|
||||
Comment 1 Vilho Raatikka 2014-08-27 18:41:25 UTC
|
||||
Seems to happen exactly every second time with rwsplit router. Didn't experience it with read connection router.
|
||||
Comment 2 Kolbe Kegel 2014-08-27 18:47:13 UTC
|
||||
Not exactly every 2nd time.
|
||||
|
||||
$ mysql -h max1 -P 4006 -u maxuser -pmaxpwd -e 'show variables' >/dev/null
|
||||
$ mysql -h max1 -P 4006 -u maxuser -pmaxpwd -e 'show variables' >/dev/null
|
||||
$ mysql -h max1 -P 4006 -u maxuser -pmaxpwd -e 'show variables' >/dev/null
|
||||
ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query
|
||||
$ mysql -h max1 -P 4006 -u maxuser -pmaxpwd -e 'show variables' >/dev/null
|
||||
ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query
|
||||
$ mysql -h max1 -P 4006 -u maxuser -pmaxpwd -e 'show variables' >/dev/null
|
||||
$ mysql -h max1 -P 4006 -u maxuser -pmaxpwd -e 'show variables' >/dev/null
|
||||
ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query
|
||||
$ mysql -h max1 -P 4006 -u maxuser -pmaxpwd -e 'show variables' >/dev/null
|
||||
ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query
|
||||
$ mysql -h max1 -P 4006 -u maxuser -pmaxpwd -e 'show variables' >/dev/null
|
||||
ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query
|
||||
Comment 3 Vilho Raatikka 2014-08-28 10:48:39 UTC
|
||||
SHOW VARIABLES is session write command - which is unnecessary because those could be read from any server - and what causes client to return 'lost connection' message to the user is duplicated response packet from MaxScale to the client.
|
||||
|
||||
SHOW VARIABLES response should start like this:
|
||||
T 127.0.0.1:59776 -> 127.0.0.1:4006 [AP]
|
||||
0f 00 00 00 03 73 68 6f 77 20 76 61 72 69 61 62 .....show variab
|
||||
6c 65 73 les
|
||||
|
||||
T 127.0.0.1:4006 -> 127.0.0.1:59776 [AP]
|
||||
01 00 00 01 02 .....
|
||||
|
||||
T 127.0.0.1:4006 -> 127.0.0.1:59776 [AP]
|
||||
54 00 00 02 03 64 65 66 12 69 6e 66 6f 72 6d 61 T....def.informa
|
||||
74 69 6f 6e 5f 73 63 68 65 6d 61 09 56 41 52 49 tion_schema.VARI
|
||||
41 42 4c 45 53 09 56 41 52 49 41 42 4c 45 53 0d ABLES.VARIABLES.
|
||||
56 61 72 69 61 62 6c 65 5f 6e 61 6d 65 0d 56 41 Variable_name.VA
|
||||
52 49 41 42 4c 45 5f 4e 41 4d 45 0c 08 00 40 00 RIABLE_NAME...@.
|
||||
00 00 fd 01 00 00 00 00 ........
|
||||
|
||||
While in the failing case the initial packet is followed something like this:
|
||||
|
||||
T 127.0.0.1:59776 -> 127.0.0.1:4006 [AP]
|
||||
0f 00 00 00 03 73 68 6f 77 20 76 61 72 69 61 62 .....show variab
|
||||
6c 65 73 les
|
||||
|
||||
T 127.0.0.1:4006 -> 127.0.0.1:59776 [AP]
|
||||
1d 00 00 d5 18 69 6e 6e 6f 64 62 5f 75 73 65 5f .....innodb_use_
|
||||
61 74 6f 6d 69 63 5f 77 72 69 74 65 73 03 4f 46 atomic_writes.OF
|
||||
46 F
|
||||
|
||||
T 127.0.0.1:4006 -> 127.0.0.1:59776 [AP]
|
||||
19 00 00 d6 14 69 6e 6e 6f 64 62 5f 75 73 65 5f .....innodb_use_
|
||||
66 61 6c 6c 6f 63 61 74 65 03 4f 46 46 fallocate.OFF
|
||||
|
||||
- where those innodb related packets are duplicates from the previous response.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
int i;
|
||||
|
||||
Test->repl->connect();
|
||||
Test->connect_maxscale();
|
||||
|
||||
Test->tprintf("Trying SHOW VARIABLES to different Maxscale services\n");
|
||||
fflush(stdout);
|
||||
Test->tprintf("RWSplit\n");
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
Test->set_timeout(5);
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "SHOW VARIABLES;");
|
||||
}
|
||||
Test->tprintf("ReadConn master\n");
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
Test->set_timeout(5);
|
||||
Test->try_query(Test->conn_master, (char *) "SHOW VARIABLES;");
|
||||
}
|
||||
Test->tprintf("ReadConn slave\n");
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
Test->set_timeout(5);
|
||||
Test->try_query(Test->conn_slave, (char *) "SHOW VARIABLES;");
|
||||
}
|
||||
|
||||
Test->tprintf("All in one loop\n");
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
Test->set_timeout(5);
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "SHOW VARIABLES;");
|
||||
Test->try_query(Test->conn_master, (char *) "SHOW VARIABLES;");
|
||||
Test->try_query(Test->conn_slave, (char *) "SHOW VARIABLES;");
|
||||
}
|
||||
|
||||
Test->set_timeout(10);
|
||||
Test->close_maxscale_connections();
|
||||
Test->repl->close_connections();
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
90
maxscale-system-test/bug493.cpp
Normal file
90
maxscale-system-test/bug493.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @file bug493.cpp regression case for bug 493 ( Can have same section name multiple times without warning)
|
||||
*
|
||||
* - Maxscale.cnf in which 'server2' is defined twice and tests checks error log for proper error message.
|
||||
* - check if Maxscale is alive
|
||||
*/
|
||||
|
||||
/*
|
||||
Hartmut Holzgraefe 2014-08-31 21:01:06 UTC
|
||||
Due to a copy/paste error I ended up with two [server2] sections instead of having [server2] and [server3].
|
||||
|
||||
There were no error or warning messages about this in skygw_err1.log or skygw_msg1.log but only the second [server2] was actually used.
|
||||
|
||||
|
||||
Configuration file:
|
||||
|
||||
---8<------------------
|
||||
[maxscale]
|
||||
threads=1
|
||||
|
||||
[CLI]
|
||||
type=service
|
||||
router=cli
|
||||
|
||||
[CLI Listener]
|
||||
type=listener
|
||||
service=CLI
|
||||
protocol=maxscaled
|
||||
address=localhost
|
||||
port=6603
|
||||
|
||||
[server1]
|
||||
type=server
|
||||
address=127.0.0.1
|
||||
port=3000
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server2]
|
||||
type=server
|
||||
address=127.0.0.1
|
||||
port=3001
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server2]
|
||||
type=server
|
||||
address=127.0.0.1
|
||||
port=3002
|
||||
protocol=MySQLBackend
|
||||
-------->8---
|
||||
|
||||
maxadmin results:
|
||||
|
||||
|
||||
---8<--------------------
|
||||
MaxScale> list servers
|
||||
Servers.
|
||||
-------------------+-----------------+-------+----------------------+------------
|
||||
Server | Address | Port | Status | Connections
|
||||
-------------------+-----------------+-------+----------------------+------------
|
||||
server1 | 127.0.0.1 | 3000 | Running | 0
|
||||
server2 | 127.0.0.1 | 3002 | Running | 0
|
||||
-------------------+-----------------+-------+----------------------+------------
|
||||
------------->8---
|
||||
|
||||
So no entry for the first (actually correct) [server2] on port 3001,
|
||||
but only for the duplicate 2nd [server2] with port set to 3002 ...
|
||||
Comment 1 Mark Riddoch 2014-09-01 16:17:51 UTC
|
||||
The ini file parser we use allows multiple sections with the same name and will combine the section contains. Within this restriction we now have added code that will detect the same parameter being set twice and will warn the user.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
Test->check_log_err((char *) "Duplicate section found: server2", true);
|
||||
Test->check_log_err((char *)
|
||||
"Failed to open, read or process the MaxScale configuration file /etc/maxscale.cnf. Exiting", true);
|
||||
//Test->check_maxscale_alive();
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
43
maxscale-system-test/bug495.cpp
Normal file
43
maxscale-system-test/bug495.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file bug495.cpp regression case for bug 495 ( Referring to a nonexisting server in servers=... doesn't even raise a warning )
|
||||
*
|
||||
* - Maxscale.cnf with "servers= server1, server2,server3 ,server4,server5"
|
||||
* but 'server5' is not defined. Test checks error log for proper error message.
|
||||
* - check if Maxscale is alive
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Description Hartmut Holzgraefe 2014-08-31 21:32:09 UTC
|
||||
Only [server1] and [server2] are defined,
|
||||
service [test_service] and monitor [MySQL monitor]
|
||||
refer to a third server "server3" in their servers=...
|
||||
list though ...
|
||||
|
||||
Nothing in the err or msg log hints towards a problem ...
|
||||
(which originally was caused by a copy/paste error that
|
||||
also lead to the "duplicate section name" error reported
|
||||
earlier ... and which would have been easy to track down
|
||||
if either of these problems would at least have raised a
|
||||
warning - took me almost an hour to track down the actual
|
||||
problem ... :(
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
Test->check_log_err((char *) "Unable to find server", true);
|
||||
Test->check_log_err((char *) "errors were encountered while processing the configuration", true);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
126
maxscale-system-test/bug507.cpp
Normal file
126
maxscale-system-test/bug507.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
/**
|
||||
* @file bug507.cpp regression case for bug 507 ( "rw-split router does not send last_insert_id() to master" )
|
||||
*
|
||||
* - "CREATE TABLE t2 (id INT(10) NOT NULL AUTO_INCREMENT, x int, PRIMARY KEY (id));",
|
||||
* - do INSERT using RWsplit
|
||||
* - do "select last_insert_id(), @@server_id" using RWSplit and directly to Master, compare @@server_id
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Kolbe Kegel 2014-09-01 14:45:56 UTC
|
||||
After inserting a row via the rw-split router, a call to last_insert_id() can go to a slave, producing bad results.
|
||||
|
||||
mariadb> select * from t1;
|
||||
+----+
|
||||
| id |
|
||||
+----+
|
||||
| 1 |
|
||||
| 4 |
|
||||
+----+
|
||||
2 rows in set (0.00 sec)
|
||||
|
||||
mariadb> insert into t1 values ();
|
||||
Query OK, 1 row affected (0.00 sec)
|
||||
|
||||
mariadb> select * from t1;
|
||||
+----+
|
||||
| id |
|
||||
+----+
|
||||
| 1 |
|
||||
| 4 |
|
||||
| 7 |
|
||||
+----+
|
||||
3 rows in set (0.00 sec)
|
||||
|
||||
mariadb> select last_insert_id();
|
||||
+------------------+
|
||||
| last_insert_id() |
|
||||
+------------------+
|
||||
| 0 |
|
||||
+------------------+
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
mariadb> select @@wsrep_node_address, last_insert_id();
|
||||
+----------------------+------------------+
|
||||
| @@wsrep_node_address | last_insert_id() |
|
||||
+----------------------+------------------+
|
||||
| 192.168.30.31 | 7 |
|
||||
+----------------------+------------------+
|
||||
1 row in set (0.00 sec)
|
||||
Comment 1 Vilho Raatikka 2014-09-01 17:51:45 UTC
|
||||
last_inserted_id() belongs to UNKNOWN_FUNC class to which many read-only system functions belong too. Thus last_inserted_id() was routed to any slave.
|
||||
|
||||
Unfortunately I can't confirm wrong behavior since running the same sequence generates same output when connected directly to MariaDB backend. Perhaps there is something required for the table t1 which is not included here?
|
||||
Comment 2 Vilho Raatikka 2014-09-01 20:01:35 UTC
|
||||
An autoincrement attribute was missing.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
const char * sel1 = "select last_insert_id(), @@server_id";
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->repl->connect();
|
||||
Test->connect_maxscale();
|
||||
|
||||
if (Test->repl->N < 3)
|
||||
{
|
||||
Test->tprintf("There is not enoght nodes for test\n");
|
||||
delete Test;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Test->tprintf("Creating table\n");
|
||||
fflush(stdout);
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "DROP TABLE IF EXISTS t2");
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "CREATE TABLE t2 (id INT(10) NOT NULL AUTO_INCREMENT, x int, PRIMARY KEY (id));");
|
||||
Test->tprintf("Doing INSERTs\n");
|
||||
fflush(stdout);
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "insert into t2 (x) values (1);");
|
||||
|
||||
Test->stop_timeout();
|
||||
Test->repl->sync_slaves();
|
||||
|
||||
Test->set_timeout(20);
|
||||
Test->tprintf("Trying \n");
|
||||
char last_insert_id1[1024];
|
||||
char last_insert_id2[1024];
|
||||
if ( (
|
||||
find_field(
|
||||
Test->conn_rwsplit, sel1,
|
||||
"@@server_id", &last_insert_id1[0])
|
||||
!= 0 ) || (
|
||||
find_field(
|
||||
Test->repl->nodes[0], sel1,
|
||||
"@@server_id", &last_insert_id2[0])
|
||||
!= 0 ))
|
||||
{
|
||||
Test->tprintf("@@server_id fied not found!!\n");
|
||||
delete Test;
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->tprintf("'%s' to RWSplit gave @@server_id %s\n", sel1, last_insert_id1);
|
||||
Test->tprintf("'%s' directly to master gave @@server_id %s\n", sel1, last_insert_id2);
|
||||
Test->add_result(strcmp(last_insert_id1, last_insert_id2),
|
||||
"last_insert_id() are different depending in which order terms are in SELECT\n");
|
||||
}
|
||||
|
||||
Test->close_maxscale_connections();
|
||||
Test->repl->close_connections();
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
144
maxscale-system-test/bug509.cpp
Normal file
144
maxscale-system-test/bug509.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* @file bug509.cpp regression case for bug 509 and 507 ( "Referring to a nonexisting server in servers=... doesn't even raise a warning"
|
||||
* and "rw-split router does not send last_insert_id() to master" )
|
||||
*
|
||||
* - "CREATE TABLE t2 (id INT(10) NOT NULL AUTO_INCREMENT, x int, PRIMARY KEY (id));",
|
||||
* - do a number of INSERTs first using RWsplit, then directly Galera nodes.
|
||||
* - do "select @@wsrep_node_address, last_insert_id();" and "select last_insert_id(), @@wsrep_node_address;" and compares results.
|
||||
* - do "insert into t2 (x) values (i);" 1000 times and compares results of
|
||||
* "select @@wsrep_node_address, last_insert_id();" and "select last_insert_id(), @@wsrep_node_address;"
|
||||
*
|
||||
* Test fails if results are different (after 5 seconds of waiting after last INSERT)
|
||||
*/
|
||||
|
||||
/*
|
||||
Kolbe Kegel 2014-09-01 14:48:12 UTC
|
||||
For some reason, the order of terms in the field list of a SELECT statement influences how the rw-split router decides where to send a statement.
|
||||
|
||||
mariadb> select @@wsrep_node_address, last_insert_id();
|
||||
+----------------------+------------------+
|
||||
| @@wsrep_node_address | last_insert_id() |
|
||||
+----------------------+------------------+
|
||||
| 192.168.30.31 | 7 |
|
||||
+----------------------+------------------+
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
mariadb> select last_insert_id(), @@wsrep_node_address;
|
||||
+------------------+----------------------+
|
||||
| last_insert_id() | @@wsrep_node_address |
|
||||
+------------------+----------------------+
|
||||
| 0 | 192.168.30.33 |
|
||||
+------------------+----------------------+
|
||||
1 row in set (0.00 sec)
|
||||
Comment 1 Vilho Raatikka 2014-09-03 20:44:17 UTC
|
||||
Added code to detect last_insert_id() function and now both types of elements are routed to master and their order of appearance doesn't matter.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
const char * sel1 = "select @@wsrep_node_address, last_insert_id();";
|
||||
const char * sel2 = "select last_insert_id(), @@wsrep_node_address;";
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(60);
|
||||
|
||||
Test->galera->connect();
|
||||
Test->connect_maxscale();
|
||||
|
||||
if (Test->galera->N < 3)
|
||||
{
|
||||
Test->tprintf("There is not enoght nodes for test\n");
|
||||
delete Test;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Test->tprintf("Creating table\n");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "DROP TABLE IF EXISTS t2;");
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "CREATE TABLE t2 (id INT(10) NOT NULL AUTO_INCREMENT, x int, PRIMARY KEY (id));");
|
||||
Test->tprintf("Doing INSERTs\n");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "insert into t2 (x) values (1);");
|
||||
|
||||
Test->try_query(Test->galera->nodes[0], (char *) "insert into t2 (x) values (2);");
|
||||
Test->try_query(Test->galera->nodes[0], (char *) "insert into t2 (x) values (3);");
|
||||
|
||||
Test->try_query(Test->galera->nodes[1], (char *) "insert into t2 (x) values (4);");
|
||||
Test->try_query(Test->galera->nodes[1], (char *) "insert into t2 (x) values (5);");
|
||||
Test->try_query(Test->galera->nodes[1], (char *) "insert into t2 (x) values (6);");
|
||||
|
||||
Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (7);");
|
||||
Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (8);");
|
||||
Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (9);");
|
||||
Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (10);");
|
||||
|
||||
Test->stop_timeout();
|
||||
Test->repl->sync_slaves();
|
||||
|
||||
Test->tprintf("Trying \n");
|
||||
char last_insert_id1[1024];
|
||||
char last_insert_id2[1024];
|
||||
if ( (
|
||||
find_field(
|
||||
Test->conn_rwsplit, sel1,
|
||||
"last_insert_id()", &last_insert_id1[0])
|
||||
!= 0 ) || (
|
||||
find_field(
|
||||
Test->conn_rwsplit, sel2,
|
||||
"last_insert_id()", &last_insert_id2[0])
|
||||
!= 0 ))
|
||||
{
|
||||
Test->tprintf("last_insert_id() fied not found!!\n");
|
||||
delete Test;
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->tprintf("'%s' gave last_insert_id() %s\n", sel1, last_insert_id1);
|
||||
Test->tprintf("'%s' gave last_insert_id() %s\n", sel2, last_insert_id2);
|
||||
Test->add_result(strcmp(last_insert_id1, last_insert_id2),
|
||||
"last_insert_id() are different depending in which order terms are in SELECT\n");
|
||||
}
|
||||
|
||||
char id_str[1024];
|
||||
char str1[1024];
|
||||
int iterations = 150;
|
||||
|
||||
for (int i = 100; i < iterations; i++)
|
||||
{
|
||||
Test->set_timeout(50);
|
||||
Test->add_result(execute_query(Test->conn_rwsplit, "insert into t2 (x) values (%d);", i), "Query failed");
|
||||
|
||||
sprintf(str1, "select * from t2 where x=%d;", i);
|
||||
|
||||
find_field(Test->conn_rwsplit, sel1, "last_insert_id()", &last_insert_id1[0]);
|
||||
find_field(Test->conn_rwsplit, str1, "id", &id_str[0]);
|
||||
|
||||
int n = 0;
|
||||
|
||||
while (strcmp(last_insert_id1, id_str) != 0 && n < 5)
|
||||
{
|
||||
Test->tprintf("Replication is lagging");
|
||||
sleep(1);
|
||||
find_field(Test->conn_rwsplit, str1, "id", &id_str[0]);
|
||||
n++;
|
||||
}
|
||||
|
||||
Test->add_result(strcmp(last_insert_id1, id_str),
|
||||
"last_insert_id is not equal to id even after waiting 5 seconds");
|
||||
|
||||
if (i % 10 == 0)
|
||||
{
|
||||
Test->tprintf("last_insert_id is %s, id is %s", last_insert_id1, id_str);
|
||||
}
|
||||
}
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
152
maxscale-system-test/bug519.cpp
Normal file
152
maxscale-system-test/bug519.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @file bug519.cpp - Jira task is MAX-345
|
||||
* - fill t1 with data
|
||||
* - execute SELECT * INTO OUTFILE '/tmp/t1.csv' FROM t1; against all routers
|
||||
* - DROP TABLE t1
|
||||
* - LOAD DATA LOCAL INFILE 't1.csv' INTO TABLE t1; using RWSplit
|
||||
* - check if t1 contains right data
|
||||
* - DROP t1 again and repeat LOAD DATA LOCAL INFILE 't1.csv' INTO TABLE t1; using ReadConn master
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
It seems that LOAD DATA LOCAL INFILE is not handled by readwritesplit? Maybe it's a bigger problem elsewhere in MaxScale?
|
||||
|
||||
I can execute the command, it looks like it is getting sent to the master, but ... no data is actually loaded. Does/can MaxScale handle LOAD DATA LOCAL INFILE?
|
||||
Comment 1 Kolbe Kegel 2014-09-03 02:39:47 UTC
|
||||
The LOAD DATA LOCAL INFILE statement is stuck in "Reading from net" until some timeout is hit:
|
||||
|
||||
| 22 | maxuser | 192.168.30.38:59996 | test | Query | 10 | Reading from net | load data local infile '/Users/kolbe/Devel/seattleparking/Street_Parking_Signs.csv' into table parki | 0.000 |
|
||||
|
||||
The client never sees the statement end, though, even after the server has long ago killed its connection...
|
||||
|
||||
When I start a *new* connection to MaxScale and I try to execute the LOAD DATA LOCAL INFILE statement again, I have some problems:
|
||||
|
||||
mysql 5.5.38-MariaDB (maxuser) [test]> source /Users/kolbe/Devel/seattleparking/loaddata.sql
|
||||
ERROR 2013 (HY000) at line 1 in file: '/Users/kolbe/Devel/seattleparking/loaddata.sql': Lost connection to MySQL server during query
|
||||
mysql 5.5.38-MariaDB (maxuser) [test]> select @@wsrep_node_address;
|
||||
ERROR 2006 (HY000): MySQL server has gone away
|
||||
No connection. Trying to reconnect...
|
||||
Connection id: 1709
|
||||
Current database: test
|
||||
|
||||
+----------------------+
|
||||
| @@wsrep_node_address |
|
||||
+----------------------+
|
||||
| 192.168.30.32 |
|
||||
+----------------------+
|
||||
1 row in set (0.01 sec)
|
||||
|
||||
mysql 5.5.38-MariaDB (maxuser) [test]> source /Users/kolbe/Devel/seattleparking/loaddata.sql
|
||||
ERROR 2013 (HY000) at line 1 in file: '/Users/kolbe/Devel/seattleparking/loaddata.sql': Lost connection to MySQL server during query
|
||||
mysql 5.5.38-MariaDB (maxuser) [test]> select @@wsrep_node_address;
|
||||
ERROR 2006 (HY000): MySQL server has gone away
|
||||
No connection. Trying to reconnect...
|
||||
Connection id: 1709
|
||||
Current database: test
|
||||
|
||||
+----------------------+
|
||||
| @@wsrep_node_address |
|
||||
+----------------------+
|
||||
| 192.168.30.32 |
|
||||
+----------------------+
|
||||
1 row in set (0.01 sec)
|
||||
|
||||
mysql 5.5.38-MariaDB (maxuser) [test]> source /Users/kolbe/Devel/seattleparking/loaddata.sql
|
||||
ERROR 2013 (HY000) at line 1 in file: '/Users/kolbe/Devel/seattleparking/loaddata.sql': Lost connection to MySQL server during query
|
||||
mysql 5.5.38-MariaDB (maxuser) [test]> Bye
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "sql_t1.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
int N = 4;
|
||||
int iterations = 2;
|
||||
if (Test->smoke)
|
||||
{
|
||||
iterations = 1;
|
||||
}
|
||||
char str[1024];
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->connect_maxscale();
|
||||
Test->repl->connect();
|
||||
|
||||
Test->tprintf("Create t1\n");
|
||||
create_t1(Test->conn_rwsplit);
|
||||
Test->tprintf("Insert data into t1\n");
|
||||
Test->set_timeout(60);
|
||||
insert_into_t1(Test->conn_rwsplit, N);
|
||||
Test->stop_timeout();
|
||||
Test->repl->sync_slaves();
|
||||
Test->set_timeout(200);
|
||||
|
||||
sprintf(str, "%s rm -f /tmp/t*.csv; %s chmod 777 /tmp", Test->repl->access_sudo[0],
|
||||
Test->repl->access_sudo[0]);
|
||||
Test->tprintf("%s\n", str);
|
||||
for (int k = 0; k < Test->repl->N; k++)
|
||||
{
|
||||
Test->repl->ssh_node(k, str, false);
|
||||
}
|
||||
//system(str);
|
||||
|
||||
Test->tprintf("Copying data from t1 to file...\n");
|
||||
Test->tprintf("using RWSplit: SELECT * INTO OUTFILE '/tmp/t1.csv' FROM t1;\n");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "SELECT * INTO OUTFILE '/tmp/t1.csv' FROM t1;");
|
||||
Test->tprintf("using ReadConn master: SELECT * INTO OUTFILE '/tmp/t2.csv' FROM t1;\n");
|
||||
Test->try_query(Test->conn_master, (char *) "SELECT * INTO OUTFILE '/tmp/t2.csv' FROM t1;");
|
||||
Test->tprintf("using ReadConn slave: SELECT * INTO OUTFILE '/tmp/t3.csv' FROM t1;\n");
|
||||
Test->try_query(Test->conn_slave, (char *) "SELECT * INTO OUTFILE '/tmp/t3.csv' FROM t1;");
|
||||
|
||||
Test->tprintf("Copying t1.cvs from Maxscale machine:\n");
|
||||
Test->copy_from_maxscale((char *) "/tmp/t1.csv", (char *) "./");
|
||||
/*sprintf(str,
|
||||
"scp -i %s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s:/tmp/t1.csv ./",
|
||||
Test->repl->sshkey[0], Test->repl->access_user[0], Test->repl->IP[0]);
|
||||
Test->tprintf("%s\n", str);
|
||||
system(str);*/
|
||||
|
||||
MYSQL *srv[2];
|
||||
|
||||
srv[0] = Test->conn_rwsplit;
|
||||
srv[1] = Test->conn_master;
|
||||
for (int i = 0; i < iterations; i++)
|
||||
{
|
||||
Test->set_timeout(100);
|
||||
Test->tprintf("Dropping t1 \n");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "DROP TABLE t1;");
|
||||
Test->stop_timeout();
|
||||
Test->repl->sync_slaves();
|
||||
|
||||
Test->set_timeout(100);
|
||||
Test->tprintf("Create t1\n");
|
||||
create_t1(Test->conn_rwsplit);
|
||||
Test->tprintf("Loading data to t1 from file\n");
|
||||
Test->try_query(srv[i], (char *) "LOAD DATA LOCAL INFILE 't1.csv' INTO TABLE t1;");
|
||||
Test->stop_timeout();
|
||||
Test->repl->sync_slaves();
|
||||
|
||||
Test->set_timeout(100);
|
||||
Test->tprintf("SELECT: rwsplitter\n");
|
||||
Test->add_result(select_from_t1(Test->conn_rwsplit, N), "Wrong data in 't1'");
|
||||
Test->tprintf("SELECT: master\n");
|
||||
Test->add_result(select_from_t1(Test->conn_master, N), "Wrong data in 't1'");
|
||||
Test->tprintf("SELECT: slave\n");
|
||||
Test->add_result(select_from_t1(Test->conn_slave, N), "Wrong data in 't1'");
|
||||
}
|
||||
|
||||
Test->repl->close_connections();
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
69
maxscale-system-test/bug526.cpp
Normal file
69
maxscale-system-test/bug526.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @file bug526.cpp regression case for bug 526 ( " Wrong module name crashes maxscale on connect" )
|
||||
*
|
||||
* - Maxscale.cnf with "filters=QLA|testfilter" for RWSplit router service, 'testfilter' is not defined.
|
||||
* - check error log for proper error messages and checks if ReadConn services are alive
|
||||
*/
|
||||
|
||||
/*
|
||||
Hartmut Holzgraefe 2014-09-08 13:08:46 UTC
|
||||
I mistyped a module name (for a filter in this case)
|
||||
|
||||
[testfilter]
|
||||
type=filter
|
||||
module=foobar
|
||||
|
||||
There were no warnings about this on startup at all, but at the first time trying to connect to a service this filter was used in maxscale crashed with a segmentation fault after writing the following error log entries:
|
||||
|
||||
2014 09/08 15:00:53 Error : Unable to find library for module: foobar.
|
||||
2014 09/08 15:00:53 Failed to create filter 'testfilter' for service 'testrouter'.
|
||||
2014 09/08 15:00:53 Error : Failed to create Read Connection Router session.
|
||||
2014 09/08 15:00:53 Error : Invalid authentication message from backend. Error : 28000, Msg : Access denied for user 'maxuser'@'localhost' (using password: YES)
|
||||
2014 09/08 15:00:53 Error : Backend server didn't accept authentication for user denied for user 'maxuser'@'localhost' (using password: YES).
|
||||
|
||||
Two problems here:
|
||||
|
||||
1) can't check up front that my configuration is valid / without errors without connecting to each defined service
|
||||
|
||||
2) maxscale crashes instead of handling this situation gracefully (e.g. ignoring the misconfigured filter, or disabling the service that refers to it alltogether)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
#include "maxadmin_operations.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(20);
|
||||
|
||||
if (Test->connect_rwsplit() == 0)
|
||||
{
|
||||
Test->add_result(1, "Filter config is broken, but service is started\n");
|
||||
}
|
||||
if (Test->connect_readconn_master() == 0)
|
||||
{
|
||||
Test->add_result(1, "Filter config is broken, but Maxscale is started\n");
|
||||
}
|
||||
if (Test->connect_readconn_slave() == 0)
|
||||
{
|
||||
Test->add_result(1, "Filter config is broken, but Maxscale is started\n");
|
||||
}
|
||||
|
||||
//sleep(5);
|
||||
Test->execute_maxadmin_command((char*) "sync logs");
|
||||
Test->check_log_err((char *) "Unable to find library for module: foobar", true);
|
||||
Test->check_log_err((char *) "Failed to load filter module 'foobar'", true);
|
||||
Test->check_log_err((char *) "Failed to load filter 'testfilter' for service 'RW Split Router'", true);
|
||||
Test->check_log_err((char *)
|
||||
"Failed to open, read or process the MaxScale configuration file /etc/maxscale.cnf. Exiting", true);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
315
maxscale-system-test/bug529.cpp
Normal file
315
maxscale-system-test/bug529.cpp
Normal file
@ -0,0 +1,315 @@
|
||||
/**
|
||||
* @file bug529.cpp regression case for bug 529 ( "'Current no. of conns' not going down" )
|
||||
*
|
||||
* - create table, opens 50 connections for every router, fill table with data using these connections.
|
||||
* - check number of connections to Master - failure if there are more then 100 connections to master.
|
||||
* - close RWSptit and ReadConn master connections and check connections to master again.
|
||||
* - create 50 ReadConn slave connection in parallel threads, execute "SELECT * FROM t1" ones for every connections, then
|
||||
* start using one of connections to create "SELECT" load.
|
||||
* - check number of connections to Master again, wait 5 seconds and check number of connections to
|
||||
* master ones more time: now expecting 0 connections to master (fail if there is a least one connection to master).
|
||||
* - close and reopens all ReadConn slave connections in the main thread and check connections to master again
|
||||
* - close all connection in all threads, close parallel thread
|
||||
* - do final 'connections to master' check
|
||||
*/
|
||||
|
||||
/*
|
||||
lisu87 2014-09-08 16:50:29 UTC
|
||||
After starting maxscale and putting some traffic to it, the number of current connections to master server are still going up:
|
||||
|
||||
Server 0x29e6330 (carlsberg)
|
||||
Server: xxx.xxx.xxx.xxx
|
||||
Status: Master, Running
|
||||
Protocol: MySQLBackend
|
||||
Port: 3306
|
||||
Node Id: -1
|
||||
Master Id: -1
|
||||
Repl Depth: -1
|
||||
Number of connections: 58
|
||||
Current no. of conns: 29
|
||||
Current no. of operations: 0
|
||||
Server 0x2948f60 (psy-carslave-1)
|
||||
Server: xxx.xxx.xxx.xxx
|
||||
Status: Slave, Running
|
||||
Protocol: MySQLBackend
|
||||
Port: 3306
|
||||
Node Id: -1
|
||||
Master Id: -1
|
||||
Repl Depth: -1
|
||||
Number of connections: 0
|
||||
Current no. of conns: 0
|
||||
Current no. of operations: 0
|
||||
Server 0x2948e60 (psy-carslave-2)
|
||||
Server: xxx.xxx.xxx.xxx
|
||||
Status: Slave, Running
|
||||
Protocol: MySQLBackend
|
||||
Port: 3306
|
||||
Node Id: -1
|
||||
Master Id: -1
|
||||
Repl Depth: -1
|
||||
Number of connections: 29
|
||||
Current no. of conns: 0
|
||||
Current no. of operations: 0
|
||||
Comment 1 Vilho Raatikka 2014-09-09 06:53:56 UTC
|
||||
Is the version release-1.0beta?
|
||||
Does any load cause this or does it require multiple parallel clients, for example?
|
||||
Comment 2 lisu87 2014-09-09 07:53:18 UTC
|
||||
The version is release-1.0beta.
|
||||
|
||||
Even when just one short connection is made the counter of "Current no. of conns" goes up.
|
||||
|
||||
Interesting thing is that the amount of current connections for my slave is always exactly two times smaller than "Number of connections":
|
||||
|
||||
Server 0x1f51330 (carlsberg)
|
||||
Server: 172.16.76.8
|
||||
Status: Master, Running
|
||||
Protocol: MySQLBackend
|
||||
Port: 3306
|
||||
Node Id: -1
|
||||
Master Id: -1
|
||||
Repl Depth: -1
|
||||
Number of connections: 3278
|
||||
Current no. of conns: 1639
|
||||
Current no. of operations: 0
|
||||
Comment 3 lisu87 2014-09-11 09:54:34 UTC
|
||||
Any update on this one?
|
||||
Comment 4 Vilho Raatikka 2014-09-11 10:34:20 UTC
|
||||
The problem can't be reproduced with the code I'm working currently, and which will be the one where beta release will be refresed from. Thus, I'd wait till beta refresh is done and see if the problem still exists.
|
||||
Comment 5 lisu87 2014-09-11 10:47:32 UTC
|
||||
Thank you.
|
||||
|
||||
And one more question: is it normal that even if SELECT query has been performed on skave the "Number of connections" counter for master increases too?
|
||||
Comment 6 Vilho Raatikka 2014-09-11 11:02:08 UTC
|
||||
(In reply to comment #5)
|
||||
> Thank you.
|
||||
>
|
||||
> And one more question: is it normal that even if SELECT query has been
|
||||
> performed on skave the "Number of connections" counter for master increases
|
||||
> too?
|
||||
|
||||
When rwsplit listens port 3333 and when a command like :
|
||||
|
||||
mysql -h 127.0.0.1 -P 3333 -u maxscaleuser -ppwd -e "select count(user) from mysql.user"
|
||||
|
||||
is executed client connects to MaxScale:3333, and MaxScale connects to master and slave(s). So connection count increases in each of those backends despite of query type.
|
||||
|
||||
If you already have a rwsplit session, no new connections should be created when new queries are executed.
|
||||
Comment 7 Vilho Raatikka 2014-09-11 12:34:26 UTC
|
||||
I built MaxScale from releaes-1.0beta-refresh branch and tested by running 5000 prepared statements in one session to MaxScale/RWSplit and executing 'show servers' in another window. During the run the number of current connections was 1 in each server and after the run all 'current' counters show 0.
|
||||
|
||||
If you want me to try with some other use case, describe it and I'll give it a try.
|
||||
Comment 8 lisu87 2014-09-11 12:45:37 UTC
|
||||
Thanks, Vilho.
|
||||
|
||||
I'm building maxscale from that branch now and will retest shortly.
|
||||
Comment 9 lisu87 2014-09-11 14:45:26 UTC
|
||||
Confirmed. It works fine with 1.0beta-refresh.
|
||||
|
||||
Thank you!
|
||||
Comment 10 Vilho Raatikka 2014-09-22 10:11:06 UTC
|
||||
The problem reappeared later and was eventually fixed in release-1.0beta-refresh commit a41a8d6060c7b60e09686bea8124803f047d85ad
|
||||
|
||||
*/
|
||||
|
||||
// counting connection to all services
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "sql_t1.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
|
||||
int exit_flag = 0;
|
||||
int conn_N = 50;
|
||||
|
||||
TestConnections * Test ;
|
||||
|
||||
void *parall_traffic( void *ptr );
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(120);
|
||||
int i;
|
||||
int num_conn = 0;
|
||||
char sql[100];
|
||||
|
||||
pthread_t parall_traffic1;
|
||||
int check_iret;
|
||||
|
||||
MYSQL * conn;
|
||||
MYSQL * rwsplit_conn[conn_N];
|
||||
MYSQL * master_conn[conn_N];
|
||||
MYSQL * slave_conn[conn_N];
|
||||
|
||||
Test->repl->connect();
|
||||
|
||||
conn = Test->open_rwsplit_connection();
|
||||
execute_query(conn, (char *) "DROP DATABASE IF EXISTS test");
|
||||
execute_query(conn, (char *) "CREATE DATABASE test");
|
||||
execute_query(conn, (char *) "USE test;");
|
||||
|
||||
create_t1(conn);
|
||||
mysql_close(conn);
|
||||
Test->tprintf("Table t1 is created\n");
|
||||
|
||||
for (i = 0; i < conn_N; i++)
|
||||
{
|
||||
Test->set_timeout(60);
|
||||
rwsplit_conn[i] = Test->open_rwsplit_connection();
|
||||
master_conn[i] = Test->open_readconn_master_connection();
|
||||
slave_conn[i] = Test->open_readconn_slave_connection();
|
||||
sprintf(sql, "INSERT INTO t1 (x1, fl) VALUES(%d, 1);", i);
|
||||
execute_query(rwsplit_conn[i], sql);
|
||||
sprintf(sql, "INSERT INTO t1 (x1, fl) VALUES(%d, 2);", i);
|
||||
execute_query(master_conn[i], sql);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
for (i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->set_timeout(60);
|
||||
num_conn = get_conn_num(Test->repl->nodes[i], Test->maxscale_IP, Test->maxscale_hostname, (char *) "test");
|
||||
Test->tprintf("Connections to node %d (%s): %d\n", i, Test->repl->IP[i], num_conn);
|
||||
if ((i == 0) && (num_conn > 2 * conn_N))
|
||||
{
|
||||
Test->add_result(1, "too many connections to master\n");
|
||||
}
|
||||
}
|
||||
|
||||
Test->tprintf("Closing RWSptit and ReadConn master connections\n");
|
||||
for (i = 0; i < conn_N; i++)
|
||||
{
|
||||
mysql_close(rwsplit_conn[i]);
|
||||
mysql_close(master_conn[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->set_timeout(60);
|
||||
num_conn = get_conn_num(Test->repl->nodes[i], Test->maxscale_IP, Test->maxscale_hostname, (char *) "test");
|
||||
printf("Connections to node %d (%s): %d\n", i, Test->repl->IP[i], num_conn);
|
||||
if ((i == 0) && (num_conn > 2 * conn_N))
|
||||
{
|
||||
Test->add_result(1, "too many connections to master\n");
|
||||
}
|
||||
}
|
||||
|
||||
Test->tprintf("Opening more connection to ReadConn slave in parallel thread\n");
|
||||
|
||||
check_iret = pthread_create( ¶ll_traffic1, NULL, parall_traffic, NULL);
|
||||
|
||||
for (i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
num_conn = get_conn_num(Test->repl->nodes[i], Test->maxscale_IP, Test->maxscale_hostname, (char *) "test");
|
||||
printf("Connections to node %d (%s): %d\n", i, Test->repl->IP[i], num_conn);
|
||||
if ((i == 0) && (num_conn > 2 * conn_N))
|
||||
{
|
||||
Test->add_result(1, "too many connections to master\n");
|
||||
}
|
||||
}
|
||||
|
||||
Test->stop_timeout();
|
||||
Test->tprintf("Sleeping 15 seconds\n");
|
||||
sleep(15);
|
||||
|
||||
for (i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->set_timeout(60);
|
||||
num_conn = get_conn_num(Test->repl->nodes[i], Test->maxscale_IP, Test->maxscale_hostname, (char *) "test");
|
||||
printf("Connections to node %d (%s): %d\n", i, Test->repl->IP[i], num_conn);
|
||||
if ((i == 0) && (num_conn != 0))
|
||||
{
|
||||
Test->add_result(1, "there are still connections to master\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("Closing ReadConn slave connections\n");
|
||||
for (i = 0; i < conn_N; i++)
|
||||
{
|
||||
mysql_close(slave_conn[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->set_timeout(60);
|
||||
num_conn = get_conn_num(Test->repl->nodes[i], Test->maxscale_IP, Test->maxscale_hostname, (char *) "test");
|
||||
Test->tprintf("Connections to node %d (%s): %d\n", i, Test->repl->IP[i], num_conn);
|
||||
if ((i == 0) && (num_conn != 0))
|
||||
{
|
||||
Test->add_result(1, "there are still connections to master\n");
|
||||
}
|
||||
}
|
||||
|
||||
Test->tprintf("Opening ReadConn slave connections again\n");
|
||||
for (i = 0; i < conn_N; i++)
|
||||
{
|
||||
Test->set_timeout(60);
|
||||
slave_conn[i] = Test->open_readconn_slave_connection();
|
||||
sprintf(sql, "SELECT * FROM t1");
|
||||
execute_query(slave_conn[i], sql);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
for (i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->set_timeout(60);
|
||||
num_conn = get_conn_num(Test->repl->nodes[i], Test->maxscale_IP, Test->maxscale_hostname, (char *) "test");
|
||||
Test->tprintf("Connections to node %d (%s): %d\n", i, Test->repl->IP[i], num_conn);
|
||||
if ((i == 0) && (num_conn != 0))
|
||||
{
|
||||
Test->add_result(1, "there are still connections to master\n");
|
||||
}
|
||||
}
|
||||
|
||||
Test->tprintf("Closing ReadConn slave connections\n");
|
||||
for (i = 0; i < conn_N; i++)
|
||||
{
|
||||
Test->set_timeout(20);
|
||||
mysql_close(slave_conn[i]);
|
||||
}
|
||||
exit_flag = 1;
|
||||
|
||||
for (i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->set_timeout(60);
|
||||
num_conn = get_conn_num(Test->repl->nodes[i], Test->maxscale_IP, Test->maxscale_hostname, (char *) "test");
|
||||
Test->tprintf("Connections to node %d (%s): %d\n", i, Test->repl->IP[i], num_conn);
|
||||
if ((i == 0) && (num_conn != 0))
|
||||
{
|
||||
Test->add_result(1, "there are still connections to master\n");
|
||||
}
|
||||
}
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
void *parall_traffic( void *ptr )
|
||||
{
|
||||
MYSQL * slave_conn1[conn_N];
|
||||
int i;
|
||||
for (i = 0; i < conn_N; i++)
|
||||
{
|
||||
slave_conn1[i] = Test->open_readconn_slave_connection();
|
||||
execute_query(slave_conn1[i], "SELECT * FROM t1");
|
||||
}
|
||||
|
||||
while (exit_flag == 0)
|
||||
{
|
||||
execute_query(slave_conn1[0], "SELECT * FROM t1");
|
||||
}
|
||||
for (i = 0; i < conn_N; i++)
|
||||
{
|
||||
mysql_close(slave_conn1[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
56
maxscale-system-test/bug539.cpp
Normal file
56
maxscale-system-test/bug539.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file bug539.cpp regression case for bug539 ("MaxScale crashes in session_setup_filters")
|
||||
* using maxadmin execute "fail backendfd"
|
||||
* try quries against all services
|
||||
* using maxadmin execute "fail clientfd"
|
||||
* try quries against all services
|
||||
* check if MaxScale alive
|
||||
*/
|
||||
|
||||
|
||||
#include "testconnections.h"
|
||||
#include "maxadmin_operations.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(20);
|
||||
int i, j;
|
||||
MYSQL * conn;
|
||||
|
||||
int N_cmd = 2;
|
||||
char * fail_cmd[N_cmd - 1];
|
||||
|
||||
int N_ports = 3;
|
||||
int ports[N_ports];
|
||||
|
||||
fail_cmd[0] = (char *) "fail backendfd";
|
||||
fail_cmd[1] = (char *) "fail clientfd";
|
||||
|
||||
ports[0] = Test->rwsplit_port;
|
||||
ports[1] = Test->readconn_master_port;
|
||||
ports[2] = Test->readconn_slave_port;
|
||||
|
||||
for (i = 0; i < N_cmd; i++)
|
||||
{
|
||||
for (j = 0; j < N_ports; j++)
|
||||
{
|
||||
Test->tprintf("Executing MaxAdmin command '%s'\n", fail_cmd[i]);
|
||||
if (execute_maxadmin_command(Test->maxscale_IP, (char *) "admin", Test->maxadmin_password, fail_cmd[i]) != 0)
|
||||
{
|
||||
Test->add_result(1, "MaxAdmin command failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Trying query against %d\n", ports[j]);
|
||||
conn = open_conn(ports[j], Test->maxscale_IP, Test->maxscale_user, Test->maxscale_user, Test->ssl);
|
||||
Test->try_query(conn, (char *) "show processlist;");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
72
maxscale-system-test/bug547.cpp
Normal file
72
maxscale-system-test/bug547.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @file bug547.cpp regression case for bug 547 and bug 594 ( "get_dcb fails if slaves are not available" and "Maxscale fails to start without anything in the logs if there is no slave available" )
|
||||
* Behaviour has been changed and this test check only for crash
|
||||
* - block all slaves
|
||||
* - try some queries (create table, do INSERT using RWSplit router)
|
||||
* - check there is no crash
|
||||
*/
|
||||
|
||||
/*
|
||||
Vilho Raatikka 2014-09-16 07:43:54 UTC
|
||||
get_dcb function returns the backend descriptor for router. Some merge has broken the logic and in case of non-existent slave the router simply fails to find a backend server although master would be available.
|
||||
Comment 1 Vilho Raatikka 2014-09-16 09:40:14 UTC
|
||||
get_dcb now searches master if slaves are not available.
|
||||
*/
|
||||
|
||||
// also relates to bug594
|
||||
// all slaves in MaxScale config have wrong IP
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
int i;
|
||||
|
||||
for (i = 1; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->set_timeout(20);
|
||||
Test->repl->block_node(i);
|
||||
}
|
||||
|
||||
Test->set_timeout(30);
|
||||
sleep(15);
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->tprintf("Connecting to all MaxScale services, expecting error\n");
|
||||
Test->connect_maxscale();
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->tprintf("Trying some queries, expecting failure, but not a crash\n");
|
||||
execute_query(Test->conn_rwsplit, (char *) "DROP TABLE IF EXISTS t1");
|
||||
execute_query(Test->conn_rwsplit, (char *) "CREATE TABLE t1 (x INT)");
|
||||
execute_query(Test->conn_rwsplit, (char *) "INSERT INTO t1 (x) VALUES (1)");
|
||||
execute_query(Test->conn_rwsplit, (char *) "select * from t1");
|
||||
execute_query(Test->conn_master, (char *) "select * from t1");
|
||||
execute_query(Test->conn_slave, (char *) "select * from t1");
|
||||
|
||||
Test->set_timeout(10);
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->repl->unblock_all_nodes();
|
||||
|
||||
Test->stop_timeout();
|
||||
sleep(15);
|
||||
Test->check_log_err((char *) "fatal signal 11", false);
|
||||
Test->check_log_err((char *) "Failed to create new router session for service 'RW-Split-Router'", true);
|
||||
Test->check_log_err((char *)
|
||||
"Failed to create new router session for service 'Read-Connection-Router-Master'", true);
|
||||
Test->check_log_err((char *) "Failed to create new router session for service 'Read-Connection-Router-Slave'",
|
||||
true);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
73
maxscale-system-test/bug561.sh
Executable file
73
maxscale-system-test/bug561.sh
Executable file
@ -0,0 +1,73 @@
|
||||
#!/bin/bash
|
||||
|
||||
###
|
||||
## @file bug561.sh Regression case for the bug "Different error messages from MariaDB and Maxscale"
|
||||
## - try to connect to non existing DB directly to MariaDB server and via Maxscale
|
||||
## - compare error messages
|
||||
## - repeat for RWSplit, ReadConn
|
||||
|
||||
|
||||
rp=`realpath $0`
|
||||
export test_dir=`dirname $rp`
|
||||
export test_name=`basename $rp`
|
||||
|
||||
$test_dir/non_native_setup $test_name
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "configuring maxscale failed"
|
||||
exit 1
|
||||
fi
|
||||
export ssl_options="--ssl-cert=$test_dir/ssl-cert/client-cert.pem --ssl-key=$test_dir/ssl-cert/client-key.pem"
|
||||
|
||||
#echo "Waiting for 15 seconds"
|
||||
#sleep 15
|
||||
|
||||
mariadb_err=`mysql -u$node_user -p$node_password -h $node_000_network $ssl_options --socket=$node_000_socket -P $node_000_port non_existing_db 2>&1`
|
||||
maxscale_err=`mysql -u$node_user -p$node_password -h $maxscale_IP -P 4006 $ssl_options non_existing_db 2>&1`
|
||||
|
||||
maxscale_err1=`mysql -u$node_user -p$node_password -h $maxscale_IP -P 4008 $ssl_options non_existing_db 2>&1`
|
||||
maxscale_err2=`mysql -u$node_user -p$node_password -h $maxscale_IP -P 4009 $ssl_options non_existing_db 2>&1`
|
||||
|
||||
echo "MariaDB message"
|
||||
echo "$mariadb_err"
|
||||
echo " "
|
||||
echo "Maxscale message from RWSplit"
|
||||
echo "$maxscale_err"
|
||||
echo "Maxscale message from ReadConn master"
|
||||
echo "$maxscale_err1"
|
||||
echo "Maxscale message from ReadConn slave"
|
||||
echo "$maxscale_err2"
|
||||
|
||||
res=0
|
||||
|
||||
#echo "$maxscale_err" | grep "$mariadb_err"
|
||||
if [ "$maxscale_err" != "$mariadb_err" ] ; then
|
||||
echo "Messages are different!"
|
||||
echo "MaxScale: $maxscale_err"
|
||||
echo "Server: $mariadb_err"
|
||||
res=1
|
||||
else
|
||||
echo "Messages are same"
|
||||
fi
|
||||
|
||||
if [ "$maxscale_err1" != "$mariadb_err" ] ; then
|
||||
echo "Messages are different!"
|
||||
echo "MaxScale: $maxscale_err1"
|
||||
echo "Server: $mariadb_err"
|
||||
res=1
|
||||
else
|
||||
echo "Messages are same"
|
||||
fi
|
||||
|
||||
if [ "$maxscale_err2" != "$mariadb_err" ] ; then
|
||||
echo "Messages are different!"
|
||||
echo "MaxScale: $maxscale_err2"
|
||||
echo "Server: $mariadb_err"
|
||||
|
||||
res=1
|
||||
else
|
||||
echo "Messages are same"
|
||||
fi
|
||||
|
||||
$test_dir/copy_logs.sh bug561
|
||||
exit $res
|
42
maxscale-system-test/bug562.sh
Executable file
42
maxscale-system-test/bug562.sh
Executable file
@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
|
||||
###
|
||||
## @file bug562.sh Regression case for the bug "Wrong error message for Access denied error"
|
||||
## - try to connect with bad credestials directly to MariaDB server and via Maxscale
|
||||
## - compare error messages
|
||||
|
||||
rp=`realpath $0`
|
||||
export test_dir=`dirname $rp`
|
||||
export test_name=`basename $rp`
|
||||
|
||||
$test_dir/non_native_setup $test_name
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "configuring maxscale failed"
|
||||
exit 1
|
||||
fi
|
||||
export ssl_options="--ssl-cert=$test_dir/ssl-cert/client-cert.pem --ssl-key=$test_dir/ssl-cert/client-key.pem"
|
||||
|
||||
mariadb_err=`mysql -u no_such_user -psome_pwd -h $node_001_network $ssl_option --socket=$node_000_socket test 2>&1`
|
||||
maxscale_err=`mysql -u no_such_user -psome_pwd -h $maxscale_IP -P 4006 $ssl_options test 2>&1`
|
||||
|
||||
echo "MariaDB message"
|
||||
echo "$mariadb_err"
|
||||
echo " "
|
||||
echo "Maxscale message"
|
||||
echo "$maxscale_err"
|
||||
|
||||
res=0
|
||||
#echo "$maxscale_err" | grep "$mariadb_err"
|
||||
echo "$maxscale_err" |grep "ERROR 1045 (28000): Access denied for user 'no_such_user'@'"
|
||||
if [ "$?" != 0 ]; then
|
||||
echo "Maxscale message is not ok!"
|
||||
echo "Message: $maxscale_err"
|
||||
res=1
|
||||
else
|
||||
echo "Messages are same"
|
||||
res=0
|
||||
fi
|
||||
|
||||
$test_dir/copy_logs.sh bug562
|
||||
exit $res
|
44
maxscale-system-test/bug564.sh
Executable file
44
maxscale-system-test/bug564.sh
Executable file
@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
###
|
||||
## @file bug564.sh Regression case for the bug "Wrong charset settings"
|
||||
## - call MariaDB client with different --default-character-set= settings
|
||||
## - check output of SHOW VARIABLES LIKE 'char%'
|
||||
|
||||
rp=`realpath $0`
|
||||
export test_dir=`dirname $rp`
|
||||
export test_name=`basename $rp`
|
||||
$test_dir/non_native_setup $test_name
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "configuring maxscale failed"
|
||||
exit 1
|
||||
fi
|
||||
export ssl_options="--ssl-cert=$test_dir/ssl-cert/client-cert.pem --ssl-key=$test_dir/ssl-cert/client-key.pem"
|
||||
|
||||
for char_set in "latin1" "latin2"
|
||||
do
|
||||
|
||||
line1=`mysql -u$node_user -p$node_password -h $maxscale_IP -P 4006 $ssl_options --default-character-set="$char_set" -e "SHOW VARIABLES LIKE 'char%'" | grep "character_set_client"`
|
||||
line2=`mysql -u$node_user -p$node_password -h $maxscale_IP -P 4006 $ssl_options --default-character-set="$char_set" -e "SHOW VARIABLES LIKE 'char%'" | grep "character_set_connection"`
|
||||
line3=`mysql -u$node_user -p$node_password -h $maxscale_IP -P 4006 $ssl_options --default-character-set="$char_set" -e "SHOW VARIABLES LIKE 'char%'" | grep "character_set_results"`
|
||||
|
||||
echo $line1 | grep "$char_set"
|
||||
res1=$?
|
||||
echo $line2 | grep "$char_set"
|
||||
res2=$?
|
||||
echo $line3 | grep "$char_set"
|
||||
res3=$?
|
||||
|
||||
|
||||
if [[ $res1 != 0 ]] || [[ $res2 != 0 ]] || [[ $res3 != 0 ]] ; then
|
||||
echo "charset is ignored"
|
||||
mysql -u$node_user -p$node_password -h $maxscale_IP -P 4006 $ssl_options --default-character-set="latin2" -e "SHOW VARIABLES LIKE 'char%'"
|
||||
$test_dir/copy_logs.sh bug564
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
$test_dir/copy_logs.sh bug564
|
||||
exit 0
|
||||
|
||||
|
106
maxscale-system-test/bug565.cpp
Normal file
106
maxscale-system-test/bug565.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @file bug565.cpp regression case for bug 565 ( "Clients CLIENT_FOUND_ROWS setting is ignored by maxscale" ) MAX-311
|
||||
*
|
||||
* - open connection with CLIENT_FOUND_ROWS flag
|
||||
* - CREATE TABLE t1(id INT PRIMARY KEY, val INT, msg VARCHAR(100))
|
||||
* - INSERT INTO t1 VALUES (1, 1, 'foo'), (2, 1, 'bar'), (3, 2, 'baz'), (4, 2, 'abc')"
|
||||
* - check 'affected_rows' for folloing UPDATES:
|
||||
* + UPDATE t1 SET msg='xyz' WHERE val=2" (expect 2)
|
||||
* + UPDATE t1 SET msg='xyz' WHERE val=2 (expect 0)
|
||||
* + UPDATE t1 SET msg='xyz' WHERE val=2 (expect 2)
|
||||
*/
|
||||
|
||||
/*
|
||||
Hartmut Holzgraefe 2014-10-02 14:27:18 UTC
|
||||
Created attachment 155 [details]
|
||||
test for mysql_affected_rows() with/without CLIENT_FOUND_ROWS connection flag
|
||||
|
||||
Even worse: connections via maxscale always behave as if CLIENT_FOUND_ROWS is set even though the default is NOT having it set.
|
||||
|
||||
When doing the same update two times in a row without CLIENT_FOUND_ROWS
|
||||
mysql_affected_rows() should return the number of rows actually changed
|
||||
by the last query, while with CLIENT_FOUND_ROWS connection flag set the
|
||||
number of matching rows is returned, even if the UPDATE didn't change
|
||||
any column values.
|
||||
|
||||
With a direct connection to mysqld this works as expected,
|
||||
through readconnroute(master) I'm always getting the number of matching
|
||||
rows (as if CLIENT_FOUND_ROWS was set), and not the number of actually
|
||||
changed rows when CLIENT_FOUND_ROWS is not set (which is the default
|
||||
behaviour when not setting connection options)
|
||||
|
||||
Attaching PHP mysqli test script, result with direct mysqld connection is
|
||||
|
||||
update #1: 2
|
||||
update #2: 0
|
||||
update #3: 2
|
||||
|
||||
while through maxscale it is
|
||||
|
||||
update #1: 2
|
||||
update #2: 2
|
||||
update #3: 2
|
||||
|
||||
I also verified this using the C API directly to rule out that this is
|
||||
a PHP specific problem
|
||||
Comment 1 Vilho Raatikka 2014-10-08 14:11:38 UTC
|
||||
Client flags are not passed to backend server properly.
|
||||
Comment 2 Vilho Raatikka 2014-10-08 19:35:58 UTC
|
||||
Pushed initial fix to MAX-311. Waiting for validation for the fix.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(30);
|
||||
MYSQL * conn_found_rows;
|
||||
my_ulonglong rows;
|
||||
|
||||
|
||||
Test->repl->connect();
|
||||
Test->connect_maxscale();
|
||||
|
||||
conn_found_rows = open_conn_db_flags(Test->rwsplit_port, Test->maxscale_IP, (char *) "test",
|
||||
Test->maxscale_user, Test->maxscale_password, CLIENT_FOUND_ROWS, Test->ssl);
|
||||
|
||||
Test->set_timeout(30);
|
||||
execute_query(Test->conn_rwsplit, "DROP TABLE IF EXISTS t1");
|
||||
execute_query(Test->conn_rwsplit, "CREATE TABLE t1(id INT PRIMARY KEY, val INT, msg VARCHAR(100))");
|
||||
execute_query(Test->conn_rwsplit,
|
||||
"INSERT INTO t1 VALUES (1, 1, 'foo'), (2, 1, 'bar'), (3, 2, 'baz'), (4, 2, 'abc')");
|
||||
|
||||
Test->set_timeout(30);
|
||||
execute_query_affected_rows(Test->conn_rwsplit, "UPDATE t1 SET msg='xyz' WHERE val=2", &rows);
|
||||
Test->tprintf("update #1: %ld (expeced value is 2)\n", (long) rows);
|
||||
if (rows != 2)
|
||||
{
|
||||
Test->add_result(1, "Affected rows is not 2\n");
|
||||
}
|
||||
|
||||
Test->set_timeout(30);
|
||||
execute_query_affected_rows(Test->conn_rwsplit, "UPDATE t1 SET msg='xyz' WHERE val=2", &rows);
|
||||
Test->tprintf("update #2: %ld (expeced value is 0)\n", (long) rows);
|
||||
if (rows != 0)
|
||||
{
|
||||
Test->add_result(1, "Affected rows is not 0\n");
|
||||
}
|
||||
|
||||
Test->set_timeout(30);
|
||||
execute_query_affected_rows(conn_found_rows, "UPDATE t1 SET msg='xyz' WHERE val=2", &rows);
|
||||
Test->tprintf("update #3: %ld (expeced value is 2)\n", (long) rows);
|
||||
if (rows != 2)
|
||||
{
|
||||
Test->add_result(1, "Affected rows is not 2\n");
|
||||
}
|
||||
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
|
||||
}
|
34
maxscale-system-test/bug567.sh
Executable file
34
maxscale-system-test/bug567.sh
Executable file
@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
###
|
||||
## @file bug567.sh Regression case for the bug "Crash if files from /dev/shm/ removed"
|
||||
## - try to remove everythign from /dev/shm/$maxscale_pid
|
||||
## check if Maxscale is alive
|
||||
|
||||
rp=`realpath $0`
|
||||
export test_dir=`dirname $rp`
|
||||
export test_name=`basename $rp`
|
||||
$test_dir/non_native_setup $test_name
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "configuring maxscale failed"
|
||||
exit 1
|
||||
fi
|
||||
export ssl_options="--ssl-cert=$test_dir/ssl-cert/client-cert.pem --ssl-key=$test_dir/ssl-cert/client-key.pem"
|
||||
|
||||
#pid=`ssh -i $maxscale_sshkey -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $maxscale_access_user@$maxscale_IP "pgrep maxscale"`
|
||||
#echo "Maxscale pid is $pid"
|
||||
echo "removing log directory from /dev/shm/"
|
||||
if [ $maxscale_IP != "127.0.0.1" ] ; then
|
||||
ssh -i $maxscale_sshkey -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $maxscale_access_user@$maxscale_IP "sudo rm -rf /dev/shm/maxscale/*"
|
||||
else
|
||||
sudo rm -rf /dev/shm/maxscale/*
|
||||
fi
|
||||
sleep 1
|
||||
echo "checking if Maxscale is alive"
|
||||
echo "show databases;" | mysql -u$node_user -p$node_password -h $maxscale_IP -P 4006 $ssl_options
|
||||
res=$?
|
||||
|
||||
$test_dir/copy_logs.sh bug567
|
||||
exit $res
|
||||
|
141
maxscale-system-test/bug571.cpp
Normal file
141
maxscale-system-test/bug571.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
/**
|
||||
* @file bug571.cpp regression case for bug 571 and bug 585 ( "Using regex filter hangs MaxScale" and "modutil_extract_SQL doesn't work with multiple GWBUF buffers" )
|
||||
*
|
||||
* - Maxscale.cnf
|
||||
* @verbatim
|
||||
[regex]
|
||||
type=filter
|
||||
module=regexfilter
|
||||
match=[Ff][Oo0][rR][mM]
|
||||
replace=FROM
|
||||
|
||||
[r2]
|
||||
type=filter
|
||||
module=regexfilter
|
||||
match=fetch
|
||||
replace=select
|
||||
|
||||
[hints]
|
||||
type=filter
|
||||
module=hintfilter
|
||||
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router= readwritesplit
|
||||
servers=server1, server2, server3,server4
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
max_slave_connections=100%
|
||||
use_sql_variables_in=all
|
||||
router_options=slave_selection_criteria=LEAST_BEHIND_MASTER
|
||||
filters=hints|regex|r2
|
||||
@endverbatim
|
||||
* for bug585:
|
||||
* @verbatim
|
||||
[regex]
|
||||
type=filter
|
||||
module=regexfilter
|
||||
match=fetch
|
||||
replace=select
|
||||
|
||||
[typo]
|
||||
type=filter
|
||||
module=regexfilter
|
||||
match=[Ff][Oo0][Rr][Mm]
|
||||
replace=from
|
||||
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router= readwritesplit
|
||||
servers=server1, server2, server3,server4
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
max_slave_connections=100%
|
||||
use_sql_variables_in=all
|
||||
router_options=slave_selection_criteria=LEAST_BEHIND_MASTER
|
||||
filters=regex|typo
|
||||
@endverbatim
|
||||
* - fetch * from mysql.user;
|
||||
* - fetch count(*) form mysql.user;
|
||||
* - check if Maxscale is alive
|
||||
*/
|
||||
|
||||
/*
|
||||
Vilho Raatikka 2014-10-10 11:09:19 UTC
|
||||
Branch:release-1.0.1beta
|
||||
Executing :
|
||||
|
||||
fetch * from mysql.user
|
||||
|
||||
with this config hangs MaxScale
|
||||
|
||||
[regex]
|
||||
type=filter
|
||||
module=regexfilter
|
||||
match=[Ff][Oo0][rR][mM]
|
||||
replace=FROM
|
||||
|
||||
[r2]
|
||||
type=filter
|
||||
module=regexfilter
|
||||
match=fetch
|
||||
replace=select
|
||||
|
||||
|
||||
[hints]
|
||||
type=filter
|
||||
module=hintfilter
|
||||
|
||||
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1,server2,server3,server4
|
||||
max_slave_connections=100%
|
||||
use_sql_variables_in=all
|
||||
router_options=slave_selection_criteria=LEAST_BEHIND_MASTER
|
||||
user=maxuser
|
||||
passwd=maxpwd
|
||||
filters=hints|regex|r2
|
||||
Comment 1 Vilho Raatikka 2014-10-11 18:55:23 UTC
|
||||
If we look at the rewrite function we see that query lacks one character.
|
||||
|
||||
T 127.0.0.1:37858 -> 127.0.0.1:4006 [AP]
|
||||
16 00 00 00 03 66 65 74 63 68 20 69 64 20 66 72 .....fetch id fr
|
||||
6f 6d 20 74 65 73 74 2e 74 31 om test.t1
|
||||
|
||||
T 127.0.0.1:44591 -> 127.0.0.1:3000 [AP]
|
||||
17 00 00 00 03 73 65 6c 65 63 74 20 69 64 20 66 .....select id f
|
||||
72 6f 6d 20 74 65 73 74 2e 74 rom test.t
|
||||
*/
|
||||
|
||||
// the same code is used for bug585
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
|
||||
Test->tprintf("Connecting to all MaxScale services\n");
|
||||
Test->set_timeout(10);
|
||||
Test->add_result(Test->connect_maxscale(), "Error connectiong to Maxscale\n");
|
||||
|
||||
Test->tprintf("executing fetch * from mysql.user \n");
|
||||
Test->set_timeout(10);
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "fetch * from mysql.user;");
|
||||
Test->set_timeout(10);
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "fetch count(*) form mysql.user;");
|
||||
|
||||
Test->set_timeout(10);
|
||||
Test->close_maxscale_connections();
|
||||
Test->check_maxscale_alive();
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
46
maxscale-system-test/bug572.cpp
Normal file
46
maxscale-system-test/bug572.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file bug572.cpp regression case for bug 572 ( " If reading a user from users table fails, MaxScale fails" )
|
||||
*
|
||||
* - try GRANT with wrong IP using all Maxscale services:
|
||||
* + GRANT ALL PRIVILEGES ON *.* TO 'foo'@'*.foo.notexists' IDENTIFIED BY 'foo';
|
||||
* + GRANT ALL PRIVILEGES ON *.* TO 'bar'@'127.0.0.*' IDENTIFIED BY 'bar'
|
||||
* + DROP USER 'foo'@'*.foo.notexists'
|
||||
* + DROP USER 'bar'@'127.0.0.*'
|
||||
* - do "select * from mysql.user" using RWSplit to check if Maxsclae crashed
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void create_drop_bad_user(MYSQL * conn, TestConnections * Test)
|
||||
{
|
||||
|
||||
Test->try_query(conn, (char *)
|
||||
"GRANT ALL PRIVILEGES ON *.* TO 'foo'@'*.foo.notexists' IDENTIFIED BY 'foo';");
|
||||
Test->try_query(conn, (char *) "GRANT ALL PRIVILEGES ON *.* TO 'bar'@'127.0.0.*' IDENTIFIED BY 'bar'");
|
||||
Test->try_query(conn, (char *) "DROP USER 'foo'@'*.foo.notexists'");
|
||||
Test->try_query(conn, (char *) "DROP USER 'bar'@'127.0.0.*'");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->repl->connect();
|
||||
Test->connect_maxscale();
|
||||
|
||||
Test->tprintf("Trying GRANT for with bad IP: RWSplit\n");
|
||||
create_drop_bad_user(Test->conn_rwsplit, Test);
|
||||
|
||||
Test->tprintf("Trying SELECT to check if Maxscale hangs\n");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "select * from mysql.user");
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
110
maxscale-system-test/bug587.cpp
Normal file
110
maxscale-system-test/bug587.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
/**
|
||||
* @file bug587.cpp regression case for the bug 587 ( "Hint filter don't work if listed before regex filter in configuration file" )
|
||||
*
|
||||
* - Maxscale.cnf
|
||||
* @verbatim
|
||||
[hints]
|
||||
type=filter
|
||||
module=hintfilter
|
||||
|
||||
[regex]
|
||||
type=filter
|
||||
module=regexfilter
|
||||
match=fetch
|
||||
replace=select
|
||||
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router= readwritesplit
|
||||
servers=server1, server2, server3,server4
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
max_slave_connections=100%
|
||||
use_sql_variables_in=all
|
||||
router_options=slave_selection_criteria=LEAST_BEHIND_MASTER
|
||||
filters=hints|regex
|
||||
@endverbatim
|
||||
* - second test (bug587_1) is executed with "filters=regex|hints" (dffeent order of filters)
|
||||
* - check if hints filter working by executing and comparing results:
|
||||
* + via RWSPLIT: "select @@server_id; -- maxscale route to server server%d" (%d - node number)
|
||||
* + directly to backend node "select @@server_id;"
|
||||
* - do the same test with "filters=regex|hints" "filters=hints|regex"
|
||||
*/
|
||||
|
||||
/*
|
||||
Vilho Raatikka 2014-10-21 19:12:33 UTC
|
||||
If filters and rwsplit are configured as follows, hints don't work.
|
||||
|
||||
[hints]
|
||||
type=filter
|
||||
module=hintfilter
|
||||
|
||||
[regex]
|
||||
type=filter
|
||||
module=regexfilter
|
||||
match=fetch
|
||||
replace=select
|
||||
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1,server2,server3,server4
|
||||
max_slave_connections=100%
|
||||
use_sql_variables_in=all
|
||||
user=maxuser
|
||||
passwd=maxpwd
|
||||
filters=hints|regex
|
||||
|
||||
Changing filters=regex|hints makes it work. This is due to processing order. Regex filter drops hint off.
|
||||
Comment 1 Vilho Raatikka 2014-10-23 18:08:07 UTC
|
||||
buffer.c:gwbuf_make_contiguous: hint wasn't duplicated to new GWBUF struct. As a result hints were lost if query rewriting resulted in longer query than the original.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
Test->repl->connect();
|
||||
Test->connect_maxscale();
|
||||
|
||||
char server_id[256];
|
||||
char server_id_d[256];
|
||||
|
||||
char hint_sql[64];
|
||||
|
||||
for (int i = 1; i < 25; i++)
|
||||
{
|
||||
for (int j = 0; j < Test->repl->N; j++)
|
||||
{
|
||||
Test->set_timeout(10);
|
||||
sprintf(hint_sql, "select @@server_id; -- maxscale route to server server%d", j + 1);
|
||||
Test->tprintf("%s\n", hint_sql);
|
||||
|
||||
find_field(Test->conn_rwsplit, hint_sql, (char *) "@@server_id", &server_id[0]);
|
||||
find_field(Test->repl->nodes[j], (char *) "select @@server_id;", (char *) "@@server_id", &server_id_d[0]);
|
||||
|
||||
Test->tprintf("server%d ID from Maxscale: \t%s\n", j + 1, server_id);
|
||||
Test->tprintf("server%d ID directly from node: \t%s\n", j + 1, server_id_d);
|
||||
|
||||
Test->add_result(strcmp(server_id, server_id_d), "Hints does not work!\n");
|
||||
}
|
||||
}
|
||||
|
||||
Test->close_maxscale_connections();
|
||||
Test->repl->close_connections();
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
129
maxscale-system-test/bug592.cpp
Normal file
129
maxscale-system-test/bug592.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/**
|
||||
* @file bug592.cpp regression case for bug 592 ( "slave in "Running" state breaks authorization" ) MXS-326
|
||||
*
|
||||
* - stop all slaves: "stop slave;" directly to every node (now they are in "Running" state, not in "Russning, Slave")
|
||||
* - via RWSplit "CREATE USER 'test_user'@'%' IDENTIFIED BY 'pass'"
|
||||
* - try to connect using 'test_user' (expecting success)
|
||||
* - start all slaves: "start slave;" directly to every node
|
||||
* - via RWSplit: "DROP USER 'test_user'@'%'"
|
||||
*/
|
||||
|
||||
/*
|
||||
Timofey Turenko 2014-10-24 09:35:35 UTC
|
||||
1. setup: Master/Slave replication
|
||||
2. reboot slaves
|
||||
3. create user usinf connection to RWSplit
|
||||
4. try to use this user to connect to Maxscale
|
||||
|
||||
expected result:
|
||||
Authentication is ok
|
||||
|
||||
actual result:
|
||||
Access denied for user 'user'@'192.168.122.1' (using password: YES)
|
||||
|
||||
Th issue was discovered with following setup state:
|
||||
|
||||
MaxScale> show servers
|
||||
Server 0x3428260 (server1)
|
||||
Server: 192.168.122.106
|
||||
Status: Master, Running
|
||||
Protocol: MySQLBackend
|
||||
Port: 3306
|
||||
Server Version: 5.5.40-MariaDB-log
|
||||
Node Id: 106
|
||||
Master Id: -1
|
||||
Slave Ids: 107, 108 , 109
|
||||
Repl Depth: 0
|
||||
Number of connections: 0
|
||||
Current no. of conns: 0
|
||||
Current no. of operations: 0
|
||||
Server 0x3428160 (server2)
|
||||
Server: 192.168.122.107
|
||||
Status: Slave, Running
|
||||
Protocol: MySQLBackend
|
||||
Port: 3306
|
||||
Server Version: 5.5.40-MariaDB-log
|
||||
Node Id: 107
|
||||
Master Id: 106
|
||||
Slave Ids:
|
||||
Repl Depth: 1
|
||||
Number of connections: 0
|
||||
Current no. of conns: 0
|
||||
Current no. of operations: 0
|
||||
Server 0x3428060 (server3)
|
||||
Server: 192.168.122.108
|
||||
Status: Running
|
||||
Protocol: MySQLBackend
|
||||
Port: 3306
|
||||
Server Version: 5.5.40-MariaDB-log
|
||||
Node Id: 108
|
||||
Master Id: 106
|
||||
Slave Ids:
|
||||
Repl Depth: 1
|
||||
Number of connections: 0
|
||||
Current no. of conns: 0
|
||||
Current no. of operations: 0
|
||||
Server 0x338c3f0 (server4)
|
||||
Server: 192.168.122.109
|
||||
Status: Running
|
||||
Protocol: MySQLBackend
|
||||
Port: 3306
|
||||
Server Version: 5.5.40-MariaDB-log
|
||||
Node Id: 109
|
||||
Master Id: 106
|
||||
Slave Ids:
|
||||
Repl Depth: 1
|
||||
Number of connections: 0
|
||||
Current no. of conns: 0
|
||||
Current no. of operations: 0
|
||||
|
||||
|
||||
Maxscale read mysql.user table from server4 which was not properly replicated
|
||||
Comment 1 Mark Riddoch 2014-11-05 09:55:07 UTC
|
||||
In the reload users routine, if there is a master available then use that rather than the first.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
int i;
|
||||
|
||||
Test->repl->connect();
|
||||
Test->connect_maxscale();
|
||||
|
||||
for (i = 1; i < Test->repl->N; i++)
|
||||
{
|
||||
execute_query(Test->repl->nodes[i], (char *) "stop slave;");
|
||||
}
|
||||
|
||||
execute_query(Test->conn_rwsplit, (char *) "CREATE USER 'test_user'@'%%' IDENTIFIED BY 'pass'");
|
||||
|
||||
MYSQL * conn = open_conn_no_db(Test->rwsplit_port, Test->maxscale_IP, (char *) "test_user", (char *) "pass",
|
||||
Test->ssl);
|
||||
|
||||
if (conn == NULL)
|
||||
{
|
||||
Test->add_result(1, "Connections error\n");
|
||||
}
|
||||
|
||||
for (i = 1; i < Test->repl->N; i++)
|
||||
{
|
||||
execute_query(Test->repl->nodes[i], (char *) "start slave;");
|
||||
}
|
||||
|
||||
execute_query(Test->conn_rwsplit, (char *) "DROP USER 'test_user'@'%%'");
|
||||
|
||||
Test->repl->close_connections();
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
|
||||
}
|
128
maxscale-system-test/bug601.cpp
Normal file
128
maxscale-system-test/bug601.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* @file bug601.cpp regression case for bug 601 ("COM_CHANGE_USER fails with correct user/pwd if executed during authentication")
|
||||
* - configure Maxscale.cnf to use only one thread
|
||||
* - in 100 parallel threads start to open/close session
|
||||
* - do change_user 2000 times
|
||||
* - check all change_user are ok
|
||||
* - check Mascale is alive
|
||||
*/
|
||||
|
||||
/*
|
||||
Vilho Raatikka 2014-10-30 14:30:57 UTC
|
||||
If COM_CHANGE_USER is executed while backend protocol's state is not yet MYSQL_AUTH_RECV it will fail in the backend.
|
||||
|
||||
If MaxScale uses multiple worked threads this occurs rarely and it would be possible to easily suspend execution of COM_CHANGE_USER.
|
||||
|
||||
If MaxScale uses one worker thread then there's currently no way to suspend execution. It would require thread to put current task on hold, complete authentication task and return to COM_CHANGE_USER execution.
|
||||
|
||||
In theory it is possible to add an event to client's DCB and let it become notified in the same way than events that occur in sockets. It would have to be added first (not last) and ensure that no other command is executed before it.
|
||||
|
||||
Since this is the only case known where this would be necessary, it could be enough to add a "pending auth change" pointer in client's protocol object which would be checked before thread returns to epoll_wait after completing the authentication.
|
||||
Comment 1 Massimiliano 2014-11-07 17:01:29 UTC
|
||||
Current code in develop branch let COM_CHANGE_USER work fine.
|
||||
|
||||
I noticed sometime a failed authentication issue using only.
|
||||
This because backend protocol's state is not yet MYSQL_AUTH_RECV and necessary data for succesfull backend change user (such as scramble data from handshake) may be not available.
|
||||
|
||||
|
||||
I put a query before change_user and the issue doesn't appear: that's another proof.
|
||||
Comment 2 Vilho Raatikka 2014-11-13 15:54:15 UTC
|
||||
In gw_change_user->gw_send_change_user_to_backend authentication message was sent to backend server before backend had its scramble data. That caused authentication to fail.
|
||||
Comment 3 Vilho Raatikka 2014-11-13 15:58:34 UTC
|
||||
if (func.auth ==)gw_change_user->gw_send_change_user_to_backend is called before backend has its scramble, auth packet is set to backend's delauqueue instead of writing it to backend. When backend_write_delayqueue is called COM_CHANGE_USER packets are rewritten with backend's current data.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
|
||||
int exit_flag = 0;
|
||||
|
||||
TestConnections * Test ;
|
||||
|
||||
void *parall_traffic( void *ptr );
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int iterations = 1000;
|
||||
Test = new TestConnections(argc, argv);
|
||||
if (Test->smoke)
|
||||
{
|
||||
iterations = 100;
|
||||
}
|
||||
|
||||
|
||||
pthread_t parall_traffic1[100];
|
||||
int check_iret[100];
|
||||
|
||||
Test->set_timeout(60);
|
||||
Test->repl->connect();
|
||||
Test->repl->execute_query_all_nodes((char *) "set global max_connect_errors=1000;");
|
||||
Test->repl->execute_query_all_nodes((char *) "set global max_connections=1000;");
|
||||
|
||||
Test->connect_maxscale();
|
||||
Test->tprintf("Creating one user 'user@%%'");
|
||||
execute_query_silent(Test->conn_rwsplit, (char *) "DROP USER user@'%'");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "CREATE USER user@'%%' identified by 'pass2'");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "GRANT SELECT ON test.* TO user@'%%';");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "FLUSH PRIVILEGES;");
|
||||
|
||||
Test->tprintf("Starting parallel thread which opens/closes session in the loop");
|
||||
|
||||
for (int j = 0; j < 25; j++)
|
||||
{
|
||||
check_iret[j] = pthread_create(¶ll_traffic1[j], NULL, parall_traffic, NULL);
|
||||
}
|
||||
|
||||
Test->tprintf("Doing change_user in the loop");
|
||||
for (int i = 0; i < iterations; i++)
|
||||
{
|
||||
Test->set_timeout(15);
|
||||
Test->add_result(mysql_change_user(Test->conn_rwsplit, "user", "pass2", (char *) "test"),
|
||||
"change_user failed! %", mysql_error(Test->conn_rwsplit));
|
||||
Test->add_result(mysql_change_user(Test->conn_rwsplit, Test->maxscale_user, Test->maxscale_password,
|
||||
(char *) "test"), "change_user failed! %s", mysql_error(Test->conn_rwsplit));
|
||||
}
|
||||
|
||||
Test->tprintf("Waiting for all threads to finish");
|
||||
exit_flag = 1;
|
||||
for (int j = 0; j < 25; j++)
|
||||
{
|
||||
Test->set_timeout(30);
|
||||
pthread_join(parall_traffic1[j], NULL);
|
||||
}
|
||||
Test->tprintf("All threads are finished");
|
||||
Test->repl->flush_hosts();
|
||||
|
||||
Test->tprintf("Change user to '%s' in order to be able to DROP user", Test->maxscale_user);
|
||||
Test->set_timeout(30);
|
||||
mysql_change_user(Test->conn_rwsplit, Test->maxscale_user, Test->maxscale_password, NULL);
|
||||
|
||||
Test->tprintf("Dropping user", Test->maxscale_user);
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "DROP USER user@'%%';");
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
||||
void *parall_traffic( void *ptr )
|
||||
{
|
||||
MYSQL * conn;
|
||||
while (exit_flag == 0)
|
||||
{
|
||||
conn = Test->open_rwsplit_connection();
|
||||
mysql_close(conn);
|
||||
if (Test->backend_ssl)
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
268
maxscale-system-test/bug620.cpp
Normal file
268
maxscale-system-test/bug620.cpp
Normal file
@ -0,0 +1,268 @@
|
||||
/**
|
||||
* @file bug620.cpp bug620 regression case ("enable_root_user=true generates errors to error log")
|
||||
*
|
||||
* - Maxscale.cnf contains RWSplit router definition with enable_root_user=true
|
||||
* - GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'skysqlroot';
|
||||
* - try to connect using 'root' user and execute some query
|
||||
* - errors are not expected in the log. All Maxscale services should be alive.
|
||||
*/
|
||||
|
||||
/*
|
||||
Vilho Raatikka 2014-11-14 09:03:59 UTC
|
||||
Enabling use of root user in MaxScale causes the following being printed to error log. Disabling the setting enable_root_user prevents these errors.
|
||||
|
||||
2014-11-14 11:02:47 Error : getaddrinfo failed for [linux-yxkl.site] due [Name or service not known]
|
||||
2014-11-14 11:02:47 140635119954176 [mysql_users_add()] Failed adding user root@linux-yxkl.site for service [RW Split Router]
|
||||
2014-11-14 11:02:47 Error : getaddrinfo failed for [::1] due [Address family for hostname not supported]
|
||||
2014-11-14 11:02:47 140635119954176 [mysql_users_add()] Failed adding user root@::1 for service [RW Split Router]
|
||||
2014-11-14 11:02:47 140635119954176 [mysql_users_add()] Failed adding user root@127.0.0.1 for service [RW Split Router]
|
||||
Comment 1 Vilho Raatikka 2014-11-14 09:04:40 UTC
|
||||
This appears with binary built from develop branch 14.11.14
|
||||
Comment 2 Massimiliano 2014-11-14 09:15:27 UTC
|
||||
The messages appear in the log because root user has an invalid hostname: linux-yxkl.site
|
||||
|
||||
|
||||
The second message root@127.0.0.1 may be related to a previous root@localhost entry.
|
||||
|
||||
|
||||
Names are resolved to IPs and added into maxscale hashtable: localhost and 127.0.0.1 result in a duplicated entry
|
||||
|
||||
|
||||
|
||||
A standard root@localhost only entry doesn't cause any logged message
|
||||
Comment 3 Vilho Raatikka 2014-11-14 09:24:56 UTC
|
||||
Problem is that they seem critical errors but MaxScale still works like nothing had happened. If the default hostname of the server host is not good, what does it mean for MaxScale? Doest it still accept root user or not? Why it only causes trouble for root user but not for others?
|
||||
|
||||
If the error has no effect in practice, then log entries could be better in debug log.
|
||||
|
||||
Thread ids are suitable in debug log but not anywhere else.
|
||||
Comment 4 Massimiliano 2014-11-14 09:32:27 UTC
|
||||
The 'enable_root_user' option only allows selecting 'root' user from backend databases.
|
||||
|
||||
|
||||
The error messages are printed for all users and report that
|
||||
|
||||
specific_user@specific_host is not loaded but
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
2014-11-14 11:02:47 Error : getaddrinfo failed for [linux-yxkl.site] due [Name or service not known]
|
||||
2014-11-14 11:02:47 140635119954176 [mysql_users_add()] Failed adding user root@linux-yxkl.site for service [RW Split Router]
|
||||
|
||||
2014-11-14 04:19:23 Error : getaddrinfo failed for [ftp.*.fi] due [Name or service not known]
|
||||
2014-11-14 04:19:23 67322400 [mysql_users_add()] Failed adding user foo@ftp.*.fi for service [Master Service]
|
||||
|
||||
|
||||
|
||||
In the examples foo@%.funet.fi and root@linux-yxkl.site are not loaded.
|
||||
|
||||
|
||||
foo@localhost and root@localhost are loaded
|
||||
Comment 5 Vilho Raatikka 2014-11-14 10:55:35 UTC
|
||||
(In reply to comment #4)
|
||||
> The 'enable_root_user' option only allows selecting 'root' user from backend
|
||||
> databases.
|
||||
|
||||
I think that enable_root_user means : MaxScale user can use her 'root' account also with MaxScale.
|
||||
|
||||
Technically your explanation may be correct and I'm not against that. What I mean is that the user may not want to worry about what is 'loaded' or 'selected' under the cover.
|
||||
She simply wants to use root user. If it is not possible then that should be written to error log clearly. For example, "Use of 'root' disabled due to unreachable hostname" or something equally clear.
|
||||
|
||||
Reporting several lines of errors may confuse the user especially if the root account still works perfectly.
|
||||
|
||||
>
|
||||
>
|
||||
> The error messages are printed for all users and report that
|
||||
>
|
||||
> specific_user@specific_host is not loaded but
|
||||
>
|
||||
>
|
||||
> Example:
|
||||
>
|
||||
> 2014-11-14 11:02:47 Error : getaddrinfo failed for [linux-yxkl.site] due
|
||||
> [Name or service not known]
|
||||
> 2014-11-14 11:02:47 140635119954176 [mysql_users_add()] Failed adding user
|
||||
> root@linux-yxkl.site for service [RW Split Router]
|
||||
>
|
||||
> 2014-11-14 04:19:23 Error : getaddrinfo failed for [ftp.*.fi] due [Name or
|
||||
> service not known]
|
||||
> 2014-11-14 04:19:23 67322400 [mysql_users_add()] Failed adding user
|
||||
> foo@ftp.*.fi for service [Master Service]
|
||||
>
|
||||
>
|
||||
>
|
||||
> In the examples foo@%.funet.fi and root@linux-yxkl.site are not loaded.
|
||||
>
|
||||
>
|
||||
> foo@localhost and root@localhost are loaded
|
||||
Comment 6 Massimiliano 2014-11-14 11:00:04 UTC
|
||||
MaxScale MySQL authentication is based on user@host
|
||||
|
||||
|
||||
You may have such situation:
|
||||
|
||||
foo@localhost [OK]
|
||||
foo@x-y-z.notexists [KO]
|
||||
|
||||
user 'foo@localhost' is loaded the latter isn't
|
||||
|
||||
|
||||
For root user is the same.
|
||||
|
||||
Allowing selection of root user means selecting all the rows from mysql.user table where user='root'
|
||||
|
||||
|
||||
if there is any row (root@xxxx) that cannot be loaded the message appears.
|
||||
|
||||
In a standard setup we don't expect any log messages
|
||||
Comment 7 Timofey Turenko 2014-12-10 16:02:36 UTC
|
||||
I tried following:
|
||||
|
||||
via RWSplit:
|
||||
|
||||
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'skysqlroot';
|
||||
|
||||
and try to connect to RWSplit using 'root' and 'skysqlroot' and try some simple query:
|
||||
|
||||
2014-12-10 17:35:43 Error : getaddrinfo failed for [::1] due [Address family for hostname not supported]
|
||||
2014-12-10 17:35:43 Warning: Failed to add user root@::1 for service [RW Split Router]. This user will be unavailable via MaxScale.
|
||||
2014-12-10 17:35:43 Warning: Failed to add user root@127.0.0.1 for service [RW Split Router]. This user will be unavailable via MaxScale.
|
||||
2014-12-10 17:35:43 Error : Failed to start router for service 'HTTPD Router'.
|
||||
2014-12-10 17:35:43 Error : Failed to start service 'HTTPD Router'.
|
||||
2014-12-10 17:36:08 Error : getaddrinfo failed for [::1] due [Address family for hostname not supported]
|
||||
2014-12-10 17:36:08 Warning: Failed to add user root@::1 for service [RW Split Router]. This user will be unavailable via MaxScale.
|
||||
2014-12-10 17:36:08 Warning: Failed to add user root@127.0.0.1 for service [RW Split Router]. This user will be unavailable via MaxScale.
|
||||
|
||||
|
||||
Is it expected?
|
||||
Comment 8 Massimiliano 2014-12-10 16:09:23 UTC
|
||||
root@::1 could not be loaded because it's for IPv6
|
||||
|
||||
root@127.0.0.1 may be not loaded if root@localhost was found before
|
||||
|
||||
As names are translated to IPv4 addresses localhost->127.0.0.1 and that'a duplicate
|
||||
|
||||
|
||||
2014-12-10 17:35:43 Error : Failed to start router for service 'HTTPD Router'.
|
||||
2014-12-10 17:35:43 Error : Failed to start service 'HTTPD Router'.
|
||||
|
||||
Those messages are not part of mysql users load phase.
|
||||
|
||||
when you have auth errors users are reload (in the allowed time window) and you see the messages again
|
||||
|
||||
|
||||
With admin interface you can check:
|
||||
|
||||
|
||||
show dbusers RW Split Router
|
||||
|
||||
and you should see root@% you added with the grant
|
||||
Comment 9 Timofey Turenko 2014-12-12 21:59:30 UTC
|
||||
Following is present in the error log just after MaxScale start:
|
||||
|
||||
|
||||
2014-12-12 23:49:07 Error : getaddrinfo failed for [::1] due [Address family for hostname not supported]
|
||||
2014-12-12 23:49:07 Warning: Failed to add user root@::1 for service [RW Split Router]. This user will be unavailable via MaxScale.
|
||||
2014-12-12 23:49:07 Warning: Failed to add user root@127.0.0.1 for service [RW Split Router]. This user will be unavailable via MaxScale.
|
||||
|
||||
|
||||
first two line are clear: no support for IPv6, but would it be better to print 'warning' instead of 'error'?
|
||||
|
||||
"Failed to add user root@127.0.0.1" - is it correct?
|
||||
|
||||
direct connection to backend gives:
|
||||
MariaDB [(none)]> select User, host from mysql.user;
|
||||
+---------+-----------+
|
||||
| User | host |
|
||||
+---------+-----------+
|
||||
| maxuser | % |
|
||||
| repl | % |
|
||||
| skysql | % |
|
||||
| root | 127.0.0.1 |
|
||||
| root | ::1 |
|
||||
| | localhost |
|
||||
| maxuser | localhost |
|
||||
| root | localhost |
|
||||
| skysql | localhost |
|
||||
| | node1 |
|
||||
| root | node1 |
|
||||
+---------+-----------+
|
||||
|
||||
admin interface gives:
|
||||
|
||||
MaxScale> show dbusers "RW Split Router"
|
||||
Users table data
|
||||
Hashtable: 0x7f6b64000c30, size 52
|
||||
No. of entries: 7
|
||||
Average chain length: 0.1
|
||||
Longest chain length: 1
|
||||
User names: root@192.168.122.106, repl@%, skysql@%, maxuser@127.0.0.1, skysql@127.0.0.1, root@127.0.0.1, maxuser@%
|
||||
|
||||
|
||||
So, root@127.0.0.1 is present in the list.
|
||||
Comment 10 Mark Riddoch 2015-01-05 13:03:34 UTC
|
||||
The message "Failed to add user root@127.0.0.1" is because the two entries root@localhsot and root@127.0.0.1 are seen as duplicates in MaxScale. This is a result of MaxScale resolving hostnames at the time it reads the database rather than at connect time. So a duplicate is detected and the second one causes the error to be displayed.
|
||||
Comment 11 Timofey Turenko 2015-01-09 19:26:35 UTC
|
||||
works as expected, closing.
|
||||
Check for lack of "Error : getaddrinfo failed" added (just in case) and for warning about 'skysql'
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(30);
|
||||
|
||||
Test->connect_maxscale();
|
||||
|
||||
Test->tprintf("Creating 'root'@'%%'\n");
|
||||
//global_result += execute_query(Test->conn_rwsplit, (char *) "CREATE USER 'root'@'%'; SET PASSWORD FOR 'root'@'%' = PASSWORD('skysqlroot');");
|
||||
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%%' IDENTIFIED BY 'skysqlroot';");
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY 'skysqlroot';");
|
||||
sleep(10);
|
||||
|
||||
MYSQL * conn;
|
||||
|
||||
Test->tprintf("Connecting using 'root'@'%%'\n");
|
||||
conn = open_conn(Test->rwsplit_port, Test->maxscale_IP, (char *) "root", (char *) "skysqlroot", Test->ssl);
|
||||
if (mysql_errno(conn) != 0)
|
||||
{
|
||||
Test->add_result(1, "Connection using 'root' user failed, error: %s\n", mysql_error(conn));
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->tprintf("Simple query...\n");
|
||||
Test->try_query(conn, (char *) "SELECT * from mysql.user");
|
||||
Test->try_query(conn,
|
||||
(char *) "set password for 'root'@'localhost' = PASSWORD('');");
|
||||
}
|
||||
if (conn != NULL)
|
||||
{
|
||||
mysql_close(conn);
|
||||
}
|
||||
|
||||
Test->tprintf("Dropping 'root'@'%%'\n");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "DROP USER 'root'@'%%';");
|
||||
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
Test->check_log_err((char *) "Failed to add user skysql", false);
|
||||
Test->check_log_err((char *) "getaddrinfo failed", false);
|
||||
Test->check_log_err((char *) "Couldn't find suitable Master", false);
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
181
maxscale-system-test/bug626.cpp
Normal file
181
maxscale-system-test/bug626.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
/**
|
||||
* @file bug626.cpp regression case for bug 626 ("Crash when user define with old password style (before 4.1 protocol)"), also checks error message in the log for bug428 ("Pre MySQL 4.1 encrypted passwords cause authorization failure")
|
||||
*
|
||||
* - CREATE USER 'old'@'%' IDENTIFIED BY 'old';
|
||||
* - SET PASSWORD FOR 'old'@'%' = OLD_PASSWORD('old');
|
||||
* - try to connect using user 'old'
|
||||
* - check log for "MaxScale does not support these old passwords" warning
|
||||
* - DROP USER 'old'@'%'
|
||||
* - check MaxScale is alive
|
||||
*/
|
||||
|
||||
/*
|
||||
Stephane VAROQUI 2014-11-25 17:37:58 UTC
|
||||
2014-11-21 16:24:03 Error : Invalid authentication message from backend. Error code: 1129, Msg : Host '192.168.42.172' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
|
||||
2014-11-21 16:24:03 Error : access for secrets file [/usr/local/maxscale/maxscale-1.0.1-beta/etc/.secrets] failed. Error 2, No such file or directory.
|
||||
2014-11-21 16:24:03 Error : Unable to get user data from backend database for service RW Split Router. Missing server information.
|
||||
2014-11-21 16:24:03 Error : Unable to write to backend due to authentication failure.
|
||||
2014-11-21 16:24:03 Error : Invalid authentication message from backend. Error code: 1129, Msg : Host '192.168.42.172' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
|
||||
2014-11-21 16:24:03 Error : access for secrets file [/usr/local/maxscale/maxscale-1.0.1-beta/etc/.secrets] failed. Error 2, No such file or directory.
|
||||
2014-11-21 16:24:03 Error : Unable to get user data from backend database for service RW Split Router. Missing server information.
|
||||
2014-11-21 16:24:03 Error : Unable to write to backend due to authentication failure.
|
||||
2014-11-21 16:24:03 Fatal: MaxScale received fatal signal 11. Attempting backtrace.
|
||||
2014-11-21 16:24:03 ./maxscale() [0x53ad1c]
|
||||
|
||||
2014-11-21 16:24:03 /usr/lib64/libpthread.so.0(+0xf6d0) [0x7fd8039756d0]
|
||||
|
||||
2014-11-21 16:24:03 /usr/local/maxscale/maxscale-1.0.1-beta/modules/libreadwritesplit.so(is_read_tmp_table+0x64) [0x7fd7ec0f9d25]
|
||||
|
||||
2014-11-21 16:24:03 /usr/local/maxscale/maxscale-1.0.1-beta/modules/libreadwritesplit.so(+0x5577) [0x7fd7ec0fa577]
|
||||
|
||||
2014-11-21 16:24:03 /usr/local/maxscale/maxscale-1.0.1-beta/modules/libMySQLClient.so(+0x5821) [0x7fd7ea1a1821]
|
||||
|
||||
2014-11-21 16:24:03 /usr/local/maxscale/maxscale-1.0.1-beta/modules/libMySQLClient.so(+0x49df) [0x7fd7ea1a09df]
|
||||
|
||||
2014-11-21 16:24:03 ./maxscale() [0x547093]
|
||||
|
||||
2014-11-21 16:24:03 ./maxscale(poll_waitevents+0xbd) [0x546858]
|
||||
|
||||
2014-11-21 16:24:03 ./maxscale(main+0x12b2) [0x53cfd2]
|
||||
|
||||
2014-11-21 16:24:03 /usr/lib64/libc.so.6(__libc_start_main+0xf5) [0x7fd8035c9d65]
|
||||
|
||||
2014-11-21 16:24:03 ./maxscale() [0x539fdd]
|
||||
Comment 1 Mark Riddoch 2014-11-25 17:57:20 UTC
|
||||
Vilho,
|
||||
|
||||
looks like multiple issues here, the missing authentication data is one problem, but the SEGFAULT appears to occur in the Read/Write Splitter
|
||||
|
||||
2014-11-21 16:24:03 Fatal: MaxScale received fatal signal 11. Attempting backtrace.
|
||||
2014-11-21 16:24:03 ./maxscale() [0x53ad1c]
|
||||
|
||||
2014-11-21 16:24:03 /usr/lib64/libpthread.so.0(+0xf6d0) [0x7fd8039756d0]
|
||||
|
||||
2014-11-21 16:24:03 /usr/local/maxscale/maxscale-1.0.1-beta/modules/libreadwritesplit.so(is_read_tmp_table+0x64) [0x7fd7ec0f9d25]
|
||||
|
||||
2014-11-21 16:24:03 /usr/local/maxscale/maxscale-1.0.1-beta/modules/libreadwritesplit.so(+0x5577) [0x7fd7ec0fa577]
|
||||
|
||||
2014-11-21 16:24:03 /usr/local/maxscale/maxscale-1.0.1-beta/modules/libMySQLClient.so(+0x5821) [0x7fd7ea1a1821]
|
||||
|
||||
Massimiliano 2014-12-01 17:29:26 UTC
|
||||
I have found an easy way to produce the "Host xxxx is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'" error
|
||||
|
||||
|
||||
Connect directly to mysql backend(s):
|
||||
|
||||
# mysql -h 127.0.0.1 -P 3310
|
||||
MariaDB [(none)]> set global max_connect_errors=1;
|
||||
Query OK, 0 rows affected (0.00 sec)
|
||||
|
||||
...
|
||||
|
||||
# nc 127.0.0.1 3310
|
||||
]
|
||||
5.5.5-10.0.11-MariaDB-log??A[(SHQ>$???6$PEI"ilc+L{mysql_native_password
|
||||
|
||||
Ctrl-C
|
||||
|
||||
Next attempt results in:
|
||||
|
||||
# nc 127.0.0.1 3310
|
||||
j?iHost '151.20.6.153' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'[root@mcentos62 ~]
|
||||
|
||||
|
||||
Then I restored error count:
|
||||
|
||||
# mysqladmin -h 127.0.0.1 -P 3310 flush-hosts
|
||||
|
||||
|
||||
|
||||
I launched a mysqlslap test against MaxScale, and after a few seconds I caused the error as described above and ...
|
||||
|
||||
[root@mcentos62 ~]# mysqlslap -h 127.0.0.1 -P 4008 -umassi -pmassi --query="select 1" --concurrency=16 --iterations=200
|
||||
mysqlslap: Cannot run query select 1 ERROR : Authentication with backend failed. Session will be closed.
|
||||
|
||||
But no crash at all, this with GA branch and maxscale-1.0.1-beta RPMs.
|
||||
|
||||
|
||||
Some details about the error itself.
|
||||
|
||||
http://dev.mysql.com/doc/refman/5.0/en/blocked-host.html
|
||||
|
||||
B.5.2.6 Host 'host_name' is blocked
|
||||
If the following error occurs, it means that mysqld has received many connection requests from the given host that were interrupted in the middle:
|
||||
|
||||
...
|
||||
|
||||
By default, mysqld blocks a host after 10 connection errors.
|
||||
|
||||
|
||||
------------------------------------
|
||||
|
||||
I also tried with with gdb and MaxScale binary, with a breakpoint set to the gw_create_backend_connection routine.
|
||||
|
||||
Once the breakpoint is reached I did Ctrl-C int the mysql client (connected to MaxScale) and this caused the error too in the next connection.
|
||||
|
||||
As the client stopped running, MaxScale cannot continue with async backend connection and this may increase the error counter: this may be a good example looking for any possible incomplete backend authentication due to a potential bug.
|
||||
|
||||
|
||||
Note, using a value as high as 10000 for max_connect_errors doesn't result in any issue of course.
|
||||
|
||||
|
||||
BTW, in my today setup even having backends with max_connect_errors=1 doesn't result in any issue at all.
|
||||
|
||||
I run a test with MaxScale on a Virtual CentOS 6.2 on my laptop and backends in a Digital Ocean server, so with the Internet in the middle.
|
||||
Comment 9 Massimiliano 2014-12-03 10:04:49 UTC
|
||||
Reported segfault is related to is_read_tmp_table() routine.
|
||||
|
||||
|
||||
"many connection errors" not spotted yet during MaxScale tests
|
||||
|
||||
|
||||
A new setup is highly desiderable, it should happen in a few days.
|
||||
Comment 10 Massimiliano 2014-12-03 15:48:55 UTC
|
||||
No issues/crea found with user and old_password style.
|
||||
|
||||
Message is logged into the error log where there is such case.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(20);
|
||||
|
||||
printf("Creating user with old style password\n");
|
||||
Test->repl->connect();
|
||||
execute_query(Test->repl->nodes[0], "CREATE USER 'old'@'%%' IDENTIFIED BY 'old';");
|
||||
execute_query(Test->repl->nodes[0], "SET PASSWORD FOR 'old'@'%%' = OLD_PASSWORD('old');");
|
||||
Test->stop_timeout();
|
||||
Test->repl->sync_slaves();
|
||||
|
||||
Test->set_timeout(20);
|
||||
printf("Trying to connect using user with old style password\n");
|
||||
MYSQL * conn = open_conn(Test->rwsplit_port, Test->maxscale_IP, (char *) "old", (char *) "old", Test->ssl);
|
||||
|
||||
if ( mysql_errno(conn) != 0)
|
||||
{
|
||||
Test->tprintf("Connections is not open as expected\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->add_result(1, "Connections is open for the user with old style password.\n");
|
||||
}
|
||||
if (conn != NULL)
|
||||
{
|
||||
mysql_close(conn);
|
||||
}
|
||||
|
||||
execute_query(Test->repl->nodes[0], "DROP USER 'old'@'%%'");
|
||||
|
||||
Test->check_log_err((char *) "MaxScale does not support these old passwords", true);
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
42
maxscale-system-test/bug634.cpp
Normal file
42
maxscale-system-test/bug634.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file bug634.cpp regression case for bug 634 ("SHOW SLAVE STATUS in RW SPLITTER is send to master")
|
||||
*
|
||||
* - execute SHOW SLAVE STATUS and check resut
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Description Stephane VAROQUI 2014-12-03 10:41:30 UTC
|
||||
SHOW SLAVE STATUS in RW SPLITTER is send to master ? That could break some monitoring scripts for generic proxy abstraction .
|
||||
Comment 1 Vilho Raatikka 2014-12-03 11:10:12 UTC
|
||||
COM_SHOW_SLAVE_STAT was unknown to query classifier. Being fixed.
|
||||
Comment 2 Vilho Raatikka 2014-12-03 11:26:17 UTC
|
||||
COM_SHOW_SLAVE_STAT wasn't classified but it was treated as 'unknown' and thus routed to master.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(5);
|
||||
|
||||
char master_ip[100];
|
||||
|
||||
Test->connect_maxscale();
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
Test->set_timeout(5);
|
||||
Test->add_result(find_field(Test->conn_rwsplit, (char *) "SHOW SLAVE STATUS", (char *) "Master_Host",
|
||||
master_ip), "Master_host files is not found in the SHOW SLAVE STATUS reply, probably query went to master\n");
|
||||
Test->add_result(strcmp(master_ip, Test->repl->IP_private[0]), "Master IP is wrong\n");
|
||||
}
|
||||
|
||||
Test->close_maxscale_connections();
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
64
maxscale-system-test/bug643.cpp
Normal file
64
maxscale-system-test/bug643.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @file bug643.cpp regression case for bugs 643 ("Hints, RWSplit: MaxScale goes into infinite loop and crashes") and bug645
|
||||
* - setup RWSplit in the following way for bug643
|
||||
* @verbatim
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1,server2,server3,server4
|
||||
max_slave_connections=100%
|
||||
use_sql_variables_in=all
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
filters=duplicate
|
||||
|
||||
[duplicate]
|
||||
type=filter
|
||||
module=tee
|
||||
service=RW Split Router
|
||||
@endverbatim
|
||||
* - try to connect
|
||||
* - try simple query using ReadConn router (both, master and slave)
|
||||
* - check warnig in the log "RW Split Router: Recursive use of tee filter in service"
|
||||
*/
|
||||
|
||||
/*
|
||||
Mark Riddoch 2014-12-11 11:59:19 UTC
|
||||
There is a recursive use of the tee filter in the configuration.
|
||||
|
||||
The "RW Split Router" uses the"duplicate" filter that will then duplicate all traffic to the original destination and another copy of the "RW Split Router", which again will duplicate all traffic to the original destination and another copy of the "RW Split Router"...
|
||||
|
||||
Really this needs to be trapped as a configuration error.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->tprintf("Trying to connect to all Maxscale services\n");
|
||||
fflush(stdout);
|
||||
Test->connect_maxscale();
|
||||
Test->tprintf("Trying to send query to ReadConn master\n");
|
||||
fflush(stdout);
|
||||
Test->try_query(Test->conn_master, (char *) "show processlist");
|
||||
Test->tprintf("Trying to send query to ReadConn slave\n");
|
||||
fflush(stdout);
|
||||
Test->try_query(Test->conn_slave, (char *) "show processlist");
|
||||
Test->tprintf("Trying to send query to RWSplit, expecting failure\n");
|
||||
fflush(stdout);
|
||||
if (execute_query(Test->conn_rwsplit, (char *) "show processlist") == 0)
|
||||
{
|
||||
Test->add_result(1, "FAIL: Query to broken service succeeded!\n");
|
||||
}
|
||||
Test->close_maxscale_connections();
|
||||
Test->check_log_err((char *) "RW-Split-Router: Recursive use of tee filter in service", true);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
96
maxscale-system-test/bug643_1.cpp
Normal file
96
maxscale-system-test/bug643_1.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @file bug643.cpp regression case for bugs 643 ("Hints, RWSplit: MaxScale goes into infinite loop and crashes") and bug645
|
||||
* - setup RWSplit in the following way for bug643
|
||||
* @verbatim
|
||||
[hints]
|
||||
type=filter
|
||||
module=hintfilter
|
||||
|
||||
|
||||
[regex]
|
||||
type=filter
|
||||
module=regexfilter
|
||||
match=fetch
|
||||
replace=select
|
||||
|
||||
[typo]
|
||||
type=filter
|
||||
module=regexfilter
|
||||
match=[Ff][Oo0][Rr][Mm]
|
||||
replace=from
|
||||
|
||||
[qla]
|
||||
type=filter
|
||||
module=qlafilter
|
||||
options=/tmp/QueryLog
|
||||
|
||||
[duplicate]
|
||||
type=filter
|
||||
module=tee
|
||||
service=RW Split2
|
||||
|
||||
[testfilter]
|
||||
type=filter
|
||||
module=foobar
|
||||
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1,server2,server3,server4
|
||||
#servers=server1,server2
|
||||
max_slave_connections=100%
|
||||
use_sql_variables_in=all
|
||||
#use_sql_variables_in=master
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
#filters=typo|qla|regex|hints|regex|hints
|
||||
#enable_root_user=1
|
||||
filters=duplicate
|
||||
|
||||
[RW Split2]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1,server2,server3,server4
|
||||
max_slave_connections=100%
|
||||
use_sql_variables_in=all
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
filters=qla|tests|hints
|
||||
|
||||
@endverbatim
|
||||
* - try to connect
|
||||
* - try simple query using all services
|
||||
* - check warnig in the log "Failed to start service 'RW Split2"
|
||||
* - check if Maxscale still alive
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->tprintf("Trying to connect to all Maxscale services\n");
|
||||
fflush(stdout);
|
||||
Test->connect_maxscale();
|
||||
Test->tprintf("Trying to send query to RWSplit\n");
|
||||
fflush(stdout);
|
||||
execute_query(Test->conn_rwsplit, (char *) "show processlist");
|
||||
Test->tprintf("Trying to send query to ReadConn master\n");
|
||||
fflush(stdout);
|
||||
execute_query(Test->conn_master, (char *) "show processlist");
|
||||
Test->tprintf("Trying to send query to ReadConn slave\n");
|
||||
fflush(stdout);
|
||||
execute_query(Test->conn_slave, (char *) "show processlist");
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
Test->check_log_err((char *) "Unable to find filter 'tests' for service 'RW Split2'", true);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
213
maxscale-system-test/bug645.cpp
Normal file
213
maxscale-system-test/bug645.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
/**
|
||||
* @file bug643.cpp regression case for bugs 645 ("Tee filter with readwritesplit service hangs MaxScale")
|
||||
* - setup RWSplit in the following way
|
||||
* @verbatim
|
||||
[RW_Router]
|
||||
type=service
|
||||
router=readconnroute
|
||||
servers=server1
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
version_string=5.1-OLD-Bored-Mysql
|
||||
filters=DuplicaFilter
|
||||
|
||||
[RW_Split]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1, server3,server2
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
|
||||
[DuplicaFilter]
|
||||
type=filter
|
||||
module=tee
|
||||
service=RW_Split
|
||||
|
||||
[RW_Listener]
|
||||
type=listener
|
||||
service=RW_Router
|
||||
protocol=MySQLClient
|
||||
port=4006
|
||||
|
||||
[RW_Split_list]
|
||||
type=listener
|
||||
service=RW_Split
|
||||
protocol=MySQLClient
|
||||
port=4016
|
||||
|
||||
@endverbatim
|
||||
* - try to connect
|
||||
* - try simple query
|
||||
* - check MaxScale is alive
|
||||
*/
|
||||
|
||||
/*
|
||||
Massimiliano 2014-12-11 14:19:51 UTC
|
||||
When tee filter is used with a readwritesplit service MaxScale hangs (each service including admin interface)or there is a failed assetion in Debug mode:
|
||||
|
||||
debug assert /source/GA/server/modules/routing/readwritesplit/readwritesplit.c:1825
|
||||
maxscale: /source/GA/server/modules/routing/readwritesplit/readwritesplit.c:1825: routeQuery: Assertion `!(querybuf->gwbuf_type == 0)' failed.
|
||||
|
||||
|
||||
Configuration:
|
||||
|
||||
|
||||
[RW_Router]
|
||||
type=service
|
||||
router=readconnroute
|
||||
servers=server1
|
||||
user=massi
|
||||
passwd=massi
|
||||
version_string=5.1-OLD-Bored-Mysql
|
||||
filters=DuplicaFilter
|
||||
|
||||
[RW_Split]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server3,server2
|
||||
user=massi
|
||||
passwd=massi
|
||||
|
||||
[DuplicaFilter]
|
||||
type=filter
|
||||
module=tee
|
||||
service=RW_Split
|
||||
|
||||
[RW_Listener]
|
||||
type=listener
|
||||
service=RW_Router
|
||||
protocol=MySQLClient
|
||||
port=4606
|
||||
|
||||
|
||||
Accessing the RW_listener:
|
||||
|
||||
mysql -h 127.0.0.1 -P 4606 -umassi -pmassi
|
||||
|
||||
|
||||
|
||||
Debug version:
|
||||
|
||||
2014-12-11 08:48:48 Fatal: MaxScale received fatal signal 6. Attempting backtrace.
|
||||
2014-12-11 08:48:48 ./maxscale() [0x53c80e]
|
||||
2014-12-11 08:48:48 /lib64/libpthread.so.0(+0xf710) [0x7fd418a62710]
|
||||
2014-12-11 08:48:48 /lib64/libc.so.6(gsignal+0x35) [0x7fd417318925]
|
||||
2014-12-11 08:48:48 /lib64/libc.so.6(abort+0x175) [0x7fd41731a105]
|
||||
2014-12-11 08:48:48 /lib64/libc.so.6(+0x2ba4e) [0x7fd417311a4e]
|
||||
2014-12-11 08:48:48 /lib64/libc.so.6(__assert_perror_fail+0) [0x7fd417311b10]
|
||||
2014-12-11 08:48:48 /usr/local/skysql/maxscale/modules/libreadwritesplit.so(+0x69ca) [0x7fd4142789ca]
|
||||
2014-12-11 08:48:48 /usr/local/skysql/maxscale/modules/libtee.so(+0x3707) [0x7fd3fc2db707]
|
||||
2014-12-11 08:48:48 /usr/local/skysql/maxscale/modules/libMySQLClient.so(+0x595d) [0x7fd3fe34b95d]
|
||||
2014-12-11 08:48:48 ./maxscale() [0x54d3ec]
|
||||
2014-12-11 08:48:48 ./maxscale(poll_waitevents+0x63d) [0x54ca8a]
|
||||
2014-12-11 08:48:48 ./maxscale(main+0x1acc) [0x53f616]
|
||||
2014-12-11 08:48:48 /lib64/libc.so.6(__libc_start_main+0xfd) [0x7fd417304d1d]
|
||||
2014-12-11 08:48:48 ./maxscale() [0x53a92d]
|
||||
|
||||
|
||||
Without debug:
|
||||
|
||||
we got mysql prompt but then maxscale is stucked
|
||||
or
|
||||
when don't have the prompt, it hangs after few welcome messages
|
||||
Comment 1 Vilho Raatikka 2014-12-11 15:14:50 UTC
|
||||
The assertion occurs because query is is not statement - but packet type. That is, it was sent to read connection router which doesn't examine MySQL packets except the header. Thus, the type of query is not set in mysql_client.c:gw_read_client_event:
|
||||
>>>
|
||||
if (cap == 0 || (cap == RCAP_TYPE_PACKET_INPUT))
|
||||
{
|
||||
stmt_input = false;
|
||||
}
|
||||
else if (cap == RCAP_TYPE_STMT_INPUT)
|
||||
{
|
||||
stmt_input = true;
|
||||
|
||||
gwbuf_set_type(read_buffer, GWBUF_TYPE_MYSQL);
|
||||
}
|
||||
>>>
|
||||
Comment 2 Massimiliano 2014-12-11 16:00:52 UTC
|
||||
Using readconnroute (with router_options=master) instead seems fine.
|
||||
|
||||
I found that "USE dbname" is not passed via tee filter:
|
||||
|
||||
|
||||
4606 is the listener to a service with tee filter
|
||||
|
||||
root@maxscale-02 build]# mysql -h 127.0.0.1 -P 4606 -u massi -pmassi
|
||||
|
||||
|
||||
|
||||
USE test; SELECT DATABASE()
|
||||
client to maxscale:
|
||||
|
||||
T 127.0.0.1:40440 -> 127.0.0.1:4606 [AP]
|
||||
05 00 00 00 02 74 65 73 74 .....test
|
||||
|
||||
T 127.0.0.1:4606 -> 127.0.0.1:40440 [AP]
|
||||
07 00 00 01 00 00 00 02 00 00 00 ...........
|
||||
|
||||
T 127.0.0.1:40440 -> 127.0.0.1:4606 [AP]
|
||||
12 00 00 00 03 53 45 4c 45 43 54 20 44 41 54 41 .....SELECT DATA
|
||||
42 41 53 45 28 29 BASE()
|
||||
|
||||
T 127.0.0.1:4606 -> 127.0.0.1:40440 [AP]
|
||||
01 00 00 01 01 20 00 00 02 03 64 65 66 00 00 00 ..... ....def...
|
||||
0a 44 41 54 41 42 41 53 45 28 29 00 0c 08 00 22 .DATABASE()...."
|
||||
00 00 00 fd 00 00 1f 00 00 05 00 00 03 fe 00 00 ................
|
||||
02 00 05 00 00 04 04 74 65 73 74 05 00 00 05 fe .......test.....
|
||||
00 00 02 00 ....
|
||||
|
||||
maxscale to backend:
|
||||
|
||||
|
||||
T 127.0.0.1:56578 -> 127.0.0.1:3308 [AP]
|
||||
12 00 00 00 03 53 45 4c 45 43 54 20 44 41 54 41 .....SELECT DATA
|
||||
42 41 53 45 28 29 BASE()
|
||||
|
||||
T 127.0.0.1:3308 -> 127.0.0.1:56578 [AP]
|
||||
01 00 00 01 01 20 00 00 02 03 64 65 66 00 00 00 ..... ....def...
|
||||
0a 44 41 54 41 42 41 53 45 28 29 00 0c 08 00 22 .DATABASE()...."
|
||||
00 00 00 fd 00 00 1f 00 00 05 00 00 03 fe 00 00 ................
|
||||
02 00 01 00 00 04 fb 05 00 00 05 fe 00 00 02 00 ................
|
||||
|
||||
|
||||
USE test was not sent
|
||||
|
||||
|
||||
|
||||
May be a similar issue is present with readwritesplit but I cannot test it
|
||||
Comment 3 Vilho Raatikka 2014-12-11 16:35:46 UTC
|
||||
(In reply to comment #2)
|
||||
> Using readconnroute (with router_options=master) instead seems fine.
|
||||
|
||||
Using readconnroute _where_? in tee?
|
||||
Comment 4 Vilho Raatikka 2014-12-12 08:27:41 UTC
|
||||
gwbuf_type is not set and that is the immediate cause for assertion with Debug version.
|
||||
Reason why the type is not set is in the way the packets are first processed in mysql_client.c client protocol module and then passed optionally to filters and router. There is a bug because it is assumed that when client protocol module reads incoming packet it can resolve which router will handle the packet processing. The code doesn't take into account that same packet can be processed by many different routers, like in the case of readconnrouter->tee->readwritesplit.
|
||||
Another problem is in readwritesplit where it is assumed that it is the first and the only router that will process tha data. So it includes checks that the buffer has correct type.
|
||||
|
||||
Required changes are:
|
||||
- readwritesplit should check if buffer has no type and in that case, insted of asserting, merge incoming MySQL packet fragments into a single contiguous buffer.
|
||||
- remove checks which enforce rules which are based on false assumption.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->connect_maxscale();
|
||||
Test->try_query(Test->conn_master, (char *) "show processlist");
|
||||
Test->try_query(Test->conn_slave, (char *) "show processlist");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "show processlist");
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
104
maxscale-system-test/bug645_1.cpp
Normal file
104
maxscale-system-test/bug645_1.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* @file bug643.cpp regression case for bugs 645 ("Tee filter with readwritesplit service hangs MaxScale")
|
||||
* - setup RWSplit in the following way
|
||||
* @verbatim
|
||||
[RW_Router]
|
||||
type=service
|
||||
router=readconnroute
|
||||
servers=server1
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
version_string=5.1-OLD-Bored-Mysql
|
||||
filters=DuplicaFilter
|
||||
|
||||
[RW_Split]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server3,server2
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
|
||||
[DuplicaFilter]
|
||||
type=filter
|
||||
module=tee
|
||||
service=RW_Split
|
||||
|
||||
[RW_Listener]
|
||||
type=listener
|
||||
service=RW_Router
|
||||
protocol=MySQLClient
|
||||
port=4006
|
||||
|
||||
[RW_Split_list]
|
||||
type=listener
|
||||
service=RW_Split
|
||||
protocol=MySQLClient
|
||||
port=4016
|
||||
|
||||
[Read Connection Router Slave]
|
||||
type=service
|
||||
router=readconnroute
|
||||
router_options= slave
|
||||
servers=server1,server2,server3,server4
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
filters=QLA
|
||||
|
||||
[Read Connection Router Master]
|
||||
type=service
|
||||
router=readconnroute
|
||||
router_options=master
|
||||
servers=server1,server2,server3,server4
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
filters=QLA
|
||||
|
||||
[Read Connection Listener Slave]
|
||||
type=listener
|
||||
service=Read Connection Router Slave
|
||||
protocol=MySQLClient
|
||||
port=4009
|
||||
|
||||
[Read Connection Listener Master]
|
||||
type=listener
|
||||
service=Read Connection Router Master
|
||||
protocol=MySQLClient
|
||||
port=4008
|
||||
|
||||
|
||||
@endverbatim
|
||||
* - try to connect to all services except 4016
|
||||
* - try simple query
|
||||
* - check ReadConn is ok
|
||||
* - check log for presens of "Couldn't find suitable Master from 2 candidates" errors
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->connect_maxscale();
|
||||
Test->tprintf("trying query to RWSplit, expecting failure\n");
|
||||
if (execute_query(Test->conn_rwsplit, (char *) "show processlist") == 0)
|
||||
{
|
||||
Test->add_result(1, "Query is ok, but failue is expected\n");
|
||||
}
|
||||
Test->tprintf("Trying query to ReadConn router master\n");
|
||||
Test->try_query(Test->conn_master, (char *) "show processlist");
|
||||
Test->tprintf("Trying query to ReadConn router slave\n");
|
||||
Test->try_query(Test->conn_slave, (char *) "show processlist");
|
||||
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
Test->check_log_err((char *) "Couldn't find suitable Master from 2 candidates", true);
|
||||
Test->check_log_err((char *) "Creating client session for Tee filter failed. Terminating session.", true);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
156
maxscale-system-test/bug649.cpp
Normal file
156
maxscale-system-test/bug649.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
/**
|
||||
* @file bug649.cpp regression case for bug 649 ("Segfault using RW Splitter")
|
||||
* @verbatim
|
||||
|
||||
[RW_Router]
|
||||
type=service
|
||||
router=readconnroute
|
||||
servers=server1
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
version_string=5.1-OLD-Bored-Mysql
|
||||
filters=DuplicaFilter
|
||||
|
||||
[RW_Split]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1,server3,server2
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
|
||||
[DuplicaFilter]
|
||||
type=filter
|
||||
module=tee
|
||||
service=RW_Split
|
||||
|
||||
@endverbatim
|
||||
* - Connect to RWSplit
|
||||
* - create load on RWSplit (25 threads doing long INSERTs in the loop)
|
||||
* - block Mariadb server on Master node by Firewall
|
||||
* - unblock Mariadb server
|
||||
* - check if Maxscale is alive
|
||||
* - reconnect and check if query execution is ok
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
#include "sql_t1.h"
|
||||
|
||||
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
|
||||
int exit_flag = 0;
|
||||
|
||||
TestConnections * Test ;
|
||||
|
||||
char sql[1000000];
|
||||
|
||||
void *parall_traffic( void *ptr );
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int threads_num = 20;
|
||||
pthread_t parall_traffic1[threads_num];
|
||||
int check_iret[threads_num];
|
||||
|
||||
Test = new TestConnections(argc, argv);
|
||||
int time_to_run = (Test->smoke) ? 10 : 30;
|
||||
Test->set_timeout(10);
|
||||
|
||||
Test->tprintf("Connecting to RWSplit %s\n", Test->maxscale_IP);
|
||||
Test->connect_rwsplit();
|
||||
|
||||
Test->repl->connect();
|
||||
Test->tprintf("Drop t1 if exists\n");
|
||||
execute_query(Test->repl->nodes[0], "DROP TABLE IF EXISTS t1;");
|
||||
Test->tprintf("Create t1\n");
|
||||
Test->add_result(create_t1(Test->repl->nodes[0]), "t1 creation Failed\n");
|
||||
Test->repl->close_connections();
|
||||
|
||||
Test->stop_timeout();
|
||||
sleep(5);
|
||||
|
||||
create_insert_string(sql, 65000, 1);
|
||||
Test->tprintf("Creating query threads\n", time_to_run);
|
||||
for (int j = 0; j < threads_num; j++)
|
||||
{
|
||||
Test->set_timeout(20);
|
||||
check_iret[j] = pthread_create(¶ll_traffic1[j], NULL, parall_traffic, NULL);
|
||||
}
|
||||
|
||||
Test->stop_timeout();
|
||||
Test->tprintf("Waiting %d seconds\n", time_to_run);
|
||||
sleep(time_to_run);
|
||||
|
||||
Test->tprintf("Setup firewall to block mysql on master\n");
|
||||
Test->repl->block_node(0);
|
||||
fflush(stdout);
|
||||
|
||||
Test->tprintf("Waiting %d seconds\n", time_to_run);
|
||||
sleep(time_to_run);
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->tprintf("Trying query to RWSplit, expecting failure, but not a crash\n");
|
||||
if (execute_query_silent(Test->conn_rwsplit, (char *) "show processlist;") == 0)
|
||||
{
|
||||
Test->add_result(1, "Failure is expected, but query is ok\n");
|
||||
}
|
||||
|
||||
Test->stop_timeout();
|
||||
sleep(time_to_run);
|
||||
|
||||
Test->tprintf("Setup firewall back to allow mysql\n");
|
||||
Test->repl->unblock_node(0);
|
||||
fflush(stdout);
|
||||
Test->stop_timeout();
|
||||
sleep(time_to_run);
|
||||
exit_flag = 1;
|
||||
for (int i = 0; i < threads_num; i++)
|
||||
{
|
||||
Test->set_timeout(30);
|
||||
pthread_join(parall_traffic1[i], NULL);
|
||||
Test->tprintf("exit %d\n", i);
|
||||
}
|
||||
Test->stop_timeout();
|
||||
sleep(5);
|
||||
|
||||
Test->set_timeout(20);
|
||||
Test->tprintf("Checking Maxscale is alive\n");
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
Test->set_timeout(20);
|
||||
Test->tprintf("Reconnecting to RWSplit ...\n");
|
||||
Test->connect_rwsplit();
|
||||
Test->tprintf(" ... and trying query\n");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "show processlist;");
|
||||
Test->close_rwsplit();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
void *parall_traffic( void *ptr )
|
||||
{
|
||||
MYSQL * conn;
|
||||
mysql_thread_init();
|
||||
conn = Test->open_rwsplit_connection();
|
||||
if ((conn != NULL) && (mysql_errno(conn) == 0))
|
||||
{
|
||||
while (exit_flag == 0)
|
||||
{
|
||||
execute_query_silent(conn, sql);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->tprintf("Error opening connection");
|
||||
}
|
||||
|
||||
if (conn != NULL )
|
||||
{
|
||||
mysql_close(conn);
|
||||
}
|
||||
return NULL;
|
||||
}
|
84
maxscale-system-test/bug650.cpp
Normal file
84
maxscale-system-test/bug650.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @file bug650.cpp regression case for bug 650 ("Hints, RWSplit: MaxScale goes into infinite loop and crashes") and bug645
|
||||
* - setup RWSplit in the following way
|
||||
* @verbatim
|
||||
[RW_Router]
|
||||
type=service
|
||||
router=readconnroute
|
||||
servers=server1
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
version_string=5.1-OLD-Bored-Mysql
|
||||
filters=DuplicaFilter
|
||||
|
||||
[RW_Split]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server3,server2
|
||||
user=skysql
|
||||
passwd=skysql
|
||||
|
||||
[DuplicaFilter]
|
||||
type=filter
|
||||
module=tee
|
||||
service=RW_Split
|
||||
|
||||
[RW_Listener]
|
||||
type=listener
|
||||
service=RW_Router
|
||||
protocol=MySQLClient
|
||||
port=4006
|
||||
|
||||
[RW_Split_list]
|
||||
type=listener
|
||||
service=RW_Split
|
||||
protocol=MySQLClient
|
||||
port=4016
|
||||
|
||||
@endverbatim
|
||||
* - try to connect
|
||||
* - try simple query using ReadConn router (both, master and slave)
|
||||
* - check errors in the log
|
||||
@verbatim
|
||||
Couldn't find suitable Master from 2 candidates
|
||||
Failed to create RW_Split session.
|
||||
Creating client session for Tee filter failed. Terminating session.
|
||||
Failed to create filter 'DuplicaFilter' for service 'RW_Router'
|
||||
Setting up filters failed. Terminating session RW_Router
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(20);
|
||||
|
||||
Test->connect_maxscale();
|
||||
Test->tprintf("Trying query to ReadConn master\n");
|
||||
Test->try_query(Test->conn_master, (char *) "show processlist");
|
||||
Test->tprintf("Trying query to ReadConn slave\n");
|
||||
Test->try_query(Test->conn_slave, (char *) "show processlist");
|
||||
Test->tprintf("Trying query to RWSplit, expecting failure\n");
|
||||
if (execute_query(Test->conn_rwsplit, (char *) "show processlist") == 0)
|
||||
{
|
||||
Test->add_result(1, "Query is ok, but failure is expected\n");
|
||||
}
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
Test->tprintf("Checking logs\n");
|
||||
|
||||
Test->check_log_err((char *) "Couldn't find suitable Master from 2 candidates", true);
|
||||
Test->check_log_err((char *) "Failed to create new router session for service 'RW_Split'", true);
|
||||
Test->check_log_err((char *) "Creating client session for Tee filter failed. Terminating session.", true);
|
||||
Test->check_log_err((char *) "Failed to create filter 'DuplicaFilter' for service 'RW_Router'", true);
|
||||
Test->check_log_err((char *) "Setting up filters failed. Terminating session RW_Router", true);
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
||||
|
80
maxscale-system-test/bug653.cpp
Normal file
80
maxscale-system-test/bug653.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @file bug653.cpp regression case for bug 653 ("Memory corruption when users with long hostnames that can no the resolved are loaded into MaxScale")
|
||||
*
|
||||
* - CREATE USER 'user_with_very_long_hostname'@'very_long_hostname_that_can_not_be_resolved_and_it_probably_caused_crash.com.net.org' IDENTIFIED BY 'old';
|
||||
* - try to connect using user 'user_with_very_long_hostname'
|
||||
* - DROP USER 'user_with_very_long_hostname'@'very_long_hostname_that_can_not_be_resolved_and_it_probably_caused_crash.com.net.org'
|
||||
* - check MaxScale is alive
|
||||
*/
|
||||
|
||||
/*
|
||||
Mark Riddoch 2014-12-16 13:17:25 UTC
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
0x00007ffff49385ac in free () from /lib64/libc.so.6
|
||||
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.47.el6_2.12.x86_64 keyutils-libs-1.4-4.el6.x86_64 krb5-libs-1.10.3-10.el6_4.2.x86_64 libaio-0.3.107-10.el6.x86_64 libcom_err-1.41.12-14.el6.x86_64 libgcc-4.4.7-4.el6.x86_64 libselinux-2.0.94-5.3.el6_4.1.x86_64 libstdc++-4.4.7-4.el6.x86_64 nss-pam-ldapd-0.7.5-14.el6_2.1.x86_64 nss-softokn-freebl-3.14.3-10.el6_5.x86_64 openssl-1.0.1e-16.el6_5.15.x86_64 zlib-1.2.3-29.el6.x86_64
|
||||
(gdb) where
|
||||
#0 0x00007ffff49385ac in free () from /lib64/libc.so.6
|
||||
#1 0x000000000041d421 in add_mysql_users_with_host_ipv4 (users=0x72c4c0,
|
||||
user=0x739030 "u3", host=0x739033 "aver.log.hostname.to.overflow.the.buffer",
|
||||
passwd=0x73905c "", anydb=0x739089 "Y", db=0x0) at dbusers.c:291
|
||||
#2 0x000000000041e302 in getUsers (service=0x728ef0, users=0x72c4c0)
|
||||
at dbusers.c:742
|
||||
#3 0x000000000041cf97 in load_mysql_users (service=0x728ef0) at dbusers.c:99
|
||||
#4 0x00000000004128c7 in serviceStartPort (service=0x728ef0, port=0x729b70)
|
||||
at service.c:227
|
||||
#5 0x0000000000412e27 in serviceStart (service=0x728ef0) at service.c:365
|
||||
#6 0x0000000000412f00 in serviceStartAll () at service.c:413
|
||||
#7 0x000000000040b592 in main (argc=2, argv=0x7fffffffe108) at gateway.c:1750
|
||||
Comment 1 Mark Riddoch 2014-12-16 13:18:09 UTC
|
||||
The problem is a buffer overrun in normalise_hostname. Fix underway.
|
||||
Comment 2 Mark Riddoch 2014-12-16 15:45:59 UTC
|
||||
Increased buffer size to prevent overrun issue
|
||||
Comment 3 Timofey Turenko 2014-12-22 15:39:32 UTC
|
||||
I'm not sure I understand the bug correctly.
|
||||
But 60-chars long host name does not cause problem (longer is not possible "String 'very_long_hostname_that_can_not_be_resolved_and_it_probably_caused_cra' is too long for host name (should be no longer than 60)"
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(50);
|
||||
Test->connect_maxscale();
|
||||
|
||||
Test->tprintf("Creating user with old style password\n");
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "CREATE USER 'user_long_host11'@'very_long_hostname_that_probably_caused_crashhh.com.net.org' IDENTIFIED BY 'old'");
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "GRANT ALL PRIVILEGES ON *.* TO 'user_long_host11'@'very_long_hostname_that_probably_caused_crashhh.com.net.org' WITH GRANT OPTION");
|
||||
sleep(10);
|
||||
|
||||
Test->tprintf("Trying to connect using user with old style password\n");
|
||||
MYSQL * conn = open_conn(Test->rwsplit_port, Test->maxscale_IP, (char *) "user_long_host11", (char *) "old",
|
||||
Test->ssl);
|
||||
|
||||
if ( mysql_errno(conn) != 0 )
|
||||
{
|
||||
Test->tprintf("Connections is not open as expected\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->add_result(1, "Connections is open for the user with bad host\n");
|
||||
}
|
||||
if (conn != NULL)
|
||||
{
|
||||
mysql_close(conn);
|
||||
}
|
||||
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "DROP USER 'user_long_host11'@'very_long_hostname_that_probably_caused_crashhh.com.net.org'");
|
||||
Test->close_maxscale_connections();
|
||||
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
202
maxscale-system-test/bug654.cpp
Normal file
202
maxscale-system-test/bug654.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
/**
|
||||
* @file bug654.cpp regression case for bug654 abd 698 ("maxadm: show dbusers <two-part service name without quotation> causes SEGFAULT", "Using invalid parameter in many maxadmin commands causes MaxScale to fail")
|
||||
*
|
||||
* - execute maxadmin command show dbusers RW Split Router and show dbusers "RW Split Router"
|
||||
* . execute different maxadmin commands with wrong parameters
|
||||
* - check MaxScale is alive
|
||||
*/
|
||||
|
||||
/*
|
||||
Vilho Raatikka 2014-12-16 13:54:36 UTC
|
||||
MaxScale> show services
|
||||
Service 0x1af7eb0
|
||||
Service: RW Split Router
|
||||
Router: readwritesplit (0x7fffdf501440)
|
||||
Number of router sessions: 0
|
||||
Current no. of router sessions: 0
|
||||
Number of queries forwarded: 0
|
||||
Number of queries forwarded to master: 0
|
||||
Number of queries forwarded to slave: 0
|
||||
Number of queries forwarded to all: 0
|
||||
Started: Tue Dec 16 15:51:54 2014
|
||||
Root user access: Disabled
|
||||
Filter chain: duplicate
|
||||
Backend databases
|
||||
127.0.0.1:3003 Protocol: MySQLBackend
|
||||
127.0.0.1:3002 Protocol: MySQLBackend
|
||||
127.0.0.1:3001 Protocol: MySQLBackend
|
||||
127.0.0.1:3000 Protocol: MySQLBackend
|
||||
Users data: 0x1aea000
|
||||
Total connections: 1
|
||||
Currently connected: 1
|
||||
|
||||
...
|
||||
|
||||
MaxScale> show dbusers RW Split Router
|
||||
|
||||
(gdb) bt
|
||||
#0 0x00007fffdfb4950a in execute_cmd (cli=0x7fffc0000c70) at /home/raatikka/src/git/MaxScale/server/modules/routing/debugcmd.c:805
|
||||
#1 0x00007fffdfb48ef8 in execute (instance=0x1b0f7b0, router_session=0x7fffc0000c70, queue=0x0) at /home/raatikka/src/git/MaxScale/server/modules/routing/cli.c:279
|
||||
#2 0x00007ffff46ae934 in maxscaled_read_event (dcb=0x7fffc00009c0) at /home/raatikka/src/git/MaxScale/server/modules/protocol/maxscaled.c:177
|
||||
#3 0x000000000058b145 in process_pollq (thread_id=2) at /home/raatikka/src/git/MaxScale/server/core/poll.c:858
|
||||
#4 0x000000000058a7df in poll_waitevents (arg=0x2) at /home/raatikka/src/git/MaxScale/server/core/poll.c:608
|
||||
#5 0x00007ffff7527e0f in start_thread () from /lib64/libpthread.so.0
|
||||
#6 0x00007ffff5e0e0dd in clone () from /lib64/libc.so.6
|
||||
(gdb)
|
||||
Comment 1 Vilho Raatikka 2014-12-16 13:58:37 UTC
|
||||
805 for (i = 0; args[i] && *args[i]; i++)
|
||||
|
||||
Off-by-one if there are more arguments than expected.
|
||||
Comment 2 Vilho Raatikka 2014-12-23 16:11:12 UTC
|
||||
NULL-terminated argument list in case where there are given more arguments than expected.
|
||||
*/
|
||||
|
||||
|
||||
#include "testconnections.h"
|
||||
#include "maxadmin_operations.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
Test->set_timeout(30);
|
||||
char result[1024];
|
||||
|
||||
Test->get_maxadmin_param((char *) "show dbusers RW Split Router", (char *) "Incorrect number of arguments:",
|
||||
result);
|
||||
Test->tprintf("result %s\n", result);
|
||||
|
||||
if (strstr(result, "show dbusers expects 1 argument") == NULL)
|
||||
{
|
||||
Test->add_result(1, "there is NO \"show dbusers expects 1 argument\" message");
|
||||
}
|
||||
Test->set_timeout(30);
|
||||
Test->get_maxadmin_param((char *) "show dbusers \"RW Split Router\"", (char *) "User names:", result);
|
||||
Test->tprintf("result %s\n", result);
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "reload dbusers 0x232fed0");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "reload dbusers Хрен");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "reload dbusers Хрен моржовый");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "Хрен моржовый");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "khren morzhovyj");
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show Хрен");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show Хрен моржовый");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show khren morzhovyj");
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show dcb Хрен");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show dcb Хрен моржовый");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show dcb khren morzhovyj");
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show server Хрен");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show server Хрен моржовый");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show server khren morzhovyj");
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show service Хрен");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show service Хрен моржовый");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show service khren morzhovyj");
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "show service khren morzhovyj");
|
||||
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "list listeners");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "restart monitor");
|
||||
Test->set_timeout(30);
|
||||
Test->execute_maxadmin_command((char *) "restart service");
|
||||
|
||||
if (!Test->smoke)
|
||||
{
|
||||
int N = 28;
|
||||
const char * cmd[N];
|
||||
|
||||
int Ng = 6;
|
||||
const char * garbage[Ng];
|
||||
|
||||
garbage[0] = "qwerty";
|
||||
garbage[1] = "khren morzhovyj";
|
||||
garbage[2] = "Хрен";
|
||||
garbage[3] = "Хрен моржовый";
|
||||
garbage[4] =
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
garbage[5] =
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Хрен моржовый Хрен моржовый ";
|
||||
|
||||
cmd[0] = "enable disable heartbeat ";
|
||||
cmd[1] = "disable heartbeat ";
|
||||
cmd[2] = "reload dbusers ";
|
||||
|
||||
cmd[3] = "set server server1 master ";
|
||||
|
||||
cmd[4] = "set pollsleep ";
|
||||
cmd[5] = "set nbpolls ";
|
||||
|
||||
cmd[6] = "show dcb ";
|
||||
cmd[7] = "show eventq ";
|
||||
cmd[8] = "show eventstats ";
|
||||
cmd[9] = "show filter ";
|
||||
cmd[10] = "show monitor ";
|
||||
cmd[11] = "show server ";
|
||||
cmd[12] = "show service ";
|
||||
cmd[13] = "show session ";
|
||||
|
||||
cmd[14] = "show filters ";
|
||||
cmd[15] = "show modules ";
|
||||
cmd[16] = "show monitors ";
|
||||
cmd[17] = "show servers ";
|
||||
cmd[18] = "show services ";
|
||||
cmd[19] = "show sessions ";
|
||||
cmd[20] = "show tasks ";
|
||||
cmd[21] = "show threads ";
|
||||
cmd[22] = "show users ";
|
||||
|
||||
cmd[23] = "shutdown monitor ";
|
||||
cmd[24] = "shutdown service ";
|
||||
|
||||
cmd[25] = "shutdown maxscale ";
|
||||
|
||||
cmd[26] = "enable root ";
|
||||
cmd[27] = "disable root ";
|
||||
|
||||
char str1[4096];
|
||||
int i1, i2;
|
||||
|
||||
for (i1 = 0; i1 < N; i1++)
|
||||
{
|
||||
for (i2 = 0; i2 < Ng; i2++)
|
||||
{
|
||||
Test->set_timeout(30);
|
||||
sprintf(str1, "%s %s", cmd[i1], garbage[i2]);
|
||||
Test->tprintf("Trying '%s'\n", str1);
|
||||
Test->execute_maxadmin_command(str1);
|
||||
|
||||
sprintf(str1, "%s %s%s%s%s %s ", cmd[i1], garbage[i2], garbage[i2], garbage[i2], garbage[i2], garbage[i2]);
|
||||
Test->tprintf("Trying '%s'\n", str1);
|
||||
Test->execute_maxadmin_command(str1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
delete Test;
|
||||
return rval;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user