156da53a9000d627e1fd32e5764d6b5c668dd424
[metze/wireshark/wip.git] / test / test.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # Wireshark tests
5 # By Gerald Combs <gerald@wireshark.org>
6 #
7 # Ported from a set of Bash scripts which were copyright 2005 Ulf Lamping
8 #
9 # SPDX-License-Identifier: GPL-2.0-or-later
10 #
11 '''Main test script'''
12
13 # To do:
14 # - Avoid printing Python tracebacks when we assert? It looks like we'd need
15 #   to override unittest.TextTestResult.addFailure().
16 # - Switch to Python 3 only? [Windows, Linux, macOS] x [Python 2, Python 3]
17 #   is painful.
18 # - Remove BIN_PATH/hosts via config.tearDownHostFiles + case_name_resolution.tearDownClass?
19
20
21 import argparse
22 import config
23 import os.path
24 import sys
25 import unittest
26
27 def find_test_ids(suite, all_ids):
28     if hasattr(suite, '__iter__'):
29         for s in suite:
30             find_test_ids(s, all_ids)
31     else:
32         all_ids.append(suite.id())
33
34 def dump_failed_output(suite):
35     if hasattr(suite, '__iter__'):
36         for s in suite:
37             dump_failures = getattr(s, 'dump_failures', None)
38             if dump_failures:
39                 dump_failures()
40             else:
41                 dump_failed_output(s)
42
43 def main():
44     parser = argparse.ArgumentParser(description='Wireshark unit tests')
45     cap_group = parser.add_mutually_exclusive_group()
46     cap_group.add_argument('-e', '--enable-capture', action='store_true', help='Enable capture tests')
47     cap_group.add_argument('-E', '--disable-capture', action='store_true', help='Disable capture tests')
48     cap_group.add_argument('-i', '--capture-interface', nargs=1, default=None, help='Capture interface index or name')
49     parser.add_argument('-p', '--program-path', nargs=1, default=os.path.curdir, help='Path to Wireshark executables.')
50     list_group = parser.add_mutually_exclusive_group()
51     list_group.add_argument('-l', '--list', action='store_true', help='List tests. One of "all" or a full or partial test name.')
52     list_group.add_argument('--list-suites', action='store_true', help='List all suites.')
53     list_group.add_argument('--list-cases', action='store_true', help='List all suites and cases.')
54     parser.add_argument('-v', '--verbose', action='store_const', const=2, default=1, help='Verbose tests.')
55     parser.add_argument('tests_to_run', nargs='*', metavar='test', default=['all'], help='Tests to run. One of "all" or a full or partial test name. Default is "all".')
56     args = parser.parse_args()
57
58     if args.enable_capture:
59         config.setCanCapture(True)
60     elif args.disable_capture:
61         config.setCanCapture(False)
62
63     if args.capture_interface:
64         config.setCaptureInterface(args.capture_interface[0])
65
66     all_tests = unittest.defaultTestLoader.discover(os.path.dirname(__file__), pattern='suite_*.py')
67
68     all_ids = []
69     find_test_ids(all_tests, all_ids)
70
71     run_ids = []
72     for tid in all_ids:
73         for ttr in args.tests_to_run:
74             ttrl = ttr.lower()
75             if ttrl == 'all':
76                 run_ids = all_ids
77                 break
78             if ttrl in tid.lower():
79                 run_ids.append(tid)
80
81     if not run_ids:
82         print('No tests found. You asked for:\n  ' + '\n  '.join(args.tests_to_run))
83         parser.print_usage()
84         sys.exit(1)
85
86     if args.list:
87         print('\n'.join(run_ids))
88         sys.exit(0)
89
90     if args.list_suites:
91         suites = set()
92         for rid in run_ids:
93             rparts = rid.split('.')
94             suites |= {rparts[0]}
95         print('\n'.join(list(suites)))
96         sys.exit(0)
97
98     if args.list_cases:
99         cases = set()
100         for rid in run_ids:
101             rparts = rid.split('.')
102             cases |= {'.'.join(rparts[:2])}
103         print('\n'.join(list(cases)))
104         sys.exit(0)
105
106     program_path = args.program_path[0]
107     if not config.setProgramPath(program_path):
108         print('One or more required executables not found at {}\n'.format(program_path))
109         parser.print_usage()
110         sys.exit(1)
111
112     run_suite = unittest.defaultTestLoader.loadTestsFromNames(run_ids)
113     runner = unittest.TextTestRunner(verbosity=args.verbose)
114     test_result = runner.run(run_suite)
115
116     dump_failed_output(run_suite)
117
118     if test_result.errors:
119         sys.exit(2)
120
121     if test_result.failures:
122         sys.exit(1)
123
124 if __name__ == '__main__':
125     main()