diff --git a/staticlibs/tests/unit/host/python/apf_utils_test.py b/staticlibs/tests/unit/host/python/apf_utils_test.py index b5a941bf77..96b967b079 100644 --- a/staticlibs/tests/unit/host/python/apf_utils_test.py +++ b/staticlibs/tests/unit/host/python/apf_utils_test.py @@ -25,6 +25,8 @@ from net_tests_utils.host.python.apf_utils import ( get_apf_capabilities, get_apf_counter, get_apf_counters_from_dumpsys, + get_ipv4_address, + get_ipv6_address, get_hardware_address, is_send_raw_packet_downstream_supported, send_raw_packet_downstream, @@ -111,6 +113,46 @@ IpClient.wlan1 with asserts.assert_raises(PatternNotFoundException): get_hardware_address(self.mock_ad, "wlan0") + @patch("net_tests_utils.host.python.adb_utils.adb_shell") + def test_get_ipv4_address_success( + self, mock_adb_shell: MagicMock + ) -> None: + mock_adb_shell.return_value = """ +54: wlan0: mtu 1500 state UP qlen 1000 +inet 192.168.195.162/24 brd 192.168.195.255 scope global wlan0 +valid_lft forever preferred_lft forever +""" + ip_address = get_ipv4_address(self.mock_ad, "wlan0") + asserts.assert_equal(ip_address, "192.168.195.162") + + @patch("net_tests_utils.host.python.adb_utils.adb_shell") + def test_get_ipv4_address_not_found( + self, mock_adb_shell: MagicMock + ) -> None: + mock_adb_shell.return_value = "" + with asserts.assert_raises(PatternNotFoundException): + get_ipv4_address(self.mock_ad, "wlan0") + + @patch("net_tests_utils.host.python.adb_utils.adb_shell") + def test_get_ipv6_address_success( + self, mock_adb_shell: MagicMock + ) -> None: + mock_adb_shell.return_value = """ +54: wlan0: mtu 1500 state UP qlen 1000 +inet6 fe80::10a3:5dff:fe52:de32/64 scope link +valid_lft forever preferred_lft forever +""" + ip_address = get_ipv6_address(self.mock_ad, "wlan0") + asserts.assert_equal(ip_address, "fe80::10a3:5dff:fe52:de32") + + @patch("net_tests_utils.host.python.adb_utils.adb_shell") + def test_get_ipv6_address_not_found( + self, mock_adb_shell: MagicMock + ) -> None: + mock_adb_shell.return_value = "" + with asserts.assert_raises(PatternNotFoundException): + get_ipv6_address(self.mock_ad, "wlan0") + @patch("net_tests_utils.host.python.adb_utils.adb_shell") def test_send_raw_packet_downstream_success( self, mock_adb_shell: MagicMock diff --git a/staticlibs/testutils/host/python/apf_utils.py b/staticlibs/testutils/host/python/apf_utils.py index c3330d259a..b312bcf4b5 100644 --- a/staticlibs/testutils/host/python/apf_utils.py +++ b/staticlibs/testutils/host/python/apf_utils.py @@ -83,6 +83,80 @@ def get_apf_counters_from_dumpsys( ad.log.debug("Getting apf counters: " + str(result)) return result +def get_ipv4_address( + ad: android_device.AndroidDevice, iface_name: str +) -> str: + """Retrieves the IPv4 address of a given interface on an Android device. + + This function executes an ADB shell command (`ip -4 address show`) to get the + network interface information and extracts the IPv4 address from the output. + If devices has multiple IPv4 addresses, return the first one. + If devices have no IPv4 address, raise PatternNotFoundException. + + Args: + ad: The Android device object. + iface_name: The name of the network interface (e.g., "wlan0"). + + Returns: + The IPv4 address of the interface as a string. + + Raises: + PatternNotFoundException: If the IPv4 address is not found in the command + output. + """ + # output format: + # 54: wlan2: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 + # inet 192.168.195.162/24 brd 192.168.195.255 scope global wlan2 + # valid_lft forever preferred_lft forever + output = adb_utils.adb_shell(ad, f"ip -4 address show {iface_name}") + pattern = r"inet\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/\d+" + match = re.search(pattern, output) + + if match: + return match.group(1) # Extract the IPv4 address string. + else: + raise PatternNotFoundException( + "Cannot get hardware address for " + iface_name + ) + +def get_ipv6_address( + ad: android_device.AndroidDevice, iface_name: str +) -> str: + """Retrieves the IPv6 address of a given interface on an Android device. + + This function executes an ADB shell command (`ip -6 address show`) to get the + network interface information and extracts the IPv6 address from the output. + If devices has multiple IPv6 addresses, return the first one. + If devices have no IPv6 address, raise PatternNotFoundException. + + Args: + ad: The Android device object. + iface_name: The name of the network interface (e.g., "wlan0"). + + Returns: + The IPv6 address of the interface as a string. + + Raises: + PatternNotFoundException: If the IPv6 address is not found in the command + output. + """ + # output format + # 54: wlan2: mtu 1500 state UP qlen 1000 + # inet6 fe80::10a3:5dff:fe52:de32/64 scope link + # valid_lft forever preferred_lft forever + output = adb_utils.adb_shell(ad, f"ip -6 address show {iface_name}") + if output is "": + raise PatternNotFoundException( + "Cannot get ipv6 address for " + iface_name + ) + pattern = r"inet6\s+([0-9a-fA-F:]+)\/\d+" + match = re.search(pattern, output) + if match: + return match.group(1) # Extract the IPv6 address string. + else: + raise PatternNotFoundException( + "Cannot get IPv6 address for " + iface_name + ) def get_hardware_address( ad: android_device.AndroidDevice, iface_name: str