[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Run asychronous tests in a subprocess
commit 4fe31c5fa8444fed4ccb2d5c47a5191ab0f1b730
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sun Jun 4 11:10:57 2017 -0700
Run asychronous tests in a subprocess
Fully parallelizing asynchronously run tests to avoid the GIL. This doesn't
have a noticeable impact on our installation runtime (it causes the install
test to be slower, but the overall runtime to be the same). That said, in
theory should benefit others. I'll probably experiment back and forth between
this and threads as we expand the tests which do this.
---
run_tests.py | 10 +++-------
stem/util/test_tools.py | 48 ++++++++++++++++++++++++++++++----------------
test/integ/installation.py | 9 ++++++---
3 files changed, 40 insertions(+), 27 deletions(-)
diff --git a/run_tests.py b/run_tests.py
index 49f8465..a174f65 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -232,6 +232,9 @@ def main():
skipped_tests = 0
+ if args.run_integ and (not args.specific_test or 'test.integ.installation'.startswith(args.specific_test)):
+ test.integ.installation.setup()
+
if args.run_unit:
test.output.print_divider('UNIT TESTS', True)
error_tracker.set_category('UNIT TEST')
@@ -251,10 +254,6 @@ def main():
our_version = stem.version.get_system_tor_version(args.tor_path)
skipped_targets = {}
- integ_setup_thread = None
-
- if not args.specific_test or 'test.integ.installation'.startswith(args.specific_test):
- integ_setup_thread = test.integ.installation.setup()
for target in args.run_targets:
# check if we meet this target's tor version prerequisites
@@ -286,9 +285,6 @@ def main():
# We should have joined on all threads. If not then that indicates a
# leak that could both likely be a bug and disrupt further targets.
- if integ_setup_thread:
- integ_setup_thread.join()
-
active_threads = threading.enumerate()
if len(active_threads) > 1:
diff --git a/stem/util/test_tools.py b/stem/util/test_tools.py
index c9912c0..47fc02a 100644
--- a/stem/util/test_tools.py
+++ b/stem/util/test_tools.py
@@ -30,6 +30,7 @@ to match just against the prefix or suffix. For instance...
import collections
import linecache
+import multiprocessing
import os
import re
import time
@@ -59,31 +60,44 @@ class AsyncTestResult(object):
Test results that can be applied later.
"""
- def __init__(self, runner):
- self._failure = None
- self._skip_reason = None
-
- def _wrapper():
+ def __init__(self, test_runner, *test_runner_args):
+ def _wrapper(conn, runner, args):
try:
- runner()
+ runner(*args) if args else runner()
+ conn.send(('success', None))
except AssertionError as exc:
- self._failure = str(exc)
+ conn.send(('failure', str(exc)))
except SkipTest as exc:
- self._skip_reason = str(exc)
+ conn.send(('skipped', str(exc)))
+ finally:
+ conn.close()
+
+ self._result_type, self._result_msg = None, None
+ self._result_lock = threading.RLock()
+ self._results_pipe, child_pipe = multiprocessing.Pipe()
+ self._test_process = multiprocessing.Process(target = _wrapper, args = (child_pipe, test_runner, test_runner_args))
+ self._test_process.start()
- self._thread = threading.Thread(target = _wrapper)
- self._thread.start()
+ def pid(self):
+ with self._result_lock:
+ return self._test_process.pid if self._test_process else None
def join(self):
- self._thread.join()
+ self.result(None)
def result(self, test):
- self.join()
-
- if self._failure:
- test.fail(self._failure)
- elif self._skip_reason:
- test.skipTest(self._skip_reason)
+ with self._result_lock:
+ if self._test_process:
+ self._result_type, self._result_msg = self._results_pipe.recv()
+ self._test_process.join()
+ self._test_process = None
+
+ if not test:
+ return
+ elif self._result_type == 'failure':
+ test.fail(self._result_msg)
+ elif self._result_type == 'skipped':
+ test.skipTest(self._result_msg)
class Issue(collections.namedtuple('Issue', ['line_number', 'message', 'line'])):
diff --git a/test/integ/installation.py b/test/integ/installation.py
index da918a4..8b39e9d 100644
--- a/test/integ/installation.py
+++ b/test/integ/installation.py
@@ -7,6 +7,7 @@ import os
import shutil
import sys
import tarfile
+import time
import unittest
import stem
@@ -29,7 +30,7 @@ def setup():
global TEST_INSTALL, TEST_SDIST
TEST_INSTALL = stem.util.test_tools.AsyncTestResult(_test_install)
- TEST_SDIST = stem.util.test_tools.AsyncTestResult(_test_sdist)
+ TEST_SDIST = stem.util.test_tools.AsyncTestResult(_test_sdist, TEST_INSTALL.pid())
def _test_install():
@@ -56,8 +57,10 @@ def _test_install():
shutil.rmtree(BASE_INSTALL_PATH)
-def _test_sdist():
- TEST_INSTALL.join() # we need to run these tests serially
+def _test_sdist(dependency_pid):
+ while stem.util.system.is_running(dependency_pid):
+ time.sleep(0.1) # we need to run these tests serially
+
git_dir = os.path.join(test.STEM_BASE, '.git')
if not stem.util.system.is_available('git'):
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits