Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
wendelin.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Kirill Smelkov
wendelin.core
Commits
257018a5
Commit
257018a5
authored
Nov 16, 2021
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
eeb7a544
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
76 additions
and
23 deletions
+76
-23
.nxdtest
.nxdtest
+16
-11
Makefile
Makefile
+1
-1
conftest.py
conftest.py
+16
-1
lib/testing.py
lib/testing.py
+4
-1
setup.py
setup.py
+2
-2
wcfs/__init__.py
wcfs/__init__.py
+35
-3
wcfs/wcfs_test.py
wcfs/wcfs_test.py
+2
-4
No files found.
.nxdtest
View file @
257018a5
...
@@ -3,11 +3,6 @@
...
@@ -3,11 +3,6 @@
storv = ['fs', 'zeo', 'neo'] # storage backends to test against
storv = ['fs', 'zeo', 'neo'] # storage backends to test against
# some bugs are only likely to trigger when there is only 1 or 2 main OS thread(s) in wcfs
# GOMAXPROCS='' means use `nproc`
gonprocv = ['1', '2', ''] # GOMAXPROCS=... to test against
# test.t & friends unit-test core of UVMM and are Go-, Python- and ZODB-storage independent.
# test.t & friends unit-test core of UVMM and are Go-, Python- and ZODB-storage independent.
# we don't run test.vg* because there is currently no valgrind on SlapOS.
# we don't run test.vg* because there is currently no valgrind on SlapOS.
for kind in ['t', 'fault', 'asan', 'tsan']:
for kind in ['t', 'fault', 'asan', 'tsan']:
...
@@ -34,20 +29,30 @@ for stor in storv:
...
@@ -34,20 +29,30 @@ for stor in storv:
# test.go unit-tests Go bits in wcfs.
# test.go unit-tests Go bits in wcfs.
for nproc in gonprocv:
TestCase('test.go', ['make', 'test.go'])
TestCase('test.go:%s' % nproc, ['make', 'test.go'],
envadj={'GOMAXPROCS': nproc})
# test.wcfs/<stor> runs unit tests for WCFS
# test.wcfs/<stor> runs unit tests for WCFS
# test.py/<stor>-wcfs runs unit- and functional- tests for wendelin.core in wcfs mode.
# test.py/<stor>-wcfs runs unit- and functional- tests for wendelin.core in wcfs mode.
for stor in storv:
for stor in storv:
envdb = {'WENDELIN_CORE_TEST_DB': '<%s>' % stor}
env = {
'WENDELIN_CORE_TEST_DB': '<%s>' % stor,
# run in verbose mode and don't capture output in the early days of WCFS
#
# non-capture is needed because if WCFS gets stuck somehow on testnode, we
# still want to see some test output instead of full silence and pytest
# being killed after 4 hours of timeout.
'PYTEST_ADDOPTS': '-vs',
}
# some bugs are only likely to trigger when there is only 1 or 2 main OS thread(s) in wcfs
# GOMAXPROCS='' means use `nproc`
gonprocv = ['1', '2', ''] # GOMAXPROCS=... to test against
for nproc in gonprocv:
for nproc in gonprocv:
TestCase('test.wcfs/%s:%s' % (stor, nproc), ['make', 'test.wcfs'],
TestCase('test.wcfs/%s:%s' % (stor, nproc), ['make', 'test.wcfs'],
envadj=dict(GOMAXPROCS=nproc, **env
db
), summaryf=PyTest.summary)
envadj=dict(GOMAXPROCS=nproc, **env), summaryf=PyTest.summary)
for nproc in gonprocv:
for nproc in gonprocv:
TestCase('test.py/%s-wcfs:%s' % (stor, nproc), ['make', 'test.py'],
TestCase('test.py/%s-wcfs:%s' % (stor, nproc), ['make', 'test.py'],
envadj=dict(WENDELIN_CORE_VIRTMEM='r:wcfs+w:uvmm', GOMAXPROCS=nproc, **env
db
),
envadj=dict(WENDELIN_CORE_VIRTMEM='r:wcfs+w:uvmm', GOMAXPROCS=nproc, **env),
summaryf=PyTest.summary)
summaryf=PyTest.summary)
Makefile
View file @
257018a5
...
@@ -20,7 +20,7 @@
...
@@ -20,7 +20,7 @@
all
:
all
:
PYTHON
?=
python
PYTHON
?=
python
PYTEST
?=
$(PYTHON)
-m
pytest
-vs
PYTEST
?=
$(PYTHON)
-m
pytest
PYBENCH
?=
$(PYTHON)
-m
golang.cmd.pybench
PYBENCH
?=
$(PYTHON)
-m
golang.cmd.pybench
VALGRIND
?=
valgrind
VALGRIND
?=
valgrind
GO
?=
go
GO
?=
go
...
...
conftest.py
View file @
257018a5
...
@@ -24,7 +24,7 @@ import pytest
...
@@ -24,7 +24,7 @@ import pytest
import
transaction
import
transaction
from
golang
import
func
,
defer
from
golang
import
func
,
defer
from
functools
import
partial
from
functools
import
partial
import
gc
import
os
,
gc
# reset transaction synchronizers before every test run.
# reset transaction synchronizers before every test run.
#
#
...
@@ -46,9 +46,24 @@ def transaction_reset():
...
@@ -46,9 +46,24 @@ def transaction_reset():
# nothing to run after test
# nothing to run after test
# prepend_env prepends prefix + ' ' to environment variable var.
def
prepend_env
(
var
,
prefix
):
v
=
os
.
environ
.
get
(
var
,
''
)
if
v
!=
''
:
v
=
' '
+
v
v
=
prefix
+
v
os
.
environ
[
var
]
=
v
# enable log_cli on no-capture
# enable log_cli on no-capture
# (output during a test is a mixture of print and log)
# (output during a test is a mixture of print and log)
def
pytest_configure
(
config
):
def
pytest_configure
(
config
):
# put WCFS log into stderr instead of to many files in /tmp/wcfs.*.log
# this way we don't leak those files and include relevant information in test output
#
# TODO put WCFS logs into dedicated dir without -v?
prepend_env
(
'WENDELIN_CORE_WCFS_OPTIONS'
,
'-logtostderr'
)
if
config
.
option
.
capture
==
"no"
:
if
config
.
option
.
capture
==
"no"
:
config
.
inicfg
[
'log_cli'
]
=
"true"
config
.
inicfg
[
'log_cli'
]
=
"true"
assert
config
.
getini
(
"log_cli"
)
is
True
assert
config
.
getini
(
"log_cli"
)
is
True
...
...
lib/testing.py
View file @
257018a5
...
@@ -292,14 +292,17 @@ class TestDB_NEO(TestDB_Base):
...
@@ -292,14 +292,17 @@ class TestDB_NEO(TestDB_Base):
def
__init__
(
self
,
dburi
):
def
__init__
(
self
,
dburi
):
super
(
TestDB_NEO
,
self
).
__init__
(
dburi
)
super
(
TestDB_NEO
,
self
).
__init__
(
dburi
)
from
neo.tests.functional
import
NEOCluster
from
neo.tests.functional
import
NEOCluster
self
.
cluster
=
NEOCluster
([
'1'
],
adapter
=
'SQLite'
)
self
.
NEOCluster
=
NEOCluster
def
setup
(
self
):
def
setup
(
self
):
self
.
tmpd
=
mkdtemp
(
''
,
'testdb_neo.'
)
self
.
cluster
=
self
.
NEOCluster
([
'1'
],
temp_dir
=
self
.
tmpd
,
adapter
=
'SQLite'
)
self
.
cluster
.
start
()
self
.
cluster
.
start
()
self
.
cluster
.
expectClusterRunning
()
self
.
cluster
.
expectClusterRunning
()
def
_teardown
(
self
):
def
_teardown
(
self
):
self
.
cluster
.
stop
()
self
.
cluster
.
stop
()
rmtree
(
self
.
tmpd
)
def
getZODBStorage
(
self
):
def
getZODBStorage
(
self
):
return
self
.
cluster
.
getZODBStorage
()
return
self
.
cluster
.
getZODBStorage
()
...
...
setup.py
View file @
257018a5
...
@@ -246,11 +246,11 @@ def git_lsfiles(dirname):
...
@@ -246,11 +246,11 @@ def git_lsfiles(dirname):
# FIXME dirname is currently ignored
# FIXME dirname is currently ignored
# XXX non-ascii names, etc
# XXX non-ascii names, etc
for
_
in
runcmd
([
'git'
,
'ls-files'
]).
splitlines
():
for
_
in
runcmd
([
'git'
,
'ls-files'
]).
splitlines
():
yield
_
.
decode
(
'utf8'
)
# XXX utf8 hardcoded
yield
_
# XXX recursive submodules
# XXX recursive submodules
for
_
in
runcmd
([
'git'
,
'submodule'
,
'foreach'
,
'--quiet'
,
\
for
_
in
runcmd
([
'git'
,
'submodule'
,
'foreach'
,
'--quiet'
,
\
r'git ls-files | sed "s|\
(.*
\)\
$|$p
ath/\1|g"'
]).
splitlines
():
r'git ls-files | sed "s|\
(.*
\)\
$|$p
ath/\1|g"'
]).
splitlines
():
yield
_
.
decode
(
'utf8'
)
# XXX utf8 hardcoded
yield
_
# if we are in git checkout - inject git_lsfiles to setuptools.file_finders
# if we are in git checkout - inject git_lsfiles to setuptools.file_finders
# entry-point on the fly.
# entry-point on the fly.
...
...
wcfs/__init__.py
View file @
257018a5
...
@@ -417,6 +417,24 @@ def __stop(wcsrv, ctx, _onstuck):
...
@@ -417,6 +417,24 @@ def __stop(wcsrv, ctx, _onstuck):
# unmount and wait for wcfs to exit
# unmount and wait for wcfs to exit
# kill wcfs and abort FUSE connection if clean unmount fails
# kill wcfs and abort FUSE connection if clean unmount fails
# at the end make sure mount entry and mountpoint directory are removed
def
_
():
# when stop runs:
# - wcsrv could be already `fusermount -u`'ed from outside
# - the mountpoint could be also already removed from outside
_rmdir_ifexists
(
wcsrv
.
mountpoint
)
defer
(
_
)
def
_
():
# second unmount, if first unmount failed and we had to abort FUSE connection
# -z (lazy) because this one has to succeed, but there could be still
# client file descriptors left pointing to the mounted filesystem.
if
_is_mountpoint
(
wcsrv
.
mountpoint
):
log
.
warn
(
"-> unmount -z ..."
)
_fuse_unmount
(
wcsrv
.
mountpoint
,
"-z"
)
defer
(
_
)
def
_
():
def
_
():
if
wcsrv
.
_fuseabort
is
not
None
:
if
wcsrv
.
_fuseabort
is
not
None
:
wcsrv
.
_fuseabort
.
close
()
wcsrv
.
_fuseabort
.
close
()
...
@@ -521,10 +539,20 @@ def _mkdir_p(path, mode=0o777): # -> created(bool)
...
@@ -521,10 +539,20 @@ def _mkdir_p(path, mode=0o777): # -> created(bool)
return
False
return
False
return
True
return
True
# rmdir if path exists.
def
_rmdir_ifexists
(
path
):
try
:
os
.
rmdir
(
path
)
except
OSError
as
e
:
if
e
.
errno
!=
ENOENT
:
raise
# _fuse_unmount calls `fusermount -u` + logs details if unmount failed.
# _fuse_unmount calls `fusermount -u` + logs details if unmount failed.
#
# Additional options to fusermount can be passed via optv.
@
func
@
func
def
_fuse_unmount
(
mntpt
):
def
_fuse_unmount
(
mntpt
,
*
optv
):
ret
,
out
=
_sysproccallout
([
"fusermount"
,
"-u"
,
mntpt
])
ret
,
out
=
_sysproccallout
([
"fusermount"
,
"-u"
]
+
list
(
optv
)
+
[
mntpt
])
if
ret
!=
0
:
if
ret
!=
0
:
# unmount failed, usually due to "device is busy".
# unmount failed, usually due to "device is busy".
# Log which files are still opened and reraise
# Log which files are still opened and reraise
...
@@ -543,7 +571,10 @@ def _fuse_unmount(mntpt):
...
@@ -543,7 +571,10 @@ def _fuse_unmount(mntpt):
defer
(
_
)
defer
(
_
)
out
=
out
.
rstrip
()
# kill trailing \n\n
out
=
out
.
rstrip
()
# kill trailing \n\n
emsg
=
"fuse_unmount %s: failed: %s"
%
(
mntpt
,
out
)
opts
=
' '
.
join
(
optv
)
if
opts
!=
''
:
opts
+=
' '
emsg
=
"fuse_unmount %s%s: failed: %s"
%
(
opts
,
mntpt
,
out
)
log
.
warn
(
emsg
)
log
.
warn
(
emsg
)
raise
RuntimeError
(
"%s
\
n
(more details logged)"
%
emsg
)
raise
RuntimeError
(
"%s
\
n
(more details logged)"
%
emsg
)
...
@@ -713,6 +744,7 @@ def main():
...
@@ -713,6 +744,7 @@ def main():
elif
cmd
==
"stop"
:
elif
cmd
==
"stop"
:
mntpt
=
_mntpt_4zurl
(
zurl
)
mntpt
=
_mntpt_4zurl
(
zurl
)
_fuse_unmount
(
mntpt
)
_fuse_unmount
(
mntpt
)
_rmdir_ifexists
(
mntpt
)
else
:
else
:
print
(
"wcfs: unknown command %s"
%
qq
(
cmd
),
file
=
sys
.
stderr
)
print
(
"wcfs: unknown command %s"
%
qq
(
cmd
),
file
=
sys
.
stderr
)
...
...
wcfs/wcfs_test.py
View file @
257018a5
...
@@ -53,7 +53,7 @@ from pytest import raises, fail
...
@@ -53,7 +53,7 @@ from pytest import raises, fail
from
wendelin.wcfs.internal
import
io
,
mm
from
wendelin.wcfs.internal
import
io
,
mm
from
wendelin.wcfs.internal.wcfs_test
import
_tWCFS
,
read_exfault_nogil
,
SegmentationFault
,
install_sigbus_trap
,
fadvise_dontneed
from
wendelin.wcfs.internal.wcfs_test
import
_tWCFS
,
read_exfault_nogil
,
SegmentationFault
,
install_sigbus_trap
,
fadvise_dontneed
from
wendelin.wcfs.client._wcfs
import
_tpywlinkwrite
as
_twlinkwrite
from
wendelin.wcfs.client._wcfs
import
_tpywlinkwrite
as
_twlinkwrite
from
wendelin.wcfs
import
_is_mountpoint
as
is_mountpoint
,
_procwait
as
procwait
,
_ready
as
ready
from
wendelin.wcfs
import
_is_mountpoint
as
is_mountpoint
,
_procwait
as
procwait
,
_ready
as
ready
,
_rmdir_ifexists
as
rmdir_ifexists
# setup:
# setup:
...
@@ -106,8 +106,7 @@ def teardown_function(f):
...
@@ -106,8 +106,7 @@ def teardown_function(f):
mounted
=
is_mountpoint
(
testmntpt
)
mounted
=
is_mountpoint
(
testmntpt
)
if
mounted
:
if
mounted
:
fuse_unmount
(
testmntpt
)
fuse_unmount
(
testmntpt
)
if
os
.
path
.
exists
(
testmntpt
):
rmdir_ifexists
(
testmntpt
)
os
.
rmdir
(
testmntpt
)
with
raises
(
KeyError
):
with
raises
(
KeyError
):
procmounts_lookup_wcfs
(
testzurl
)
procmounts_lookup_wcfs
(
testzurl
)
...
@@ -384,7 +383,6 @@ class tWCFS(_tWCFS):
...
@@ -384,7 +383,6 @@ class tWCFS(_tWCFS):
if
is_mountpoint
(
t
.
wc
.
mountpoint
):
if
is_mountpoint
(
t
.
wc
.
mountpoint
):
fuse_unmount
(
t
.
wc
.
mountpoint
)
fuse_unmount
(
t
.
wc
.
mountpoint
)
assert
not
is_mountpoint
(
t
.
wc
.
mountpoint
)
assert
not
is_mountpoint
(
t
.
wc
.
mountpoint
)
os
.
rmdir
(
t
.
wc
.
mountpoint
)
defer
(
_
)
defer
(
_
)
def
_
():
def
_
():
def
onstuck
():
def
onstuck
():
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment