Mocked method socket.accept() is not called - python

I am trying to mock server side of socket. This example is not working and I don't know why (it still uses original socket.socket.accept() method).
Any ideas how to mock listening socket correctly?
class MySocket:
def __init__:
self.socket = socket.socket()
def listen(self):
self.socket.accept() # original socket method
class MockConn:
def recv(self, int):
return b''
def close(self):
pass
def sendall(self, str):
pass
with mock.patch('socket.socket') as mock_socket:
conn = MockConn()
mock_socket.return_value.accept.return_value = (conn, 'localhost')
s = MySocket(None)
s.listen() # this should call accept from the mock

Not sure what you want, but this works:
import socket
from unittest import mock
class MySocket:
def listen(self):
print('Accept result:', socket.socket().accept())
# Accept result: (<__main__.MockConn object at 0x000001E592B36B38>, 'localhost')
class MockConn:
def recv(self, int):
return b''
def close(self):
pass
def sendall(self, str):
pass
with mock.patch('socket.socket') as mock_socket:
conn = MockConn()
mock_socket.return_value.accept.return_value = (conn, 'localhost')
s = MySocket()
s.listen()

With some very minor changes to your current code this works:
from unittest import mock
import socket
class MySocket:
def __init__(self): # init takes self
self.socket = socket.socket()
def listen(self):
return self.socket.accept() # original socket method
class MockConn:
def recv(self, int):
return b''
def close(self):
pass
def sendall(self, str):
pass
with mock.patch('socket.socket') as mock_socket:
conn = MockConn()
mock_socket.return_value.accept.return_value = (conn, 'localhost')
s = MySocket()
print(s.listen()) # this should call accept from the mock
Output:
(<__main__.MockConn object at 0x00000255C5A53B00>, 'localhost')

Related

How I can check connection correctly

I have a boolean variable:
is_conected = False
And I have this part of code:
def start(self, host='localhost', port=32767):
self.__connection.bind((host, port))
self.__connection.listen(5)
def send_frame(self, frame: str):
if not self.__connection.send(bytes(frame, encoding='utf-8')):
raise RuntimeError("Connection broken.")
def recieve_frame(self) -> str:
socket, adress = self.__connection.accept()
str(__data) = socket.recv(1024)
__frame_buffer.append(__data)
Where I need to put If... Else, for checking, if someone connected or not? And what kind of condition I need to use?
The whole code:
import socket
class TCPServer():
__frame_buffer = list()
__connection = None
is_conected = True
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(TCPServer, cls).__new__(cls)
return cls.instance
def __init__(self):
self.__connection = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
def start(self, host='localhost', port=32767):
# """ Start server """
self.__connection.bind((host, port))
self.__connection.listen(5)
def send_frame(self, frame: str):
# """ Send frame """
if not self.__connection.send(bytes(frame, encoding='utf-8')):
raise RuntimeError("Connection broken.")
def recieve_frame(self) -> str:
socket, adress = self.__connection.accept()
str(__data) = socket.recv(1024)
__frame_buffer.append(__data)
def get_frame(self) -> str:
if self.__frame_buffer:
self.__frame_buffer.pop(0)
server = TCPServer()
while True:
if server.is_conected:
server.send_frame(str(input("String to send")))
print(server.get_frame())
That's the whole code. I don't write a more part of it, only a send and recieve frame function. So, that's kinda a school project for me and I'm not too good in working with any kind of connection or protocols
This is how the server generally works
with socket(AF_INET, SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen() # Start listening
while True:
conn, addr = s.accept() # Accept connection request
Connected = True # You are connected
try:
#Work with connection
except:
Connected = False
Figure out how you can do this with your code

Mocking socket.recv()

I want to mock the recv function of a socket and having trouble. Getting errors that I need to actually connect my socket even though I should not have to.
Here is all relevant code:
Class A:
def __init__.py(self):
self.s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
def connect(self):
self.s.connect((host,port))
def data_collection(self, d):
self.send_over_socket(self.cg.get_privilege_command())
self.send_over_socket(self.status_string)
buf = ""
while 1:
buf = buf + self.s.recv(self.BUFFER_SIZE).decode()
#Removed string manipulation below
self.publish(data from string manipulation)
def send_over_socket(self,data):
return (self.s.send(bytes(data.encode())))
Pytest code;
def test_data_collection():
with mock.patch('moduleA.classA.send_over_socket') as mock_send_over_socket:
A = classA()
A.send_over_socket.return_value = 1
with mock.patch('socket.socket') as mock_socket:
mock_socket.return_value.recv.decode.return_value = "packet_string"
with mock.patch('moduleA.ClassA.publish') as mock_publish:
d = {}
A.data_collection(d)
A.publish.assert_called_with("0","500","2","1")
You're missing a return_value for your mock_socket; you need to work off of what socket.socket is going to return. Your test should look like this:
def test_data_collection():
with mock.patch('socket.socket') as mock_socket:
A = classA()
mock_socket.return_value.recv.decode.return_value = "ABC123"
buf = A.data_collection()
assert "ABC123" == buf
Note that I had to fix some syntax errors in your class code, and I made data_collection return the buf variable so that it can be tested.
EDIT: File with class:
"""receiver.py"""
import socket
IP = 'localhost'
PORT = 80
class classA:
def __init__(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def connect(self):
self.s.connect((IP, PORT))
def data_collection(self):
buf = self.s.recv.decode()
return buf

How to get client connection object in tornado websocket, Python

I am using tornado websocket for simple test code.
In the test code, i want to get tornado.websocket.WebSocketHandler.
For example, I used this way below.
class ConvPlayerInterface(object):
class WebsocketHandler(tornado.websocket.WebSocketHandler):
client = None
queue = ipcQueue.IpcQueue()
def open(self):
print 'new connection'
self.client = self #in my simple code, it handles only one client.
self.write_message("Connection Open")
def on_message(self, message):
self.queue.put(message)
def on_close(self):
print 'connection closed'
def __init__(self, url='/ws'):
self.application = tornado.web.Application([(url, self.WebsocketHandler),])
self.httpServer = tornado.httpserver.HTTPServer(self.application)
self.httpServer.listen(8888)
self.queue = self.WebsocketHandler.queue
self.ioLoop = threading.Thread(target = tornado.ioloop.IOLoop.instance().start)
def start(self):
self.ioLoop.start()
def get(self):
return self.queue.get()
def put(self, command):
self.WebsocketHandler.client.write_message(command)
But the point when it calls self.WebsocketHandler.client.write_message(command) in put() method, Python says client is Non type.
Any advice?
And how usually it is used to get client connection handler object in tornado?
In this part of your code
def put(self, command):
self.WebsocketHandler.client.write_message(command)
you are accessing to WebsocketHandler class, not a class member.
And the "client" attribute of WebsocketHandler is None, as expected.
WebsocketHandler instance will be created for each request tornado will accept, so there can be several websocket handlers simultaneously.
If you really want to have handle only one connection - you can do something like this:
class ConvPlayerInterface(object):
the_only_handler = None
class WebsocketHandler(tornado.websocket.WebSocketHandler):
client = None
queue = ipcQueue.IpcQueue()
def open(self):
print 'new connection'
ConvPlayerInterface.the_only_handler = self
self.write_message("Connection Open")
def on_message(self, message):
self.queue.put(message)
def on_close(self):
ConvPlayerInterface.the_only_handler = None
print 'connection closed'
def __init__(self, url='/ws'):
self.application = tornado.web.Application([(url, self.WebsocketHandler),])
self.httpServer = tornado.httpserver.HTTPServer(self.application)
self.httpServer.listen(8888)
self.queue = self.WebsocketHandler.queue
self.ioLoop = threading.Thread(target = tornado.ioloop.IOLoop.instance().start)
def start(self):
self.ioLoop.start()
def get(self):
return self.queue.get()
def put(self, command):
if self.the_only_handler is not None
self.the_only_handler.write_message(command)

Python socket hangs program

I am working on a simple HTTP server in Python. I am taking bits and pieces from here: http://hg.python.org/cpython/file/3.3/Lib/socketserver.py to see how Python's standard library handles it.
My problem is that as soon as I try to accept requests my program hangs. Here is my code its only 100 lines so I'll just post it directly here.
I have a process() function which is in a loop that loops forever and it's suppose to handle new connections. Inside I have a print statement that only gets printed once.
print('processing') in TCPServer.process()
I have tried threading off process() but I get the same result.
"""."""
import socket
import select
from abc import abstractmethod, ABCMeta
class BaseServer(metaclass=ABCMeta):
def __init__(self, server_address, server_port, RequestHandlerClass):
self._server_address = server_address
self._server_port = server_port
self._RequestHandlerClass = RequestHandlerClass
self._running = False
def serve_forever(self):
self._running = True
while self._running:
self.process()
#abstractmethod
def process(self):
pass
def shutdown(self):
self._running = False
class TCPServer(BaseServer):
def __init__(self,
server_address,
server_port,
RequestHandlerClass,
address_family=socket.AF_INET,
socket_type=socket.SOCK_STREAM,
request_queue_size=1,
bind=True):
super(TCPServer, self).__init__(server_address,
server_port,
RequestHandlerClass)
self._address_family = address_family
self._socket_type = socket_type
self._request_queue_size = request_queue_size
self._socket = socket.socket(self._address_family, self._socket_type)
self._read_list = [self._socket]
if bind:
self.bind()
def bind(self):
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._socket.bind((self._server_address, self._server_port))
self._socket.listen(self._request_queue_size)
def shutdown(self):
super().shutdown()
self._socket.close()
def process(self):
print('processing')
readable, writeable, errored = select.select(self._read_list, [], [])
for socket in readable:
if socket is self._socket:
client_socket, client_address = self._socket.accept()
self._read_list.append(client_socket)
print('connection from: ', client_address)
else:
self._RequestHandlerClass(client_socket)
self._read_list.remove(client_socket)
class BaseRequestHandler(metaclass=ABCMeta):
def __init__(self, client_socket):
self._client_socket = client_socket
self.setup()
try:
self.handle()
finally:
self.finish()
#abstractmethod
def setup(self):
pass
#abstractmethod
def handle(self):
pass
#abstractmethod
def finish(self):
pass
class HTTPRequestHandler(BaseRequestHandler):
def setup(self):
print('REQUEST SETUP')
print(self._client_socket.recv(2048))
def handle(self):
print('REQUEST HANDLE')
def finish(self):
print('REQUEST FINISH')
self._client_socket.close()
if __name__ == '__main__':
tcp_server = TCPServer(server_address='',
server_port=9000,
RequestHandlerClass=HTTPRequestHandler)
tcp_server.serve_forever()
I ran your code but couldn't make it hang. However, there is a fatal error in your process() function where you refer to client_socket in the else: branch, but client_socket is not defined at that point. You probably meant to refer to socket.
I was able to make two connections to the server on port 9000, and get "connection from:" lines for each. As soon as one of those connections sent something, your server would crash for the above reason.

How to make a dynamic port forwarding on python?

I modified the code (found here) a bit (added class AsyncEventLoop)
import socket,asyncore
import threading
class forwarder(asyncore.dispatcher):
def __init__(self, ip, port, remoteip,remoteport,backlog=5):
asyncore.dispatcher.__init__(self)
self.remoteip=remoteip
self.remoteport=remoteport
self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((ip,port))
self.listen(backlog)
def handle_accept(self):
conn, addr = self.accept()
# print '--- Connect --- '
sender(receiver(conn),self.remoteip,self.remoteport)
def closef(self):
self.close()
class receiver(asyncore.dispatcher):
def __init__(self,conn):
asyncore.dispatcher.__init__(self,conn)
self.from_remote_buffer=''
self.to_remote_buffer=''
self.sender=None
def handle_connect(self):
pass
def handle_read(self):
read = self.recv(4096)
# print '%04i -->'%len(read)
self.from_remote_buffer += read
def writable(self):
return (len(self.to_remote_buffer) > 0)
def handle_write(self):
sent = self.send(self.to_remote_buffer)
# print '%04i <--'%sent
self.to_remote_buffer = self.to_remote_buffer[sent:]
def handle_close(self):
self.close()
if self.sender:
self.sender.close()
class sender(asyncore.dispatcher):
def __init__(self, receiver, remoteaddr,remoteport):
asyncore.dispatcher.__init__(self)
self.receiver=receiver
receiver.sender=self
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((remoteaddr, remoteport))
def handle_connect(self):
pass
def handle_read(self):
read = self.recv(4096)
# print '<-- %04i'%len(read)
self.receiver.to_remote_buffer += read
def writable(self):
return (len(self.receiver.from_remote_buffer) > 0)
def handle_write(self):
sent = self.send(self.receiver.from_remote_buffer)
# print '--> %04i'%sent
self.receiver.from_remote_buffer = self.receiver.from_remote_buffer[sent:]
def handle_close(self):
self.close()
self.receiver.close()
class AsyncEventLoop(threading.Thread):
def run(self):
asyncore.loop()
starting in the code
ser = forwarder('127.0.0.1', 7774, 'google.com.ua', 80)
evLoop = AsyncEventLoop()
Can I change remoteip, remoteport on the fly? If the fly is not possible to change, as well stop this thread to start with the new settings (remoteip, remoteport)?
yes, you can
ser.remoteip, ser.remoteport = IP, port

Categories

Resources