mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
kunit: Adjust kunit_test timeout based on test_{suite,case} speed
Currently, the in-kernel kunit test case timeout is 300 seconds. (There is a separate timeout mechanism for the whole test execution in kunit.py, but that's unrelated.) However, tests marked 'slow' or 'very slow' may timeout, particularly on slower machines. Implement a multiplier to the test-case timeout, so that slower tests have longer to complete: - DEFAULT -> 1x default timeout - KUNIT_SPEED_SLOW -> 3x default timeout - KUNIT_SPEED_VERY_SLOW -> 12x default timeout A further change is planned to allow user configuration of the default/base timeout to allow people with faster or slower machines to adjust these to their use-cases. Link: https://lore.kernel.org/r/20250614084711.2654593-2-davidgow@google.com Signed-off-by: Ujwal Jain <ujwaljain@google.com> Co-developed-by: David Gow <davidgow@google.com> Signed-off-by: David Gow <davidgow@google.com> Reviewed-by: Rae Moar <rmoar@google.com> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
This commit is contained in:
parent
e42ad39318
commit
63d0a91231
5 changed files with 56 additions and 33 deletions
|
@ -47,6 +47,7 @@ struct kunit_try_catch {
|
|||
int try_result;
|
||||
kunit_try_catch_func_t try;
|
||||
kunit_try_catch_func_t catch;
|
||||
unsigned long timeout;
|
||||
void *context;
|
||||
};
|
||||
|
||||
|
|
|
@ -44,7 +44,8 @@ static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
|
|||
kunit_try_catch_init(try_catch,
|
||||
test,
|
||||
kunit_test_successful_try,
|
||||
kunit_test_no_catch);
|
||||
kunit_test_no_catch,
|
||||
300 * msecs_to_jiffies(MSEC_PER_SEC));
|
||||
kunit_try_catch_run(try_catch, test);
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, ctx->function_called);
|
||||
|
@ -76,7 +77,8 @@ static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test)
|
|||
kunit_try_catch_init(try_catch,
|
||||
test,
|
||||
kunit_test_unsuccessful_try,
|
||||
kunit_test_catch);
|
||||
kunit_test_catch,
|
||||
300 * msecs_to_jiffies(MSEC_PER_SEC));
|
||||
kunit_try_catch_run(try_catch, test);
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, ctx->function_called);
|
||||
|
@ -130,7 +132,8 @@ static void kunit_test_fault_null_dereference(struct kunit *test)
|
|||
kunit_try_catch_init(try_catch,
|
||||
test,
|
||||
kunit_test_null_dereference,
|
||||
kunit_test_catch);
|
||||
kunit_test_catch,
|
||||
300 * msecs_to_jiffies(MSEC_PER_SEC));
|
||||
kunit_try_catch_run(try_catch, test);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, try_catch->try_result, -EINTR);
|
||||
|
|
|
@ -373,6 +373,46 @@ static void kunit_run_case_check_speed(struct kunit *test,
|
|||
duration.tv_sec, duration.tv_nsec);
|
||||
}
|
||||
|
||||
/* Returns timeout multiplier based on speed.
|
||||
* DEFAULT: 1
|
||||
* KUNIT_SPEED_SLOW: 3
|
||||
* KUNIT_SPEED_VERY_SLOW: 12
|
||||
*/
|
||||
static int 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;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long kunit_test_timeout(struct kunit_suite *suite, struct kunit_case *test_case)
|
||||
{
|
||||
int mult = 1;
|
||||
/*
|
||||
* TODO: Make the default (base) timeout configurable, so that users with
|
||||
* particularly slow or fast machines can successfully run tests, while
|
||||
* still taking advantage of the relative speed.
|
||||
*/
|
||||
unsigned long default_timeout = 300;
|
||||
|
||||
/*
|
||||
* 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 * default_timeout * msecs_to_jiffies(MSEC_PER_SEC);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initializes and runs test case. Does not clean up or do post validations.
|
||||
*/
|
||||
|
@ -527,7 +567,8 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
|
|||
kunit_try_catch_init(try_catch,
|
||||
test,
|
||||
kunit_try_run_case,
|
||||
kunit_catch_run_case);
|
||||
kunit_catch_run_case,
|
||||
kunit_test_timeout(suite, test_case));
|
||||
context.test = test;
|
||||
context.suite = suite;
|
||||
context.test_case = test_case;
|
||||
|
@ -537,7 +578,8 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
|
|||
kunit_try_catch_init(try_catch,
|
||||
test,
|
||||
kunit_try_run_case_cleanup,
|
||||
kunit_catch_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. */
|
||||
|
|
|
@ -17,11 +17,13 @@ struct kunit;
|
|||
static inline void kunit_try_catch_init(struct kunit_try_catch *try_catch,
|
||||
struct kunit *test,
|
||||
kunit_try_catch_func_t try,
|
||||
kunit_try_catch_func_t catch)
|
||||
kunit_try_catch_func_t catch,
|
||||
unsigned long timeout)
|
||||
{
|
||||
try_catch->test = test;
|
||||
try_catch->try = try;
|
||||
try_catch->catch = catch;
|
||||
try_catch->timeout = timeout;
|
||||
}
|
||||
|
||||
#endif /* _KUNIT_TRY_CATCH_IMPL_H */
|
||||
|
|
|
@ -34,31 +34,6 @@ static int kunit_generic_run_threadfn_adapter(void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long kunit_test_timeout(void)
|
||||
{
|
||||
/*
|
||||
* TODO(brendanhiggins@google.com): We should probably have some type of
|
||||
* variable timeout here. The only question is what that timeout value
|
||||
* should be.
|
||||
*
|
||||
* The intention has always been, at some point, to be able to label
|
||||
* tests with some type of size bucket (unit/small, integration/medium,
|
||||
* large/system/end-to-end, etc), where each size bucket would get a
|
||||
* default timeout value kind of like what Bazel does:
|
||||
* https://docs.bazel.build/versions/master/be/common-definitions.html#test.size
|
||||
* There is still some debate to be had on exactly how we do this. (For
|
||||
* one, we probably want to have some sort of test runner level
|
||||
* timeout.)
|
||||
*
|
||||
* For more background on this topic, see:
|
||||
* https://mike-bland.com/2011/11/01/small-medium-large.html
|
||||
*
|
||||
* If tests timeout due to exceeding sysctl_hung_task_timeout_secs,
|
||||
* the task will be killed and an oops generated.
|
||||
*/
|
||||
return 300 * msecs_to_jiffies(MSEC_PER_SEC); /* 5 min */
|
||||
}
|
||||
|
||||
void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
|
||||
{
|
||||
struct kunit *test = try_catch->test;
|
||||
|
@ -85,8 +60,8 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
|
|||
task_done = task_struct->vfork_done;
|
||||
wake_up_process(task_struct);
|
||||
|
||||
time_remaining = wait_for_completion_timeout(task_done,
|
||||
kunit_test_timeout());
|
||||
time_remaining = wait_for_completion_timeout(
|
||||
task_done, try_catch->timeout);
|
||||
if (time_remaining == 0) {
|
||||
try_catch->try_result = -ETIMEDOUT;
|
||||
kthread_stop(task_struct);
|
||||
|
|
Loading…
Add table
Reference in a new issue