* moving execnet tests to funcarg-style, some cleanup
* slight refinement to FAQ license topic --HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									f9eadc6440
								
							
						
					
					
						commit
						b70c7a209d
					
				
							
								
								
									
										30
									
								
								doc/faq.txt
								
								
								
								
							
							
						
						
									
										30
									
								
								doc/faq.txt
								
								
								
								
							|  | @ -51,7 +51,7 @@ have no counterpart in nose_. | |||
| Why did you choose a GPL-style license?  | ||||
| ---------------------------------------- | ||||
| 
 | ||||
| Older versions of the py lib and (up until 1.0.x)  | ||||
| Older versions of the py lib and py.test (up until 1.0.x)  | ||||
| were licensed under the MIT license.  Starting | ||||
| with the 1.1 series Holger Krekel - being the main maintainer | ||||
| and developer since several years - decided to go for  | ||||
|  | @ -66,23 +66,25 @@ a GPL-style license mainly for these reasons: | |||
| Developers want to co-operate no matter what context they | ||||
| are in, commercial, free, whatever.  BSD-licenses sound like | ||||
| a fit because they minimize the need for checking for  | ||||
| constraints from the company or legal department.  | ||||
| constraints from the company or legal department. They allow | ||||
| to use and modify software for whatever purpose.  | ||||
| 
 | ||||
| Developers wanting to produce free software for a living also | ||||
| want to connect to a sustainable revenue system, however.  When  | ||||
| releasing software for public use they want to seek means,  | ||||
| some security on getting something back: Contributions,  | ||||
| recognition or money.  The GPL license tries to foster a  | ||||
| universe of free software and force proprietary players  | ||||
| to contribute back.   | ||||
| However, developers wanting to produce free software for a living  | ||||
| often need to connect to a sustainable revenue system.  When  | ||||
| releasing software for public use they seek means, some security  | ||||
| on getting something back: Contributions, recognition or money.   | ||||
| The GPL license tries to foster a universe of free software and  | ||||
| force proprietary players to contribute back.   | ||||
| 
 | ||||
| Choosing the Lesser GPL kind of strikes a balance - it allows | ||||
| the code to interact in proprietary contexts but increases | ||||
| likelyness of flow backs.  Practically it all does not make  | ||||
| much of a difference.  Anyway, if you do have actual practical  | ||||
| issues regarding the license please just get in contact.   | ||||
| The py lib choose the Lesser GPL.  It strikes a balance because it | ||||
| allows the code to interact in proprietary contexts and increases | ||||
| likelyness of flow backs.    | ||||
| 
 | ||||
| If you do have or get actual practical issues regarding  | ||||
| licensing please get in contact_.   | ||||
| 
 | ||||
| .. _fsf: http://www.fsf.org | ||||
| .. _contact: contact.html | ||||
| 
 | ||||
| What's all this "magic" with py.test?  | ||||
| ---------------------------------------- | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| import sys, os, inspect, socket, atexit, weakref | ||||
| import py | ||||
| from subprocess import Popen, PIPE | ||||
| from py.__.execnet.gateway_base import BaseGateway, Message, Popen2IO, SocketIO | ||||
| from py.__.execnet.gateway_base import ExecnetAPI | ||||
| 
 | ||||
|  | @ -196,6 +195,7 @@ channel.send(dict( | |||
| 
 | ||||
| class PopenCmdGateway(InitiatingGateway): | ||||
|     def __init__(self, args): | ||||
|         from subprocess import Popen, PIPE | ||||
|         self._popen = p = Popen(args, stdin=PIPE, stdout=PIPE)  | ||||
|         io = Popen2IO(p.stdin, p.stdout) | ||||
|         super(PopenCmdGateway, self).__init__(io=io) | ||||
|  |  | |||
|  | @ -1,34 +1,27 @@ | |||
| from __future__ import generators | ||||
| """ | ||||
| mostly functional tests of gateways. | ||||
| """ | ||||
| import os, sys, time | ||||
| import py | ||||
| from py.__.execnet import gateway_base, gateway | ||||
| queue = py.builtin._tryimport('queue', 'Queue') | ||||
| 
 | ||||
| pytest_plugins = "pytester" | ||||
| 
 | ||||
| TESTTIMEOUT = 10.0 # seconds | ||||
|          | ||||
| class PopenGatewayTestSetup: | ||||
|     def setup_class(cls): | ||||
|         cls.gw = py.execnet.PopenGateway() | ||||
| class TestBasicRemoteExecution: | ||||
|     def test_correct_setup(self, gw): | ||||
|         assert gw._receiverthread.isAlive() | ||||
| 
 | ||||
|     #def teardown_class(cls): | ||||
|     #    cls.gw.exit() | ||||
|     def test_repr_doesnt_crash(self, gw): | ||||
|         assert isinstance(repr(gw), str) | ||||
| 
 | ||||
| class BasicRemoteExecution: | ||||
|     def test_correct_setup(self): | ||||
|         assert self.gw._receiverthread.isAlive() | ||||
| 
 | ||||
|     def test_repr_doesnt_crash(self): | ||||
|         assert isinstance(repr(self.gw), str) | ||||
| 
 | ||||
|     def test_attribute__name__(self): | ||||
|         channel = self.gw.remote_exec("channel.send(__name__)") | ||||
|     def test_attribute__name__(self, gw): | ||||
|         channel = gw.remote_exec("channel.send(__name__)") | ||||
|         name = channel.receive() | ||||
|         assert name == "__channelexec__"  | ||||
| 
 | ||||
|     def test_correct_setup_no_py(self): | ||||
|         channel = self.gw.remote_exec(""" | ||||
|     def test_correct_setup_no_py(self, gw): | ||||
|         channel = gw.remote_exec(""" | ||||
|             import sys | ||||
|             channel.send(list(sys.modules)) | ||||
|         """)  | ||||
|  | @ -36,25 +29,25 @@ class BasicRemoteExecution: | |||
|         assert 'py' not in remotemodules, ( | ||||
|                 "py should not be imported on remote side")  | ||||
| 
 | ||||
|     def test_remote_exec_waitclose(self): | ||||
|         channel = self.gw.remote_exec('pass') | ||||
|     def test_remote_exec_waitclose(self, gw): | ||||
|         channel = gw.remote_exec('pass') | ||||
|         channel.waitclose(TESTTIMEOUT) | ||||
| 
 | ||||
|     def test_remote_exec_waitclose_2(self): | ||||
|         channel = self.gw.remote_exec('def gccycle(): pass') | ||||
|     def test_remote_exec_waitclose_2(self, gw): | ||||
|         channel = gw.remote_exec('def gccycle(): pass') | ||||
|         channel.waitclose(TESTTIMEOUT) | ||||
| 
 | ||||
|     def test_remote_exec_waitclose_noarg(self): | ||||
|         channel = self.gw.remote_exec('pass') | ||||
|     def test_remote_exec_waitclose_noarg(self, gw): | ||||
|         channel = gw.remote_exec('pass') | ||||
|         channel.waitclose() | ||||
| 
 | ||||
|     def test_remote_exec_error_after_close(self): | ||||
|         channel = self.gw.remote_exec('pass') | ||||
|     def test_remote_exec_error_after_close(self, gw): | ||||
|         channel = gw.remote_exec('pass') | ||||
|         channel.waitclose(TESTTIMEOUT) | ||||
|         py.test.raises(IOError, channel.send, 0) | ||||
| 
 | ||||
|     def test_remote_exec_channel_anonymous(self): | ||||
|         channel = self.gw.remote_exec(''' | ||||
|     def test_remote_exec_channel_anonymous(self, gw): | ||||
|         channel = gw.remote_exec(''' | ||||
|            obj = channel.receive() | ||||
|            channel.send(obj) | ||||
|         ''') | ||||
|  | @ -62,37 +55,38 @@ class BasicRemoteExecution: | |||
|         result = channel.receive() | ||||
|         assert result == 42 | ||||
| 
 | ||||
|     def test_channel_close_and_then_receive_error(self): | ||||
|         channel = self.gw.remote_exec('raise ValueError') | ||||
| class TestChannelBasicBehaviour: | ||||
|     def test_channel_close_and_then_receive_error(self, gw): | ||||
|         channel = gw.remote_exec('raise ValueError') | ||||
|         py.test.raises(channel.RemoteError, channel.receive) | ||||
| 
 | ||||
|     def test_channel_finish_and_then_EOFError(self): | ||||
|         channel = self.gw.remote_exec('channel.send(42)')  | ||||
|     def test_channel_finish_and_then_EOFError(self, gw): | ||||
|         channel = gw.remote_exec('channel.send(42)')  | ||||
|         x = channel.receive() | ||||
|         assert x == 42 | ||||
|         py.test.raises(EOFError, channel.receive)  | ||||
|         py.test.raises(EOFError, channel.receive)  | ||||
|         py.test.raises(EOFError, channel.receive)  | ||||
| 
 | ||||
|     def test_channel_close_and_then_receive_error_multiple(self): | ||||
|         channel = self.gw.remote_exec('channel.send(42) ; raise ValueError') | ||||
|     def test_channel_close_and_then_receive_error_multiple(self, gw): | ||||
|         channel = gw.remote_exec('channel.send(42) ; raise ValueError') | ||||
|         x = channel.receive() | ||||
|         assert x == 42 | ||||
|         py.test.raises(channel.RemoteError, channel.receive) | ||||
| 
 | ||||
|     def test_channel__local_close(self): | ||||
|         channel = self.gw._channelfactory.new() | ||||
|         self.gw._channelfactory._local_close(channel.id) | ||||
|     def test_channel__local_close(self, gw): | ||||
|         channel = gw._channelfactory.new() | ||||
|         gw._channelfactory._local_close(channel.id) | ||||
|         channel.waitclose(0.1) | ||||
| 
 | ||||
|     def test_channel__local_close_error(self): | ||||
|         channel = self.gw._channelfactory.new() | ||||
|         self.gw._channelfactory._local_close(channel.id, | ||||
|     def test_channel__local_close_error(self, gw): | ||||
|         channel = gw._channelfactory.new() | ||||
|         gw._channelfactory._local_close(channel.id, | ||||
|                                             channel.RemoteError("error")) | ||||
|         py.test.raises(channel.RemoteError, channel.waitclose, 0.01) | ||||
| 
 | ||||
|     def test_channel_error_reporting(self): | ||||
|         channel = self.gw.remote_exec('def foo():\n  return foobar()\nfoo()\n') | ||||
|     def test_channel_error_reporting(self, gw): | ||||
|         channel = gw.remote_exec('def foo():\n  return foobar()\nfoo()\n') | ||||
|         try: | ||||
|             channel.receive() | ||||
|         except channel.RemoteError: | ||||
|  | @ -103,9 +97,9 @@ class BasicRemoteExecution: | |||
|         else: | ||||
|             py.test.fail('No exception raised') | ||||
| 
 | ||||
|     def test_channel_syntax_error(self): | ||||
|     def test_channel_syntax_error(self, gw): | ||||
|         # missing colon | ||||
|         channel = self.gw.remote_exec('def foo()\n return 1\nfoo()\n') | ||||
|         channel = gw.remote_exec('def foo()\n return 1\nfoo()\n') | ||||
|         try: | ||||
|             channel.receive() | ||||
|         except channel.RemoteError: | ||||
|  | @ -113,16 +107,16 @@ class BasicRemoteExecution: | |||
|             assert str(e).startswith('Traceback (most recent call last):') | ||||
|             assert str(e).find('SyntaxError') > -1 | ||||
| 
 | ||||
|     def test_channel_iter(self): | ||||
|         channel = self.gw.remote_exec(""" | ||||
|     def test_channel_iter(self, gw): | ||||
|         channel = gw.remote_exec(""" | ||||
|               for x in range(3):  | ||||
|                 channel.send(x) | ||||
|         """)  | ||||
|         l = list(channel)  | ||||
|         assert l == [0, 1, 2] | ||||
| 
 | ||||
|     def test_channel_passing_over_channel(self): | ||||
|         channel = self.gw.remote_exec(''' | ||||
|     def test_channel_passing_over_channel(self, gw): | ||||
|         channel = gw.remote_exec(''' | ||||
|                     c = channel.gateway.newchannel() | ||||
|                     channel.send(c) | ||||
|                     c.send(42) | ||||
|  | @ -133,17 +127,17 @@ class BasicRemoteExecution: | |||
| 
 | ||||
|         # check that the both sides previous channels are really gone | ||||
|         channel.waitclose(TESTTIMEOUT) | ||||
|         #assert c.id not in self.gw._channelfactory | ||||
|         newchan = self.gw.remote_exec(''' | ||||
|         #assert c.id not in gw._channelfactory | ||||
|         newchan = gw.remote_exec(''' | ||||
|                     assert %d not in channel.gateway._channelfactory._channels | ||||
|                   ''' % (channel.id)) | ||||
|         newchan.waitclose(TESTTIMEOUT) | ||||
|         assert channel.id not in self.gw._channelfactory._channels | ||||
|         assert channel.id not in gw._channelfactory._channels | ||||
| 
 | ||||
|     def test_channel_receiver_callback(self):  | ||||
|     def test_channel_receiver_callback(self, gw):  | ||||
|         l = [] | ||||
|         #channel = self.gw.newchannel(receiver=l.append) | ||||
|         channel = self.gw.remote_exec(source=''' | ||||
|         #channel = gw.newchannel(receiver=l.append) | ||||
|         channel = gw.remote_exec(source=''' | ||||
|             channel.send(42) | ||||
|             channel.send(13) | ||||
|             channel.send(channel.gateway.newchannel()) | ||||
|  | @ -155,9 +149,9 @@ class BasicRemoteExecution: | |||
|         assert l[:2] == [42,13] | ||||
|         assert isinstance(l[2], channel.__class__)  | ||||
| 
 | ||||
|     def test_channel_callback_after_receive(self): | ||||
|     def test_channel_callback_after_receive(self, gw): | ||||
|         l = [] | ||||
|         channel = self.gw.remote_exec(source=''' | ||||
|         channel = gw.remote_exec(source=''' | ||||
|             channel.send(42) | ||||
|             channel.send(13) | ||||
|             channel.send(channel.gateway.newchannel()) | ||||
|  | @ -171,25 +165,25 @@ class BasicRemoteExecution: | |||
|         assert l[0] == 13 | ||||
|         assert isinstance(l[1], channel.__class__)  | ||||
| 
 | ||||
|     def test_waiting_for_callbacks(self): | ||||
|     def test_waiting_for_callbacks(self, gw): | ||||
|         l = [] | ||||
|         def callback(msg): | ||||
|             import time; time.sleep(0.2) | ||||
|             l.append(msg) | ||||
|         channel = self.gw.remote_exec(source=''' | ||||
|         channel = gw.remote_exec(source=''' | ||||
|             channel.send(42) | ||||
|             ''') | ||||
|         channel.setcallback(callback) | ||||
|         channel.waitclose(TESTTIMEOUT)  | ||||
|         assert l == [42] | ||||
| 
 | ||||
|     def test_channel_callback_stays_active(self): | ||||
|         self.check_channel_callback_stays_active(earlyfree=True) | ||||
|     def test_channel_callback_stays_active(self, gw): | ||||
|         self.check_channel_callback_stays_active(gw, earlyfree=True) | ||||
| 
 | ||||
|     def check_channel_callback_stays_active(self, earlyfree=True): | ||||
|     def check_channel_callback_stays_active(self, gw, earlyfree=True): | ||||
|         # with 'earlyfree==True', this tests the "sendonly" channel state. | ||||
|         l = [] | ||||
|         channel = self.gw.remote_exec(source=''' | ||||
|         channel = gw.remote_exec(source=''' | ||||
|             try: | ||||
|                 import thread | ||||
|             except ImportError: | ||||
|  | @ -203,7 +197,7 @@ class BasicRemoteExecution: | |||
|             thread.start_new_thread(producer, (channel2,)) | ||||
|             del channel2 | ||||
|             ''') | ||||
|         subchannel = self.gw.newchannel() | ||||
|         subchannel = gw.newchannel() | ||||
|         subchannel.setcallback(l.append) | ||||
|         channel.send(subchannel) | ||||
|         if earlyfree: | ||||
|  | @ -220,13 +214,14 @@ class BasicRemoteExecution: | |||
|         assert l == [0, 100, 200, 300, 400] | ||||
|         return subchannel | ||||
| 
 | ||||
|     def test_channel_callback_remote_freed(self): | ||||
|         channel = self.check_channel_callback_stays_active(earlyfree=False) | ||||
|         channel.waitclose(TESTTIMEOUT) # freed automatically at the end of producer() | ||||
|     def test_channel_callback_remote_freed(self, gw): | ||||
|         channel = self.check_channel_callback_stays_active(gw, earlyfree=False) | ||||
|         # freed automatically at the end of producer() | ||||
|         channel.waitclose(TESTTIMEOUT)  | ||||
| 
 | ||||
|     def test_channel_endmarker_callback(self): | ||||
|     def test_channel_endmarker_callback(self, gw): | ||||
|         l = [] | ||||
|         channel = self.gw.remote_exec(source=''' | ||||
|         channel = gw.remote_exec(source=''' | ||||
|             channel.send(42) | ||||
|             channel.send(13) | ||||
|             channel.send(channel.gateway.newchannel()) | ||||
|  | @ -239,9 +234,9 @@ class BasicRemoteExecution: | |||
|         assert isinstance(l[2], channel.__class__)  | ||||
|         assert l[3] == 999 | ||||
| 
 | ||||
|     def test_channel_endmarker_callback_error(self): | ||||
|     def test_channel_endmarker_callback_error(self, gw): | ||||
|         q = queue.Queue() | ||||
|         channel = self.gw.remote_exec(source=''' | ||||
|         channel = gw.remote_exec(source=''' | ||||
|             raise ValueError() | ||||
|         ''')  | ||||
|         channel.setcallback(q.put, endmarker=999) | ||||
|  | @ -252,20 +247,20 @@ class BasicRemoteExecution: | |||
|         assert str(err).find("ValueError") != -1 | ||||
| 
 | ||||
|     @py.test.mark.xfail | ||||
|     def test_remote_redirect_stdout(self):  | ||||
|     def test_remote_redirect_stdout(self, gw):  | ||||
|         out = py.io.TextIO()  | ||||
|         handle = self.gw._remote_redirect(stdout=out)  | ||||
|         c = self.gw.remote_exec("print 42") | ||||
|         handle = gw._remote_redirect(stdout=out)  | ||||
|         c = gw.remote_exec("print 42") | ||||
|         c.waitclose(TESTTIMEOUT) | ||||
|         handle.close()  | ||||
|         s = out.getvalue()  | ||||
|         assert s.strip() == "42"  | ||||
| 
 | ||||
|     @py.test.mark.xfail | ||||
|     def test_remote_exec_redirect_multi(self):  | ||||
|     def test_remote_exec_redirect_multi(self, gw):  | ||||
|         num = 3 | ||||
|         l = [[] for x in range(num)] | ||||
|         channels = [self.gw.remote_exec("print %d" % i,  | ||||
|         channels = [gw.remote_exec("print %d" % i,  | ||||
|                                         stdout=l[i].append) | ||||
|                         for i in range(num)] | ||||
|         for x in channels:  | ||||
|  | @ -277,8 +272,9 @@ class BasicRemoteExecution: | |||
|             s = subl[0] | ||||
|             assert s.strip() == str(i) | ||||
| 
 | ||||
|     def test_channel_file_write(self):  | ||||
|         channel = self.gw.remote_exec(""" | ||||
| class TestChannelFile: | ||||
|     def test_channel_file_write(self, gw):  | ||||
|         channel = gw.remote_exec(""" | ||||
|             f = channel.makefile()  | ||||
|             f.write("hello world\\n") | ||||
|             f.close()  | ||||
|  | @ -289,14 +285,14 @@ class BasicRemoteExecution: | |||
|         second = channel.receive()  | ||||
|         assert second == 42  | ||||
| 
 | ||||
|     def test_channel_file_write_error(self):  | ||||
|         channel = self.gw.remote_exec("pass")  | ||||
|     def test_channel_file_write_error(self, gw):  | ||||
|         channel = gw.remote_exec("pass")  | ||||
|         f = channel.makefile()  | ||||
|         channel.waitclose(TESTTIMEOUT) | ||||
|         py.test.raises(IOError, f.write, 'hello') | ||||
| 
 | ||||
|     def test_channel_file_proxyclose(self):  | ||||
|         channel = self.gw.remote_exec(""" | ||||
|     def test_channel_file_proxyclose(self, gw):  | ||||
|         channel = gw.remote_exec(""" | ||||
|             f = channel.makefile(proxyclose=True)  | ||||
|             f.write("hello world") | ||||
|             f.close()  | ||||
|  | @ -306,8 +302,8 @@ class BasicRemoteExecution: | |||
|         assert first.strip() == 'hello world'  | ||||
|         py.test.raises(EOFError, channel.receive) | ||||
| 
 | ||||
|     def test_channel_file_read(self):  | ||||
|         channel = self.gw.remote_exec(""" | ||||
|     def test_channel_file_read(self, gw):  | ||||
|         channel = gw.remote_exec(""" | ||||
|             f = channel.makefile(mode='r')  | ||||
|             s = f.read(2) | ||||
|             channel.send(s)  | ||||
|  | @ -320,16 +316,16 @@ class BasicRemoteExecution: | |||
|         assert s1 == "xy"  | ||||
|         assert s2 == "abcde" | ||||
| 
 | ||||
|     def test_channel_file_read_empty(self):  | ||||
|         channel = self.gw.remote_exec("pass")  | ||||
|     def test_channel_file_read_empty(self, gw):  | ||||
|         channel = gw.remote_exec("pass")  | ||||
|         f = channel.makefile(mode="r")  | ||||
|         s = f.read(3)  | ||||
|         assert s == "" | ||||
|         s = f.read(5)  | ||||
|         assert s == "" | ||||
| 
 | ||||
|     def test_channel_file_readline_remote(self):  | ||||
|         channel = self.gw.remote_exec(""" | ||||
|     def test_channel_file_readline_remote(self, gw):  | ||||
|         channel = gw.remote_exec(""" | ||||
|             channel.send('123\\n45') | ||||
|         """) | ||||
|         channel.waitclose(TESTTIMEOUT) | ||||
|  | @ -339,12 +335,12 @@ class BasicRemoteExecution: | |||
|         s = f.readline() | ||||
|         assert s == "45" | ||||
| 
 | ||||
|     def test_channel_makefile_incompatmode(self): | ||||
|         channel = self.gw.newchannel() | ||||
|     def test_channel_makefile_incompatmode(self, gw): | ||||
|         channel = gw.newchannel() | ||||
|         py.test.raises(ValueError, 'channel.makefile("rw")') | ||||
| 
 | ||||
|     def test_confusion_from_os_write_stdout(self): | ||||
|         channel = self.gw.remote_exec(""" | ||||
|     def test_confusion_from_os_write_stdout(self, gw): | ||||
|         channel = gw.remote_exec(""" | ||||
|             import os | ||||
|             os.write(1, 'confusion!'.encode('ascii')) | ||||
|             channel.send(channel.receive() * 6) | ||||
|  | @ -357,8 +353,8 @@ class BasicRemoteExecution: | |||
|         res = channel.receive() | ||||
|         assert res == 42 | ||||
| 
 | ||||
|     def test_confusion_from_os_write_stderr(self): | ||||
|         channel = self.gw.remote_exec(""" | ||||
|     def test_confusion_from_os_write_stderr(self, gw): | ||||
|         channel = gw.remote_exec(""" | ||||
|             import os | ||||
|             os.write(2, 'test'.encode('ascii')) | ||||
|             channel.send(channel.receive() * 6) | ||||
|  | @ -371,53 +367,44 @@ class BasicRemoteExecution: | |||
|         res = channel.receive() | ||||
|         assert res == 42 | ||||
| 
 | ||||
|     def test__rinfo(self): | ||||
|         rinfo = self.gw._rinfo() | ||||
|     def test__rinfo(self, gw): | ||||
|         rinfo = gw._rinfo() | ||||
|         assert rinfo.executable  | ||||
|         assert rinfo.cwd  | ||||
|         assert rinfo.version_info  | ||||
|         s = repr(rinfo)  | ||||
|         old = self.gw.remote_exec(""" | ||||
|         old = gw.remote_exec(""" | ||||
|             import os.path | ||||
|             cwd = os.getcwd() | ||||
|             channel.send(os.path.basename(cwd)) | ||||
|             os.chdir('..') | ||||
|         """).receive() | ||||
|         try: | ||||
|             rinfo2 = self.gw._rinfo() | ||||
|             rinfo2 = gw._rinfo() | ||||
|             assert rinfo2.cwd == rinfo.cwd | ||||
|             rinfo3 = self.gw._rinfo(update=True) | ||||
|             rinfo3 = gw._rinfo(update=True) | ||||
|             assert rinfo3.cwd != rinfo2.cwd | ||||
|         finally: | ||||
|             self.gw._cache_rinfo = rinfo | ||||
|             self.gw.remote_exec("import os ; os.chdir(%r)" % old).waitclose() | ||||
|             gw._cache_rinfo = rinfo | ||||
|             gw.remote_exec("import os ; os.chdir(%r)" % old).waitclose() | ||||
| 
 | ||||
| class BasicCmdbasedRemoteExecution(BasicRemoteExecution): | ||||
|     def test_cmdattr(self): | ||||
|         assert hasattr(self.gw, '_cmd') | ||||
| def test_join_blocked_execution_gateway():  | ||||
|     gateway = py.execnet.PopenGateway()  | ||||
|     channel = gateway.remote_exec(""" | ||||
|         time.sleep(5.0) | ||||
|     """) | ||||
|     def doit():  | ||||
|         gateway.exit()  | ||||
|         gateway.join(joinexec=True)  | ||||
|         return 17  | ||||
| 
 | ||||
| #class TestBlockingIssues:  | ||||
| #    def test_join_blocked_execution_gateway(self):  | ||||
| #        gateway = py.execnet.PopenGateway()  | ||||
| #        channel = gateway.remote_exec(""" | ||||
| #            time.sleep(5.0) | ||||
| #        """) | ||||
| #        def doit():  | ||||
| #            gateway.exit()  | ||||
| #            gateway.join(joinexec=True)  | ||||
| #            return 17  | ||||
| # | ||||
| #        pool = py._thread.WorkerPool()  | ||||
| #        reply = pool.dispatch(doit)  | ||||
| #        x = reply.get(timeout=1.0)  | ||||
| #        assert x == 17  | ||||
|     pool = py._thread.WorkerPool()  | ||||
|     reply = pool.dispatch(doit)  | ||||
|     x = reply.get(timeout=1.0)  | ||||
|     assert x == 17  | ||||
| 
 | ||||
| class TestPopenGateway(PopenGatewayTestSetup, BasicRemoteExecution): | ||||
|     def test_rinfo_popen(self): | ||||
|         rinfo = self.gw._rinfo() | ||||
|         assert rinfo.executable == py.std.sys.executable  | ||||
|         assert rinfo.cwd == py.std.os.getcwd() | ||||
|         assert rinfo.version_info == py.std.sys.version_info | ||||
| class TestPopenGateway: | ||||
|     gwtype = 'popen' | ||||
| 
 | ||||
|     def test_chdir_separation(self, tmpdir): | ||||
|         old = tmpdir.chdir() | ||||
|  | @ -454,6 +441,21 @@ class TestPopenGateway(PopenGatewayTestSetup, BasicRemoteExecution): | |||
|             ret = channel.receive() | ||||
|             assert ret == 42 | ||||
| 
 | ||||
|     def test_rinfo_popen(self, gw): | ||||
|         rinfo = gw._rinfo() | ||||
|         assert rinfo.executable == py.std.sys.executable  | ||||
|         assert rinfo.cwd == py.std.os.getcwd() | ||||
|         assert rinfo.version_info == py.std.sys.version_info | ||||
| 
 | ||||
|     def test_gateway_init_event(self, _pytest): | ||||
|         rec = _pytest.gethookrecorder(gateway_base.ExecnetAPI) | ||||
|         gw = py.execnet.PopenGateway() | ||||
|         call = rec.popcall("pyexecnet_gateway_init")  | ||||
|         assert call.gateway == gw | ||||
|         gw.exit() | ||||
|         call = rec.popcall("pyexecnet_gateway_exit") | ||||
|         assert call.gateway == gw | ||||
|              | ||||
|     @py.test.mark.xfail # "fix needed: dying remote process does not cause waitclose() to fail" | ||||
|     def test_waitclose_on_remote_killed(self): | ||||
|         gw = py.execnet.PopenGateway() | ||||
|  | @ -491,48 +493,35 @@ def test_endmarker_delivery_on_remote_killterm(): | |||
|     assert "15" in str(err) | ||||
| 
 | ||||
| 
 | ||||
| class SocketGatewaySetup: | ||||
|     def setup_class(cls): | ||||
|         # open a gateway to a fresh child process | ||||
|         cls.proxygw = py.execnet.PopenGateway()  | ||||
|         cls.gw = py.execnet.SocketGateway.new_remote(cls.proxygw, | ||||
|                                                      ("127.0.0.1", 0) | ||||
|                                                      )  | ||||
|     def test_host_not_found(self): | ||||
| def test_socket_gw_host_not_found(gw): | ||||
|     py.test.raises(py.execnet.HostNotFound,  | ||||
|             'py.execnet.SocketGateway("qowieuqowe", 9000)' | ||||
|     ) | ||||
| 
 | ||||
| ##    def teardown_class(cls): | ||||
| ##        cls.gw.exit() | ||||
| ##        cls.proxygw.exit() | ||||
| class TestSshPopenGateway: | ||||
|     gwtype = "ssh" | ||||
| 
 | ||||
| class TestSocketGateway(SocketGatewaySetup, BasicRemoteExecution): | ||||
|     pass | ||||
|     def test_sshconfig_config_parsing(self, monkeypatch): | ||||
|         import subprocess | ||||
|         l = [] | ||||
|         monkeypatch.setattr(subprocess, 'Popen',  | ||||
|             lambda *args, **kwargs: l.append(args[0])) | ||||
|         py.test.raises(AttributeError,   | ||||
|             """py.execnet.SshGateway("xyz", ssh_config='qwe')""") | ||||
|         assert len(l) == 1 | ||||
|         popen_args = l[0] | ||||
|         i = popen_args.index('-F') | ||||
|         assert popen_args[i+1] == "qwe" | ||||
| 
 | ||||
| class TestSshGateway(BasicRemoteExecution): | ||||
|     def setup_class(cls):  | ||||
|         from conftest import getspecssh | ||||
|         cls.sshhost = getspecssh().ssh | ||||
|         cls.gw = py.execnet.SshGateway(cls.sshhost) | ||||
|     def test_sshaddress(self, gw, specssh): | ||||
|         assert gw.remoteaddress == specssh.ssh | ||||
| 
 | ||||
|     def test_sshconfig_functional(self, tmpdir): | ||||
|         ssh_config = tmpdir.join("ssh_config")  | ||||
|         ssh_config.write( | ||||
|             "Host alias123\n" | ||||
|             "   HostName %s\n" % self.sshhost) | ||||
|         gw = py.execnet.SshGateway("alias123", ssh_config=ssh_config) | ||||
|         pid = gw.remote_exec("import os ; channel.send(os.getpid())").receive() | ||||
|         gw.exit() | ||||
| 
 | ||||
|     def test_sshaddress(self): | ||||
|         assert self.gw.remoteaddress == self.sshhost | ||||
| 
 | ||||
|     def test_connexion_failes_on_non_existing_hosts(self): | ||||
|     def test_host_not_found(self): | ||||
|         py.test.raises(py.execnet.HostNotFound,  | ||||
|             "py.execnet.SshGateway('nowhere.codespeak.net')") | ||||
| 
 | ||||
| def test_threads(): | ||||
| class TestThreads: | ||||
|     def test_threads(self): | ||||
|         gw = py.execnet.PopenGateway() | ||||
|         gw.remote_init_threads(3) | ||||
|         c1 = gw.remote_exec("channel.send(channel.receive())") | ||||
|  | @ -543,23 +532,12 @@ def test_threads(): | |||
|         c1.send(42) | ||||
|         res = c1.receive() | ||||
|         assert res == 42 | ||||
|     gw.exit() | ||||
| 
 | ||||
| def test_threads_twice(): | ||||
|     def test_threads_twice(self): | ||||
|         gw = py.execnet.PopenGateway() | ||||
|         gw.remote_init_threads(3) | ||||
|         py.test.raises(IOError, gw.remote_init_threads, 3) | ||||
|     gw.exit()  | ||||
| 
 | ||||
| class TestExecnetEvents: | ||||
|     def test_popengateway(self, _pytest): | ||||
|         rec = _pytest.gethookrecorder(gateway_base.ExecnetAPI) | ||||
|         gw = py.execnet.PopenGateway() | ||||
|         call = rec.popcall("pyexecnet_gateway_init")  | ||||
|         assert call.gateway == gw | ||||
|         gw.exit() | ||||
|         call = rec.popcall("pyexecnet_gateway_exit") | ||||
|         assert call.gateway == gw | ||||
| 
 | ||||
| def test_nodebug(): | ||||
|     from py.__.execnet import gateway_base | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue