@@ -147,6 +147,33 @@ async def test_unknown_driver_is_rejected(self) -> None:
147147
148148
149149class TargetResolutionTests (unittest .IsolatedAsyncioTestCase ):
150+ async def test_unbound_support_reads_use_explicit_route_without_binding_driver (self ) -> None :
151+ # #23: read the documented candidate ranges before selecting any map.
152+ # Synthetic replies validate the runner, not Hopewind device support.
153+ class ReadOnlyFixture (FixtureTransport ):
154+ async def async_send_payload (self , payload , * , route ):
155+ self_test .assertEqual (payload [1 ], 3 )
156+ return await super ().async_send_payload (payload , route = route )
157+
158+ self_test = self
159+ bank = {register : register for register in range (40500 , 40651 )}
160+ transport = ReadOnlyFixture (registers = bank , command_responses = None , probe_target = ProbeTarget (1 , 255 , 1 ))
161+ ctx = DiagnosticRuntimeContext (transport = transport , configured_driver_hint = "auto" , confirm_write = False )
162+ result = await run_scenario (
163+ "driver modbus_smg\n devcode 1\n collector_addr 255\n device_addr 1\n "
164+ "stop_on_error false\n operation_timeout 8\n "
165+ "read 40600 51\n read 40500 71\n read 40571 29\n " , ctx ,
166+ )
167+ self .assertTrue (result .success , result .output )
168+ self .assertEqual ([step ["response" ]["decimal" ] for step in result .results ], [
169+ list (range (40600 , 40651 )), list (range (40500 , 40571 )), list (range (40571 , 40600 )),
170+ ])
171+ self .assertEqual (result .context ["probe_target" ], {"devcode" : 1 , "collector_addr" : 255 , "device_addr" : 1 })
172+ self .assertEqual (result .context ["driver_source" ], "scenario_override" )
173+ self .assertIsNone (ctx .active_driver_key )
174+ self .assertIsNone (ctx .active_probe_target )
175+ self .assertEqual (ctx .configured_driver_hint , "auto" )
176+
150177 async def test_address_overrides_apply (self ) -> None :
151178 transport = _modbus ({10 : 1 })
152179 result = await run_scenario (
0 commit comments