Skip to content

Commit

Permalink
test: fix flakiness
Browse files Browse the repository at this point in the history
Patch makes testcases more reliable with wait_cond() instead of sleep().
wait_cond() and wait_cond_finish() have been imported from test-run [1].

1. https://github.com/tarantool/test-run/blob/master/test_run.lua

Closes #76
  • Loading branch information
ligurio committed Oct 13, 2021
1 parent 2c372ce commit fbe02a7
Showing 1 changed file with 85 additions and 16 deletions.
101 changes: 85 additions & 16 deletions test.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env tarantool

local clock = require('clock')
local fun = require('fun')
local log = require('log')
local tap = require('tap')
Expand All @@ -16,6 +17,54 @@ strict.on()
-- local support functions --
-- ========================================================================= --

-- Strip pcall()'s true or re-raise catched error.
local function wait_cond_finish(res)
-- res: 1: pcall_ok
-- 2: pcall_error / cond_function_res_1
-- 3: cond_function_res_2
-- 4: cond_function_res_3
-- ...
--
-- cond_function_res_1 is the 'ok' / 'not ok' indicator for
-- wait_cond(). But we return it: this is deliberate choice.
-- This way a user may understand, whether we finally hit
-- timeout or not.
if not res[1] then
error(res[2])
end
return select(2, unpack(res, 1, table.maxn(res)))
end

-- Block until the condition function returns a positive value
-- (anything except `nil` and `false`) or until the timeout
-- exceeds. Return the result of the last invocation of the
-- condition function (it is `false` or `nil` in case of exiting
-- by the timeout).
--
-- If the condition function raises a Lua error, wait_cond()
-- continues retrying. If the latest attempt raises an error (and
-- we hit a timeout), the error will be re-raised.
local function wait_cond(cond, timeout, delay)
assert(type(cond) == 'function')

local timeout = timeout or 60
local delay = delay or 0.001

local start_time = clock.monotonic()
local res = {pcall(cond)}

while not res[1] or not res[2] do
local work_time = clock.monotonic() - start_time
if work_time > timeout then
return wait_cond_finish(res)
end
fiber.sleep(delay)
res = {pcall(cond)}
end

return wait_cond_finish(res)
end

-- get field
local function get_field(tuple, field_no)
if tuple == nil then
Expand Down Expand Up @@ -419,11 +468,14 @@ test:test("multiple expires test", function(test)
local tuples_count = 10
local time = fiber.time()
local space_name = 'exp_test'
local expire_delta = 2
local expire_delta = 0.5

for i = 1, tuples_count do
box.space[space_name]:delete{i}
box.space[space_name]:insert{i, get_email(i), time + expire_delta}
if i <= tuples_count / 2 then
time = time + expire_delta
end
box.space[space_name]:insert{i, get_email(i), time}
end

expirationd.start(
Expand All @@ -441,15 +493,26 @@ test:test("multiple expires test", function(test)
}
)
-- test first expire part
fiber.sleep(1 + expire_delta)
local task = expirationd.task("test")
local cnt = task.expired_tuples_count
test:ok(cnt < tuples_count and cnt > 0, 'First part expires done')
local res = wait_cond(
function()
local task = expirationd.task("test")
local cnt = task.expired_tuples_count
return cnt < tuples_count and cnt > 0
end,
2 + expire_delta
)
test:ok(res, true, 'First part expires done')

-- test second expire part
fiber.sleep(1)
test:is(expirationd.task("test").expired_tuples_count,
tuples_count, 'Multiple expires done')
res = wait_cond(
function()
local task = expirationd.task("test")
local cnt = task.expired_tuples_count
return cnt == tuples_count
end,
4
)
test:ok(res, true, 'Multiple expires done')
expirationd.kill("test")
end)

Expand All @@ -459,8 +522,9 @@ test:test("default drop function test", function(test)
local space_name = 'drop_test'
local space = box.space[space_name]
for i = 1, tuples_count do
space:insert{i, 'test_data', fiber.time() + 2}
space:insert{i, 'test_data', fiber.time()}
end
test:is(space:count{}, tuples_count, 'tuples are in space')

expirationd.start(
"test",
Expand All @@ -476,9 +540,14 @@ test:test("default drop function test", function(test)
}
)

test:is(space:count{}, tuples_count, 'tuples are in space')
fiber.sleep(3)
test:is(space:count{}, 0, 'all tuples are expired with default function')
local task = expirationd.task("test")
local res = wait_cond(
function()
return space:count{} == 0
end,
2
)
test:is(res, true, 'all tuples are expired with default function')
expirationd.kill("test")
end)

Expand Down Expand Up @@ -658,10 +727,10 @@ test:test('delays and scan callbacks test', function(test)
if first_iteration_done then
cond:signal()
else
-- Check the iteration delay with an accuracy
-- of 0.1 seconds.
-- Check the accuracy of iteration delay,
-- it should be not beyond 1 second.
test:ok(math.abs(complete_time - start_time -
iteration_delay) < 0.1, 'test iteration delay')
iteration_delay) < 1, 'test iteration delay')
first_iteration_done = true
end
end
Expand Down

0 comments on commit fbe02a7

Please sign in to comment.