Skip to content

Commit 6356dd0

Browse files
authored
Clean test_server_asyncio.py (#885)
1 parent 71ea7e4 commit 6356dd0

File tree

1 file changed

+36
-96
lines changed

1 file changed

+36
-96
lines changed

test/test_server_asyncio.py

Lines changed: 36 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ async def asyncTearDown(self):
136136
pass
137137
except Exception as exc: # pylint: disable=broad-except
138138
pytest.fail(f"Exception in task serve_forever: {exc} ")
139-
self.assertTrue(self.task.cancelled())
140139
self.task = None
141140
self.context = ModbusServerContext(slaves=self.store, single=True)
142141
BasicClient.clear()
@@ -176,7 +175,7 @@ async def start_server(self, do_forever=True, do_defer=True, do_tls=False, do_ud
176175
await asyncio.wait_for(self.server.serving, timeout=0.1)
177176
if not do_udp:
178177
self.assertIsNotNone(self.server.server)
179-
else:
178+
elif not do_udp: # pylint: disable=confusing-consecutive-elif
180179
self.assertIsNone(self.server.server)
181180
self.assertEqual(self.server.control.Identity.VendorName, 'VendorName')
182181
await asyncio.sleep(0.1)
@@ -197,7 +196,7 @@ async def connect_server(self):
197196

198197
async def test_async_start_server_no_loop(self):
199198
"""Test that the modbus tcp asyncio server starts correctly"""
200-
await self.start_server(False)
199+
await self.start_server(do_forever=False)
201200

202201
async def test_async_start_server(self):
203202
"""Test that the modbus tcp asyncio server starts correctly"""
@@ -219,35 +218,24 @@ async def test_async_tcp_server_receive_data(self):
219218
process.assert_called_once()
220219
self.assertTrue(process.call_args[1]["data"] == BasicClient.data)
221220

222-
@pytest.mark.skipif(pytest.IS_WINDOWS, reason="To fix")
223221
async def test_async_tcp_server_roundtrip(self):
224222
"""Test sending and receiving data on tcp socket"""
225223
expected_response = b'\x01\x00\x00\x00\x00\x05\x01\x03\x02\x00\x11'
226224
BasicClient.data = TEST_DATA # unit 1, read register
227-
228-
# value of 17 as per context
229225
await self.start_server()
230226
await self.connect_server()
231227
await asyncio.wait_for(BasicClient.done, timeout=0.1)
232228
self.assertEqual(BasicClient.received_data, expected_response)
233229

234-
@pytest.mark.skipif(pytest.IS_WINDOWS, reason="To fix")
235230
async def test_async_tcp_server_connection_lost(self):
236231
"""Test tcp stream interruption"""
237232
await self.start_server()
238233
await self.connect_server()
239-
# On Windows we seem to need to give this an extra chance to finish,
240-
# otherwise there ends up being an active connection at the assert.
241-
await asyncio.sleep(0.2)
242234
self.assertEqual(len(self.server.active_connections), 1)
243235

244236
BasicClient.protocol.transport.close()
245-
# close isn't synchronous and there's no
246-
# notification that it's done
247237
await asyncio.sleep(0.2) # so we have to wait a bit
248238
self.assertFalse(self.server.active_connections)
249-
BasicClient.protocol = None
250-
BasicClient.transport = None
251239

252240
async def test_async_tcp_server_close_active_connection(self):
253241
"""Test server_close() while there are active TCP connections"""
@@ -263,8 +251,6 @@ async def test_async_tcp_server_no_slave(self):
263251
"""Test unknown slave unit exception"""
264252
self.context = ModbusServerContext(slaves={0x01: self.store, 0x02: self.store}, single=False)
265253
BasicClient.data = b"\x01\x00\x00\x00\x00\x06\x05\x03\x00\x00\x00\x01"
266-
267-
# get slave 5 function 3 (holding register)
268254
await self.start_server()
269255
await self.connect_server()
270256
self.assertFalse(BasicClient.eof.done())
@@ -274,8 +260,6 @@ async def test_async_tcp_server_no_slave(self):
274260
async def test_async_tcp_server_modbus_error(self):
275261
"""Test sending garbage data on a TCP socket should drop the connection"""
276262
BasicClient.data = TEST_DATA
277-
278-
# get slave 5 function 3 (holding register)
279263
await self.start_server()
280264
with patch("pymodbus.register_read_message.ReadHoldingRegistersRequest.execute",
281265
side_effect=NoSuchSlaveException):
@@ -288,16 +272,16 @@ async def test_async_tcp_server_modbus_error(self):
288272
async def test_async_start_tls_server_no_loop(self):
289273
"""Test that the modbus tls asyncio server starts correctly"""
290274
with patch.object(ssl.SSLContext, 'load_cert_chain'):
291-
await self.start_server(do_tls=True, do_ident=True)
275+
await self.start_server(do_tls=True, do_forever=False, do_ident=True)
292276
self.assertEqual(self.server.control.Identity.VendorName, 'VendorName')
293-
self.assertTrue(self.server.sslctx is not None)
277+
self.assertIsNotNone(self.server.sslctx)
294278

295279
async def test_async_start_tls_server(self):
296280
"""Test that the modbus tls asyncio server starts correctly"""
297281
with patch.object(ssl.SSLContext, 'load_cert_chain'):
298282
await self.start_server(do_tls=True, do_ident=True)
299283
self.assertEqual(self.server.control.Identity.VendorName, 'VendorName')
300-
self.assertTrue(self.server.sslctx is not None)
284+
self.assertIsNotNone(self.server.sslctx)
301285

302286
async def test_async_tls_server_serve_forever(self):
303287
"""Test StartTcpServer serve_forever() method"""
@@ -321,125 +305,95 @@ async def test_async_tls_server_serve_forever_twice(self):
321305

322306
async def test_async_start_udp_server_no_loop(self):
323307
"""Test that the modbus udp asyncio server starts correctly"""
324-
server = await StartUdpServer(context=self.context, address=SERV_ADDR,
325-
loop=self.loop, identity=self.identity)
326-
self.assertEqual(server.control.Identity.VendorName, 'VendorName')
327-
self.assertIsNone(server.protocol)
308+
await self.start_server(do_udp=True, do_forever=False, do_ident=True)
309+
self.assertEqual(self.server.control.Identity.VendorName, 'VendorName')
310+
self.assertIsNone(self.server.protocol)
328311

329312
async def test_async_start_udp_server(self):
330313
"""Test that the modbus udp asyncio server starts correctly"""
331-
server = await StartUdpServer(context=self.context, address=SERV_ADDR,
332-
loop=self.loop, identity=self.identity)
333-
asyncio.create_task(server.serve_forever())
334-
await server.serving
335-
self.assertEqual(server.control.Identity.VendorName, 'VendorName')
336-
self.assertFalse(server.protocol is None)
337-
server.server_close()
314+
await self.start_server(do_udp=True, do_ident=True)
315+
self.assertEqual(self.server.control.Identity.VendorName, 'VendorName')
316+
self.assertFalse(self.server.protocol is None)
338317

339318
async def test_async_udp_server_serve_forever_start(self):
340319
"""Test StartUdpServer serve_forever() method"""
341320
with patch('asyncio.base_events.Server.serve_forever',
342321
new_callable=AsyncMock) as serve:
343-
server = await StartTcpServer(context=self.context,
344-
address=SERV_ADDR, loop=self.loop)
345-
await server.serve_forever()
322+
await self.start_server(do_forever=False, do_ident=True)
323+
await self.server.serve_forever()
346324
serve.assert_awaited()
347-
server.server_close()
348325

349326
async def test_async_udp_server_serve_forever_close(self):
350327
"""Test StartUdpServer serve_forever() method"""
351-
server = await StartUdpServer(context=self.context, address=SERV_ADDR, loop=self.loop)
352-
asyncio.create_task(server.serve_forever())
353-
await server.serving
328+
await self.start_server(do_udp=True)
329+
self.assertTrue(asyncio.isfuture(self.server.on_connection_terminated))
330+
self.assertFalse(self.server.on_connection_terminated.done())
354331

355-
self.assertTrue(asyncio.isfuture(server.on_connection_terminated))
356-
self.assertFalse(server.on_connection_terminated.done())
357-
358-
server.server_close()
359-
self.assertTrue(server.protocol.is_closing())
332+
self.server.server_close()
333+
self.assertTrue(self.server.protocol.is_closing())
334+
self.server = None
360335

361336
async def test_async_udp_server_serve_forever_twice(self):
362337
"""Call on serve_forever() twice should result in a runtime error"""
363-
server = await StartUdpServer(context=self.context, address=SERV_ADDR,
364-
loop=self.loop, identity=self.identity)
365-
asyncio.create_task(server.serve_forever())
366-
await server.serving
338+
await self.start_server(do_udp=True, do_ident=True)
367339
with self.assertRaises(RuntimeError):
368-
await server.serve_forever()
369-
server.server_close()
340+
await self.server.serve_forever()
370341

371342
async def test_async_udp_server_receive_data(self):
372343
"""Test that the sending data on datagram socket gets data pushed to framer"""
373-
server = await StartUdpServer(context=self.context, address=SERV_ADDR, loop=self.loop)
374-
task = asyncio.create_task(server.serve_forever())
375-
await server.serving
344+
await self.start_server(do_udp=True)
376345
with patch('pymodbus.transaction.ModbusSocketFramer.processIncomingPacket',
377346
new_callable=Mock) as process:
378-
server.endpoint.datagram_received(data=b"12345", addr=(SERV_IP, 12345))
347+
self.server.endpoint.datagram_received(data=b"12345", addr=(SERV_IP, 12345))
379348
await asyncio.sleep(0.1)
380349
process.seal()
381350
process.assert_called_once()
382351
self.assertTrue(process.call_args[1]["data"] == b"12345")
383-
server.server_close()
384-
await asyncio.sleep(0.1)
385-
task.cancel()
386352

387353
async def test_async_udp_server_send_data(self):
388354
"""Test that the modbus udp asyncio server correctly sends data outbound"""
389-
ModbusDeviceIdentification(info={0x00: 'VendorName'})
390355
BasicClient.dataTo = b'x\01\x00\x00\x00\x00\x06\x01\x03\x00\x00\x00\x19'
391-
BasicClient.done = self.loop.create_future()
392-
server = await StartUdpServer(context=self.context, address=SERV_ADDR)
393-
task = asyncio.create_task(server.serve_forever())
394-
await server.serving
395-
random_port = server.protocol._sock.getsockname()[1] # pylint: disable=protected-access
396-
received = server.endpoint.datagram_received = Mock(wraps=server.endpoint.datagram_received)
356+
await self.start_server(do_udp=True)
357+
random_port = self.server.protocol._sock.getsockname()[1] # pylint: disable=protected-access
358+
received = self.server.endpoint.datagram_received = Mock(wraps=self.server.endpoint.datagram_received)
397359
await self.loop.create_datagram_endpoint(BasicClient,
398360
remote_addr=('127.0.0.1', random_port))
399361
await asyncio.sleep(0.1)
400362
received.assert_called_once()
401363
self.assertEqual(received.call_args[0][0], BasicClient.dataTo)
402-
server.server_close()
403-
self.assertTrue(server.protocol.is_closing())
404-
task.cancel()
364+
self.server.server_close()
365+
self.assertTrue(self.server.protocol.is_closing())
366+
self.server = None
405367

406368
async def test_async_udp_server_roundtrip(self):
407369
"""Test sending and receiving data on udp socket"""
408370
expected_response = b'\x01\x00\x00\x00\x00\x05'\
409371
b'\x01\x03\x02\x00\x11' # value of 17 as per context
410372
BasicClient.dataTo = TEST_DATA # unit 1, read register
411373
BasicClient.done = self.loop.create_future()
412-
server = await StartUdpServer(context=self.context, address=SERV_ADDR, loop=self.loop)
413-
asyncio.create_task(server.serve_forever())
414-
await server.serving
415-
random_port = server.protocol._sock.getsockname()[1] # pylint: disable=protected-access
374+
await self.start_server(do_udp=True)
375+
random_port = self.server.protocol._sock.getsockname()[1] # pylint: disable=protected-access
416376
transport, _ = await self.loop.create_datagram_endpoint(BasicClient,
417377
remote_addr=('127.0.0.1', random_port))
418378
await asyncio.wait_for(BasicClient.done, timeout=0.1)
419379
self.assertEqual(BasicClient.received_data, expected_response)
420380
transport.close()
421-
await asyncio.sleep(0)
422-
server.server_close()
423381

424382
async def test_async_udp_server_exception(self):
425383
"""Test sending garbage data on a TCP socket should drop the connection"""
426384
BasicClient.dataTo = b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF'
427385
BasicClient.connected = self.loop.create_future()
428386
BasicClient.done = self.loop.create_future()
429-
server = await StartUdpServer(context=self.context, address=SERV_ADDR, loop=self.loop)
430-
asyncio.create_task(server.serve_forever())
431-
await server.serving
387+
await self.start_server(do_udp=True)
432388
with patch('pymodbus.transaction.ModbusSocketFramer.processIncomingPacket',
433389
new_callable=lambda: Mock(side_effect=Exception)):
434390
# get the random server port pylint: disable=protected-access
435-
random_port = server.protocol._sock.getsockname()[1]
391+
random_port = self.server.protocol._sock.getsockname()[1]
436392
_, _ = await self.loop.create_datagram_endpoint(BasicClient,
437393
remote_addr=('127.0.0.1', random_port))
438394
await asyncio.wait_for(BasicClient.connected, timeout=0.1)
439395
self.assertFalse(BasicClient.done.done())
440-
self.assertFalse(server.protocol._sock._closed) # pylint: disable=protected-access
441-
server.server_close()
442-
await asyncio.sleep(0.1)
396+
self.assertFalse(self.server.protocol._sock._closed) # pylint: disable=protected-access
443397

444398
# -----------------------------------------------------------------------#
445399
# Test ModbusServerFactory
@@ -453,26 +407,12 @@ def test_async_stop_server(self): # pylint: disable=no-self-use
453407
"""Test stop server."""
454408
StopServer()
455409

456-
@pytest.mark.skipif(pytest.IS_WINDOWS, reason="To fix")
457410
async def test_async_tcp_server_exception(self):
458411
"""Send garbage data on a TCP socket should drop the connection"""
459412
BasicClient.data = b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF'
460-
BasicClient.connected = self.loop.create_future()
461-
BasicClient.done = self.loop.create_future()
462-
BasicClient.eof = self.loop.create_future()
463-
server = await StartTcpServer(context=self.context,
464-
address=SERV_ADDR, loop=self.loop)
465-
task = asyncio.create_task(server.serve_forever())
466-
await server.serving
413+
await self.start_server()
467414
with patch('pymodbus.transaction.ModbusSocketFramer.processIncomingPacket',
468415
new_callable=lambda: Mock(side_effect=Exception)):
469-
random_port = server.server.sockets[0].getsockname()[1] # get the random server port
470-
_, _ = await self.loop.create_connection(BasicClient, host='127.0.0.1',
471-
port=random_port)
472-
await asyncio.wait_for(BasicClient.connected, timeout=0.1)
416+
await self.connect_server()
473417
await asyncio.wait_for(BasicClient.eof, timeout=0.1)
474418
# neither of these should timeout if the test is successful
475-
server.server_close()
476-
await asyncio.sleep(0.1)
477-
task.cancel()
478-
self.assertTrue(task.cancelled())

0 commit comments

Comments
 (0)