mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +00:00 
			
		
		
		
	Rather than having the help in the longhelp, put it in the suite info so 'ut info -s' can show it. This is tidier, particular due to the removal of #ifdefs This means that the help text is present in the image (although not displayed with 'ut info -s') so the image-size increases. But with UNIT_TEST enabled, we expect large images so this doesn't seem important. Signed-off-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			325 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			325 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0
 | 
						|
/*
 | 
						|
 * (C) Copyright 2015
 | 
						|
 * Joe Hershberger, National Instruments, joe.hershberger@ni.com
 | 
						|
 */
 | 
						|
 | 
						|
#include <command.h>
 | 
						|
#include <console.h>
 | 
						|
#include <vsprintf.h>
 | 
						|
#include <test/suites.h>
 | 
						|
#include <test/test.h>
 | 
						|
#include <test/ut.h>
 | 
						|
 | 
						|
/**
 | 
						|
 * struct suite - A set of tests for a certain topic
 | 
						|
 *
 | 
						|
 * All tests end up in a single 'struct unit_test' linker-list array, in order
 | 
						|
 * of the suite they are in
 | 
						|
 *
 | 
						|
 * @name: Name of suite
 | 
						|
 * @start: First test in suite
 | 
						|
 * @end: End test in suite (points to the first test in the next suite)
 | 
						|
 * @cmd: Command to use to run the suite
 | 
						|
 * @help: Help-string to show for this suite
 | 
						|
 */
 | 
						|
struct suite {
 | 
						|
	const char *name;
 | 
						|
	struct unit_test *start;
 | 
						|
	struct unit_test *end;
 | 
						|
	ut_cmd_func cmd;
 | 
						|
	const char *help;
 | 
						|
};
 | 
						|
 | 
						|
static int do_ut_all(struct unit_test_state *uts, struct cmd_tbl *cmdtp,
 | 
						|
		     int flag, int argc, char *const argv[]);
 | 
						|
 | 
						|
static int do_ut_info(struct cmd_tbl *cmdtp, int flag, int argc,
 | 
						|
		      char *const argv[]);
 | 
						|
 | 
						|
int cmd_ut_category(struct unit_test_state *uts, const char *name,
 | 
						|
		    const char *prefix, struct unit_test *tests, int n_ents,
 | 
						|
		    int argc, char *const argv[])
 | 
						|
{
 | 
						|
	const char *test_insert = NULL;
 | 
						|
	int runs_per_text = 1;
 | 
						|
	bool force_run = false;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	while (argc > 1 && *argv[1] == '-') {
 | 
						|
		const char *str = argv[1];
 | 
						|
 | 
						|
		switch (str[1]) {
 | 
						|
		case 'r':
 | 
						|
			runs_per_text = dectoul(str + 2, NULL);
 | 
						|
			break;
 | 
						|
		case 'f':
 | 
						|
			force_run = true;
 | 
						|
			break;
 | 
						|
		case 'I':
 | 
						|
			test_insert = str + 2;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		argv++;
 | 
						|
		argc--;
 | 
						|
	}
 | 
						|
 | 
						|
	ret = ut_run_list(uts, name, prefix, tests, n_ents,
 | 
						|
			  cmd_arg1(argc, argv), runs_per_text, force_run,
 | 
						|
			  test_insert);
 | 
						|
 | 
						|
	return ret ? CMD_RET_FAILURE : 0;
 | 
						|
}
 | 
						|
 | 
						|
/* declare linker-list symbols for the start and end of a suite */
 | 
						|
#define SUITE_DECL(_name) \
 | 
						|
	ll_start_decl(suite_start_ ## _name, struct unit_test, ut_ ## _name); \
 | 
						|
	ll_end_decl(suite_end_ ## _name, struct unit_test, ut_ ## _name)
 | 
						|
 | 
						|
/* declare a test suite which uses a subcommand to run */
 | 
						|
#define SUITE_CMD(_name, _cmd_func, _help) { \
 | 
						|
	#_name, \
 | 
						|
	suite_start_ ## _name, \
 | 
						|
	suite_end_ ## _name, \
 | 
						|
	_cmd_func, \
 | 
						|
	_help, \
 | 
						|
	}
 | 
						|
 | 
						|
/* declare a test suite which can be run directly without a subcommand */
 | 
						|
#define SUITE(_name, _help) { \
 | 
						|
	#_name, \
 | 
						|
	suite_start_ ## _name, \
 | 
						|
	suite_end_ ## _name, \
 | 
						|
	NULL, \
 | 
						|
	_help, \
 | 
						|
	}
 | 
						|
 | 
						|
SUITE_DECL(addrmap);
 | 
						|
SUITE_DECL(bdinfo);
 | 
						|
SUITE_DECL(bloblist);
 | 
						|
SUITE_DECL(bootm);
 | 
						|
SUITE_DECL(bootstd);
 | 
						|
SUITE_DECL(cmd);
 | 
						|
SUITE_DECL(common);
 | 
						|
SUITE_DECL(dm);
 | 
						|
SUITE_DECL(env);
 | 
						|
SUITE_DECL(exit);
 | 
						|
SUITE_DECL(fdt);
 | 
						|
SUITE_DECL(font);
 | 
						|
SUITE_DECL(hush);
 | 
						|
SUITE_DECL(lib);
 | 
						|
SUITE_DECL(loadm);
 | 
						|
SUITE_DECL(log);
 | 
						|
SUITE_DECL(mbr);
 | 
						|
SUITE_DECL(measurement);
 | 
						|
SUITE_DECL(mem);
 | 
						|
SUITE_DECL(optee);
 | 
						|
SUITE_DECL(overlay);
 | 
						|
SUITE_DECL(pci_mps);
 | 
						|
SUITE_DECL(seama);
 | 
						|
SUITE_DECL(setexpr);
 | 
						|
SUITE_DECL(upl);
 | 
						|
 | 
						|
static struct suite suites[] = {
 | 
						|
	SUITE(addrmap, "very basic test of addrmap command"),
 | 
						|
	SUITE(bdinfo, "bdinfo (board info) command"),
 | 
						|
	SUITE(bloblist, "bloblist implementation"),
 | 
						|
	SUITE(bootm, "bootm command"),
 | 
						|
#ifdef CONFIG_UT_BOOTSTD
 | 
						|
	SUITE_CMD(bootstd, do_ut_bootstd, "standard boot implementation"),
 | 
						|
#endif
 | 
						|
	SUITE(cmd, "various commands"),
 | 
						|
	SUITE(common, "tests for common/ directory"),
 | 
						|
	SUITE(dm, "driver model"),
 | 
						|
	SUITE(env, "environment"),
 | 
						|
	SUITE(exit, "shell exit and variables"),
 | 
						|
	SUITE(fdt, "fdt command"),
 | 
						|
	SUITE(font, "font command"),
 | 
						|
	SUITE(hush, "hush behaviour"),
 | 
						|
	SUITE(lib, "library functions"),
 | 
						|
	SUITE(loadm, "loadm command parameters and loading memory blob"),
 | 
						|
	SUITE(log, "logging functions"),
 | 
						|
	SUITE(mbr, "mbr command"),
 | 
						|
	SUITE(measurement, "TPM-based measured boot"),
 | 
						|
	SUITE(mem, "memory-related commands"),
 | 
						|
#ifdef CONFIG_UT_OPTEE
 | 
						|
	SUITE_CMD(optee, do_ut_optee, "OP-TEE"),
 | 
						|
#endif
 | 
						|
#ifdef CONFIG_UT_OVERLAY
 | 
						|
	SUITE_CMD(overlay, do_ut_overlay, "device tree overlays"),
 | 
						|
#endif
 | 
						|
	SUITE(pci_mps, "PCI Express Maximum Payload Size"),
 | 
						|
	SUITE(seama, "seama command parameters loading and decoding"),
 | 
						|
	SUITE(setexpr, "setexpr command"),
 | 
						|
	SUITE(upl, "Universal payload support"),
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * has_tests() - Check if a suite has tests, i.e. is supported in this build
 | 
						|
 *
 | 
						|
 * If the suite is run using a command, we have to assume that tests may be
 | 
						|
 * present, since we have no visibility
 | 
						|
 *
 | 
						|
 * @ste: Suite to check
 | 
						|
 * Return: true if supported, false if not
 | 
						|
 */
 | 
						|
static bool has_tests(struct suite *ste)
 | 
						|
{
 | 
						|
	int n_ents = ste->end - ste->start;
 | 
						|
 | 
						|
	return n_ents || ste->cmd;
 | 
						|
}
 | 
						|
 | 
						|
/** run_suite() - Run a suite of tests */
 | 
						|
static int run_suite(struct unit_test_state *uts, struct suite *ste,
 | 
						|
		     struct cmd_tbl *cmdtp, int flag, int argc,
 | 
						|
		     char *const argv[])
 | 
						|
{
 | 
						|
	int ret;
 | 
						|
 | 
						|
	if (ste->cmd) {
 | 
						|
		ret = ste->cmd(uts, cmdtp, flag, argc, argv);
 | 
						|
	} else {
 | 
						|
		int n_ents = ste->end - ste->start;
 | 
						|
		char prefix[30];
 | 
						|
 | 
						|
		/* use a standard prefix */
 | 
						|
		snprintf(prefix, sizeof(prefix), "%s_test", ste->name);
 | 
						|
		ret = cmd_ut_category(uts, ste->name, prefix, ste->start,
 | 
						|
				      n_ents, argc, argv);
 | 
						|
	}
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int do_ut_all(struct unit_test_state *uts, struct cmd_tbl *cmdtp,
 | 
						|
		     int flag, int argc, char *const argv[])
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	int retval;
 | 
						|
	int any_fail = 0;
 | 
						|
 | 
						|
	for (i = 0; i < ARRAY_SIZE(suites); i++) {
 | 
						|
		struct suite *ste = &suites[i];
 | 
						|
		char *const argv[] = {(char *)ste->name, NULL};
 | 
						|
 | 
						|
		if (has_tests(ste)) {
 | 
						|
			printf("----Running %s tests----\n", ste->name);
 | 
						|
			retval = run_suite(uts, ste, cmdtp, flag, 1, argv);
 | 
						|
			if (!any_fail)
 | 
						|
				any_fail = retval;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	ut_report(&uts->total, uts->run_count);
 | 
						|
 | 
						|
	return any_fail;
 | 
						|
}
 | 
						|
 | 
						|
static int do_ut_info(struct cmd_tbl *cmdtp, int flag, int argc,
 | 
						|
		      char *const argv[])
 | 
						|
{
 | 
						|
	int suite_count, i;
 | 
						|
	const char *flags;
 | 
						|
 | 
						|
	for (suite_count = 0, i = 0; i < ARRAY_SIZE(suites); i++) {
 | 
						|
		struct suite *ste = &suites[i];
 | 
						|
 | 
						|
		if (has_tests(ste))
 | 
						|
			suite_count++;
 | 
						|
	}
 | 
						|
 | 
						|
	printf("Test suites: %d\n", suite_count);
 | 
						|
	printf("Total tests: %d\n", (int)UNIT_TEST_ALL_COUNT());
 | 
						|
 | 
						|
	flags = cmd_arg1(argc, argv);
 | 
						|
	if (flags && !strcmp("-s", flags)) {
 | 
						|
		int i;
 | 
						|
 | 
						|
		puts("\nTests  Suite         Purpose");
 | 
						|
		puts("\n-----  ------------  -------------------------\n");
 | 
						|
		for (i = 0; i < ARRAY_SIZE(suites); i++) {
 | 
						|
			struct suite *ste = &suites[i];
 | 
						|
			long n_ent = ste->end - ste->start;
 | 
						|
 | 
						|
			if (n_ent)
 | 
						|
				printf("%5ld", n_ent);
 | 
						|
			else if (ste->cmd)
 | 
						|
				printf("%5s", "?");
 | 
						|
			else  /* suite is not present */
 | 
						|
				continue;
 | 
						|
			printf("  %-13.13s %s\n", ste->name, ste->help);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static struct suite *find_suite(const char *name)
 | 
						|
{
 | 
						|
	struct suite *ste;
 | 
						|
	int i;
 | 
						|
 | 
						|
	for (i = 0, ste = suites; i < ARRAY_SIZE(suites); i++, ste++) {
 | 
						|
		if (!strcmp(ste->name, name))
 | 
						|
			return ste;
 | 
						|
	}
 | 
						|
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 | 
						|
{
 | 
						|
	struct unit_test_state uts;
 | 
						|
	struct suite *ste;
 | 
						|
	const char *name;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	if (argc < 2)
 | 
						|
		return CMD_RET_USAGE;
 | 
						|
 | 
						|
	/* drop initial "ut" arg */
 | 
						|
	argc--;
 | 
						|
	argv++;
 | 
						|
 | 
						|
	ut_init_state(&uts);
 | 
						|
	name = argv[0];
 | 
						|
	if (!strcmp(name, "all")) {
 | 
						|
		ret = do_ut_all(&uts, cmdtp, flag, argc, argv);
 | 
						|
	} else if (!strcmp(name, "info")) {
 | 
						|
		ret = do_ut_info(cmdtp, flag, argc, argv);
 | 
						|
	} else {
 | 
						|
		ste = find_suite(argv[0]);
 | 
						|
		if (!ste) {
 | 
						|
			printf("Suite '%s' not found\n", argv[0]);
 | 
						|
			return CMD_RET_FAILURE;
 | 
						|
		} else if (!has_tests(ste)) {
 | 
						|
			/* perhaps a Kconfig option needs to be set? */
 | 
						|
			printf("Suite '%s' is not enabled\n", argv[0]);
 | 
						|
			return CMD_RET_FAILURE;
 | 
						|
		}
 | 
						|
 | 
						|
		ret = run_suite(&uts, ste, cmdtp, flag, argc, argv);
 | 
						|
	}
 | 
						|
	if (ret)
 | 
						|
		return ret;
 | 
						|
	ut_uninit_state(&uts);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
U_BOOT_LONGHELP(ut,
 | 
						|
	"[-r] [-f] [<suite>] - run unit tests\n"
 | 
						|
	"   -r<runs>   Number of times to run each test\n"
 | 
						|
	"   -f         Force 'manual' tests to run as well\n"
 | 
						|
	"   <suite>    Test suite to run, or all\n"
 | 
						|
	"\n"
 | 
						|
	"\nOptions for <suite>:"
 | 
						|
	"\nall - execute all enabled tests"
 | 
						|
	"\ninfo [-s] - show info about tests [and suites]"
 | 
						|
	);
 | 
						|
 | 
						|
U_BOOT_CMD(
 | 
						|
	ut, CONFIG_SYS_MAXARGS, 1, do_ut,
 | 
						|
	"unit tests", ut_help_text
 | 
						|
);
 |