xref: /freebsd/share/man/man9/kern_testfrwk.9 (revision d6b92ffa)
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.Bd -literal -offset indent
69	switch (type) {
70	case MOD_LOAD:
71		err = kern_testframework_register("callout_test",
72		    run_callout_test);
73.Ed
74.Pp
75Here the test is "callout_test" and it is registered to run the function
76.Fn run_callout_test
77passing it a
78.Fa struct kern_test *ptr .
79The
80.Vt kern_test
81structure is defined in
82.Pa kern_testfrwk.h .
83.Bd -literal -offset indent
84struct kern_test {
85	char name[TEST_NAME_LEN];
86	int num_threads;  /* Fill in how many threads you want */
87	int tot_threads_running;       /* Private to framework */
88	uint8_t test_options[TEST_OPTION_SPACE];
89};
90.Ed
91.Pp
92The user sends this structure down via a sysctl to start your test.
93He or she places the same name you registered ("callout_test"
94in our example) in the
95.Va name
96field.
97The user can also set the number of threads to run with
98.Va num_threads .
99.Pp
100The framework will start the requested number of kernel threads, all running
101your test at the same time.
102The user does not specify anything in
103.Va tot_threads_running ;
104it is private to the framework.
105As the framework calls each of your tests, it will set the
106.Va tot_threads_running
107to the index of the thread that your call is made from.
108For example, if the user sets
109.Va num_threads
110to 2, then the function
111.Fn run_callout_test
112will be called once with
113.Va tot_threads_running
114to 0, and a second time with
115.Va tot_threads_running
116set to 1.
117.Pp
118The
119.Va test_options
120field is a test-specific set of information that is an opaque blob.
121It is passed in from user space and has a maximum size of 256 bytes.
122You can pass arbitrary test input in the space.
123In the case of callout_test we reshape that to:
124.Bd -literal -offset indent
125struct callout_test {
126	int number_of_callouts;
127	int test_number;
128};
129.Ed
130.Pp
131So the first lines of
132.Fn run_callout_test
133does the following to get at the user specific data:
134.\" This is a bad example and violates strict aliasing.  It should be replaced.
135.Bd -literal -offset indent
136	struct callout_test *u;
137	size_t sz;
138	int i;
139	struct callout_run *rn;
140	int index = test->tot_threads_running;
141
142	u = (struct callout_test *)test->test_options;
143.Ed
144.Pp
145That way it can access:
146.Va u->test_number
147(there are two types of tests provided with this test)
148and
149.Va u->number_of_callouts
150(how many simultaneous callouts to run).
151.Pp
152Your test can do anything with these bytes.
153So the callout_test in question wants to create a situation where multiple
154callouts are all run, that is the
155.Va number_of_callouts ,
156and it tries to cancel the callout with the new
157.Fn callout_async_drain .
158The threads do this by acquiring the lock in question, and then
159starting each of the callouts.
160It waits for the callouts to all go off (the executor spins waits).
161This forces the situation that the callouts have expired and are all waiting on
162the lock that the executor holds.
163After the callouts are all blocked, the executor calls
164.Fn callout_async_drain
165on each callout and releases the lock.
166.Pp
167.\" callout_test(4) specific documentation should probably be moved to its own
168.\" page.
169After all the callouts are done, a total status is printed
170showing the results via
171.Xr printf 9 .
172The human tester can run
173.Xr dmesg 8
174to see the results.
175In this case it is expected that if you are running test 0, all the callouts
176expire on the same CPU so only one callout_drain function would have been
177called.
178the number of zero_returns should match the number of callout_drains that were
179called, i.e., 1.
180The one_returns should be the remainder of the callouts.
181If the test number was 1, the callouts were spread across all CPUs.
182The number of zero_returns will again match the number of drain calls made
183which matches the number of CPUs that were put in use.
184.Pp
185More than one thread can be used with this test, though in the example case it
186is probably not necessary.
187.Pp
188You should not need to change the framework.
189Just add tests and register them after loading.
190.Sh AUTHORS
191The kernel test framework was written by
192.An Randall Stewart Aq Mt rrs@FreeBSD.org
193with help from
194.An John Mark Gurney Aq Mt jmg@FreeBSD.org .
195