Refactor ApfV4Test
This is a no-op refactoring, which is preparation for follow-up
changes to add more apf test classes.
This includes:
1. Move initialization code to a base class, which setup a hotspot
and a client connects to it, and enable doze mode to
activate the apf.
2. Check whether send raw packet is supported before testing.
Test: m connectivity_multi_devices_snippet && \
atest CtsConnectivityMultiDevicesTestCases
Test: atest NetworkStaticLibHostPythonTests
Bug: 350880989
Change-Id: I6376935883653182728e473e2f5533407d993d7b
diff --git a/staticlibs/tests/unit/host/python/apf_utils_test.py b/staticlibs/tests/unit/host/python/apf_utils_test.py
index caaf959..b9a270f 100644
--- a/staticlibs/tests/unit/host/python/apf_utils_test.py
+++ b/staticlibs/tests/unit/host/python/apf_utils_test.py
@@ -26,11 +26,15 @@
get_apf_counter,
get_apf_counters_from_dumpsys,
get_hardware_address,
+ is_send_raw_packet_downstream_supported,
send_broadcast_empty_ethercat_packet,
send_raw_packet_downstream,
)
from net_tests_utils.host.python.assert_utils import UnexpectedBehaviorError
+TEST_IFACE_NAME = "eth0"
+TEST_PACKET_IN_HEX = "AABBCCDDEEFF"
+
class TestApfUtils(base_test.BaseTestClass, parameterized.TestCase):
@@ -125,13 +129,13 @@
self, mock_adb_shell: MagicMock
) -> None:
mock_adb_shell.return_value = "" # Successful command output
- iface_name = "eth0"
- packet_in_hex = "AABBCCDDEEFF"
- send_raw_packet_downstream(self.mock_ad, iface_name, packet_in_hex)
+ send_raw_packet_downstream(
+ self.mock_ad, TEST_IFACE_NAME, TEST_PACKET_IN_HEX
+ )
mock_adb_shell.assert_called_once_with(
self.mock_ad,
"cmd network_stack send-raw-packet-downstream"
- f" {iface_name} {packet_in_hex}",
+ f" {TEST_IFACE_NAME} {TEST_PACKET_IN_HEX}",
)
@patch("net_tests_utils.host.python.adb_utils.adb_shell")
@@ -142,7 +146,13 @@
"Any Unexpected Output"
)
with asserts.assert_raises(UnexpectedBehaviorError):
- send_raw_packet_downstream(self.mock_ad, "eth0", "AABBCCDDEEFF")
+ send_raw_packet_downstream(
+ self.mock_ad, TEST_IFACE_NAME, TEST_PACKET_IN_HEX
+ )
+ asserts.assert_true(
+ is_send_raw_packet_downstream_supported(self.mock_ad),
+ "Send raw packet should be supported.",
+ )
@patch("net_tests_utils.host.python.adb_utils.adb_shell")
def test_send_raw_packet_downstream_unsupported(
@@ -152,7 +162,13 @@
cmd="", stdout="Unknown command", stderr="", ret_code=3
)
with asserts.assert_raises(UnsupportedOperationException):
- send_raw_packet_downstream(self.mock_ad, "eth0", "AABBCCDDEEFF")
+ send_raw_packet_downstream(
+ self.mock_ad, TEST_IFACE_NAME, TEST_PACKET_IN_HEX
+ )
+ asserts.assert_false(
+ is_send_raw_packet_downstream_supported(self.mock_ad),
+ "Send raw packet should not be supported.",
+ )
@parameterized.parameters(
("2,2048,1", ApfCapabilities(2, 2048, 1)), # Valid input
diff --git a/staticlibs/testutils/host/python/apf_test_base.py b/staticlibs/testutils/host/python/apf_test_base.py
new file mode 100644
index 0000000..86e7a26
--- /dev/null
+++ b/staticlibs/testutils/host/python/apf_test_base.py
@@ -0,0 +1,51 @@
+# Copyright (C) 2024 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.
+
+from mobly import asserts
+from net_tests_utils.host.python import adb_utils, apf_utils, multi_devices_test_base, tether_utils
+from net_tests_utils.host.python.tether_utils import UpstreamType
+
+
+class ApfTestBase(multi_devices_test_base.MultiDevicesTestBase):
+
+ def setup_class(self):
+ super().setup_class()
+ tether_utils.assume_hotspot_test_preconditions(
+ self.serverDevice, self.clientDevice, UpstreamType.NONE
+ )
+ asserts.abort_class_if(
+ not apf_utils.is_send_raw_packet_downstream_supported(
+ self.serverDevice
+ ),
+ "NetworkStack is too old to support send raw packet, skip test.",
+ )
+
+ client = self.clientDevice.connectivity_multi_devices_snippet
+
+ self.server_iface_name, client_network = (
+ tether_utils.setup_hotspot_and_client_for_upstream_type(
+ self.serverDevice, self.clientDevice, UpstreamType.NONE
+ )
+ )
+ self.client_iface_name = client.getInterfaceNameFromNetworkHandle(
+ client_network
+ )
+
+ adb_utils.set_doze_mode(self.clientDevice, True)
+
+ def teardown_class(self):
+ adb_utils.set_doze_mode(self.clientDevice, False)
+ tether_utils.cleanup_tethering_for_upstream_type(
+ self.serverDevice, UpstreamType.NONE
+ )
diff --git a/staticlibs/testutils/host/python/apf_utils.py b/staticlibs/testutils/host/python/apf_utils.py
index 415799c..7ebf792 100644
--- a/staticlibs/testutils/host/python/apf_utils.py
+++ b/staticlibs/testutils/host/python/apf_utils.py
@@ -142,6 +142,19 @@
send_raw_packet_downstream(ad, iface_name, packet)
+def is_send_raw_packet_downstream_supported(
+ ad: android_device.AndroidDevice,
+) -> bool:
+ try:
+ # Invoke the shell command with empty argument and see how NetworkStack respond.
+ # If supported, an IllegalArgumentException with help page will be printed.
+ send_raw_packet_downstream(ad, "", "")
+ except assert_utils.UnexpectedBehaviorError:
+ return True
+ except UnsupportedOperationException:
+ return False
+
+
def send_raw_packet_downstream(
ad: android_device.AndroidDevice,
iface_name: str,
diff --git a/tests/cts/multidevices/apfv4_test.py b/tests/cts/multidevices/apfv4_test.py
index 5844e49..7652c65 100644
--- a/tests/cts/multidevices/apfv4_test.py
+++ b/tests/cts/multidevices/apfv4_test.py
@@ -12,57 +12,32 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from net_tests_utils.host.python import adb_utils, apf_utils, assert_utils, mdns_utils, multi_devices_test_base, tether_utils
+from mobly import asserts
+from net_tests_utils.host.python import adb_utils, apf_test_base, apf_utils, assert_utils, tether_utils
from net_tests_utils.host.python.tether_utils import UpstreamType
COUNTER_DROPPED_ETHERTYPE_NOT_ALLOWED = "DROPPED_ETHERTYPE_NOT_ALLOWED"
-class ApfV4Test(multi_devices_test_base.MultiDevicesTestBase):
+class ApfV4Test(apf_test_base.ApfTestBase):
def test_apf_drop_ethercat(self):
- tether_utils.assume_hotspot_test_preconditions(
- self.serverDevice, self.clientDevice, UpstreamType.NONE
+ count_before_test = apf_utils.get_apf_counter(
+ self.clientDevice,
+ self.client_iface_name,
+ COUNTER_DROPPED_ETHERTYPE_NOT_ALLOWED,
)
- client = self.clientDevice.connectivity_multi_devices_snippet
- try:
- server_iface_name, client_network = (
- tether_utils.setup_hotspot_and_client_for_upstream_type(
- self.serverDevice, self.clientDevice, UpstreamType.NONE
- )
- )
- client_iface_name = client.getInterfaceNameFromNetworkHandle(
- client_network
- )
+ apf_utils.send_broadcast_empty_ethercat_packet(
+ self.serverDevice, self.server_iface_name
+ )
- adb_utils.set_doze_mode(self.clientDevice, True)
-
- count_before_test = apf_utils.get_apf_counter(
- self.clientDevice,
- client_iface_name,
- COUNTER_DROPPED_ETHERTYPE_NOT_ALLOWED,
- )
- try:
- apf_utils.send_broadcast_empty_ethercat_packet(
- self.serverDevice, server_iface_name
+ assert_utils.expect_with_retry(
+ lambda: apf_utils.get_apf_counter(
+ self.clientDevice,
+ self.client_iface_name,
+ COUNTER_DROPPED_ETHERTYPE_NOT_ALLOWED,
)
- except apf_utils.UnsupportedOperationException:
- asserts.skip(
- "NetworkStack is too old to support send raw packet, skip test."
- )
+ > count_before_test
+ )
- assert_utils.expect_with_retry(
- lambda: apf_utils.get_apf_counter(
- self.clientDevice,
- client_iface_name,
- COUNTER_DROPPED_ETHERTYPE_NOT_ALLOWED,
- )
- > count_before_test
- )
-
- # TODO: Verify the packet is not actually received.
- finally:
- adb_utils.set_doze_mode(self.clientDevice, False)
- tether_utils.cleanup_tethering_for_upstream_type(
- self.serverDevice, UpstreamType.NONE
- )
+ # TODO: Verify the packet is not actually received.