Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199// SPDX-License-Identifier: GPL-2.0/* * KUnit test for suppressing warning tracebacks. * * Copyright (C) 2024, Guenter Roeck * Author: Guenter Roeck <linux@roeck-us.net> */
#include <kunit/test.h>#include <linux/bug.h>#include <linux/completion.h>#include <linux/kthread.h>
static void backtrace_suppression_test_warn_direct(struct kunit *test){ if (!IS_ENABLED(CONFIG_BUG)) kunit_skip(test, "requires CONFIG_BUG");
kunit_warning_suppress(test) { WARN(1, "This backtrace should be suppressed"); /* * Count must be checked inside the scope; the handle * is not accessible after the block exits. */ KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1); } KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());}
static noinline void trigger_backtrace_warn(void){ WARN(1, "This backtrace should be suppressed");}
static void backtrace_suppression_test_warn_indirect(struct kunit *test){ if (!IS_ENABLED(CONFIG_BUG)) kunit_skip(test, "requires CONFIG_BUG");
kunit_warning_suppress(test) { trigger_backtrace_warn(); KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1); }}
static void backtrace_suppression_test_warn_multi(struct kunit *test){ if (!IS_ENABLED(CONFIG_BUG)) kunit_skip(test, "requires CONFIG_BUG");
kunit_warning_suppress(test) { WARN(1, "This backtrace should be suppressed"); trigger_backtrace_warn(); KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 2); }}
static void backtrace_suppression_test_warn_on_direct(struct kunit *test){ if (!IS_ENABLED(CONFIG_BUG)) kunit_skip(test, "requires CONFIG_BUG"); if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE) && !IS_ENABLED(CONFIG_KALLSYMS)) kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE or CONFIG_KALLSYMS");
kunit_warning_suppress(test) { WARN_ON(1); KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1); }}
static noinline void trigger_backtrace_warn_on(void){ WARN_ON(1);}
static void backtrace_suppression_test_warn_on_indirect(struct kunit *test){ if (!IS_ENABLED(CONFIG_BUG)) kunit_skip(test, "requires CONFIG_BUG"); if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE)) kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE");
kunit_warning_suppress(test) { trigger_backtrace_warn_on(); KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1); }}
static void backtrace_suppression_test_count(struct kunit *test){ if (!IS_ENABLED(CONFIG_BUG)) kunit_skip(test, "requires CONFIG_BUG");
kunit_warning_suppress(test) { KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 0);
WARN(1, "suppressed"); KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
WARN(1, "suppressed again"); KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 2); }}
static void backtrace_suppression_test_active_state(struct kunit *test){ KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());
kunit_warning_suppress(test) { KUNIT_EXPECT_TRUE(test, kunit_has_active_suppress_warning()); }
KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());
kunit_warning_suppress(test) { KUNIT_EXPECT_TRUE(test, kunit_has_active_suppress_warning()); }
KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());}
static void backtrace_suppression_test_multi_scope(struct kunit *test){ struct kunit_suppressed_warning *sw1, *sw2;
if (!IS_ENABLED(CONFIG_BUG)) kunit_skip(test, "requires CONFIG_BUG"); if (!IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE)) kunit_skip(test, "requires CONFIG_DEBUG_BUGVERBOSE");
sw1 = kunit_start_suppress_warning(test); trigger_backtrace_warn_on(); WARN(1, "suppressed by sw1"); kunit_end_suppress_warning(test, sw1);
sw2 = kunit_start_suppress_warning(test); WARN(1, "suppressed by sw2"); kunit_end_suppress_warning(test, sw2);
KUNIT_EXPECT_EQ(test, kunit_suppressed_warning_count(sw1), 2); KUNIT_EXPECT_EQ(test, kunit_suppressed_warning_count(sw2), 1);}
struct cross_kthread_data { bool was_active; struct completion done;};
static int cross_kthread_fn(void *data){ struct cross_kthread_data *d = data;
d->was_active = kunit_has_active_suppress_warning(); complete(&d->done); while (!kthread_should_stop()) schedule(); return 0;}
static void backtrace_suppression_test_cross_kthread(struct kunit *test){ struct cross_kthread_data data; struct task_struct *task;
data.was_active = false; init_completion(&data.done);
kunit_warning_suppress(test) { task = kthread_run(cross_kthread_fn, &data, "kunit-cross-test"); KUNIT_ASSERT_FALSE(test, IS_ERR(task)); wait_for_completion(&data.done); kthread_stop(task); }
KUNIT_EXPECT_FALSE(test, data.was_active);}
static struct kunit_case backtrace_suppression_test_cases[] = { KUNIT_CASE(backtrace_suppression_test_warn_direct), KUNIT_CASE(backtrace_suppression_test_warn_indirect), KUNIT_CASE(backtrace_suppression_test_warn_multi), KUNIT_CASE(backtrace_suppression_test_warn_on_direct), KUNIT_CASE(backtrace_suppression_test_warn_on_indirect), KUNIT_CASE(backtrace_suppression_test_count), KUNIT_CASE(backtrace_suppression_test_active_state), KUNIT_CASE(backtrace_suppression_test_multi_scope), KUNIT_CASE(backtrace_suppression_test_cross_kthread), {}};
static struct kunit_suite backtrace_suppression_test_suite = { .name = "backtrace-suppression-test", .test_cases = backtrace_suppression_test_cases,};kunit_test_suites(&backtrace_suppression_test_suite);
MODULE_LICENSE("GPL");MODULE_DESCRIPTION("KUnit test to verify warning backtrace suppression");