Commit ff329f3a authored by Kirill Smelkov's avatar Kirill Smelkov

wcfs: tests: Use small "pin timeout" for faulty protection tests

The default "pin timeout" is 30s and we are going to add many tests that
exercise pinkilling functionality soon. If every such test takes
2·pintimeout time = 60s, it will result in significant time increase
needed to run WCFS tests. Avoid that by adjusting pin timeout to
one order of magnitude smaller pintimeout=3s during faulty protection
tests.
parent 9d7a4a41
...@@ -543,6 +543,9 @@ type Root struct { ...@@ -543,6 +543,9 @@ type Root struct {
revMu sync.Mutex revMu sync.Mutex
revTab map[zodb.Tid]*Head revTab map[zodb.Tid]*Head
// time budget for a client to handle pin notification (TODO)
pinTimeout time.Duration
// collected statistics // collected statistics
stats *Stats stats *Stats
} }
...@@ -2498,6 +2501,7 @@ func main() { ...@@ -2498,6 +2501,7 @@ func main() {
func _main() (err error) { func _main() (err error) {
debug := flag.Bool("d", false, "debug") debug := flag.Bool("d", false, "debug")
autoexit := flag.Bool("autoexit", false, "automatically stop service when there is no client activity") autoexit := flag.Bool("autoexit", false, "automatically stop service when there is no client activity")
pintimeout := flag.Duration("pintimeout", 30*time.Second, "clients are killed if they do not handle pin notification in pintimeout time")
flag.Parse() flag.Parse()
if len(flag.Args()) != 2 { if len(flag.Args()) != 2 {
...@@ -2585,6 +2589,7 @@ func _main() (err error) { ...@@ -2585,6 +2589,7 @@ func _main() (err error) {
zdb: zdb, zdb: zdb,
head: head, head: head,
revTab: make(map[zodb.Tid]*Head), revTab: make(map[zodb.Tid]*Head),
pinTimeout: *pintimeout,
stats: &Stats{}, stats: &Stats{},
} }
...@@ -2641,6 +2646,7 @@ func _main() (err error) { ...@@ -2641,6 +2646,7 @@ func _main() (err error) {
_wcfs := newFSNode(fSticky) _wcfs := newFSNode(fSticky)
mkdir(root, ".wcfs", &_wcfs) mkdir(root, ".wcfs", &_wcfs)
mkfile(&_wcfs, "zurl", NewStaticFile([]byte(zurl))) mkfile(&_wcfs, "zurl", NewStaticFile([]byte(zurl)))
mkfile(&_wcfs, "pintimeout", NewStaticFile([]byte(fmt.Sprintf("%.1f", float64(root.pinTimeout) / float64(time.Second)))))
// .wcfs/zhead - special file channel that sends zhead.at. // .wcfs/zhead - special file channel that sends zhead.at.
// //
......
...@@ -26,18 +26,24 @@ from golang import select, func, defer ...@@ -26,18 +26,24 @@ from golang import select, func, defer
from golang import context, sync, time from golang import context, sync, time
import pytest; xfail = pytest.mark.xfail import pytest; xfail = pytest.mark.xfail
from pytest import fail from pytest import fail, fixture
from wendelin.wcfs.wcfs_test import tDB, h, \ from wendelin.wcfs.wcfs_test import tDB, h, \
setup_module, teardown_module, setup_function, teardown_function setup_module, teardown_module, setup_function, teardown_function
# tests in this module require WCFS to promptly react to pin handler
# timeouts so that verifying WCFS killing logic does not take a lot of time.
@fixture
def with_prompt_pintimeout(monkeypatch):
tkill = 3*time.second
return monkeypatch.setenv("WENDELIN_CORE_WCFS_OPTIONS", "-pintimeout %.1fs" % tkill, prepend=" ")
# verify that wcfs kills slow/faulty client who does not reply to pin in time. # verify that wcfs kills slow/faulty client who does not reply to pin in time.
@xfail # protection against faulty/slow clients @xfail # protection against faulty/slow clients
@func @func
def test_wcfs_pintimeout_kill(): def test_wcfs_pintimeout_kill(with_prompt_pintimeout):
# adjusted wcfs timeout to kill client who is stuck not providing pin reply t = tDB(); zf = t.zfile
tkill = 3*time.second
t = tDB(); zf = t.zfile # XXX wcfs args += tkill=<small>
defer(t.close) defer(t.close)
at1 = t.commit(zf, {2:'c1'}) at1 = t.commit(zf, {2:'c1'})
...@@ -46,7 +52,7 @@ def test_wcfs_pintimeout_kill(): ...@@ -46,7 +52,7 @@ def test_wcfs_pintimeout_kill():
f.assertData(['','','c2']) f.assertData(['','','c2'])
# XXX move into subprocess not to kill whole testing # XXX move into subprocess not to kill whole testing
ctx, _ = context.with_timeout(context.background(), 2*tkill) ctx, _ = context.with_timeout(context.background(), 2*t.pintimeout)
wl = t.openwatch() wl = t.openwatch()
wg = sync.WorkGroup(ctx) wg = sync.WorkGroup(ctx)
...@@ -63,7 +69,7 @@ def test_wcfs_pintimeout_kill(): ...@@ -63,7 +69,7 @@ def test_wcfs_pintimeout_kill():
# sleep > wcfs pin timeout - wcfs must kill us # sleep > wcfs pin timeout - wcfs must kill us
_, _rx = select( _, _rx = select(
ctx.done().recv, # 0 ctx.done().recv, # 0
time.after(tkill).recv, # 1 time.after(t.pintimeout).recv, # 1
) )
if _ == 0: if _ == 0:
raise ctx.err() raise ctx.err()
......
...@@ -357,10 +357,13 @@ class tWCFS(_tWCFS): ...@@ -357,10 +357,13 @@ class tWCFS(_tWCFS):
assert os.path.exists(wc.mountpoint) assert os.path.exists(wc.mountpoint)
assert is_mountpoint(wc.mountpoint) assert is_mountpoint(wc.mountpoint)
t.wc = wc t.wc = wc
t.pintimeout = float(t.wc._read(".wcfs/pintimeout"))
# the whole test is limited in time to detect deadlocks # the whole test is limited in time to detect deadlocks
# NOTE with_timeout must be << timeout # NOTE with_timeout must be << timeout
# NOTE wcfs_pin_timeout must be >> timeout # NOTE pintimeout can be either
# * >> timeout (most of the test), or
# * << timeout (faulty protection tests)
timeout = 10*time.second timeout = 10*time.second
t.ctx, t._ctx_cancel = context.with_timeout(context.background(), timeout) t.ctx, t._ctx_cancel = context.with_timeout(context.background(), timeout)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment