Skip to content

Commit 63d0a91

Browse files
ujwal-jain-googleshuahkh
authored andcommitted
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>
1 parent e42ad39 commit 63d0a91

5 files changed

Lines changed: 56 additions & 33 deletions

File tree

include/kunit/try-catch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct kunit_try_catch {
4747
int try_result;
4848
kunit_try_catch_func_t try;
4949
kunit_try_catch_func_t catch;
50+
unsigned long timeout;
5051
void *context;
5152
};
5253

lib/kunit/kunit-test.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
4444
kunit_try_catch_init(try_catch,
4545
test,
4646
kunit_test_successful_try,
47-
kunit_test_no_catch);
47+
kunit_test_no_catch,
48+
300 * msecs_to_jiffies(MSEC_PER_SEC));
4849
kunit_try_catch_run(try_catch, test);
4950

5051
KUNIT_EXPECT_TRUE(test, ctx->function_called);
@@ -76,7 +77,8 @@ static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test)
7677
kunit_try_catch_init(try_catch,
7778
test,
7879
kunit_test_unsuccessful_try,
79-
kunit_test_catch);
80+
kunit_test_catch,
81+
300 * msecs_to_jiffies(MSEC_PER_SEC));
8082
kunit_try_catch_run(try_catch, test);
8183

8284
KUNIT_EXPECT_TRUE(test, ctx->function_called);
@@ -130,7 +132,8 @@ static void kunit_test_fault_null_dereference(struct kunit *test)
130132
kunit_try_catch_init(try_catch,
131133
test,
132134
kunit_test_null_dereference,
133-
kunit_test_catch);
135+
kunit_test_catch,
136+
300 * msecs_to_jiffies(MSEC_PER_SEC));
134137
kunit_try_catch_run(try_catch, test);
135138

136139
KUNIT_EXPECT_EQ(test, try_catch->try_result, -EINTR);

lib/kunit/test.c

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,46 @@ static void kunit_run_case_check_speed(struct kunit *test,
373373
duration.tv_sec, duration.tv_nsec);
374374
}
375375

376+
/* Returns timeout multiplier based on speed.
377+
* DEFAULT: 1
378+
* KUNIT_SPEED_SLOW: 3
379+
* KUNIT_SPEED_VERY_SLOW: 12
380+
*/
381+
static int kunit_timeout_mult(enum kunit_speed speed)
382+
{
383+
switch (speed) {
384+
case KUNIT_SPEED_SLOW:
385+
return 3;
386+
case KUNIT_SPEED_VERY_SLOW:
387+
return 12;
388+
default:
389+
return 1;
390+
}
391+
}
392+
393+
static unsigned long kunit_test_timeout(struct kunit_suite *suite, struct kunit_case *test_case)
394+
{
395+
int mult = 1;
396+
/*
397+
* TODO: Make the default (base) timeout configurable, so that users with
398+
* particularly slow or fast machines can successfully run tests, while
399+
* still taking advantage of the relative speed.
400+
*/
401+
unsigned long default_timeout = 300;
402+
403+
/*
404+
* The default test timeout is 300 seconds and will be adjusted by mult
405+
* based on the test speed. The test speed will be overridden by the
406+
* innermost test component.
407+
*/
408+
if (suite->attr.speed != KUNIT_SPEED_UNSET)
409+
mult = kunit_timeout_mult(suite->attr.speed);
410+
if (test_case->attr.speed != KUNIT_SPEED_UNSET)
411+
mult = kunit_timeout_mult(test_case->attr.speed);
412+
return mult * default_timeout * msecs_to_jiffies(MSEC_PER_SEC);
413+
}
414+
415+
376416
/*
377417
* Initializes and runs test case. Does not clean up or do post validations.
378418
*/
@@ -527,7 +567,8 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
527567
kunit_try_catch_init(try_catch,
528568
test,
529569
kunit_try_run_case,
530-
kunit_catch_run_case);
570+
kunit_catch_run_case,
571+
kunit_test_timeout(suite, test_case));
531572
context.test = test;
532573
context.suite = suite;
533574
context.test_case = test_case;
@@ -537,7 +578,8 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
537578
kunit_try_catch_init(try_catch,
538579
test,
539580
kunit_try_run_case_cleanup,
540-
kunit_catch_run_case_cleanup);
581+
kunit_catch_run_case_cleanup,
582+
kunit_test_timeout(suite, test_case));
541583
kunit_try_catch_run(try_catch, &context);
542584

543585
/* Propagate the parameter result to the test case. */

lib/kunit/try-catch-impl.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ struct kunit;
1717
static inline void kunit_try_catch_init(struct kunit_try_catch *try_catch,
1818
struct kunit *test,
1919
kunit_try_catch_func_t try,
20-
kunit_try_catch_func_t catch)
20+
kunit_try_catch_func_t catch,
21+
unsigned long timeout)
2122
{
2223
try_catch->test = test;
2324
try_catch->try = try;
2425
try_catch->catch = catch;
26+
try_catch->timeout = timeout;
2527
}
2628

2729
#endif /* _KUNIT_TRY_CATCH_IMPL_H */

lib/kunit/try-catch.c

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,31 +34,6 @@ static int kunit_generic_run_threadfn_adapter(void *data)
3434
return 0;
3535
}
3636

37-
static unsigned long kunit_test_timeout(void)
38-
{
39-
/*
40-
* TODO(brendanhiggins@google.com): We should probably have some type of
41-
* variable timeout here. The only question is what that timeout value
42-
* should be.
43-
*
44-
* The intention has always been, at some point, to be able to label
45-
* tests with some type of size bucket (unit/small, integration/medium,
46-
* large/system/end-to-end, etc), where each size bucket would get a
47-
* default timeout value kind of like what Bazel does:
48-
* https://docs.bazel.build/versions/master/be/common-definitions.html#test.size
49-
* There is still some debate to be had on exactly how we do this. (For
50-
* one, we probably want to have some sort of test runner level
51-
* timeout.)
52-
*
53-
* For more background on this topic, see:
54-
* https://mike-bland.com/2011/11/01/small-medium-large.html
55-
*
56-
* If tests timeout due to exceeding sysctl_hung_task_timeout_secs,
57-
* the task will be killed and an oops generated.
58-
*/
59-
return 300 * msecs_to_jiffies(MSEC_PER_SEC); /* 5 min */
60-
}
61-
6237
void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
6338
{
6439
struct kunit *test = try_catch->test;
@@ -85,8 +60,8 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
8560
task_done = task_struct->vfork_done;
8661
wake_up_process(task_struct);
8762

88-
time_remaining = wait_for_completion_timeout(task_done,
89-
kunit_test_timeout());
63+
time_remaining = wait_for_completion_timeout(
64+
task_done, try_catch->timeout);
9065
if (time_remaining == 0) {
9166
try_catch->try_result = -ETIMEDOUT;
9267
kthread_stop(task_struct);

0 commit comments

Comments
 (0)