diff options
author | Peter Wu <peter@lekensteyn.nl> | 2019-01-22 19:01:44 +0100 |
---|---|---|
committer | Peter Wu <peter@lekensteyn.nl> | 2019-01-24 00:26:17 +0000 |
commit | 8c698ffc99375e67809fb376d5090fcc2d535048 (patch) | |
tree | 2c8978cbf5784b6fc1b7c343d146ff963de39742 /test | |
parent | e35139533912890217259cf5dbec8d7388733f1a (diff) |
Test: enable capture tests by default using the Loopback interface
Avoid pinging www.wireshark.org, this removes an external dependency.
Instead send small UDP datagrams to UDP port 9 (discard) every 50ms.
Enable this for all platforms (including macOS and Linux) by default.
On Windows the tests requires Npcap and will be skipped with WinPcap.
Remove the --capture-interface option since it is no longer needed.
Copy WSDG Wireshark Tests Quick Start to README.test and add a link.
Change-Id: Id4105a6b1e95407ebf69b871c785c68f9ae26368
Reviewed-on: https://code.wireshark.org/review/31677
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
Diffstat (limited to 'test')
-rw-r--r-- | test/README.test | 26 | ||||
-rw-r--r-- | test/conftest.py | 3 | ||||
-rw-r--r-- | test/fixtures_ws.py | 48 | ||||
-rw-r--r-- | test/suite_capture.py | 59 | ||||
-rwxr-xr-x | test/test.py | 1 |
5 files changed, 62 insertions, 75 deletions
diff --git a/test/README.test b/test/README.test index ef484348cc..535913eeb0 100644 --- a/test/README.test +++ b/test/README.test @@ -1,23 +1,13 @@ Wireshark Tests -The main testing script is `test.py`. It will attempt to test as much as -possible by default, including packet capture. This means that you will -probably either have to supply a capture interface (`--capture-interface -<interface>`) or disable capture tests (`--disable-capture`). You must -also build the test-programs target in order for the unittests suite to -pass. +The recommended steps to prepare for and to run tests: -To run all tests from CMake do the following: -- Pass `-DTEST_EXTRA_ARGS=--disable-capture` or - `-DTEST_EXTRA_ARGS=--capture-interface=<interface>` - as needed for your system. -- Build the “test” target or run ctest, e.g. `ctest --force-new-ctest-process -j 4 --verbose`. +* Install two Python packages, pytest: `pip install pytest pytest-xdist` +* Build programs (“wireshark”, “tshark”, etc.): `ninja` +* Build additional programs for the “unittests” suite: `ninja test-programs` +* Run tests in the build directory: `pytest` -To run all tests directly, run `test.py -p -/path/to/wireshark-build/run-directory <capture args>`. +Replace `ninja test-programs` by `make test-programs` as needed. -To see a list of all options, run `test.py -h` or `test.py --help`. - -To see a list of all tests, run `test.py -l`. - -See the “Wireshark Tests” chapter of the Developer's Guide for details. +See the “Wireshark Tests” chapter of the Developer's Guide for details: +https://www.wireshark.org/docs/wsdg_html_chunked/ChapterTests.html diff --git a/test/conftest.py b/test/conftest.py index 3b70e049c3..954195fdfb 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -15,9 +15,6 @@ def pytest_addoption(parser): parser.addoption('--disable-capture', action='store_true', help='Disable capture tests' ) - parser.addoption('--capture-interface', - help='Capture interface index or name.' - ) parser.addoption('--program-path', help='Path to Wireshark executables.') parser.addoption('--skip-missing-programs', help='Skip tests that lack programs from this list instead of failing' diff --git a/test/fixtures_ws.py b/test/fixtures_ws.py index ed656e0c2d..5b5d9b8061 100644 --- a/test/fixtures_ws.py +++ b/test/fixtures_ws.py @@ -8,7 +8,6 @@ # '''Fixtures that are specific to Wireshark.''' -import logging import os import re import subprocess @@ -24,31 +23,36 @@ import subprocesstest def capture_interface(request, cmd_dumpcap): ''' Name of capture interface. Tests will be skipped if dumpcap is not - available or if the capture interface is unknown. + available or no Loopback interface is available. ''' - iface = request.config.getoption('--capture-interface', default=None) disabled = request.config.getoption('--disable-capture', default=False) if disabled: fixtures.skip('Capture tests are disabled via --disable-capture') - if iface: - # If a non-empty interface is given, assume capturing is possible. + proc = subprocess.Popen((cmd_dumpcap, '-D'), stdout=subprocess.PIPE, + stderr=subprocess.PIPE, universal_newlines=True) + outs, errs = proc.communicate() + if proc.returncode != 0: + print('"dumpcap -D" exited with %d. stderr:\n%s' % + (proc.returncode, errs)) + fixtures.skip('Test requires capture privileges and an interface.') + # Matches: "lo (Loopback)" (Linux), "lo0 (Loopback)" (macOS) or + # "\Device\NPF_{...} (Npcap Loopback Adapter)" (Windows) + print('"dumpcap -D" output:\n%s' % (outs,)) + m = re.search(r'^(\d+)\. .*\(.*Loopback.*\)', outs, re.MULTILINE) + if not m: + fixtures.skip('Test requires a capture interface.') + iface = m.group(1) + # Interface found, check for capture privileges (needed for Linux). + try: + subprocess.check_output((cmd_dumpcap, '-L', '-i', iface), + stderr=subprocess.STDOUT, + universal_newlines=True) return iface - else: - if sys.platform == 'win32': - patterns = '.*(Ethernet|Network Connection|VMware|Intel)' - else: - patterns = None - if patterns: - try: - output = subprocess.check_output((cmd_dumpcap, '-D'), - stderr=subprocess.DEVNULL, - universal_newlines=True) - m = re.search(r'^(\d+)\. %s' % patterns, output, re.MULTILINE) - if m: - return m.group(1) - except subprocess.CalledProcessError: - pass - fixtures.skip('Test requires capture privileges and an interface.') + except subprocess.CalledProcessError as e: + print('"dumpcap -L -i %s" exited with %d. Output:\n%s' % (iface, + e.returncode, + e.output)) + fixtures.skip('Test requires capture privileges.') @fixtures.fixture(scope='session') @@ -152,7 +156,7 @@ def features(cmd_tshark, make_env): ) tshark_v = re.sub(r'\s+', ' ', tshark_v) except subprocess.CalledProcessError as ex: - logging.warning('Failed to detect tshark features: %s', ex) + print('Failed to detect tshark features: %s' % (ex,)) tshark_v = '' gcry_m = re.search(r'with +Gcrypt +([0-9]+\.[0-9]+)', tshark_v) return types.SimpleNamespace( diff --git a/test/suite_capture.py b/test/suite_capture.py index 6da25578d6..2522530668 100644 --- a/test/suite_capture.py +++ b/test/suite_capture.py @@ -13,9 +13,11 @@ import fixtures import glob import hashlib import os +import socket import subprocess import subprocesstest import sys +import threading import time import uuid @@ -25,6 +27,23 @@ testout_pcap = 'testout.pcap' testout_pcapng = 'testout.pcapng' snapshot_len = 96 +class UdpTrafficGenerator(threading.Thread): + def __init__(self): + super().__init__(daemon=True) + self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.stopped = False + + def run(self): + while not self.stopped: + time.sleep(.05) + self.sock.sendto(b'Wireshark test\n', ('127.0.0.1', 9)) + + def stop(self): + if not self.stopped: + self.stopped = True + self.join() + + @fixtures.fixture def traffic_generator(): ''' @@ -32,41 +51,19 @@ def traffic_generator(): where cfilter is a capture filter to match the generated traffic. start_func can be invoked to start generating traffic and returns a function which can be used to stop traffic generation early. - Currently calls ping www.wireshark.org for 60 seconds. + Currently generates a bunch of UDP traffic to localhost. ''' - # XXX replace this by something that generates UDP traffic to localhost? - # That would avoid external access which is forbidden by the Debian policy. - nprocs = 1 - if sys.platform.startswith('win32'): - # XXX Check for psping? https://docs.microsoft.com/en-us/sysinternals/downloads/psping - args_ping = ('ping', '-n', '60', '-l', '100', 'www.wireshark.org') - nprocs = 3 - elif sys.platform.startswith('linux') or sys.platform.startswith('freebsd'): - args_ping = ('ping', '-c', '240', '-s', '100', '-i', '0.25', 'www.wireshark.org') - elif sys.platform.startswith('darwin'): - args_ping = ('ping', '-c', '1', '-g', '1', '-G', '240', '-i', '0.25', 'www.wireshark.org') - else: - # XXX Other BSDs, Solaris, etc - fixtures.skip('ping utility is unavailable - cannot generate traffic') - procs = [] - def kill_processes(): - for proc in procs: - proc.kill() - for proc in procs: - proc.wait() - procs.clear() + threads = [] def start_processes(): - for i in range(nprocs): - if i > 0: - # Fake subsecond interval if the ping utility lacks support. - time.sleep(0.1) - proc = subprocess.Popen(args_ping, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) - procs.append(proc) - return kill_processes + thread = UdpTrafficGenerator() + thread.start() + threads.append(thread) + return thread.stop try: - yield start_processes, 'icmp || icmp6' + yield start_processes, 'udp port 9' finally: - kill_processes() + for thread in threads: + thread.stop() @fixtures.fixture(scope='session') diff --git a/test/test.py b/test/test.py index 27d75efc63..df3e9337aa 100755 --- a/test/test.py +++ b/test/test.py @@ -54,7 +54,6 @@ def main(): parser = argparse.ArgumentParser(description='Wireshark unit tests') cap_group = parser.add_mutually_exclusive_group() cap_group.add_argument('-E', '--disable-capture', action='store_true', help='Disable capture tests') - cap_group.add_argument('-i', '--capture-interface', help='Capture interface index or name') parser.add_argument('-p', '--program-path', default=os.path.curdir, help='Path to Wireshark executables.') parser.add_argument('--skip-missing-programs', help='Skip tests that lack programs from this list instead of failing' |