| #!/usr/bin/env python3.4 |
| # |
| # Copyright 2022 The Fuchsia Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| """ |
| This test exercises basic scanning functionality to confirm expected behavior |
| related to wlan scanning |
| """ |
| |
| from datetime import datetime |
| |
| from antlion import signals |
| from antlion.controllers.ap_lib import hostapd_ap_preset |
| from antlion.controllers.ap_lib import hostapd_bss_settings |
| from antlion.controllers.ap_lib import hostapd_constants |
| from antlion.controllers.ap_lib import hostapd_security |
| from antlion_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest |
| |
| |
| class WlanScanTest(WifiBaseTest): |
| """WLAN scan test class. |
| |
| Test Bed Requirement: |
| * One or more Fuchsia devices |
| * Several Wi-Fi networks visible to the device, including an open Wi-Fi |
| network or a onHub/GoogleWifi |
| """ |
| |
| def setup_class(self): |
| super().setup_class() |
| |
| self.access_point = self.access_points[0] |
| self.start_access_point = False |
| for fd in self.fuchsia_devices: |
| fd.configure_wlan(association_mechanism='drivers') |
| if "AccessPoint" in self.user_params: |
| # This section sets up the config that could be sent to the AP if |
| # the AP is needed. The reasoning is since ACTS already connects |
| # to the AP if it is in the config, generating the config in memory |
| # has no over head is used if need by the test if one of the ssids |
| # needed for the test is not included in the config. The logic |
| # here creates 2 ssids on each radio, 5ghz and 2.4ghz, with an |
| # open, no security network and one that is wpa2, for a total of 4 |
| # networks. However, if all of the ssids are specified in the |
| # the config will never be written to the AP and the AP will not be |
| # brought up. For more information about how to configure the |
| # hostapd config info, see the hostapd libraries, which have more |
| # documentation. |
| bss_settings_2g = [] |
| bss_settings_5g = [] |
| open_network = self.get_open_network(False, []) |
| self.open_network_2g = open_network['2g'] |
| self.open_network_5g = open_network['5g'] |
| wpa2_settings = self.get_psk_network(False, []) |
| self.wpa2_network_2g = wpa2_settings['2g'] |
| self.wpa2_network_5g = wpa2_settings['5g'] |
| bss_settings_2g.append( |
| hostapd_bss_settings.BssSettings( |
| name=self.wpa2_network_2g['SSID'], |
| ssid=self.wpa2_network_2g['SSID'], |
| security=hostapd_security.Security( |
| security_mode=self.wpa2_network_2g["security"], |
| password=self.wpa2_network_2g["password"]))) |
| bss_settings_5g.append( |
| hostapd_bss_settings.BssSettings( |
| name=self.wpa2_network_5g['SSID'], |
| ssid=self.wpa2_network_5g['SSID'], |
| security=hostapd_security.Security( |
| security_mode=self.wpa2_network_5g["security"], |
| password=self.wpa2_network_5g["password"]))) |
| self.ap_2g = hostapd_ap_preset.create_ap_preset( |
| iface_wlan_2g=self.access_point.wlan_2g, |
| iface_wlan_5g=self.access_point.wlan_5g, |
| channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G, |
| ssid=self.open_network_2g['SSID'], |
| bss_settings=bss_settings_2g) |
| self.ap_5g = hostapd_ap_preset.create_ap_preset( |
| iface_wlan_2g=self.access_point.wlan_2g, |
| iface_wlan_5g=self.access_point.wlan_5g, |
| channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G, |
| ssid=self.open_network_5g['SSID'], |
| bss_settings=bss_settings_5g) |
| |
| if "wlan_open_network_2g" in self.user_params: |
| self.open_network_2g = self.user_params.get("wlan_open_network_2g") |
| elif "AccessPoint" in self.user_params: |
| self.start_access_point_2g = True |
| else: |
| raise Exception('Missing parameter in config ' |
| '(wlan_open_network_2g)') |
| |
| if "wlan_open_network_5g" in self.user_params: |
| self.open_network_5g = self.user_params.get("wlan_open_network_5g") |
| elif "AccessPoint" in self.user_params: |
| self.start_access_point_5g = True |
| else: |
| raise Exception('Missing parameter in config ' |
| '(wlan_open_network_5g)') |
| |
| if "wlan_wpa2_network_2g" in self.user_params: |
| self.wpa2_network_2g = self.user_params.get("wlan_wpa2_network_2g") |
| elif "AccessPoint" in self.user_params: |
| self.start_access_point_2g = True |
| else: |
| raise Exception('Missing parameter in config ' |
| '(wlan_wpa2_network_2g)') |
| |
| if "wlan_wpa2_network_5g" in self.user_params: |
| self.wpa2_network_5g = self.user_params.get("wlan_wpa2_network_5g") |
| elif "AccessPoint" in self.user_params: |
| self.start_access_point_5g = True |
| else: |
| raise Exception('Missing parameter in config ' |
| '(wlan_wpa2_network_5g)') |
| |
| # Only bring up the APs that are needed for the test. Each ssid is |
| # randomly generated so there is no chance of re associating to a |
| # previously saved ssid on the device. |
| if self.start_access_point_2g: |
| self.start_access_point = True |
| self.access_point.start_ap(hostapd_config=self.ap_2g) |
| if self.start_access_point_5g: |
| self.start_access_point = True |
| self.access_point.start_ap(hostapd_config=self.ap_5g) |
| |
| def setup_test(self): |
| for fd in self.fuchsia_devices: |
| # stub for setting up all the fuchsia devices in the testbed. |
| pass |
| |
| def teardown_test(self): |
| for fd in self.fuchsia_devices: |
| fd.sl4f.wlan_lib.wlanDisconnect() |
| |
| def teardown_class(self): |
| if self.start_access_point: |
| self.download_ap_logs() |
| self.access_point.stop_all_aps() |
| |
| def on_fail(self, test_name, begin_time): |
| for fd in self.fuchsia_devices: |
| super().on_device_fail(fd, test_name, begin_time) |
| fd.configure_wlan(association_mechanism='drivers') |
| |
| """Helper Functions""" |
| |
| def check_connect_response(self, connection_response): |
| """ Checks the result of connecting to a wlan. |
| Args: |
| connection_response: The response from SL4F after attempting |
| to connect to a wlan. |
| """ |
| if connection_response.get("error") is None: |
| # the command did not get an error response - go ahead and |
| # check the result |
| connection_result = connection_response.get("result") |
| if connection_result: |
| self.log.info("connection to network successful") |
| else: |
| # ideally, we would have the actual error... but logging |
| # here to cover that error case |
| raise signals.TestFailure("Connect call failed, aborting test") |
| else: |
| # the response indicates an error - log and raise failure |
| raise signals.TestFailure("Aborting test - Connect call failed " |
| "with error: %s" % |
| connection_response.get("error")) |
| |
| def scan_while_connected(self, wlan_network_params, fd): |
| """ Connects to as specified network and initiates a scan |
| Args: |
| wlan_network_params: A dictionary containing wlan |
| infomation. |
| fd: The fuchsia device to connect to the wlan. |
| """ |
| target_ssid = wlan_network_params['SSID'] |
| self.log.info("got the ssid! %s", target_ssid) |
| target_pwd = None |
| if 'password' in wlan_network_params: |
| target_pwd = wlan_network_params['password'] |
| |
| bss_scan_response = fd.sl4f.wlan_lib.wlanScanForBSSInfo().get('result') |
| connection_response = fd.sl4f.wlan_lib.wlanConnectToNetwork( |
| target_ssid, |
| bss_scan_response[target_ssid][0], |
| target_pwd=target_pwd) |
| self.check_connect_response(connection_response) |
| self.basic_scan_request(fd) |
| |
| def basic_scan_request(self, fd): |
| """ Initiates a basic scan on a Fuchsia device |
| Args: |
| fd: A fuchsia device |
| """ |
| start_time = datetime.now() |
| |
| scan_response = fd.sl4f.wlan_lib.wlanStartScan() |
| |
| # first check if we received an error |
| if scan_response.get("error") is None: |
| # the scan command did not get an error response - go ahead |
| # and check for scan results |
| scan_results = scan_response["result"] |
| else: |
| # the response indicates an error - log and raise failure |
| raise signals.TestFailure("Aborting test - scan failed with " |
| "error: %s" % scan_response.get("error")) |
| |
| self.log.info("scan contained %d results", len(scan_results)) |
| |
| total_time_ms = (datetime.now() - start_time).total_seconds() * 1000 |
| self.log.info("scan time: %d ms", total_time_ms) |
| |
| if len(scan_results) > 0: |
| raise signals.TestPass(details="", |
| extras={"Scan time": "%d" % total_time_ms}) |
| else: |
| raise signals.TestFailure("Scan failed or did not " |
| "find any networks") |
| |
| """Tests""" |
| |
| def test_basic_scan_request(self): |
| """Verify a general scan trigger returns at least one result""" |
| for fd in self.fuchsia_devices: |
| self.basic_scan_request(fd) |
| |
| def test_scan_while_connected_open_network_2g(self): |
| for fd in self.fuchsia_devices: |
| self.scan_while_connected(self.open_network_2g, fd) |
| |
| def test_scan_while_connected_wpa2_network_2g(self): |
| for fd in self.fuchsia_devices: |
| self.scan_while_connected(self.wpa2_network_2g, fd) |
| |
| def test_scan_while_connected_open_network_5g(self): |
| for fd in self.fuchsia_devices: |
| self.scan_while_connected(self.open_network_5g, fd) |
| |
| def test_scan_while_connected_wpa2_network_5g(self): |
| for fd in self.fuchsia_devices: |
| self.scan_while_connected(self.wpa2_network_5g, fd) |