summaryrefslogtreecommitdiff
path: root/tests/util.py
diff options
context:
space:
mode:
authorJustin Husted <sigstop@gmail.com>2019-11-03 00:35:03 -0700
committerKent Overstreet <kent.overstreet@gmail.com>2019-11-03 23:17:43 -0500
commit61bc316a4da4831d8812eb5051732cca27652d8d (patch)
tree3a7309c6010e5b918839319e7fc8140b2968687e /tests/util.py
parentd79d57ef89000f857158875055b977dbc54354da (diff)
Initial version of bcachefs tests.
So far, these tests just test basic format, fsck, and list functions under valgrind, as well as a few self-validation tests. Signed-off-by: Justin Husted <sigstop@gmail.com>
Diffstat (limited to 'tests/util.py')
-rw-r--r--tests/util.py71
1 files changed, 71 insertions, 0 deletions
diff --git a/tests/util.py b/tests/util.py
new file mode 100644
index 00000000..6eea103d
--- /dev/null
+++ b/tests/util.py
@@ -0,0 +1,71 @@
+#!/usr/bin/python3
+
+import os
+import re
+import subprocess
+import tempfile
+from pathlib import Path
+
+DIR = Path('..')
+BCH_PATH = DIR / 'bcachefs'
+
+VPAT = re.compile(r'ERROR SUMMARY: (\d+) errors from (\d+) contexts')
+
+class ValgrindFailedError(Exception):
+ def __init__(self, log):
+ self.log = log
+
+def check_valgrind(logfile):
+ log = logfile.read().decode('utf-8')
+ m = VPAT.search(log)
+ assert m is not None, 'Internal error: valgrind log did not match.'
+
+ errors = int(m.group(1))
+ if errors > 0:
+ raise ValgrindFailedError(log)
+
+def run(cmd, *args, valgrind=False, check=False):
+ """Run an external program via subprocess, optionally with valgrind.
+
+ This subprocess wrapper will capture the stdout and stderr. If valgrind is
+ requested, it will be checked for errors and raise a
+ ValgrindFailedError if there's a problem.
+ """
+ cmds = [cmd] + list(args)
+
+ if valgrind:
+ vout = tempfile.NamedTemporaryFile()
+ vcmd = ['valgrind',
+ '--leak-check=full',
+ '--log-file={}'.format(vout.name)]
+ cmds = vcmd + cmds
+
+ print("Running '{}'".format(cmds))
+ res = subprocess.run(cmds, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ encoding='utf-8', check=check)
+
+ if valgrind:
+ check_valgrind(vout)
+
+ return res
+
+def run_bch(*args, **kwargs):
+ """Wrapper to run the bcachefs binary specifically."""
+ cmds = [BCH_PATH] + list(args)
+ return run(*cmds, **kwargs)
+
+def sparse_file(lpath, size):
+ """Construct a sparse file of the specified size.
+
+ This is typically used to create device files for bcachefs.
+ """
+ path = Path(lpath)
+ f = path.touch(mode = 0o600, exist_ok = False)
+ os.truncate(path, size)
+
+ return path
+
+def device_1g(tmpdir):
+ """Default 1g sparse file for use with bcachefs."""
+ path = tmpdir / 'dev-1g'
+ return sparse_file(path, 1024**3)