__init__.py
131 lines
| 4.4 KiB
| text/x-python
|
PythonLexer
MinRK
|
r3637 | """toplevel setup/teardown for parallel tests.""" | ||
Thomas Kluyver
|
r13348 | from __future__ import print_function | ||
MinRK
|
r3637 | |||
MinRK
|
r3664 | #------------------------------------------------------------------------------- | ||
# Copyright (C) 2011 The IPython Development Team | ||||
# | ||||
# Distributed under the terms of the BSD License. The full license is in | ||||
# the file COPYING, distributed as part of this software. | ||||
#------------------------------------------------------------------------------- | ||||
#------------------------------------------------------------------------------- | ||||
# Imports | ||||
#------------------------------------------------------------------------------- | ||||
MinRK
|
r3678 | import os | ||
MinRK
|
r3654 | import tempfile | ||
MinRK
|
r3595 | import time | ||
Thomas Kluyver
|
r12973 | from subprocess import Popen, PIPE, STDOUT | ||
import nose | ||||
MinRK
|
r3595 | |||
MinRK
|
r3678 | from IPython.utils.path import get_ipython_dir | ||
MinRK
|
r3673 | from IPython.parallel import Client | ||
MinRK
|
r3778 | from IPython.parallel.apps.launcher import (LocalProcessLauncher, | ||
ipengine_cmd_argv, | ||||
ipcontroller_cmd_argv, | ||||
MinRK
|
r6270 | SIGKILL, | ||
ProcessStateError, | ||||
) | ||||
MinRK
|
r3595 | |||
MinRK
|
r3778 | # globals | ||
launchers = [] | ||||
blackhole = open(os.devnull, 'w') | ||||
# Launcher class | ||||
class TestProcessLauncher(LocalProcessLauncher): | ||||
"""subclass LocalProcessLauncher, to prevent extra sockets and threads being created on Windows""" | ||||
def start(self): | ||||
if self.state == 'before': | ||||
self.process = Popen(self.args, | ||||
Thomas Kluyver
|
r13405 | stdout=nose.ipy_stream_capturer.writefd, stderr=STDOUT, | ||
MinRK
|
r3778 | env=os.environ, | ||
cwd=self.work_dir | ||||
) | ||||
self.notify_start(self.process.pid) | ||||
self.poll = self.process.poll | ||||
Thomas Kluyver
|
r12973 | # Store stdout & stderr to show with failing tests. | ||
# This is defined in IPython.testing.iptest | ||||
nose.ipy_stream_capturer.ensure_started() | ||||
MinRK
|
r3778 | else: | ||
s = 'The process was already started and has state: %r' % self.state | ||||
raise ProcessStateError(s) | ||||
MinRK
|
r3637 | |||
# nose setup/teardown | ||||
MinRK
|
r3595 | |||
def setup(): | ||||
MinRK
|
r4116 | cluster_dir = os.path.join(get_ipython_dir(), 'profile_iptest') | ||
engine_json = os.path.join(cluster_dir, 'security', 'ipcontroller-engine.json') | ||||
client_json = os.path.join(cluster_dir, 'security', 'ipcontroller-client.json') | ||||
for json in (engine_json, client_json): | ||||
if os.path.exists(json): | ||||
os.remove(json) | ||||
MinRK
|
r3778 | cp = TestProcessLauncher() | ||
cp.cmd_and_args = ipcontroller_cmd_argv + \ | ||||
Thomas Kluyver
|
r12973 | ['--profile=iptest', '--log-level=20', '--ping=250', '--dictdb'] | ||
MinRK
|
r3778 | cp.start() | ||
launchers.append(cp) | ||||
MinRK
|
r3680 | tic = time.time() | ||
while not os.path.exists(engine_json) or not os.path.exists(client_json): | ||||
if cp.poll() is not None: | ||||
MinRK
|
r12522 | raise RuntimeError("The test controller exited with status %s" % cp.poll()) | ||
MinRK
|
r6890 | elif time.time()-tic > 15: | ||
MinRK
|
r3680 | raise RuntimeError("Timeout waiting for the test controller to start.") | ||
MinRK
|
r3678 | time.sleep(0.1) | ||
MinRK
|
r3664 | add_engines(1) | ||
MinRK
|
r3595 | |||
MinRK
|
r6162 | def add_engines(n=1, profile='iptest', total=False): | ||
"""add a number of engines to a given profile. | ||||
If total is True, then already running engines are counted, and only | ||||
the additional engines necessary (if any) are started. | ||||
""" | ||||
MinRK
|
r3673 | rc = Client(profile=profile) | ||
MinRK
|
r3664 | base = len(rc) | ||
MinRK
|
r6162 | |||
if total: | ||||
n = max(n - base, 0) | ||||
MinRK
|
r3664 | eps = [] | ||
for i in range(n): | ||||
MinRK
|
r3778 | ep = TestProcessLauncher() | ||
MinRK
|
r9731 | ep.cmd_and_args = ipengine_cmd_argv + [ | ||
'--profile=%s' % profile, | ||||
'--log-level=50', | ||||
'--InteractiveShell.colors=nocolor' | ||||
] | ||||
MinRK
|
r3778 | ep.start() | ||
launchers.append(ep) | ||||
MinRK
|
r3664 | eps.append(ep) | ||
MinRK
|
r3680 | tic = time.time() | ||
MinRK
|
r3664 | while len(rc) < base+n: | ||
MinRK
|
r3680 | if any([ ep.poll() is not None for ep in eps ]): | ||
raise RuntimeError("A test engine failed to start.") | ||||
MinRK
|
r6890 | elif time.time()-tic > 15: | ||
MinRK
|
r3680 | raise RuntimeError("Timeout waiting for engines to connect.") | ||
MinRK
|
r3664 | time.sleep(.1) | ||
rc.spin() | ||||
rc.close() | ||||
return eps | ||||
MinRK
|
r3595 | |||
def teardown(): | ||||
time.sleep(1) | ||||
MinRK
|
r3778 | while launchers: | ||
p = launchers.pop() | ||||
MinRK
|
r3595 | if p.poll() is None: | ||
try: | ||||
MinRK
|
r3778 | p.stop() | ||
Matthias BUSSONNIER
|
r7787 | except Exception as e: | ||
Thomas Kluyver
|
r13348 | print(e) | ||
MinRK
|
r3595 | pass | ||
if p.poll() is None: | ||||
time.sleep(.25) | ||||
if p.poll() is None: | ||||
try: | ||||
Thomas Kluyver
|
r13348 | print('cleaning up test process...') | ||
MinRK
|
r3778 | p.signal(SIGKILL) | ||
MinRK
|
r3595 | except: | ||
Thomas Kluyver
|
r13348 | print("couldn't shutdown process: ", p) | ||
MinRK
|
r3778 | blackhole.close() | ||
MinRK
|
r3595 | |||