Blob Blame History Raw
From d9b41f72d4b2d545b2600aff7bd8a27ed0093750 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Wed, 29 May 2019 11:33:57 -0400
Subject: [PATCH 2/3] Parallelize the valgrind tests

This considerably reduces the time needed to perform the valgrind
memory tests on systems with multiple available processors. In the
case of my laptop, the duration was reduced from ~200s to 90s.

Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
---
 modulemd/common/tests/test-valgrind.py | 74 ++++++++++++++------------
 1 file changed, 41 insertions(+), 33 deletions(-)

diff --git a/modulemd/common/tests/test-valgrind.py b/modulemd/common/tests/test-valgrind.py
index 9be72c705fde79aa305d831eaa4f31f7e2cc663f..9349749658ccca0529776f3d534664d614c1cb4d 100644
--- a/modulemd/common/tests/test-valgrind.py
+++ b/modulemd/common/tests/test-valgrind.py
@@ -16,13 +16,16 @@ import os
 import sys
 import subprocess
 import tempfile
 import xml.etree.ElementTree as ET
 
+from multiprocessing import Pool, TimeoutError
+
 if os.getenv('MMD_SKIP_VALGRIND'):
     sys.exit(77)
 
+
 failed = False
 
 # Get the list of tests to run
 proc_result = subprocess.run(['meson', 'test', '--list'],
                              stdout=subprocess.PIPE,
@@ -47,13 +50,13 @@ for test in unfiltered_tests:
         test == 'test_dirty_repo' or
             test == 'valgrind'):
         continue
     tests.append(test)
 
+
 with tempfile.TemporaryDirectory(prefix="libmodulemd_valgrind_") as tmpdirname:
-    for test in tests:
-        # TODO: auto-detect the location of the suppression file
+    def exec_valgrind(test):
         valgrind_command = "/usr/bin/valgrind " \
                            "--leak-check=full " \
                            "--suppressions=/usr/share/glib-2.0/valgrind/glib.supp " \
                            "--xml=yes " \
                            "--xml-file=%s/%s.xml " % (tmpdirname, test)
@@ -64,45 +67,50 @@ with tempfile.TemporaryDirectory(prefix="libmodulemd_valgrind_") as tmpdirname:
                 '-t', '10',
                 '--logbase=%s' % test,
                 '--wrap=%s' % valgrind_command,
                 test])
 
-        if proc_result.returncode != 0:
-            print("Valgrind exited with an error on %s" % test,
-                  file=sys.stderr)
-            failed = True
-            continue
+        return proc_result.returncode, test
 
-        # Process the XML for leaks
-        tree = ET.parse('%s/%s.xml' % (tmpdirname, test))
-        root = tree.getroot()
+    with Pool() as pool:
+        for returncode, test in pool.map(exec_valgrind, tests):
+            if returncode != 0:
+                print("Valgrind exited with an error on %s" % test,
+                      file=sys.stderr)
+                failed = True
+                continue
 
-        for root_child in root:
-            if (root_child.tag == "error"):
-                for error_child in root_child:
-                    if error_child.tag == 'kind':
-                        if error_child.text == 'Leak_DefinitelyLost':
-                            print("Memory leak detected in %s" % test,
-                                  file=sys.stderr)
-                            failed = True
+            # Process the XML for leaks
+            tree = ET.parse('%s/%s.xml' % (tmpdirname, test))
+            root = tree.getroot()
 
-                        elif error_child.text == 'InvalidFree':
-                            print("Invalid free() detected in %s" % test,
-                                  file=sys.stderr)
-                            failed = True
+            for root_child in root:
+                if (root_child.tag == "error"):
+                    for error_child in root_child:
+                        if error_child.tag == 'kind':
+                            if error_child.text == 'Leak_DefinitelyLost':
+                                print("Memory leak detected in %s" % test,
+                                      file=sys.stderr)
+                                failed = True
 
-                        elif error_child.text == 'InvalidRead':
-                            print("Invalid read detected in %s" % test,
-                                  file=sys.stderr)
-                            failed = True
+                            elif error_child.text == 'InvalidFree':
+                                print("Invalid free() detected in %s" % test,
+                                      file=sys.stderr)
+                                failed = True
 
-                        elif error_child.text == 'UninitCondition':
-                            print("Uninitialized usage detected in %s" % test,
-                                  file=sys.stderr)
-                            failed = True
-        if failed:
-            with open('%s/%s.xml' % (tmpdirname, test), 'r') as xml:
-                print(xml.read())
+                            elif error_child.text == 'InvalidRead':
+                                print("Invalid read detected in %s" % test,
+                                      file=sys.stderr)
+                                failed = True
+
+                            elif error_child.text == 'UninitCondition':
+                                print(
+                                    "Uninitialized usage detected in %s" %
+                                    test, file=sys.stderr)
+                                failed = True
+            if failed:
+                with open('%s/%s.xml' % (tmpdirname, test), 'r') as xml:
+                    print(xml.read())
 
 
 if failed:
     sys.exit(1)
-- 
2.21.0