tarantool/mysql

test: fix tests on broken connections

Totktonada opened this issue · 0 comments

Just observed that my test cases for broken connections actually act on healthy connections. I mean the following cases:

mysql/test/mysql.test.lua

Lines 96 to 114 in 2d22046

-- Case: the same, but for broken connection.
test:test('loss a broken connection', function(test)
test:plan(2)
assert(pool.size >= 1, 'test case precondition fails')
-- Get a connection, make a bad query and loss the
-- connection.
local conn = pool:get()
local ok = pcall(conn.execute, conn, 'bad query')
test:ok(not ok, 'a query actually fails')
conn = nil -- luacheck: no unused
-- Collect the lost connection.
collectgarbage('collect')
-- Verify that a pool is aware of collected connections.
test:is(pool.queue:count(), pool.size, 'all connections are put back')
end)

mysql/test/mysql.test.lua

Lines 312 to 354 in 2d22046

-- Case: get a connection, broke it and put back.
test:test('get, broke and put a connection', function(test)
test:plan(2)
assert(pool.size >= 1, 'test case precondition fails')
-- Get a connection and make a bad query.
local conn = pool:get()
local ok = pcall(conn.execute, conn, 'bad query')
test:ok(not ok, 'a query actually fails')
-- Put the connection back and verify that the pool is full.
pool:put(conn)
test:ok(pool.queue:is_full(), 'a broken connection was given back')
end)
-- Case: the same, but loss and collect a connection after
-- put.
test:test('get, broke, put and loss a connection', function(test)
test:plan(3)
assert(pool.size >= 1, 'test case precondition fails')
-- Get a connection and make a bad query.
local conn = pool:get()
local ok = pcall(conn.execute, conn, 'bad query')
test:ok(not ok, 'a query actually fails')
-- Put the connection back, loss it and trigger GC.
pool:put(conn)
conn = nil -- luacheck: no unused
collectgarbage('collect')
-- Verify that the pool is full
test:ok(pool.queue:is_full(), 'a broken connection was given back')
-- Verify the pool will not be populated by a connection's
-- GC callback. Otherwise :put() will hang.
local item = pool.queue:get()
pool.queue:put(item)
test:ok(true, 'GC callback does not put back a connection that was ' ..
'put manually')
end)

My initial assumption was that any SQL error (including syntax error) will lead to marking the connection as broken, however it is not so. Only CR_SERVER_LOST or CR_SERVER_GONE_ERROR errors matter here:

mysql/mysql/driver.c

Lines 149 to 157 in 2d22046

int err = mysql_errno(raw_conn);
switch (err) {
case CR_SERVER_LOST:
case CR_SERVER_GONE_ERROR:
lua_pushnumber(L, -1);
break;
default:
lua_pushnumber(L, 1);
}

mysql/mysql/init.lua

Lines 71 to 74 in 2d22046

if status ~= 0 then
self.queue:put(status > 0)
return error(datas)
end

It seems we should find a way to broke a connection from a test. It seems that support of an error injection is needed for Debug build.