From 71c0347477c3baf678041cb4f7ecc5b6bda03437 Mon Sep 17 00:00:00 2001 From: Dio He <133635472+diohe0311@users.noreply.github.com> Date: Mon, 29 May 2023 15:31:53 +0800 Subject: [PATCH 01/11] add test_network_device_info.py for unit test --- .../base/tests/test_network_device_info.py | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 providers/base/tests/test_network_device_info.py diff --git a/providers/base/tests/test_network_device_info.py b/providers/base/tests/test_network_device_info.py new file mode 100644 index 0000000000..b6c7ed45b3 --- /dev/null +++ b/providers/base/tests/test_network_device_info.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# Copyright 2020 Canonical Ltd. +# Written by: +# Dio He +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import fcntl +import struct +import socket +import unittest +import subprocess +from unittest.mock import Mock, patch + +import network_device_info + +class GetIpv4AddressTests(unittest.TestCase): + # There are 2 output we could get from fcntl.ioctl(): + # 1. No WiFi connected + # (It pulls out bytes data directly from kernel, so if the given SIOCGIFADDR doesn't exist, it raise a OSError) + # "None" + + # 2. Connected with WiFi + # It will pulls out a 256 bytes data into buffer, then we get to parse the IP address + # "192.168.68.101" + def test_get_ipv4_address_without_connection(self): + test_input = "" + mock_ioctl = Mock(return_value=test_input) + with patch("fcntl.ioctl", mock_ioctl): + interface = "wlo1" + addr = get_ipv4_address(interface) + self.assertEqual(addr, "***NOT CONFIGURED***") + + def test_get_ipv4_address_with_connection(self): + test_input = "192.168.68.101" + mock_inet_ntoa = Mock(return_value=test_input) + with patch("socket.inet_ntoa", mock_inet_ntoa): + interface = "wlo1" + addr = get_ipv4_address(interface) + self.assertEqual(addr, "192.168.68.101") + +class GetIpv6AddressTests(unittest.TestCase): + # There are 3 output we could get, but only 2 cases will happen due to the way we command it + # 1. No WiFi connected + # "" + + # 2. Connected with WiFi + # "2: wlo1 inet6 fe80::d9eb:3f93:c7b2:86ba/64 scope link noprefixroute \ valid_lft forever preferred_lft forever" + + # 3. Connected with WiFi, but we ask the wrong interface name (This would not happen in our case, because the name is given by NetworkManager) + # "Device "wlan0" does not exist." + def test_get_ipv6_address_without_connection(self): + test_input = "" + mock_check_output = Mock(return_value=test_input) + with patch("subprocess.check_output", mock_check_output): + interface = "wlo1" + addr = get_ipv6_address(interface) + self.assertEqual(addr, "***NOT CONFIGURED***") + + def test_get_ipv6_address_with_connection(self): + test_input = "2: wlo1 inet6 fe80::d9eb:3f93:c7b2:86ba/64 scope link noprefixroute \ valid_lft forever preferred_lft forever" + mock_check_output = Mock(return_value=test_input) + with patch("subprocess.check_output", mock_check_output): # somehow it don't regonize check_output() if I don't put subprocess in front + interface = "wlo1" + addr = get_ipv6_address(interface) + self.assertEqual(addr, "fe80::d9eb:3f93:c7b2:86ba/64") + +if __name__ == '__main__': + unittest.main() From 7403331e8cc401c50997249b9096055a3c9f2327 Mon Sep 17 00:00:00 2001 From: Dio He <133635472+diohe0311@users.noreply.github.com> Date: Mon, 29 May 2023 15:34:05 +0800 Subject: [PATCH 02/11] modify get_ipv6_address function --- providers/base/bin/network_device_info.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/providers/base/bin/network_device_info.py b/providers/base/bin/network_device_info.py index 9d31f75a88..0842b4ef2d 100755 --- a/providers/base/bin/network_device_info.py +++ b/providers/base/bin/network_device_info.py @@ -96,10 +96,15 @@ def get_ipv4_address(interface): @staticmethod def get_ipv6_address(interface): - cmd = ['/sbin/ip', '-6', '-o', 'addr', 'show', 'dev', interface, - 'scope', 'link'] + cmd = ['/sbin/ip', '-6', '-o', 'addr', 'show', 'dev', interface, 'scope', 'link'] proc = check_output(cmd, universal_newlines=True) - return proc.split()[3].strip() + try: + ipv6_addr = proc.split()[3].strip() + except Exception as e: + print("ERROR: getting the IPv6 address for %s: %s" % + (interface, repr(e))) + ipv6_addr = "***NOT CONFIGURED***" + return ipv6_addr @classmethod def get_mac_address(cls, interface): From 4f895fb26e358837a93d07107f940baea6805d52 Mon Sep 17 00:00:00 2001 From: Dio He <133635472+diohe0311@users.noreply.github.com> Date: Mon, 29 May 2023 16:37:51 +0800 Subject: [PATCH 03/11] fix import issue --- .../base/tests/test_network_device_info.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/providers/base/tests/test_network_device_info.py b/providers/base/tests/test_network_device_info.py index b6c7ed45b3..9c6d48fb13 100644 --- a/providers/base/tests/test_network_device_info.py +++ b/providers/base/tests/test_network_device_info.py @@ -15,14 +15,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import fcntl -import struct -import socket import unittest -import subprocess from unittest.mock import Mock, patch -import network_device_info +from network_device_info import Utils class GetIpv4AddressTests(unittest.TestCase): # There are 2 output we could get from fcntl.ioctl(): @@ -38,7 +34,7 @@ def test_get_ipv4_address_without_connection(self): mock_ioctl = Mock(return_value=test_input) with patch("fcntl.ioctl", mock_ioctl): interface = "wlo1" - addr = get_ipv4_address(interface) + addr = Utils.get_ipv4_address(interface) self.assertEqual(addr, "***NOT CONFIGURED***") def test_get_ipv4_address_with_connection(self): @@ -46,7 +42,7 @@ def test_get_ipv4_address_with_connection(self): mock_inet_ntoa = Mock(return_value=test_input) with patch("socket.inet_ntoa", mock_inet_ntoa): interface = "wlo1" - addr = get_ipv4_address(interface) + addr = Utils.get_ipv4_address(interface) self.assertEqual(addr, "192.168.68.101") class GetIpv6AddressTests(unittest.TestCase): @@ -62,17 +58,17 @@ class GetIpv6AddressTests(unittest.TestCase): def test_get_ipv6_address_without_connection(self): test_input = "" mock_check_output = Mock(return_value=test_input) - with patch("subprocess.check_output", mock_check_output): + with patch("network_device_info.check_output", mock_check_output): interface = "wlo1" - addr = get_ipv6_address(interface) + addr = Utils.get_ipv6_address(interface) self.assertEqual(addr, "***NOT CONFIGURED***") def test_get_ipv6_address_with_connection(self): test_input = "2: wlo1 inet6 fe80::d9eb:3f93:c7b2:86ba/64 scope link noprefixroute \ valid_lft forever preferred_lft forever" mock_check_output = Mock(return_value=test_input) - with patch("subprocess.check_output", mock_check_output): # somehow it don't regonize check_output() if I don't put subprocess in front + with patch("network_device_info.check_output", mock_check_output): # somehow it don't regonize check_output() if I don't put subprocess in front interface = "wlo1" - addr = get_ipv6_address(interface) + addr = Utils.get_ipv6_address(interface) self.assertEqual(addr, "fe80::d9eb:3f93:c7b2:86ba/64") if __name__ == '__main__': From 8b39ec5ac97a1b167a8bd8d44cae4f6eadb7dc80 Mon Sep 17 00:00:00 2001 From: Dio He <133635472+diohe0311@users.noreply.github.com> Date: Mon, 29 May 2023 17:01:56 +0800 Subject: [PATCH 04/11] fix line too long (89 > 79 characters) --- providers/base/bin/network_device_info.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/providers/base/bin/network_device_info.py b/providers/base/bin/network_device_info.py index 0842b4ef2d..d00dca83a8 100755 --- a/providers/base/bin/network_device_info.py +++ b/providers/base/bin/network_device_info.py @@ -96,7 +96,8 @@ def get_ipv4_address(interface): @staticmethod def get_ipv6_address(interface): - cmd = ['/sbin/ip', '-6', '-o', 'addr', 'show', 'dev', interface, 'scope', 'link'] + cmd = ['/sbin/ip', '-6', '-o', 'addr', 'show', 'dev', interface, + 'scope', 'link'] proc = check_output(cmd, universal_newlines=True) try: ipv6_addr = proc.split()[3].strip() From 173dfdbc78476d662960a0d2af30d706427b73f4 Mon Sep 17 00:00:00 2001 From: Dio He <133635472+diohe0311@users.noreply.github.com> Date: Mon, 29 May 2023 17:21:07 +0800 Subject: [PATCH 05/11] modify space --- providers/base/bin/network_device_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers/base/bin/network_device_info.py b/providers/base/bin/network_device_info.py index d00dca83a8..0eabf5c0e1 100755 --- a/providers/base/bin/network_device_info.py +++ b/providers/base/bin/network_device_info.py @@ -96,7 +96,7 @@ def get_ipv4_address(interface): @staticmethod def get_ipv6_address(interface): - cmd = ['/sbin/ip', '-6', '-o', 'addr', 'show', 'dev', interface, + cmd = ['/sbin/ip', '-6', '-o', 'addr', 'show', 'dev', interface, 'scope', 'link'] proc = check_output(cmd, universal_newlines=True) try: From f23c9e58718d376c3c26ecda919ea08343fb2c1a Mon Sep 17 00:00:00 2001 From: Dio He <133635472+diohe0311@users.noreply.github.com> Date: Tue, 30 May 2023 17:01:04 +0800 Subject: [PATCH 06/11] update network_device_info.py move dbus import to where it belong --- providers/base/bin/network_device_info.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/providers/base/bin/network_device_info.py b/providers/base/bin/network_device_info.py index 0eabf5c0e1..d802a2c52c 100755 --- a/providers/base/bin/network_device_info.py +++ b/providers/base/bin/network_device_info.py @@ -28,8 +28,6 @@ from subprocess import check_output, CalledProcessError, STDOUT import sys -import dbus - from checkbox_support.parsers.modinfo import ModinfoParser from checkbox_support.parsers.udevadm import UdevadmParser @@ -284,7 +282,6 @@ def _driver_populate(self): class NMDevices(): - # This example lists basic information about network interfaces known to NM devtypes = {1: "Ethernet", 2: "WiFi", @@ -302,6 +299,7 @@ def __len__(self): return len(self._devices) def _collect_devices(self): + import dbus bus = dbus.SystemBus() proxy = bus.get_object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager") From 4cfcc545917d7a734a76859d9bc76b8278695ed2 Mon Sep 17 00:00:00 2001 From: Dio He <133635472+diohe0311@users.noreply.github.com> Date: Wed, 31 May 2023 10:07:55 +0800 Subject: [PATCH 07/11] Update test_network_device_info.py modify mocked input --- .../base/tests/test_network_device_info.py | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/providers/base/tests/test_network_device_info.py b/providers/base/tests/test_network_device_info.py index 9c6d48fb13..8672d457cf 100644 --- a/providers/base/tests/test_network_device_info.py +++ b/providers/base/tests/test_network_device_info.py @@ -30,7 +30,7 @@ class GetIpv4AddressTests(unittest.TestCase): # It will pulls out a 256 bytes data into buffer, then we get to parse the IP address # "192.168.68.101" def test_get_ipv4_address_without_connection(self): - test_input = "" + test_input = b"" mock_ioctl = Mock(return_value=test_input) with patch("fcntl.ioctl", mock_ioctl): interface = "wlo1" @@ -38,9 +38,26 @@ def test_get_ipv4_address_without_connection(self): self.assertEqual(addr, "***NOT CONFIGURED***") def test_get_ipv4_address_with_connection(self): - test_input = "192.168.68.101" + test_input = (b'wlo1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x02\x00\x00\x00\xc0\xa8De\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + # test_input = b"I'm fake!!!" mock_inet_ntoa = Mock(return_value=test_input) - with patch("socket.inet_ntoa", mock_inet_ntoa): + with patch("fcntl.ioctl", mock_inet_ntoa): interface = "wlo1" addr = Utils.get_ipv4_address(interface) self.assertEqual(addr, "192.168.68.101") From f4199361d2243ed7a2b156ebad5d88ad2ad1c911 Mon Sep 17 00:00:00 2001 From: diohe Date: Wed, 31 May 2023 10:30:20 +0800 Subject: [PATCH 08/11] fix flake8 issue --- providers/base/bin/network_device_info.py | 1 + providers/base/tests/test_network_device_info.py | 0 2 files changed, 1 insertion(+) mode change 100644 => 100755 providers/base/tests/test_network_device_info.py diff --git a/providers/base/bin/network_device_info.py b/providers/base/bin/network_device_info.py index d802a2c52c..4588b43d98 100755 --- a/providers/base/bin/network_device_info.py +++ b/providers/base/bin/network_device_info.py @@ -308,6 +308,7 @@ def _collect_devices(self): def devices(self): """Convert to list of NetworkDevice with NM derived attrs set""" + import dbus for d in self._devices: bus = dbus.SystemBus() dev_proxy = bus.get_object("org.freedesktop.NetworkManager", d) diff --git a/providers/base/tests/test_network_device_info.py b/providers/base/tests/test_network_device_info.py old mode 100644 new mode 100755 From 51ab38d8ca8fc486fe6139d7f608058f375a4ab2 Mon Sep 17 00:00:00 2001 From: diohe Date: Thu, 1 Jun 2023 16:34:21 +0800 Subject: [PATCH 09/11] remove old comments --- providers/base/tests/test_network_device_info.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/providers/base/tests/test_network_device_info.py b/providers/base/tests/test_network_device_info.py index 8672d457cf..4f3b290511 100755 --- a/providers/base/tests/test_network_device_info.py +++ b/providers/base/tests/test_network_device_info.py @@ -24,11 +24,9 @@ class GetIpv4AddressTests(unittest.TestCase): # There are 2 output we could get from fcntl.ioctl(): # 1. No WiFi connected # (It pulls out bytes data directly from kernel, so if the given SIOCGIFADDR doesn't exist, it raise a OSError) - # "None" # 2. Connected with WiFi # It will pulls out a 256 bytes data into buffer, then we get to parse the IP address - # "192.168.68.101" def test_get_ipv4_address_without_connection(self): test_input = b"" mock_ioctl = Mock(return_value=test_input) @@ -65,13 +63,10 @@ def test_get_ipv4_address_with_connection(self): class GetIpv6AddressTests(unittest.TestCase): # There are 3 output we could get, but only 2 cases will happen due to the way we command it # 1. No WiFi connected - # "" # 2. Connected with WiFi - # "2: wlo1 inet6 fe80::d9eb:3f93:c7b2:86ba/64 scope link noprefixroute \ valid_lft forever preferred_lft forever" # 3. Connected with WiFi, but we ask the wrong interface name (This would not happen in our case, because the name is given by NetworkManager) - # "Device "wlan0" does not exist." def test_get_ipv6_address_without_connection(self): test_input = "" mock_check_output = Mock(return_value=test_input) @@ -83,7 +78,7 @@ def test_get_ipv6_address_without_connection(self): def test_get_ipv6_address_with_connection(self): test_input = "2: wlo1 inet6 fe80::d9eb:3f93:c7b2:86ba/64 scope link noprefixroute \ valid_lft forever preferred_lft forever" mock_check_output = Mock(return_value=test_input) - with patch("network_device_info.check_output", mock_check_output): # somehow it don't regonize check_output() if I don't put subprocess in front + with patch("network_device_info.check_output", mock_check_output): interface = "wlo1" addr = Utils.get_ipv6_address(interface) self.assertEqual(addr, "fe80::d9eb:3f93:c7b2:86ba/64") From 6921403b0b1ce76f488da66a4e9df0d93ad53088 Mon Sep 17 00:00:00 2001 From: diohe Date: Thu, 1 Jun 2023 18:16:30 +0800 Subject: [PATCH 10/11] modify the error msg --- providers/base/bin/network_device_info.py | 23 ++++++++++--------- .../base/tests/test_network_device_info.py | 19 ++++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/providers/base/bin/network_device_info.py b/providers/base/bin/network_device_info.py index 4588b43d98..1b0debd4ec 100755 --- a/providers/base/bin/network_device_info.py +++ b/providers/base/bin/network_device_info.py @@ -80,14 +80,14 @@ def is_iface_connected(cls, iface): def get_ipv4_address(interface): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: - ipv4_addr = socket.inet_ntoa(fcntl.ioctl( - s.fileno(), - 0x8915, # SIOCGIFADDR - struct.pack('256s', interface[:15].encode()) - )[20:24]) - except Exception as e: - print("ERROR: getting the IPv4 address for %s: %s" % - (interface, repr(e))) + + buffer = struct.pack('256s', interface[:15].encode()) + # retrieve the IP address associated with a network interface. + data = fcntl.ioctl(s.fileno(), 0x8915, buffer) + ipv4_addr = socket.inet_ntoa(data[20:24]) + except OSError: + print("OSError: failed to get the IPv4 address for %s" % + interface, file=sys.stderr) ipv4_addr = "***NOT CONFIGURED***" finally: return ipv4_addr @@ -98,10 +98,11 @@ def get_ipv6_address(interface): 'scope', 'link'] proc = check_output(cmd, universal_newlines=True) try: + # if it failed at split(), it means there is no output from cmd. ipv6_addr = proc.split()[3].strip() - except Exception as e: - print("ERROR: getting the IPv6 address for %s: %s" % - (interface, repr(e))) + except IndexError: + print("IndexError: failed to get the IPv6 address for %s" % + interface, file=sys.stderr) ipv6_addr = "***NOT CONFIGURED***" return ipv6_addr diff --git a/providers/base/tests/test_network_device_info.py b/providers/base/tests/test_network_device_info.py index 4f3b290511..ad7fab1ee8 100755 --- a/providers/base/tests/test_network_device_info.py +++ b/providers/base/tests/test_network_device_info.py @@ -27,13 +27,12 @@ class GetIpv4AddressTests(unittest.TestCase): # 2. Connected with WiFi # It will pulls out a 256 bytes data into buffer, then we get to parse the IP address - def test_get_ipv4_address_without_connection(self): - test_input = b"" - mock_ioctl = Mock(return_value=test_input) - with patch("fcntl.ioctl", mock_ioctl): - interface = "wlo1" - addr = Utils.get_ipv4_address(interface) - self.assertEqual(addr, "***NOT CONFIGURED***") + @patch("fcntl.ioctl") + def test_get_ipv4_address_without_connection(self, mock_ioctl): + mock_ioctl.side_effect = OSError() + interface = "wlo1" + addr = Utils.get_ipv4_address(interface) + self.assertEqual(addr, "***NOT CONFIGURED***") def test_get_ipv4_address_with_connection(self): test_input = (b'wlo1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' @@ -53,7 +52,6 @@ def test_get_ipv4_address_with_connection(self): b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') - # test_input = b"I'm fake!!!" mock_inet_ntoa = Mock(return_value=test_input) with patch("fcntl.ioctl", mock_inet_ntoa): interface = "wlo1" @@ -61,12 +59,13 @@ def test_get_ipv4_address_with_connection(self): self.assertEqual(addr, "192.168.68.101") class GetIpv6AddressTests(unittest.TestCase): - # There are 3 output we could get, but only 2 cases will happen due to the way we command it + # There are 3 kind of output it could return, but only 2 will happen in this case. # 1. No WiFi connected # 2. Connected with WiFi - # 3. Connected with WiFi, but we ask the wrong interface name (This would not happen in our case, because the name is given by NetworkManager) + # 3. Connected with WiFi, but we ask the wrong interface name + # (This would not happen in our case, because the name is given by NetworkManager) def test_get_ipv6_address_without_connection(self): test_input = "" mock_check_output = Mock(return_value=test_input) From 55883431d3e42e5573f1b996ca7546656ff258c3 Mon Sep 17 00:00:00 2001 From: diohe Date: Fri, 2 Jun 2023 16:48:12 +0800 Subject: [PATCH 11/11] modify error msg display --- providers/base/bin/network_device_info.py | 14 +++++++------- providers/base/tests/test_network_device_info.py | 10 ++++++++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/providers/base/bin/network_device_info.py b/providers/base/bin/network_device_info.py index 1b0debd4ec..72be308454 100755 --- a/providers/base/bin/network_device_info.py +++ b/providers/base/bin/network_device_info.py @@ -85,9 +85,9 @@ def get_ipv4_address(interface): # retrieve the IP address associated with a network interface. data = fcntl.ioctl(s.fileno(), 0x8915, buffer) ipv4_addr = socket.inet_ntoa(data[20:24]) - except OSError: - print("OSError: failed to get the IPv4 address for %s" % - interface, file=sys.stderr) + except OSError as e: + print("OSError: failed to get the IPv4 address for %s: %s" % + (interface, repr(e)), file=sys.stderr) ipv4_addr = "***NOT CONFIGURED***" finally: return ipv4_addr @@ -98,11 +98,11 @@ def get_ipv6_address(interface): 'scope', 'link'] proc = check_output(cmd, universal_newlines=True) try: - # if it failed at split(), it means there is no output from cmd. + # If it failed at split(), it means there is no output from cmd. ipv6_addr = proc.split()[3].strip() - except IndexError: - print("IndexError: failed to get the IPv6 address for %s" % - interface, file=sys.stderr) + except IndexError as e: + print("IndexError: failed to get the IPv6 address for %s: %s" % + (interface, repr(e)), file=sys.stderr) ipv6_addr = "***NOT CONFIGURED***" return ipv6_addr diff --git a/providers/base/tests/test_network_device_info.py b/providers/base/tests/test_network_device_info.py index ad7fab1ee8..4d77df6e88 100755 --- a/providers/base/tests/test_network_device_info.py +++ b/providers/base/tests/test_network_device_info.py @@ -16,7 +16,9 @@ # along with this program. If not, see . import unittest +from io import StringIO from unittest.mock import Mock, patch +from contextlib import redirect_stderr from network_device_info import Utils @@ -31,7 +33,9 @@ class GetIpv4AddressTests(unittest.TestCase): def test_get_ipv4_address_without_connection(self, mock_ioctl): mock_ioctl.side_effect = OSError() interface = "wlo1" - addr = Utils.get_ipv4_address(interface) + with redirect_stderr(StringIO()) as stderr: + addr = Utils.get_ipv4_address(interface) + self.assertEqual(addr, "***NOT CONFIGURED***") def test_get_ipv4_address_with_connection(self): @@ -71,7 +75,9 @@ def test_get_ipv6_address_without_connection(self): mock_check_output = Mock(return_value=test_input) with patch("network_device_info.check_output", mock_check_output): interface = "wlo1" - addr = Utils.get_ipv6_address(interface) + with redirect_stderr(StringIO()) as stderr: + addr = Utils.get_ipv6_address(interface) + self.assertEqual(addr, "***NOT CONFIGURED***") def test_get_ipv6_address_with_connection(self):