blob: 8879dd7e46c4a56dfacc3f1a6b6ce8f74c20f5bd [file] [log] [blame]
#!/usr/bin/env python3
#
# 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.
"""
Script for testing WiFi connection and disconnection in a loop
"""
import logging
import time
from dataclasses import dataclass
from mobly import asserts, signals, test_runner
from mobly.records import TestResultRecord
from antlion.controllers.access_point import setup_ap
from antlion.controllers.ap_lib.hostapd_constants import (
AP_DEFAULT_CHANNEL_2G,
AP_DEFAULT_CHANNEL_5G,
)
from antlion.controllers.ap_lib.hostapd_security import Security, SecurityMode
from antlion.test_utils.abstract_devices.wlan_device import AssociationMode
from antlion.test_utils.wifi import base_test
from antlion.utils import rand_ascii_str
@dataclass
class TestParams:
profile: str
channel: int
security_mode: SecurityMode
ap_ssid: str
ap_password: str | None
dut_ssid: str
dut_password: str | None
expect_associated: bool
class ConnectionStressTest(base_test.WifiBaseTest):
# Default number of test iterations here.
# Override using parameter in config file.
# Eg: "connection_stress_test_iterations": "50"
num_of_iterations = 10
def pre_run(self) -> None:
tests: list[TestParams] = []
# Successful associate
for profile in ["whirlwind", "whirlwind_11ab_legacy", "whirlwind_11ag_legacy"]:
for channel in [AP_DEFAULT_CHANNEL_2G, AP_DEFAULT_CHANNEL_5G]:
ssid = rand_ascii_str(10)
tests.append(
TestParams(
profile=profile,
channel=channel,
security_mode=SecurityMode.OPEN,
ap_ssid=ssid,
ap_password=None,
dut_ssid=ssid,
dut_password=None,
expect_associated=True,
)
)
# Wrong SSID
for channel in [AP_DEFAULT_CHANNEL_2G, AP_DEFAULT_CHANNEL_5G]:
ssid = rand_ascii_str(10)
tests.append(
TestParams(
profile="whirlwind",
channel=channel,
security_mode=SecurityMode.OPEN,
ap_ssid=ssid,
ap_password=None,
dut_ssid=f"wrong_{ssid}",
dut_password=None,
expect_associated=False,
)
)
# Wrong password
for channel in [AP_DEFAULT_CHANNEL_2G, AP_DEFAULT_CHANNEL_5G]:
ssid = rand_ascii_str(10)
password = rand_ascii_str(20)
tests.append(
TestParams(
profile="whirlwind",
channel=channel,
security_mode=SecurityMode.WPA2,
ap_ssid=ssid,
ap_password=password,
dut_ssid=ssid,
dut_password=f"wrong_{password}",
expect_associated=False,
)
)
def test_name(test: TestParams) -> str:
channel = "2g" if test.channel == AP_DEFAULT_CHANNEL_2G else "5g"
if test.expect_associated:
return f"test_{test.profile}_{channel}"
if test.ap_ssid != test.dut_ssid:
return f"test_{test.profile}_{channel}_wrong_ssid"
if test.ap_password != test.dut_password:
return f"test_{test.profile}_{channel}_wrong_password"
raise TypeError(f"Unknown name for {test}")
self.generate_tests(self.connect_disconnect, test_name, [(t,) for t in tests])
def setup_class(self) -> None:
super().setup_class()
self.log = logging.getLogger()
self.ssid = rand_ascii_str(10)
self.dut = self.get_dut(AssociationMode.POLICY)
if len(self.access_points) == 0:
raise signals.TestAbortClass("Requires at least one access point")
self.access_point = self.access_points[0]
self.num_of_iterations = int(
self.user_params.get(
"connection_stress_test_iterations", self.num_of_iterations
)
)
self.log.info(f"iterations: {self.num_of_iterations}")
def teardown_test(self) -> None:
self.dut.reset_wifi()
self.download_logs()
self.access_point.stop_all_aps()
def on_fail(self, record: TestResultRecord) -> None:
super().on_fail(record)
self.access_point.stop_all_aps()
def connect_disconnect(self, test: TestParams) -> None:
"""Helper to start an AP, connect DUT to it and disconnect
Args:
ap_config: Dictionary containing profile name and channel
ssid: ssid to connect to
password: password for the ssid to connect to
"""
setup_ap(
access_point=self.access_point,
profile_name=test.profile,
channel=test.channel,
ssid=test.ap_ssid,
security=Security(
security_mode=test.security_mode, password=test.ap_password
),
)
for iteration in range(0, self.num_of_iterations):
associated = self.dut.associate(
test.dut_ssid,
target_pwd=test.dut_password,
target_security=test.security_mode,
)
asserts.assert_equal(
associated,
test.expect_associated,
(
f"Attempt {iteration}/{self.num_of_iterations}: "
f"associated={associated}, want {test.expect_associated}"
),
)
self.dut.disconnect()
# Wait a second before trying again
time.sleep(1)
if __name__ == "__main__":
test_runner.main()