blob: 578cc40fa2a84a775e80b57789162073535782db [file] [log] [blame]
Klement Sekerab23ffd72021-05-31 16:08:53 +02001import argparse
2import os
3import psutil
Klement Sekerab23ffd72021-05-31 16:08:53 +02004import time
5
6
7def positive_int_or_default(default):
8 def positive_integer(v):
9 if v is None or v == "":
10 return default
Andrew Yourtchenkof56b0072022-03-18 17:05:53 +000011 if int(v) <= 0:
12 raise ValueError("value must be positive")
Klement Sekerab23ffd72021-05-31 16:08:53 +020013 return int(v)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020014
Klement Sekerab23ffd72021-05-31 16:08:53 +020015 return positive_integer
16
17
Andrew Yourtchenkof56b0072022-03-18 17:05:53 +000018def positive_float_or_default(default):
19 def positive_float(v):
20 if v is None or v == "":
21 return default
22 if float(v) <= 0:
23 raise ValueError("value must be positive")
24 return float(v)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020025
Andrew Yourtchenkof56b0072022-03-18 17:05:53 +000026 return positive_float
27
28
Klement Sekerab23ffd72021-05-31 16:08:53 +020029def positive_int_or_auto(v):
30 if v is None or v in ("", "auto"):
31 return "auto"
32 if int(v) <= 0:
33 raise ValueError("value must be positive or auto")
34 return int(v)
35
36
37def int_or_auto(v):
38 if v is None or v in ("", "auto"):
39 return "auto"
40 if int(v) < 0:
41 raise ValueError("value must be positive or auto")
42 return int(v)
43
44
45def int_choice_or_default(options, default):
46 assert default in options
47
48 def choice(v):
49 if v is None or v == "":
50 return default
51 if int(v) in options:
52 return int(v)
53 raise ValueError("invalid choice")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020054
Klement Sekerab23ffd72021-05-31 16:08:53 +020055 return choice
56
57
58def worker_config(v):
59 if v is None or v == "":
60 return 0
61 if v.startswith("workers "):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020062 return int(v.split(" ")[1])
Klement Sekerab23ffd72021-05-31 16:08:53 +020063 return int(v)
64
65
66def directory(v):
67 if not os.path.isdir(v):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020068 raise ValueError(f"provided path '{v}' doesn't exist or is not a directory")
Klement Sekerab23ffd72021-05-31 16:08:53 +020069 return v
70
71
72def directory_verify_or_create(v):
73 if not os.path.isdir(v):
74 os.mkdir(v)
75 return v
76
77
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020078parser = argparse.ArgumentParser(
79 description="VPP unit tests", formatter_class=argparse.RawTextHelpFormatter
80)
Klement Sekerab23ffd72021-05-31 16:08:53 +020081
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020082parser.add_argument(
83 "--failfast", action="store_true", help="stop running tests on first failure"
84)
Klement Sekerab23ffd72021-05-31 16:08:53 +020085
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020086parser.add_argument(
87 "--test-src-dir",
88 action="append",
89 type=directory,
90 help="directory containing test files "
91 "(may be specified multiple times) "
92 "(VPP_WS_DIR/test is added automatically to the set)",
93)
Klement Sekerab23ffd72021-05-31 16:08:53 +020094
95default_verbose = 0
96
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020097parser.add_argument(
98 "--verbose",
99 action="store",
100 default=default_verbose,
101 type=int_choice_or_default((0, 1, 2), default_verbose),
102 help="verbosity setting - 0 - least verbose, 2 - most verbose (default: 0)",
103)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200104
105default_test_run_timeout = 600
106
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200107parser.add_argument(
108 "--timeout",
109 action="store",
110 type=positive_int_or_default(default_test_run_timeout),
111 default=default_test_run_timeout,
112 metavar="TEST_RUN_TIMEOUT",
113 help="test run timeout in seconds - per test "
114 f"(default: {default_test_run_timeout})",
115)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200116
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200117parser.add_argument(
118 "--failed-dir",
119 action="store",
120 type=directory,
Klement Sekera152a9b62022-05-13 18:01:36 +0200121 help="directory containing failed tests (default: --tmp-dir)",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200122)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200123
124filter_help_string = """\
Klement Sekera08c50e32023-04-14 17:44:04 +0200125expression consists of one or more filters separated by commas (',')
126filter consists of 3 string selectors separated by dots ('.')
Klement Sekerab23ffd72021-05-31 16:08:53 +0200127
128 <file>.<class>.<function>
129
130- selectors restrict which files/classes/functions are run
131- selector can be replaced with '*' or omitted entirely if not needed
132- <file> selector is automatically prepended with 'test_' if required
133- '.' separators are required only if selector(s) follow(s)
134
135examples:
136
1371. all of the following expressions are equivalent and will select
138 all test classes and functions from test_bfd.py:
139 'test_bfd' 'bfd' 'test_bfd..' 'bfd.' 'bfd.*.*' 'test_bfd.*.*'
1402. 'bfd.BFDAPITestCase' selects all tests from test_bfd.py,
141 which are part of BFDAPITestCase class
1423. 'bfd.BFDAPITestCase.test_add_bfd' selects a single test named
143 test_add_bfd from test_bfd.py/BFDAPITestCase
1444. '.*.test_add_bfd' selects all test functions named test_add_bfd
145 from all files/classes
Klement Sekera08c50e32023-04-14 17:44:04 +02001465. 'bfd,ip4,..test_icmp_error' selects all test functions in test_bfd.py,
147 test_ip4.py and all test functions named 'test_icmp_error' in all files
Klement Sekerab23ffd72021-05-31 16:08:53 +0200148"""
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200149parser.add_argument(
150 "--filter", action="store", metavar="FILTER_EXPRESSION", help=filter_help_string
151)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200152
153default_retries = 0
154
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200155parser.add_argument(
156 "--retries",
157 action="store",
158 default=default_retries,
159 type=positive_int_or_default(default_retries),
160 help="retry failed tests RETRIES times",
161)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200162
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200163parser.add_argument(
164 "--step", action="store_true", default=False, help="enable stepping through tests"
165)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200166
167debug_help_string = """\
168attach - attach to already running vpp
169core - detect coredump and load core in gdb on crash
170gdb - print VPP PID and pause allowing attaching gdb
171gdbserver - same as above, but run gdb in gdbserver
172"""
173
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200174parser.add_argument(
175 "--debug",
176 action="store",
177 choices=["attach", "core", "gdb", "gdbserver"],
178 help=debug_help_string,
179)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200180
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200181parser.add_argument(
182 "--debug-framework",
183 action="store_true",
184 help="enable internal test framework debugging",
185)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200186
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200187parser.add_argument(
188 "--compress-core",
189 action="store_true",
190 help="compress core files if not debugging them",
191)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200192
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200193parser.add_argument("--extended", action="store_true", help="run extended tests")
Klement Sekerab23ffd72021-05-31 16:08:53 +0200194
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200195parser.add_argument(
196 "--sanity", action="store_true", help="perform sanity vpp run before running tests"
197)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200198
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200199parser.add_argument(
200 "--force-foreground",
201 action="store_true",
202 help="force running in foreground - don't fork",
203)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200204
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200205parser.add_argument(
206 "--jobs",
207 action="store",
208 type=positive_int_or_auto,
209 default="auto",
210 help="maximum concurrent test jobs",
211)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200212
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200213parser.add_argument(
214 "--venv-dir", action="store", type=directory, help="path to virtual environment"
215)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200216
217default_rnd_seed = time.time()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200218parser.add_argument(
219 "--rnd-seed",
220 action="store",
221 default=default_rnd_seed,
222 type=positive_float_or_default(default_rnd_seed),
223 help="random generator seed (default: current time)",
224)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200225
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200226parser.add_argument(
227 "--vpp-worker-count",
228 action="store",
229 type=worker_config,
230 default=0,
231 help="number of vpp workers",
232)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200233
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200234parser.add_argument(
235 "--gcov", action="store_true", default=False, help="running gcov tests"
236)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200237
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200238parser.add_argument(
239 "--cache-vpp-output",
240 action="store_true",
241 default=False,
242 help="cache VPP stdout/stderr and log as one block after test finishes",
243)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200244
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200245parser.add_argument(
246 "--vpp-ws-dir",
247 action="store",
248 required=True,
249 type=directory,
250 help="vpp workspace directory",
251)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200252
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200253parser.add_argument(
254 "--vpp-tag",
255 action="store",
256 default="vpp_debug",
257 metavar="VPP_TAG",
258 required=True,
259 help="vpp tag (e.g. vpp, vpp_debug, vpp_gcov)",
260)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200261
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200262parser.add_argument(
263 "--vpp",
264 action="store",
265 help="path to vpp binary (default: derive from VPP_WS_DIR and VPP_TAG)",
266)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200267
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200268parser.add_argument(
269 "--vpp-install-dir",
270 type=directory,
271 action="store",
272 help="path to vpp install directory"
273 "(default: derive from VPP_WS_DIR and VPP_TAG)",
274)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200275
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200276parser.add_argument(
277 "--vpp-build-dir",
278 action="store",
279 type=directory,
280 help="vpp build directory (default: derive from VPP_WS_DIR and VPP_TAG)",
281)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200282
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200283parser.add_argument(
284 "--vpp-plugin-dir",
285 action="append",
286 type=directory,
287 help="directory containing vpp plugins"
288 "(default: derive from VPP_WS_DIR and VPP_TAG)",
289)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200290
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200291parser.add_argument(
292 "--vpp-test-plugin-dir",
293 action="append",
294 type=directory,
295 help="directory containing vpp api test plugins"
296 "(default: derive from VPP_WS_DIR and VPP_TAG)",
297)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200298
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200299parser.add_argument(
300 "--extern-plugin-dir",
301 action="append",
302 type=directory,
303 default=[],
304 help="directory containing external plugins",
305)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200306
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200307parser.add_argument(
Ole Troan37157da2022-12-01 11:22:06 +0100308 "--extern-apidir",
309 action="append",
310 type=directory,
311 default=[],
312 help="directory to look for API JSON files",
313)
314
315parser.add_argument(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200316 "--coredump-size",
317 action="store",
318 default="unlimited",
319 help="specify vpp coredump size",
320)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200321
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200322parser.add_argument(
323 "--max-vpp-cpus",
324 action="store",
325 type=int_or_auto,
326 default=0,
327 help="max cpus used by vpp",
328)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200329
330variant_help_string = """\
331specify which march node variant to unit test
332 e.g. --variant=skx - test the skx march variants
333 e.g. --variant=icl - test the icl march variants
334"""
335
336parser.add_argument("--variant", action="store", help=variant_help_string)
337
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200338parser.add_argument(
339 "--api-fuzz", action="store", default=None, help="specify api fuzzing parameters"
340)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200341
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200342parser.add_argument(
343 "--wipe-tmp-dir",
344 action="store_true",
345 default=True,
346 help="remove test tmp directory before running test",
347)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200348
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200349parser.add_argument(
350 "--tmp-dir",
351 action="store",
352 default="/tmp",
353 type=directory_verify_or_create,
354 help="directory where to store test temporary directories",
355)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200356
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200357parser.add_argument(
358 "--log-dir",
359 action="store",
360 type=directory_verify_or_create,
361 help="directory where to store directories "
362 "containing log files (default: --tmp-dir)",
363)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200364
365default_keep_pcaps = False
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200366parser.add_argument(
367 "--keep-pcaps",
368 action="store_true",
369 default=default_keep_pcaps,
Klement Sekera152a9b62022-05-13 18:01:36 +0200370 help=f"if set, keep all pcap files from a test run (default: {default_keep_pcaps})",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200371)
Klement Sekerab23ffd72021-05-31 16:08:53 +0200372
Naveen Joyc872cec2022-08-30 13:59:03 -0700373parser.add_argument(
374 "-r",
375 "--use-running-vpp",
376 dest="running_vpp",
377 required=False,
378 action="store_true",
379 default=False,
380 help="Runs tests against a running VPP.",
381)
382
383parser.add_argument(
384 "-d",
385 "--socket-dir",
386 dest="socket_dir",
387 required=False,
388 action="store",
389 default="",
390 help="Relative or absolute path to running VPP's socket directory.\n"
391 "The directory must contain VPP's socket files:api.sock & stats.sock.\n"
392 "Default: /var/run/vpp if VPP is started as the root user, else "
393 "/var/run/user/${uid}/vpp.",
394)
395
Klement Sekerab23ffd72021-05-31 16:08:53 +0200396config = parser.parse_args()
397
398ws = config.vpp_ws_dir
399br = f"{ws}/build-root"
400tag = config.vpp_tag
401
402if config.vpp_install_dir is None:
403 config.vpp_install_dir = f"{br}/install-{tag}-native"
404
405if config.vpp is None:
406 config.vpp = f"{config.vpp_install_dir}/vpp/bin/vpp"
407
408if config.vpp_build_dir is None:
409 config.vpp_build_dir = f"{br}/build-{tag}-native"
410
411libs = ["lib", "lib64"]
412
413if config.vpp_plugin_dir is None:
414 config.vpp_plugin_dir = [
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200415 f"{config.vpp_install_dir}/vpp/{lib}/vpp_plugins" for lib in libs
416 ]
Klement Sekerab23ffd72021-05-31 16:08:53 +0200417
418if config.vpp_test_plugin_dir is None:
419 config.vpp_test_plugin_dir = [
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200420 f"{config.vpp_install_dir}/vpp/{lib}/vpp_api_test_plugins" for lib in libs
421 ]
Klement Sekerab23ffd72021-05-31 16:08:53 +0200422
423test_dirs = [f"{ws}/test"]
424
425if config.test_src_dir is not None:
426 test_dirs.extend(config.test_src_dir)
427
428config.test_src_dir = test_dirs
429
430
431if config.venv_dir is None:
Saima Yunusc7f93b32022-08-10 03:25:31 -0400432 config.venv_dir = f"{ws}/build-root/test/venv"
Klement Sekerab23ffd72021-05-31 16:08:53 +0200433
Klement Sekera152a9b62022-05-13 18:01:36 +0200434if config.failed_dir is None:
435 config.failed_dir = f"{config.tmp_dir}"
436
Klement Sekerab23ffd72021-05-31 16:08:53 +0200437available_cpus = psutil.Process().cpu_affinity()
438num_cpus = len(available_cpus)
439
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200440if config.max_vpp_cpus == "auto":
Klement Sekerab23ffd72021-05-31 16:08:53 +0200441 max_vpp_cpus = num_cpus
442elif config.max_vpp_cpus > 0:
443 max_vpp_cpus = min(config.max_vpp_cpus, num_cpus)
444else:
445 max_vpp_cpus = num_cpus
446
447if __name__ == "__main__":
448 print("Provided arguments:")
449 for i in config.__dict__:
450 print(f" {i} is {config.__dict__[i]}")