def test_simple_run_with_close(monkeypatch, mocker): """Test graceful close.""" monkeypatch.setattr('os.urandom', b'\x00'.__mul__) Mocket.register( MocketEntry(('example.com', 80), [(b'HTTP/1.1 101 Switching Protocols\r\n' b'Upgrade: websocket\r\n' b'Connection: Upgrade\r\n' b'Sec-WebSocket-Accept: icx+yqv66kxgm0fcwalwlflwtai=\r\n' b'\r\n' b'\x81\x81\x00\x00\x00\x00A\x88\x80\xba51e')])) session = WebsocketSession(WebSocket('ws://example.com/')) session._selector_cls = FakeSelector session._on_ready() session._regular_orig = session._regular mocker.patch('lomond.websocket.WebSocket._send_close') mocker.patch.object(session.websocket, 'send_ping') session.websocket.state.session = session _events = list(session.run()) assert len(_events) == 7 assert isinstance(_events[0], events.Connecting) assert isinstance(_events[1], events.Connected) assert isinstance(_events[2], events.Ready) assert isinstance(_events[3], events.Poll) assert isinstance(_events[4], events.Text) assert isinstance(_events[5], events.Closing) assert isinstance(_events[6], events.Disconnected) assert _events[6].graceful
def apply_safety_net(fake_getaddrinfo): fake_getaddrinfo.append( ( socket.AF_INET6, socket.SOCK_STREAM, socket.IPPROTO_TCP, "", ("2606:2800:220:1:248:1893:25c8:1946", 80), ) ) # Set up a fake entry to return some data for all of the IP's so mocket # doesn't try to connect if it can't find an entry. mocket_entry = Entry( "http://example.com/info.json", Entry.GET, Entry.response_cls( body=json.dumps({"ip": "2606:2800:220:1:248:1893:25c8:1946"}), status=200, headers=None, ), ) mocket_entry.location = ("2606:2800:220:1:248:1893:25c8:1946", 80) Mocket.register(mocket_entry)
def test_unresponsive(monkeypatch, mocker): """Check ping timeout.""" monkeypatch.setattr( 'os.urandom', b'\x00'.__mul__ ) Mocket.register( MocketEntry( ('example.com', 80), [( b'HTTP/1.1 101 Switching Protocols\r\n' b'Upgrade: websocket\r\n' b'Connection: Upgrade\r\n' b'Sec-WebSocket-Accept: icx+yqv66kxgm0fcwalwlflwtai=\r\n' b'\r\n' b'\x81\x81\x00\x00\x00\x00A' )] ) ) # mocket doesn't support .pending() call which is used when ssl is used session = WebsocketSession(WebSocket('ws://example.com/')) session._selector_cls = FakeSelector session._on_ready() # well, we have to cheat a little. The thing is, inner loop of # run() sets last poll time to time.time and so we would have to # wait for some time to actually hit poll / ping. This is not desirable # so we can do the following: # save original _regular call into _regular_orig # (_regular is a first - well, technically, a second) call inside run # after _poll_start is set which makes it a nice candidate for monkey-patch # location. Here's how we do it: session._regular_orig = session._regular mocker.patch( 'lomond.websocket.WebSocket._send_close') mocker.patch.object(session.websocket, 'send_ping') _events = [] iter_events = iter(session.run(ping_timeout=5)) for event in iter_events: _events.append(event) if event.name == 'text': break with freeze_time("1994-05-01 18:41:00"): for event in iter_events: _events.append(event) assert len(_events) == 8 assert isinstance(_events[0], events.Connecting) assert isinstance(_events[1], events.Connected) assert isinstance(_events[2], events.Ready) assert isinstance(_events[3], events.Poll) assert isinstance(_events[4], events.Text) assert isinstance(_events[5], events.Poll) assert isinstance(_events[6], events.Unresponsive) assert isinstance(_events[7], events.Disconnected)
def test_register(self): entry_1 = MocketEntry(('localhost', 80), True) entry_2 = MocketEntry(('localhost', 80), True) entry_3 = MocketEntry(('localhost', 8080), True) Mocket.register(entry_1, entry_2, entry_3) self.assertEqual(Mocket._entries, { ('localhost', 80): [entry_1, entry_2], ('localhost', 8080): [entry_3], })
def test_socket_fail(session, mocker): def select_that_throws_exception(*args, **kwargs): raise select.error('this is just a test') Mocket.register(MocketEntry(('example.com', 80), [b'some binary data'])) mocker.patch('lomond.session.select.select', select_that_throws_exception) with pytest.raises(WebsocketSession._SocketFail): session._select(session._sock, poll=5)
def test_socket_as_context_manager(self): addr = ("localhost", 80) Mocket.register(MocketEntry(addr, ["Show me.\r\n"])) with Mocketizer(): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as _so: _so.connect(addr) _so.sendall(encode_to_bytes("Whatever...")) data = _so.recv(4096) self.assertEqual(data, encode_to_bytes("Show me.\r\n"))
def test_connect(session, mocker): Mocket.register( MocketEntry( ('example.com', 80), [b'some binary data'] ) ) _socket, _proxy = session._connect() assert isinstance(_socket, socket.socket)
def test_subsequent_recv_requests_have_correct_length(self): Mocket.register( MocketEntry(('localhost', 80), [b'Long payload', b'Short'])) _so = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _so.connect(('localhost', 80)) _so.sendall(b'first\r\n') assert _so.recv(4096) == b'Long payload' _so.sendall(b'second\r\n') assert _so.recv(4096) == b'Short' _so.close()
def test_send_command(self): Mocket.register( MocketEntry(self.bulb_addr, [b'{"id":1, "result":["ok"]}\r\n'])) with Bulb(*self.bulb_addr, **self.kwargs | { "id": 1, "support": ["set_ct_abx"] }) as b: loop = asyncio.get_event_loop() loop.run_until_complete( b.send_command("set_ct_abx", [3500, "smooth", 500]))
def session_with_socket(monkeypatch): Mocket.register( MocketEntry( ('example.com', 80), [b'some binary data'] ) ) session_obj = session(monkeypatch) return session_obj
def test_makefile(self): addr = ("localhost", 80) Mocket.register(MocketEntry(addr, ["Show me.\r\n"])) with Mocketizer(): _so = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _so.connect(addr) fp = _so.makefile("rb") _so.sendall(encode_to_bytes("...\r\n")) self.assertEqual(fp.read().strip(), encode_to_bytes("Show me.")) self.assertEqual(len(Mocket.request_list()), 1)
def test_collect_last_request(self): addr = ("localhost", 80) entry = MocketEntry(addr, True) Mocket.register(entry) with Mocketizer(): _so = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _so.connect(addr) _so.sendall(b"data\r\n") _so.close() self.assertEqual(Mocket.last_request(), b"data\r\n")
def test_subsequent_recv_requests_have_correct_length(self): addr = ("localhost", 80) Mocket.register(MocketEntry(addr, [b"Long payload", b"Short"])) with Mocketizer(): _so = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _so.connect(addr) _so.sendall(b"first\r\n") self.assertEqual(_so.recv(4096), b"Long payload") _so.sendall(b"second\r\n") self.assertEqual(_so.recv(4096), b"Short") _so.close()
def test_recv_into(self): Mocket.register( MocketEntry(('localhost', 80), [b'Long payload', b'Short'])) buffer = io.BytesIO() with Mocketizer(): _so = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _so.connect(('localhost', 80)) _so.sendall(b'first\r\n') assert _so.recv_into(buffer, 4096) == 12 _so.sendall(b'second\r\n') assert _so.recv_into(buffer) == 5 _so.close() buffer.seek(0) assert buffer.read() == b'Long payloadShort'
def test_recv_into(self): addr = ("localhost", 80) Mocket.register(MocketEntry(addr, [b"Long payload", b"Short"])) buffer = io.BytesIO() with Mocketizer(): _so = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _so.connect(addr) _so.sendall(b"first\r\n") self.assertEqual(_so.recv_into(buffer, 4096), 12) _so.sendall(b"second\r\n") self.assertEqual(_so.recv_into(buffer), 5) _so.close() buffer.seek(0) assert buffer.read() == b"Long payloadShort"
def request_succeeds(request, fake_getaddrinfo): for (family, ip, port) in request.param: fake_getaddrinfo.append( (family, socket.SOCK_STREAM, socket.IPPROTO_TCP, "", (ip, port)) ) # Set up a fake entry to return some data for all of the IP's so mocket # doesn't try to connect if it can't find an entry. mocket_entry = Entry( "http://example.com/info.json", Entry.GET, Entry.response_cls(body=json.dumps({"ip": ip}), status=200, headers=None), ) mocket_entry.location = (ip, port) Mocket.register(mocket_entry)
def test_subsequent_recv_requests_have_correct_length(self): Mocket.register( MocketEntry( ('localhost', 80), [ b'Long payload', b'Short' ] ) ) with Mocketizer(): _so = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _so.connect(('localhost', 80)) _so.sendall(b'first\r\n') assert _so.recv(4096) == b'Long payload' _so.sendall(b'second\r\n') assert _so.recv(4096) == b'Short' _so.close()
def test_redirect_to_ip_unsafe_fails(session, fake_getaddrinfo): fake_getaddrinfo.append( ( socket.AF_INET6, socket.SOCK_STREAM, socket.IPPROTO_TCP, "", ("2606:2800:220:1:248:1893:25c8:1946", 80), ) ) # Set up a fake entry to return some data for all of the IP's so mocket # doesn't try to connect if it can't find an entry. mocket_entry = Entry( "http://example.com/info.json", Entry.GET, Entry.response_cls( body=json.dumps({"ip": "2606:2800:220:1:248:1893:25c8:1946"}), status=301, headers={"Location": "http://10.10.10.58/other.json"}, ), ) mocket_entry.location = ("2606:2800:220:1:248:1893:25c8:1946", 80) Mocket.register(mocket_entry) mocket_entry = Entry( "http://10.10.10.58/other.json", Entry.GET, Entry.response_cls( body=json.dumps({"ip": "10.10.10.58"}), status=200, headers=None ), ) mocket_entry.location = ("10.10.10.58", 80) Mocket.register(mocket_entry) with pytest.raises(requests.exceptions.ConnectionError) as exc: session.get("http://exampe.com/info.json") assert "getaddrinfo returns an empty list" in str(exc.value)
def test_recv_into(self): Mocket.register( MocketEntry( ('localhost', 80), [ b'Long payload', b'Short' ] ) ) buffer = io.BytesIO() with Mocketizer(): _so = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _so.connect(('localhost', 80)) _so.sendall(b'first\r\n') assert _so.recv_into(buffer, 4096) == 12 _so.sendall(b'second\r\n') assert _so.recv_into(buffer, 4096) == 5 _so.close() buffer.seek(0) assert buffer.read() == b'Long payloadShort'
def register_conversation(self, response_port=None, response_data=None): from mocket import Mocket, MocketEntry response_port = response_port or self.LORA_RESPONSE_PORT response_data = response_data or [] lora_entry = MocketEntry(location=(None, None), responses=response_data) lora_entry.request_cls = bytearray Mocket.reset() Mocket.register(lora_entry) def recvfrom(self, buffersize): if response_data: buffer = self.recv(buffersize) return buffer, response_port else: return None, response_port self.monkeypatch.setattr(MocketSocket, 'recvfrom', recvfrom, raising=False)
def test_simple_run(monkeypatch, mocker): monkeypatch.setattr('os.urandom', b'\x00'.__mul__) Mocket.register( MocketEntry(('example.com', 80), [(b'HTTP/1.1 101 Switching Protocols\r\n' b'Upgrade: websocket\r\n' b'Connection: Upgrade\r\n' b'Sec-WebSocket-Accept: icx+yqv66kxgm0fcwalwlflwtai=\r\n' b'\r\n' b'\x81\x81\x00\x00\x00\x00A')])) # mocket doesn't support .pending() call which is used when ssl is used session = WebsocketSession(WebSocket('ws://example.com/')) session._on_ready() # well, we have to cheat a little. The thing is, inner loop of # run() sets last poll time to time.time and so we would have to # wait for some time to actually hit poll / ping. This is not desirable # so we can do the following: # save original _regular call into _regular_orig # (_regular is a first - well, technically, a second) call inside run # after _poll_start is set which makes it a nice candidate for monkey-patch # location. Here's how we do it: session._regular_orig = session._regular mocker.patch('lomond.websocket.WebSocket._send_close') mocker.patch.object(session.websocket, 'send_ping') mocker.patch('lomond.session.WebsocketSession._select', lambda self, sock, poll: [True, False]) _events = list(session.run()) assert len(_events) == 6 assert isinstance(_events[0], events.Connecting) assert isinstance(_events[1], events.Connected) assert isinstance(_events[2], events.Ready) assert isinstance(_events[3], events.Poll) assert isinstance(_events[4], events.Text) assert isinstance(_events[5], events.Disconnected)
def test_getentry(self): entry = MocketEntry(('localhost', 80), True) Mocket.register(entry) self.assertEqual(Mocket.get_entry('localhost', 80, True), entry)
def register(addr, command, *responses): responses = [Entry.response_cls(r) for r in responses] Mocket.register(Entry(addr, command, responses))
def register(method, uri, *responses): Mocket.register(Entry(uri, method, responses))