aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2017-03-28 12:17:38 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2017-03-28 14:47:55 +0530
commit52e1b0a3c9097d3fc647785d3cee180de0272a5c (patch)
treee112f69eed4ec1e034a5d1c0484b983a3a68baec
parentffdb6fa0a7b909fb767260d4802f3dc53988a59d (diff)
downloadmeson-52e1b0a3c9097d3fc647785d3cee180de0272a5c.zip
meson-52e1b0a3c9097d3fc647785d3cee180de0272a5c.tar.gz
meson-52e1b0a3c9097d3fc647785d3cee180de0272a5c.tar.bz2
project tests: DummyExecutor for MSYS2 and OpenBSD
Added and tested on MSYS2/MinGW which doesn't implement the required semaphore locks in the multiprocessing module: Traceback (most recent call last): File "C:/msys64/mingw64/lib/python3.5\multiprocessing\synchronize.py", line 29, in <module> from _multiprocessing import SemLock, sem_unlink ImportError: cannot import name 'sem_unlink' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "run_project_tests.py", line 560, in <module> (passing_tests, failing_tests, skipped_tests) = run_tests(all_tests, 'meson-test-run', options.extra_args) File "run_project_tests.py", line 406, in run_tests executor = conc.ProcessPoolExecutor(max_workers=num_workers) File "F:/msys64/mingw64/lib/python3.5\concurrent\futures\process.py", line 390, in __init__ EXTRA_QUEUED_CALLS) File "F:/msys64/mingw64/lib/python3.5\multiprocessing\context.py", line 101, in Queue return Queue(maxsize, ctx=self.get_context()) File "F:/msys64/mingw64/lib/python3.5\multiprocessing\queues.py", line 42, in __init__ self._rlock = ctx.Lock() File "F:/msys64/mingw64/lib/python3.5\multiprocessing\context.py", line 65, in Lock from .synchronize import Lock File "F:/msys64/mingw64/lib/python3.5\multiprocessing\synchronize.py", line 34, in <module> " function, see issue 3770.") ImportError: This platform lacks a functioning sem_open implementation, therefore, the required synchronization primitives needed will not function, see issue 3770. See also: https://bugs.python.org/issue3770 https://github.com/mesonbuild/meson/issues/1323 According to 3770, the same problem also exists on OpenBSD, so this will potentially also be useful there.
-rwxr-xr-xrun_project_tests.py57
1 files changed, 56 insertions, 1 deletions
diff --git a/run_project_tests.py b/run_project_tests.py
index 3684de5..a487da2 100755
--- a/run_project_tests.py
+++ b/run_project_tests.py
@@ -34,6 +34,7 @@ import concurrent.futures as conc
from mesonbuild.coredata import backendlist
+
class BuildStep(Enum):
configure = 1
build = 2
@@ -41,6 +42,7 @@ class BuildStep(Enum):
install = 4
clean = 5
+
class TestResult:
def __init__(self, msg, step, stdo, stde, mlog, conftime=0, buildtime=0, testtime=0):
self.msg = msg
@@ -52,6 +54,54 @@ class TestResult:
self.buildtime = buildtime
self.testtime = testtime
+class DummyFuture(conc.Future):
+ '''
+ Dummy Future implementation that executes the provided function when you
+ ask for the result. Used on platforms where sem_open() is not available:
+ MSYS2, OpenBSD, etc: https://bugs.python.org/issue3770
+ '''
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ def set_function(self, fn, *args, **kwargs):
+ self.fn = fn
+ self.fn_args = args
+ self.fn_kwargs = kwargs
+
+ def result(self, **kwargs):
+ try:
+ result = self.fn(*self.fn_args, **self.fn_kwargs)
+ except BaseException as e:
+ self.set_exception(e)
+ else:
+ self.set_result(result)
+ return super().result(**kwargs)
+
+
+class DummyExecutor(conc.Executor):
+ '''
+ Dummy single-thread 'concurrent' executor for use on platforms where
+ sem_open is not available: https://bugs.python.org/issue3770
+ '''
+
+ def __init__(self):
+ from threading import Lock
+ self._shutdown = False
+ self._shutdownLock = Lock()
+
+ def submit(self, fn, *args, **kwargs):
+ with self._shutdownLock:
+ if self._shutdown:
+ raise RuntimeError('Cannot schedule new futures after shutdown')
+ f = DummyFuture()
+ f.set_function(fn, *args, **kwargs)
+ return f
+
+ def shutdown(self, wait=True):
+ with self._shutdownLock:
+ self._shutdown = True
+
+
class AutoDeletedDir:
def __init__(self, d):
self.dir = d
@@ -421,7 +471,11 @@ def run_tests(all_tests, log_name_base, extra_args):
print('Could not determine number of CPUs due to the following reason:' + str(e))
print('Defaulting to using only one process')
num_workers = 1
- executor = conc.ProcessPoolExecutor(max_workers=num_workers)
+ try:
+ executor = conc.ProcessPoolExecutor(max_workers=num_workers)
+ except ImportError:
+ print('Platform doesn\'t ProcessPoolExecutor, falling back to single-threaded testing\n')
+ executor = DummyExecutor()
for name, test_cases, skipped in all_tests:
current_suite = ET.SubElement(junit_root, 'testsuite', {'name': name, 'tests': str(len(test_cases))})
@@ -441,6 +495,7 @@ def run_tests(all_tests, log_name_base, extra_args):
result = executor.submit(run_test, skipped, t, extra_args, unity_flags + backend_flags, compile_commands, should_fail)
futures.append((testname, t, result))
for (testname, t, result) in futures:
+ sys.stdout.flush()
result = result.result()
if result is None or 'MESON_SKIP_TEST' in result.stdo:
print('Skipping:', t)