/* * Hook to fail the current test and print an error message to the log.
*/ void __printf(3, 4) __kunit_fail_current_test_impl(constchar *file, int line, constchar*fmt, ...)
{
va_list args; int len; char *buffer;
if (!current->kunit_test) return;
kunit_set_failure(current->kunit_test);
/* kunit_err() only accepts literals, so evaluate the args first. */
va_start(args, fmt);
len = vsnprintf(NULL, 0, fmt, args) + 1;
va_end(args);
buffer = kunit_kmalloc(current->kunit_test, len, GFP_KERNEL); if (!buffer) return;
/* * Configure the base timeout.
*/ staticunsignedlong kunit_base_timeout = CONFIG_KUNIT_DEFAULT_TIMEOUT;
module_param_named(timeout, kunit_base_timeout, ulong, 0644);
MODULE_PARM_DESC(timeout, "Set the base timeout for Kunit test cases");
/* * KUnit statistic mode: * 0 - disabled * 1 - only when there is more than one subtest * 2 - enabled
*/ staticint kunit_stats_enabled = 1;
module_param_named(stats_enabled, kunit_stats_enabled, int, 0644);
MODULE_PARM_DESC(stats_enabled, "Print test stats: never (0), only for multiple subtests (1), or always (2)");
/* Currently supported test levels */ enum {
KUNIT_LEVEL_SUITE = 0,
KUNIT_LEVEL_CASE,
KUNIT_LEVEL_CASE_PARAM,
};
staticvoid kunit_print_suite_start(struct kunit_suite *suite)
{ /* * We do not log the test suite header as doing so would * mean debugfs display would consist of the test suite * header prior to individual test results. * Hence directly printk the suite status, and we will * separately seq_printf() the suite header for the debugfs * representation.
*/
pr_info(KUNIT_SUBTEST_INDENT "KTAP version 1\n");
pr_info(KUNIT_SUBTEST_INDENT "# Subtest: %s\n",
suite->name);
kunit_print_attr((void *)suite, false, KUNIT_LEVEL_CASE);
pr_info(KUNIT_SUBTEST_INDENT "1..%zd\n",
kunit_suite_num_test_cases(suite));
}
/* * When test is NULL assume that results are from the suite * and today suite results are expected at level 0 only.
*/
WARN(!test && test_level, "suite test level can't be %u!\n", test_level);
/* * We do not log the test suite results as doing so would * mean debugfs display would consist of an incorrect test * number. Hence directly printk the suite result, and we will * separately seq_printf() the suite results for the debugfs * representation.
*/ if (!test)
pr_info("%s %zd %s%s%s\n",
kunit_status_to_ok_not_ok(status),
test_number, description, directive_header,
directive_body); else
kunit_log(KERN_INFO, test, "%*s%s %zd %s%s%s",
KUNIT_INDENT_LEN * test_level, "",
kunit_status_to_ok_not_ok(status),
test_number, description, directive_header,
directive_body);
}
void __noreturn __kunit_abort(struct kunit *test)
{
kunit_try_catch_throw(&test->try_catch); /* Does not return. */
/* * Throw could not abort from test. * * XXX: we should never reach this line! As kunit_try_catch_throw is * marked __noreturn.
*/
WARN_ONCE(true, "Throw could not abort from test!\n");
}
EXPORT_SYMBOL_GPL(__kunit_abort);
if (timespec64_compare(&duration, &slow_thr) < 0) return;
if (speed == KUNIT_SPEED_VERY_SLOW || speed == KUNIT_SPEED_SLOW) return;
kunit_warn(test, "Test should be marked slow (runtime: %lld.%09lds)",
duration.tv_sec, duration.tv_nsec);
}
/* Returns timeout multiplier based on speed. * DEFAULT: 1 * KUNIT_SPEED_SLOW: 3 * KUNIT_SPEED_VERY_SLOW: 12
*/ staticint kunit_timeout_mult(enum kunit_speed speed)
{ switch (speed) { case KUNIT_SPEED_SLOW: return 3; case KUNIT_SPEED_VERY_SLOW: return 12; default: return 1;
}
}
staticunsignedlong kunit_test_timeout(struct kunit_suite *suite, struct kunit_case *test_case)
{ int mult = 1;
/* * The default test timeout is 300 seconds and will be adjusted by mult * based on the test speed. The test speed will be overridden by the * innermost test component.
*/ if (suite->attr.speed != KUNIT_SPEED_UNSET)
mult = kunit_timeout_mult(suite->attr.speed); if (test_case->attr.speed != KUNIT_SPEED_UNSET)
mult = kunit_timeout_mult(test_case->attr.speed); return mult * kunit_base_timeout * msecs_to_jiffies(MSEC_PER_SEC);
}
/* * Initializes and runs test case. Does not clean up or do post validations.
*/ staticvoid kunit_run_case_internal(struct kunit *test, struct kunit_suite *suite, struct kunit_case *test_case)
{ struct timespec64 start, end;
if (suite->init) { int ret;
ret = suite->init(test); if (ret) {
kunit_err(test, "failed to initialize: %d\n", ret);
kunit_set_failure(test); return;
}
}
/* * Performs post validations and cleanup after a test case was run. * XXX: Should ONLY BE CALLED AFTER kunit_run_case_internal!
*/ staticvoid kunit_run_case_cleanup(struct kunit *test, struct kunit_suite *suite)
{ if (suite->exit)
suite->exit(test);
/* * kunit_run_case_internal may encounter a fatal error; if it does, * abort will be called, this thread will exit, and finally the parent * thread will resume control and handle any necessary clean up.
*/
kunit_run_case_internal(test, suite, test_case);
}
/* It is always a failure if cleanup aborts. */
kunit_set_failure(test);
if (try_exit_code) { /* * Test case could not finish, we have no idea what state it is * in, so don't do clean up.
*/ if (try_exit_code == -ETIMEDOUT) {
kunit_err(test, "test case cleanup timed out\n"); /* * Unknown internal error occurred preventing test case from * running, so there is nothing to clean up.
*/
} else {
kunit_err(test, "internal error occurred during test case cleanup: %d\n",
try_exit_code);
} return;
}
kunit_err(test, "test aborted during cleanup. continuing without cleaning up\n");
}
if (try_exit_code) {
kunit_set_failure(test); /* * Test case could not finish, we have no idea what state it is * in, so don't do clean up.
*/ if (try_exit_code == -ETIMEDOUT) {
kunit_err(test, "test case timed out\n"); /* * Unknown internal error occurred preventing test case from * running, so there is nothing to clean up.
*/
} else {
kunit_err(test, "internal error occurred preventing test case from running: %d\n",
try_exit_code);
} return;
}
}
/* * Performs all logic to run a test case. It also catches most errors that * occur in a test case and reports them as failures.
*/ staticvoid kunit_run_case_catch_errors(struct kunit_suite *suite, struct kunit_case *test_case, struct kunit *test)
{ struct kunit_try_catch_context context; struct kunit_try_catch *try_catch;
/* Now run the cleanup */
kunit_try_catch_init(try_catch,
test,
kunit_try_run_case_cleanup,
kunit_catch_run_case_cleanup,
kunit_test_timeout(suite, test_case));
kunit_try_catch_run(try_catch, &context);
/* Propagate the parameter result to the test case. */ if (test->status == KUNIT_FAILURE)
test_case->status = KUNIT_FAILURE; elseif (test_case->status != KUNIT_FAILURE && test->status == KUNIT_SUCCESS)
test_case->status = KUNIT_SUCCESS;
}
/* Use mutex lock to guard against running tests concurrently. */ if (mutex_lock_interruptible(&kunit_run_lock)) {
pr_err("kunit: test interrupted\n"); return -EINTR;
}
static_branch_inc(&kunit_running);
for (i = 0; i < num_suites; i++) {
kunit_init_suite(suites[i]); if (run_tests)
kunit_run_tests(suites[i]);
}
/* * Check if the start address is a valid virtual address to detect * if the module load sequence has failed and the suite set has not * been initialized and filtered.
*/ if (!suite_set.start || !virt_addr_valid(suite_set.start)) return;
if (!action)
__kunit_test_suites_exit(mod->kunit_suites,
mod->num_kunit_suites);
switch (val) { case MODULE_STATE_LIVE:
kunit_module_init(mod); break; case MODULE_STATE_GOING:
kunit_module_exit(mod); break; case MODULE_STATE_COMING: break; case MODULE_STATE_UNFORMED: break;
}
/* * test->resources is a stack - each allocation must be freed in the * reverse order from which it was added since one resource may depend * on another for its entire lifetime. * Also, we cannot use the normal list_for_each constructs, even the * safe ones because *arbitrary* nodes may be deleted when * kunit_resource_free is called; the list_for_each_safe variants only * protect against the current node being deleted, not the next.
*/ while (true) {
spin_lock_irqsave(&test->lock, flags); if (list_empty(&test->resources)) {
spin_unlock_irqrestore(&test->lock, flags); break;
}
res = list_last_entry(&test->resources, struct kunit_resource,
node); /* * Need to unlock here as a resource may remove another * resource, and this can't happen if the test->lock * is held.
*/
spin_unlock_irqrestore(&test->lock, flags);
kunit_remove_resource(test, res);
}
current->kunit_test = NULL;
}
EXPORT_SYMBOL_GPL(kunit_cleanup);
MODULE_DESCRIPTION("Base unit test (KUnit) API");
MODULE_LICENSE("GPL v2");
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.17Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.