diff --git a/maxscale-system-test/CMakeLists.txt b/maxscale-system-test/CMakeLists.txt index 87d39d20b..9682608f8 100644 --- a/maxscale-system-test/CMakeLists.txt +++ b/maxscale-system-test/CMakeLists.txt @@ -1020,6 +1020,10 @@ add_test_executable(mxs1929_service_runtime.cpp mxs1929_service_runtime mxs1929_ # https://jira.mariadb.org/browse/MXS-1929 add_test_executable(mxs1929_filter_runtime.cpp mxs1929_filter_runtime mxs1929_filter_runtime LABELS REPL_BACKEND) +# MXS-1929: Create complete configuration at runtime +# https://jira.mariadb.org/browse/MXS-1929 +add_test_executable(mxs1929_start_from_scratch.cpp mxs1929_start_from_scratch mxs1929_start_from_scratch LABELS REPL_BACKEND) + # MXS-1932: Hidden files are not ignored # https://jira.mariadb.org/browse/MXS-1932 add_test_executable(mxs1932_hidden_cnf.cpp mxs1932_hidden_cnf replication LABELS REPL_BACKEND) diff --git a/maxscale-system-test/cnf/maxscale.cnf.template.mxs1929_start_from_scratch b/maxscale-system-test/cnf/maxscale.cnf.template.mxs1929_start_from_scratch new file mode 100644 index 000000000..584eabd7e --- /dev/null +++ b/maxscale-system-test/cnf/maxscale.cnf.template.mxs1929_start_from_scratch @@ -0,0 +1,12 @@ +[maxscale] +threads=###threads### + +[CLI] +type=service +router=cli + +[CLI Listener] +type=listener +service=CLI +protocol=maxscaled +socket=default diff --git a/maxscale-system-test/mxs1929_start_from_scratch.cpp b/maxscale-system-test/mxs1929_start_from_scratch.cpp new file mode 100644 index 000000000..f9a746798 --- /dev/null +++ b/maxscale-system-test/mxs1929_start_from_scratch.cpp @@ -0,0 +1,121 @@ +/** + * MXS-1929: Create a setup from an empty config and check that it can be + * repeated multiple times + */ + +#include "testconnections.h" + +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + TestConnections test(argc, argv); + std::vector threads; + std::atomic running{true}; + std::atomic conns{0}; + + auto start = std::chrono::steady_clock::now(); + + // Create some threads so that we have a constant load on the system + for (int i = 0; i < 10; i++) + { + threads.emplace_back([&, i]() + { + while (running) + { + Connection c = i % 2 == 0 ? test.maxscales->rwsplit() : test.maxscales->readconn_master(); + if (c.connect()) + { + c.query("CREATE TABLE IF NOT EXITS test.t1 (id INT)"); + c.query("INSERT INTO test.t1 VALUES (" + std::to_string(i) + ")"); + c.query("SELECT * FROM test.t1"); + c.query("DELETE FROM test.t1 WHERE id = " + std::to_string(i)); + ++conns; + } + else + { + sleep(1); + } + + } + }); + } + + // Allows the use of operator+ for concatenation + std::string create = "create "; + + std::vector commands + { + // Start by creating the servers + create + "server server1 " + test.repl->IP[0] + " 3306", + create + "server server2 " + test.repl->IP[1] + " 3306", + create + "server server3 " + test.repl->IP[2] + " 3306", + create + "server server4 " + test.repl->IP[3] + " 3306", + // A monitor for the servers + create + "monitor monitor1 mysqlmon monitor_interval=1000 user=skysql password=skysql --servers server1 server2 server3 server4", + // Services, one readwritesplit and one readconnroute + create + "service service1 readwritesplit user=skysql password=skysql --servers server1 server2 server3 server4", + create + "service service2 readconnroute user=skysql password=skysql router_options=master --servers server1 server2 server3 server4", + // Create listeners for the services + create + "listener service1 listener1 4006", + create + "listener service2 listener2 4008", + // Create the filters + create + "filter filter1 qlafilter filebase=/tmp/qla", + create + "filter filter2 regexfilter match=hello replace=world", + // Take filters into use + "alter service-filters service1 filter1", + "alter service-filters service2 filter2", + // Remove server then filters + "alter service-filters service1", + "unlink service service1 server1 server2 server3 server4", + // Do it the other way around for the second service + "unlink service service2 server1 server2 server3 server4", + "alter service-filters service2", + // Unlink the monitor from the servers + "unlink monitor monitor1 server1 server2 server3 server4", + // Start destroying things + "destroy filter filter1", + "destroy filter filter2", + "destroy listener service1 listener1", + "destroy listener service2 listener2", + // Draining the servers makes sure they aren't used + "drain server server1", + "drain server server2", + "drain server server3", + "drain server server4", + "destroy service service1", + "destroy service service2", + "destroy monitor monitor1", + "destroy server server1", + "destroy server server2", + "destroy server server3", + "destroy server server4" + }; + + for (int i = 0; i < 3; i++) + { + for (const auto& cmd : commands) + { + test.check_maxctrl(cmd); + } + + test.tprintf("Completed round %d", i + 1); + } + + running = false; + + for (auto& a : threads) + { + a.join(); + } + + auto end = std::chrono::steady_clock::now(); + + test.tprintf("A total of %d connections were created over %d seconds", conns.load(), + std::chrono::duration_cast(end - start).count()); + + return test.global_result; +}