Extend text protocol PS test
The test now checks that text protocol prepared statements are load balanced just like normal queries.
This commit is contained in:
@ -11,48 +11,89 @@
|
|||||||
* - check if Maxscale is alive
|
* - check if Maxscale is alive
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include "testconnections.h"
|
#include "testconnections.h"
|
||||||
#include "sql_t1.h"
|
#include "sql_t1.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
void test_basic(TestConnections& test)
|
||||||
{
|
{
|
||||||
TestConnections * Test = new TestConnections(argc, argv);
|
test.set_timeout(60);
|
||||||
Test->set_timeout(60);
|
|
||||||
int N = 4;
|
int N = 4;
|
||||||
|
|
||||||
Test->repl->connect();
|
test.repl->connect();
|
||||||
if (Test->connect_maxscale() != 0 )
|
test.connect_maxscale();
|
||||||
{
|
|
||||||
printf("Error connecting to MaxScale\n");
|
|
||||||
delete Test;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
create_t1(Test->conn_rwsplit);
|
create_t1(test.conn_rwsplit);
|
||||||
insert_into_t1(Test->conn_rwsplit, N);
|
insert_into_t1(test.conn_rwsplit, N);
|
||||||
|
|
||||||
Test->set_timeout(20);
|
test.set_timeout(20);
|
||||||
Test->try_query(Test->conn_rwsplit, (char *) "PREPARE stmt FROM 'SELECT * FROM t1 WHERE fl=@x;';");
|
test.try_query(test.conn_rwsplit, "PREPARE stmt FROM 'SELECT * FROM t1 WHERE fl=@x;';");
|
||||||
Test->try_query(Test->conn_rwsplit, (char *) "SET @x = 3;");
|
test.try_query(test.conn_rwsplit, "SET @x = 3;");
|
||||||
Test->try_query(Test->conn_rwsplit, (char *) "EXECUTE stmt");
|
test.try_query(test.conn_rwsplit, "EXECUTE stmt");
|
||||||
Test->try_query(Test->conn_rwsplit, (char *) "SET @x = 4;");
|
test.try_query(test.conn_rwsplit, "SET @x = 4;");
|
||||||
Test->try_query(Test->conn_rwsplit, (char *) "EXECUTE stmt");
|
test.try_query(test.conn_rwsplit, "EXECUTE stmt");
|
||||||
|
|
||||||
Test->check_maxscale_alive();
|
test.check_maxscale_alive();
|
||||||
int rval = Test->global_result;
|
test.stop_timeout();
|
||||||
delete Test;
|
|
||||||
return rval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_routing(TestConnections& test)
|
||||||
|
{
|
||||||
|
test.set_timeout(60);
|
||||||
|
test.repl->connect();
|
||||||
|
int server_id = test.repl->get_server_id(0);
|
||||||
|
test.connect_maxscale();
|
||||||
|
|
||||||
/*
|
// Test that reads are routed to slaves
|
||||||
Hi Timofey, I can't imagine repeatable way to run in to the situation where session command replies would arrive in different order, at least without additional instrumentation. You can, however, increase the probability for it to occur by setting up master and multiple slaves, the more the better.
|
char buf[1024] = "-1";
|
||||||
|
test.try_query(test.conn_rwsplit, "PREPARE ps1 FROM 'SELECT @@server_id'");
|
||||||
|
test.add_result(find_field(test.conn_rwsplit, "EXECUTE ps1", "@@server_id", buf),
|
||||||
|
"Execute should succeed");
|
||||||
|
int res = atoi(buf);
|
||||||
|
test.add_result(res == server_id, "Query should be routed to a slave (got %d, master is %d)", res, server_id);
|
||||||
|
|
||||||
Then start to prepare statements which return much data. The length of response packet depends on number of columns so good query would be something that produces lots of columns, like select a.user, b.user, c.user, ... z.user from mysql.user a, mysql.user b, mysql.user c, ... mysql.user z
|
|
||||||
|
|
||||||
I'm not sure that it will happen but it is possible. You can also try to make it happen by decreasing the size of network packet because the smaller that is the more likely it is that responses are split into multiple packets - which can then becomen interleaved with packets from different slaves.
|
// Test reads inside transactions are routed to master
|
||||||
*/
|
test.try_query(test.conn_rwsplit, "BEGIN");
|
||||||
|
test.add_result(find_field(test.conn_rwsplit, "EXECUTE ps1", "@@server_id", buf),
|
||||||
|
"Execute should succeed");
|
||||||
|
res = atoi(buf);
|
||||||
|
test.add_result(res != server_id, "Query should be routed to master inside a transaction (got %d, master is %d)", res, server_id);
|
||||||
|
test.try_query(test.conn_rwsplit, "COMMIT");
|
||||||
|
|
||||||
|
// Test reads inside read-only transactions are routed slaves
|
||||||
|
test.try_query(test.conn_rwsplit, "START TRANSACTION READ ONLY");
|
||||||
|
test.add_result(find_field(test.conn_rwsplit, "EXECUTE ps1", "@@server_id", buf),
|
||||||
|
"Execute should succeed");
|
||||||
|
res = atoi(buf);
|
||||||
|
test.add_result(res == server_id, "Query should be routed to a slave inside a read-only transaction (got %d, master is %d)", res, server_id);
|
||||||
|
test.try_query(test.conn_rwsplit, "COMMIT");
|
||||||
|
|
||||||
|
// Test prepared statements that modify data
|
||||||
|
test.try_query(test.conn_rwsplit, "CREATE OR REPLACE TABLE test.t1 (id INT)");
|
||||||
|
test.try_query(test.conn_rwsplit, "PREPARE ps2 FROM 'INSERT INTO test.t1 VALUES (?)'");
|
||||||
|
test.try_query(test.conn_rwsplit, "SET @a = 1");
|
||||||
|
test.try_query(test.conn_rwsplit, "EXECUTE ps2 USING @a");
|
||||||
|
test.add_result(find_field(test.conn_rwsplit, "SELECT id FROM test.t1", "id", buf),
|
||||||
|
"Read should succeed");
|
||||||
|
res = atoi(buf);
|
||||||
|
test.add_result(res != server_id, "Writes should be routed to the master (got %d, master is %d)", res, server_id);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
test.check_maxscale_alive();
|
||||||
|
test.stop_timeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
TestConnections test(argc, argv);
|
||||||
|
|
||||||
|
test.tprintf("Running basic test");
|
||||||
|
test_basic(test);
|
||||||
|
|
||||||
|
test.tprintf("Running text PS routing test");
|
||||||
|
test_routing(test);
|
||||||
|
|
||||||
|
return test.global_result;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user