How to kill a socket in unit tests for reconnecting

I am trying to verify a code that reconnects to the server after disconnecting. This works fine outside of tests, but does not confirm that the socket is disconnected during tests.

I am using a Gevent Stream server to bully a real listening server:

import gevent.server from gevent import queue class TestServer(gevent.server.StreamServer): def __init__(self, *args, **kwargs): super(TestServer, self).__init__(*args, **kwargs) self.sockets = {} def handle(self, socket, address): self.sockets[address] = (socket, queue.Queue()) socket.sendall('testing the connection\r\n') gevent.spawn(self.recv, address) def recv(self, address): socket = self.sockets[address][0] queue = self.sockets[address][1] print 'Connection accepted %s:%d' % address try: for data in socket.recv(1024): queue.put(data) except: pass def murder(self): self.stop() for sock in self.sockets.iteritems(): print sock sock[1][0].shutdown(socket.SHUT_RDWR) sock[1][0].close() self.sockets = {} def run_server(): test_server = TestServer(('127.0.0.1', 10666)) test_server.start() return test_server 

And my test is as follows:

 def test_can_reconnect(self): test_server = run_server() client_config = {'host': '127.0.0.1', 'port': 10666} client = Connection('test client', client_config, get_config()) client.connect() assert client.socket_connected test_server.murder() #time.sleep(4) #tried sleeping. no dice. assert not client.socket_connected assert client.server_disconnect test_server = run_server() client.reconnect() assert client.socket_connected 

Cannot execute assert not client.socket_connected .

I detect "no data" during recv. If it is None, then I set some variables so that other code can decide whether to reconnect (do not reconnect if it was user_disconnect, etc.). This behavior has worked and always worked for me in the past, I just never tried to pass the test so far. Is there anything strange with socket connections and areas of local function or something else? it looks like the connection still exists even after the server stops.

The code I'm trying to verify is open: https://github.com/kyleterry/tenyks.git

If you run the tests, you will see the one I'm trying to fix.

+4
source share
4 answers

Trying to run unit test using a real socket is a tough line for a hoe. This will be difficult, since only one set of tests can run at a time, since the server port will be used, and it will be slow when the sockets are installed and demolished. To top it all off, if this is really a unit test, you don’t want to test a socket, just code that uses a socket.

If you mock socket calls, you can throw exceptions from inexperienced code and make sure that code using the socket does the right thing. You do not need a real socket to make sure that the tested class is working correctly, you can fake it if you can wrap socket calls in an object. Pass the link to the socket object when building your class, and you are ready to go.

My suggestion is to wrap socket calls in a class that supports sendall, recv, and all the methods you call on the socket. Then you can swap the real Socket class with TestReconnectSocket (or something else) and run your tests.

Take a look at mox , a fake python framework.

+2
source

The answer is fuzzy, but my immediate reaction will be that your recv () call blocks and keeps the socket alive - did you try to make a non-blocking socket and instead catch an error when closing?

0
source

One thing to keep in mind when testing such sockets is that operating systems do not like to reopen a socket shortly after using it. You can set the socket option to tell it to continue and reuse it. Immediately after creating the socket, set the socket parameter:

 mysocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 

Hope this solves your problem. You may have to do this both on the server side and on the client side, depending on which one gives you problems.

0
source
  • you call shutdown(socket.SHUT_RDWR) , so this doesn't seem like a recv lock issue.
  • however , you are using gevent.socket.socket.recv , so please check the version of gevent , there is a problem with recv() that causes it to block if the lower file descriptor is closed (version < v0.13.0 )
  • you may need gevent.sleep() to make shared income and give the client the option to exit the recv() call.
0
source

Source: https://habr.com/ru/post/1440168/


All Articles