1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Copyright (c) 2024 Meta Platforms, Inc. and affiliates.
4 * Copyright (c) 2024 David Vernet <dvernet@meta.com>
5 * Copyright (c) 2024 Tejun Heo <tj@kernel.org>
14 const char help_fmt
[] =
15 "The runner for sched_ext tests.\n"
17 "The runner is statically linked against all testcases, and runs them all serially.\n"
18 "It's required for the testcases to be serial, as only a single host-wide sched_ext\n"
19 "scheduler may be loaded at any given time."
21 "Usage: %s [-t TEST] [-h]\n"
23 " -t TEST Only run tests whose name includes this string\n"
24 " -s Include print output for skipped tests\n"
25 " -q Don't print the test descriptions during run\n"
26 " -h Display this help and exit\n";
28 static volatile int exit_req
;
29 static bool quiet
, print_skipped
;
31 #define MAX_SCX_TESTS 2048
33 static struct scx_test __scx_tests
[MAX_SCX_TESTS
];
34 static unsigned __scx_num_tests
= 0;
36 static void sigint_handler(int simple
)
41 static void print_test_preamble(const struct scx_test
*test
, bool quiet
)
43 printf("===== START =====\n");
44 printf("TEST: %s\n", test
->name
);
46 printf("DESCRIPTION: %s\n", test
->description
);
50 static const char *status_to_result(enum scx_test_status status
)
63 static void print_test_result(const struct scx_test
*test
,
64 enum scx_test_status status
,
67 const char *result
= status_to_result(status
);
68 const char *directive
= status
== SCX_TEST_SKIP
? "SKIP " : "";
70 printf("%s %u %s # %s\n", result
, testnum
, test
->name
, directive
);
71 printf("===== END =====\n");
74 static bool should_skip_test(const struct scx_test
*test
, const char * filter
)
76 return !strstr(test
->name
, filter
);
79 static enum scx_test_status
run_test(const struct scx_test
*test
)
81 enum scx_test_status status
;
85 status
= test
->setup(&context
);
86 if (status
!= SCX_TEST_PASS
)
90 status
= test
->run(context
);
93 test
->cleanup(context
);
98 static bool test_valid(const struct scx_test
*test
)
101 fprintf(stderr
, "NULL test detected\n");
107 "Test with no name found. Must specify test name.\n");
111 if (!test
->description
) {
112 fprintf(stderr
, "Test %s requires description.\n", test
->name
);
117 fprintf(stderr
, "Test %s has no run() callback\n", test
->name
);
124 int main(int argc
, char **argv
)
126 const char *filter
= NULL
;
127 unsigned testnum
= 0, i
;
128 unsigned passed
= 0, skipped
= 0, failed
= 0;
131 signal(SIGINT
, sigint_handler
);
132 signal(SIGTERM
, sigint_handler
);
134 libbpf_set_strict_mode(LIBBPF_STRICT_ALL
);
136 while ((opt
= getopt(argc
, argv
, "qst:h")) != -1) {
142 print_skipped
= true;
148 fprintf(stderr
, help_fmt
, basename(argv
[0]));
153 for (i
= 0; i
< __scx_num_tests
; i
++) {
154 enum scx_test_status status
;
155 struct scx_test
*test
= &__scx_tests
[i
];
157 if (filter
&& should_skip_test(test
, filter
)) {
159 * Printing the skipped tests and their preambles can
160 * add a lot of noise to the runner output. Printing
161 * this is only really useful for CI, so let's skip it
165 print_test_preamble(test
, quiet
);
166 print_test_result(test
, SCX_TEST_SKIP
, ++testnum
);
171 print_test_preamble(test
, quiet
);
172 status
= run_test(test
);
173 print_test_result(test
, status
, ++testnum
);
186 printf("\n\n=============================\n\n");
187 printf("RESULTS:\n\n");
188 printf("PASSED: %u\n", passed
);
189 printf("SKIPPED: %u\n", skipped
);
190 printf("FAILED: %u\n", failed
);
195 void scx_test_register(struct scx_test
*test
)
197 SCX_BUG_ON(!test_valid(test
), "Invalid test found");
198 SCX_BUG_ON(__scx_num_tests
>= MAX_SCX_TESTS
, "Maximum tests exceeded");
200 __scx_tests
[__scx_num_tests
++] = *test
;