1# Radio work tests
2# Copyright (c) 2014, Jouni Malinen <j@w1.fi>
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
7import time
8import logging
9logger = logging.getLogger()
10
11import hostapd
12from wpasupplicant import WpaSupplicant
13
14def test_ext_radio_work(dev, apdev):
15    """External radio work item"""
16    id = dev[0].request("RADIO_WORK add test-work-a")
17    if "FAIL" in id:
18        raise Exception("Failed to add radio work")
19    id2 = dev[0].request("RADIO_WORK add test-work-b freq=2417")
20    if "FAIL" in id2:
21        raise Exception("Failed to add radio work")
22    id3 = dev[0].request("RADIO_WORK add test-work-c")
23    if "FAIL" in id3:
24        raise Exception("Failed to add radio work")
25
26    ev = dev[0].wait_event(["EXT-RADIO-WORK-START"])
27    if ev is None:
28        raise Exception("Timeout while waiting radio work to start")
29    if "EXT-RADIO-WORK-START " + id not in ev:
30        raise Exception("Unexpected radio work start id")
31
32    items = dev[0].request("RADIO_WORK show")
33    if "ext:test-work-a@wlan0:0:1:" not in items:
34        logger.info("Pending radio work items:\n" + items)
35        raise Exception("Radio work item(a) missing from the list")
36    if "ext:test-work-b@wlan0:2417:0:" not in items:
37        logger.info("Pending radio work items:\n" + items)
38        raise Exception("Radio work item(b) missing from the list")
39    if "ext:test-work-c@wlan0:0:0:" not in items:
40        logger.info("Pending radio work items:\n" + items)
41        raise Exception("Radio work item(c) missing from the list")
42
43    dev[0].request("RADIO_WORK done " + id2)
44    dev[0].request("RADIO_WORK done " + id)
45
46    ev = dev[0].wait_event(["EXT-RADIO-WORK-START"])
47    if ev is None:
48        raise Exception("Timeout while waiting radio work to start")
49    if "EXT-RADIO-WORK-START " + id3 not in ev:
50        raise Exception("Unexpected radio work start id")
51    dev[0].request("RADIO_WORK done " + id3)
52    items = dev[0].request("RADIO_WORK show")
53    if "ext:" in items:
54        logger.info("Pending radio work items:\n" + items)
55        raise Exception("Unexpected remaining radio work item")
56
57    id = dev[0].request("RADIO_WORK add test-work timeout=1")
58    ev = dev[0].wait_event(["EXT-RADIO-WORK-START"])
59    if ev is None:
60        raise Exception("Timeout while waiting radio work to start")
61    ev = dev[0].wait_event(["EXT-RADIO-WORK-TIMEOUT"], timeout=2)
62    if ev is None:
63        raise Exception("Timeout while waiting radio work to time out")
64    if id not in ev:
65        raise Exception("Radio work id mismatch")
66
67    for i in range(5):
68        dev[0].request(("RADIO_WORK add test-work-%d-" % i) + 100*'a')
69    ev = dev[0].wait_event(["EXT-RADIO-WORK-START"])
70    if ev is None:
71        raise Exception("Timeout while waiting radio work to start")
72    if "FAIL" not in dev[0].request("RADIO_WORK done 12345678"):
73        raise Exception("Invalid RADIO_WORK done accepted")
74    if "FAIL" not in dev[0].request("RADIO_WORK foo"):
75        raise Exception("Invalid RADIO_WORK accepted")
76    dev[0].request("FLUSH")
77    items = dev[0].request("RADIO_WORK show")
78    if items != "":
79        raise Exception("Unexpected radio work remaining after FLUSH: " + items)
80
81def test_radio_work_cancel(dev, apdev):
82    """Radio work items cancelled on interface removal"""
83    params = hostapd.wpa2_params(ssid="radio", passphrase="12345678")
84    hostapd.add_ap(apdev[0], params)
85    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
86    wpas.interface_add("wlan5")
87    wpas.scan(freq="2412")
88
89    id = wpas.request("RADIO_WORK add test-work-a")
90    if "FAIL" in id:
91        raise Exception("Failed to add radio work")
92    ev = wpas.wait_event(["EXT-RADIO-WORK-START"])
93    if ev is None:
94        raise Exception("Timeout while waiting radio work to start")
95    if "EXT-RADIO-WORK-START " + id not in ev:
96        raise Exception("Unexpected radio work start id")
97
98    wpas.connect("radio", psk="12345678", scan_freq="2412",
99                   wait_connect=False)
100    time.sleep(1)
101    wpas.interface_remove("wlan5")
102    # add to allow log file renaming
103    wpas.interface_add("wlan5")
104
105def test_ext_radio_work_disconnect_connect(dev, apdev):
106    """External radio work and DISCONNECT clearing connection attempt"""
107    hapd = hostapd.add_ap(apdev[0], {"ssid": "open"})
108    dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
109
110    # Start a radio work to block connection attempt
111    id1 = dev[0].request("RADIO_WORK add test-work-a")
112    if "FAIL" in id1:
113        raise Exception("Failed to add radio work")
114    ev = dev[0].wait_event(["EXT-RADIO-WORK-START"])
115    if ev is None:
116        raise Exception("Timeout while waiting radio work to start")
117
118    dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
119                   wait_connect=False)
120    items = dev[0].request("RADIO_WORK show")
121    if "connect" not in items:
122        raise Exception("Connection radio work not scheduled")
123    dev[0].request("DISCONNECT")
124    items = dev[0].request("RADIO_WORK show")
125    if "connect" in items:
126        raise Exception("Connection radio work not removed on DISCONNECT")
127
128    # Clear radio work to allow any pending work to be started
129    dev[0].request("RADIO_WORK done " + id1)
130
131    ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
132    if ev is not None:
133        raise Exception("Unexpected connection seen")
134