Skip to content

Commit ab453e3

Browse files
Totktonadakyukhin
authored andcommitted
Retry on a Lua error in test_run:wait_cond()
I think that a developer expects that wait_cond() will continue retrying on any failure: as on a negative result from the condition function, as well as when it raises a Lua error. See motivating example in the linked issue: it was not obvious that a condition function may raise an error in this case. I guess it is more or less frequent case. Fixes tarantool/tarantool-qa#128
1 parent 53389a8 commit ab453e3

File tree

1 file changed

+27
-5
lines changed

1 file changed

+27
-5
lines changed

test_run.lua

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -405,30 +405,52 @@ local function grep_log(self, node, what, bytes, opts)
405405
return found
406406
end
407407

408+
-- Strip pcall()'s true or re-raise catched error.
409+
local function wait_cond_finish(res)
410+
-- res: 1: pcall_ok
411+
-- 2: pcall_error / cond_function_res_1
412+
-- 3: cond_function_res_2
413+
-- 4: cond_function_res_3
414+
-- ...
415+
--
416+
-- cond_function_res_1 is the 'ok' / 'not ok' indicator for
417+
-- wait_cond(). But we return it: this is deliberate choice.
418+
-- This way a user may understand, whether we finally hit
419+
-- timeout or not.
420+
if not res[1] then
421+
error(res[2])
422+
end
423+
return select(2, unpack(res))
424+
end
425+
408426
-- Block until the condition function returns a positive value
409427
-- (anything except `nil` and `false`) or until the timeout
410428
-- exceeds. Return the result of the last invocation of the
411429
-- condition function (it is `false` or `nil` in case of exiting
412430
-- by the timeout).
431+
--
432+
-- If the condition function raises a Lua error, wait_cond()
433+
-- continues retrying. If the latest attempt raises an error (and
434+
-- we hit a timeout), the error will be re-raised.
413435
local function wait_cond(self, cond, timeout, delay)
414436
assert(type(cond) == 'function')
415437

416438
local timeout = timeout or 60
417439
local delay = delay or 0.001
418440

419441
local start_time = clock.monotonic()
420-
local res = {cond()}
442+
local res = {pcall(cond)}
421443

422-
while not res[1] do
444+
while not res[1] or not res[2] do
423445
local work_time = clock.monotonic() - start_time
424446
if work_time > timeout then
425-
return unpack(res)
447+
return wait_cond_finish(res)
426448
end
427449
fiber.sleep(delay)
428-
res = {cond()}
450+
res = {pcall(cond)}
429451
end
430452

431-
return unpack(res)
453+
return wait_cond_finish(res)
432454
end
433455

434456
-- Wrapper for grep_log, wait until expected log entry is appear

0 commit comments

Comments
 (0)