ACTS: test link probing does not crash device
Added helper method in wifi_test_utils.py to trigger a
link probe and return the result. Added a test to
verify that link probing does not crash the device.
Bug: 112029045
Test: act.py -c ~/Desktop/android_wifi_sanity.config -tb chromeos1-dev-test-station-3 -tc WifiLinkProbeTest
Change-Id: I7557da468a43d68e72b5d32841bbb955cfc2b675
diff --git a/acts/framework/acts/test_utils/wifi/wifi_test_utils.py b/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
index 5d4bba9..12920dc 100755
--- a/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
+++ b/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
@@ -19,6 +19,7 @@
import shutil
import time
+from collections import namedtuple
from enum import IntEnum
from queue import Empty
@@ -2138,6 +2139,65 @@
ad.pull_files(logs, log_path)
+LinkProbeResult = namedtuple('LinkProbeResult', (
+ 'is_success', 'stdout', 'elapsed_time', 'failure_reason'))
+
+
+def send_link_probe(ad):
+ """Sends a link probe to the currently connected AP, and returns whether the
+ probe succeeded or not.
+
+ Args:
+ ad: android device object
+ Returns:
+ LinkProbeResult namedtuple
+ """
+ stdout = ad.adb.shell('cmd wifi send-link-probe')
+ asserts.assert_false('Error' in stdout or 'Exception' in stdout,
+ 'Exception while sending link probe: ' + stdout)
+
+ is_success = False
+ elapsed_time = None
+ failure_reason = None
+ if 'succeeded' in stdout:
+ is_success = True
+ elapsed_time = next(
+ (int(token) for token in stdout.split() if token.isdigit()), None)
+ elif 'failed with reason' in stdout:
+ failure_reason = next(
+ (int(token) for token in stdout.split() if token.isdigit()), None)
+ else:
+ asserts.fail('Unexpected link probe result: ' + stdout)
+
+ return LinkProbeResult(
+ is_success=is_success, stdout=stdout,
+ elapsed_time=elapsed_time, failure_reason=failure_reason)
+
+
+def send_link_probes(ad, num_probes, delay_sec):
+ """Sends a sequence of link probes to the currently connected AP, and
+ returns whether the probes succeeded or not.
+
+ Args:
+ ad: android device object
+ num_probes: number of probes to perform
+ delay_sec: delay time between probes, in seconds
+ Returns:
+ List[LinkProbeResult] one LinkProbeResults for each probe
+ """
+ logging.info('Sending link probes')
+ results = []
+ for _ in range(num_probes):
+ # send_link_probe() will also fail the test if it sees an exception
+ # in the stdout of the adb shell command
+ result = send_link_probe(ad)
+ logging.info('link probe results: ' + str(result))
+ results.append(result)
+ time.sleep(delay_sec)
+
+ return results
+
+
def ap_setup(test, index, ap, network, bandwidth=80, channel=6):
"""Set up the AP with provided network info.
diff --git a/acts/tests/google/wifi/WifiLinkProbeTest.py b/acts/tests/google/wifi/WifiLinkProbeTest.py
new file mode 100644
index 0000000..23ea7a5
--- /dev/null
+++ b/acts/tests/google/wifi/WifiLinkProbeTest.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 - The Android Open Source Project
+#
+# 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.
+
+import time
+
+from acts import asserts
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
+import acts.test_utils.wifi.wifi_test_utils as wutils
+
+WifiEnums = wutils.WifiEnums
+NUM_LINK_PROBES = 8
+PROBE_DELAY_SEC = 3
+ATTENUATION = 40
+
+
+class WifiLinkProbeTest(WifiBaseTest):
+ """
+ Tests sending 802.11 Probe Request frames to the currently connected AP to
+ determine if the uplink to the AP is working.
+
+ Test Bed Requirements:
+ * One Android Device
+ * One Wi-Fi network visible to the device, with an attenuator
+ """
+
+ def __init__(self, controllers):
+ super().__init__(controllers)
+
+ def setup_class(self):
+ self.dut = self.android_devices[0]
+ wutils.wifi_test_device_init(self.dut)
+ self.unpack_userparams(req_param_names=[],
+ opt_param_names=["reference_networks"])
+
+ if "AccessPoint" in self.user_params:
+ self.legacy_configure_ap_and_start()
+
+ asserts.assert_true(len(self.reference_networks) > 0,
+ "Need at least one reference network with psk.")
+ self.attenuators = wutils.group_attenuators(self.attenuators)
+
+ def setup_test(self):
+ self.dut.droid.wakeLockAcquireBright()
+ self.dut.droid.wakeUpNow()
+ wutils.wifi_toggle_state(self.dut, True)
+ self.attenuators[0].set_atten(0)
+ self.attenuators[1].set_atten(0)
+
+ def teardown_test(self):
+ self.dut.droid.wakeLockRelease()
+ self.dut.droid.goToSleepNow()
+ wutils.reset_wifi(self.dut)
+
+ def on_fail(self, test_name, begin_time):
+ self.dut.take_bug_report(test_name, begin_time)
+ self.dut.cat_adb_log(test_name, begin_time)
+
+ def teardown_class(self):
+ if "AccessPoint" in self.user_params:
+ del self.user_params["reference_networks"]
+
+ # HELPER METHODS
+
+ def _test_link_probe_does_not_crash_device(self, network):
+ """
+ Connect to a network, send link probes, and verify that the device did
+ not crash. Also verify that at least one link probe succeeded.
+
+ Steps:
+ 1. Connect to a network.
+ 2. Send a few link probes.
+ 3. Verify that at least one link probe succeeded.
+ 4. Ensure that the device did not crash (by checking that it is
+ connected to the expected network).
+ """
+ wutils.wifi_connect(self.dut, network, num_of_tries=3)
+
+ results = wutils.send_link_probes(
+ self.dut, NUM_LINK_PROBES, PROBE_DELAY_SEC)
+
+ asserts.assert_true(any(result.is_success for result in results),
+ "Expect at least 1 probe success: " + str(results))
+
+ wifi_info = self.dut.droid.wifiGetConnectionInfo()
+ expected = network[WifiEnums.SSID_KEY]
+ actual = wifi_info[WifiEnums.SSID_KEY]
+ asserts.assert_equal(
+ expected, actual,
+ "Device did not remain connected after sending link probes!")
+
+ def _test_link_probe_ap_attenuated(self, network):
+ """
+ Connect to a network, significantly attenuate the signal, and verify
+ that the device did not crash.
+
+ Steps:
+ 1. Connect to a network.
+ 2. Attenuate the signal.
+ 3. Send a few link probes.
+ 4. Stop attenuating the signal.
+ 5. Ensure that the device did not crash (by checking that it is
+ connected to the expected network).
+ """
+ wutils.wifi_connect(self.dut, network, num_of_tries=3)
+ self.attenuators[0].set_atten(ATTENUATION)
+
+ wutils.send_link_probes(self.dut, NUM_LINK_PROBES, PROBE_DELAY_SEC)
+
+ # we cannot assert for failed link probe when attenuated, this would
+ # depend too much on the attenuator setup => too flaky
+
+ self.attenuators[0].set_atten(0)
+ time.sleep(PROBE_DELAY_SEC * 3)
+ wifi_info = self.dut.droid.wifiGetConnectionInfo()
+ expected = network[WifiEnums.SSID_KEY]
+ actual = wifi_info[WifiEnums.SSID_KEY]
+ asserts.assert_equal(
+ expected, actual,
+ "Device did not remain connected after sending link probes!")
+
+ # TEST METHODS
+
+ @test_tracker_info(uuid='2afd309b-6bf3-4de4-9d8a-e4d35354a2cb')
+ def test_link_probe_does_not_crash_device_2g(self):
+ network = self.reference_networks[0]["2g"]
+ self._test_link_probe_does_not_crash_device(network)
+
+ @test_tracker_info(uuid='69417a6d-7090-4dd0-81ad-55fa3f12b7b1')
+ def test_link_probe_does_not_crash_device_5g(self):
+ network = self.reference_networks[0]["5g"]
+ self._test_link_probe_does_not_crash_device(network)
+
+ @test_tracker_info(uuid='54b8ffaa-c305-4772-928d-03342c51122d')
+ def test_link_probe_ap_attenuated_2g(self):
+ network = self.reference_networks[0]["2g"]
+ self._test_link_probe_ap_attenuated(network)
+
+ @test_tracker_info(uuid='54e29fa4-ff44-4aad-8999-676b361cacf4')
+ def test_link_probe_ap_attenuated_5g(self):
+ network = self.reference_networks[0]["5g"]
+ self._test_link_probe_ap_attenuated(network)
+