diff options
author | David Malcolm <dmalcolm@redhat.com> | 2013-02-05 15:58:28 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2013-02-05 15:58:28 -0500 |
commit | 40b4e12903d4fdf696e89d0cd52c3914a87464f8 (patch) | |
tree | 42e66fdfdff1bda515a260d4298f218598a6fcec | |
parent | 5f6339c432dc227e456b70c459cf6f57c6cfe7c2 (diff) | |
download | python-ethtool-40b4e12903d4fdf696e89d0cd52c3914a87464f8.tar.gz python-ethtool-40b4e12903d4fdf696e89d0cd52c3914a87464f8.tar.xz python-ethtool-40b4e12903d4fdf696e89d0cd52c3914a87464f8.zip |
add a test suite
This is based on a suite I wrote internally at Red Hat for python-ethtool,
later modified by Braňo Náter <bnater@redhat.com>.
-rw-r--r-- | Makefile | 29 | ||||
-rw-r--r-- | tests/__init__.py | 0 | ||||
-rw-r--r-- | tests/parse_ifconfig.py | 919 | ||||
-rwxr-xr-x | tests/test_ethtool.py | 251 |
4 files changed, 1199 insertions, 0 deletions
@@ -24,3 +24,32 @@ bz2dev: rpmdirs rpmdev: bz2dev rpmdirs rpmbuild -ba --define "_topdir $(PWD)/rpm" rpm/SPECS/$(PACKAGE).spec + + +build: + python setup.py build + +# Need to set PYTHONPATH appropriately when invoking this +test: + python tests/parse_ifconfig.py -v + python -m unittest discover -v + valgrind --leak-check=full python tests/test_ethtool.py + +# As of 5f6339c432dc227e456b70c459cf6f57c6cfe7c2 I (dmalcolm) hope to have +# fixed the memory leaks within python-ethtool itself, but I expect +# to see a few blocks lost within libnl which appear to be caches, +# and thus (presumably) false positives: +# ==9163== 4,600 (80 direct, 4,520 indirect) bytes in 2 blocks are definitely lost in loss record 2,559 of 2,612 +# ==9163== at 0x4C26F18: calloc (vg_replace_malloc.c:566) +# ==9163== by 0x1152C307: nl_cache_alloc (in /usr/lib64/libnl.so.1.1) +# ==9163== by 0x115309FC: rtnl_link_alloc_cache (in /usr/lib64/libnl.so.1.1) +# ==9163== by 0x1130C843: get_etherinfo (etherinfo.c:315) +# ==9163== by 0x1130CFD0: _ethtool_etherinfo_getter (etherinfo_obj.c:152) +# ==9163== by 0x4F07E90: PyEval_EvalFrameEx (ceval.c:2330) +# ...etc... +# ==9163== LEAK SUMMARY: +# ==9163== definitely lost: 160 bytes in 4 blocks +# ==9163== indirectly lost: 9,040 bytes in 60 blocks +# ==9163== possibly lost: 489,676 bytes in 3,299 blocks +# ==9163== still reachable: 1,277,848 bytes in 11,100 blocks +# ==9163== suppressed: 0 bytes in 0 blocks diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/__init__.py diff --git a/tests/parse_ifconfig.py b/tests/parse_ifconfig.py new file mode 100644 index 0000000..a8835ea --- /dev/null +++ b/tests/parse_ifconfig.py @@ -0,0 +1,919 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2012 Red Hat, Inc. All rights reserved. +# +# This copyrighted material is made available to anyone wishing +# to use, modify, copy, or redistribute it subject to the terms +# and conditions of the GNU General Public License version 2. +# +# 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, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# Author: Dave Malcolm <dmalcolm@redhat.com> +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Screenscraper for the output of "ifconfig" +# The relevant sources for ifconfig can be found in e.g.: +# net-tools-1.60/lib/interface.c +# within ife_print_long() + +import re +from subprocess import Popen, PIPE +import unittest + +__all__ = ['IfConfig'] + +# any whitespace: +ws = '\s+' + +# any non-whitespace, as a delimited group: +group_nonws = '(\S+)' + +# a decimal number, as a delimited group: +group_dec = '([0-9]+)' + +# hexadecimal number of the form "0xf2600000" +group_o_hex = '0x([0-9a-f]+)' + +# hexadecimal number without the "0x" prefix, e.g. "f2600000" +group_hex = '([0-9a-f]+)' + +dot = r'\.' + +dec = '[0-9]+' + +group_ip4addr = ('(' + dec + dot + + dec + dot + + dec + dot + + dec + ')') + +def parse_ip4addr(addr): + import socket + return (socket.inet_aton(addr)) + +class IfConfig: + """ + Wrapper around a single invocation of "ifconfig" + """ + def __init__(self, stdout=None, debug=False): + if stdout is not None: + self.stdout = stdout + self.stderr = '' + else: + p = Popen('ifconfig', stdout=PIPE, stderr=PIPE) + self.stdout, self.stderr = p.communicate() + if self.stderr != '': + raise ValueError('stderr from ifconfig was nonempty:\n%s' % self.stderr) + if 0: + print('self.stdout: %r' % self.stdout) + self.devices = [] + curdev = None + for line in self.stdout.splitlines(): + if 0: + print('line: %r' % line) + + if line == '': + continue + + # Start of a device entry, e.g: + # 'lo: flags=73<UP,LOOPBACK,RUNNING> mtu 16436' + # old ifconfig format: + # 'lo Link encap:Local Loopback' + m = re.match(r'(\w+): (.+)', line) + mo = re.match(r'(\w+)\s+(.+)', line) + if m: + self.oldFormat = False + devname = m.group(1) + curdev = Device(devname, debug) + self.devices.append(curdev) + curdev._parse_rest_of_first_line(m.group(2)) + continue + + if mo: + self.oldFormat = True + devname = mo.group(1) + curdev = Device(devname, debug) + self.devices.append(curdev) + curdev._parse_rest_of_first_line_old(mo.group(2)) + continue + + if self.oldFormat: + curdev._parse_line_old(line) + else: + curdev._parse_line(line) + + def get_device_by_name(self, devname): + for dev in self.devices: + if dev.name == devname: + return dev + raise ValueError('device not found: %r' % devname) + +class Device: + """ + Wrapper around a device entry within the output of "ifconfig" + """ + def __init__(self, name, debug=False): + self.name = name + self.debug = debug + + self.flagsint = None + self.flagsstr = None + self.mtu = None + self.metric = None + self.outfill = None + self.keepalive = None + + self.inet = None + self.netmask = None + self.broadcast = None + self.destination = None + + self.inet6 = None + self.prefixlen = None + self.scopeid = None + + self.hwname = None + self.hwaddr = None + self.txqueuelen = None + self.hwtitle = None + + self.rxpackets = None + self.rxbytes = None + + self.rxerrors = None + self.rxdropped = None + self.rxoverruns = None + self.rxframe = None + + self.rxcompressed = None + + self.txpackets = None + self.txbytes = None + + self.txerrors = None + self.txdropped = None + self.txoverruns = None + self.txcarrier = None + self.txcollisions = None + + self.txcompressed = None + + self.interrupt = None + self.baseaddr = None + self.memstart = None + self.memend = None + self.dma = None + + def get_netmask_bits(self): + # Convert a dotted netmask string to a bitcount int + # e.g. from "255.255.252.0" to 22: + packed = parse_ip4addr(self.netmask) + # count bits in "packed": + result = 0 + for ch in packed: + ch = ord(ch) + while ch: + if ch & 1: + result += 1 + ch /= 2 + return result + + def __repr__(self): + return ('Device(name=%(name)r, flagsint=%(flagsint)r, flagsstr=%(flagsstr)r, mtu=%(mtu)r)' + % (self.__dict__)) + + def _debug(self, groups): + if self.debug: + print('groups: %r' % (groups,)) + + def _parse_rest_of_first_line(self, text): + m = re.match(r'flags=([0-9]+)<(.*)> mtu ([0-9]+)(.*)', text) + if not m: + raise ValueError('unable to parse: %r'% text) + self._debug(m.groups()) + self.flagsint = int(m.group(1)) + self.flagsstr = m.group(2) + self.mtu = int(m.group(3)) + + # It might have " outfill %d keepalive %d": + m = re.match(ws + + 'outfill' + ws + group_dec + ws + + 'keepalive' + ws + group_dec, + m.group(4)) + if m: + self._debug(m.groups()) + self.outfill = int(m.group(1)) + self.keepalive = int(m.group(2)) + + def _parse_rest_of_first_line_old(self, text): + m = re.match('Link encap:(\w+ ?\w*)\s*(HWaddr )?(\S*)', text) + if not m: + raise ValueError('unable to parse: %r'% text) + self.hwtitle = m.group(1).strip() + if m.group(2): + self.hwaddr = m.group(3) + + def _parse_line(self, line): + m = re.match(ws + + 'inet ' + group_ip4addr + ws + + 'netmask ' + group_ip4addr + '(.*)', + line) + if m: + self._debug(m.groups()) + self.inet = m.group(1) + self.netmask = m.group(2) + # "broadcast" and "destination" are both optional: + line = m.group(3) + m = re.match(ws + 'broadcast ' + group_ip4addr + '(.*)', line) + if m: + self.broadcast = m.group(1) + line = m.group(2) + + m = re.match(ws + 'destination ' + group_nonws, line) + if m: + self.destination = m.group(1) + return + + m = re.match(ws + + 'inet6 ' + group_nonws + ws + + 'prefixlen' + ws + group_dec + ws + + 'scopeid '+ group_nonws, + line) + if m: + self._debug(m.groups()) + self.inet6 = m.group(1) + self.prefixlen = int(m.group(2)) + self.scopeid = m.group(3) + return + + # e.g. (with hwaddr): + # ' ether ff:00:11:22:33:42 txqueuelen 1000 (Ethernet)' + m = re.match(ws + + group_nonws + ws + group_nonws + ws + + 'txqueuelen' + ws + group_dec + ws + + '\((.*)\)', line) + if m: + self._debug(m.groups()) + self.hwname = m.group(1) + self.hwaddr = m.group(2) + self.txqueuelen = int(m.group(3)) + self.hwtitle = m.group(4) + return + + # e.g. (without hwaddr): + # ' loop txqueuelen 0 (Local Loopback)' + m = re.match(ws + + group_nonws + ws + + 'txqueuelen' + ws + group_dec + ws + + '\((.*)\)', line) + if m: + self._debug(m.groups()) + self.hwname = m.group(1) + self.hwaddr = None + self.txqueuelen = int(m.group(2)) + self.hwtitle = m.group(3) + return + + # e.g. ' RX packets 5313261 bytes 6062336615 (5.6 GiB)' + m = re.match(ws + + 'RX packets ' + group_dec + ws + + 'bytes ' + group_dec + ws + + '\(.*\)', + line) + if m: + self._debug(m.groups()) + self.rxpackets = int(m.group(1)) + self.rxbytes = int(m.group(2)) + return + + # e.g. ' RX errors 0 dropped 0 overruns 0 frame 0' + m = re.match(ws + + 'RX errors ' + group_dec + ws + + 'dropped ' + group_dec + ws + + 'overruns ' + group_dec + ws + + 'frame ' + group_dec, + line) + if m: + self._debug(m.groups()) + self.rxerrors = int(m.group(1)) + self.rxdropped = int(m.group(2)) + self.rxoverruns = int(m.group(3)) + self.rxframe = int(m.group(4)) + return + + # e.g. ' TX packets 2949524 bytes 344092625 (328.1 MiB)' + m = re.match(ws + + 'TX packets '+ group_dec + ws + + 'bytes ' + group_dec + ws + + '\(.*\)', + line) + if m: + self._debug(m.groups()) + self.txpackets = int(m.group(1)) + self.txbytes = int(m.group(2)) + return + + # e.g. ' TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0' + m = re.match(ws + + 'TX errors ' + group_dec + ws + + 'dropped ' + group_dec + ws + + 'overruns ' + group_dec + ws + + 'carrier ' + group_dec + ws + + 'collisions ' + group_dec, + line) + if m: + self._debug(m.groups()) + self.txerrors = int(m.group(1)) + self.txdropped = int(m.group(2)) + self.txoverruns = int(m.group(3)) + self.txcarrier = int(m.group(4)) + self.txcollisions = int(m.group(5)) + return + + # e.g.' device interrupt 20 memory 0xf2600000-f2620000 ' + m = re.match(ws + + 'device' + ws + '(.*)', + line) + if m: + self._debug(m.groups()) + line = m.group(1) + m = re.match('interrupt ' + group_dec + ws + '(.*)', + line) + if m: + self.interrupt = int(m.group(1)) + line = m.group(2) + + m = re.match('base ' + group_o_hex + ws + '(.*)', + line) + if m: + self.baseaddr = int(m.group(1), 16) + line = m.group(2) + + m = re.match('memory ' + group_o_hex + '-' + group_hex + ws + '(.*)', + line) + if m: + self.memstart = int(m.group(1), 16) + self.memend = int(m.group(2), 16) + line = m.group(3) + + m = re.match('dma ' + group_o_hex, + line) + if m: + self.dma = int(m.group(1), 16) + + return + + raise ValueError('parser could not handle line: %r' % line) + + def _parse_line_old(self, line): + m = re.match(ws + + 'inet addr:' + group_ip4addr + + '(.*)', + line) + if m: + self._debug(m.groups()) + self.inet = m.group(1) + # "destination (P-t-P)" and "Bcast" are both optional: + line = m.group(2) + m = re.match(ws + 'P-t-P:' + group_ip4addr + '(.*)', line) + if m: + self.destination = m.group(1) + line = m.group(2) + + m = re.match(ws + 'Bcast:' + group_ip4addr + '(.*)', line) + if m: + self.broadcast = m.group(1) + line = m.group(2) + + m = re.match(ws + 'Mask:' + group_ip4addr, line) + if m: + self.netmask = m.group(1) + return + + m = re.match(ws + + 'inet6 addr: ' + group_nonws + '/' + + group_dec + ws + + 'Scope:'+ group_nonws, + line) + if m: + self._debug(m.groups()) + self.inet6 = m.group(1) + self.prefixlen = int(m.group(2)) + self.scopeid = m.group(3) + return + + #UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + m = re.match(ws + '(.*)' + + ' MTU:' + group_dec + ws + + 'Metric:' + group_dec + + '(.*)', line) + if m: + self._debug(m.groups()) + self.flagsstr = m.group(1) + self.mtu = int(m.group(2)) + self.metric = int(m.group(3)) + + # It might have " Outfill:%d Keepalive:%d": + m = re.match(ws + + 'Outfill:' + group_dec + ws + + 'Keepalive:'+ group_dec, + m.group(4)) + if m: + self._debug(m.groups()) + self.outfill = int(m.group(1)) + self.keepalive = int(m.group(2)) + return + + #RX packets:4458926 errors:0 dropped:0 overruns:0 frame:0 + m = re.match(ws + + 'RX packets:' + group_dec + ws + + 'errors:' + group_dec + ws + + 'dropped:' + group_dec + ws + + 'overruns:' + group_dec + ws + + 'frame:' + group_dec, + line) + if m: + self._debug(m.groups()) + self.rxpackets = int(m.group(1)) + self.rxerrors = int(m.group(2)) + self.rxdropped = int(m.group(3)) + self.rxoverruns = int(m.group(4)) + self.rxframe = int(m.group(5)) + return + + #" compressed:%lu\n" + m = re.match(ws + 'compressed:' + group_dec, line) + if m: + self.rxcompressed = int(m.group(1)) + return + + #TX packets:3536982 errors:0 dropped:0 overruns:0 carrier:0 + m = re.match(ws + + 'TX packets:' + group_dec + ws + + 'errors:' + group_dec + ws + + 'dropped:' + group_dec + ws + + 'overruns:' + group_dec + ws + + 'carrier:' + group_dec, + line) + if m: + self._debug(m.groups()) + self.txpackets = int(m.group(1)) + self.txerrors = int(m.group(2)) + self.txdropped = int(m.group(3)) + self.txoverruns = int(m.group(4)) + self.txcarrier = int(m.group(5)) + return + + #" collisions:%lu compressed:%lu txqueuelen:%d " + m = re.match(ws + 'collisions:' + group_dec + ws + '(.*)', line) + if m: + self._debug(m.groups()) + self.txcollisions = int(m.group(1)) + line = m.group(2) + m = re.match('compressed:' + group_dec + ws + '(.*)', line) + if m: + self.txcompressed = int(m.group(1)) + line = m.group(2) + + m = re.match('txqueuelen:' + group_dec, line) + if m: + self.txqueuelen = int(m.group(1)) + return + + #RX bytes:3380060233 (3.1 GiB) TX bytes:713438255 (680.3 MiB) + m = re.match(ws + 'RX bytes:' + group_dec + ws + '\(.*\)' + ws + + 'TX bytes:' + group_dec + ws + '\(.*\)', + line) + if m: + self._debug(m.groups()) + self.rxbytes = int(m.group(1)) + self.txbytes = int(m.group(2)) + return + + #Interrupt:17 Memory:da000000-da012800 + m = re.match(ws + 'Interrupt:' + group_dec + '\s*(.*)', line) + if m: + self._debug(m.groups()) + self.interrupt = int(m.group(1)) + line = m.group(2) + + m = re.match('Base address:' + group_o_hex + '\s*(.*)', line) + if m: + self._debug(m.groups()) + self.baseaddr = int(m.group(1), 16) + line = m.group(2) + + m = re.match('Memory:' + group_hex + '-' + group_hex + '\s*(.*)', line) + if m: + self._debug(m.groups()) + self.memstart = int(m.group(1), 16) + self.memend = int(m.group(2), 16) + line = m.group(3) + + m = re.match('DMA chan:' + group_hex, line) + if m: + self._debug(m.groups()) + self.dma = int(m.group(1), 16) + + return + + raise ValueError('parser could not handle line: %r' % line) + +#ifconfig = IfConfig() +#for dev in ifconfig.devices: +# print(dev) + +class ParserTests(unittest.TestCase): + def test_full(self): + # Parse a complex pre-canned output from ifconfig + # This is the output of "ifconfig" on this machine, sanitized + # to remove stuff that identifies it + full = ''' +eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 + inet 1.12.123.124 netmask 255.255.252.0 broadcast 1.12.123.255 + inet6 ffff::ffff:ffff:ffff:ffff prefixlen 64 scopeid 0x20<link> + ether ff:00:11:22:33:42 txqueuelen 1000 (Ethernet) + RX packets 5329294 bytes 6074440831 (5.6 GiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 2955574 bytes 344607935 (328.6 MiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +''' + ' device interrupt 20 memory 0xf2600000-f2620000 ' + ''' + +lo: flags=73<UP,LOOPBACK,RUNNING> mtu 16436 + inet 127.0.0.1 netmask 255.0.0.0 + inet6 ::1 prefixlen 128 scopeid 0x10<host> + loop txqueuelen 0 (Local Loopback) + RX packets 1562620 bytes 524530977 (500.2 MiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 1562620 bytes 524530977 (500.2 MiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +virbr0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 + inet 1.12.123.124 netmask 255.255.252.0 broadcast 1.12.123.255 + ether ff:00:11:22:33:42 txqueuelen 0 (Ethernet) + RX packets 88730 bytes 5140566 (4.9 MiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 177583 bytes 244647206 (233.3 MiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +vnet0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 + inet6 ffff::ffff:ffff:ffff:ffff prefixlen 64 scopeid 0x20<link> + ether ff:00:11:22:33:42 txqueuelen 0 (Ethernet) + RX packets 538 bytes 172743 (168.6 KiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 26593 bytes 1379054 (1.3 MiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +vnet1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 + inet6 ffff::ffff:ffff:ffff:ffff prefixlen 64 scopeid 0x20<link> + ether ff:00:11:22:33:42 txqueuelen 0 (Ethernet) + RX packets 71567 bytes 5033151 (4.7 MiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 216553 bytes 200424748 (191.1 MiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +''' + ifconfig = IfConfig(stdout=full) + self.assertEqual(len(ifconfig.devices), 5) + + # Verify eth1: + eth1 = ifconfig.devices[0] + # eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 + self.assertEqual(eth1.name, 'eth1') + self.assertEqual(eth1.flagsint, 4163) + self.assertEqual(eth1.flagsstr, 'UP,BROADCAST,RUNNING,MULTICAST') + self.assertEqual(eth1.mtu, 1500) + # inet 1.12.123.124 netmask 255.255.252.0 broadcast 1.12.123.255 + self.assertEqual(eth1.inet, '1.12.123.124') + self.assertEqual(eth1.netmask, '255.255.252.0') + self.assertEqual(eth1.broadcast, '1.12.123.255') + # inet6 ffff::ffff:ffff:ffff:ffff prefixlen 64 scopeid 0x20<link> + self.assertEqual(eth1.inet6, 'ffff::ffff:ffff:ffff:ffff') + self.assertEqual(eth1.prefixlen, 64) + self.assertEqual(eth1.scopeid, '0x20<link>') + # ether ff:00:11:22:33:42 txqueuelen 1000 (Ethernet) + self.assertEqual(eth1.hwname, 'ether') + self.assertEqual(eth1.hwaddr, 'ff:00:11:22:33:42') + self.assertEqual(eth1.txqueuelen, 1000) + self.assertEqual(eth1.hwtitle, 'Ethernet') + # RX packets 5329294 bytes 6074440831 (5.6 GiB) + self.assertEqual(eth1.rxpackets, 5329294) + self.assertEqual(eth1.rxbytes, 6074440831) + # RX errors 0 dropped 0 overruns 0 frame 0 + self.assertEqual(eth1.rxerrors, 0) + self.assertEqual(eth1.rxdropped, 0) + self.assertEqual(eth1.rxoverruns, 0) + self.assertEqual(eth1.rxframe, 0) + # TX packets 2955574 bytes 344607935 (328.6 MiB) + self.assertEqual(eth1.txpackets, 2955574) + self.assertEqual(eth1.txbytes, 344607935) + # TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + self.assertEqual(eth1.txerrors, 0) + self.assertEqual(eth1.txdropped, 0) + self.assertEqual(eth1.txoverruns, 0) + self.assertEqual(eth1.txcarrier, 0) + self.assertEqual(eth1.txcollisions, 0) + # device interrupt 20 memory 0xf2600000-f2620000 + self.assertEqual(eth1.interrupt, 20) + + # Verify lo: + lo = ifconfig.devices[1] + self.assertEqual(lo.name, 'lo') + # lo: flags=73<UP,LOOPBACK,RUNNING> mtu 16436 + self.assertEqual(lo.flagsint, 73) + self.assertEqual(lo.flagsstr, 'UP,LOOPBACK,RUNNING') + self.assertEqual(lo.mtu, 16436) + # inet 127.0.0.1 netmask 255.0.0.0 + self.assertEqual(lo.inet, '127.0.0.1') + self.assertEqual(lo.netmask, '255.0.0.0') + self.assertEqual(lo.broadcast, None) + # inet6 ::1 prefixlen 128 scopeid 0x10<host> + self.assertEqual(lo.inet6, '::1') + self.assertEqual(lo.prefixlen, 128) + self.assertEqual(lo.scopeid, '0x10<host>') + # loop txqueuelen 0 (Local Loopback) + self.assertEqual(lo.hwname, 'loop') + self.assertEqual(lo.txqueuelen, 0) + self.assertEqual(lo.hwtitle, 'Local Loopback') + # RX packets 1562620 bytes 524530977 (500.2 MiB) + # RX errors 0 dropped 0 overruns 0 frame 0 + # TX packets 1562620 bytes 524530977 (500.2 MiB) + # TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + + # Verify virbr0: + virbr0 = ifconfig.devices[2] + self.assertEqual(virbr0.name, 'virbr0') + # virbr0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 + # inet 1.12.123.124 netmask 255.255.252.0 broadcast 1.12.123.255 + # ether ff:00:11:22:33:42 txqueuelen 0 (Ethernet) + # RX packets 88730 bytes 5140566 (4.9 MiB) + # RX errors 0 dropped 0 overruns 0 frame 0 + # TX packets 177583 bytes 244647206 (233.3 MiB) + # TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + + # Verify vnet0: + vnet0 = ifconfig.devices[3] + self.assertEqual(vnet0.name, 'vnet0') + # vnet0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 + # inet6 ffff::ffff:ffff:ffff:ffff prefixlen 64 scopeid 0x20<link> + # ether ff:00:11:22:33:42 txqueuelen 0 (Ethernet) + # RX packets 538 bytes 172743 (168.6 KiB) + # RX errors 0 dropped 0 overruns 0 frame 0 + # TX packets 26593 bytes 1379054 (1.3 MiB) + # TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + + # Verify vnet1: + vnet1 = ifconfig.devices[4] + self.assertEqual(vnet1.name, 'vnet1') + # vnet1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 + # inet6 ffff::ffff:ffff:ffff:ffff prefixlen 64 scopeid 0x20<link> + # ether ff:00:11:22:33:42 txqueuelen 0 (Ethernet) + # RX packets 71567 bytes 5033151 (4.7 MiB) + # RX errors 0 dropped 0 overruns 0 frame 0 + # TX packets 216553 bytes 200424748 (191.1 MiB) + # TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + + fullOld = ''' +eth0 Link encap:Ethernet HWaddr 00:11:22:33:44:55 + inet addr:1.12.123.124 Bcast:1.12.123.255 Mask:255.255.252.0 + inet6 addr: dddd::dddd:dddd:dddd:dddd:dddd:dddd/64 Scope:Site + inet6 addr: eeee::eeee:eeee:eeee:eeee:eeee:eeee/64 Scope:Global + inet6 addr: ffff::ffff:ffff:ffff:ffff/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:4458926 errors:0 dropped:0 overruns:0 frame:0 + TX packets:3536982 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:3380060233 (3.1 GiB) TX bytes:713438255 (680.3 MiB) + Interrupt:17 Memory:da000000-da012800 + +lo Link encap:Local Loopback + inet addr:127.0.0.1 Mask:255.0.0.0 + inet6 addr: ::1/128 Scope:Host + UP LOOPBACK RUNNING MTU:16436 Metric:1 + RX packets:805234 errors:0 dropped:0 overruns:0 frame:0 + TX packets:805234 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:132177529 (126.0 MiB) TX bytes:132177529 (126.0 MiB) +''' + ifconfig = IfConfig(stdout=fullOld) + self.assertEqual(len(ifconfig.devices), 2) + + # Verify eth0: + eth0 = ifconfig.devices[0] + #eth0 Link encap:Ethernet HWaddr 00:11:22:33:44:55 + self.assertEqual(eth0.name, 'eth0') + self.assertEqual(eth0.hwtitle, 'Ethernet') + self.assertEqual(eth0.hwaddr, '00:11:22:33:44:55') + # inet addr:1.12.123.124 Bcast:1.12.123.255 Mask:255.255.252.0 + self.assertEqual(eth0.inet, '1.12.123.124') + self.assertEqual(eth0.netmask, '255.255.252.0') + self.assertEqual(eth0.broadcast, '1.12.123.255') + # inet6 addr: dddd::dddd:dddd:dddd:dddd:dddd:dddd/64 Scope:Site + #self.assertEqual(eth0.inet6, 'dddd::dddd:dddd:dddd:dddd:dddd:dddd') + #self.assertEqual(eth0.prefixlen, 64) + #self.assertEqual(eth0.scopeid, 'Site') + # inet6 addr: eeee::eeee:eeee:eeee:eeee:eeee:eeee/64 Scope:Global + #self.assertEqual(eth0.inet6, 'eeee::eeee:eeee:eeee:eeee:eeee:eeee') + #self.assertEqual(eth0.prefixlen, 64) + #self.assertEqual(eth0.scopeid, 'Global') + # inet6 addr: ffff::ffff:ffff:ffff:ffff/64 Scope:Link + self.assertEqual(eth0.inet6, 'ffff::ffff:ffff:ffff:ffff') + self.assertEqual(eth0.prefixlen, 64) + self.assertEqual(eth0.scopeid, 'Link') + # UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + self.assertEqual(eth0.flagsstr, 'UP BROADCAST RUNNING MULTICAST') + self.assertEqual(eth0.mtu, 1500) + self.assertEqual(eth0.metric, 1) + # RX packets:4458926 errors:0 dropped:0 overruns:0 frame:0 + self.assertEqual(eth0.rxpackets, 4458926) + self.assertEqual(eth0.rxerrors, 0) + self.assertEqual(eth0.rxdropped, 0) + self.assertEqual(eth0.rxoverruns, 0) + self.assertEqual(eth0.rxframe, 0) + # TX packets:3536982 errors:0 dropped:0 overruns:0 carrier:0 + self.assertEqual(eth0.txpackets, 3536982) + self.assertEqual(eth0.txerrors, 0) + self.assertEqual(eth0.txdropped, 0) + self.assertEqual(eth0.txoverruns, 0) + self.assertEqual(eth0.txcarrier, 0) + # collisions:0 txqueuelen:1000 + self.assertEqual(eth0.txcollisions, 0) + self.assertEqual(eth0.txqueuelen, 1000) + # RX bytes:3380060233 (3.1 GiB) TX bytes:713438255 (680.3 MiB) + self.assertEqual(eth0.rxbytes, 3380060233) + self.assertEqual(eth0.txbytes, 713438255) + # Interrupt:17 Memory:da000000-da012800 + self.assertEqual(eth0.interrupt, 17) + self.assertEqual(eth0.memstart, 0xda000000) + self.assertEqual(eth0.memend, 0xda012800) + + # Verify lo: + lo = ifconfig.devices[1] + #lo Link encap:Local Loopback + self.assertEqual(lo.name, 'lo') + self.assertEqual(lo.hwtitle, 'Local Loopback') + self.assertEqual(lo.hwaddr, None) + # inet addr:127.0.0.1 Mask:255.0.0.0 + self.assertEqual(lo.inet, '127.0.0.1') + self.assertEqual(lo.netmask, '255.0.0.0') + self.assertEqual(lo.broadcast, None) + # inet6 addr: ::1/128 Scope:Host + self.assertEqual(lo.inet6, '::1') + self.assertEqual(lo.prefixlen, 128) + self.assertEqual(lo.scopeid, 'Host') + # UP LOOPBACK RUNNING MTU:16436 Metric:1 + self.assertEqual(lo.flagsstr, 'UP LOOPBACK RUNNING') + self.assertEqual(lo.mtu, 16436) + self.assertEqual(lo.metric, 1) + # RX packets:805234 errors:0 dropped:0 overruns:0 frame:0 + self.assertEqual(lo.rxpackets, 805234) + # TX packets:805234 errors:0 dropped:0 overruns:0 carrier:0 + self.assertEqual(lo.txpackets, 805234) + # collisions:0 txqueuelen:0 + # RX bytes:132177529 (126.0 MiB) TX bytes:132177529 (126.0 MiB) + self.assertEqual(lo.rxbytes, 132177529) + self.assertEqual(lo.txbytes, 132177529) + + def parse_single_device(self, stdout, debug=False): + ifconfig = IfConfig(stdout, debug) + self.assertEqual(len(ifconfig.devices), 1) + return ifconfig.devices[0] + + def test_parsing_flags_line(self): + dev = self.parse_single_device( + 'foo: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n') + self.assertEqual(dev.name, 'foo') + self.assertEqual(dev.flagsint, 4163) + self.assertEqual(dev.flagsstr, 'UP,BROADCAST,RUNNING,MULTICAST') + self.assertEqual(dev.mtu, 1500) + + dev = self.parse_single_device( + 'foo: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 outfill 32 keepalive 96\n') + self.assertEqual(dev.mtu, 1500) + self.assertEqual(dev.outfill, 32) + self.assertEqual(dev.keepalive, 96) + + # old format + dev = self.parse_single_device( + 'foo Link encap:Ethernet HWaddr F0:F0:F0:F0:F0:F0\n' + ' UP BROADCAST RUNNING MULTICAST MTU:500 Metric:2 Outfill:55 Keepalive:66\n') + self.assertEqual(dev.flagsstr, 'UP BROADCAST RUNNING MULTICAST') + self.assertEqual(dev.mtu, 500) + self.assertEqual(dev.metric, 2) + self.assertEqual(dev.outfill, 55) + self.assertEqual(dev.keepalive, 66) + + def test_parsing_ip(self): + dev = self.parse_single_device( + 'foo: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n' + ' inet 1.12.123.124 netmask 255.255.252.0 broadcast 1.12.123.255\n') + self.assertEqual(dev.inet, '1.12.123.124') + self.assertEqual(dev.netmask, '255.255.252.0') + self.assertEqual(dev.get_netmask_bits(), 22) + self.assertEqual(dev.broadcast, '1.12.123.255') + self.assertEqual(dev.destination, None) + + dev = self.parse_single_device( + 'lo: flags=73<UP,LOOPBACK,RUNNING> mtu 16436\n' + ' inet 127.0.0.1 netmask 255.0.0.0\n') + self.assertEqual(dev.inet, '127.0.0.1') + self.assertEqual(dev.netmask, '255.0.0.0') + self.assertEqual(dev.get_netmask_bits(), 8) + + self.assertEqual(dev.broadcast, None) + self.assertEqual(dev.destination, None) + + dev = self.parse_single_device( + 'foo: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n' + ' inet 1.1.1.1 netmask 255.255.255.254 destination 1.12.123.255\n') + self.assertEqual(dev.inet, '1.1.1.1') + self.assertEqual(dev.netmask, '255.255.255.254') + self.assertEqual(dev.broadcast, None) + self.assertEqual(dev.destination, '1.12.123.255') + + # old format + dev = self.parse_single_device( + 'foo Link encap:Ethernet HWaddr F0:F0:F0:F0:F0:F0\n' + ' inet addr:1.2.3.4 P-t-P:10.20.30.40 Mask:255.255.254.0\n') + self.assertEqual(dev.inet, '1.2.3.4') + self.assertEqual(dev.destination, '10.20.30.40') + self.assertEqual(dev.broadcast, None) + self.assertEqual(dev.get_netmask_bits(), 23) + self.assertEqual(dev.netmask, '255.255.254.0') + + def test_parsing_device_line(self): + dev = self.parse_single_device( + 'foo: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n' + ' device interrupt 20 memory 0xf2600000-f2620000 \n') + self.assertEqual(dev.interrupt, 20) + self.assertEqual(dev.baseaddr, None) + self.assertEqual(dev.memstart, 0xf2600000) + self.assertEqual(dev.memend, 0xf2620000) + self.assertEqual(dev.dma, None) + + # but the fields in the "device" field are optional: + dev = self.parse_single_device( + 'foo: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n' + ' device \n') + self.assertEqual(dev.interrupt, None) + self.assertEqual(dev.baseaddr, None) + self.assertEqual(dev.memstart, None) + self.assertEqual(dev.memend, None) + self.assertEqual(dev.dma, None) + + dev = self.parse_single_device( + 'foo: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n' + ' device memory 0xf2600000-f2620000 \n') + self.assertEqual(dev.interrupt, None) + self.assertEqual(dev.baseaddr, None) + self.assertEqual(dev.memstart, 0xf2600000) + self.assertEqual(dev.memend, 0xf2620000) + self.assertEqual(dev.dma, None) + + # and there could potentially be "base" and "dma" fields: + dev = self.parse_single_device( + 'foo: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n' + ' device base 0xdeadbeef \n') + self.assertEqual(dev.interrupt, None) + self.assertEqual(dev.baseaddr, 0xdeadbeef) + self.assertEqual(dev.memstart, None) + self.assertEqual(dev.memend, None) + self.assertEqual(dev.dma, None) + + dev = self.parse_single_device( + 'foo: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n' + ' device interrupt 20 dma 0xbad4f00d\n') + self.assertEqual(dev.interrupt, 20) + self.assertEqual(dev.baseaddr, None) + self.assertEqual(dev.memstart, None) + self.assertEqual(dev.memend, None) + self.assertEqual(dev.dma, 0xbad4f00d) + + # old format + dev = self.parse_single_device( + 'foo Link encap:Ethernet HWaddr F0:F0:F0:F0:F0:F0\n' + ' Interrupt:20 Base address:0xdeadbeef DMA chan:bad4f00d\n' + ' collisions:13 compressed:11 \n') + self.assertEqual(dev.interrupt, 20) + self.assertEqual(dev.baseaddr, 0xdeadbeef) + self.assertEqual(dev.dma, 0xbad4f00d) + self.assertEqual(dev.txcollisions, 13) + self.assertEqual(dev.txcompressed, 11) + + def test_parse_ip4addr(self): + self.assertEqual(parse_ip4addr('1.1.1.1'), '\x01\x01\x01\x01') + self.assertEqual(parse_ip4addr('127.0.0.1'), '\x7f\x00\x00\x01') + + def test_local(self): + # Actually invoke ifconfig locally, and parse whatever it emits: + ifconfig = IfConfig() + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_ethtool.py b/tests/test_ethtool.py new file mode 100755 index 0000000..32b6b36 --- /dev/null +++ b/tests/test_ethtool.py @@ -0,0 +1,251 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2011, 2012, 2013 Red Hat, Inc. All rights reserved. +# +# This copyrighted material is made available to anyone wishing +# to use, modify, copy, or redistribute it subject to the terms +# and conditions of the GNU General Public License version 2. +# +# 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, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# +# Author: Dave Malcolm <dmalcolm@redhat.com> +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import sys +import unittest +from test.test_support import run_unittest # requires python-test subpackage on Fedora/RHEL + +import ethtool + +from parse_ifconfig import IfConfig + +INVALID_DEVICE_NAME = "I am not a valid device name" + +# Screenscrape the output from "ifconfig". We will use this below to validate +# the results from the "ethtool" module: +ifconfig = IfConfig() +for dev in ifconfig.devices: + print(dev) + +class EthtoolTests(unittest.TestCase): + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # asserts + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + def assertIsString(self, value): + self.assert_(isinstance(value, str)) + + def assertIsStringOrNone(self, value): + if value is not None: + self.assert_(isinstance(value, str)) + + def assertIsInt(self, value): + self.assert_(isinstance(value, int)) + + def assertRaisesIOError(self, fn, args, errmsg): + """ + Verify that an IOError is raised, and that the errno and message are + as expected + + (Python 2.6 and earlier's assertRaises doesn't allow us to check the + details of the exception that is raised) + """ + try: + fn(*args) + except IOError, e: + # Check the details of the exception: + self.assertEquals(e.args, (errmsg, )) + else: + self.fail('IOError was not raised calling %s on %s' % (fn, args)) + + def assertRaisesNoSuchDevice(self, fn, *args): + self.assertRaisesIOError(fn, args, '[Errno 19] No such device') + + def assertIsStringExceptForLoopback(self, fn, devname, errmsg): + if devname == 'lo': + self.assertRaisesIOError(fn, (devname, ), errmsg) + else: + self.assertIsString(fn(devname)) + + def assertEqualIpv4Str(self, ethtooladdr, scrapedaddr): + if scrapedaddr is None: + self.assertEqual(ethtooladdr, '0.0.0.0') + else: + self.assertEqual(ethtooladdr, scrapedaddr) + + def assertEqualHwAddr(self, ethtooladdr, scrapedaddr): + if scrapedaddr is None: + self.assertEqual(ethtooladdr, '00:00:00:00:00:00') + else: + self.assertEqual(ethtooladdr, scrapedaddr.lower()) + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # helpers + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + def _functions_accepting_devnames(self, devname): + self.assertIsString(devname) + + scraped = ifconfig.get_device_by_name(devname) + + self.assertIsString(ethtool.get_broadcast(devname)) + self.assertEqualIpv4Str(ethtool.get_broadcast(devname), + scraped.broadcast) + + self.assertIsStringExceptForLoopback(ethtool.get_businfo, devname, + '[Errno 95] Operation not supported') + + # ethtool.get_coalesce(devname) + # this gives me: + # IOError: [Errno 95] Operation not supported + # on my test box + + self.assertIsInt(ethtool.get_flags(devname)) + # flagsint cannot be obtained from old ifconfig format + if not ifconfig.oldFormat: + self.assertEqual(ethtool.get_flags(devname), scraped.flagsint) + self.assertIsInt(ethtool.get_gso(devname)) + + self.assertIsString(ethtool.get_hwaddr(devname)) + self.assertEqualHwAddr(ethtool.get_hwaddr(devname), + scraped.hwaddr) + self.assertIsString(ethtool.get_ipaddr(devname)) + self.assertEqual(ethtool.get_ipaddr(devname), scraped.inet) + + self.assertIsStringExceptForLoopback(ethtool.get_module, devname, + '[Errno 95] Operation not supported') + + self.assertIsString(ethtool.get_netmask(devname)) + self.assertEqual(ethtool.get_netmask(devname), + scraped.netmask) + + #self.assertRaisesIOError(ethtool.get_ringparam, (devname, ), + # '[Errno 95] Operation not supported') + + # Disabling until BZ#703089 is investigated + #self.assertIsInt(ethtool.get_sg(devname)) + #self.assertIsInt(ethtool.get_ufo(devname)) + + self.assertIsInt(ethtool.get_tso(devname)) + + + #TODO: self.assertIsString(ethtool.set_coalesce(devname)) + + #TODO: self.assertIsString(ethtool.set_ringparam(devname)) + + #TODO: self.assertIsString(ethtool.set_tso(devname)) + + def _verify_etherinfo_object(self, ei): + self.assert_(isinstance(ei, ethtool.etherinfo)) + self.assertIsString(ei.device) + + try: + scraped = ifconfig.get_device_by_name(ei.device) + except ValueError: + scraped = None + + self.assertIsStringOrNone(ei.ipv4_address) + if scraped: + self.assertEqual(ei.ipv4_address, scraped.inet) + + self.assertIsStringOrNone(ei.ipv4_broadcast) + if scraped: + self.assertEqual(ei.ipv4_broadcast, scraped.broadcast) + + self.assertIsInt(ei.ipv4_netmask) + if scraped: + self.assertEqual(ei.ipv4_netmask, scraped.get_netmask_bits()) + + self.assertIsStringOrNone(ei.mac_address) + if scraped: + if scraped.hwaddr: + scraped.hwaddr = scraped.hwaddr.lower() + self.assertEqualHwAddr(ei.mac_address.lower(), scraped.hwaddr) + + i6s = ei.get_ipv6_addresses() + for i6 in i6s: + self.assert_(isinstance(i6, ethtool.etherinfo_ipv6addr)) + self.assertIsString(i6.address) + self.assertIsInt(i6.netmask) + self.assertIsString(i6.scope) + self.assertEquals(str(i6), + '[%s] %s/%i' % (i6.scope, + i6.address, + i6.netmask)) + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + # tests + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + def test_invalid_devices(self): + # Verify sane handling of non-existant devices + + get_fns = ('get_broadcast', 'get_businfo', 'get_coalesce', 'get_flags', + 'get_gso', 'get_hwaddr', 'get_ipaddr', 'get_module', + 'get_netmask', 'get_ringparam', 'get_sg', 'get_tso', + 'get_ufo') + for fnname in get_fns: + self.assertRaisesNoSuchDevice(getattr(ethtool, fnname), + INVALID_DEVICE_NAME) + + set_fns = ('set_coalesce', 'set_ringparam', 'set_tso') + for fnname in set_fns: + # Currently this fails, with an IOError from + # ethtool.c:__struct_desc_from_dict + # with message: + # 'Missing dict entry for field rx_coalesce_usecs' + if False: + self.assertRaisesNoSuchDevice(getattr(ethtool, fnname), + INVALID_DEVICE_NAME, 42) + + + def test_get_interface_info_invalid(self): + eis = ethtool.get_interfaces_info(INVALID_DEVICE_NAME) + self.assertEquals(len(eis), 1) + ei = eis[0] + self.assertEquals(ei.device, INVALID_DEVICE_NAME) + self.assertEquals(ei.ipv4_address, None) + self.assertEquals(ei.ipv4_broadcast, None) + self.assertEquals(ei.ipv4_netmask, 0) + self.assertEquals(ei.mac_address, None) + + def test_get_interface_info_active(self): + eis = ethtool.get_interfaces_info(ethtool.get_active_devices()) + for ei in eis: + self._verify_etherinfo_object(ei) + + def test_get_interface_info_all(self): + eis = ethtool.get_interfaces_info(ethtool.get_devices()) + for ei in eis: + self._verify_etherinfo_object(ei) + + def test_get_active_devices(self): + for devname in ethtool.get_active_devices(): + self._functions_accepting_devnames(devname) + + def test_etherinfo_objects(self): + devnames = ethtool.get_devices() + eis = ethtool.get_interfaces_info(devnames) + for ei in eis: + self._verify_etherinfo_object(ei) + + +if __name__ == '__main__': + try: + # if count provided do a soak test, to detect leaking resources + count = int(sys.argv[1]) + for i in range(count): + run_unittest(EthtoolTests) + if i % (count / 10) == 0: + sys.stderr.write("%s %%\n" % (i * 100 / count)) + except: + run_unittest(EthtoolTests) |