[svn r63040] try harder to record and auto-exit gateways after test runs
--HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									ee52739b17
								
							
						
					
					
						commit
						941d06e509
					
				|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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  | ||||||
|  | @ -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): | ||||||
|  |  | ||||||
|  | @ -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  | ||||||
|  |  | ||||||
|  | @ -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  | ||||||
|  |      | ||||||
|  | @ -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. """ | ||||||
|  |  | ||||||
|  | @ -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: | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue