forked from goodboy/tractor
Merge pull request #63 from chrizzFTD/update_tests_for_windows
Update tests for windowspropagate_loglevel
commit
29ffbfe6ca
|
@ -34,5 +34,6 @@ def pytest_generate_tests(metafunc):
|
||||||
if 'start_method' in metafunc.fixturenames:
|
if 'start_method' in metafunc.fixturenames:
|
||||||
from multiprocessing import get_all_start_methods
|
from multiprocessing import get_all_start_methods
|
||||||
methods = get_all_start_methods()
|
methods = get_all_start_methods()
|
||||||
|
if 'fork' in methods: # fork not available on windows, so check before removing
|
||||||
methods.remove('fork')
|
methods.remove('fork')
|
||||||
metafunc.parametrize("start_method", methods, scope='module')
|
metafunc.parametrize("start_method", methods, scope='module')
|
||||||
|
|
|
@ -45,13 +45,15 @@ async def hi():
|
||||||
|
|
||||||
|
|
||||||
async def say_hello(other_actor):
|
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:
|
async with tractor.find_actor(other_actor) as portal:
|
||||||
|
assert portal is not None
|
||||||
return await portal.run(__name__, 'hi')
|
return await portal.run(__name__, 'hi')
|
||||||
|
|
||||||
|
|
||||||
async def say_hello_use_wait(other_actor):
|
async def say_hello_use_wait(other_actor):
|
||||||
async with tractor.wait_for_actor(other_actor) as portal:
|
async with tractor.wait_for_actor(other_actor) as portal:
|
||||||
|
assert portal is not None
|
||||||
result = await portal.run(__name__, 'hi')
|
result = await portal.run(__name__, 'hi')
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,19 @@ import subprocess
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import tractor
|
import tractor
|
||||||
|
import platform
|
||||||
from conftest import tractor_test
|
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):
|
def sig_prog(proc, sig):
|
||||||
"Kill the actor-process with ``sig``."
|
"Kill the actor-process with ``sig``."
|
||||||
|
@ -18,8 +29,7 @@ def sig_prog(proc, sig):
|
||||||
if not proc.poll():
|
if not proc.poll():
|
||||||
# TODO: why sometimes does SIGINT not work on teardown?
|
# TODO: why sometimes does SIGINT not work on teardown?
|
||||||
# seems to happen only when trace logging enabled?
|
# seems to happen only when trace logging enabled?
|
||||||
proc.send_signal(signal.SIGKILL)
|
proc.send_signal(_KILL_SIGNAL)
|
||||||
|
|
||||||
ret = proc.wait()
|
ret = proc.wait()
|
||||||
assert ret
|
assert ret
|
||||||
|
|
||||||
|
@ -33,24 +43,32 @@ def daemon(loglevel, testdir, arb_addr):
|
||||||
arb_addr,
|
arb_addr,
|
||||||
"'{}'".format(loglevel) if loglevel else None)
|
"'{}'".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(
|
proc = testdir.popen(
|
||||||
cmdargs,
|
cmdargs,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
|
**kwargs,
|
||||||
)
|
)
|
||||||
assert not proc.returncode
|
assert not proc.returncode
|
||||||
wait = 0.6 if sys.version_info < (3, 7) else 0.4
|
wait = 0.6 if sys.version_info < (3, 7) else 0.4
|
||||||
time.sleep(wait)
|
time.sleep(wait)
|
||||||
yield proc
|
yield proc
|
||||||
sig_prog(proc, signal.SIGINT)
|
sig_prog(proc, _INT_SIGNAL)
|
||||||
|
|
||||||
|
|
||||||
def test_abort_on_sigint(daemon):
|
def test_abort_on_sigint(daemon):
|
||||||
assert daemon.returncode is None
|
assert daemon.returncode is None
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
sig_prog(daemon, signal.SIGINT)
|
sig_prog(daemon, _INT_SIGNAL)
|
||||||
assert daemon.returncode == 1
|
assert daemon.returncode == _INT_RETURN_CODE
|
||||||
# XXX: oddly, couldn't get capfd.readouterr() to work here?
|
# XXX: oddly, couldn't get capfd.readouterr() to work here?
|
||||||
|
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())
|
assert "KeyboardInterrupt" in str(daemon.stderr.read())
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,9 @@ def try_set_start_method(name: str) -> mp.context.BaseContext:
|
||||||
global _ctx
|
global _ctx
|
||||||
|
|
||||||
allowed = mp.get_all_start_methods()
|
allowed = mp.get_all_start_methods()
|
||||||
assert name in allowed
|
|
||||||
|
|
||||||
if name not in allowed:
|
if name not in allowed:
|
||||||
name == 'spawn'
|
name = 'spawn'
|
||||||
elif name == 'fork':
|
elif name == 'fork':
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"`fork` is unsupported due to incompatibility with `trio`"
|
"`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':
|
elif name == 'forkserver':
|
||||||
_forkserver_hackzorz.override_stdlib()
|
_forkserver_hackzorz.override_stdlib()
|
||||||
|
|
||||||
|
assert name in allowed
|
||||||
|
|
||||||
_ctx = mp.get_context(name)
|
_ctx = mp.get_context(name)
|
||||||
return _ctx
|
return _ctx
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue