150 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2016 MariaDB Corporation Ab
 | |
|  *
 | |
|  * Use of this software is governed by the Business Source License included
 | |
|  * in the LICENSE.TXT file and at www.mariadb.com/bsl11.
 | |
|  *
 | |
|  * Change Date: 2025-01-18
 | |
|  *
 | |
|  * On the date above, in accordance with the Business Source License, use
 | |
|  * of this software will be governed by version 2 or later of the General
 | |
|  * Public License.
 | |
|  */
 | |
| 
 | |
| #include <iostream>
 | |
| #include <map>
 | |
| #include <vector>
 | |
| #include <maxbase/assert.h>
 | |
| #include <maxtest/testconnections.hh>
 | |
| 
 | |
| using namespace std;
 | |
| 
 | |
| namespace
 | |
| {
 | |
| 
 | |
| void init(TestConnections& test, Connection& c)
 | |
| {
 | |
|     test.expect(c.query("DROP TABLE IF EXISTS sq"), "Could not drop table.");
 | |
|     test.expect(c.query("CREATE TABLE sq (id INT, value INT)"), "Could not create table.");
 | |
|     sleep(2);
 | |
| }
 | |
| 
 | |
| void finish(TestConnections& test, Connection& c)
 | |
| {
 | |
|     test.expect(c.query("DROP TABLE IF EXISTS sq"), "Could not drop table.");
 | |
| }
 | |
| 
 | |
| const size_t N_THREADS = 10;
 | |
| const size_t N_INSERTS = 100;
 | |
| const size_t N_SELECTS = 10;
 | |
| 
 | |
| void thread_stress(TestConnections* pTest, int id)
 | |
| {
 | |
|     string greeting("Hello from thread ");
 | |
|     greeting += std::to_string(id);
 | |
|     greeting += "\n";
 | |
| 
 | |
|     cout << greeting << flush;
 | |
| 
 | |
|     Connection c = pTest->maxscales->rwsplit();
 | |
| 
 | |
|     c.connect();
 | |
| 
 | |
|     string preamble("INSERT INTO sq VALUES (");
 | |
|     preamble += std::to_string(id);
 | |
|     preamble += ", ";
 | |
| 
 | |
|     for (size_t i = 0; i < N_INSERTS; ++i)
 | |
|     {
 | |
|         string query = preamble + std::to_string(i) + ")";
 | |
| 
 | |
|         c.query(query);
 | |
| 
 | |
|         for (size_t i = 0; i < N_SELECTS; ++i)
 | |
|         {
 | |
|             c.query("SELECT * FROM sq");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     string goodbye("Goodbye from thread ");
 | |
|     goodbye += std::to_string(id);
 | |
|     goodbye += "\n";
 | |
| 
 | |
|     cout << goodbye << flush;
 | |
| }
 | |
| 
 | |
| void test_stress(TestConnections& test)
 | |
| {
 | |
|     vector<thread> threads;
 | |
| 
 | |
|     for (size_t i = 0; i < N_THREADS; ++i)
 | |
|     {
 | |
|         thread t(thread_stress, &test, i);
 | |
| 
 | |
|         threads.emplace_back(std::move(t));
 | |
|     }
 | |
| 
 | |
|     for (size_t i = 0; i < threads.size(); ++i)
 | |
|     {
 | |
|         threads[i].join();
 | |
|     }
 | |
| 
 | |
|     Connection c = test.maxscales->rwsplit();
 | |
|     c.connect();
 | |
| 
 | |
|     test.repl->sync_slaves();
 | |
| 
 | |
|     Result rows = c.rows("SELECT * FROM sq");
 | |
|     test.expect(rows.size() == N_THREADS * N_INSERTS,
 | |
|                 "Expected %lu inserts in total, but found %lu.", N_THREADS * N_INSERTS, rows.size());
 | |
| 
 | |
|     map<string, vector<string>> found_results;
 | |
| 
 | |
|     for (const auto& row : rows)
 | |
|     {
 | |
|         mxb_assert(row.size() == 2);
 | |
| 
 | |
|         string tid { row[0] };
 | |
|         string f { row[1] };
 | |
| 
 | |
|         found_results[tid].push_back(f);
 | |
|     }
 | |
| 
 | |
|     test.expect(found_results.size() == N_THREADS,
 | |
|                 "Expected results from %lu threads, but found %lu.", N_THREADS, found_results.size());
 | |
| 
 | |
|     for (const auto& kv : found_results)
 | |
|     {
 | |
|         const string& tid { kv.first };
 | |
|         const vector<string>& fields { kv.second };
 | |
| 
 | |
|         test.expect(fields.size() == N_INSERTS,
 | |
|                     "Expected %lu inserts for thread %s, but found only %lu.",
 | |
|                     N_INSERTS, tid.c_str(), fields.size());
 | |
|     }
 | |
| }
 | |
| 
 | |
| void run_tests(TestConnections& test)
 | |
| {
 | |
|     test_stress(test);
 | |
| }
 | |
| 
 | |
| }
 | |
| 
 | |
| int main(int argc, char* argv[])
 | |
| {
 | |
|     TestConnections test(argc, argv);
 | |
| 
 | |
|     Connection c = test.maxscales->rwsplit();
 | |
| 
 | |
|     test.expect(c.connect(), "Could not connect to MaxScale.");
 | |
| 
 | |
|     init(test, c);
 | |
| 
 | |
|     run_tests(test);
 | |
| 
 | |
|     finish(test, c);
 | |
| 
 | |
|     return test.global_result;
 | |
| }
 | 
