kunit.py (126901ba3499880c9ed033633817cf7493120fda) kunit.py (1da2e6220e1115930694c649605534baf6fa3dea)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3#
4# A thin wrapper on top of the KUnit Kernel
5#
6# Copyright (C) 2019, Google LLC.
7# Author: Felix Guo <felixguoxiuping@gmail.com>
8# Author: Brendan Higgins <brendanhiggins@google.com>

--- 255 unchanged lines hidden (view full) ---

264 if arg not in pseudo_bool_flag_defaults:
265 return arg
266 return f'{arg}={pseudo_bool_flag_defaults[arg]}'
267 return list(map(massage_arg, argv))
268
269def get_default_jobs() -> int:
270 return len(os.sched_getaffinity(0))
271
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3#
4# A thin wrapper on top of the KUnit Kernel
5#
6# Copyright (C) 2019, Google LLC.
7# Author: Felix Guo <felixguoxiuping@gmail.com>
8# Author: Brendan Higgins <brendanhiggins@google.com>

--- 255 unchanged lines hidden (view full) ---

264 if arg not in pseudo_bool_flag_defaults:
265 return arg
266 return f'{arg}={pseudo_bool_flag_defaults[arg]}'
267 return list(map(massage_arg, argv))
268
269def get_default_jobs() -> int:
270 return len(os.sched_getaffinity(0))
271
272def add_common_opts(parser) -> None:
272def add_common_opts(parser: argparse.ArgumentParser) -> None:
273 parser.add_argument('--build_dir',
274 help='As in the make command, it specifies the build '
275 'directory.',
276 type=str, default='.kunit', metavar='DIR')
277 parser.add_argument('--make_options',
278 help='X=Y make option, can be repeated.',
279 action='append', metavar='X=Y')
280 parser.add_argument('--alltests',

--- 34 unchanged lines hidden (view full) ---

315 help=('Takes a path to a path to a file containing '
316 'a QemuArchParams object.'),
317 type=str, metavar='FILE')
318
319 parser.add_argument('--qemu_args',
320 help='Additional QEMU arguments, e.g. "-smp 8"',
321 action='append', metavar='')
322
273 parser.add_argument('--build_dir',
274 help='As in the make command, it specifies the build '
275 'directory.',
276 type=str, default='.kunit', metavar='DIR')
277 parser.add_argument('--make_options',
278 help='X=Y make option, can be repeated.',
279 action='append', metavar='X=Y')
280 parser.add_argument('--alltests',

--- 34 unchanged lines hidden (view full) ---

315 help=('Takes a path to a path to a file containing '
316 'a QemuArchParams object.'),
317 type=str, metavar='FILE')
318
319 parser.add_argument('--qemu_args',
320 help='Additional QEMU arguments, e.g. "-smp 8"',
321 action='append', metavar='')
322
323def add_build_opts(parser) -> None:
323def add_build_opts(parser: argparse.ArgumentParser) -> None:
324 parser.add_argument('--jobs',
325 help='As in the make command, "Specifies the number of '
326 'jobs (commands) to run simultaneously."',
327 type=int, default=get_default_jobs(), metavar='N')
328
324 parser.add_argument('--jobs',
325 help='As in the make command, "Specifies the number of '
326 'jobs (commands) to run simultaneously."',
327 type=int, default=get_default_jobs(), metavar='N')
328
329def add_exec_opts(parser) -> None:
329def add_exec_opts(parser: argparse.ArgumentParser) -> None:
330 parser.add_argument('--timeout',
331 help='maximum number of seconds to allow for all tests '
332 'to run. This does not include time taken to build the '
333 'tests.',
334 type=int,
335 default=300,
336 metavar='SECONDS')
337 parser.add_argument('filter_glob',

--- 8 unchanged lines hidden (view full) ---

346 action='append', metavar='')
347 parser.add_argument('--run_isolated', help='If set, boot the kernel for each '
348 'individual suite/test. This is can be useful for debugging '
349 'a non-hermetic test, one that might pass/fail based on '
350 'what ran before it.',
351 type=str,
352 choices=['suite', 'test'])
353
330 parser.add_argument('--timeout',
331 help='maximum number of seconds to allow for all tests '
332 'to run. This does not include time taken to build the '
333 'tests.',
334 type=int,
335 default=300,
336 metavar='SECONDS')
337 parser.add_argument('filter_glob',

--- 8 unchanged lines hidden (view full) ---

346 action='append', metavar='')
347 parser.add_argument('--run_isolated', help='If set, boot the kernel for each '
348 'individual suite/test. This is can be useful for debugging '
349 'a non-hermetic test, one that might pass/fail based on '
350 'what ran before it.',
351 type=str,
352 choices=['suite', 'test'])
353
354def add_parse_opts(parser) -> None:
354def add_parse_opts(parser: argparse.ArgumentParser) -> None:
355 parser.add_argument('--raw_output', help='If set don\'t parse output from kernel. '
356 'By default, filters to just KUnit output. Use '
357 '--raw_output=all to show everything',
358 type=str, nargs='?', const='all', default=None, choices=['all', 'kunit'])
359 parser.add_argument('--json',
360 nargs='?',
361 help='Prints parsed test results as JSON to stdout or a file if '
362 'a filename is specified. Does nothing if --raw_output is set.',

--- 18 unchanged lines hidden (view full) ---

381 kunitconfig_paths=kunitconfigs,
382 kconfig_add=cli_args.kconfig_add,
383 arch=cli_args.arch,
384 cross_compile=cli_args.cross_compile,
385 qemu_config_path=cli_args.qemu_config,
386 extra_qemu_args=qemu_args)
387
388
355 parser.add_argument('--raw_output', help='If set don\'t parse output from kernel. '
356 'By default, filters to just KUnit output. Use '
357 '--raw_output=all to show everything',
358 type=str, nargs='?', const='all', default=None, choices=['all', 'kunit'])
359 parser.add_argument('--json',
360 nargs='?',
361 help='Prints parsed test results as JSON to stdout or a file if '
362 'a filename is specified. Does nothing if --raw_output is set.',

--- 18 unchanged lines hidden (view full) ---

381 kunitconfig_paths=kunitconfigs,
382 kconfig_add=cli_args.kconfig_add,
383 arch=cli_args.arch,
384 cross_compile=cli_args.cross_compile,
385 qemu_config_path=cli_args.qemu_config,
386 extra_qemu_args=qemu_args)
387
388
389def run_handler(cli_args):
389def run_handler(cli_args: argparse.Namespace) -> None:
390 if not os.path.exists(cli_args.build_dir):
391 os.mkdir(cli_args.build_dir)
392
393 linux = tree_from_args(cli_args)
394 request = KunitRequest(build_dir=cli_args.build_dir,
395 make_options=cli_args.make_options,
396 jobs=cli_args.jobs,
397 raw_output=cli_args.raw_output,
398 json=cli_args.json,
399 timeout=cli_args.timeout,
400 filter_glob=cli_args.filter_glob,
401 kernel_args=cli_args.kernel_args,
402 run_isolated=cli_args.run_isolated)
403 result = run_tests(linux, request)
404 if result.status != KunitStatus.SUCCESS:
405 sys.exit(1)
406
407
390 if not os.path.exists(cli_args.build_dir):
391 os.mkdir(cli_args.build_dir)
392
393 linux = tree_from_args(cli_args)
394 request = KunitRequest(build_dir=cli_args.build_dir,
395 make_options=cli_args.make_options,
396 jobs=cli_args.jobs,
397 raw_output=cli_args.raw_output,
398 json=cli_args.json,
399 timeout=cli_args.timeout,
400 filter_glob=cli_args.filter_glob,
401 kernel_args=cli_args.kernel_args,
402 run_isolated=cli_args.run_isolated)
403 result = run_tests(linux, request)
404 if result.status != KunitStatus.SUCCESS:
405 sys.exit(1)
406
407
408def config_handler(cli_args):
408def config_handler(cli_args: argparse.Namespace) -> None:
409 if cli_args.build_dir and (
410 not os.path.exists(cli_args.build_dir)):
411 os.mkdir(cli_args.build_dir)
412
413 linux = tree_from_args(cli_args)
414 request = KunitConfigRequest(build_dir=cli_args.build_dir,
415 make_options=cli_args.make_options)
416 result = config_tests(linux, request)
417 stdout.print_with_timestamp((
418 'Elapsed time: %.3fs\n') % (
419 result.elapsed_time))
420 if result.status != KunitStatus.SUCCESS:
421 sys.exit(1)
422
423
409 if cli_args.build_dir and (
410 not os.path.exists(cli_args.build_dir)):
411 os.mkdir(cli_args.build_dir)
412
413 linux = tree_from_args(cli_args)
414 request = KunitConfigRequest(build_dir=cli_args.build_dir,
415 make_options=cli_args.make_options)
416 result = config_tests(linux, request)
417 stdout.print_with_timestamp((
418 'Elapsed time: %.3fs\n') % (
419 result.elapsed_time))
420 if result.status != KunitStatus.SUCCESS:
421 sys.exit(1)
422
423
424def build_handler(cli_args):
424def build_handler(cli_args: argparse.Namespace) -> None:
425 linux = tree_from_args(cli_args)
426 request = KunitBuildRequest(build_dir=cli_args.build_dir,
427 make_options=cli_args.make_options,
428 jobs=cli_args.jobs)
429 result = config_and_build_tests(linux, request)
430 stdout.print_with_timestamp((
431 'Elapsed time: %.3fs\n') % (
432 result.elapsed_time))
433 if result.status != KunitStatus.SUCCESS:
434 sys.exit(1)
435
436
425 linux = tree_from_args(cli_args)
426 request = KunitBuildRequest(build_dir=cli_args.build_dir,
427 make_options=cli_args.make_options,
428 jobs=cli_args.jobs)
429 result = config_and_build_tests(linux, request)
430 stdout.print_with_timestamp((
431 'Elapsed time: %.3fs\n') % (
432 result.elapsed_time))
433 if result.status != KunitStatus.SUCCESS:
434 sys.exit(1)
435
436
437def exec_handler(cli_args):
437def exec_handler(cli_args: argparse.Namespace) -> None:
438 linux = tree_from_args(cli_args)
439 exec_request = KunitExecRequest(raw_output=cli_args.raw_output,
440 build_dir=cli_args.build_dir,
441 json=cli_args.json,
442 timeout=cli_args.timeout,
443 filter_glob=cli_args.filter_glob,
444 kernel_args=cli_args.kernel_args,
445 run_isolated=cli_args.run_isolated)
446 result = exec_tests(linux, exec_request)
447 stdout.print_with_timestamp((
448 'Elapsed time: %.3fs\n') % (result.elapsed_time))
449 if result.status != KunitStatus.SUCCESS:
450 sys.exit(1)
451
452
438 linux = tree_from_args(cli_args)
439 exec_request = KunitExecRequest(raw_output=cli_args.raw_output,
440 build_dir=cli_args.build_dir,
441 json=cli_args.json,
442 timeout=cli_args.timeout,
443 filter_glob=cli_args.filter_glob,
444 kernel_args=cli_args.kernel_args,
445 run_isolated=cli_args.run_isolated)
446 result = exec_tests(linux, exec_request)
447 stdout.print_with_timestamp((
448 'Elapsed time: %.3fs\n') % (result.elapsed_time))
449 if result.status != KunitStatus.SUCCESS:
450 sys.exit(1)
451
452
453def parse_handler(cli_args):
453def parse_handler(cli_args: argparse.Namespace) -> None:
454 if cli_args.file is None:
454 if cli_args.file is None:
455 sys.stdin.reconfigure(errors='backslashreplace') # pytype: disable=attribute-error
456 kunit_output = sys.stdin
455 sys.stdin.reconfigure(errors='backslashreplace') # type: ignore
456 kunit_output = sys.stdin # type: Iterable[str]
457 else:
458 with open(cli_args.file, 'r', errors='backslashreplace') as f:
459 kunit_output = f.read().splitlines()
460 # We know nothing about how the result was created!
461 metadata = kunit_json.Metadata()
462 request = KunitParseRequest(raw_output=cli_args.raw_output,
463 json=cli_args.json)
464 result, _ = parse_tests(request, metadata, kunit_output)

--- 5 unchanged lines hidden (view full) ---

470 'run': run_handler,
471 'config': config_handler,
472 'build': build_handler,
473 'exec': exec_handler,
474 'parse': parse_handler
475}
476
477
457 else:
458 with open(cli_args.file, 'r', errors='backslashreplace') as f:
459 kunit_output = f.read().splitlines()
460 # We know nothing about how the result was created!
461 metadata = kunit_json.Metadata()
462 request = KunitParseRequest(raw_output=cli_args.raw_output,
463 json=cli_args.json)
464 result, _ = parse_tests(request, metadata, kunit_output)

--- 5 unchanged lines hidden (view full) ---

470 'run': run_handler,
471 'config': config_handler,
472 'build': build_handler,
473 'exec': exec_handler,
474 'parse': parse_handler
475}
476
477
478def main(argv):
478def main(argv: Sequence[str]) -> None:
479 parser = argparse.ArgumentParser(
480 description='Helps writing and running KUnit tests.')
481 subparser = parser.add_subparsers(dest='subcommand')
482
483 # The 'run' command will config, build, exec, and parse in one go.
484 run_parser = subparser.add_parser('run', help='Runs KUnit tests.')
485 add_common_opts(run_parser)
486 add_build_opts(run_parser)

--- 45 unchanged lines hidden ---
479 parser = argparse.ArgumentParser(
480 description='Helps writing and running KUnit tests.')
481 subparser = parser.add_subparsers(dest='subcommand')
482
483 # The 'run' command will config, build, exec, and parse in one go.
484 run_parser = subparser.add_parser('run', help='Runs KUnit tests.')
485 add_common_opts(run_parser)
486 add_build_opts(run_parser)

--- 45 unchanged lines hidden ---