xref: /illumos-gate/usr/src/man/man9f/ktest_result_pass.9f (revision 2833423dc59f4c35fe4713dbb942950c82df0437)
1.\"
2.\" This file and its contents are supplied under the terms of the
3.\" Common Development and Distribution License ("CDDL"), version 1.0.
4.\" You may only use this file in accordance with the terms of version
5.\" 1.0 of the CDDL.
6.\"
7.\" A full copy of the text of the CDDL should have accompanied this
8.\" source.  A copy of the CDDL is also available via the Internet at
9.\" http://www.illumos.org/license/CDDL.
10.\"
11.\"
12.\" Copyright 2023 Oxide Computer Company
13.\"
14.Dd February 15, 2023
15.Dt KTEST_RESULT_PASS 9F
16.Os
17.Sh NAME
18.Nm KT_PASS ,
19.Nm KT_FAIL ,
20.Nm KT_ERROR ,
21.Nm KT_SKIP ,
22.Nm KT_ASSERT ,
23.Nm KT_ASSERT0 ,
24.Nm KT_ASSERT3S ,
25.Nm KT_ASSERT3U ,
26.Nm KT_ASSERT3P ,
27.Nm KT_ASSERTG ,
28.Nm KT_ASSERT0G ,
29.Nm KT_ASSERT3SG ,
30.Nm KT_ASSERT3UG ,
31.Nm KT_ASSERT3PG ,
32.Nm ktest_result_pass ,
33.Nm ktest_result_fail ,
34.Nm ktest_result_error ,
35.Nm ktest_result_skip ,
36.Nm ktest_msg_prepend ,
37.Nm ktest_msg_clear
38.Nd set test result, assert test conditions, add failure context
39.Sh SYNOPSIS
40.In sys/ktest.h
41.Ft void
42.Fo ktest_result_pass
43.Fa "ktest_ctx_hdl_t *ctx"
44.Fa "int line"
45.Fc
46.Ft void
47.Fo ktest_result_fail
48.Fa "ktest_ctx_hdl_t *ctx"
49.Fa "int line"
50.Fa "const char *msg"
51.Fa "..."
52.Fc
53.Ft void
54.Fo ktest_result_error
55.Fa "ktest_ctx_hdl_t *ctx"
56.Fa "int line"
57.Fa "const char *msg"
58.Fa "..."
59.Fc
60.Ft void
61.Fo ktest_result_skip
62.Fa "ktest_ctx_hdl_t *ctx"
63.Fa "int line"
64.Fa "const char *msg"
65.Fa "..."
66.Fc
67.Ft void
68.Fo ktest_msg_prepend
69.Fa "ktest_ctx_hdl_t *ctx"
70.Fa "const char *msg"
71.Fa "..."
72.Fc
73.Ft void
74.Fo ktest_msg_clear
75.Fa "ktest_ctx_hdl_t *ctx"
76.Fc
77.Ft void
78.Fo KT_PASS
79.Fa "ktest_ctx_hdl_t *ctx"
80.Fc
81.Ft void
82.Fo KT_FAIL
83.Fa "ktest_ctx_hdl_t *ctx"
84.Fa "const char *msg"
85.Fa "..."
86.Fc
87.Ft void
88.Fo KT_ERROR
89.Fa "ktest_ctx_hdl_t *ctx"
90.Fa "const char *msg"
91.Fa "..."
92.Fc
93.Ft void
94.Fo KT_SKIP
95.Fa "ktest_ctx_hdl_t *ctx"
96.Fa "const char *msg"
97.Fa "..."
98.Fc
99.Ft void
100.Fo KT_ASSERT
101.Fa "exp"
102.Fa "ktest_ctx_hdl_t *ctx"
103.Fc
104.Ft void
105.Fo KT_ASSERT0
106.Fa "exp"
107.Fa "ktest_ctx_hdl_t *ctx"
108.Fc
109.Ft void
110.Fo KT_ASSERT3S
111.Fa "int64_t left"
112.Fa "op"
113.Fa "int64_t right"
114.Fa "ktest_ctx_hdl_t *ctx"
115.Fc
116.Ft void
117.Fo KT_ASSERT3U
118.Fa "uint64_t left"
119.Fa "op"
120.Fa "uint64_t right"
121.Fa "ktest_ctx_hdl_t *ctx"
122.Fc
123.Ft void
124.Fo KT_ASSERT3P
125.Fa "uintptr_t left"
126.Fa "op"
127.Fa "uintptr_t right"
128.Fa "ktest_ctx_hdl_t *ctx"
129.Fc
130.Ft void
131.Fo KT_ASSERTG
132.Fa "exp"
133.Fa "ktest_ctx_hdl_t *ctx"
134.Fa "label"
135.Fc
136.Ft void
137.Fo KT_ASSERT0G
138.Fa "exp"
139.Fa "ktest_ctx_hdl_t *ctx"
140.Fa "label"
141.Fc
142.Ft void
143.Fo KT_ASSERT3SG
144.Fa "int64_t left"
145.Fa "op"
146.Fa "int64_t right"
147.Fa "ktest_ctx_hdl_t *ctx"
148.Fa "label"
149.Fc
150.Ft void
151.Fo KT_ASSERT3UG
152.Fa "uint64_t left"
153.Fa "op"
154.Fa "uint64_t right"
155.Fa "ktest_ctx_hdl_t *ctx"
156.Fa "label"
157.Fc
158.Ft void
159.Fo KT_ASSERT3PG
160.Fa "uintptr_t left"
161.Fa "op"
162.Fa "uintptr_t right"
163.Fa "ktest_ctx_hdl_t *ctx"
164.Fa "label"
165.Fc
166.Sh INTERFACE LEVEL
167.Sy Volatile -
168This interface is still evolving in illumos.
169API and ABI stability is not guaranteed.
170.Sh PARAMETERS
171.Bl -tag -width Fa
172.It Fa ctx
173A handle to the test context.
174This handle is passed as argument to the test function by the ktest facility.
175.It Fa exp
176A test condition expression.
177.It Fa left
178The left side value of the test condition.
179This may be an expression.
180.It Fa right
181The right side value of the test condition.
182This may be an expression.
183.It Fa op
184The operator used to compare the
185.Fa left
186and
187.Fa right
188side values.
189.It Fa label
190The source code label to jump to if the test condition is false.
191.It Fa line
192The source line number where the result is set.
193This should always be the
194.Sy __LINE__
195macro.
196.It Fa msg
197A message giving additional context on why a test did not pass.
198.El
199.Sh DESCRIPTION
200These functions and macros are used to set the result of a test function.
201.Ss Result Macros
202These are convenience macros for setting the test result, providing an
203alternative to the verbose result functions.
204In general, you should only need to use the
205.Fn KT_PASS
206and
207.Fn KT_SKIP
208macros.
209For most test assertions it's more convenient to use the "KTest ASSERT
210Macros" described below.
211These macros do not cause a
212.Sy return .
213.Bl -tag -width 2m
214.It Fn KT_PASS
215Set a passing result.
216.It Fn KT_FAIL
217Set a failure result along with the failure message.
218.It Fn KT_ERROR
219Set an error result along with the error message.
220.It Fn KT_SKIP
221Set a skip result along with the skip message.
222.El
223.Ss KTest ASSERT Macros
224These macros evaluate their test condition expression and verify it's true.
225They take care of building a failure message based on the expression
226and calling the
227.Fn ktest_result_fail
228function with the appropriate line number.
229They provide a convenient way to express test conditions and
230automatically build failure messages on the caller's behalf.
231They are essentially the same as the traditional
232.Sy ASSERT3
233family of macros with three exceptions:
234.Bl -enum
235.It
236They all require the additional
237.Fa ctx
238argument in order to set the failure result when the assert trips.
239.It
240They do not panic but instead build a failure message, call
241.Fn ktest_result_fail ,
242and cause an immediate return of the test function.
243.It
244The "goto" variations of these macros provide the ability to cleanup
245test state instead of returning immediately.
246.El
247.Pp
248There are two variations of these macros.
249.Bl -tag -width 6m
250.It Sy KT_ASSERT*
251Essentially the same as the traditional
252.Sy ASSERT3
253family of macros, with the exception that they all take the
254.Fa ctx
255as an additional argument.
256This assert returns from the test function.
257.It Sy KT_ASSERT*G
258Assert the condition or
259.Sy goto
260.Fa label .
261.El
262.Ss KTest Error ASSERT Macros
263These macros are the same as the
264.Fn KT_ASSERT*
265macros with the only exception being that they call the
266.Fn ktest_result_error
267function to indicate an error condition.
268These macros use the same names as the
269.Fn KT_ASSERT*
270macros but prefixed with the character 'E', like so:
271.Fn KT_EASSERT* .
272This is a convenience for checking conditions which are indicative of
273a test error rather than failure.
274For example, for most tests a failure to acquire memory is considered
275an error, not a test failure.
276In that case one could use the following assert to raise a test error.
277.Bd -literal
278	mblk_t *mp = allocb(len, 0);
279	KT_EASSERT(mp != NULL, ctx);
280.Ed
281.Ss Additional Message Context
282Sometimes the failure message generated by the
283.Fn KT_ASSERT*
284macros is not enough.
285You may find the need to prepend additional information to the message
286to disambiguate the reason for failure.
287For example, you might find yourself asserting an invariant against an
288array of values and in order to disambiguate the failure you need to
289know the index of the value which tripped the assert.
290The
291.Fn ktest_msg_prepend
292function provides this ability.
293.Bl -tag -width 4m
294.It Nm ktest_msg_prepend
295Append the given format string to the failure message.
296This overwrites the prepended string of any previous call making it
297more convenient to use in a
298.Sy for
299loop.
300.It Nm ktest_msg_clear
301Clear the prepend buffer.
302This is equivalent to
303.Sy ktest_msg_prepend("") .
304.El
305.Ss Multiple Results
306Given the nature of ktest's design it is trivial to accidentally write
307a test that can produce multiple results for a given execution of its
308code.
309For example, placing the
310.Nm KT_PASS
311call in a cleanup label would overwrite a failure result with a pass
312result.
313This is the unavoidable nature of ktest's implementation: unlike
314typical testing frameworks we are executing in kernel context and it
315would be annoying if test failure was reported by way of host panic.
316.Pp
317To avoid incorrect test results the ktest facility itself checks for
318this scenario.
319For each call to the result API, ktest first checks if a result has
320already been set.
321If no result is present, then it stores the result along with its line
322number.
323However, if a result already exists, it generates an error result
324describing the line number of the overriding result along with the
325line number of the original result.
326.Sh EXAMPLES
327.Ss Test Without Cleanup
328This example shows the basic skeleton of a contrived test for a fictional
329.Ft object_t
330type.
331As there is no allocation or resource acquisition, there is no need
332for cleanup.
333.Bd -literal
334void
335no_cleanup_test(ktest_ctx_hdl_t *ctx)
336{
337	object_t obj;
338
339	obj.obj_value = 7777;
340	obj.obj_state = OBJ_STATE_FIRST;
341
342	if (!check_for_condition_x()) {
343		KT_SKIP(ctx, "condition X was not met");
344		return;
345	}
346
347	KT_ASSERT3U(obj.obj_state, ==, OBJ_STATE_FIRST, ctx);
348	next_state(&obj);
349	KT_ASSERT3U(obj.obj_state, ==, OBJ_STATE_SECOND, ctx);
350
351	<... more obj manipulation and assertions ...>
352
353	KT_PASS(ctx);
354}
355.Ed
356.Ss Test With Cleanup
357It's more likely that your test will require some amount of allocation and
358thus will need to make use of the
359.Fn KT_ASSERTG*
360macros.
361In this scenario
362.Fn KT_PASS
363must come before the
364.Sy cleanup
365label.
366Calling it after the
367.Sy cleanup
368label produces a multiple-result bug when one of the assertions trips.
369The ktest facility automatically catches this type of bug as explained
370in the "Multiple Results" section.
371.Bd -literal
372void
373test_with_cleanup(ktest_ctx_hdl_t *ctx)
374{
375	mblk_t *mp = allocb(74, 0);
376
377	/*
378	 * Failure to allocate is an error, not a test failure.
379	 */
380	KT_EASSERT(mp != NULL, ctx);
381
382	/*
383	 * If any of these assertions trips, a failure result is set
384	 * and execution jumps to the 'cleanup' label.
385	 */
386	KT_ASSERT3UG(msgsize(mp), ==, 0, ctx, cleanup);
387	KT_ASSERT3PG(mp->b_rptr, ==, mp->b_wptr, ctx, cleanup);
388	KT_ASSERT3PG(mp->b_next, ==, NULL, ctx, cleanup);
389	KT_ASSERT3PG(mp->b_cont, ==, NULL, ctx, cleanup);
390
391	/*
392	 * All assertions passed; mark the test a success and let
393	 * execution fall into the 'cleanup' label.
394	 */
395	KT_PASS(ctx);
396
397cleanup:
398	freeb(mp);
399}
400.Ed
401.Ss Additional Failure Context
402This example shows how to prepend additional context to the failure
403message.
404The
405.Fn ktest_msg_clear
406call after the loop is important; otherwise any subsequent assert failure
407would pick up the prepended message from the last iteration of the loop.
408.Bd -literal
409for (uint_t i = 0; i < num_objs; i++) {
410        obj_t *obj = &objs[i];
411
412        ktest_msg_prepend(ctx, "objs[%d]: ", i);
413        KT_ASSERT3U(obj->o_state, ==, EXPECTED_STATE, ctx);
414}
415
416ktest_msg_clear(ctx);
417.Ed
418