]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - tests/util.py
Disable pristine-tar option in gbp.conf, since there is no pristine-tar branch.
[bcachefs-tools-debian] / tests / util.py
index a9e9746441dc3a9e60ffc3449dde9172518ad849..68fe9e950672a4824e3f3aba981578380a4e2dd8 100644 (file)
@@ -1,18 +1,19 @@
 #!/usr/bin/python3
 
+import errno
 import os
-import pytest
 import re
 import subprocess
-import sys
 import tempfile
 import threading
 import time
 
 from pathlib import Path
 
-DIR = Path('..')
-BCH_PATH = DIR / 'bcachefs'
+BASE_PATH= os.path.dirname(__file__)
+BCH_PATH = os.path.abspath(os.path.join(BASE_PATH, '../target/release', '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')
 
@@ -22,10 +23,14 @@ class ValgrindFailedError(Exception):
     def __init__(self, log):
         self.log = log
 
-def check_valgrind(logfile):
-    log = logfile.read().decode('utf-8')
+def check_valgrind(log):
     m = VPAT.search(log)
-    assert m is not None, 'Internal error: valgrind log did not match.'
+    if m is None:
+        print('Internal error: valgrind log did not match.')
+        print('-- valgrind log:')
+        print(log)
+        print('-- end log --')
+        assert False
 
     errors = int(m.group(1))
     if errors > 0:
@@ -41,19 +46,22 @@ def run(cmd, *args, valgrind=False, check=False):
     cmds = [cmd] + list(args)
     valgrind = valgrind and ENABLE_VALGRIND
 
+    print("Running '{}'".format(cmds))
     if valgrind:
         vout = tempfile.NamedTemporaryFile()
         vcmd = ['valgrind',
                '--leak-check=full',
+               '--gen-suppressions=all',
+               '--suppressions={}'.format(VALGRIND_PATH),
                '--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)
+        res = subprocess.run(cmds, stdout=subprocess.PIPE,
+                stderr=subprocess.PIPE, encoding='utf-8', check=check)
+        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
 
@@ -68,7 +76,7 @@ def sparse_file(lpath, size):
     This is typically used to create device files for bcachefs.
     """
     path = Path(lpath)
-    f = path.touch(mode = 0o600, exist_ok = False)
+    path.touch(mode = 0o600, exist_ok = False)
     os.truncate(path, size)
 
     return path
@@ -150,14 +158,16 @@ class BFuse:
     def run(self):
         """Background thread which runs "bcachefs fusemount" under valgrind"""
 
-        vout = None
+        vlog = None
         cmd = []
 
         if ENABLE_VALGRIND:
-            vout = tempfile.NamedTemporaryFile()
+            vlog = tempfile.NamedTemporaryFile()
             cmd += [ 'valgrind',
                      '--leak-check=full',
-                     '--log-file={}'.format(vout.name) ]
+                     '--gen-suppressions=all',
+                     '--suppressions=valgrind-suppressions.txt',
+                     '--log-file={}'.format(vlog.name) ]
 
         cmd += [ BCH_PATH,
                  'fusemount', '-f', self.dev, self.mnt]
@@ -175,10 +185,19 @@ class BFuse:
         (out2, _) = self.proc.communicate()
         print("Process exited.")
 
+        self.returncode = self.proc.returncode
+        if self.returncode == 0:
+            errors = [ 'btree iterators leaked!',
+                       'emergency read only!' ]
+            for e in errors:
+                if e in out2:
+                    print('Debug error found in output: "{}"'.format(e))
+                    self.returncode = errno.ENOMSG
+
         self.stdout = out1 + out2
         self.stderr = err.read()
-        self.returncode = self.proc.returncode
-        self.vout = vout
+        if vlog:
+            self.vout = vlog.read().decode('utf-8')
 
     def expect(self, pipe, regex):
         """Wait for the child process to mount."""
@@ -208,12 +227,16 @@ class BFuse:
     def unmount(self, timeout=None):
         print("Unmounting fuse.")
         run("fusermount3", "-zu", self.mnt)
-        print("Waiting for thread to exit.")
 
-        self.thread.join(timeout)
-        if self.thread.is_alive():
-            self.proc.kill()
-            self.thread.join()
+        if self.thread:
+            print("Waiting for thread to exit.")
+            self.thread.join(timeout)
+            if self.thread.is_alive():
+                if self.proc:
+                    self.proc.kill()
+                self.thread.join()
+        else:
+            print("Thread was already done.")
 
         self.thread = None
         self.ready.clear()
@@ -222,6 +245,9 @@ class BFuse:
             check_valgrind(self.vout)
 
     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 len(self.stdout) > 0
         assert len(self.stderr) == 0