Hi Alvin,
On Thu, 2021-01-28 at 13:24 +0000, Alvin Šipraga wrote:
---
autotests/testRoamRetry/stop_retry_test.py | 134
+++++++++++++++++++++
1 file changed, 134 insertions(+)
create mode 100644 autotests/testRoamRetry/stop_retry_test.py
diff --git a/autotests/testRoamRetry/stop_retry_test.py
b/autotests/testRoamRetry/stop_retry_test.py
new file mode 100644
index 00000000..bbe6e2a1
--- /dev/null
+++ b/autotests/testRoamRetry/stop_retry_test.py
@@ -0,0 +1,134 @@
+#!/usr/bin/python3
+
+import unittest
+import sys
+
+sys.path.append('../util')
+import iwd
+from iwd import IWD
+from iwd import PSKAgent
+from iwd import NetworkType
+
+import testutil
+
+from hostapd import HostapdCLI
+from hwsim import Hwsim
+
+class Test(unittest.TestCase):
+ # Test that we do not periodically retry roaming if the
transision looks
+ # like this: LOW [roam] [new bss] HIGH.
+ def test_stop_retry(self):
+ hwsim = Hwsim()
+
+ bss_hostapd = [ HostapdCLI(config='ssid1.conf'),
+ HostapdCLI(config='ssid2.conf') ]
+ bss_radio = [ hwsim.get_radio('rad0'),
+ hwsim.get_radio('rad1') ]
+
+ rule0 = hwsim.rules.create()
+ rule0.source = bss_radio[0].addresses[0]
+ rule0.bidirectional = True
+
+ rule1 = hwsim.rules.create()
+ rule1.source = bss_radio[1].addresses[0]
+ rule1.bidirectional = True
+
+ # Fill in the neighbor AP tables in both BSSes. By default
each
+ # instance knows only about current BSS, even inside one
hostapd
+ # process.
+ # Roaming still works without the neighbor AP table but
neighbor
+ # reports have to be disabled in the .conf files
+ bss0_nr = ''.join(bss_radio[0].addresses[0].split(':')) + \
+ '8f0000005101060603000000'
+ bss1_nr = ''.join(bss_radio[1].addresses[0].split(':')) + \
+ '8f0000005102060603000000'
+
+ bss_hostapd[0].set_neighbor(bss_radio[1].addresses[0],
'TestRoamRetry',
+ bss1_nr)
+ bss_hostapd[1].set_neighbor(bss_radio[0].addresses[0],
'TestRoamRetry',
+ bss0_nr)
+
+ # Start in the vicinity of BSS 0, check that iwd connects to
BSS 0
+ rule0.signal = -2000
+ rule1.signal = -5000
+
+ wd = IWD()
+
+ psk_agent = PSKAgent("secret123")
+ wd.register_psk_agent(psk_agent)
+
+ devices = wd.list_devices(1)
+ device = devices[0]
+
+ condition = 'not obj.scanning'
+ wd.wait_for_object_condition(device, condition)
+
+ device.scan()
+
+ condition = 'not obj.scanning'
+ wd.wait_for_object_condition(device, condition)
+
+ ordered_network =
device.get_ordered_network('TestRoamRetry')
+
+ self.assertEqual(ordered_network.type, NetworkType.psk)
+
+ condition = 'not obj.connected'
+ wd.wait_for_object_condition(ordered_network.network_object,
condition)
+
+ ordered_network.network_object.connect()
+
+ condition = 'obj.state == DeviceState.connected'
+ wd.wait_for_object_condition(device, condition)
+
+ self.assertTrue(bss_hostapd[0].list_sta())
+ self.assertFalse(bss_hostapd[1].list_sta())
+
+ wd.wait(5)
Generally we try and avoid waits/sleeps at all costs because its very
unreliable. For example test-runner is used by some people inside a VM
(which then nests another VM) and this can be extremely slow. This
causes all kinds of weird behavior when a test relies on a sleep or
wait. Sometimes waits are necissary but in this case I don't think it
is.
Instead it looks like this wait could be removed completely, then also
remove max_wait=10 below. This is, again, not something we generally
set explicitly for reasons mentioned above. Your fast system may start
roaming in 10 seconds, but a slow VM may take longer.
+
+ # Now push the signal below the RSSI threshold and check
that iwd
+ # connects to BSS 1
+ rule0.signal = -8000
+
+ condition = 'obj.state == DeviceState.roaming'
+ wd.wait_for_object_condition(device, condition, max_wait=10)
I would just remove max_wait here.
+
+ # Check that iwd is on BSS 1 once out of roaming state and
doesn't
+ # go through 'disconnected', 'autoconnect', 'connecting'
in
between
+ condition = 'obj.state != DeviceState.roaming'
+ wd.wait_for_object_condition(device, condition, max_wait=5)
And here.
+
+ self.assertEqual(device.state, iwd.DeviceState.connected)
+ self.assertTrue(bss_hostapd[1].list_sta())
+
+ wd.wait(5)
I also would remove this wait.
+
+ # Now make sure that we don't roam anymore. In order to
catch this via
+ # DeviceState, a suitable roaming target needs to be
available. So jack
+ # up the RSSI of BSS 0 again. The retry interval is 60
seconds, so we
+ # should have roamed within that timeframe.
+ rule0.signal = -2000
+
+ condition = 'obj.state == DeviceState.roaming'
+ self.assertRaises(TimeoutError,
wd.wait_for_object_condition, device,
+ condition, max_wait=60)
+
+ device.disconnect()
+
+ condition = 'not obj.connected'
+ wd.wait_for_object_condition(ordered_network.network_object,
condition)
+
+ wd.unregister_psk_agent(psk_agent)
+
+ rule0.remove()
+ rule1.remove()
+
+ @classmethod
+ def setUpClass(cls):
+ pass
+
+ @classmethod
+ def tearDownClass(cls):
+ IWD.clear_storage()
+
+if __name__ == '__main__':
+ unittest.main(exit=True)
Thanks again for your patches! Sorry if its frustrating that our test
framework has what seem like 'rules' which are undocumented and not
intuative. These type of things have been added over time for certain
cases and not much care was taken to prevent them from being used
generally. Besides these minor things the tests look great.
Thanks,
James