From efffca371a47e4266e262d49e940ab991f148057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=B3pez=20Barr=C3=B3n?= Date: Sat, 9 Mar 2019 16:45:55 +1100 Subject: [PATCH 1/4] pytest_generate_tests remove `fork` only if it's in list --- tests/conftest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 1e46da3..2da68f7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -34,5 +34,6 @@ def pytest_generate_tests(metafunc): if 'start_method' in metafunc.fixturenames: from multiprocessing import get_all_start_methods methods = get_all_start_methods() - methods.remove('fork') + if 'fork' in methods: # fork not available on windows, so check before removing + methods.remove('fork') metafunc.parametrize("start_method", methods, scope='module') From b992dc19e31d539dec7365d1a47501f7a582ae61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=B3pez=20Barr=C3=B3n?= Date: Sat, 9 Mar 2019 18:42:51 +1100 Subject: [PATCH 2/4] moved assert statement for name on try_set_start_method after its autoset --- tractor/_spawn.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tractor/_spawn.py b/tractor/_spawn.py index 859cc4e..2d8a4bf 100644 --- a/tractor/_spawn.py +++ b/tractor/_spawn.py @@ -24,10 +24,9 @@ def try_set_start_method(name: str) -> mp.context.BaseContext: global _ctx allowed = mp.get_all_start_methods() - assert name in allowed if name not in allowed: - name == 'spawn' + name = 'spawn' elif name == 'fork': raise ValueError( "`fork` is unsupported due to incompatibility with `trio`" @@ -35,6 +34,8 @@ def try_set_start_method(name: str) -> mp.context.BaseContext: elif name == 'forkserver': _forkserver_hackzorz.override_stdlib() + assert name in allowed + _ctx = mp.get_context(name) return _ctx From 2138d55a60488feb4c83c6f56db15cec66f68ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=B3pez=20Barr=C3=B3n?= Date: Sat, 9 Mar 2019 18:43:17 +1100 Subject: [PATCH 3/4] increased trio.sleep time for other actors to spawn --- tests/test_discovery.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_discovery.py b/tests/test_discovery.py index 238633f..8a217dd 100644 --- a/tests/test_discovery.py +++ b/tests/test_discovery.py @@ -45,13 +45,15 @@ async def hi(): async def say_hello(other_actor): - await trio.sleep(0.4) # wait for other actor to spawn + await trio.sleep(1) # wait for other actor to spawn async with tractor.find_actor(other_actor) as portal: + assert portal is not None return await portal.run(__name__, 'hi') async def say_hello_use_wait(other_actor): async with tractor.wait_for_actor(other_actor) as portal: + assert portal is not None result = await portal.run(__name__, 'hi') return result From 5fc51fd7455dffb4ab101af9fdd8d3e37cb97567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=B3pez=20Barr=C3=B3n?= Date: Sun, 10 Mar 2019 14:48:50 +1100 Subject: [PATCH 4/4] multi_program signal for windows missing SIGKILL, SIGINT --- tests/test_multi_program.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/tests/test_multi_program.py b/tests/test_multi_program.py index 299a698..f68e3ac 100644 --- a/tests/test_multi_program.py +++ b/tests/test_multi_program.py @@ -8,8 +8,19 @@ import subprocess import pytest import tractor +import platform from conftest import tractor_test +# Sending signal.SIGINT on subprocess fails on windows. Use CTRL_* alternatives +if platform.system() == 'Windows': + _KILL_SIGNAL = signal.CTRL_BREAK_EVENT + _INT_SIGNAL = signal.CTRL_C_EVENT + _INT_RETURN_CODE = 3221225786 +else: + _KILL_SIGNAL = signal.SIGKILL + _INT_SIGNAL = signal.SIGINT + _INT_RETURN_CODE = 1 + def sig_prog(proc, sig): "Kill the actor-process with ``sig``." @@ -18,8 +29,7 @@ def sig_prog(proc, sig): if not proc.poll(): # TODO: why sometimes does SIGINT not work on teardown? # seems to happen only when trace logging enabled? - proc.send_signal(signal.SIGKILL) - + proc.send_signal(_KILL_SIGNAL) ret = proc.wait() assert ret @@ -33,25 +43,33 @@ def daemon(loglevel, testdir, arb_addr): arb_addr, "'{}'".format(loglevel) if loglevel else None) ] + kwargs = dict() + if platform.system() == 'Windows': + # without this, tests hang on windows forever + kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP + proc = testdir.popen( cmdargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + **kwargs, ) assert not proc.returncode wait = 0.6 if sys.version_info < (3, 7) else 0.4 time.sleep(wait) yield proc - sig_prog(proc, signal.SIGINT) + sig_prog(proc, _INT_SIGNAL) def test_abort_on_sigint(daemon): assert daemon.returncode is None time.sleep(0.1) - sig_prog(daemon, signal.SIGINT) - assert daemon.returncode == 1 + sig_prog(daemon, _INT_SIGNAL) + assert daemon.returncode == _INT_RETURN_CODE # XXX: oddly, couldn't get capfd.readouterr() to work here? - assert "KeyboardInterrupt" in str(daemon.stderr.read()) + if platform.system() != 'Windows': + # don't check stderr on windows as its empty when sending CTRL_C_EVENT + assert "KeyboardInterrupt" in str(daemon.stderr.read()) @tractor_test