blob: fca98b6b7be045c8cadd249fcf28b4f5954f7156 [file] [log] [blame]
#!/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
"""
import logging
from datetime import datetime
from mobly import signals, test_runner
from mobly.records import TestResultRecord
from antlion.controllers.ap_lib import (
hostapd_ap_preset,
hostapd_bss_settings,
hostapd_constants,
hostapd_security,
)
from antlion.test_utils.wifi import base_test
class WlanScanTest(base_test.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.log = logging.getLogger()
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 self.access_point:
# 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 self.access_point:
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 self.access_point:
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 self.access_point:
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 self.access_point:
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.disconnect()
def teardown_class(self):
if self.start_access_point:
self.download_ap_logs()
self.access_point.stop_all_aps()
def on_fail(self, record: TestResultRecord):
for fd in self.fuchsia_devices:
super().on_device_fail(fd, record)
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: "
f"{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.scan_for_bss_info().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.scan()
# 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(
f"Aborting test - scan failed with error: {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(f"scan time: {total_time_ms:.2f} ms")
if len(scan_results) > 0:
raise signals.TestPass(
details="", extras={"Scan time": f"{total_time_ms:.2f}"}
)
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)
if __name__ == "__main__":
test_runner.main()