Skip to contentSkip to conversation

hwsim: return radio ID on create

PATCH In review James Prestwood 2 participants 18 messages Aug 27, 2020 Kbuild

lore
Share & tools
lore
#0 lore raw

PATCH 1/16 hwsim: return radio ID on create

Hwsim was relying on some internal behavior of mac80211_hwsim where new radios are created with ID's starting at zero and incremented. While this is a reasonable assumption its better to obtain the actual radio ID since mac80211_hwsim returns it in the radio creation callback.

Now hwsim will return the radio ID when creating radios. Negative returns are still errors, but any value >= 0 indicates the radio ID of the newly created radio.

---
 tools/hwsim.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
tools/hwsim.c +7 -2
index 02053fa1..467ccd2d 100644
@@ -216,6 +216,7 @@ static void create_callback(struct l_genl_msg *msg, void *user_data)
 		radio_id = err;
 
 		l_info("Created new radio with id %u", radio_id);
+		exit_status = radio_id;
 	} else {
 		l_warn("Failed to get create return value");
 		exit_status = EXIT_FAILURE;
@@ -2605,7 +2606,8 @@ static void usage(void)
 	printf("\thwsim [options]\n");
 	printf("Options:\n"
 		"\t-L, --list [id]        List simulated radios\n"
-		"\t-C, --create           Create new simulated radio\n"
+		"\t-C, --create           Create new simulated radio. The "
+						"return value is the new radio ID\n"
 		"\t-D, --destroy <id>     Destroy existing radio\n"
 		"\t-n, --name <name>      Name of a radio to be created\n"
 		"\t-i, --nointerface      Do not create VIF\n"
@@ -2632,6 +2634,7 @@ static const struct option main_options[] = {
 int main(int argc, char *argv[])
 {
 	int actions = 0;
+	int ret;
 
 	for (;;) {
 		int opt;
@@ -2729,7 +2732,9 @@ int main(int argc, char *argv[])
 		goto done;
 	}
 
-	exit_status = l_main_run_with_signal(signal_handler, NULL);
+	ret = l_main_run_with_signal(signal_handler, NULL);
+	if (ret)
+		exit_status = ret;
 
 	l_genl_family_free(hwsim);
 	l_genl_family_free(nl80211);
Signature · 1 line
2.21.1
#1 lore raw

PATCH 2/16 auto-t: prepare autotests for test-runner re-write

The tests basically remained the same with a few minor changes. The wiphy_map and in turn hostapd_map are no longer used. This was already partially converted a long time ago when the 'config' parameter was added to HostapdCLI. This patch fully converts all autotests to use 'config' rather than looking up by interface.

Some test scripts were named 'test.py' which was fine before but the new rewrite actually loads each python test as a module. The name 'test' is too ambiguous and causes issues due to a native python module with the same name. All of these files were renamed to 'connection_test.py'.

---
 .../{test.py => connection_test.py}           |  0
 .../testAP/{test.py => connection_test.py}    |  9 ++--
 autotests/testAP/failure_test.py              |  6 +--
 autotests/testAPRoam/connection_test.py       |  2 -
 .../testBSSBlacklist/all_blacklisted_test.py  |  4 --
 autotests/testBSSBlacklist/bad_pass_test.py   |  4 --
 autotests/testBSSBlacklist/connection_test.py |  1 -
 .../testBSSBlacklist/temp_blacklist_test.py   |  4 --
 .../connect_command_test.py                   | 42 +++++++------------
 .../disconnect_by_ap_test.py                  |  4 +-
 autotests/testEAP-AKA/connection_test.py      |  1 -
 .../testEAP-PEAPv0-CryptoBinding/ISK_test.py  |  1 -
 .../NoISK_test.py                             |  1 -
 .../testEAP-PEAPv0-CryptoBinding/main.conf    |  2 -
 autotests/testEAP-PWD/connection_test.py      |  1 -
 autotests/testEAP-SIM/connection_test.py      |  1 -
 .../connection_test.py                        | 11 ++---
 .../testEAP-TTLS-CHAP/connection_test.py      |  1 -
 .../testEAP-TTLS-MSCHAP/connection_test.py    |  1 -
 autotests/testEAP-TTLS-PAP/connection_test.py |  1 -
 autotests/testEAP-WPS-Frag/wps_frag_test.py   |  4 +-
 autotests/testEAP-WPS/four_digit_pin_test.py  |  4 +-
 autotests/testEAP-WPS/pin_test.py             |  4 +-
 autotests/testEAP-WPS/push_button_test.py     |  5 +--
 autotests/testFILS/fils_256_test.py           |  1 -
 autotests/testFILS/fils_384_test.py           |  1 -
 .../{test.py => connection_test.py}           |  2 +-
 .../{test.py => connection_test.py}           |  2 +-
 .../{test.py => connection_test.py}           |  2 +-
 .../{test.py => connection_test.py}           |  2 +-
 .../{test.py => connection_test.py}           | 18 +++++---
 .../{test.py => connection_test.py}           |  2 +-
 .../{test.py => connection_test.py}           |  2 +-
 autotests/testOWE/connection_test.py          |  1 -
 autotests/testOWE/renegotiate_test.py         |  1 -
 .../{test.py => connection_test.py}           |  2 +-
 .../{test.py => connection_test.py}           |  0
 autotests/testSAE/connection_test.py          | 10 ++---
 autotests/testSAE/group_20_connection_test.py | 10 ++---
 .../testSAQuery-spoofing/connection_test.py   |  2 +-
 autotests/testSAQuery/connection_test.py      |  2 +-
 41 files changed, 57 insertions(+), 117 deletions(-)
 rename autotests/testAP-no-support/{test.py => connection_test.py} (100%)
 rename autotests/testAP/{test.py => connection_test.py} (94%)
 delete mode 100644 autotests/testEAP-PEAPv0-CryptoBinding/main.conf
 rename autotests/testFT-8021x-roam/{test.py => connection_test.py} (99%)
 rename autotests/testFT-FILS-SHA256/{test.py => connection_test.py} (99%)
 rename autotests/testFT-FILS-SHA384/{test.py => connection_test.py} (99%)
 rename autotests/testFT-PSK-over-DS/{test.py => connection_test.py} (99%)
 rename autotests/testFT-PSK-roam/{test.py => connection_test.py} (95%)
 rename autotests/testFT-SAE-roam/{test.py => connection_test.py} (99%)
 rename autotests/testHT-VHT/{test.py => connection_test.py} (98%)
 rename autotests/testPreauth-roam/{test.py => connection_test.py} (98%)
 rename autotests/testRSSIAgent/{test.py => connection_test.py} (100%)
autotests/testAP-no-support/connection_test.py renamed from autotests/testAP-no-support/test.py +0 -0
similarity index 100%
rename from autotests/testAP-no-support/test.py
rename to autotests/testAP-no-support/connection_test.py
autotests/testAP/connection_test.py renamed from autotests/testAP/test.py +5 -4
similarity index 94%
rename from autotests/testAP/test.py
rename to autotests/testAP/connection_test.py
index 4cacf9ad..36302da1 100644
@@ -3,17 +3,17 @@
 import unittest
 import sys, os
 
-sys.path.append('../util')
 import iwd
 from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
-import hostapd
+from hostapd import HostapdCLI
 import testutil
 
 class Test(unittest.TestCase):
 
     def client_connect(self, wd, dev):
+        hostapd = HostapdCLI(config='psk-ccmp.conf')
 
         ordered_network = dev.get_ordered_network('TestAP1', True)
 
@@ -30,8 +30,7 @@ class Test(unittest.TestCase):
         wd.unregister_psk_agent(psk_agent)
 
         testutil.test_iface_operstate(dev.name)
-        testutil.test_ifaces_connected(list(hostapd.hostapd_map.keys())[0],
-                                       dev.name)
+        testutil.test_ifaces_connected(hostapd.ifname, dev.name)
 
         dev.disconnect()
 
@@ -57,6 +56,7 @@ class Test(unittest.TestCase):
             wd.wait_for_object_condition(dev2, condition)
 
             ordered_networks = dev2.get_ordered_networks()
+
             networks = { n.name: n for n in ordered_networks }
             self.assertEqual(networks['TestAP1'].type, NetworkType.psk)
             self.assertEqual(networks['TestAP2'].type, NetworkType.psk)
@@ -66,6 +66,7 @@ class Test(unittest.TestCase):
 
             try:
                 dev2.disconnect()
+
                 condition = 'not obj.connected'
                 wd.wait_for_object_condition(dev2, condition)
             except:
autotests/testAP/failure_test.py +3 -3
index d30bccb4..a2622f45 100644
@@ -8,12 +8,13 @@ import iwd
 from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
-import hostapd
+from hostapd import HostapdCLI
 import testutil
 
 class Test(unittest.TestCase):
 
     def client_connect(self, wd, dev):
+        hostapd = HostapdCLI(config='psk-ccmp.conf')
 
         ordered_network = dev.get_ordered_network('TestAP1', True)
 
@@ -30,8 +31,7 @@ class Test(unittest.TestCase):
         wd.unregister_psk_agent(psk_agent)
 
         testutil.test_iface_operstate(dev.name)
-        testutil.test_ifaces_connected(list(hostapd.hostapd_map.keys())[0],
-                                       dev.name)
+        testutil.test_ifaces_connected(hostapd.ifname, dev.name)
 
         dev.disconnect()
 
autotests/testAPRoam/connection_test.py +0 -2
index 292754c9..c8c2ca9f 100644
@@ -10,8 +10,6 @@ from iwd import PSKAgent
 from iwd import NetworkType
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
-
 from hwsim import Hwsim
 
 class Test(unittest.TestCase):
autotests/testBSSBlacklist/all_blacklisted_test.py +0 -4
index 78239309..099804a8 100644
@@ -10,12 +10,8 @@ from iwd import PSKAgent
 from iwd import NetworkType
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
-
 from hwsim import Hwsim
 
-import time
-
 class Test(unittest.TestCase):
 
     def test_connection_success(self):
autotests/testBSSBlacklist/bad_pass_test.py +0 -4
index 3516f3be..220ffcc8 100644
@@ -10,12 +10,8 @@ from iwd import PSKAgent
 from iwd import NetworkType
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
-
 from hwsim import Hwsim
 
-import time
-
 class Test(unittest.TestCase):
 
     def test_connection_success(self):
autotests/testBSSBlacklist/connection_test.py +0 -1
index 7433d5f3..825439d4 100644
@@ -10,7 +10,6 @@ from iwd import PSKAgent
 from iwd import NetworkType
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 from hwsim import Hwsim
 
autotests/testBSSBlacklist/temp_blacklist_test.py +0 -4
index f43f807c..b2b57035 100644
@@ -10,12 +10,8 @@ from iwd import PSKAgent
 from iwd import NetworkType
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
-
 from hwsim import Hwsim
 
-import time
-
 class Test(unittest.TestCase):
 
     def test_connection_success(self):
autotests/testClientNonInteractive/connect_command_test.py +14 -28

105 lines not on this page · raw message

autotests/testDisconnectByAP/disconnect_by_ap_test.py +1 -3
index 298d75c4..f003ec0c 100644
@@ -10,7 +10,6 @@ from iwd import DeviceState
 from iwd import NetworkType
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
@@ -20,8 +19,7 @@ class Test(unittest.TestCase):
         devices = wd.list_devices(1)
         device = devices[0]
 
-        hostapd_if = list(hostapd_map.values())[0]
-        hostapd = HostapdCLI(hostapd_if)
+        hostapd = HostapdCLI(config='ssidOpen.conf')
 
         device.scan()
 
autotests/testEAP-AKA/connection_test.py +0 -1
index bcdb1d92..c4b7c2f9 100644
@@ -10,7 +10,6 @@ from iwd import NetworkType
 from hlrauc import AuthCenter
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
autotests/testEAP-PEAPv0-CryptoBinding/ISK_test.py +0 -1
index 7ba49384..a25f99ef 100644
@@ -11,7 +11,6 @@ from iwd import NetworkType
 import testutil
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
autotests/testEAP-PEAPv0-CryptoBinding/NoISK_test.py +0 -1
index 0f7d432c..33ff0285 100644
@@ -11,7 +11,6 @@ from iwd import NetworkType
 import testutil
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
autotests/testEAP-PEAPv0-CryptoBinding/main.conf deleted +0 -2
deleted file mode 100644
index 55a5543e..00000000
@@ -1,2 +0,0 @@
-[General]
-UseDefaultInterface=true
autotests/testEAP-PWD/connection_test.py +0 -1
index 0c722c44..2edc45b8 100644
@@ -10,7 +10,6 @@ from iwd import PSKAgent
 from iwd import NetworkType
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
autotests/testEAP-SIM/connection_test.py +0 -1
index 97956d0c..617d833b 100644
@@ -10,7 +10,6 @@ from iwd import NetworkType
 from hlrauc import AuthCenter
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
autotests/testEAP-TLS-embedded-pems/connection_test.py +3 -8
index 1102b810..5d46868d 100644
@@ -9,23 +9,18 @@ from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
 import testutil
-import hostapd
+from hostapd import HostapdCLI
 
 class Test(unittest.TestCase):
 
     def do_test_connection_success(self, ssid, passphrase=None):
+        hostapd = HostapdCLI(config=ssid + '.conf')
         wd = IWD()
 
         if passphrase:
             psk_agent = PSKAgent(passphrase)
             wd.register_psk_agent(psk_agent)
 
-        hostapd_ifname = None
-        for ifname in hostapd.hostapd_map:
-            if ssid + '.conf' in hostapd.hostapd_map[ifname].config:
-                hostapd_ifname = ifname
-                break
-
         devices = wd.list_devices(1)
         device = devices[0]
 
@@ -52,7 +47,7 @@ class Test(unittest.TestCase):
         wd.wait_for_object_condition(ordered_network.network_object, condition)
 
         testutil.test_iface_operstate()
-        testutil.test_ifaces_connected(hostapd_ifname, device.name)
+        testutil.test_ifaces_connected(hostapd.ifname, device.name)
 
         device.disconnect()
 
autotests/testEAP-TTLS-CHAP/connection_test.py +0 -1
index e3719669..331e799f 100644
@@ -11,7 +11,6 @@ from iwd import PSKAgent
 from iwd import NetworkType
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
autotests/testEAP-TTLS-MSCHAP/connection_test.py +0 -1
index ea245a38..973370a8 100644
@@ -11,7 +11,6 @@ from iwd import PSKAgent
 from iwd import NetworkType
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
autotests/testEAP-TTLS-PAP/connection_test.py +0 -1
index ce787b01..a8f6fde7 100644
@@ -11,7 +11,6 @@ from iwd import PSKAgent
 from iwd import NetworkType
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
autotests/testEAP-WPS-Frag/wps_frag_test.py +1 -3
index 9d106a75..b9be0159 100644
@@ -9,7 +9,6 @@ from iwd import IWD
 from iwd import DeviceState
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
@@ -32,8 +31,7 @@ class Test(unittest.TestCase):
 
     @classmethod
     def setUpClass(cls):
-        cls.hostapd_if = list(hostapd_map.values())[0]
-        cls.hostapd = HostapdCLI(cls.hostapd_if)
+        cls.hostapd = HostapdCLI(config='ssid-wps-small-mtu.conf')
 
         cls.hostapd.wps_push_button()
 
autotests/testEAP-WPS/four_digit_pin_test.py +1 -3
index feb4222d..10afaa5d 100644
@@ -9,7 +9,6 @@ from iwd import IWD
 from iwd import DeviceState
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
@@ -39,8 +38,7 @@ class Test(unittest.TestCase):
 
     @classmethod
     def setUpClass(cls):
-        cls.hostapd_if = list(hostapd_map.values())[0]
-        cls.hostapd = HostapdCLI(cls.hostapd_if)
+        cls.hostapd = HostapdCLI(config='ssidWPS.conf')
 
     @classmethod
     def tearDownClass(cls):
autotests/testEAP-WPS/pin_test.py +1 -3
index 080a91e1..706dc20b 100644
@@ -9,7 +9,6 @@ from iwd import IWD
 from iwd import DeviceState
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
 
 class Test(unittest.TestCase):
 
@@ -42,8 +41,7 @@ class Test(unittest.TestCase):
 
     @classmethod
     def setUpClass(cls):
-        cls.hostapd_if = list(hostapd_map.values())[0]
-        cls.hostapd = HostapdCLI(cls.hostapd_if)
+        cls.hostapd = HostapdCLI(config='ssidWPS.conf')
 
     @classmethod
     def tearDownClass(cls):
autotests/testEAP-WPS/push_button_test.py +1 -4
index bbf09dcb..f82a56b5 100644
@@ -9,8 +9,6 @@ from iwd import IWD
 from iwd import DeviceState
 
 from hostapd import HostapdCLI
-from hostapd import hostapd_map
-
 class Test(unittest.TestCase):
 
     def push_button_success(self, wd):
@@ -38,8 +36,7 @@ class Test(unittest.TestCase):
 
     @classmethod
     def setUpClass(cls):
-        cls.hostapd_if = list(hostapd_map.values())[0]
-        cls.hostapd = HostapdCLI(cls.hostapd_if)
+        cls.hostapd = HostapdCLI(config='ssidWPS.conf')
 
     @classmethod
     def tearDownClass(cls):
autotests/testFILS/fils_256_test.py +0 -1
index aa9e441d..af033d4a 100644
@@ -9,7 +9,6 @@ import iwd
 from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
-from hostapd import hostapd_map
 from hostapd import HostapdCLI
 import testutil
 
autotests/testFILS/fils_384_test.py +0 -1
index ed5cc3b0..70e3bc87 100644
@@ -9,7 +9,6 @@ import iwd
 from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
-from hostapd import hostapd_map
 from hostapd import HostapdCLI
 import testutil
 
autotests/testFT-8021x-roam/connection_test.py renamed from autotests/testFT-8021x-roam/test.py +1 -1
similarity index 99%
rename from autotests/testFT-8021x-roam/test.py
rename to autotests/testFT-8021x-roam/connection_test.py
index 0e6f733e..65c73492 100644
@@ -8,7 +8,7 @@ import iwd
 from iwd import IWD
 from iwd import NetworkType
 from hwsim import Hwsim
-from hostapd import HostapdCLI, hostapd_map
+from hostapd import HostapdCLI
 import testutil
 
 class Test(unittest.TestCase):
autotests/testFT-FILS-SHA256/connection_test.py renamed from autotests/testFT-FILS-SHA256/test.py +1 -1
similarity index 99%
rename from autotests/testFT-FILS-SHA256/test.py
rename to autotests/testFT-FILS-SHA256/connection_test.py
index 7b800f1c..16f46210 100644
@@ -9,7 +9,7 @@ from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
 from hwsim import Hwsim
-from hostapd import HostapdCLI, hostapd_map
+from hostapd import HostapdCLI
 import testutil
 
 class Test(unittest.TestCase):
autotests/testFT-FILS-SHA384/connection_test.py renamed from autotests/testFT-FILS-SHA384/test.py +1 -1
similarity index 99%
rename from autotests/testFT-FILS-SHA384/test.py
rename to autotests/testFT-FILS-SHA384/connection_test.py
index 7b800f1c..16f46210 100644
@@ -9,7 +9,7 @@ from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
 from hwsim import Hwsim
-from hostapd import HostapdCLI, hostapd_map
+from hostapd import HostapdCLI
 import testutil
 
 class Test(unittest.TestCase):
autotests/testFT-PSK-over-DS/connection_test.py renamed from autotests/testFT-PSK-over-DS/test.py +1 -1
similarity index 99%
rename from autotests/testFT-PSK-over-DS/test.py
rename to autotests/testFT-PSK-over-DS/connection_test.py
index f3dd088c..2cfdf245 100644
@@ -9,7 +9,7 @@ from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
 from hwsim import Hwsim
-from hostapd import HostapdCLI, hostapd_map
+from hostapd import HostapdCLI
 import testutil
 
 class Test(unittest.TestCase):
autotests/testFT-PSK-roam/connection_test.py renamed from autotests/testFT-PSK-roam/test.py +12 -6
similarity index 95%
rename from autotests/testFT-PSK-roam/test.py
rename to autotests/testFT-PSK-roam/connection_test.py
index 2443593d..1b32cc0b 100644
@@ -9,7 +9,7 @@ from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
 from hwsim import Hwsim
-from hostapd import HostapdCLI, hostapd_map
+from hostapd import HostapdCLI
 import testutil
 
 class Test(unittest.TestCase):
@@ -24,12 +24,14 @@ class Test(unittest.TestCase):
         rule1.source = self.bss_radio[1].addresses[0]
         rule1.bidirectional = True
 
-        wd = IWD()
+        wd = self.wd
 
         psk_agent = PSKAgent("EasilyGuessedPassword")
         wd.register_psk_agent(psk_agent)
 
         device = wd.list_devices(1)[0]
+        # prevent autoconnect
+        device.disconnect()
 
         # Check that iwd selects BSS 0 first
         rule0.signal = -2000
@@ -97,6 +99,7 @@ class Test(unittest.TestCase):
                           (self.bss_hostapd[0].ifname, device.name))
 
     def test_roam_on_beacon_loss(self):
+        print("Starting test_roam_on_beacon_loss")
         hwsim = Hwsim()
 
         rule0 = hwsim.rules.create()
@@ -107,12 +110,14 @@ class Test(unittest.TestCase):
         rule1.source = self.bss_radio[1].addresses[0]
         rule1.bidirectional = True
 
-        wd = IWD()
+        wd = self.wd
 
         psk_agent = PSKAgent("EasilyGuessedPassword")
         wd.register_psk_agent(psk_agent)
 
         device = wd.list_devices(1)[0]
+        # prevent autoconnect
+        device.disconnect()
 
         # Check that iwd selects BSS 0 first
         rule0.signal = -2000
@@ -176,6 +181,8 @@ class Test(unittest.TestCase):
         testutil.test_ifaces_connected(self.bss_hostapd[1].ifname, device.name)
         self.assertRaises(Exception, testutil.test_ifaces_connected,
                           (self.bss_hostapd[0].ifname, device.name))
+    def setUp(self):
+        self.wd = IWD()
 
     def tearDown(self):
         os.system('ifconfig "' + self.bss_hostapd[0].ifname + '" down')
@@ -184,15 +191,14 @@ class Test(unittest.TestCase):
         os.system('ifconfig "' + self.bss_hostapd[1].ifname + '" up')
 
         hwsim = Hwsim()
-        wd = IWD()
-        device = wd.list_devices(1)[0]
+        device = self.wd.list_devices(1)[0]
         try:
             device.disconnect()
         except:
             pass
 
         condition = 'obj.state == DeviceState.disconnected'
-        wd.wait_for_object_condition(device, condition)
+        self.wd.wait_for_object_condition(device, condition)
 
         for rule in list(hwsim.rules.keys()):
             del hwsim.rules[rule]
autotests/testFT-SAE-roam/connection_test.py renamed from autotests/testFT-SAE-roam/test.py +1 -1
similarity index 99%
rename from autotests/testFT-SAE-roam/test.py
rename to autotests/testFT-SAE-roam/connection_test.py
index 9c2b3ee1..3e209560 100644
@@ -9,7 +9,7 @@ from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
 from hwsim import Hwsim
-from hostapd import HostapdCLI, hostapd_map
+from hostapd import HostapdCLI
 import testutil
 
 class Test(unittest.TestCase):
autotests/testHT-VHT/connection_test.py renamed from autotests/testHT-VHT/test.py +1 -1
similarity index 98%
rename from autotests/testHT-VHT/test.py
rename to autotests/testHT-VHT/connection_test.py
index 0129d8a0..e4781ea0 100644
@@ -9,9 +9,9 @@ from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
 from hwsim import Hwsim
-from hostapd import HostapdCLI, hostapd_map
 import testutil
 from time import sleep
+from hostapd import HostapdCLI
 
 class Test(unittest.TestCase):
     def do_connect(self, wd, device, hostapd):
autotests/testOWE/connection_test.py +0 -1
index e4482bc0..539b06d0 100644
@@ -7,7 +7,6 @@ sys.path.append('../util')
 import iwd
 from iwd import IWD
 from iwd import NetworkType
-from hostapd import hostapd_map
 from hostapd import HostapdCLI
 import testutil
 
autotests/testOWE/renegotiate_test.py +0 -1
index 57705a59..7c736acd 100644
@@ -7,7 +7,6 @@ sys.path.append('../util')
 import iwd
 from iwd import IWD
 from iwd import NetworkType
-from hostapd import hostapd_map
 from hostapd import HostapdCLI
 import testutil
 
autotests/testPreauth-roam/connection_test.py renamed from autotests/testPreauth-roam/test.py +1 -1
similarity index 98%
rename from autotests/testPreauth-roam/test.py
rename to autotests/testPreauth-roam/connection_test.py
index 06babcea..ed043c3f 100644
@@ -9,7 +9,7 @@ from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
 from hwsim import Hwsim
-from hostapd import HostapdCLI, hostapd_map
+from hostapd import HostapdCLI
 import testutil
 
 class Test(unittest.TestCase):
autotests/testRSSIAgent/connection_test.py renamed from autotests/testRSSIAgent/test.py +0 -0
similarity index 100%
rename from autotests/testRSSIAgent/test.py
rename to autotests/testRSSIAgent/connection_test.py
autotests/testSAE/connection_test.py +3 -7
index 874eb833..56bb1f6d 100644
@@ -8,17 +8,13 @@ import iwd
 from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
-from hostapd import hostapd_map
+from hostapd import HostapdCLI
 import testutil
 
 class Test(unittest.TestCase):
 
     def validate_connection(self, wd):
-        hostapd_if = None
-
-        for hostapd in hostapd_map.values():
-            if hostapd.config == 'ssidSAE.conf':
-                hostapd_if = hostapd.name
+        hostapd = HostapdCLI(config='ssidSAE.conf')
 
         psk_agent = PSKAgent("secret123")
         wd.register_psk_agent(psk_agent)
@@ -56,7 +52,7 @@ class Test(unittest.TestCase):
         wd.wait(2)
 
         testutil.test_iface_operstate(intf=device.name)
-        testutil.test_ifaces_connected(if0=device.name, if1=hostapd_if)
+        testutil.test_ifaces_connected(if0=device.name, if1=hostapd.ifname)
 
         device.disconnect()
 
autotests/testSAE/group_20_connection_test.py +3 -7
index 033c8850..5631878a 100644
@@ -8,17 +8,13 @@ import iwd
 from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
-from hostapd import hostapd_map
+from hostapd import HostapdCLI
 import testutil
 
 class Test(unittest.TestCase):
 
     def validate_connection(self, wd):
-        hostapd_if = None
-
-        for hostapd in hostapd_map.values():
-            if hostapd.config == 'ssidSAE-20.conf':
-                hostapd_if = hostapd.name
+        hostapd = HostapdCLI(config='ssidSAE-20.conf')
 
         psk_agent = PSKAgent("secret123")
         wd.register_psk_agent(psk_agent)
@@ -56,7 +52,7 @@ class Test(unittest.TestCase):
         wd.wait(2)
 
         testutil.test_iface_operstate(intf=device.name)
-        testutil.test_ifaces_connected(if0=device.name, if1=hostapd_if)
+        testutil.test_ifaces_connected(if0=device.name, if1=hostapd.ifname)
 
         device.disconnect()
 
autotests/testSAQuery-spoofing/connection_test.py +1 -1
index e9d31c15..4887b172 100644
@@ -9,7 +9,7 @@ from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
 from hwsim import Hwsim
-from hostapd import HostapdCLI, hostapd_map
+from hostapd import HostapdCLI
 
 from time import sleep
 
autotests/testSAQuery/connection_test.py +1 -1
index de0fe2cd..9ea95e2b 100644
@@ -8,7 +8,7 @@ import iwd
 from iwd import IWD
 from iwd import PSKAgent
 from iwd import NetworkType
-from hostapd import HostapdCLI, hostapd_map
+from hostapd import HostapdCLI
 
 class Test(unittest.TestCase):
 
Signature · 1 line
2.21.1
#2 lore raw

PATCH 3/16 auto-t: introduce pure python test-runner re-write

In reply to James Prestwood

This patch completely re-writes test-runner in Python. This was done because the existing C test-runner had some clunky work arounds and maintaining or adding new features was starting to become a huge pain.

There were a few aspects of test-runner which continually had to be dealt with when adding any new functionality:

* Argument parsing: Adding new arguments to test-runner wasn't so bad, but if you wanted those arguments passed into the VM it became a huge pain. Arguments needed to be parsed, then re-formatted into the qemu command line, then re-parsed in a special order (backwards) once in the VM. The burden for adding new arguments was quite high so it was avoided (at least by me) at all costs.
* The separation between C and Python: The tests are all written in python, but the executables, radios, and interfaces were all created from C. The way we solved this was by encoding the require info as environment variables, then parsing those from Python. It worked, but it was, again, a huge pain.
* Process management: It started with all processes being launched from C, but eventually tests required the ability to start IWD, or kill hostapd ungracefully in order to test certain functionality. Since the processes were tracked in C, Python had no way of signalling that it killed a process and when it started one C had no idea. This was mitigated (basically by killall), but it was no where close to an elegant solution.

Re-writing test-runner in python solves all these problems and will be much easier to maintain.

* Argument parsing: Now all arguments are forwarded automatically to the VM. The ArgParse library takes care of parsing and each argument is stored in a dictionary.
* Separation between C and Python: No more C, so no more separation.
* Process management: Python will now manage all processes. This allows a test to kill, restart, or start a new process and not have to remember the PID or to kill it after the test.

There are a few more important aspects of the python implementation that should now be considered when writing new tests:

* The IWD constructor now has different default arugments. IWD will always be started unless specified and the configuration directory will always be /tmp
* Any non *.py file in the test directory will be copied to /tmp. This avoids the need for 'tmpfs_extra_stuff' completely.
* ctrl_interface will automatically be appended to every hostapd config. There is no need to include this in a config file from now on.
* Test cleanup is extremely important. All tests get run in the same interpreter now and the tests themselves are actually loaded as python modules. This means e.g. if you somehow kept a reference to IWD() any subsequent tests would not start since IWD is still running.
* For debugging, the test context can be printed which shows running processes, radios, and interfaces.

Three non-native python modules were used: PrettyTable, colored, and pyroute2

$ pip3 install prettytable
$ pip3 install termcolor
$ pip3 install pyroute2
---
 autotests/util/config.py |    6 +
 tools/py_runner.py       | 1245 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 1251 insertions(+)
 create mode 100644 autotests/util/config.py
 create mode 100755 tools/py_runner.py
autotests/util/config.py new file +6 -0
new file mode 100644
index 00000000..be8edbfc
@@ -0,0 +1,6 @@
+#
+# Acts as a global store for test information. 'ctx' is set by the creator of
+# of the TestContext (test-runner).
+#
+
+ctx = {}
tools/py_runner.py new file +1245 -0

1,245 lines not on this page · raw message

Signature · 1 line
2.21.1
#3 lore raw

PATCH 4/16 auto-t: hostapd.py: update to work with test-runner rewrite

In reply to James Prestwood

Before hostapd was initialized using the wiphy_map which has now gone away. Instead we have a global config module which contains a single 'ctx'. This is the centeral store for all test information.

This patch converts hostapd.py to lookup instances by already initialized Hostapd object. The interface parameter was removed since all tests have been converted to use config= instead.

In addition HostapdCLI was changed to allow no parameters if there is only a single hostapd instance.

---
 autotests/util/hostapd.py | 57 +++++++++++++++++----------------------
 1 file changed, 24 insertions(+), 33 deletions(-)
autotests/util/hostapd.py +24 -33
index 0ed4e004..b8cfe231 100644
@@ -1,11 +1,11 @@
 #!/usr/bin/python3
 import os, os.path
-from wiphy import wiphy_map
 import re
 import socket
 import select
 import time
 from gi.repository import GLib
+from config import ctx
 
 chan_freq_map = [
     None,
@@ -28,28 +28,24 @@ chan_freq_map = [
 ctrl_count = 0
 mainloop = GLib.MainLoop()
 
-hostapd_map = {ifname: intf for wname, wiphy in wiphy_map.items()
-        for ifname, intf in wiphy.interface_map.items()
-        if wiphy.use == 'hostapd'}
-
 class HostapdCLI:
-    def _init_hostapd(self, interface=None, config=None):
+    def _init_hostapd(self, config=None):
         global ctrl_count
+        interface = None
+
+        if not config and len(ctx.hostapd.instances) > 1:
+            raise Exception('config must be provided if more than one hostapd instance exists')
 
-        if not interface and not config:
-            raise Exception('interface or config must be provided')
+        hapd = ctx.hostapd[config]
 
-        if not interface:
-            for intf in hostapd_map.values():
-                if intf.config == config:
-                    interface = intf
-                    break
+        self.interface = hapd.intf
+        self.config = hapd.config
 
-        if not interface:
+        if not self.interface:
             raise Exception('config %s not found' % config)
 
-        self.ifname = interface.name
-        self.socket_path = os.path.dirname(interface.ctrl_interface)
+        self.ifname = self.interface.name
+        self.socket_path = os.path.dirname(self.interface.ctrl_interface)
 
         self.cmdline = 'hostapd_cli -p"' + self.socket_path + '" -i"' + \
                 self.ifname + '"'
@@ -61,6 +57,7 @@ class HostapdCLI:
                             str(ctrl_count)
         self.ctrl_sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
         self.ctrl_sock.bind(self.local_ctrl)
+
         self.ctrl_sock.connect(self.socket_path + '/' + self.ifname)
 
         if 'OK' not in self._ctrl_request('ATTACH'):
@@ -68,8 +65,8 @@ class HostapdCLI:
 
         ctrl_count = ctrl_count + 1
 
-    def __init__(self, interface=None, config=None):
-        self._init_hostapd(interface, config)
+    def __init__(self, config=None):
+        self._init_hostapd(config)
 
     def wait_for_event(self, event, timeout=10):
         global mainloop
@@ -115,15 +112,13 @@ class HostapdCLI:
 
     def _del_hostapd(self, force=False):
         self.ctrl_sock.close()
+        os.remove(self.local_ctrl)
 
         if self._hostapd_restarted:
-            if force:
-                os.system('killall -9 hostapd')
-            else:
-                os.system('killall hostapd')
+            ctx.stop_process(ctx.hostapd.process, force)
 
-            os.system('ifconfig %s down' % self.ifname)
-            os.system('ifconfig %s up' % self.ifname)
+            self.interface.set_interface_state('down')
+            self.interface.set_interface_state('up')
 
     def __del__(self):
         self._del_hostapd()
@@ -139,10 +134,7 @@ class HostapdCLI:
 
     def eapol_reauth(self, client_address):
         cmd = 'IFNAME=' + self.ifname + ' EAPOL_REAUTH ' + client_address
-        s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
-        s.connect(self.socket_path + '/' + self.ifname)
-        s.sendall(cmd.encode('utf-8'))
-        s.close()
+        self.ctrl_sock.sendall(cmd.encode('utf-8'))
 
     def reload(self):
         # Seemingly all three commands needed for the instance to notice
@@ -192,7 +184,7 @@ class HostapdCLI:
 
     def get_config_value(self, key):
         # first find the right config file
-        with open(hostapd_map[self.ifname].config, 'r') as f:
+        with open(self.config, 'r') as f:
             # read in config file and search for key
             cfg = f.read()
             match = re.search(r'%s=.*' % key, cfg)
@@ -200,6 +192,7 @@ class HostapdCLI:
                 return match.group(0).split('=')[1]
         return None
 
+
     def get_freq(self):
         return chan_freq_map[int(self.get_config_value('channel'))]
 
@@ -209,18 +202,16 @@ class HostapdCLI:
         '''
         # set flag so hostapd can be killed after the test
         self._hostapd_restarted = True
-        intf = hostapd_map[self.ifname]
 
         self._del_hostapd(force=True)
 
-        os.system('hostapd -g %s -i %s %s &' %
-                  (intf.ctrl_interface, intf.name, intf.config))
+        ctx.start_hostapd()
 
         # Give hostapd a second to start and initialize the control interface
         time.sleep(1)
 
         # New hostapd process, so re-init
-        self._init_hostapd(intf)
+        self._init_hostapd(config=self.config)
 
     def req_beacon(self, addr, request):
         '''
Signature · 1 line
2.21.1
#4 lore raw

PATCH 5/16 auto-t: testutil.py: update to work with test-runner rewrite

In reply to James Prestwood

Similar to the others, testutil.py was converted to use the global test context to lookup radios/interfaces rather than the wiphy_map

---
 autotests/util/testutil.py | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
autotests/util/testutil.py +4 -3
index aaa4e7e1..0a94e23a 100644
@@ -5,8 +5,8 @@ import fcntl
 import struct
 import select
 
-import wiphy
 import iwd
+from config import ctx
 
 HWSIM_ETHERTYPE = 0x0800
 HWSIM_PACKETLEN = 250
@@ -54,8 +54,9 @@ def tx(fromsock, tosock, src, dst):
 def test_connected(if0=None, if1=None, group=True):
     if if0 is None or if1 is None:
         iwd_list = [dev.name for dev in iwd.IWD.get_instance().list_devices()]
-        non_iwd_list = [ifname for w in wiphy.wiphy_map.values()
-                for ifname in w.interface_map]
+
+        non_iwd_list = [rad.interface.name for rad in ctx.radios if rad.interface is not None]
+
         for intf in iwd_list + non_iwd_list:
             if if0 is None:
                 if0 = intf
Signature · 1 line
2.21.1
#5 lore raw

PATCH 6/16 auto-t: ofono.py: fix timeout cleanup and wait for service

In reply to James Prestwood

Ofono.py was not cleaning up the timeout, nor waiting for the ofono.org service to come up before continuing.

---
 autotests/util/ofono.py | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)
autotests/util/ofono.py +18 -7
index 2bc6338b..f1ed14ee 100644
@@ -1,4 +1,5 @@
 import dbus
+import time
 from gi.repository import GLib
 
 SIM_AUTH_IFACE = 'org.ofono.SimAuthentication'
@@ -7,6 +8,14 @@ class Ofono(dbus.service.Object):
     def __init__(self):
         self._bus = dbus.SystemBus()
 
+        tries = 0
+
+        while not self._bus.name_has_owner('org.ofono'):
+            if tries > 100:
+                raise TimeoutError('Waiting for org.ofono service timed out')
+            tries += 1
+            time.sleep(0.1)
+
     def enable_modem(self, path):
         self._modem_path = path
         self._modem_iface = dbus.Interface(
@@ -37,11 +46,13 @@ class Ofono(dbus.service.Object):
             self._wait_timed_out = True
             return False
 
-        timeout = GLib.timeout_add_seconds(max_wait, wait_timeout_cb)
-        context = mainloop.get_context()
-        while (not self._sim_auth_up):
-            context.iteration(may_block=True)
-            if self._wait_timed_out:
-                raise TimeoutError('waiting for SimAuthentication timed out')
+        try:
+            timeout = GLib.timeout_add_seconds(max_wait, wait_timeout_cb)
+            context = mainloop.get_context()
+            while (not self._sim_auth_up):
+                context.iteration(may_block=True)
+                if self._wait_timed_out:
+                    raise TimeoutError('waiting for SimAuthentication timed out')
 
-        GLib.source_remove(timeout)
+        finally:
+            GLib.source_remove(timeout)
Signature · 1 line
2.21.1
#6 lore raw

PATCH 7/16 auto-t: iwd.py: update to work with test-runner rewrite

In reply to James Prestwood

The class initializer was changed to make starting IWD on by default. This allows us to not have multiple places where IWD is started. You can still pass False which will initialize the class but not start IWD itself. The configuration director was also chaged to /tmp by default. This was done by all tests requiring main.conf anyways, so we might as well make it the default.

---
 autotests/util/iwd.py | 48 ++++++++++++++-----------------------------
 1 file changed, 15 insertions(+), 33 deletions(-)
autotests/util/iwd.py +15 -33
index ef1ea80e..37daaeef 100755
@@ -15,7 +15,7 @@ import weakref
 from abc import ABCMeta, abstractmethod
 from enum import Enum
 
-import wiphy
+from config import ctx
 
 IWD_STORAGE_DIR =               '/var/lib/iwd'
 IWD_CONFIG_DIR =                '/etc/iwd'
@@ -873,7 +873,10 @@ class DeviceList(collections.Mapping):
 
 
 class IWD(AsyncOpAbstract):
-    ''''''
+    '''
+        Start an IWD instance. By default IWD will be started and with the
+        config directory set to /tmp.
+    '''
     _bus = dbus.SystemBus()
 
     _object_manager_if = None
@@ -882,40 +885,22 @@ class IWD(AsyncOpAbstract):
     _devices = None
     _instance = None
 
-    def __init__(self, start_iwd_daemon = False,
-                                               iwd_config_dir = IWD_CONFIG_DIR):
+    def __init__(self, start_iwd_daemon = True, iwd_config_dir = '/tmp'):
         global mainloop
         mainloop = GLib.MainLoop()
 
-        if start_iwd_daemon:
-            args = []
-            iwd_wiphys = [wname for wname, wiphy in wiphy.wiphy_map.items()
-                          if wiphy.use == 'iwd']
-            whitelist = ','.join(iwd_wiphys)
-
-            if os.environ.get('IWD_TEST_VALGRIND', None) == 'on':
-                    args.append('valgrind')
-                    args.append('--leak-check=full')
-                    args.append('--log-file=/tmp/valgrind.log')
-
-            os.environ["CONFIGURATION_DIRECTORY"] = iwd_config_dir;
-
-            args.append('iwd')
-            args.append('-p')
-            args.append(whitelist)
-            args.append('-d')
-
-            import subprocess
-            iwd_proc = subprocess.Popen(args)
+        self._iwd_proc = None
 
-            self._iwd_proc = iwd_proc
+        if start_iwd_daemon:
+            self._iwd_proc = ctx.start_iwd(iwd_config_dir)
 
         tries = 0
         while not self._bus.name_has_owner(IWD_SERVICE):
-            if os.environ['IWD_TEST_TIMEOUTS'] == 'on':
+            if ctx.args.gdb == 'None':
                 if tries > 100:
                     if start_iwd_daemon:
-                        iwd_proc.terminate()
+                        self._iwd_proc.kill()
+                        self._iwd_proc = None
                     raise TimeoutError('IWD has failed to start')
                 tries += 1
             time.sleep(0.1)
@@ -935,12 +920,9 @@ class IWD(AsyncOpAbstract):
         self._known_networks = None
         self._devices = None
 
-        self._iwd_proc.terminate()
-        self._iwd_proc.wait()
-
-        self._iwd_proc = None
-
-        del os.environ["CONFIGURATION_DIRECTORY"]
+        if self._iwd_proc is not None:
+            self._iwd_proc.kill()
+            self._iwd_proc = None
 
     @property
     def _object_manager(self):
Signature · 1 line
2.21.1
#7 lore raw

PATCH 8/16 auto-t: iwd.py: fix multiple timeout cleanup issues

In reply to James Prestwood

There were a few more places where the GLib timeout was not being removed which could cause the IWD object to hang around longer than expected causing problems for subsequent tests.

---
 autotests/util/iwd.py | 51 +++++++++++++++++++++++++------------------
 1 file changed, 30 insertions(+), 21 deletions(-)
autotests/util/iwd.py +30 -21
index 37daaeef..113039b6 100755
@@ -948,15 +948,18 @@ class IWD(AsyncOpAbstract):
             self._wait_timed_out = True
             return False
 
-        timeout = GLib.timeout_add_seconds(max_wait, wait_timeout_cb)
-        context = mainloop.get_context()
-        while not eval(condition_str):
-            context.iteration(may_block=True)
-            if self._wait_timed_out and os.environ['IWD_TEST_TIMEOUTS'] == 'on':
-                raise TimeoutError('[' + condition_str + ']'\
-                                   ' condition was not met in '\
-                                   + str(max_wait) + ' sec')
-        GLib.source_remove(timeout)
+        try:
+            timeout = GLib.timeout_add_seconds(max_wait, wait_timeout_cb)
+            context = mainloop.get_context()
+            while not eval(condition_str):
+                context.iteration(may_block=True)
+                if self._wait_timed_out and ctx.args.gdb == 'None':
+                    raise TimeoutError('[' + condition_str + ']'\
+                                       ' condition was not met in '\
+                                       + str(max_wait) + ' sec')
+        finally:
+            if not self._wait_timed_out:
+                GLib.source_remove(timeout)
 
     def wait(self, time):
         self._wait_timed_out = False
@@ -964,10 +967,14 @@ class IWD(AsyncOpAbstract):
             self._wait_timed_out = True
             return False
 
-        GLib.timeout_add(int(time * 1000), wait_timeout_cb)
-        context = mainloop.get_context()
-        while not self._wait_timed_out:
-            context.iteration(may_block=True)
+        try:
+            timeout = GLib.timeout_add(int(time * 1000), wait_timeout_cb)
+            context = mainloop.get_context()
+            while not self._wait_timed_out:
+                context.iteration(may_block=True)
+        finally:
+            if not self._wait_timed_out:
+                GLib.source_remove(timeout)
 
     @staticmethod
     def clear_storage():
@@ -1013,14 +1020,16 @@ class IWD(AsyncOpAbstract):
             self._wait_timed_out = True
             return False
 
-        timeout = GLib.timeout_add_seconds(max_wait, wait_timeout_cb)
-        context = mainloop.get_context()
-        while len(self._devices) < wait_to_appear:
-            context.iteration(may_block=True)
-            if self._wait_timed_out:
-                raise TimeoutError('IWD has no associated devices')
-
-        GLib.source_remove(timeout)
+        try:
+            timeout = GLib.timeout_add_seconds(max_wait, wait_timeout_cb)
+            context = mainloop.get_context()
+            while len(self._devices) < wait_to_appear:
+                context.iteration(may_block=True)
+                if self._wait_timed_out:
+                    raise TimeoutError('IWD has no associated devices')
+        finally:
+            if not self._wait_timed_out:
+                GLib.source_remove(timeout)
 
         return list(self._devices.values())
 
Signature · 1 line
2.21.1
#8 lore raw

PATCH 9/16 auto-t: remove wiphy.py

In reply to James Prestwood

This is no longer needed

---
 autotests/util/wiphy.py | 32 --------------------------------
 1 file changed, 32 deletions(-)
 delete mode 100644 autotests/util/wiphy.py
autotests/util/wiphy.py deleted +0 -32
deleted file mode 100644
index 3f94d87b..00000000
@@ -1,32 +0,0 @@
-#! /usr/bin/python3
-import os
-import collections
-
-wiphy_map = {}
-
-Wiphy = collections.namedtuple('Wiphy', ['name', 'use', 'interface_map'])
-
-Intf = collections.namedtuple('Intf',
-        ['name', 'wiphy', 'ctrl_interface', 'config'])
-
-def parse_list():
-    for entry in os.environ['TEST_WIPHY_LIST'].split('\n'):
-        wname, use_str = entry.split('=', 1)
-        use = use_str.split(',')
-
-        if wname not in wiphy_map:
-            wiphy_map[wname] = Wiphy(use=use[0], name=wname, interface_map={})
-
-        if len(use) <= 1:
-            continue
-
-        intf = {}
-        intf['name'] = None
-        intf['wiphy'] = wiphy_map[wname]
-        intf['ctrl_interface'] = None
-        intf['config'] = None
-        intf.update(dict([param.split('=', 1) for param in use[1:]]))
-
-        wiphy_map[wname].interface_map[intf['name']] = Intf(**intf)
-
-parse_list()
Signature · 1 line
2.21.1
#9 lore raw

PATCH 10/16 auto-t: fix hidden network test

In reply to James Prestwood

This test was never 100% reliable, and after the test-runner re-write it became extremely unreliable. The issue came down to the very common block of code thats present in many tests where we wait for obj.scanning then not obj.scanning. This is fine when a dbus scan() is explicitly done before, otherwise it could lead to problems. Without a dbus scan explicitly called we are assuming a periodic scan will happen. If it already happen the initial wait for obj.scanning will never return and time out.

This probably needs to be changed in several tests, but for this specific case we can remove the waits completely. Since check_autoconnect_hidden_network has a 30 second wait on DeviceState.connected this will ultimately time out if anything goes wrong. There isn't any great reason to wait for scanning (for this test specifically).

A minor style change was also made when initializing IWD. The values passed in this test are now the default, so no arguments need to be passed.

---
 autotests/testHiddenNetworks/validation.py | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)
autotests/testHiddenNetworks/validation.py +1 -7
index 9c433623..991a5b32 100644
@@ -50,11 +50,6 @@ class TestConnectAutoConnect(unittest.TestCase):
         device = devices[0]
 
         if autoconnect:
-            condition = 'obj.scanning'
-            wd.wait_for_object_condition(device, condition)
-            condition = 'not obj.scanning'
-            wd.wait_for_object_condition(device, condition)
-
             self.check_autoconnect_hidden_network(wd, device, ssid, throws)
         else:
             if wait_periodic_scan:
@@ -71,7 +66,6 @@ class TestConnectAutoConnect(unittest.TestCase):
 
     def validate(self, ssid, autoconnect, throws = None, use_agent = False,
                                                     wait_periodic_scan = False):
-        wd = IWD(True, '/tmp')
-
+        wd = IWD()
         self.validate_connection(wd, ssid, autoconnect, throws, use_agent,
                                                         wait_periodic_scan)
Signature · 1 line
2.21.1
#10 lore raw

PATCH 11/16 auto-t: fix testSAE autoconnect_test.py

In reply to James Prestwood

This test was unreliable since it was assuming a periodic scan would happen at just the right time. Instead since we are expecting autoconnect we can just wait for DeviceState.connected then after we are connected verify the network was correct.

---
 autotests/testSAE/autoconnect_test.py | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)
autotests/testSAE/autoconnect_test.py +5 -10
index a45fd09d..2eb73b7f 100644
@@ -23,20 +23,15 @@ class Test(unittest.TestCase):
         devices[2].disconnect()
         devices[3].disconnect()
 
-        condition = 'obj.scanning'
-        wd.wait_for_object_condition(device, condition)
+        condition = 'obj.state == DeviceState.connected'
+        wd.wait_for_object_condition(device, condition, 30)
 
-        condition = 'not obj.scanning'
+        condition = 'obj.connected_network is not None'
         wd.wait_for_object_condition(device, condition)
 
         ordered_network = device.get_ordered_network('ssidSAE')
 
-        self.assertEqual(ordered_network.type, NetworkType.psk)
-
-        condition = 'obj.connected'
-        wd.wait_for_object_condition(ordered_network.network_object, condition)
-
-        device.wait_for_connected()
+        self.assertTrue(ordered_network.network_object.connected)
 
         device.disconnect()
 
@@ -44,7 +39,7 @@ class Test(unittest.TestCase):
         wd.wait_for_object_condition(ordered_network.network_object, condition)
 
     def test_connection_success(self):
-        wd = IWD(True)
+        wd = IWD()
 
         self.validate_connection(wd)
 
Signature · 1 line
2.21.1
#11 lore raw

PATCH 12/16 auto-t: skip ofono tests if ofonod isn't running

In reply to James Prestwood
---
 autotests/testEAP-AKA-ofono/connection_test.py       | 4 ++++
 autotests/testEAP-AKA-prime-ofono/connection_test.py | 4 ++++
 autotests/testEAP-SIM-ofono/connection_test.py       | 4 ++++
 3 files changed, 12 insertions(+)
autotests/testEAP-AKA-ofono/connection_test.py +4 -0
index 94066f76..27f736f6 100644
@@ -9,6 +9,7 @@ from iwd import IWD
 from iwd import NetworkType
 from hlrauc import AuthCenter
 from ofono import Ofono
+from config import ctx
 
 class Test(unittest.TestCase):
 
@@ -56,6 +57,9 @@ class Test(unittest.TestCase):
         auth.stop()
     @classmethod
     def setUpClass(cls):
+        if not ctx.is_process_running('ofonod'):
+            cls.skipTest(cls, "ofono not running")
+
         IWD.copy_to_storage('ssidEAP-AKA.8021x')
 
     @classmethod
autotests/testEAP-AKA-prime-ofono/connection_test.py +4 -0
index 2ff99894..967ba352 100644
@@ -9,6 +9,7 @@ from iwd import IWD
 from iwd import NetworkType
 from hlrauc import AuthCenter
 from ofono import Ofono
+from config import ctx
 
 class Test(unittest.TestCase):
 
@@ -57,6 +58,9 @@ class Test(unittest.TestCase):
 
     @classmethod
     def setUpClass(cls):
+        if not ctx.is_process_running('ofonod'):
+            cls.skipTest(cls, "ofono not running")
+
         IWD.copy_to_storage('ssidEAP-AKA.8021x')
 
     @classmethod
autotests/testEAP-SIM-ofono/connection_test.py +4 -0
index 95242943..de7c4b48 100644
@@ -9,6 +9,7 @@ from iwd import IWD
 from iwd import NetworkType
 from hlrauc import AuthCenter
 from ofono import Ofono
+from config import ctx
 
 class Test(unittest.TestCase):
 
@@ -57,6 +58,9 @@ class Test(unittest.TestCase):
 
     @classmethod
     def setUpClass(cls):
+        if not ctx.is_process_running('ofonod'):
+            cls.skipTest(cls, "ofono not running")
+
         IWD.copy_to_storage('ssidEAP-SIM.8021x')
 
     @classmethod
Signature · 1 line
2.21.1
#12 lore raw

PATCH 13/16 auto-t: replace hard-coded interfaces

In reply to James Prestwood

test-runner now supports interface name replacement inside hostapd config files. Since a given test configuration doesn't know what interface names there will be $ifaceN can be specified instead e.g.

rsn_preauth_interfaces=$iface0 $iface1

The $ifaceN values will be replace with actual interface names when the test is started.

This patch also removes ctrl_interface inside the hostapd config files as this is no longer required.

---
 autotests/testPreauth-roam/eaptls-preauth-1.conf | 3 +--
 autotests/testPreauth-roam/eaptls-preauth-2.conf | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)
autotests/testPreauth-roam/eaptls-preauth-1.conf +1 -2
index 0c7f96a7..bc808ed7 100644
@@ -2,7 +2,6 @@ hw_mode=g
 channel=1
 ssid=TestPreauth
 utf8_ssid=1
-ctrl_interface=/var/run/hostapd
 
 wpa=2
 wpa_key_mgmt=WPA-EAP
@@ -24,7 +23,7 @@ radius_server_auth_port=1812
 nas_identifier=testeap1
 
 rsn_preauth=1
-rsn_preauth_interfaces=wln0 wln1
+rsn_preauth_interfaces=$iface0 $iface1
 disable_pmksa_caching=0
 
 # Allow PMK cache to be shared opportunistically among configured interfaces
autotests/testPreauth-roam/eaptls-preauth-2.conf +1 -2
index bddcca69..6d3a18e7 100644
@@ -2,7 +2,6 @@ hw_mode=g
 channel=2
 ssid=TestPreauth
 utf8_ssid=1
-ctrl_interface=/var/run/hostapd
 
 wpa=2
 wpa_key_mgmt=WPA-EAP
@@ -20,7 +19,7 @@ auth_server_port=1812
 auth_server_shared_secret=secret
 
 rsn_preauth=1
-rsn_preauth_interfaces=wln0 wln1
+rsn_preauth_interfaces=$iface0 $iface1
 disable_pmksa_caching=0
 
 # Allow PMK cache to be shared opportunistically among configured interfaces
Signature · 1 line
2.21.1
#13 lore raw

PATCH 14/16 auto-t: remove device.wait_for_connected

In reply to James Prestwood

I had added this without realizing wait_for_object_condition can do this already using the device object.

---
 autotests/testSAE/clogging_test.py |  3 ++-
 autotests/util/iwd.py              | 25 -------------------------
 2 files changed, 2 insertions(+), 26 deletions(-)
autotests/testSAE/clogging_test.py +2 -1
index e94e2ad6..c46c5821 100644
@@ -48,7 +48,8 @@ class Test(unittest.TestCase):
             wd.wait_for_object_condition(n.network_object, condition)
 
         for d in devices:
-            d.wait_for_connected()
+            condition = 'obj.state == DeviceState.connected'
+            wd.wait_for_object_condition(d, condition)
 
         for d in devices:
             d.disconnect()
autotests/util/iwd.py +0 -25
index 113039b6..9c106b89 100755
@@ -568,31 +568,6 @@ class Device(IWDDBusAbstract):
             if self._adhoc_timed_out:
                 raise TimeoutError("Timed out waiting for peer %s" % addr)
 
-    def wait_for_connected(self):
-        if str(self.state) == "connected":
-            return
-
-        self._connected_success = False
-        self._connected_timed_out = False
-
-        def wait_timeout_cb():
-            self._connected_timed_out = True
-            return False
-
-        def connected_prop_changed(iface, changed, invalid):
-            if changed.get('State', None):
-                if changed['State'] == 'connected':
-                    self._connected_success = True
-
-        self._prop_proxy.connect_to_signal('PropertiesChanged',
-                                            connected_prop_changed)
-        GLib.timeout_add(int(15 * 1000), wait_timeout_cb)
-        context = mainloop.get_context()
-        while not self._connected_success:
-            context.iteration(may_block=True)
-            if self._connected_timed_out:
-                raise TimeoutError("Timed out waiting for connected")
-
     def __str__(self, prefix = ''):
         return prefix + 'Device: ' + self.device_path + '\n'\
                + prefix + '\tName:\t\t' + self.name + '\n'\
Signature · 1 line
2.21.1
#14 lore raw

PATCH 15/16 tools: post test-runner rewrite cleanup

In reply to James Prestwood

Removed test-runner.c, and renamed py_runner to test-runner. Removed tools/test-runner from .gitignore.

This was done as a separate commit to avoid a nasty diff between the existing test runner, and the new python version

---
 .gitignore                          |    1 -
 Makefile.am                         |    7 -
 tools/{py_runner.py => test-runner} |    0
 tools/test-runner.c                 | 3310 ---------------------------
 4 files changed, 3318 deletions(-)
 rename tools/{py_runner.py => test-runner} (100%)
 delete mode 100644 tools/test-runner.c
.gitignore +0 -1
index 93fec4f7..33405af8 100644
@@ -33,7 +33,6 @@ wired/ead.8
 wired/ead.service
 tools/hwsim
 tools/hwsim.1
-tools/test-runner
 tools/probe-req
 unit/test-cmac-aes
 unit/test-arc4
Makefile.am +0 -7
index e83dbeee..5f16920f 100644
@@ -366,13 +366,6 @@ man_MANS += tools/hwsim.1
 endif
 endif
 
-if TOOLS
-noinst_PROGRAMS += tools/test-runner
-
-tools_test_runner_SOURCES = tools/test-runner.c
-tools_test_runner_LDADD = $(ell_ldadd)
-endif
-
 unit_tests = unit/test-cmac-aes \
 		unit/test-hmac-md5 unit/test-hmac-sha1 unit/test-hmac-sha256 \
 		unit/test-prf-sha1 unit/test-kdf-sha256 \
tools/test-runner renamed from tools/py_runner.py +0 -0
similarity index 100%
rename from tools/py_runner.py
rename to tools/test-runner
tools/test-runner.c deleted +0 -3310

2,980 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.21.1

Part of the diff is not shown here. View the raw message.

#15 lore raw

PATCH 16/16 doc: update test runner docs

In reply to James Prestwood
---
 doc/test-runner.txt | 117 +++++++++++++-------------------------------
 1 file changed, 34 insertions(+), 83 deletions(-)
doc/test-runner.txt +34 -83
index 2d45bedc..17d7bbb2 100644
@@ -17,18 +17,21 @@ OS:
 
 	Name:			Tested ver.:
 	 1. qemu		2.4.1
-	 2. Linux kernel	4.20
+	 2. Linux kernel	4.20+
 	 3. dbus-daemon		1.11.18
 	 4. ifconfig		2.10-alpha
 	 5. iw			3.17
 	 6. python		2.7
 	 7. haveged		no ver. avail.
-	 8. hostapd		commit id: 31d3692
+	 8. hostapd		recent
 	 9. <iwd>/tools/hwsim	0.0
 	10. <iwd>/src/iwd	0.0
+	11. ofono (optional)
+	12. phonesim (optional)
 
-Note: You will need ell-key-crypto branch, not the master branch from the tree
-in step 2 above.
+Note: The version for hostapd is listed as 'recent'. Older hostapd versions
+will work but we are continually adopting new features from hostapd and using
+those to test. Its recommended to use a recent release of hostapd.
 
 Note: The test-runner mounts host's file system in readonly mode and executes
 the above binaries inside of an emulated environment directly from it.
@@ -100,7 +103,6 @@ By default the test-runner will search for the kernel image in these locations:
 An arbitrary kernel image location can be specified by using '--kernel <path>'
 parameter into test-runner.
 
-
 Running Automated Tests
 =======================
 Before running any tests, its expected that the folder /var/lib/iwd exists on
@@ -113,8 +115,8 @@ By default, the automated test configuration directories reside in
 '<iwd>/autotests' and have a mandatory prefix of 'test'.
 
 	<iwd>/autotests/test1
-                       /test2
-                         ...
+			/test2
+			...
 
 The test configurations along with test cases in <iwd>/autotests/test*
 directories will be discovered and executed by test-runner in sequential
@@ -133,6 +135,10 @@ The command line may look as follows:
 
 	$ sudo ./test-runner -t test1,test3,/home/test4
 
+Glob matching is also supported when specifying a test list:
+
+	$ sudo ./test-runner -t testWPA*
+
 
 Creating Test Configurations
 ============================
@@ -145,7 +151,11 @@ A typical test configuration directory may consist of these types of files:
 	*Test or *Test.py	The set of test cases for IWD functionality
 				implemented using Python scripting language.
 				These files must have one of the two predefined
-				suffixes: 'Test' or 'Test.py'
+				suffixes: 'test' or 'test.py'. The file name
+				must also be more descriptive than simply 'test'.
+				e.g. 'connection_test' or 'failure_test'. Files
+				named 'test' will not be dynamically loaded due
+				to python module naming overlap.
 
 	*.conf			A configuration file for an instance of hostapd
 	(Defined in hw.conf)	service.
@@ -164,6 +174,9 @@ A typical contents of a test configuration directory may look as follows:
 		networkScanTest
 		networkConnectTest.py
 
+Note: Any additional files in your test directory will be copied to /tmp inside
+the VM. These additional file should be referenced using /tmp/<file> inside
+any configuration file for hostapd.
 
 Defining Network
 ----------------
@@ -187,61 +200,26 @@ supplicant running IWD:
 # has a range of [1, 100].
 num_radios=3
 
-# Definition of the radio configuration identifiers. These identifiers are used
-# to map the APs and IWD to the radios with the particular hardware properties.
-# This field is optional. If identifier is omitted from this list, then the
-# default radio properties will be used as they are defined in mac80211_hwsim
-# driver to satisfy a total number of radios requested in 'num_radios' field.
-radio_confs=rad0:rad1
-
 # Maximum execution interval per Python script file in seconds. This field is
 # optional.
 # Default: 20 seconds.
 #max_test_exec_interval_sec=5
 
-# List of paths inside of a test configuration directory for which
-# the symlinks will be created inside of /tmp. Such paths can be used
-# to specify an absolute path to the needed files inside of IWD and Hostapd
-# configuration files.
-# Example:
-#	 <some path>/test1/certs
-#		           misc
-#
-# certs and misc directories will be respectively mapped to:
-#
-#	 /tmp/certs
-#	      misc
-#
-# This field is optional.
-#tmpfs_extra_stuff=certs:misc
-
-# Flag to prevent test-runner from starting IWD. Therefore, it may later be
-# started from the python test cases.
-# This field is optional. Default: 1 (true)
-#start_iwd=0
-
-# Configuration directory to use for IWD daemon. IWD expects 'main.conf' to be
-# inside of the specified directory.
-# This field is optional. Default: /etc/iwd
-#iwd_config_dir=/etc/iwd
-
 #
 # The following two configuration groups are examples of the radio
 # configurations.
 #
 # This group of settings allows to specify a set of properties for a radio. The
-# name of the group represents a radio identifier and must be predefined in
-# 'radio_confs' field inside of 'SETUP' group. This configuration group is
-# optional.
-# TODO: explain each one of the properties.
+# name of the group represents a radio identifier. These configuration groups
+# are optional.
 [rad0]
-channels=2
-p2p_device=1
-use_chanctx=1
 
-# Properties of the second radio. This configuration group is optional.
-[rad1]
-p2p=0
+# For each radX group you can specify radio properties:
+# Disables the provided interface type(s):
+disable_iftype=ap,p2p
+
+# Disables the provided cipher types:
+disable_cipher=ccmp,bip
 
 # 'HOSTAPD' configuration group identifies a set of access points (AP) for the
 # current network topology. Each key/value pair represents a single AP that is
@@ -253,8 +231,12 @@ p2p=0
 [HOSTAPD]
 rad0=ap1.conf
 rad1=ap2.conf
-#~~~~~~~~~~~~~~~~~~ end of hw.conf ~~~~~~~~~~~~~~~~~~~~~~~~~
 
+# 'radius_server' is a special option used to specify a hostapd instance which
+# acts as a radius server only (not an access point). This option does not
+# require an additional 'num_radios' to be used.
+radius_server=radius.conf
+#~~~~~~~~~~~~~~~~~~ end of hw.conf ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Configuring Access Points
 -------------------------
@@ -358,37 +340,6 @@ For more information on Python unit test framework refer to the following page:
 
 	http://pyunit.sourceforge.net/pyunit.html
 
-
-Examples of the framework usage:
-
-#~~~~~~~~~~~~~~~~~~~~~~~~~ alwaysPassingTest.py ~~~~~~~~~~~~~~~~~~~~~~~~~
-#!/usr/bin/python
-
-import unittest
-
-class TestPassingCase(unittest.TestCase):
-
-	def test_pass(self):
-		self.assertTrue(True)
-
-if __name__ == '__main__':
-	unittest.main()
-#~~~~~~~~~~~~~~~~~~ end of alwaysPassingTest.py ~~~~~~~~~~~~~~~~~~~~~~~~~
-
-#~~~~~~~~~~~~~~~~~~~~~~~~~ alwaysFailingTest.py ~~~~~~~~~~~~~~~~~~~~~~~~~
-#!/usr/bin/python
-
-import unittest
-
-class TestFailingCase(unittest.TestCase):
-
-	def test_fail(self):
-		self.assertTrue(False)
-
-if __name__ == '__main__':
-	unittest.main()
-#~~~~~~~~~~~~~~~~~~ end of alwaysFailingTest.py ~~~~~~~~~~~~~~~~~~~~~~~~~
-
 Using hardware passthrough
 ---------------------------
 
Signature · 1 line
2.21.1
#16 lore raw
In reply to James Prestwood

Hi James,

Quoted 8 lines · James Prestwood

Hwsim was relying on some internal behavior of mac80211_hwsim where new radios are created with ID's starting at zero and incremented. While this is a reasonable assumption its better to obtain the actual radio ID since mac80211_hwsim returns it in the radio creation callback.

Now hwsim will return the radio ID when creating radios. Negative returns are still errors, but any value >= 0 indicates the radio ID of the newly created radio.

Ah, now I see what you meant by exit code. Sorry I should have caught this earlier.

So the problem is that UNIX doesn't really understand negative exit codes. exit code of 0 is a success and anything else is a failure.

I think you will get people screaming obscenities if they try to use hwsim in a script...

Quoted 4 lines
---
  tools/hwsim.c | 9 +++++++--
  1 file changed, 7 insertions(+), 2 deletions(-)

Regards,
-Denis

#17 lore raw
Quoted 20 lines · Denis Kenzior

Hi James,

Quoted 8 lines · James Prestwood

Hwsim was relying on some internal behavior of mac80211_hwsim where new
radios are created with ID's starting at zero and incremented. While
this is a reasonable assumption its better to obtain the actual radio
ID since mac80211_hwsim returns it in the radio creation callback.

Quoted 5 lines

Now hwsim will return the radio ID when creating radios. Negative returns
are still errors, but any value >= 0 indicates the radio ID of the newly
created radio.

Ah, now I see what you meant by exit code. Sorry I should have caught this earlier.

Quoted 7 lines

So the problem is that UNIX doesn't really understand negative exit codes. exit
code of 0 is a success and anything else is a failure.

I think you will get people screaming obscenities if they try to use hwsim in a
script...

Ok, makes sense. I can just track the ID internally until I get the dbus stuff sorted out.

Quoted 8 lines
Quoted 5 lines
---
  tools/hwsim.c | 9 +++++++--
  1 file changed, 7 insertions(+), 2 deletions(-)

Regards,
-Denis