Major overhaul to testing infrastructure
[akaros.git] / kern / include / ktest.h
1 #ifndef ROS_INC_KTEST_H
2 #define ROS_INC_KTEST_H
3
4 /*
5  * Header file with infrastructure needed for kernel unit tests:
6  *  - Assertion functions.
7  *  - Test structures.
8  */
9
10 #include <common.h>
11 #include <stdio.h>
12 #include <stdbool.h>
13 #include <kmalloc.h>
14 #include <arch/arch.h>
15 #include <time.h>
16
17 /* Global string used to report info about the last completed test */
18 extern char ktest_msg[1024];
19
20 /* Macros for assertions. 
21  */
22 #define KT_ASSERT(test)                                                          \
23         KT_ASSERT_M("", test)
24
25 #define KT_ASSERT_M(message, test)                                               \
26         do {                                                                         \
27                 if (!(test)) {                                                           \
28                         char fmt[] = "Assertion failure in %s() at %s:%d: %s";               \
29                         snprintf(ktest_msg, sizeof(ktest_msg), fmt, __FUNCTION__,            \
30                                  __FILE__, __LINE__, message);                               \
31                         return false;                                                        \
32                 }                                                                        \
33         } while (0)
34
35 struct ktest {
36         char name[256]; // Name of the test function.
37         bool (*func)(void); // Name of the test function, should be equal to 'name'.
38         bool enabled; // Whether to run or not the test.
39 };
40
41 /* Macro for registering a kernel test. */
42 #define KTEST_REG(name, config) \
43         {"test_" #name, test_##name, is_defined(config)}
44
45 static void run_ktests(char *suite_name, struct ktest tests[], int num_tests)
46 {
47         extern char ktest_msg[];
48         printk("<-- BEGIN_KERNEL_%s_TESTS -->\n", suite_name);
49
50         for (int i=0; i<num_tests; i++) {
51                 struct ktest *test = &tests[i];
52                 if (test->enabled) {
53                         uint64_t start = read_tsc();
54                         bool result = test->func();
55                         uint64_t end = read_tsc();
56                         uint64_t et_us = tsc2usec(end - start) % 1000000;
57                         uint64_t et_s = tsc2sec(end - start);
58
59                         char fmt[] = "\t%s   [%s](%llu.%06llus)   %s\n";
60                         if (result) {
61                                 printk(fmt, "PASSED", test->name, et_s, et_us, "");
62                         } else {
63                                 printk(fmt, "FAILED", test->name, et_s, et_us, ktest_msg);
64                         }
65                 } else {
66                         printk("\tDISABLED [%s]\n", test->name);
67                 }
68         }
69
70         printk("<-- END_KERNEL_%s_TESTS -->\n", suite_name);
71 }
72
73 #endif // ROS_INC_KTEST_H