Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Linux] Test failure due to broken handling of IPv6 [FAIL: psutil.tests.test_linux.TestSystemNetIfAddrs.test_ips] #1909

Closed
torsava opened this issue Jan 26, 2021 · 1 comment

Comments

@torsava
Copy link

torsava commented Jan 26, 2021

Summary

  • OS: Linux
  • Architecture: 64bit (x86_64)
  • Psutil version: 5.8.0
  • Python version: Python 3.9.1
  • Type: tests

Description

Test psutil.tests.test_linux.TestSystemNetIfAddrs.test_ips fails when an interface has multiple IPv6 addresses.

Test failure:

...
======================================================================
FAIL: psutil.tests.test_linux.TestSystemNetIfAddrs.test_ips
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/builddir/build/BUILD/psutil-release-5.8.0/psutil/tests/test_linux.py", line 947, in test_ips
    self.assertEqual(address, get_ipv6_address(name))
AssertionError: '2620:52:0:1330:d7b2:99a4:96ab:a55' != 'fe80::f1d4:c17e:7251:901b'
- 2620:52:0:1330:d7b2:99a4:96ab:a55
+ fe80::f1d4:c17e:7251:901b
----------------------------------------------------------------------
Ran 543 tests in 3.524s
FAILED (failures=1, skipped=182)

Test case:

   def test_ips(self):
        for name, addrs in psutil.net_if_addrs().items():
            for addr in addrs:
                if addr.family == psutil.AF_LINK:
                    self.assertEqual(addr.address, get_mac_address(name))
                elif addr.family == socket.AF_INET:
                    self.assertEqual(addr.address, get_ipv4_address(name))
                    self.assertEqual(addr.netmask, get_ipv4_netmask(name))
                    if addr.broadcast is not None:
                        self.assertEqual(addr.broadcast,
                                         get_ipv4_broadcast(name))
                    else:
                        self.assertEqual(get_ipv4_broadcast(name), '0.0.0.0')
                elif addr.family == socket.AF_INET6:
                    # IPv6 addresses can have a percent symbol at the end.
                    # E.g. these 2 are equivalent:
                    # "fe80::1ff:fe23:4567:890a"
                    # "fe80::1ff:fe23:4567:890a%eth0"
                    # That is the "zone id" portion, which usually is the name
                    # of the network interface.
                    address = addr.address.split('%')[0]
                    self.assertEqual(address, get_ipv6_address(name))

Current code of the get_ipv6_address function:

def get_ipv6_address(ifname):
    with open("/proc/net/if_inet6", 'rt') as f:
        for line in f.readlines():
            fields = line.split()
            if fields[-1] == ifname:
                break
        else:
            raise ValueError("could not find interface %r" % ifname)
    unformatted = fields[0]
    groups = []
    for i in range(0, len(unformatted), 4):
        groups.append(unformatted[i:i + 4])
    formatted = ":".join(groups)
    packed = socket.inet_pton(socket.AF_INET6, formatted)
    return socket.inet_ntop(socket.AF_INET6, packed)

The problem is caused because get_ipv6_address returns only the first IPv6 address for the given interface, and then the address is compared in self.assertEqual(address, get_ipv6_address(name)).

Instead, get_ipv6_address should return all IPv6 addresses for the given interface, and then the test should check whether address is among them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants