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

import argparse
import sys
import os
import time
14
import shutil
15 16 17 18 19 20 21 22 23 24

from collections import namedtuple
from enum import Enum, auto

import kunit_config
import kunit_kernel
import kunit_parser

KunitResult = namedtuple('KunitResult', ['status','result'])

25
KunitRequest = namedtuple('KunitRequest', ['raw_output','timeout', 'jobs', 'build_dir', 'defconfig'])
26 27 28 29 30 31 32

class KunitStatus(Enum):
	SUCCESS = auto()
	CONFIG_FAILURE = auto()
	BUILD_FAILURE = auto()
	TEST_FAILURE = auto()

33
def create_default_kunitconfig():
34
	if not os.path.exists(kunit_kernel.kunitconfig_path):
35
		shutil.copyfile('arch/um/configs/kunit_defconfig',
36
				kunit_kernel.kunitconfig_path)
37

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
def run_tests(linux: kunit_kernel.LinuxSourceTree,
	      request: KunitRequest) -> KunitResult:
	config_start = time.time()
	success = linux.build_reconfig(request.build_dir)
	config_end = time.time()
	if not success:
		return KunitResult(KunitStatus.CONFIG_FAILURE, 'could not configure kernel')

	kunit_parser.print_with_timestamp('Building KUnit Kernel ...')

	build_start = time.time()
	success = linux.build_um_kernel(request.jobs, request.build_dir)
	build_end = time.time()
	if not success:
		return KunitResult(KunitStatus.BUILD_FAILURE, 'could not build kernel')

	kunit_parser.print_with_timestamp('Starting KUnit Kernel ...')
	test_start = time.time()

	test_result = kunit_parser.TestResult(kunit_parser.TestStatus.SUCCESS,
					      [],
					      'Tests not Parsed.')
	if request.raw_output:
		kunit_parser.raw_output(
S
SeongJae Park 已提交
62 63
			linux.run_kernel(timeout=request.timeout,
					 build_dir=request.build_dir))
64
	else:
S
SeongJae Park 已提交
65 66
		kunit_output = linux.run_kernel(timeout=request.timeout,
						build_dir=request.build_dir)
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
		test_result = kunit_parser.parse_run_tests(kunit_output)
	test_end = time.time()

	kunit_parser.print_with_timestamp((
		'Elapsed time: %.3fs total, %.3fs configuring, %.3fs ' +
		'building, %.3fs running\n') % (
				test_end - config_start,
				config_end - config_start,
				build_end - build_start,
				test_end - test_start))

	if test_result.status != kunit_parser.TestStatus.SUCCESS:
		return KunitResult(KunitStatus.TEST_FAILURE, test_result)
	else:
		return KunitResult(KunitStatus.SUCCESS, test_result)

83
def main(argv, linux=None):
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
	parser = argparse.ArgumentParser(
			description='Helps writing and running KUnit tests.')
	subparser = parser.add_subparsers(dest='subcommand')

	run_parser = subparser.add_parser('run', help='Runs KUnit tests.')
	run_parser.add_argument('--raw_output', help='don\'t format output from kernel',
				action='store_true')

	run_parser.add_argument('--timeout',
				help='maximum number of seconds to allow for all tests '
				'to run. This does not include time taken to build the '
				'tests.',
				type=int,
				default=300,
				metavar='timeout')

	run_parser.add_argument('--jobs',
				help='As in the make command, "Specifies  the number of '
				'jobs (commands) to run simultaneously."',
				type=int, default=8, metavar='jobs')

	run_parser.add_argument('--build_dir',
				help='As in the make command, it specifies the build '
				'directory.',
108
				type=str, default='', metavar='build_dir')
109

110
	run_parser.add_argument('--defconfig',
111
				help='Uses a default .kunitconfig.',
112 113
				action='store_true')

114 115 116
	cli_args = parser.parse_args(argv)

	if cli_args.subcommand == 'run':
117 118 119 120 121 122 123
		if cli_args.build_dir:
			if not os.path.exists(cli_args.build_dir):
				os.mkdir(cli_args.build_dir)
			kunit_kernel.kunitconfig_path = os.path.join(
				cli_args.build_dir,
				kunit_kernel.kunitconfig_path)

124 125 126 127 128 129
		if cli_args.defconfig:
			create_default_kunitconfig()

		if not linux:
			linux = kunit_kernel.LinuxSourceTree()

130 131 132
		request = KunitRequest(cli_args.raw_output,
				       cli_args.timeout,
				       cli_args.jobs,
133 134
				       cli_args.build_dir,
				       cli_args.defconfig)
135 136 137 138 139 140 141
		result = run_tests(linux, request)
		if result.status != KunitStatus.SUCCESS:
			sys.exit(1)
	else:
		parser.print_help()

if __name__ == '__main__':
142
	main(sys.argv[1:])