diff --git a/maxscale-system-test/CMakeLists.txt b/maxscale-system-test/CMakeLists.txt index 64ab5396a..d86ebd863 100644 --- a/maxscale-system-test/CMakeLists.txt +++ b/maxscale-system-test/CMakeLists.txt @@ -28,7 +28,7 @@ include_directories(${CMAKE_SOURCE_DIR}/../connectors/cdc-connector/) include_directories(maxtest/include/maxtest) # Tool used to check backend state -add_test_executable_notest(check_backend.cpp check_backend check_backend LABELS CONFIG REPL_BACKEND GALERA_BACKEND TWO_MAXSCALES) +add_test_executable_notest(check_backend.cpp check_backend check_backend LABELS CONFIG REPL_BACKEND GALERA_BACKEND SECOND_MAXSCALE) # Configuration tests add_template_manual(bug359 bug359) @@ -203,7 +203,7 @@ add_test_executable(mxs2355_wrong_auth.cpp mxs2355_wrong_auth maxctrl LABELS REP ############################################ # Configures 'keepalived' on two Maxscale machines and tried failover -#add_test_executable(keepalived_masterdown.cpp keepalived_masterdown keepalived_masterdown LABELS REPL_BACKEND TWO_MAXSCALES) +#add_test_executable(keepalived_masterdown.cpp keepalived_masterdown keepalived_masterdown LABELS REPL_BACKEND SECOND_MAXSCALE) # MySQL Monitor with Multi-master configurations add_test_executable(mysqlmon_multimaster.cpp mysqlmon_multimaster mysqlmon_multimaster LABELS mysqlmon REPL_BACKEND BREAKS_REPL) @@ -851,7 +851,7 @@ add_test_executable(kerberos_setup.cpp kerberos_setup kerberos LABELS HEAVY gssa add_test_derived(kerberos_setup_ssl kerberos_setup kerberos_ssl LABELS HEAVY gssapi BACKEND_SSL REPL_BACKEND) # Configures 'keepalived' on two Maxscale machines and tried failover -#add_test_executable(keepalived.cpp keepalived keepalived LABELS REPL_BACKEND TWO_MAXSCALES) +#add_test_executable(keepalived.cpp keepalived keepalived LABELS REPL_BACKEND SECOND_MAXSCALE) # a tool to delete RDS Aurora cluster add_test_executable_notest(delete_rds.cpp delete_rds replication LABELS EXTERN_BACKEND) diff --git a/maxscale-system-test/maxtest/include/maxtest/testconnections.h b/maxscale-system-test/maxtest/include/maxtest/testconnections.h index 29ff05606..e81395f3c 100644 --- a/maxscale-system-test/maxtest/include/maxtest/testconnections.h +++ b/maxscale-system-test/maxtest/include/maxtest/testconnections.h @@ -52,6 +52,8 @@ typedef std::set StringSet; class TestConnections { public: + using StringSet = std::set; + /** * @brief TestConnections constructor: reads environmental variables, copies MaxScale.cnf for MaxScale * machine @@ -206,11 +208,6 @@ public: */ bool use_ipv6; - /** - * @brief configured_labels List of lables for which nodes are configured - */ - std::string configured_labels; - /** * @brief vm_path Path to the VM Vagrant directory */ @@ -614,7 +611,6 @@ private: void set_template_and_labels(); void set_mdbci_labels(); - bool has_label(std::string labels, std::string label); bool log_matches(int m, const char* pattern); bool too_many_maxscales() const; @@ -623,8 +619,14 @@ private: std::string m_test_name; /**< Test name */ std::string m_cnf_template_path; /**< MaxScale config file template used by test */ - std::string m_labels; /**< Test labels */ - std::string m_mdbci_labels; /**< Labels for MDBCI */ + + std::string m_test_labels_str; /**< Test labels as given in CMakeLists.txt and required by the test */ + StringSet m_test_labels; /**< Test labels parsed to a set. */ + + StringSet m_required_mdbci_labels;/**< MDBCI-labels required by test. Subset of test labels. */ + std::string m_mdbci_labels_str; /**< MDBCI-labels in string form. Used on the command line. */ + + StringSet m_configured_mdbci_labels; /**< MDBCI-labels already configured on the VM setup */ std::string m_mdbci_config_name; /**< Name of MDBCI VMs set */ std::string m_mdbci_vm_path; /**< Path to directory with MDBCI VMs descriptions */ @@ -654,6 +656,9 @@ private: /** If true tests do not revert VMs after the test even if test failed (use it for debugging) */ bool no_vm_revert {true}; + + std::string flatten_stringset(const StringSet& set); + StringSet parse_to_stringset(const std::string& source); }; /** diff --git a/maxscale-system-test/maxtest/src/CMakeLists.txt b/maxscale-system-test/maxtest/src/CMakeLists.txt index 5c3a61c18..7b2ae34e0 100644 --- a/maxscale-system-test/maxtest/src/CMakeLists.txt +++ b/maxscale-system-test/maxtest/src/CMakeLists.txt @@ -11,7 +11,6 @@ add_library(maxtest SHARED get_com_select_insert.cpp get_my_ip.cpp keepalived_func.cpp - labels_table.cpp mariadb_func.cpp mariadb_nodes.cpp maxadmin_operations.cpp diff --git a/maxscale-system-test/maxtest/src/labels_table.cpp b/maxscale-system-test/maxtest/src/labels_table.cpp deleted file mode 100644 index 9a4fda2c3..000000000 --- a/maxscale-system-test/maxtest/src/labels_table.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include "testconnections.h" - -namespace -{ -struct labels_table_t -{ - std::string test_label; - std::string mdbci_label; -}; - -const labels_table_t labels_table[] = -{ - {"REPL_BACKEND", "REPL_BACKEND"}, - {"BIG_REPL_BACKEND", "BIG_REPL_BACKEND"}, - {"GALERA_BACKEND", "GALERA_BACKEND"}, - {"TWO_MAXSCALES", "SECOND_MAXSCALE"}, - {"COLUMNSTORE_BACKEND", "COLUMNSTORE_BACKEND"}, - {"CLUSTRIX_BACKEND", "CLUSTRIX_BACKEND"}, -}; -} -/** - * Generate MDBCI labels required by test. Every test has a number of labels defined in CMakeLists.txt. - * Some of these labels define which nodes (virtual machines) are needed for this particular test. - * This function generates the equivalent labels for the 'mdbci up'-command. - */ -void TestConnections::set_mdbci_labels() -{ - std::string mdbci_labels_str("MAXSCALE"); - for (size_t i = 0; i < sizeof(labels_table) / sizeof(labels_table_t); i++) - { - std::string test_label = ";" + labels_table[i].test_label; - if (m_labels.find(test_label) != std::string::npos) - { - mdbci_labels_str += "," + labels_table[i].mdbci_label; - } - } - - if (TestConnections::verbose) - { - printf("mdbci labels %s\n", mdbci_labels_str.c_str()); - } - m_mdbci_labels = mdbci_labels_str; -} - -/** - * Check if label is part of current test labels. - * - * @param labels String with all labels of the test - * @param label Labels to find - * @return true if label present - */ -bool TestConnections::has_label(std::string labels, std::string label) -{ - std::string labels_ext = ";" + labels + ";"; - std::string label_ext = std::string(";") + label + std::string(";"); - return (labels_ext.find(label_ext, 0) != std::string::npos); -} diff --git a/maxscale-system-test/maxtest/src/testconnections.cpp b/maxscale-system-test/maxtest/src/testconnections.cpp index 7b21ad49e..720423bfc 100644 --- a/maxscale-system-test/maxtest/src/testconnections.cpp +++ b/maxscale-system-test/maxtest/src/testconnections.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include "mariadb_func.h" #include "maxadmin_operations.h" @@ -28,6 +29,20 @@ using std::cout; using std::endl; using std::string; +namespace +{ +// These must match the labels recognized by MDBCI. +const string label_repl_be = "REPL_BACKEND"; +const string label_galera_be = "GALERA_BACKEND"; +const string label_big_be = "BIG_REPL_BACKEND"; +const string label_2nd_mxs = "SECOND_MAXSCALE"; +const string label_cs_be = "COLUMNSTORE_BACKEND"; +const string label_clx_be = "CLUSTRIX_BACKEND"; + +const StringSet recognized_mdbci_labels = +{label_repl_be, label_big_be, label_galera_be, label_2nd_mxs, label_cs_be, label_clx_be}; +} + namespace maxscale { @@ -275,36 +290,36 @@ TestConnections::TestConnections(int argc, char* argv[]) m_test_name = (optind < argc) ? argv[optind] : basename(argv[0]); set_template_and_labels(); tprintf("Test: '%s', config template: '%s', labels: '%s'", - m_test_name.c_str(), m_cnf_template_path.c_str(), m_labels.c_str()); + m_test_name.c_str(), m_cnf_template_path.c_str(), m_test_labels_str.c_str()); set_mdbci_labels(); - if (has_label(m_labels, "BACKEND_SSL")) + if (m_test_labels.count("BACKEND_SSL") > 0) { backend_ssl = true; tprintf("Test has BACKEND_SSL label"); } - std::string delimiter = std::string (","); - size_t pos_start = 0, pos_end, delim_len = delimiter.length(); - std::string label; - std::string mdbci_labels_c = m_mdbci_labels + delimiter; + StringSet missing_mdbci_labels; + std::set_difference(m_required_mdbci_labels.begin(), m_required_mdbci_labels.end(), + m_configured_mdbci_labels.begin(), m_configured_mdbci_labels.end(), + std::inserter(missing_mdbci_labels, missing_mdbci_labels.begin())); bool mdbci_call_needed = false; - - while ((pos_end = mdbci_labels_c.find (delimiter, pos_start)) != std::string::npos) + if (missing_mdbci_labels.empty()) { - label = mdbci_labels_c.substr (pos_start, pos_end - pos_start); - pos_start = pos_end + delim_len; - if (configured_labels.find(label, 0) == std::string::npos) + if (verbose) { - mdbci_call_needed = true; - tprintf("Machines with label '%s' are not running, MDBCI UP call is needed", label.c_str()); - } - else if (verbose) - { - tprintf("Machines with label '%s' are running, MDBCI UP call is not needed", label.c_str()); + tprintf("Machines with all required labels '%s' are running, MDBCI UP call is not needed", + m_mdbci_labels_str.c_str()); } } + else + { + string missing_labels_str = flatten_stringset(missing_mdbci_labels); + tprintf("Machines with labels '%s' are not running, MDBCI UP call is needed", + missing_labels_str.c_str()); + mdbci_call_needed = true; + } if (mdbci_call_needed) { @@ -314,7 +329,7 @@ TestConnections::TestConnections(int argc, char* argv[]) } } - if (m_mdbci_labels.find(std::string("REPL_BACKEND")) == std::string::npos) + if (m_required_mdbci_labels.count(label_repl_be) == 0) { no_repl = true; if (verbose) @@ -323,7 +338,7 @@ TestConnections::TestConnections(int argc, char* argv[]) } } - if (m_mdbci_labels.find(std::string("GALERA_BACKEND")) == std::string::npos) + if (m_required_mdbci_labels.count(label_galera_be) == 0) { no_galera = true; if (verbose) @@ -332,7 +347,7 @@ TestConnections::TestConnections(int argc, char* argv[]) } } - if (m_mdbci_labels.find(std::string("CLUSTRIX_BACKEND")) == std::string::npos) + if (m_required_mdbci_labels.count(label_clx_be) == 0) { no_clustrix = true; if (verbose) @@ -673,7 +688,7 @@ void TestConnections::read_mdbci_info() nc_file.open(vm_path + "_configured_labels"); std::stringstream strStream1; strStream1 << nc_file.rdbuf(); - configured_labels = strStream1.str(); + m_configured_mdbci_labels = parse_to_stringset(strStream1.str()); nc_file.close(); } else @@ -760,19 +775,19 @@ void TestConnections::set_template_and_labels() if (found) { m_cnf_template_path = found->config_template; - m_labels = found->labels; + m_test_labels_str = found->labels; } else { - printf("Failed to find configuration template for test '%s', using default template '%s'.\n", - m_test_name.c_str(), default_template); + printf("Failed to find configuration template for test '%s', using default template '%s' and " + "labels '%s'.\n", + m_test_name.c_str(), default_template, label_repl_be.c_str()); m_cnf_template_path = default_template; + m_test_labels_str = label_repl_be; } - if (m_labels.empty()) - { - m_labels = "REPL_BACKEND"; - } + // Parse the labels-string to a set. + m_test_labels = parse_to_stringset(m_test_labels_str); } void TestConnections::process_template(int m, const string& cnf_template_path, const char* dest) @@ -2227,7 +2242,7 @@ int TestConnections::call_mdbci(const char * options) if (system((std::string("mdbci up ") + m_mdbci_config_name + std::string(" --labels ") + - m_mdbci_labels + + m_mdbci_labels_str + std::string(" ") + std::string(options)).c_str() )) { @@ -2337,5 +2352,59 @@ int TestConnections::reinstall_maxscales() bool TestConnections::too_many_maxscales() const { - return maxscales->N < 2 && m_mdbci_labels.find("SECOND_MAXSCALE") != std::string::npos; + return maxscales->N < 2 && m_required_mdbci_labels.count(label_2nd_mxs) > 0; +} + +std::string TestConnections::flatten_stringset(const StringSet& set) +{ + string rval; + string sep; + for (auto& elem : set) + { + rval += sep; + rval += elem; + sep = ","; + } + return rval; +} + +StringSet TestConnections::parse_to_stringset(const string& source) +{ + string copy = source; + StringSet rval; + if (!copy.empty()) + { + char* ptr = ©[0]; + char* save_ptr = nullptr; + // mdbci uses ',' and cmake uses ';'. Add ' ' as well to ensure trimming. + const char delim[] = ",; "; + char* token = strtok_r(ptr, delim, &save_ptr); + while (token) + { + rval.insert(token); + token = strtok_r(nullptr, delim, &save_ptr); + } + } + return rval; +} + +/** + * MDBCI recognizes labels which affect backend configuration. Save those labels to a separate field. + * Also save a string version. + */ +void TestConnections::set_mdbci_labels() +{ + StringSet mdbci_labels; + mdbci_labels.insert("MAXSCALE"); + std::set_intersection(recognized_mdbci_labels.begin(), recognized_mdbci_labels.end(), + m_test_labels.begin(), m_test_labels.end(), + std::inserter(mdbci_labels, mdbci_labels.begin())); + + std::string mdbci_labels_str = flatten_stringset(mdbci_labels); + if (TestConnections::verbose) + { + printf("mdbci-labels: %s\n", mdbci_labels_str.c_str()); + } + m_required_mdbci_labels = mdbci_labels; + m_mdbci_labels_str = mdbci_labels_str; }