1 #!/usr/bin/python 2 # 3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 4 # Use of this source code is governed by a BSD-style license that can be 5 # found in the LICENSE file. 6 7 import unittest 8 9 import common 10 11 from autotest_lib.client.common_lib.cros.network import iw_runner 12 13 class IwRunnerTest(unittest.TestCase): 14 """Unit test for the IWRunner object.""" 15 16 17 class host_cmd(object): 18 """Mock host command class.""" 19 20 def __init__(self, stdout, stderr, exit_status): 21 self._stdout = stdout 22 self._stderr = stderr 23 self._exit_status = exit_status 24 25 26 @property 27 def stdout(self): 28 """Returns stdout.""" 29 return self._stdout 30 31 32 @property 33 def stderr(self): 34 """Returns stderr.""" 35 return self._stderr 36 37 38 @property 39 def exit_status(self): 40 """Returns the exit status.""" 41 return self._exit_status 42 43 44 class host(object): 45 """Mock host class.""" 46 47 def __init__(self, host_cmd): 48 self._host_cmd = IwRunnerTest.host_cmd(host_cmd, 1.0, 0) 49 50 51 def run(self, cmd, ignore_status=False): 52 """Returns the mocked output. 53 54 @param cmd: a stub input ignore 55 @param ignore_status: a stub input ignore 56 57 """ 58 return self._host_cmd 59 60 61 HT20 = str('BSS aa:aa:aa:aa:aa:aa (on wlan0)\n' 62 ' freq: 2412\n' 63 ' signal: -50.00 dBm\n' 64 ' SSID: support_ht20\n' 65 ' HT operation:\n' 66 ' * secondary channel offset: no secondary\n') 67 68 HT20_IW_BSS = iw_runner.IwBss('aa:aa:aa:aa:aa:aa', 2412, 69 'support_ht20', iw_runner.SECURITY_OPEN, 70 iw_runner.HT20, -50.00) 71 72 HT20_2 = str('BSS 11:11:11:11:11:11 (on wlan0)\n' 73 ' freq: 2462\n' 74 ' signal: -42.00 dBm\n' 75 ' SSID: support_ht20\n' 76 ' WPA: * Version: 1\n' 77 ' HT operation:\n' 78 ' * secondary channel offset: below\n') 79 80 HT20_2_IW_BSS = iw_runner.IwBss('11:11:11:11:11:11', 2462, 81 'support_ht20', iw_runner.SECURITY_WPA, 82 iw_runner.HT40_BELOW, -42.00) 83 84 HT40_ABOVE = str('BSS bb:bb:bb:bb:bb:bb (on wlan0)\n' 85 ' freq: 5180\n' 86 ' signal: -55.00 dBm\n' 87 ' SSID: support_ht40_above\n' 88 ' RSN: * Version: 1\n' 89 ' HT operation:\n' 90 ' * secondary channel offset: above\n') 91 92 HT40_ABOVE_IW_BSS = iw_runner.IwBss('bb:bb:bb:bb:bb:bb', 5180, 93 'support_ht40_above', 94 iw_runner.SECURITY_WPA2, 95 iw_runner.HT40_ABOVE, -55.00) 96 97 HT40_BELOW = str('BSS cc:cc:cc:cc:cc:cc (on wlan0)\n' 98 ' freq: 2462\n' 99 ' signal: -44.00 dBm\n' 100 ' SSID: support_ht40_below\n' 101 ' RSN: * Version: 1\n' 102 ' WPA: * Version: 1\n' 103 ' HT operation:\n' 104 ' * secondary channel offset: below\n') 105 106 HT40_BELOW_IW_BSS = iw_runner.IwBss('cc:cc:cc:cc:cc:cc', 2462, 107 'support_ht40_below', 108 iw_runner.SECURITY_MIXED, 109 iw_runner.HT40_BELOW, -44.00) 110 111 NO_HT = str('BSS dd:dd:dd:dd:dd:dd (on wlan0)\n' 112 ' freq: 2412\n' 113 ' signal: -45.00 dBm\n' 114 ' SSID: no_ht_support\n') 115 116 NO_HT_IW_BSS = iw_runner.IwBss('dd:dd:dd:dd:dd:dd', 2412, 117 'no_ht_support', iw_runner.SECURITY_OPEN, 118 None, -45.00) 119 120 HIDDEN_SSID = str('BSS ee:ee:ee:ee:ee:ee (on wlan0)\n' 121 ' freq: 2462\n' 122 ' signal: -70.00 dBm\n' 123 ' SSID: \n' 124 ' HT operation:\n' 125 ' * secondary channel offset: no secondary\n') 126 127 SCAN_TIME_OUTPUT = str('real 4.5\n' 128 'user 2.1\n' 129 'system 3.1\n') 130 131 HIDDEN_SSID_IW_BSS = iw_runner.IwBss('ee:ee:ee:ee:ee:ee', 2462, 132 None, iw_runner.SECURITY_OPEN, 133 iw_runner.HT20, -70.00) 134 135 STATION_LINK_INFORMATION = str( 136 'Connected to 12:34:56:ab:cd:ef (on wlan0)\n' 137 ' SSID: PMKSACaching_4m9p5_ch1\n' 138 ' freq: 5220\n' 139 ' RX: 5370 bytes (37 packets)\n' 140 ' TX: 3604 bytes (15 packets)\n' 141 ' signal: -59 dBm\n' 142 ' tx bitrate: 13.0 MBit/s MCS 1\n' 143 '\n' 144 ' bss flags: short-slot-time\n' 145 ' dtim period: 5\n' 146 ' beacon int: 100\n') 147 148 STATION_LINK_BSSID = '12:34:56:ab:cd:ef' 149 150 STATION_LINK_IFACE = 'wlan0' 151 152 STATION_LINK_FREQ = '5220' 153 154 STATION_LINK_PARSED = { 155 'SSID': 'PMKSACaching_4m9p5_ch1', 156 'freq': '5220', 157 'RX': '5370 bytes (37 packets)', 158 'TX': '3604 bytes (15 packets)', 159 'signal': '-59 dBm', 160 'tx bitrate': '13.0 MBit/s MCS 1', 161 'bss flags': 'short-slot-time', 162 'dtim period': '5', 163 'beacon int': '100' 164 } 165 166 STATION_DUMP_INFORMATION = str( 167 'Station dd:ee:ff:33:44:55 (on mesh-5000mhz)\n' 168 ' inactive time: 140 ms\n' 169 ' rx bytes: 2883498\n' 170 ' rx packets: 31981\n' 171 ' tx bytes: 1369934\n' 172 ' tx packets: 6615\n' 173 ' tx retries: 4\n' 174 ' tx failed: 0\n' 175 ' signal: -4 dBm\n' 176 ' signal avg: -11 dBm\n' 177 ' Toffset: 81715566854 us\n' 178 ' tx bitrate: 866.7 MBit/s VHT-MCS 9 80MHz ' 179 'short GI VHT-NSS 2\n' 180 ' rx bitrate: 866.7 MBit/s VHT-MCS 9 80MHz ' 181 'short GI VHT-NSS 2\n' 182 ' mesh llid: 0\n' 183 ' mesh plid: 0\n' 184 ' mesh plink: ESTAB\n' 185 ' mesh local PS mode: ACTIVE\n' 186 ' mesh peer PS mode: ACTIVE\n' 187 ' mesh non-peer PS mode: ACTIVE\n' 188 ' authorized: yes\n' 189 ' authenticated: yes\n' 190 ' preamble: long\n' 191 ' WMM/WME: yes\n' 192 ' MFP: yes\n' 193 ' TDLS peer: no\n' 194 ' connected time: 8726 seconds\n' 195 'Station aa:bb:cc:00:11:22 (on mesh-5000mhz)\n' 196 ' inactive time: 140 ms\n' 197 ' rx bytes: 2845200\n' 198 ' rx packets: 31938\n' 199 ' tx bytes: 1309945\n' 200 ' tx packets: 6672\n' 201 ' tx retries: 0\n' 202 ' tx failed: 0\n' 203 ' signal: -21 dBm\n' 204 ' signal avg: -21 dBm\n' 205 ' tx bitrate: 866.7 MBit/s VHT-MCS 9 80MHz ' 206 'short GI VHT-NSS 2\n' 207 ' rx bitrate: 650.0 MBit/s VHT-MCS 7 80MHz ' 208 'short GI VHT-NSS 2\n' 209 ' mesh llid: 0\n' 210 ' mesh plid: 0\n' 211 ' mesh plink: ESTAB\n' 212 ' mesh local PS mode: ACTIVE\n' 213 ' mesh peer PS mode: ACTIVE\n' 214 ' mesh non-peer PS mode: ACTIVE\n' 215 ' authorized: yes\n' 216 ' authenticated: yes\n' 217 ' preamble: long\n' 218 ' WMM/WME: yes\n' 219 ' MFP: yes\n' 220 ' TDLS peer: no\n' 221 ' connected time: 8724 seconds\n' 222 'Station ff:aa:bb:aa:44:55 (on mesh-5000mhz)\n' 223 ' inactive time: 304 ms\n' 224 ' rx bytes: 18816\n' 225 ' rx packets: 75\n' 226 ' tx bytes: 5386\n' 227 ' tx packets: 21\n' 228 ' signal: -29 dBm\n' 229 ' tx bitrate: 65.0 MBit/s VHT-MCS 0 80MHz short GI VHT-NSS 2\n' 230 ' mesh llid: 0\n' 231 ' mesh plid: 0\n' 232 ' mesh plink: ESTAB\n' 233 ' mesh local PS mode: ACTIVE\n' 234 ' mesh peer PS mode: ACTIVE\n' 235 ' mesh non-peer PS mode: ACTIVE\n' 236 ' authorized: yes\n' 237 ' authenticated: yes\n' 238 ' preamble: long\n' 239 ' WMM/WME: yes\n' 240 ' MFP: yes\n' 241 ' TDLS peer: no\n' 242 ' connected time: 824 seconds\n') 243 244 STATION_DUMP_INFORMATION_PARSED = [ 245 {'mac': 'aa:bb:cc:00:11:22', 'rssi_str': '-21 dBm', 'rssi_int': -21, 246 'tx_bitrate': '866.7 MBit/s VHT-MCS 9 80MHz short GI VHT-NSS 2', 247 'rx_bitrate': '650.0 MBit/s VHT-MCS 7 80MHz short GI VHT-NSS 2'}, 248 {'mac': 'dd:ee:ff:33:44:55', 'rssi_str': '-4 dBm', 'rssi_int': -4, 249 'tx_bitrate': '866.7 MBit/s VHT-MCS 9 80MHz short GI VHT-NSS 2', 250 'rx_bitrate': '866.7 MBit/s VHT-MCS 9 80MHz short GI VHT-NSS 2'}, 251 {'mac': 'ff:aa:bb:aa:44:55', 'rssi_str': '-29 dBm', 'rssi_int': -29, 252 'tx_bitrate': '65.0 MBit/s VHT-MCS 0 80MHz short GI VHT-NSS 2', 253 'rx_bitrate': None}, 254 ] 255 256 STATION_DUMP_IFACE = 'mesh-5000mhz' 257 258 INFO_MESH_MODE = str( 259 'Interface wlan-2400mhz\n' 260 ' ifindex 10\n' 261 ' wdev 0x100000002\n' 262 ' addr aa:bb:cc:dd:ee:ff\n' 263 ' type mesh point\n' 264 ' wiphy 1\n' 265 ' channel 149 (5745 MHz), width: 80 MHz, center1: 5775 MHz\n') 266 267 INFO_AP_MODE = str( 268 'Interface wlan-2400mhz\n' 269 ' ifindex 8\n' 270 ' wdev 0x1\n' 271 ' addr 00:11:22:33:44:55\n' 272 ' ssid testap_170501151530_wsvx\n' 273 ' type AP\n' 274 ' wiphy 0\n' 275 ' channel 11 (2462 MHz), width: 20 MHz, center1: 2462 MHz\n') 276 277 RADIO_CONFIG_AP_MODE = {'number': 11, 'freq': 2462, 'width': 20, 278 'center1_freq': 2462} 279 280 INFO_STA_MODE = str( 281 'Interface wlan-2400mhz\n' 282 ' ifindex 9\n' 283 ' wdev 0x1\n' 284 ' addr 44:55:66:77:88:99\n' 285 ' type managed\n' 286 ' wiphy 0\n' 287 ' channel 11 (2462 MHz), width: 20 MHz, center1: 2462 MHz\n') 288 289 INFO_IFACE = 'wlan-2400mhz' 290 291 292 def verify_values(self, iw_bss_1, iw_bss_2): 293 """Checks all of the IWBss values 294 295 @param iw_bss_1: an IWBss object 296 @param iw_bss_2: an IWBss object 297 298 """ 299 self.assertEquals(iw_bss_1.bss, iw_bss_2.bss) 300 self.assertEquals(iw_bss_1.ssid, iw_bss_2.ssid) 301 self.assertEquals(iw_bss_1.frequency, iw_bss_2.frequency) 302 self.assertEquals(iw_bss_1.security, iw_bss_2.security) 303 self.assertEquals(iw_bss_1.ht, iw_bss_2.ht) 304 self.assertEquals(iw_bss_1.signal, iw_bss_2.signal) 305 306 307 def search_by_bss(self, scan_output, test_iw_bss): 308 """ 309 310 @param scan_output: the output of the scan as a string 311 @param test_iw_bss: an IWBss object 312 313 Uses the runner to search for a network by bss. 314 """ 315 host = self.host(scan_output + self.SCAN_TIME_OUTPUT) 316 runner = iw_runner.IwRunner(remote_host=host) 317 network = runner.wait_for_scan_result('wlan0', bsses=[test_iw_bss.bss]) 318 self.verify_values(test_iw_bss, network[0]) 319 320 321 def test_find_first(self): 322 """Test with the first item in the list.""" 323 scan_output = self.HT20 + self.HT40_ABOVE 324 self.search_by_bss(scan_output, self.HT20_IW_BSS) 325 326 327 def test_find_last(self): 328 """Test with the last item in the list.""" 329 scan_output = self.HT40_ABOVE + self.HT20 330 self.search_by_bss(scan_output, self.HT20_IW_BSS) 331 332 333 def test_find_middle(self): 334 """Test with the middle item in the list.""" 335 scan_output = self.HT40_ABOVE + self.HT20 + self.NO_HT 336 self.search_by_bss(scan_output, self.HT20_IW_BSS) 337 338 339 def test_ht40_above(self): 340 """Test with a HT40+ network.""" 341 scan_output = self.HT20 + self.HT40_ABOVE + self.NO_HT 342 self.search_by_bss(scan_output, self.HT40_ABOVE_IW_BSS) 343 344 345 def test_ht40_below(self): 346 """Test with a HT40- network.""" 347 scan_output = self.HT20 + self.HT40_BELOW + self.NO_HT 348 self.search_by_bss(scan_output, self.HT40_BELOW_IW_BSS) 349 350 351 def test_no_ht(self): 352 """Test with a network that doesn't have ht.""" 353 scan_output = self.HT20 + self.NO_HT + self.HT40_ABOVE 354 self.search_by_bss(scan_output, self.NO_HT_IW_BSS) 355 356 357 def test_hidden_ssid(self): 358 """Test with a network with a hidden ssid.""" 359 scan_output = self.HT20 + self.HIDDEN_SSID + self.NO_HT 360 self.search_by_bss(scan_output, self.HIDDEN_SSID_IW_BSS) 361 362 363 def test_multiple_ssids(self): 364 """Test with multiple networks with the same ssids.""" 365 scan_output = self.HT40_ABOVE + self.HT20 + self.NO_HT + self.HT20_2 366 host = self.host(scan_output + self.SCAN_TIME_OUTPUT) 367 runner = iw_runner.IwRunner(remote_host=host) 368 networks = runner.wait_for_scan_result('wlan 0', 369 ssids=[self.HT20_2_IW_BSS.ssid]) 370 for iw_bss_1, iw_bss_2 in zip([self.HT20_IW_BSS, self.HT20_2_IW_BSS], 371 networks): 372 self.verify_values(iw_bss_1, iw_bss_2) 373 374 375 def test_station_bssid(self): 376 """Test parsing of the bssid of a station-mode link.""" 377 host = self.host(self.STATION_LINK_INFORMATION) 378 runner = iw_runner.IwRunner(remote_host=host) 379 self.assertEquals( 380 runner.get_current_bssid(self.STATION_LINK_IFACE), 381 self.STATION_LINK_BSSID) 382 383 384 def test_station_link_parsing(self): 385 """Test all link keys can be parsed from station link information.""" 386 self.assertEquals( 387 iw_runner._get_all_link_keys(self.STATION_LINK_INFORMATION), 388 self.STATION_LINK_PARSED) 389 390 391 def test_station_link_key(self): 392 """Test a link key is extracted from station link information.""" 393 host = self.host(self.STATION_LINK_INFORMATION) 394 runner = iw_runner.IwRunner(remote_host=host) 395 self.assertEquals( 396 runner.get_link_value(self.STATION_LINK_INFORMATION, 397 iw_runner.IW_LINK_KEY_FREQUENCY), 398 self.STATION_LINK_FREQ) 399 400 401 def test_station_dump(self): 402 """Test parsing of a station dump.""" 403 host = self.host(self.STATION_DUMP_INFORMATION) 404 runner = iw_runner.IwRunner(remote_host=host) 405 self.assertEquals( 406 runner.get_station_dump(self.STATION_DUMP_IFACE), 407 self.STATION_DUMP_INFORMATION_PARSED) 408 409 410 def test_operating_mode_mesh(self): 411 """Test mesh operating mode parsing.""" 412 host = self.host(self.INFO_MESH_MODE) 413 runner = iw_runner.IwRunner(remote_host=host) 414 self.assertEquals( 415 runner.get_operating_mode(self.INFO_IFACE), 416 iw_runner.DEV_MODE_MESH_POINT) 417 418 419 def test_operating_mode_ap(self): 420 """Test AP operating mode parsing.""" 421 host = self.host(self.INFO_AP_MODE) 422 runner = iw_runner.IwRunner(remote_host=host) 423 self.assertEquals( 424 runner.get_operating_mode(self.INFO_IFACE), 425 iw_runner.DEV_MODE_AP) 426 427 428 def test_operating_mode_station(self): 429 """Test STA operating mode parsing.""" 430 host = self.host(self.INFO_STA_MODE) 431 runner = iw_runner.IwRunner(remote_host=host) 432 self.assertEquals( 433 runner.get_operating_mode(self.INFO_IFACE), 434 iw_runner.DEV_MODE_STATION) 435 436 437 def test_radio_information(self): 438 """Test radio information parsing.""" 439 host = self.host(self.INFO_AP_MODE) 440 runner = iw_runner.IwRunner(remote_host=host) 441 self.assertEquals( 442 runner.get_radio_config(self.INFO_IFACE), 443 self.RADIO_CONFIG_AP_MODE) 444 445 446 if __name__ == '__main__': 447 unittest.main() 448