Commit 3593e678 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'linux_kselftest-kunit-fixes-7.0-rc3' of...

Merge tag 'linux_kselftest-kunit-fixes-7.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull kunit fixes from Shuah Khan:

 - Fix rust warnings when CONFIG_PRINTK is disabled

 - Reduce stack usage in kunit_run_tests() to fix warnings when
   CONFIG_FRAME_WARN is set to a relatively low value

 - Update email address for David Gow

 - Copy caller args in kunit tool in run_kernel to prevent mutation

* tag 'linux_kselftest-kunit-fixes-7.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
  kunit: reduce stack usage in kunit_run_tests()
  kunit: tool: copy caller args in run_kernel to prevent mutation
  rust: kunit: fix warning when !CONFIG_PRINTK
  MAINTAINERS: Update email address for David Gow
parents 65169048 b11b9b67
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -219,6 +219,7 @@ Daniele Alessandrelli <daniele.alessandrelli@gmail.com> <daniele.alessandrelli@i
Danilo Krummrich <dakr@kernel.org> <dakr@redhat.com>
David Brownell <david-b@pacbell.net>
David Collins <quic_collinsd@quicinc.com> <collinsd@codeaurora.org>
David Gow <david@davidgow.net> <davidgow@google.com>
David Heidelberg <david@ixit.cz> <d.okias@gmail.com>
David Hildenbrand <david@kernel.org> <david@redhat.com>
David Rheinsberg <david@readahead.eu> <dh.herrmann@gmail.com>
+2 −2
Original line number Diff line number Diff line
@@ -13938,7 +13938,7 @@ F: fs/smb/server/
KERNEL UNIT TESTING FRAMEWORK (KUnit)
M:	Brendan Higgins <brendan.higgins@linux.dev>
M:	David Gow <davidgow@google.com>
M:	David Gow <david@davidgow.net>
R:	Rae Moar <raemoar63@gmail.com>
L:	linux-kselftest@vger.kernel.org
L:	kunit-dev@googlegroups.com
@@ -14758,7 +14758,7 @@ F: drivers/misc/lis3lv02d/
F:	drivers/platform/x86/hp/hp_accel.c
LIST KUNIT TEST
M:	David Gow <davidgow@google.com>
M:	David Gow <david@davidgow.net>
L:	linux-kselftest@vger.kernel.org
L:	kunit-dev@googlegroups.com
S:	Maintained
+125 −106
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ struct kunit_result_stats {
	unsigned long total;
};

static bool kunit_should_print_stats(struct kunit_result_stats stats)
static bool kunit_should_print_stats(struct kunit_result_stats *stats)
{
	if (kunit_stats_enabled == 0)
		return false;
@@ -102,11 +102,11 @@ static bool kunit_should_print_stats(struct kunit_result_stats stats)
	if (kunit_stats_enabled == 2)
		return true;

	return (stats.total > 1);
	return (stats->total > 1);
}

static void kunit_print_test_stats(struct kunit *test,
				   struct kunit_result_stats stats)
				   struct kunit_result_stats *stats)
{
	if (!kunit_should_print_stats(stats))
		return;
@@ -115,10 +115,10 @@ static void kunit_print_test_stats(struct kunit *test,
		  KUNIT_SUBTEST_INDENT
		  "# %s: pass:%lu fail:%lu skip:%lu total:%lu",
		  test->name,
		  stats.passed,
		  stats.failed,
		  stats.skipped,
		  stats.total);
		  stats->passed,
		  stats->failed,
		  stats->skipped,
		  stats->total);
}

/* Append formatted message to log. */
@@ -600,26 +600,26 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
}

static void kunit_print_suite_stats(struct kunit_suite *suite,
				    struct kunit_result_stats suite_stats,
				    struct kunit_result_stats param_stats)
				    struct kunit_result_stats *suite_stats,
				    struct kunit_result_stats *param_stats)
{
	if (kunit_should_print_stats(suite_stats)) {
		kunit_log(KERN_INFO, suite,
			  "# %s: pass:%lu fail:%lu skip:%lu total:%lu",
			  suite->name,
			  suite_stats.passed,
			  suite_stats.failed,
			  suite_stats.skipped,
			  suite_stats.total);
			  suite_stats->passed,
			  suite_stats->failed,
			  suite_stats->skipped,
			  suite_stats->total);
	}

	if (kunit_should_print_stats(param_stats)) {
		kunit_log(KERN_INFO, suite,
			  "# Totals: pass:%lu fail:%lu skip:%lu total:%lu",
			  param_stats.passed,
			  param_stats.failed,
			  param_stats.skipped,
			  param_stats.total);
			  param_stats->passed,
			  param_stats->failed,
			  param_stats->skipped,
			  param_stats->total);
	}
}

@@ -681,69 +681,42 @@ static void kunit_init_parent_param_test(struct kunit_case *test_case, struct ku
	}
}

int kunit_run_tests(struct kunit_suite *suite)
static noinline_for_stack void
kunit_run_param_test(struct kunit_suite *suite, struct kunit_case *test_case,
		     struct kunit *test,
		     struct kunit_result_stats *suite_stats,
		     struct kunit_result_stats *total_stats,
		     struct kunit_result_stats *param_stats)
{
	char param_desc[KUNIT_PARAM_DESC_SIZE];
	struct kunit_case *test_case;
	struct kunit_result_stats suite_stats = { 0 };
	struct kunit_result_stats total_stats = { 0 };
	const void *curr_param;

	/* Taint the kernel so we know we've run tests. */
	add_taint(TAINT_TEST, LOCKDEP_STILL_OK);

	if (suite->suite_init) {
		suite->suite_init_err = suite->suite_init(suite);
		if (suite->suite_init_err) {
			kunit_err(suite, KUNIT_SUBTEST_INDENT
				  "# failed to initialize (%d)", suite->suite_init_err);
			goto suite_end;
		}
	}

	kunit_print_suite_start(suite);

	kunit_suite_for_each_test_case(suite, test_case) {
		struct kunit test = { .param_value = NULL, .param_index = 0 };
		struct kunit_result_stats param_stats = { 0 };

		kunit_init_test(&test, test_case->name, test_case->log);
		if (test_case->status == KUNIT_SKIPPED) {
			/* Test marked as skip */
			test.status = KUNIT_SKIPPED;
			kunit_update_stats(&param_stats, test.status);
		} else if (!test_case->generate_params) {
			/* Non-parameterised test. */
			test_case->status = KUNIT_SKIPPED;
			kunit_run_case_catch_errors(suite, test_case, &test);
			kunit_update_stats(&param_stats, test.status);
		} else {
			kunit_init_parent_param_test(test_case, &test);
	kunit_init_parent_param_test(test_case, test);
	if (test_case->status == KUNIT_FAILURE) {
				kunit_update_stats(&param_stats, test.status);
				goto test_case_end;
		kunit_update_stats(param_stats, test->status);
		return;
	}
	/* Get initial param. */
	param_desc[0] = '\0';
	/* TODO: Make generate_params try-catch */
			curr_param = test_case->generate_params(&test, NULL, param_desc);
	curr_param = test_case->generate_params(test, NULL, param_desc);
	test_case->status = KUNIT_SKIPPED;
			kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
	kunit_log(KERN_INFO, test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
		  "KTAP version 1\n");
			kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
	kunit_log(KERN_INFO, test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
		  "# Subtest: %s", test_case->name);
			if (test.params_array.params &&
	if (test->params_array.params &&
	    test_case->generate_params == kunit_array_gen_params) {
				kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT
		kunit_log(KERN_INFO, test, KUNIT_SUBTEST_INDENT
			  KUNIT_SUBTEST_INDENT "1..%zd\n",
					  test.params_array.num_params);
			  test->params_array.num_params);
	}

	while (curr_param) {
		struct kunit param_test = {
			.param_value = curr_param,
					.param_index = ++test.param_index,
					.parent = &test,
			.param_index = ++test->param_index,
			.parent = test,
		};
		kunit_init_test(&param_test, test_case->name, NULL);
		param_test.log = test_case->log;
@@ -760,11 +733,11 @@ int kunit_run_tests(struct kunit_suite *suite)
				      param_desc,
				      param_test.status_comment);

				kunit_update_stats(&param_stats, param_test.status);
		kunit_update_stats(param_stats, param_test.status);

		/* Get next param. */
		param_desc[0] = '\0';
				curr_param = test_case->generate_params(&test, curr_param,
		curr_param = test_case->generate_params(test, curr_param,
							param_desc);
	}
	/*
@@ -772,28 +745,74 @@ int kunit_run_tests(struct kunit_suite *suite)
	 * for it we can't reuse kunit_try_run_cleanup for this yet.
	 */
	if (test_case->param_exit)
				test_case->param_exit(&test);
		test_case->param_exit(test);
	/* TODO: Put this kunit_cleanup into a try-catch. */
			kunit_cleanup(&test);
	kunit_cleanup(test);
}

static noinline_for_stack void
kunit_run_one_test(struct kunit_suite *suite, struct kunit_case *test_case,
		   struct kunit_result_stats *suite_stats,
		   struct kunit_result_stats *total_stats)
{
	struct kunit test = { .param_value = NULL, .param_index = 0 };
	struct kunit_result_stats param_stats = { 0 };

	kunit_init_test(&test, test_case->name, test_case->log);
	if (test_case->status == KUNIT_SKIPPED) {
		/* Test marked as skip */
		test.status = KUNIT_SKIPPED;
		kunit_update_stats(&param_stats, test.status);
	} else if (!test_case->generate_params) {
		/* Non-parameterised test. */
		test_case->status = KUNIT_SKIPPED;
		kunit_run_case_catch_errors(suite, test_case, &test);
		kunit_update_stats(&param_stats, test.status);
	} else {
		kunit_run_param_test(suite, test_case, &test, suite_stats,
				     total_stats, &param_stats);
	}
test_case_end:
	kunit_print_attr((void *)test_case, true, KUNIT_LEVEL_CASE);

		kunit_print_test_stats(&test, param_stats);
	kunit_print_test_stats(&test, &param_stats);

	kunit_print_ok_not_ok(&test, KUNIT_LEVEL_CASE, test_case->status,
			      kunit_test_case_num(suite, test_case),
			      test_case->name,
			      test.status_comment);

		kunit_update_stats(&suite_stats, test_case->status);
		kunit_accumulate_stats(&total_stats, param_stats);
	kunit_update_stats(suite_stats, test_case->status);
	kunit_accumulate_stats(total_stats, param_stats);
}


int kunit_run_tests(struct kunit_suite *suite)
{
	struct kunit_case *test_case;
	struct kunit_result_stats suite_stats = { 0 };
	struct kunit_result_stats total_stats = { 0 };

	/* Taint the kernel so we know we've run tests. */
	add_taint(TAINT_TEST, LOCKDEP_STILL_OK);

	if (suite->suite_init) {
		suite->suite_init_err = suite->suite_init(suite);
		if (suite->suite_init_err) {
			kunit_err(suite, KUNIT_SUBTEST_INDENT
				  "# failed to initialize (%d)", suite->suite_init_err);
			goto suite_end;
		}
	}

	kunit_print_suite_start(suite);

	kunit_suite_for_each_test_case(suite, test_case)
		kunit_run_one_test(suite, test_case, &suite_stats, &total_stats);

	if (suite->suite_exit)
		suite->suite_exit(suite);

	kunit_print_suite_stats(suite, suite_stats, total_stats);
	kunit_print_suite_stats(suite, &suite_stats, &total_stats);
suite_end:
	kunit_print_suite_end(suite);

+8 −0
Original line number Diff line number Diff line
@@ -14,6 +14,10 @@
/// Public but hidden since it should only be used from KUnit generated code.
#[doc(hidden)]
pub fn err(args: fmt::Arguments<'_>) {
    // `args` is unused if `CONFIG_PRINTK` is not set - this avoids a build-time warning.
    #[cfg(not(CONFIG_PRINTK))]
    let _ = args;

    // SAFETY: The format string is null-terminated and the `%pA` specifier matches the argument we
    // are passing.
    #[cfg(CONFIG_PRINTK)]
@@ -30,6 +34,10 @@ pub fn err(args: fmt::Arguments<'_>) {
/// Public but hidden since it should only be used from KUnit generated code.
#[doc(hidden)]
pub fn info(args: fmt::Arguments<'_>) {
    // `args` is unused if `CONFIG_PRINTK` is not set - this avoids a build-time warning.
    #[cfg(not(CONFIG_PRINTK))]
    let _ = args;

    // SAFETY: The format string is null-terminated and the `%pA` specifier matches the argument we
    // are passing.
    #[cfg(CONFIG_PRINTK)]
+4 −2
Original line number Diff line number Diff line
@@ -346,8 +346,10 @@ class LinuxSourceTree:
		return self.validate_config(build_dir)

	def run_kernel(self, args: Optional[List[str]]=None, build_dir: str='', filter_glob: str='', filter: str='', filter_action: Optional[str]=None, timeout: Optional[int]=None) -> Iterator[str]:
		if not args:
			args = []
		# Copy to avoid mutating the caller-supplied list. exec_tests() reuses
		# the same args across repeated run_kernel() calls (e.g. --run_isolated),
		# so appending to the original would accumulate stale flags on each call.
		args = list(args) if args else []
		if filter_glob:
			args.append('kunit.filter_glob=' + filter_glob)
		if filter:
Loading