Home | History | Annotate | Download | only in network
      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     PHY_INFO_FRAGMENTATION = str(
    292         'Wiphy phy1\n'
    293         '        max # scan SSIDs: 20\n'
    294         '        max scan IEs length: 425 bytes\n'
    295         '        Fragmentation threshold: 256\n'
    296         '        Retry short limit: 7\n'
    297         '        Retry long limit: 4\n')
    298 
    299     INFO_PHY = 'phy1'
    300 
    301     PHY_FRAGMENTATION_THRESHOLD = 256
    302 
    303 
    304     def verify_values(self, iw_bss_1, iw_bss_2):
    305         """Checks all of the IWBss values
    306 
    307         @param iw_bss_1: an IWBss object
    308         @param iw_bss_2: an IWBss object
    309 
    310         """
    311         self.assertEquals(iw_bss_1.bss, iw_bss_2.bss)
    312         self.assertEquals(iw_bss_1.ssid, iw_bss_2.ssid)
    313         self.assertEquals(iw_bss_1.frequency, iw_bss_2.frequency)
    314         self.assertEquals(iw_bss_1.security, iw_bss_2.security)
    315         self.assertEquals(iw_bss_1.ht, iw_bss_2.ht)
    316         self.assertEquals(iw_bss_1.signal, iw_bss_2.signal)
    317 
    318 
    319     def search_by_bss(self, scan_output, test_iw_bss):
    320         """
    321 
    322         @param scan_output: the output of the scan as a string
    323         @param test_iw_bss: an IWBss object
    324 
    325         Uses the runner to search for a network by bss.
    326         """
    327         host = self.host(scan_output + self.SCAN_TIME_OUTPUT)
    328         runner = iw_runner.IwRunner(remote_host=host)
    329         network = runner.wait_for_scan_result('wlan0', bsses=[test_iw_bss.bss])
    330         self.verify_values(test_iw_bss, network[0])
    331 
    332 
    333     def test_find_first(self):
    334         """Test with the first item in the list."""
    335         scan_output = self.HT20 + self.HT40_ABOVE
    336         self.search_by_bss(scan_output, self.HT20_IW_BSS)
    337 
    338 
    339     def test_find_last(self):
    340         """Test with the last item in the list."""
    341         scan_output = self.HT40_ABOVE + self.HT20
    342         self.search_by_bss(scan_output, self.HT20_IW_BSS)
    343 
    344 
    345     def test_find_middle(self):
    346         """Test with the middle item in the list."""
    347         scan_output = self.HT40_ABOVE + self.HT20 + self.NO_HT
    348         self.search_by_bss(scan_output, self.HT20_IW_BSS)
    349 
    350 
    351     def test_ht40_above(self):
    352         """Test with a HT40+ network."""
    353         scan_output = self.HT20 + self.HT40_ABOVE + self.NO_HT
    354         self.search_by_bss(scan_output, self.HT40_ABOVE_IW_BSS)
    355 
    356 
    357     def test_ht40_below(self):
    358         """Test with a HT40- network."""
    359         scan_output = self.HT20 + self.HT40_BELOW + self.NO_HT
    360         self.search_by_bss(scan_output, self.HT40_BELOW_IW_BSS)
    361 
    362 
    363     def test_no_ht(self):
    364         """Test with a network that doesn't have ht."""
    365         scan_output = self.HT20 + self.NO_HT + self.HT40_ABOVE
    366         self.search_by_bss(scan_output, self.NO_HT_IW_BSS)
    367 
    368 
    369     def test_hidden_ssid(self):
    370         """Test with a network with a hidden ssid."""
    371         scan_output = self.HT20 + self.HIDDEN_SSID + self.NO_HT
    372         self.search_by_bss(scan_output, self.HIDDEN_SSID_IW_BSS)
    373 
    374 
    375     def test_multiple_ssids(self):
    376         """Test with multiple networks with the same ssids."""
    377         scan_output = self.HT40_ABOVE + self.HT20 + self.NO_HT + self.HT20_2
    378         host = self.host(scan_output + self.SCAN_TIME_OUTPUT)
    379         runner = iw_runner.IwRunner(remote_host=host)
    380         networks = runner.wait_for_scan_result('wlan 0',
    381                                                ssids=[self.HT20_2_IW_BSS.ssid])
    382         for iw_bss_1, iw_bss_2 in zip([self.HT20_IW_BSS, self.HT20_2_IW_BSS],
    383                                       networks):
    384             self.verify_values(iw_bss_1, iw_bss_2)
    385 
    386 
    387     def test_station_bssid(self):
    388         """Test parsing of the bssid of a station-mode link."""
    389         host = self.host(self.STATION_LINK_INFORMATION)
    390         runner = iw_runner.IwRunner(remote_host=host)
    391         self.assertEquals(
    392             runner.get_current_bssid(self.STATION_LINK_IFACE),
    393             self.STATION_LINK_BSSID)
    394 
    395 
    396     def test_station_link_parsing(self):
    397         """Test all link keys can be parsed from station link information."""
    398         self.assertEquals(
    399             iw_runner._get_all_link_keys(self.STATION_LINK_INFORMATION),
    400             self.STATION_LINK_PARSED)
    401 
    402 
    403     def test_station_link_key(self):
    404         """Test a link key is extracted from station link information."""
    405         host = self.host(self.STATION_LINK_INFORMATION)
    406         runner = iw_runner.IwRunner(remote_host=host)
    407         self.assertEquals(
    408             runner.get_link_value(self.STATION_LINK_INFORMATION,
    409                                   iw_runner.IW_LINK_KEY_FREQUENCY),
    410             self.STATION_LINK_FREQ)
    411 
    412 
    413     def test_station_dump(self):
    414         """Test parsing of a station dump."""
    415         host = self.host(self.STATION_DUMP_INFORMATION)
    416         runner = iw_runner.IwRunner(remote_host=host)
    417         self.assertEquals(
    418             runner.get_station_dump(self.STATION_DUMP_IFACE),
    419             self.STATION_DUMP_INFORMATION_PARSED)
    420 
    421 
    422     def test_operating_mode_mesh(self):
    423         """Test mesh operating mode parsing."""
    424         host = self.host(self.INFO_MESH_MODE)
    425         runner = iw_runner.IwRunner(remote_host=host)
    426         self.assertEquals(
    427             runner.get_operating_mode(self.INFO_IFACE),
    428             iw_runner.DEV_MODE_MESH_POINT)
    429 
    430 
    431     def test_operating_mode_ap(self):
    432         """Test AP operating mode parsing."""
    433         host = self.host(self.INFO_AP_MODE)
    434         runner = iw_runner.IwRunner(remote_host=host)
    435         self.assertEquals(
    436             runner.get_operating_mode(self.INFO_IFACE),
    437             iw_runner.DEV_MODE_AP)
    438 
    439 
    440     def test_operating_mode_station(self):
    441         """Test STA operating mode parsing."""
    442         host = self.host(self.INFO_STA_MODE)
    443         runner = iw_runner.IwRunner(remote_host=host)
    444         self.assertEquals(
    445             runner.get_operating_mode(self.INFO_IFACE),
    446             iw_runner.DEV_MODE_STATION)
    447 
    448 
    449     def test_radio_information(self):
    450         """Test radio information parsing."""
    451         host = self.host(self.INFO_AP_MODE)
    452         runner = iw_runner.IwRunner(remote_host=host)
    453         self.assertEquals(
    454             runner.get_radio_config(self.INFO_IFACE),
    455             self.RADIO_CONFIG_AP_MODE)
    456 
    457 
    458     def test_fragmentation_threshold(self):
    459         """Test fragmentation threshold parsing."""
    460         host = self.host(self.PHY_INFO_FRAGMENTATION)
    461         runner = iw_runner.IwRunner(remote_host=host)
    462         self.assertEquals(
    463             runner.get_fragmentation_threshold(self.INFO_PHY),
    464             self.PHY_FRAGMENTATION_THRESHOLD)
    465 
    466 
    467 if __name__ == '__main__':
    468     unittest.main()
    469