wmem: allow wmem_destroy_list to ignore a NULL list.
[metze/wireshark/wip.git] / test / test.py
1 #!/usr/bin/env python3
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
17
18 import argparse
19 import codecs
20 import os.path
21 import sys
22 import unittest
23 import fixtures
24 # Required to make fixtures available to tests!
25 import fixtures_ws
26
27 _all_test_groups = None
28
29 @fixtures.fixture(scope='session')
30 def all_test_groups():
31     return _all_test_groups
32
33 def find_test_ids(suite, all_ids):
34     if hasattr(suite, '__iter__'):
35         for s in suite:
36             find_test_ids(s, all_ids)
37     else:
38         all_ids.append(suite.id())
39
40 def dump_failed_output(suite):
41     if hasattr(suite, '__iter__'):
42         for s in suite:
43             dump_failures = getattr(s, 'dump_failures', None)
44             if dump_failures:
45                 dump_failures()
46             else:
47                 dump_failed_output(s)
48
49 def main():
50     if sys.version_info[0] < 3:
51         print("Unit tests require Python 3")
52         sys.exit(2)
53
54     parser = argparse.ArgumentParser(description='Wireshark unit tests')
55     cap_group = parser.add_mutually_exclusive_group()
56     cap_group.add_argument('-E', '--disable-capture', action='store_true', help='Disable capture tests')
57     cap_group.add_argument('-i', '--capture-interface', help='Capture interface index or name')
58     parser.add_argument('-p', '--program-path', default=os.path.curdir, help='Path to Wireshark executables.')
59     list_group = parser.add_mutually_exclusive_group()
60     list_group.add_argument('-l', '--list', action='store_true', help='List tests. One of "all" or a full or partial test name.')
61     list_group.add_argument('--list-suites', action='store_true', help='List all suites.')
62     list_group.add_argument('--list-groups', action='store_true', help='List all suites and groups.')
63     list_group.add_argument('--list-cases', action='store_true', help='List all suites, groups, and cases.')
64     parser.add_argument('-v', '--verbose', action='store_const', const=2, default=1, help='Verbose tests.')
65     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".')
66     args = parser.parse_args()
67
68     all_tests = unittest.defaultTestLoader.discover(os.path.dirname(__file__), pattern='suite_*')
69
70     all_ids = []
71     find_test_ids(all_tests, all_ids)
72
73     run_ids = []
74     for tid in all_ids:
75         for ttr in args.tests_to_run:
76             ttrl = ttr.lower()
77             if ttrl == 'all':
78                 run_ids = all_ids
79                 break
80             if ttrl in tid.lower():
81                 run_ids.append(tid)
82
83     if not run_ids:
84         print('No tests found. You asked for:\n  ' + '\n  '.join(args.tests_to_run))
85         parser.print_usage()
86         sys.exit(1)
87
88     if args.list:
89         print('\n'.join(run_ids))
90         sys.exit(0)
91
92     all_suites = set()
93     for aid in all_ids:
94         aparts = aid.split('.')
95         all_suites |= {aparts[0]}
96     all_suites = sorted(all_suites)
97
98     all_groups = set()
99     for aid in all_ids:
100         aparts = aid.split('.')
101         if aparts[1].startswith('group_'):
102             all_groups |= {'.'.join(aparts[:2])}
103         else:
104             all_groups |= {aparts[0]}
105     all_groups = sorted(all_groups)
106     global _all_test_groups
107     _all_test_groups = all_groups
108
109     if args.list_suites:
110         print('\n'.join(all_suites))
111         sys.exit(0)
112
113     if args.list_groups:
114         print('\n'.join(all_groups))
115         sys.exit(0)
116
117     if args.list_cases:
118         cases = set()
119         for rid in run_ids:
120             rparts = rid.split('.')
121             cases |= {'.'.join(rparts[:2])}
122         print('\n'.join(list(cases)))
123         sys.exit(0)
124
125     if codecs.lookup(sys.stdout.encoding).name != 'utf-8':
126         import locale
127         sys.stderr.write('Warning: Output encoding is {0} and not utf-8.\n'.format(sys.stdout.encoding))
128         sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout.buffer, 'backslashreplace')
129         sys.stderr = codecs.getwriter(locale.getpreferredencoding())(sys.stderr.buffer, 'backslashreplace')
130
131     run_suite = unittest.defaultTestLoader.loadTestsFromNames(run_ids)
132     runner = unittest.TextTestRunner(verbosity=args.verbose)
133     # for unittest compatibility (not needed with pytest)
134     fixtures_ws.fixtures.create_session(args)
135     try:
136         test_result = runner.run(run_suite)
137     finally:
138         # for unittest compatibility (not needed with pytest)
139         fixtures_ws.fixtures.destroy_session()
140
141     dump_failed_output(run_suite)
142
143     if test_result.errors:
144         sys.exit(2)
145
146     if test_result.failures:
147         sys.exit(1)
148
149 if __name__ == '__main__':
150     main()