Clean up smoketest and pytests.

- Replace depreciated tempfile with mktemp in smoketest.
- Remove unused pytest imports and variables.
- Make path lookup less fragile. Allows pytest to run from any cwd.
- Prevent exeptions caused by calling functions/methods on None objects.
- Disable fuse tests in smoketest. These are broken and add noise.
- Add missing travis CI dependency.

Signed-off-by: Brett Holman <bholman.devel@gmail.com>
This commit is contained in:
Brett Holman 2021-10-11 15:23:09 -06:00
parent ba1dbafc1f
commit 60a6b2882e
9 changed files with 41 additions and 37 deletions

View File

@ -9,6 +9,7 @@ addons:
apt: apt:
packages: packages:
- valgrind - valgrind
- python3-docutils
- python3-pytest - python3-pytest
- python3-pytest-xdist - python3-pytest-xdist
- meson - meson

View File

@ -85,7 +85,7 @@ tests: tests/test_helper
.PHONY: check .PHONY: check
check: tests bcachefs check: tests bcachefs
cd tests; $(PYTEST) $(PYTEST)
.PHONY: TAGS tags .PHONY: TAGS tags
TAGS: TAGS:

View File

@ -21,7 +21,7 @@
set -e set -e
PYTEST="${PYTEST:-pytest-3}" PYTEST="${PYTEST:-pytest-3}"
spam=$(tempfile) spam=$(mktemp)
unset BCACHEFS_FUSE BCACHEFS_TEST_USE_VALGRIND BCACHEFS_DEBUG unset BCACHEFS_FUSE BCACHEFS_TEST_USE_VALGRIND BCACHEFS_DEBUG
trap "set +x; cat ${spam}; rm -f ${spam} ; echo; echo FAILED." EXIT trap "set +x; cat ${spam}; rm -f ${spam} ; echo; echo FAILED." EXIT
@ -44,7 +44,6 @@ function build() {
function test() { function test() {
echo Running tests. echo Running tests.
( (
cd tests
${PYTEST} -n${JOBS} ${PYTEST} -n${JOBS}
) > ${spam} 2>&1 ) > ${spam} 2>&1
} }
@ -53,7 +52,6 @@ function test_vg() {
echo Running tests with valgrind. echo Running tests with valgrind.
( (
export BCACHEFS_TEST_USE_VALGRIND=yes export BCACHEFS_TEST_USE_VALGRIND=yes
cd tests
${PYTEST} -n${JOBS} ${PYTEST} -n${JOBS}
) > ${spam} 2>&1 ) > ${spam} 2>&1
} }
@ -71,13 +69,13 @@ test
echo -- Test: debug with valgrind -- echo -- Test: debug with valgrind --
test_vg test_vg
echo -- Test: fuse debug -- #echo -- Test: fuse debug --
export BCACHEFS_FUSE=1 #export BCACHEFS_FUSE=1
build #build
test #test
echo -- Test: fuse debug with valgrind -- #echo -- Test: fuse debug with valgrind --
test_vg #test_vg
rm -f ${spam} rm -f ${spam}
trap "set +x; echo; echo SUCCESS." EXIT trap "set +x; echo; echo SUCCESS." EXIT

0
tests/__init__.py Normal file
View File

View File

@ -3,7 +3,7 @@
# pytest fixture definitions. # pytest fixture definitions.
import pytest import pytest
import util from tests import util
@pytest.fixture @pytest.fixture
def bfuse(tmpdir): def bfuse(tmpdir):

View File

@ -3,7 +3,7 @@
# Basic bcachefs functionality tests. # Basic bcachefs functionality tests.
import re import re
import util from tests import util
def test_help(): def test_help():
ret = util.run_bch(valgrind=True) ret = util.run_bch(valgrind=True)

View File

@ -2,16 +2,15 @@
# #
# Tests of the functions in util.py # Tests of the functions in util.py
import pytest
import signal import signal
import subprocess import subprocess
import time import time
import os
import pytest
import util from tests import util
from pathlib import Path
#helper = Path('.') / 'test_helper' helper = os.path.abspath(os.path.join(util.BASE_PATH, 'test_helper'))
helper = './test_helper'
def test_sparse_file(tmpdir): def test_sparse_file(tmpdir):
dev = util.sparse_file(tmpdir / '1k', 1024) dev = util.sparse_file(tmpdir / '1k', 1024)
@ -32,32 +31,32 @@ def test_segfault():
@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind") @pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_check(): def test_check():
with pytest.raises(subprocess.CalledProcessError): with pytest.raises(subprocess.CalledProcessError):
ret = util.run(helper, 'abort', check=True) util.run(helper, 'abort', check=True)
@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind") @pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_leak(): def test_leak():
with pytest.raises(util.ValgrindFailedError): with pytest.raises(util.ValgrindFailedError):
ret = util.run(helper, 'leak', valgrind=True) util.run(helper, 'leak', valgrind=True)
@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind") @pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_undefined(): def test_undefined():
with pytest.raises(util.ValgrindFailedError): with pytest.raises(util.ValgrindFailedError):
ret = util.run(helper, 'undefined', valgrind=True) util.run(helper, 'undefined', valgrind=True)
@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind") @pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_undefined_branch(): def test_undefined_branch():
with pytest.raises(util.ValgrindFailedError): with pytest.raises(util.ValgrindFailedError):
ret = util.run(helper, 'undefined_branch', valgrind=True) util.run(helper, 'undefined_branch', valgrind=True)
@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind") @pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_read_after_free(): def test_read_after_free():
with pytest.raises(util.ValgrindFailedError): with pytest.raises(util.ValgrindFailedError):
ret = util.run(helper, 'read_after_free', valgrind=True) util.run(helper, 'read_after_free', valgrind=True)
@pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind") @pytest.mark.skipif(not util.ENABLE_VALGRIND, reason="no valgrind")
def test_write_after_free(): def test_write_after_free():
with pytest.raises(util.ValgrindFailedError): with pytest.raises(util.ValgrindFailedError):
ret = util.run(helper, 'write_after_free', valgrind=True) util.run(helper, 'write_after_free', valgrind=True)
def test_mountpoint(tmpdir): def test_mountpoint(tmpdir):
path = util.mountpoint(tmpdir) path = util.mountpoint(tmpdir)

View File

@ -4,7 +4,7 @@
import pytest import pytest
import os import os
import util from tests import util
pytestmark = pytest.mark.skipif( pytestmark = pytest.mark.skipif(
not util.have_fuse(), reason="bcachefs not built with fuse support.") not util.have_fuse(), reason="bcachefs not built with fuse support.")

View File

@ -2,18 +2,18 @@
import errno import errno
import os import os
import pytest
import re import re
import subprocess import subprocess
import sys
import tempfile import tempfile
import threading import threading
import time import time
from pathlib import Path from pathlib import Path
DIR = Path('..') BASE_PATH= os.path.dirname(__file__)
BCH_PATH = DIR / 'bcachefs' BCH_PATH = os.path.abspath(os.path.join(BASE_PATH, '..', 'bcachefs'))
VALGRIND_PATH= os.path.abspath(os.path.join(BASE_PATH,
'valgrind-suppressions.txt'))
VPAT = re.compile(r'ERROR SUMMARY: (\d+) errors from (\d+) contexts') VPAT = re.compile(r'ERROR SUMMARY: (\d+) errors from (\d+) contexts')
@ -46,21 +46,22 @@ def run(cmd, *args, valgrind=False, check=False):
cmds = [cmd] + list(args) cmds = [cmd] + list(args)
valgrind = valgrind and ENABLE_VALGRIND valgrind = valgrind and ENABLE_VALGRIND
print("Running '{}'".format(cmds))
if valgrind: if valgrind:
vout = tempfile.NamedTemporaryFile() vout = tempfile.NamedTemporaryFile()
vcmd = ['valgrind', vcmd = ['valgrind',
'--leak-check=full', '--leak-check=full',
'--gen-suppressions=all', '--gen-suppressions=all',
'--suppressions=valgrind-suppressions.txt', '--suppressions={}'.format(VALGRIND_PATH),
'--log-file={}'.format(vout.name)] '--log-file={}'.format(vout.name)]
cmds = vcmd + cmds cmds = vcmd + cmds
print("Running '{}'".format(cmds)) res = subprocess.run(cmds, stdout=subprocess.PIPE,
res = subprocess.run(cmds, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', check=check)
encoding='utf-8', check=check)
if valgrind:
check_valgrind(vout.read().decode('utf-8')) check_valgrind(vout.read().decode('utf-8'))
else:
res = subprocess.run(cmds, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, encoding='utf-8', check=check)
return res return res
@ -75,7 +76,7 @@ def sparse_file(lpath, size):
This is typically used to create device files for bcachefs. This is typically used to create device files for bcachefs.
""" """
path = Path(lpath) path = Path(lpath)
f = path.touch(mode = 0o600, exist_ok = False) path.touch(mode = 0o600, exist_ok = False)
os.truncate(path, size) os.truncate(path, size)
return path return path
@ -195,7 +196,8 @@ class BFuse:
self.stdout = out1 + out2 self.stdout = out1 + out2
self.stderr = err.read() self.stderr = err.read()
self.vout = vlog.read().decode('utf-8') if vlog:
self.vout = vlog.read().decode('utf-8')
def expect(self, pipe, regex): def expect(self, pipe, regex):
"""Wait for the child process to mount.""" """Wait for the child process to mount."""
@ -230,7 +232,8 @@ class BFuse:
print("Waiting for thread to exit.") print("Waiting for thread to exit.")
self.thread.join(timeout) self.thread.join(timeout)
if self.thread.is_alive(): if self.thread.is_alive():
self.proc.kill() if self.proc:
self.proc.kill()
self.thread.join() self.thread.join()
else: else:
print("Thread was already done.") print("Thread was already done.")
@ -242,6 +245,9 @@ class BFuse:
check_valgrind(self.vout) check_valgrind(self.vout)
def verify(self): def verify(self):
# avoid throwing exception in assertion
assert self.stdout is not None
assert self.stderr is not None
assert self.returncode == 0 assert self.returncode == 0
assert len(self.stdout) > 0 assert len(self.stdout) > 0
assert len(self.stderr) == 0 assert len(self.stderr) == 0