Commit f1167cb5 authored by Konrad Sztyber's avatar Konrad Sztyber Committed by Tomasz Zawadzki
Browse files

ut: add option to register extra command-line params



Some test apps with functional tests also use CUnit for executing the
tests.  Some of them (e.g. nvme_compliance) can take extra command-line
parameters.  To support this, spdk_ut_run_tests() was extended with
options allowing users to specify those extra parameters.

Signed-off-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I5c23add108cdfa6ef614e36f1e71339fdeb43478
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/19287


Community-CI: Mellanox Build Bot
Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
parent 8fec33ae
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -25,8 +25,30 @@
		}				\
	} while (0)

/** Extra option callback */
typedef int (*spdk_ut_option_cb)(int opt, const char *optarg, void *cb_arg);

/** Extra usage callback, called when user asks for --help */
typedef void (*spdk_ut_usage_cb)(void *cb_arg);

/** Init callback, called before tests are executed after parsing arguments */
typedef int (*spdk_ut_init_cb)(void *cb_arg);

struct spdk_ut_opts {
	/* Empty for now */
	/** Extra optstring */
	const char *optstring;
	/** Extra options */
	const struct option *opts;
	/** Number of extra options */
	size_t optlen;
	/** Callback argument */
	void *cb_arg;
	/** Extra option callback */
	spdk_ut_option_cb option_cb_fn;
	/** Init callack */
	spdk_ut_init_cb init_cb_fn;
	/** Usage callback */
	spdk_ut_usage_cb usage_cb_fn;
};

/**
+61 −8
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
 */

#include "spdk/stdinc.h"
#include "spdk/util.h"
#include "spdk_internal/cunit.h"

enum ut_action {
@@ -16,6 +17,7 @@ struct ut_config {
	const char			*test;
	const char			*suite;
	enum ut_action			action;
	const struct spdk_ut_opts	*opts;
};

#define OPTION_STRING "hls:t:"
@@ -35,23 +37,57 @@ static const struct option g_ut_options[] = {
static void
usage(struct ut_config *config)
{
	const struct spdk_ut_opts *opts = config->opts;

	printf("Usage: %s [OPTIONS]\n", config->app);
	printf("  -t, --test                       run single test case\n");
	printf("  -s, --suite                      run all tests in a given suite\n");
	printf("  -l, --list                       list registered test suites and test cases\n");
	printf("  -h, --help                       print this help\n");

	if (opts != NULL && opts->usage_cb_fn != NULL) {
		opts->usage_cb_fn(opts->cb_arg);
	}
}

static int
parse_args(int argc, char **argv, struct ut_config *config)
{
	int op;
	const struct spdk_ut_opts *opts = config->opts;
#define MAX_OPTSTRING_LEN 4096
	char optstring[MAX_OPTSTRING_LEN] = {};
#define MAX_OPT_COUNT 128
	struct option options[MAX_OPT_COUNT] = {};
	size_t optlen;
	int op, rc;

	/* Run the tests by default */
	config->action = UT_ACTION_RUN_TESTS;
	config->app = argv[0];

	while ((op = getopt_long(argc, argv, OPTION_STRING, g_ut_options, NULL)) != -1) {
	if (opts != NULL && opts->opts != NULL) {
		optlen = SPDK_COUNTOF(g_ut_options) + opts->optlen;
		if (optlen > MAX_OPT_COUNT) {
			fprintf(stderr, "%s: unsupported number of options: %zu\n",
				config->app, optlen);
			return -EINVAL;
		}

		memcpy(&options[0], opts->opts, sizeof(*opts->opts) * opts->optlen);
		memcpy(&options[opts->optlen], g_ut_options, sizeof(g_ut_options));

		rc = snprintf(optstring, MAX_OPTSTRING_LEN, "%s%s", OPTION_STRING,
			      opts->optstring);
		if (rc < 0 || rc >= MAX_OPTSTRING_LEN) {
			fprintf(stderr, "%s: bad optstring\n", config->app);
			return -EINVAL;
		}
	} else {
		snprintf(optstring, sizeof(optstring), "%s", OPTION_STRING);
		memcpy(options, g_ut_options, sizeof(g_ut_options));
	}

	while ((op = getopt_long(argc, argv, optstring, options, NULL)) != -1) {
		switch (op) {
		case OPTION_TEST_CASE:
			config->test = optarg;
@@ -65,10 +101,19 @@ parse_args(int argc, char **argv, struct ut_config *config)
		case OPTION_LIST:
			config->action = UT_ACTION_LIST_TESTS;
			break;
		case '?':
			return -EINVAL;
		default:
			if (opts != NULL && opts->option_cb_fn != NULL) {
				rc = opts->option_cb_fn(op, optarg, opts->cb_arg);
				if (rc != 0) {
					return rc;
				}
			} else {
				return -EINVAL;
			}
		}
	}

	return 0;
}
@@ -155,7 +200,7 @@ list_tests(void)
int
spdk_ut_run_tests(int argc, char **argv, const struct spdk_ut_opts *opts)
{
	struct ut_config config = {};
	struct ut_config config = {.opts = opts};
	int rc;

	rc = parse_args(argc, argv, &config);
@@ -169,6 +214,14 @@ spdk_ut_run_tests(int argc, char **argv, const struct spdk_ut_opts *opts)
		usage(&config);
		break;
	case UT_ACTION_RUN_TESTS:
		if (opts != NULL && opts->init_cb_fn != NULL) {
			rc = opts->init_cb_fn(opts->cb_arg);
			if (rc != 0) {
				usage(&config);
				return 1;
			}
		}

		rc = run_tests(&config);
		break;
	case UT_ACTION_LIST_TESTS: