1.\" 2.\" Copyright (c) 2015 Netflix Inc. 3.\" All rights reserved. 4.\" 5.\" Redistribution and use in source and binary forms, with or without 6.\" modification, are permitted provided that the following conditions 7.\" are met: 8.\" 1. Redistributions of source code must retain the above copyright 9.\" notice, this list of conditions and the following disclaimer. 10.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" notice, this list of conditions and the following disclaimer in the 12.\" documentation and/or other materials provided with the distribution. 13.\" 14.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR 15.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, 18.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24.\" 25.\" $FreeBSD$ 26.\" 27.Dd November 12, 2015 28.Dt KERN_TESTFRWK 9 29.Os 30.Sh NAME 31.Nm kern_testfrwk 32.Nd A kernel testing framework 33.Sh SYNOPSIS 34kld_load kern_testfrwk 35.Sh DESCRIPTION 36.\" This whole section is not written in manual page style and should be ripped 37.\" out and replaced. -CEM 38So what is this sys/tests directory in the kernel all about? 39.Pp 40Have you ever wanted to test a part of the FreeBSD kernel in some way and you 41had no real way from user-land to make what you want to occur happen? 42Say an error path or situation where locking occurs in a particular manner that 43happens only once in a blue moon? 44.Pp 45If so, then the kernel test framework is just what you are looking for. 46It is designed to help you create the situation you want. 47.Pp 48There are two components to the system: the test framework and your test. 49This document will describe both components and use the test submitted with the 50initial commit of this code to discuss the test 51.Xr ( callout_test 4 ) . 52All of the tests become kernel loadable modules. 53The test you write should have a dependency on the test framework. 54That way it will be loaded automatically with your test. 55For example, you can see how to do this in the bottom of callout_test.c in 56.Pa sys/tests/callout_test/callout_test.c . 57.Pp 58The framework itself is in 59.Pa sys/tests/framework/kern_testfrwk.c . 60Its job is to manage the tests that are loaded. 61(More than one can be loaded.) 62The idea is pretty simple; you load the test framework and then load your test. 63.Pp 64When your test loads, you register your tests with the kernel test framework. 65You do that through a call to 66.Fn kern_testframework_register . 67Usually this is done at the module load event as shown below: 68.Pp 69.Bd -literal -offset indent 70 switch (type) { 71 case MOD_LOAD: 72 err = kern_testframework_register("callout_test", 73 run_callout_test); 74.Ed 75.Pp 76Here the test is "callout_test" and it is registered to run the function 77.Fn run_callout_test 78passing it a 79.Fa struct kern_test *ptr . 80The 81.Vt kern_test 82structure is defined in 83.Pa kern_testfrwk.h . 84.Bd -literal -offset indent 85struct kern_test { 86 char name[TEST_NAME_LEN]; 87 int num_threads; /* Fill in how many threads you want */ 88 int tot_threads_running; /* Private to framework */ 89 uint8_t test_options[TEST_OPTION_SPACE]; 90}; 91.Ed 92.Pp 93The user sends this structure down via a sysctl to start your test. 94He or she places the same name you registered ("callout_test" 95in our example) in the 96.Va name 97field. 98The user can also set the number of threads to run with 99.Va num_threads . 100.Pp 101The framework will start the requested number of kernel threads, all running 102your test at the same time. 103The user does not specify anything in 104.Va tot_threads_running ; 105it is private to the framework. 106As the framework calls each of your tests, it will set the 107.Va tot_threads_running 108to the index of the thread that your call is made from. 109For example, if the user sets 110.Va num_threads 111to 2, then the function 112.Fn run_callout_test 113will be called once with 114.Va tot_threads_running 115to 0, and a second time with 116.Va tot_threads_running 117set to 1. 118.Pp 119The 120.Va test_options 121field is a test-specific set of information that is an opaque blob. 122It is passed in from user space and has a maximum size of 256 bytes. 123You can pass arbitrary test input in the space. 124In the case of callout_test we reshape that to: 125.Pp 126.Bd -literal -offset indent 127struct callout_test { 128 int number_of_callouts; 129 int test_number; 130}; 131.Ed 132.Pp 133So the first lines of 134.Fn run_callout_test 135does the following to get at the user specific data: 136.Pp 137.\" This is a bad example and violates strict aliasing. It should be replaced. 138.Bd -literal -offset indent 139 struct callout_test *u; 140 size_t sz; 141 int i; 142 struct callout_run *rn; 143 int index = test->tot_threads_running; 144 145 u = (struct callout_test *)test->test_options; 146.Ed 147.Pp 148That way it can access: 149.Va u->test_number 150(there are two types of tests provided with this test) 151and 152.Va u->number_of_callouts 153(how many simultaneous callouts to run). 154.Pp 155Your test can do anything with these bytes. 156So the callout_test in question wants to create a situation where multiple 157callouts are all run, that is the 158.Va number_of_callouts , 159and it tries to cancel the callout with the new 160.Fn callout_async_drain . 161The threads do this by acquiring the lock in question, and then 162starting each of the callouts. 163It waits for the callouts to all go off (the executor spins waits). 164This forces the situation that the callouts have expired and are all waiting on 165the lock that the executor holds. 166After the callouts are all blocked, the executor calls 167.Fn callout_async_drain 168on each callout and releases the lock. 169.Pp 170.\" callout_test(4) specific documentation should probably be moved to its own 171.\" page. 172After all the callouts are done, a total status is printed 173showing the results via 174.Xr printf 9 . 175The human tester can run 176.Xr dmesg 8 177to see the results. 178In this case it is expected that if you are running test 0, all the callouts 179expire on the same CPU so only one callout_drain function would have been 180called. 181the number of zero_returns should match the number of callout_drains that were 182called, i.e., 1. 183The one_returns should be the remainder of the callouts. 184If the test number was 1, the callouts were spread across all CPUs. 185The number of zero_returns will again match the number of drain calls made 186which matches the number of CPUs that were put in use. 187.Pp 188More than one thread can be used with this test, though in the example case it 189is probably not necessary. 190.Pp 191You should not need to change the framework. 192Just add tests and register them after loading. 193.Sh AUTHORS 194The kernel test framework was written by 195.An Randall Stewart Aq Mt rrs@FreeBSD.org 196with help from 197.An John Mark Gurney Aq Mt jmg@FreeBSD.org . 198