Skip to content

Commit 29e8538

Browse files
committed
server: fix artifact handling reset on restart
Fix a bug when server initialization didn't reset artifact handling, which caused stale artifacts to persist after server restarts. Closes #409
1 parent a0930d4 commit 29e8538

File tree

10 files changed

+169
-66
lines changed

10 files changed

+169
-66
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- Fixed a bug when server initialization didn't reset artifact handling,
6+
causing stale artifacts to persist after server restarts (gh-409).
57
- Fixed a bug when the JUnit reporter generated invalid XML for parameterized
68
tests with string arguments (gh-407).
79
- Group and suite hooks must now be registered using the call-style

luatest/replica_set.lua

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,10 @@ function ReplicaSet:stop()
184184
end
185185
end
186186

187-
--- Stop all servers in the replica set and save their artifacts if the test fails.
187+
--- Stop all servers in the replica set.
188188
-- This function should be used only at the end of the test (`after_test`,
189189
-- `after_each`, `after_all` hooks) to terminate all server processes in
190-
-- the replica set. Besides process termination, it saves the contents of
191-
-- each server working directory to the `<vardir>/artifacts` directory
192-
-- for further analysis if the test fails.
190+
-- the replica set.
193191
function ReplicaSet:drop()
194192
for _, server in ipairs(self.servers) do
195193
server:drop()

luatest/runner.lua

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -377,11 +377,6 @@ function Runner.mt:update_status(node, err)
377377
elseif err.status == 'fail' or err.status == 'error' or err.status == 'skip'
378378
or err.status == 'xfail' or err.status == 'xsuccess' then
379379
node:update_status(err.status, err.message, err.trace)
380-
if utils.table_len(node.servers) > 0 then
381-
for _, server in pairs(node.servers) do
382-
server:save_artifacts()
383-
end
384-
end
385380
else
386381
error('No such status: ' .. pp.tostring(err.status))
387382
end
@@ -391,6 +386,13 @@ end
391386
function Runner.mt:end_test(node)
392387
node.duration = clock.time() - node.start_time
393388
node.start_time = nil
389+
390+
if (node.had_failure or not node:is('success')) and utils.table_len(node.servers) > 0 then
391+
for _, server in pairs(node.servers) do
392+
server:save_artifacts()
393+
end
394+
end
395+
394396
self.output:end_test(node)
395397

396398
if node:is('error') or node:is('fail') or node:is('xsuccess') then
@@ -479,7 +481,7 @@ end
479481
function Runner.mt:run_tests(tests_list)
480482
-- Make seed for ordering not affect other random numbers.
481483
math.randomseed(os.time())
482-
rawset(_G, 'current_test', {value = nil})
484+
rawset(_G, 'current_test', {runner = self, value = nil})
483485
for _ = 1, self.exe_repeat_group or 1 do
484486
local last_group
485487
for _, test in ipairs(tests_list) do

luatest/server.lua

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -531,15 +531,13 @@ local function wait_for_condition(cond_desc, server, func, ...)
531531
local deadline = clock.time() + WAIT_TIMEOUT
532532
while true do
533533
if not server.process:is_alive() then
534-
server:save_artifacts()
535534
error(('Process is terminated when waiting for "%s" condition for server (alias: %s, workdir: %s, pid: %d)')
536535
:format(cond_desc, server.alias, fio.basename(server.workdir), server.process.pid))
537536
end
538537
if func(...) then
539538
return
540539
end
541540
if clock.time() > deadline then
542-
server:save_artifacts()
543541
error(('Timed out to wait for "%s" condition for server (alias: %s, workdir: %s, pid: %d) within %ds')
544542
:format(cond_desc, server.alias, fio.basename(server.workdir), server.process.pid, WAIT_TIMEOUT))
545543
end
@@ -585,15 +583,11 @@ function Server:stop()
585583
end
586584
end
587585

588-
--- Stop the server and save its artifacts if the test fails.
586+
-- Stop the server.
589587
-- This function should be used only at the end of the test (`after_test`,
590588
-- `after_each`, `after_all` hooks) to terminate the server process.
591-
-- Besides process termination, it saves the contents of the server
592-
-- working directory to the `<vardir>/artifacts` directory for further
593-
-- analysis if the test fails.
594589
function Server:drop()
595590
self:stop()
596-
self:save_artifacts()
597591

598592
self.instance_id = nil
599593
self.instance_uuid = nil

luatest/test_instance.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@ end
1717
function TestInstance.mt:initialize()
1818
self.status = 'success'
1919
self.servers = {}
20+
self.had_failure = false
2021
end
2122

2223
function TestInstance.mt:update_status(status, message, trace)
24+
if status ~= 'success' then
25+
self.had_failure = true
26+
end
2327
self.status = status
2428
self.message = message
2529
self.trace = trace

test/artifacts/hooks_test.lua

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ local fio = require('fio')
44

55
local g = t.group()
66
local Server = t.Server
7+
local deferred_artifact_checks = {}
78

89
local function is_server_in_test(server, test)
910
for _, s in pairs(test.servers) do
@@ -55,18 +56,31 @@ g.test_association_between_test_and_servers = function()
5556
end
5657

5758
g.after_test('test_association_between_test_and_servers', function()
59+
local ctx = rawget(_G, 'current_test')
60+
local test = ctx.value
61+
ctx.runner:update_status(test, {status = 'fail'})
5862
g.internal:drop()
5963
g.test:drop()
60-
t.assert(fio.path.exists(g.test.artifacts))
64+
test:update_status('success')
65+
table.insert(deferred_artifact_checks, function()
66+
t.assert(fio.path.exists(g.test.artifacts))
67+
end)
6168
end)
6269

6370
g.after_each(function()
6471
g.each:drop()
65-
t.assert(fio.path.exists(g.each.artifacts))
72+
table.insert(deferred_artifact_checks, function()
73+
t.assert(fio.path.exists(g.each.artifacts))
74+
end)
6675
end)
6776

6877
g.after_all(function()
6978
g.all:drop()
70-
t.assert(fio.path.exists(g.all.artifacts))
79+
table.insert(deferred_artifact_checks, function()
80+
t.assert(fio.path.exists(g.all.artifacts))
81+
end)
7182
g.public:drop()
83+
for _, check in ipairs(deferred_artifact_checks) do
84+
check()
85+
end
7286
end)

test/collect_rs_artifacts_test.lua

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ local utils = require('luatest.utils')
44
local ReplicaSet = require('luatest.replica_set')
55

66
local g = t.group()
7+
local deferred_artifact_checks = {}
78
local Server = t.Server
89

910
local function build_specific_replica_set(alias_suffix)
@@ -87,15 +88,24 @@ g.before_test('test_foo', function()
8788
end)
8889

8990
g.test_foo = function()
90-
local test = rawget(_G, 'current_test')
91+
local ctx = rawget(_G, 'current_test')
92+
local test = ctx.value
9193

92-
test.status = 'fail'
9394
g.rs_test:drop()
9495
g.rs_each:drop()
9596
g.rs_all:drop()
96-
test.status = 'success'
97-
98-
assert_artifacts_paths(g.rs_test, 'test')
99-
assert_artifacts_paths(g.rs_each, 'each')
100-
assert_artifacts_paths(g.rs_all, 'all')
97+
ctx.runner:update_status(test, {status = 'fail'})
98+
test:update_status('success')
99+
100+
table.insert(deferred_artifact_checks, function()
101+
assert_artifacts_paths(g.rs_test, 'test')
102+
assert_artifacts_paths(g.rs_each, 'each')
103+
assert_artifacts_paths(g.rs_all, 'all')
104+
end)
101105
end
106+
107+
g.after_all(function()
108+
for _, check in ipairs(deferred_artifact_checks) do
109+
check()
110+
end
111+
end)

test/collect_server_artifacts_test.lua

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ local fio = require('fio')
22

33
local t = require('luatest')
44
local g = t.group()
5+
local deferred_artifact_checks = {}
56

67
local Server = t.Server
78

@@ -35,21 +36,30 @@ g.before_test('test_foo', function()
3536
end)
3637

3738
g.test_foo = function()
38-
local test = rawget(_G, 'current_test')
39+
local ctx = rawget(_G, 'current_test')
40+
local test = ctx.value
3941

40-
test.status = 'fail'
4142
g.s_test:drop()
4243
g.s_test2:drop()
4344
g.s_each:drop()
4445
g.s_each2:drop()
4546
g.s_all:drop()
4647
g.s_all2:drop()
47-
test.status = 'success'
48-
49-
assert_artifacts_path(g.s_test)
50-
assert_artifacts_path(g.s_test2)
51-
assert_artifacts_path(g.s_each)
52-
assert_artifacts_path(g.s_each2)
53-
assert_artifacts_path(g.s_all)
54-
assert_artifacts_path(g.s_all2)
48+
ctx.runner:update_status(test, {status = 'fail'})
49+
test:update_status('success')
50+
51+
table.insert(deferred_artifact_checks, function()
52+
assert_artifacts_path(g.s_test)
53+
assert_artifacts_path(g.s_test2)
54+
assert_artifacts_path(g.s_each)
55+
assert_artifacts_path(g.s_each2)
56+
assert_artifacts_path(g.s_all)
57+
assert_artifacts_path(g.s_all2)
58+
end)
5559
end
60+
61+
g.after_all(function()
62+
for _, check in ipairs(deferred_artifact_checks) do
63+
check()
64+
end
65+
end)

test/replica_set_test.lua

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ local ReplicaSet = require('luatest.replica_set')
44

55
local g = t.group()
66
local Server = t.Server
7+
local deferred_artifact_checks = {}
78

89
g.before_each(function()
910
g.rs = ReplicaSet:new()
@@ -33,23 +34,26 @@ g.before_test('test_save_rs_artifacts_when_test_failed', function()
3334
end)
3435

3536
g.test_save_rs_artifacts_when_test_failed = function()
36-
local test = rawget(_G, 'current_test')
37+
local ctx = rawget(_G, 'current_test')
38+
local test = ctx.value
3739
-- the test must be failed to save artifacts
38-
test.status = 'fail'
40+
ctx.runner:update_status(test, {status = 'fail'})
3941
g.rs:drop()
40-
test.status = 'success'
42+
test:update_status('success')
4143

42-
t.assert_equals(fio.path.exists(g.rs_artifacts), true)
43-
t.assert_equals(fio.path.is_dir(g.rs_artifacts), true)
44+
table.insert(deferred_artifact_checks, function()
45+
t.assert_equals(fio.path.exists(g.rs_artifacts), true)
46+
t.assert_equals(fio.path.is_dir(g.rs_artifacts), true)
4447

45-
t.assert_equals(fio.path.exists(g.s1_artifacts), true)
46-
t.assert_equals(fio.path.is_dir(g.s1_artifacts), true)
48+
t.assert_equals(fio.path.exists(g.s1_artifacts), true)
49+
t.assert_equals(fio.path.is_dir(g.s1_artifacts), true)
4750

48-
t.assert_equals(fio.path.exists(g.s2_artifacts), true)
49-
t.assert_equals(fio.path.is_dir(g.s2_artifacts), true)
51+
t.assert_equals(fio.path.exists(g.s2_artifacts), true)
52+
t.assert_equals(fio.path.is_dir(g.s2_artifacts), true)
5053

51-
t.assert_equals(fio.path.exists(g.s3_artifacts), true)
52-
t.assert_equals(fio.path.is_dir(g.s3_artifacts), true)
54+
t.assert_equals(fio.path.exists(g.s3_artifacts), true)
55+
t.assert_equals(fio.path.is_dir(g.s3_artifacts), true)
56+
end)
5357
end
5458

5559
g.before_test('test_save_rs_artifacts_when_server_workdir_passed', function()
@@ -69,26 +73,35 @@ g.before_test('test_save_rs_artifacts_when_server_workdir_passed', function()
6973
end)
7074

7175
g.test_save_rs_artifacts_when_server_workdir_passed = function()
72-
local test = rawget(_G, 'current_test')
76+
local ctx = rawget(_G, 'current_test')
77+
local test = ctx.value
7378
-- the test must be failed to save artifacts
74-
test.status = 'fail'
79+
ctx.runner:update_status(test, {status = 'fail'})
7580
g.rs:drop()
76-
test.status = 'success'
81+
test:update_status('success')
7782

78-
t.assert_equals(fio.path.exists(g.rs_artifacts), true)
79-
t.assert_equals(fio.path.is_dir(g.rs_artifacts), true)
83+
table.insert(deferred_artifact_checks, function()
84+
t.assert_equals(fio.path.exists(g.rs_artifacts), true)
85+
t.assert_equals(fio.path.is_dir(g.rs_artifacts), true)
8086

81-
t.assert_equals(fio.path.exists(g.s1_artifacts), true)
82-
t.assert_equals(fio.path.is_dir(g.s1_artifacts), true)
87+
t.assert_equals(fio.path.exists(g.s1_artifacts), true)
88+
t.assert_equals(fio.path.is_dir(g.s1_artifacts), true)
8389

84-
t.assert_equals(fio.path.exists(g.s2_artifacts), true)
85-
t.assert_equals(fio.path.is_dir(g.s2_artifacts), true)
90+
t.assert_equals(fio.path.exists(g.s2_artifacts), true)
91+
t.assert_equals(fio.path.is_dir(g.s2_artifacts), true)
8692

87-
t.assert_equals(fio.path.exists(g.s3_artifacts), true)
88-
t.assert_equals(fio.path.is_dir(g.s3_artifacts), true)
93+
t.assert_equals(fio.path.exists(g.s3_artifacts), true)
94+
t.assert_equals(fio.path.is_dir(g.s3_artifacts), true)
95+
end)
8996

9097
end
9198

99+
g.after_all(function()
100+
for _, check in ipairs(deferred_artifact_checks) do
101+
check()
102+
end
103+
end)
104+
92105
g.test_rs_no_socket_collision_with_custom_alias = function()
93106
local s1 = g.rs:build_server({alias = 'foo'})
94107
local s2 = g.rs:build_server({alias = 'bar'})

0 commit comments

Comments
 (0)