[svn r63040] try harder to record and auto-exit gateways after test runs

--HG--
branch : trunk
This commit is contained in:
hpk 2009-03-18 16:51:55 +01:00
parent ee52739b17
commit 941d06e509
9 changed files with 94 additions and 4 deletions

View File

@ -330,6 +330,7 @@ class Gateway(object):
self._cleanup.unregister(self) self._cleanup.unregister(self)
self._stopexec() self._stopexec()
self._stopsend() self._stopsend()
py._com.pyplugins.notify("gateway_exit", self)
def _stopsend(self): def _stopsend(self):
self._send(None) self._send(None)

View File

@ -41,6 +41,7 @@ class InstallableGateway(gateway.Gateway):
super(InstallableGateway, self).__init__(io=io, _startcount=1) super(InstallableGateway, self).__init__(io=io, _startcount=1)
# XXX we dissallow execution form the other side # XXX we dissallow execution form the other side
self._initreceive(requestqueue=False) self._initreceive(requestqueue=False)
py._com.pyplugins.notify("gateway_init", self)
def _remote_bootstrap_gateway(self, io, extra=''): def _remote_bootstrap_gateway(self, io, extra=''):
""" return Gateway with a asynchronously remotely """ return Gateway with a asynchronously remotely

View File

@ -0,0 +1,11 @@
import py
pytest_plugins = "pytester"
class TestExecnetEvents:
def test_popengateway(self, eventrecorder):
gw = py.execnet.PopenGateway()
event = eventrecorder.popevent("gateway_init")
assert event.args[0] == gw
gw.exit()
event = eventrecorder.popevent("gateway_exit")
assert event.args[0] == gw

View File

@ -571,6 +571,9 @@ class TestSocketGateway(SocketGatewaySetup, BasicRemoteExecution):
class TestSshGateway(BasicRemoteExecution): class TestSshGateway(BasicRemoteExecution):
def setup_class(cls): def setup_class(cls):
sshhost = py.test.config.getvalueorskip("sshhost") sshhost = py.test.config.getvalueorskip("sshhost")
if sshhost.find(":") != -1:
sshhost = sshhost.split(":")[0]
cls.sshhost = sshhost
cls.gw = py.execnet.SshGateway(sshhost) cls.gw = py.execnet.SshGateway(sshhost)
def test_sshconfig_functional(self): def test_sshconfig_functional(self):
@ -578,7 +581,7 @@ class TestSshGateway(BasicRemoteExecution):
ssh_config = tmpdir.join("ssh_config") ssh_config = tmpdir.join("ssh_config")
ssh_config.write( ssh_config.write(
"Host alias123\n" "Host alias123\n"
" HostName %s\n" % (py.test.config.option.sshhost,)) " HostName %s\n" % self.sshhost)
gw = py.execnet.SshGateway("alias123", ssh_config=ssh_config) gw = py.execnet.SshGateway("alias123", ssh_config=ssh_config)
assert gw._cmd.find("-F") != -1 assert gw._cmd.find("-F") != -1
assert gw._cmd.find(str(ssh_config)) != -1 assert gw._cmd.find(str(ssh_config)) != -1
@ -586,7 +589,7 @@ class TestSshGateway(BasicRemoteExecution):
gw.exit() gw.exit()
def test_sshaddress(self): def test_sshaddress(self):
assert self.gw.remoteaddress == py.test.config.option.sshhost assert self.gw.remoteaddress == self.sshhost
@py.test.mark.xfail("XXX ssh-gateway error handling") @py.test.mark.xfail("XXX ssh-gateway error handling")
def test_connexion_failes_on_non_existing_hosts(self): def test_connexion_failes_on_non_existing_hosts(self):

View File

@ -11,7 +11,7 @@ Instance = py.test.collect.Instance
conf_iocapture = "fd" # overridable from conftest.py conf_iocapture = "fd" # overridable from conftest.py
# XXX resultlog should go, pypy's nightrun depends on it # XXX resultlog should go, pypy's nightrun depends on it
pytest_plugins = "default terminal xfail tmpdir resultlog monkeypatch".split() pytest_plugins = "default terminal xfail tmpdir execnetcleanup resultlog monkeypatch".split()
# =================================================== # ===================================================
# Distributed testing specific options # Distributed testing specific options

View File

@ -0,0 +1,53 @@
import py
class ExecnetcleanupPlugin:
_gateways = None
_debug = None
def pytest_configure(self, config):
self._debug = config.option.debug
def trace(self, msg, *args):
if self._debug:
print "[execnetcleanup %0x] %s %s" %(id(self), msg, args)
def pyevent_gateway_init(self, gateway):
self.trace("init", gateway)
if self._gateways is not None:
self._gateways.append(gateway)
def pyevent_gateway_exit(self, gateway):
self.trace("exit", gateway)
if self._gateways is not None:
self._gateways.remove(gateway)
def pyevent_testrunstart(self, event):
self.trace("testrunstart", event)
self._gateways = []
def pyevent_testrunfinish(self, event):
self.trace("testrunfinish", event)
l = []
for gw in self._gateways:
gw.exit()
l.append(gw)
for gw in l:
gw.join()
def test_generic(plugintester):
plugintester.apicheck(ExecnetcleanupPlugin)
@py.test.mark.xfail("clarify plugin registration/unregistration")
def test_execnetplugin(testdir):
p = ExecnetcleanupPlugin()
testdir.plugins.append(p)
testdir.inline_runsource("""
import py
import sys
def test_hello():
sys._gw = py.execnet.PopenGateway()
""", "-s", "--debug")
assert not p._gateways
assert py.std.sys._gw
py.test.raises(KeyError, "py.std.sys._gw.exit()") # already closed

View File

@ -155,8 +155,14 @@ class PytestPluginHooks:
def pyevent(self, eventname, *args, **kwargs): def pyevent(self, eventname, *args, **kwargs):
""" called for each testing event. """ """ called for each testing event. """
def pyevent_gateway_init(self, gateway):
""" called a gateway has been initialized. """
def pyevent_gateway_exit(self, gateway):
""" called when gateway is being exited. """
def pyevent_trace(self, category, msg): def pyevent_trace(self, category, msg):
""" called for tracing events events. """ """ called for tracing events. """
def pyevent_internalerror(self, event): def pyevent_internalerror(self, event):
""" called for internal errors. """ """ called for internal errors. """

View File

@ -21,6 +21,11 @@ class PytesterPlugin:
def pytest_pyfuncarg_EventRecorder(self, pyfuncitem): def pytest_pyfuncarg_EventRecorder(self, pyfuncitem):
return EventRecorder return EventRecorder
def pytest_pyfuncarg_eventrecorder(self, pyfuncitem):
evrec = EventRecorder(py._com.pyplugins)
pyfuncitem.addfinalizer(lambda: evrec.pyplugins.unregister(evrec))
return evrec
def test_generic(plugintester): def test_generic(plugintester):
plugintester.apicheck(PytesterPlugin) plugintester.apicheck(PytesterPlugin)
@ -245,6 +250,8 @@ class Event:
self.name = name self.name = name
self.args = args self.args = args
self.kwargs = kwargs self.kwargs = kwargs
def __repr__(self):
return "<Event %r %r>" %(self.name, self.args)
class EventRecorder(object): class EventRecorder(object):
def __init__(self, pyplugins, debug=False): # True): def __init__(self, pyplugins, debug=False): # True):
@ -260,6 +267,13 @@ class EventRecorder(object):
print "[event: %s]: %s **%s" %(name, ", ".join(map(str, args)), kwargs,) print "[event: %s]: %s **%s" %(name, ", ".join(map(str, args)), kwargs,)
self.events.append(Event(name, args, kwargs)) self.events.append(Event(name, args, kwargs))
def popevent(self, name):
for i, event in py.builtin.enumerate(self.events):
if event.name == name:
del self.events[i]
return event
raise KeyError("popevent: %r not found in %r" %(name, self.events))
def get(self, cls): def get(self, cls):
l = [] l = []
for event in self.events: for event in self.events:

View File

@ -95,6 +95,7 @@ class PytestPlugins(object):
config = self._config config = self._config
del self._config del self._config
self.pyplugins.call_each("pytest_unconfigure", config=config) self.pyplugins.call_each("pytest_unconfigure", config=config)
config.bus.unregister(self)
# #
# XXX old code to automatically load classes # XXX old code to automatically load classes