xref: /illumos-gate/usr/src/uts/common/io/ktest/ktest_selftest.c (revision 08855964b9970604433f7b19dcd71cf5af5e5f14)
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 /*
13  * Copyright 2023 Oxide Computer Company
14  * Copyright 2024 Ryan Zezeski
15  */
16 
17 /*
18  * The ktest self test. Make sure the basics work.
19  */
20 #include <sys/ktest.h>
21 
22 void
ktest_st_pass_test(ktest_ctx_hdl_t * ctx)23 ktest_st_pass_test(ktest_ctx_hdl_t *ctx)
24 {
25 	KT_PASS(ctx);
26 }
27 
28 static boolean_t
ktest_st_is_even(int x)29 ktest_st_is_even(int x)
30 {
31 	return ((x % 2) == 0);
32 }
33 
34 void
ktest_st_fail_test(ktest_ctx_hdl_t * ctx)35 ktest_st_fail_test(ktest_ctx_hdl_t *ctx)
36 {
37 	KT_ASSERT(ktest_st_is_even(5), ctx);
38 	KT_PASS(ctx);
39 }
40 
41 static int
ktest_st_pretend_func(int input)42 ktest_st_pretend_func(int input)
43 {
44 	if (input == 42) {
45 		return (0);
46 	}
47 
48 	return (-1);
49 }
50 
51 /*
52  * This test should report a NONE result as it never touches the
53  * context.
54  */
55 void
ktest_st_none_test(ktest_ctx_hdl_t * ctx)56 ktest_st_none_test(ktest_ctx_hdl_t *ctx)
57 {
58 	(void) ktest_st_pretend_func(7);
59 }
60 
61 /*
62  * This test should report an ERROR result.
63  */
64 void
ktest_st_err_test(ktest_ctx_hdl_t * ctx)65 ktest_st_err_test(ktest_ctx_hdl_t *ctx)
66 {
67 	KT_EASSERT0(ktest_st_pretend_func(7), ctx);
68 }
69 
70 /*
71  * This test should report a SKIP result.
72  */
73 void
ktest_st_skip_test(ktest_ctx_hdl_t * ctx)74 ktest_st_skip_test(ktest_ctx_hdl_t *ctx)
75 {
76 	KT_SKIP(ctx, "This test should be skipped.");
77 }
78 
79 /*
80  * This test should only run when given an input stream.
81  */
82 void
ktest_st_input_test(ktest_ctx_hdl_t * ctx)83 ktest_st_input_test(ktest_ctx_hdl_t *ctx)
84 {
85 	uchar_t *bytes;
86 	size_t num_bytes = 0;
87 
88 	ktest_get_input(ctx, &bytes, &num_bytes);
89 
90 	if (num_bytes < 4) {
91 		KT_ERROR(ctx, "expected 4 or more bytes, got %u", num_bytes);
92 		return;
93 	}
94 
95 	cmn_err(CE_WARN, "bytes (%lu): 0x%x 0x%x 0x%x 0x%x",
96 	    num_bytes, bytes[0], bytes[1], bytes[2],
97 	    bytes[3]);
98 
99 	KT_PASS(ctx);
100 }
101 
102 /*
103  * Verify that ktest catches multiple results and returns an error to
104  * alert the user.
105  */
106 void
ktest_st_mult_result_test(ktest_ctx_hdl_t * ctx)107 ktest_st_mult_result_test(ktest_ctx_hdl_t *ctx)
108 {
109 	KT_FAIL(ctx, "this is a fail result");
110 	KT_PASS(ctx);
111 }
112 
113 /*
114  * Verify the suite and test name uniqueness is enforced. Module name
115  * uniqueness is tested in _init().
116  */
117 void
ktest_st_unique_test(ktest_ctx_hdl_t * ctx)118 ktest_st_unique_test(ktest_ctx_hdl_t *ctx)
119 {
120 	ktest_module_hdl_t *km = NULL;
121 	ktest_suite_hdl_t *ks = NULL;
122 
123 	KT_ASSERT0(ktest_create_module("ktest", &km), ctx);
124 	KT_ASSERT0G(ktest_add_suite(km, "selftest", &ks), ctx, cleanup);
125 	KT_ASSERT3SG(ktest_add_suite(km, "selftest", &ks), ==, EEXIST, ctx,
126 	    cleanup);
127 	KT_ASSERT0G(ktest_add_test(ks, "ktest_st_pass_test", ktest_st_pass_test,
128 	    KTEST_FLAG_NONE), ctx, cleanup);
129 	KT_ASSERTG(ktest_add_test(ks, "ktest_st_pass_test", ktest_st_pass_test,
130 	    KTEST_FLAG_NONE) == EEXIST, ctx, cleanup);
131 
132 	KT_PASS(ctx);
133 
134 cleanup:
135 	ktest_free_module(km);
136 }
137 
138 void
ktest_st_name_test(ktest_ctx_hdl_t * ctx)139 ktest_st_name_test(ktest_ctx_hdl_t *ctx)
140 {
141 	ktest_module_hdl_t *km = NULL;
142 
143 	KT_ASSERT3SG(ktest_create_module("bad:name", &km), ==, EINVAL, ctx,
144 	    cleanup);
145 	KT_ASSERT3SG(ktest_create_module("bad/name", &km), ==, EINVAL, ctx,
146 	    cleanup);
147 	KT_ASSERT3SG(ktest_create_module("bad?name", &km), ==, EINVAL, ctx,
148 	    cleanup);
149 	KT_ASSERT3SG(ktest_create_module("bad name", &km), ==, EINVAL, ctx,
150 	    cleanup);
151 	KT_ASSERT3SG(ktest_create_module("bad>name", &km), ==, EINVAL, ctx,
152 	    cleanup);
153 	KT_ASSERT3SG(ktest_create_module("bad<name", &km), ==, EINVAL, ctx,
154 	    cleanup);
155 	KT_ASSERT3SG(ktest_create_module("bad&name", &km), ==, EINVAL, ctx,
156 	    cleanup);
157 	KT_ASSERT3SG(ktest_create_module("bad*name", &km), ==, EINVAL, ctx,
158 	    cleanup);
159 
160 	KT_ASSERT0G(ktest_create_module("good_name", &km), ctx, cleanup);
161 	ktest_free_module(km);
162 	KT_ASSERT0G(ktest_create_module("good_name02", &km), ctx, cleanup);
163 	ktest_free_module(km);
164 	KT_ASSERT0G(ktest_create_module("good.name02", &km), ctx, cleanup);
165 	ktest_free_module(km);
166 	KT_ASSERT0G(ktest_create_module("_l33t.n4m3", &km), ctx, cleanup);
167 
168 	KT_PASS(ctx);
169 
170 cleanup:
171 	ktest_free_module(km);
172 }
173 
174 static struct modlmisc ktest_selftest_modlmisc = {
175 	.misc_modops = &mod_miscops,
176 	.misc_linkinfo = "ktest selftest module"
177 };
178 
179 static struct modlinkage ktest_selftest_modlinkage = {
180 	.ml_rev = MODREV_1,
181 	.ml_linkage = { &ktest_selftest_modlmisc, NULL }
182 };
183 
184 int
_init()185 _init()
186 {
187 	int ret;
188 	ktest_module_hdl_t *km = NULL;
189 	ktest_suite_hdl_t *ks = NULL;
190 
191 	VERIFY0(ktest_create_module("ktest", &km));
192 	VERIFY0(ktest_add_suite(km, "selftest", &ks));
193 	VERIFY0(ktest_add_test(ks, "ktest_st_none_test", ktest_st_none_test,
194 	    KTEST_FLAG_NONE));
195 	VERIFY0(ktest_add_test(ks, "ktest_st_pass_test", ktest_st_pass_test,
196 	    KTEST_FLAG_NONE));
197 	VERIFY0(ktest_add_test(ks, "ktest_st_fail_test", ktest_st_fail_test,
198 	    KTEST_FLAG_NONE));
199 	VERIFY0(ktest_add_test(ks, "ktest_st_err_test", ktest_st_err_test,
200 	    KTEST_FLAG_NONE));
201 	VERIFY0(ktest_add_test(ks, "ktest_st_skip_test", ktest_st_skip_test,
202 	    KTEST_FLAG_NONE));
203 	VERIFY0(ktest_add_test(ks, "ktest_st_input_test", ktest_st_input_test,
204 	    KTEST_FLAG_INPUT));
205 	VERIFY0(ktest_add_test(ks, "ktest_st_mult_result_test",
206 	    ktest_st_mult_result_test, KTEST_FLAG_NONE));
207 	VERIFY0(ktest_add_test(ks, "ktest_st_unique_test",
208 	    ktest_st_unique_test, KTEST_FLAG_NONE));
209 	VERIFY0(ktest_add_test(ks, "ktest_st_name_test",
210 	    ktest_st_name_test, KTEST_FLAG_NONE));
211 
212 	if ((ret = ktest_register_module(km)) != 0) {
213 		ktest_free_module(km);
214 		return (ret);
215 	}
216 
217 	/*
218 	 * It would be nice to test this in ktest_st_test_unique(),
219 	 * but we can't because this call grabs the ktest_lock, and
220 	 * the lock is already held while a test is running. If you
221 	 * see a panic here, check ktest_register_module() to make
222 	 * sure it's enforcing module name uniqueness.
223 	 */
224 	VERIFY(ktest_register_module(km) == EEXIST);
225 
226 	if ((ret = mod_install(&ktest_selftest_modlinkage)) != 0) {
227 		ktest_unregister_module("ktest");
228 		return (ret);
229 	}
230 
231 	return (0);
232 }
233 
234 int
_fini(void)235 _fini(void)
236 {
237 	ktest_unregister_module("ktest");
238 	return (mod_remove(&ktest_selftest_modlinkage));
239 }
240 
241 int
_info(struct modinfo * modinfop)242 _info(struct modinfo *modinfop)
243 {
244 	return (mod_info(&ktest_selftest_modlinkage, modinfop));
245 }
246