 ee069ac45c
			
		
	
	ee069ac45c
	
	
	
		
			
			The sanity check replaces several old regression tests and provides a
quick test for checking mainly the readwritesplit routing behavior. It
also checks some of the connection counts and runs queries that once
caused a crash.
The set of tests that the sanity check obsoletes is:
    bug422
    bug469
    bug448
    bug507
    bug509
    bug634
    bug694
    bug669
    bug711
    mxs127
    mxs47
    mxs682_cyrillic
    mxs957
    mxs1786_statistics
    rwsplit_read_only_trx
		
	
		
			
				
	
	
		
			132 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /**
 | |
|  * Sanity check for basic functionality
 | |
|  *
 | |
|  * Combines several old regression tests into one quick test.
 | |
|  */
 | |
| 
 | |
| #include "testconnections.h"
 | |
| 
 | |
| 
 | |
| void test_rwsplit(TestConnections& test)
 | |
| {
 | |
|     test.set_timeout(300);
 | |
|     test.repl->connect();
 | |
|     std::string master_id = test.repl->get_server_id_str(0);
 | |
|     test.repl->disconnect();
 | |
| 
 | |
|     auto c = test.maxscales->rwsplit();
 | |
|     test.expect(c.connect(), "Connection to readwritesplit should succeed");
 | |
| 
 | |
|     // Transactions to master
 | |
|     c.query("START TRANSACTION");
 | |
|     test.expect(c.field("SELECT @@server_id") == master_id,
 | |
|                 "START TRANSACTION should go to the master");
 | |
|     c.query("COMMIT");
 | |
| 
 | |
|     // Read-only transactions to slave
 | |
|     c.query("START TRANSACTION READ ONLY");
 | |
|     test.expect(c.field("SELECT @@server_id") != master_id,
 | |
|                 "START TRANSACTION READ ONLY should go to a slave");
 | |
|     c.query("COMMIT");
 | |
| 
 | |
|     // @@last_insert_id routed to master
 | |
|     test.expect(c.field("SELECT @@server_id, @@last_insert_id") == master_id,
 | |
|                 "@@last_insert_id should go to the master");
 | |
|     test.expect(c.field("SELECT last_insert_id(), @@server_id", 1) == master_id,
 | |
|                 "@@last_insert_id should go to the master");
 | |
| 
 | |
|     // Replication related queries
 | |
|     test.expect(!c.row("SHOW SLAVE STATUS").empty(),
 | |
|                 "SHOW SLAVE STATUS should go to a slave");
 | |
| 
 | |
|     // User variable modification in SELECT
 | |
|     test.expect(!c.query("SELECT @a:=@a+1 as a, user FROM mysql"),
 | |
|                 "Query with variable modification should fail");
 | |
| 
 | |
|     // Repeated session commands
 | |
|     for (int i = 0; i < 10000; i++)
 | |
|     {
 | |
|         test.expect(c.query("set @test=" + std::to_string(i)), "SET should work: %s", c.error());
 | |
|     }
 | |
| 
 | |
|     // Large result sets
 | |
|     for (int i = 1; i < 5000; i += 7)
 | |
|     {
 | |
|         c.query("SELECT REPEAT('a'," + std::to_string(i) + ")");
 | |
|     }
 | |
| 
 | |
|     // Non ASCII characters
 | |
|     c.query("CREATE OR REPLACE TABLE test.t1 AS SELECT 'Кот'");
 | |
|     c.query("BEGIN");
 | |
|     c.check("SELECT * FROM test.t1", "Кот");
 | |
|     c.query("COMMIT");
 | |
|     c.query("DROP TABLE test.t1");
 | |
| 
 | |
|     // Temporary tables
 | |
|     for (auto a : {
 | |
|         "USE test",
 | |
|         "CREATE OR REPLACE TABLE t1(`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY)",
 | |
|         "CREATE OR REPLACE TABLE t2(`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY)",
 | |
|         "CREATE TEMPORARY TABLE temp1(`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY)",
 | |
|         "INSERT INTO temp1 values (1), (2), (3)",
 | |
|         "INSERT INTO t1 values (1), (2), (3)",
 | |
|         "INSERT INTO t2 values (1), (2), (3)",
 | |
|         "CREATE TEMPORARY TABLE temp2 SELECT DISTINCT p.id FROM temp1 p JOIN t1 t "
 | |
|         "    ON (t.id = p.id) LEFT JOIN t2 ON (t.id = t2.id) WHERE p.id IS NOT NULL "
 | |
|         "    AND @@server_id IS NOT NULL",
 | |
|         "SELECT * FROM temp2",
 | |
|         "DROP TABLE t1",
 | |
|         "DROP TABLE t2"
 | |
|     })
 | |
|     {
 | |
|         test.expect(c.query(a), "Temp table query failed");
 | |
|     }
 | |
| 
 | |
|     //  Temporary and real table overlap
 | |
|     c.query("CREATE OR REPLACE TABLE test.t1 AS SELECT 1 AS id");
 | |
|     c.query("CREATE TEMPORARY TABLE test.t1 AS SELECT 2 AS id");
 | |
|     c.check("SELECT id FROM test.t1", "2");
 | |
|     c.query("DROP TABLE test.t1");
 | |
|     c.query("DROP TABLE test.t1");
 | |
| 
 | |
|     // COM_STATISTICS
 | |
|     test.maxscales->connect();
 | |
|     for (int i = 0; i < 10; i++)
 | |
|     {
 | |
|         mysql_stat(test.maxscales->conn_rwsplit[0]);
 | |
|         test.try_query(test.maxscales->conn_rwsplit[0], "SELECT 1");
 | |
|     }
 | |
|     test.maxscales->disconnect();
 | |
| }
 | |
| 
 | |
| int main(int argc, char** argv)
 | |
| {
 | |
|     TestConnections test(argc, argv);
 | |
| 
 | |
|     auto connections = [&]() {
 | |
|             return test.maxctrl("api get servers/server1 data.attributes.statistics.connections").second;
 | |
|         };
 | |
| 
 | |
|     test.expect(connections()[0] == '0', "The master should have no connections");
 | |
|     test.maxscales->connect();
 | |
|     test.expect(connections()[0] == '2', "The master should have two connections");
 | |
|     test.maxscales->disconnect();
 | |
|     test.expect(connections()[0] == '0', "The master should have no connections");
 | |
| 
 | |
|     test.maxscales->connect();
 | |
|     for (auto a : {"show status", "show variables", "show global status"})
 | |
|     {
 | |
|         for (int i = 0; i < 10; i++)
 | |
|         {
 | |
|             test.try_query(test.maxscales->conn_rwsplit[0], "%s", a);
 | |
|             test.try_query(test.maxscales->conn_master[0], "%s", a);
 | |
|         }
 | |
|     }
 | |
|     test.maxscales->disconnect();
 | |
| 
 | |
|     // Readwritesplit sanity checks
 | |
|     test_rwsplit(test);
 | |
| 
 | |
|     return test.global_result;
 | |
| }
 |