Skip to content

Commit 6ef820c

Browse files
authored
Use asyncio.Event to deterministically ensure simulator start (#2734)
1 parent 0f31a53 commit 6ef820c

File tree

2 files changed

+11
-14
lines changed

2 files changed

+11
-14
lines changed

pymodbus/server/simulator/http_server.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class CallTypeResponse:
7979
clear_after: int = 1
8080

8181

82-
class ModbusSimulatorServer:
82+
class ModbusSimulatorServer: # pylint: disable=too-many-instance-attributes
8383
"""**ModbusSimulatorServer**.
8484
8585
:param modbus_server: Server name in json file (default: "server")
@@ -219,6 +219,7 @@ def __init__(
219219
self.call_response = CallTypeResponse()
220220
app_key = getattr(web, 'AppKey', str) # fall back to str for aiohttp < 3.9.0
221221
self.api_key = app_key("modbus_server")
222+
self.ready_event = asyncio.Event()
222223

223224
async def start_modbus_server(self, app):
224225
"""Start Modbus server as asyncio task."""
@@ -253,6 +254,7 @@ async def run_forever(self, only_start=False):
253254
await self.runner.setup()
254255
self.site = web.TCPSite(self.runner, self.http_host, self.http_port)
255256
await self.site.start()
257+
self.ready_event.set()
256258
except Exception as exc:
257259
Log.error("Error starting http server, reason: {}", exc)
258260
raise exc

test/server/test_simulator_api.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
"""Test simulator API."""
2-
import asyncio
32
import json
43

54
import pytest
@@ -127,20 +126,16 @@ async def simulator(self, tmp_path):
127126
json_file = config_path
128127
)
129128

130-
# Run the simulator in the current event loop. Store the task so they live
131-
# until the test is done.
132-
loop = asyncio.get_running_loop()
133-
task = loop.create_task(simulator.run_forever(only_start=True))
129+
# this will finish almost immediately; no need to keep a task
130+
await simulator.run_forever(only_start=True)
134131

135-
# TODO: Make a better way to wait for the simulator to start
136-
await asyncio.sleep(1)
132+
# wait for the simulator to start
133+
await simulator.ready_event.wait()
137134

138-
yield simulator
139-
140-
# Stop the simulator after the test is done
141-
task.cancel()
142-
await task
143-
await simulator.stop()
135+
try:
136+
yield simulator
137+
finally:
138+
await simulator.stop()
144139

145140
@pytest.mark.asyncio
146141
async def test_registers_json_valid(self, client, simulator):

0 commit comments

Comments
 (0)