]> git.saurik.com Git - apple/xnu.git/blame_incremental - osfmk/tests/README.md
xnu-7195.101.1.tar.gz
[apple/xnu.git] / osfmk / tests / README.md
... / ...
CommitLineData
1# Kernel Power On Self Tests (POST)
2
3The tests directories osfmk/tests and bsd/tests include set of tests that run in kernel at boot-time. The primary objective for these tests is to verify functionality of various subsystems like memory allocators, scheduling, VM, IPC ports etc. Following are some tips and guidelines to creating and running tests.
4
5## Features:
6 * Compiled out of RELEASE kernels.
7 * enabled with boot-arg kernPOST [ 0x1 : for on desk testing, 0x3 for BATs testing]
8 * Automatically skips tests that are designed to panic kernel for on-desk testing, but run in BATs environment.
9 * Does not require complete install on device to run. Just kernelcache is enough.
10 * Ability to check for assertions and panic path as well.
11
12## How to run kernel POST
13
14 * Start usbterm and setup your target machine/device in iBoot.
15 * set boot-args to include "```kernPOST=0x1```"" to enable kernel testing on boot.
16 * load kernelcache using "```usb get /patch/to/kc```"
17 * boot the image "```bootx```"
18 * watch for nanokdp serial output with tags like "```[KTEST] <test> logs```"
19
20## How do I configure to run just test #8?
21
22Kernel POST supports configuring test through boot-args. For example if you want to run your test #8 (say you are tweaking it to do more testing). Just set "```kernPOST_config=8```" and only your test will be run. The configuration also takes ranges as follows
23```
24-> kernPOST_config=1_3,5_9999 # skip test#4. Will run tests 1,2,3 and 5,6 and onwards.
25
26-> kernPOST_config=1_3,4_9999 # will not skip anything. lower_upper are both inclusive.
27
28```
29
30## How do I add a new test?
31Adding a new kernel POST test is very simple. Here are a few steps and guidelines for adding tests.
32
33 * There are two locations ```osfmk/tests/``` and ```bsd/tests``` where you can add tests based on your area of testing.
34 * If you wish to add a new *.c* file for your tests then, use ```#include <xnupost.h>``` to include required functions and macros for testing. Remember to add file_name.c in ```osfmk/conf/files``` or ```bsd/conf/files``` as
35
36 ```osfmk/tests/my_tests.c optional config_xnupost```
37 * To add a test function just declare a function with prototype as
38
39 ```kern_return_t my_sample_tests(void); ```
40 * And add to struct xnupost_test array in osfmk/tests/kernel_tests.c or bsd/tests/bsd_tests.c as
41
42```
43struct xnupost_test kernel_post_tests[] = {
44 XNUPOST_TEST_CONFIG_BASIC(my_sample_tests), // simple test
45 XNUPOST_TEST_CONFIG_TEST_PANIC(panic_test) // test that is expected to panic
46};
47```
48 * And you are set. Use KERN_SUCCESS to report successful run and any other error for failure. Here is an example with some available macros.
49
50```
51kern_return_t my_sample_tests() {
52 uint64_t test_begin_timestamp = 0;
53 uint64_t cur_timestamp = 0, tmp;
54
55 T_SETUPBEGIN;
56 test_begin_timestamp = mach_absolute_time();
57 T_ASSERT_NOTNULL(test_begin_timestamp, "mach_absolute_time returned 0.");
58 T_SETUPEND;
59
60 T_LOG("Testing mach_absolute_time for 100 iterations");
61 for (int i = 0; i < 100; i++) {
62 tmp = mach_absolute_time();
63 T_EXPECT_TRUE((cur_timestamp <= tmp ), "Time went backwards");
64 cur_timestamp = tmp;
65 }
66
67 T_LOG("Completed mach_absolute_time tests.");
68 return KERN_SUCCESS;
69}
70```
71
72 * There are many ** T_* ** macros available for your convenience.
73 * **Note**: Please make sure your test does a proper cleanup of state. The kernel is expected to continue to boot after testing. If you are unable to cleanup and require a reboot then use XNUPOST_TEST_CONFIG_TEST_PANIC type and panic at the end of the function. This will make sure the test controller reboots and runs the next test in automation.
74
75## What is the difference between T_EXPECT and T_ASSERT macros?
76
77 * T_ASSERT macros will check for condition and upon failure return with KERN_FAILURE. This way it ensures that no further execution of test code is done.
78 * T_EXPECT will just report failure of that test case, but will continue to run further test code.
79
80## How do I run my tests in BATs?
81
82Bats has a new test type **kernel_POST** that runs Lean test environment tests. You can run the following command to get POST testing.
83
84```
85~osdev/tat/dev/bin/bats build -b <build> -t darwinLTE -p xnu:<branch> -r <radarnum>
86```
87
88## How do I test for panic/assertions?
89
90The xnupost subsystem provides mechanism for setting up a `panic widget`. This widget can check for some conditions and report test case SUCCESS/FAILURE. See xnupost.h for `XT_RET* ` style return values. There are convenience macros for registering for generic panic and for assertion handling. For example if you wish to check for api foo(int arg) { assert(arg > 0); ... } then a test case could be like
91
92```
93kern_return_t test_foo_arg_assertion(void) {
94 void * assert_retval = NULL;
95 kern_return_t kr = T_REGISTER_ASSERT_CHECK("arg > 0", &assert_retval);
96 T_ASSERT(kr == KERN_SUCCESS, "register assertion handler");
97
98 foo(-1); /* this will cause assert to fire */
99
100 T_ASSERT(assert_retval == (void *)XT_RET_W_SUCCESS, "verify assertion was hit");
101}
102
103```
104
105## How do XNUPOST panic widgets work?
106
107On debug/development kernels, the `panic()` code is modified to call out to XNUPOST system `xnupost_process_panic()`. This callout can then determine if testing was enabled and has a widget registered for checking panics. If yes, then the corresponding widget function is called and the return value determines what action is taken. For example a widget could return either of the following values
108
109 XT_PANIC_UNRELATED /* not related. continue panic */
110 XT_RET_W_FAIL /* report FAILURE and return from panic */
111 XT_RET_W_SUCCESS /* report SUCCESS and return from panic */
112 XT_PANIC_W_FAIL /* report FAILURE and continue to panic */
113 XT_PANIC_W_SUCCESS /* report SUCCESS and continue to panic */
114
115The panic widget data is saved in internal data array where each is of type:
116struct xnupost_panic_widget {
117 void * xtp_context_p; /* a context pointer for callbacks to track */
118 void ** xtp_outval_p; /* an out param for function to return some value to running test */
119 const char * xtp_func_name; /* widget name for tracking in serial output */
120 xt_panic_widget_func xtp_func;
121};
122
123There is an example use case in `osfmk/tests/kernel_tests.c :check_panic_test() and panic_test()` for writing a widget.
124For basic assertion check see example in `osfmkt/tests/kernel_tests.c :kcdata_api_assert_tests()`
125