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