xref: /illumos-gate/usr/src/cmd/ktest/ktest.c (revision 068cf9dc70b00292d5e5ff1ab17f1b046215d6f6)
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 #include <sys/debug.h>
17 #include <sys/ktest.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/list.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <stropts.h>
24 #include <stdio.h>
25 #include <stddef.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <err.h>
29 #include <stdarg.h>
30 #include <strings.h>
31 #include <libgen.h>
32 #include <libnvpair.h>
33 #include <regex.h>
34 #include <libcmdutils.h>
35 #include <ofmt.h>
36 #include <zone.h>
37 
38 #define	EXIT_USAGE		2
39 #define	KTEST_CMD_SZ		24
40 #define	KTEST_DEV_PATH		"/dev/ktest"
41 
42 static const char *ktest_prog;
43 
44 /* Print a horizontal rule. */
45 static void
46 ktest_print_hr(uint8_t cols)
47 {
48 	for (uint8_t i = 0; i < cols; i++) {
49 		(void) putchar('-');
50 	}
51 
52 	(void) putchar('\n');
53 }
54 
55 /* An adapter to use errx with libofmt. */
56 void
57 ktest_ofmt_errx(const char *fmt, ...)
58 {
59 	va_list ap;
60 
61 	va_start(ap, fmt);
62 	verrx(EXIT_FAILURE, fmt, ap);
63 }
64 
65 typedef enum ktest_fmt_fields {
66 	KTEST_FMT_RESULT,
67 	KTEST_FMT_MODULE,
68 	KTEST_FMT_SUITE,
69 	KTEST_FMT_TEST,
70 	KTEST_FMT_INPUT_FLAG,
71 	KTEST_FMT_INPUT_PATH,
72 	KTEST_FMT_LINE,
73 	KTEST_FMT_REASON,
74 } ktest_fmt_fields_t;
75 
76 typedef struct ktest_list_ofmt {
77 	char *klof_module;
78 	char *klof_suite;
79 	char *klof_test;
80 	boolean_t klof_input;
81 } ktest_list_ofmt_t;
82 
83 static boolean_t
84 ktest_list_ofmt_cb(ofmt_arg_t *ofarg, char *buf, uint_t len)
85 {
86 	ktest_list_ofmt_t *klof = ofarg->ofmt_cbarg;
87 
88 	switch (ofarg->ofmt_id) {
89 	case KTEST_FMT_MODULE:
90 		if (snprintf(buf, len, "%s", klof->klof_module) >= len) {
91 			return (B_FALSE);
92 		}
93 		break;
94 
95 	case KTEST_FMT_SUITE:
96 		if (snprintf(buf, len, "%s", klof->klof_suite) >= len) {
97 			return (B_FALSE);
98 		}
99 		break;
100 
101 	case KTEST_FMT_TEST:
102 		if (snprintf(buf, len, "%s", klof->klof_test) >= len) {
103 			return (B_FALSE);
104 		}
105 		break;
106 
107 	case KTEST_FMT_INPUT_FLAG: {
108 		const char *flag = klof->klof_input ? "Y" : "N";
109 
110 		if (snprintf(buf, len, "%s", flag) >= len) {
111 			return (B_FALSE);
112 		}
113 	}
114 	}
115 
116 	return (B_TRUE);
117 }
118 
119 #define	KTEST_LIST_CMD_DEF_FIELDS	"module,suite,test,input"
120 
121 static const ofmt_field_t ktest_list_ofmt[] = {
122 	{ "MODULE", 12, KTEST_FMT_MODULE, ktest_list_ofmt_cb },
123 	{ "SUITE", 16, KTEST_FMT_SUITE, ktest_list_ofmt_cb },
124 	{ "TEST", 45, KTEST_FMT_TEST, ktest_list_ofmt_cb },
125 	{ "INPUT", 7, KTEST_FMT_INPUT_FLAG, ktest_list_ofmt_cb },
126 	{ NULL, 0, 0, NULL },
127 };
128 
129 static const char *
130 ktest_result_str(ktest_result_t *result)
131 {
132 	switch (result->kr_type) {
133 	case KTEST_RESULT_NONE:
134 		return ("NONE");
135 	case KTEST_RESULT_PASS:
136 		return ("PASS");
137 	case KTEST_RESULT_FAIL:
138 		return ("FAIL");
139 	case KTEST_RESULT_SKIP:
140 		return ("SKIP");
141 	case KTEST_RESULT_ERROR:
142 		return ("ERROR");
143 	}
144 
145 	/* Make the compiler happy. */
146 	return ("NONE");
147 }
148 
149 static boolean_t
150 ktest_run_ofmt_cb(ofmt_arg_t *ofarg, char *buf, uint_t len)
151 {
152 	ktest_run_op_t *op = ofarg->ofmt_cbarg;
153 	ktest_result_t *res = &op->kro_result;
154 
155 	switch (ofarg->ofmt_id) {
156 	case KTEST_FMT_RESULT:
157 		if (snprintf(buf, len, "%s", ktest_result_str(res)) >= len) {
158 			return (B_FALSE);
159 		}
160 		break;
161 
162 	case KTEST_FMT_MODULE:
163 		if (snprintf(buf, len, "%s", op->kro_module) >= len) {
164 			return (B_FALSE);
165 		}
166 		break;
167 
168 	case KTEST_FMT_SUITE:
169 		if (snprintf(buf, len, "%s", op->kro_suite) >= len) {
170 			return (B_FALSE);
171 		}
172 		break;
173 
174 	case KTEST_FMT_TEST:
175 		if (snprintf(buf, len, "%s", op->kro_test) >= len) {
176 			return (B_FALSE);
177 		}
178 		break;
179 
180 	case KTEST_FMT_INPUT_PATH: {
181 		if (snprintf(buf, len, "%s", op->kro_input_path) >= len) {
182 			return (B_FALSE);
183 		}
184 		break;
185 	}
186 
187 	case KTEST_FMT_LINE:
188 		if (snprintf(buf, len, "%d", op->kro_result.kr_line) >= len) {
189 			return (B_FALSE);
190 		}
191 		break;
192 
193 	case KTEST_FMT_REASON: {
194 		if (snprintf(buf, len, "%s%s", res->kr_msg_prepend,
195 		    res->kr_msg) >= len) {
196 			return (B_FALSE);
197 		}
198 		break;
199 	}
200 	}
201 
202 	return (B_TRUE);
203 }
204 
205 /*
206  * The 'run' and 'run-file' commands share the same fields.
207  */
208 #define	KTEST_RUN_CMD_DEF_FIELDS	"result,line,module,suite,test"
209 
210 /*
211  * The input column for the run command is for displaying the path to
212  * the input file, as opposed to the list command which indicates if
213  * the test requires input or not.
214  */
215 static const ofmt_field_t ktest_run_ofmt[] = {
216 	{ "RESULT", 7, KTEST_FMT_RESULT, ktest_run_ofmt_cb },
217 	{ "MODULE", 12, KTEST_FMT_MODULE, ktest_run_ofmt_cb },
218 	{ "SUITE", 16, KTEST_FMT_SUITE, ktest_run_ofmt_cb },
219 	{ "TEST", 45, KTEST_FMT_TEST, ktest_run_ofmt_cb },
220 	{ "INPUT", 48, KTEST_FMT_INPUT_PATH, ktest_run_ofmt_cb },
221 	{ "LINE", 6, KTEST_FMT_LINE, ktest_run_ofmt_cb },
222 	{ "REASON", 256, KTEST_FMT_REASON, ktest_run_ofmt_cb },
223 	{ NULL, 0, 0, NULL },
224 };
225 
226 typedef enum ktest_stat_type {
227 	KTEST_STAT_MOD,
228 	KTEST_STAT_SUITE,
229 } ktest_stat_type_t;
230 
231 typedef struct ktest_stats {
232 	list_node_t		ks_node;
233 	ktest_stat_type_t	ks_type;
234 	char			*ks_name;
235 	uint32_t		ks_total;
236 	uint32_t		ks_pass;
237 	uint32_t		ks_fail;
238 	uint32_t		ks_err;
239 	uint32_t		ks_skip;
240 	uint32_t		ks_none;
241 } ktest_stats_t;
242 
243 static ktest_stats_t *
244 ktest_stats_new(ktest_stat_type_t type, const char *name)
245 {
246 	ktest_stats_t *stats;
247 
248 	if ((stats = malloc(sizeof (ktest_stats_t))) == NULL) {
249 		err(EXIT_FAILURE, "failed to allocate stats structure");
250 	}
251 
252 	stats->ks_type = type;
253 	stats->ks_name = strndup(name, KTEST_MAX_NAME_LEN);
254 
255 	if (stats->ks_name == NULL) {
256 		err(EXIT_FAILURE, "failed to allocate stats name");
257 	}
258 
259 	stats->ks_total = 0;
260 	stats->ks_pass = 0;
261 	stats->ks_fail = 0;
262 	stats->ks_err = 0;
263 	stats->ks_skip = 0;
264 	stats->ks_none = 0;
265 	return (stats);
266 }
267 
268 static void
269 ktest_record_stat(ktest_stats_t *mod, ktest_stats_t *suite,
270     const ktest_result_t *res)
271 {
272 	mod->ks_total++;
273 	suite->ks_total++;
274 
275 	switch (res->kr_type) {
276 	case KTEST_RESULT_NONE:
277 		mod->ks_none++;
278 		suite->ks_none++;
279 		break;
280 
281 	case KTEST_RESULT_PASS:
282 		mod->ks_pass++;
283 		suite->ks_pass++;
284 		break;
285 
286 	case KTEST_RESULT_FAIL:
287 		mod->ks_fail++;
288 		suite->ks_fail++;
289 		break;
290 
291 	case KTEST_RESULT_SKIP:
292 		mod->ks_skip++;
293 		suite->ks_skip++;
294 		break;
295 
296 	case KTEST_RESULT_ERROR:
297 		mod->ks_err++;
298 		suite->ks_err++;
299 		break;
300 	}
301 }
302 
303 typedef enum ktest_fmt_stats {
304 	KTEST_FMT_STATS_MS,
305 	KTEST_FMT_STATS_TOTAL,
306 	KTEST_FMT_STATS_PASS,
307 	KTEST_FMT_STATS_FAIL,
308 	KTEST_FMT_STATS_ERR,
309 	KTEST_FMT_STATS_SKIP,
310 	KTEST_FMT_STATS_NONE,
311 } ktest_fmt_stats_t;
312 
313 static boolean_t
314 ktest_stats_ofmt_cb(ofmt_arg_t *ofarg, char *buf, uint_t len)
315 {
316 	ktest_stats_t *stats = ofarg->ofmt_cbarg;
317 
318 	switch (ofarg->ofmt_id) {
319 	case KTEST_FMT_STATS_MS: {
320 		char *pre = (stats->ks_type == KTEST_STAT_MOD) ? "" : "  ";
321 
322 		if (snprintf(buf, len, "%s%s", pre, stats->ks_name) >= len) {
323 			return (B_FALSE);
324 		}
325 		break;
326 	}
327 
328 	case KTEST_FMT_STATS_TOTAL:
329 		if (snprintf(buf, len, "%" PRIu32, stats->ks_total) >= len) {
330 			return (B_FALSE);
331 		}
332 		break;
333 
334 	case KTEST_FMT_STATS_PASS:
335 		if (snprintf(buf, len, "%" PRIu32, stats->ks_pass) >= len) {
336 			return (B_FALSE);
337 		}
338 		break;
339 
340 	case KTEST_FMT_STATS_FAIL:
341 		if (snprintf(buf, len, "%" PRIu32, stats->ks_fail) >= len) {
342 			return (B_FALSE);
343 		}
344 		break;
345 
346 	case KTEST_FMT_STATS_ERR:
347 		if (snprintf(buf, len, "%" PRIu32, stats->ks_err) >= len) {
348 			return (B_FALSE);
349 		}
350 		break;
351 
352 	case KTEST_FMT_STATS_SKIP:
353 		if (snprintf(buf, len, "%" PRIu32, stats->ks_skip) >= len) {
354 			return (B_FALSE);
355 		}
356 		break;
357 
358 	case KTEST_FMT_STATS_NONE:
359 		if (snprintf(buf, len, "%" PRIu32, stats->ks_none) >= len) {
360 			return (B_FALSE);
361 		}
362 		break;
363 	}
364 
365 	return (B_TRUE);
366 }
367 
368 #define	KTEST_STATS_FIELDS	"module/suite,total,pass,fail,err,skip,none"
369 
370 static const ofmt_field_t ktest_stats_ofmt[] = {
371 	{ "MODULE/SUITE", 40, KTEST_FMT_STATS_MS, ktest_stats_ofmt_cb },
372 	{ "TOTAL", 6, KTEST_FMT_STATS_TOTAL, ktest_stats_ofmt_cb },
373 	{ "PASS", 6, KTEST_FMT_STATS_PASS, ktest_stats_ofmt_cb },
374 	{ "FAIL", 6, KTEST_FMT_STATS_FAIL, ktest_stats_ofmt_cb },
375 	{ "ERR", 6, KTEST_FMT_STATS_ERR, ktest_stats_ofmt_cb },
376 	{ "SKIP", 6, KTEST_FMT_STATS_SKIP, ktest_stats_ofmt_cb },
377 	{ "NONE", 6, KTEST_FMT_STATS_NONE, ktest_stats_ofmt_cb },
378 };
379 
380 static void
381 ktest_usage(const char *fmt, ...)
382 {
383 	if (fmt != NULL) {
384 		va_list ap;
385 
386 		va_start(ap, fmt);
387 		vwarnx(fmt, ap);
388 		va_end(ap);
389 	}
390 
391 	(void) fprintf(stderr,
392 	    "usage: %s <subcommand> [<opts>] [<args>]\n\n"
393 	    "\tlist [-H] [[-p] -o field,...] [<triple> ...]: "
394 	    "list registered tests\n"
395 	    "\trun [-H] [[-p] -o field,...] [-i <file>] <triple> ...: "
396 	    "run specified tests\n"
397 	    "\trun-file [-H] [[-p] -o field,...] [<runfile>]: "
398 	    "run tests specified in runfile\n",
399 	    ktest_prog);
400 }
401 
402 /*
403  * A user-specified test triple. The input path is set to the empty
404  * string if no input is provided. The line number provides useful
405  * error reporting when an error is encountered in the run file.
406  */
407 typedef struct ktest_triple {
408 	list_node_t	ktr_node;
409 	char		ktr_module[KTEST_MAX_NAME_LEN];
410 	char		ktr_suite[KTEST_MAX_NAME_LEN];
411 	char		ktr_test[KTEST_MAX_NAME_LEN];
412 	char		ktr_input_path[MAXPATHLEN];
413 	uint32_t	ktr_lineno;
414 } ktest_triple_t;
415 
416 /* The default triple matches all tests. */
417 static ktest_triple_t *ktest_def_triple;
418 
419 /*
420  * A test description obtained from iterating the list tests nvlist.
421  */
422 typedef struct ktest_test_desc {
423 	char		*ktd_module;
424 	char		*ktd_suite;
425 	char		*ktd_test;
426 	boolean_t	ktd_requires_input;
427 } ktest_test_desc_t;
428 
429 static void
430 ktest_test_desc_init(ktest_test_desc_t *desc)
431 {
432 	desc->ktd_module = NULL;
433 	desc->ktd_suite = NULL;
434 	desc->ktd_test = NULL;
435 	desc->ktd_requires_input = B_FALSE;
436 }
437 
438 static void
439 ktest_free_triples(list_t *triples)
440 {
441 	ktest_triple_t *t = NULL;
442 
443 	while ((t = list_remove_head(triples)) != NULL) {
444 		free(t);
445 	}
446 }
447 
448 /*
449  * Does the test descriptor match this triple? The descriptor will
450  * always have module name present, but the suite and test names may
451  * or may not be present.
452  */
453 static boolean_t
454 ktest_match_triple(const ktest_test_desc_t *desc, const ktest_triple_t *triple)
455 {
456 	/* Must at least specify the module. */
457 	VERIFY(desc->ktd_module != NULL);
458 
459 	if (desc->ktd_suite != NULL && desc->ktd_test != NULL) {
460 		return (gmatch(desc->ktd_module, triple->ktr_module) != 0 &&
461 		    gmatch(desc->ktd_suite, triple->ktr_suite) != 0 &&
462 		    gmatch(desc->ktd_test, triple->ktr_test) != 0);
463 	} else if (desc->ktd_suite != NULL) {
464 		return (gmatch(desc->ktd_module, triple->ktr_module) != 0 &&
465 		    gmatch(desc->ktd_suite, triple->ktr_suite) != 0);
466 	}
467 
468 	return (gmatch(desc->ktd_module, triple->ktr_module) != 0);
469 }
470 
471 /*
472  * Does the test descriptor match any of the triples?
473  */
474 static boolean_t
475 ktest_match_any(const ktest_test_desc_t *desc, list_t *triples)
476 {
477 	for (ktest_triple_t *triple = list_head(triples); triple != NULL;
478 	    triple = list_next(triples, triple)) {
479 		if (ktest_match_triple(desc, triple)) {
480 			return (B_TRUE);
481 		}
482 	}
483 
484 	return (B_FALSE);
485 }
486 
487 typedef struct ktest_iter {
488 	/*
489 	 * The list of all modules and current module the iterator is on.
490 	 */
491 	nvlist_t	*ki_modules;
492 	nvpair_t	*ki_module;
493 
494 	/*
495 	 * The list of all suites in the current module and the
496 	 * current suite the iterator is on.
497 	 */
498 	nvlist_t	*ki_suites;
499 	nvpair_t	*ki_suite;
500 
501 	/*
502 	 * The list of all tests in the current suite and the current
503 	 * test the iterator is on.
504 	 */
505 	nvlist_t	*ki_tests;
506 	nvpair_t	*ki_test;
507 
508 	ktest_test_desc_t	ki_desc;
509 
510 	/*
511 	 * A list of ktest_triple_t used to filter the tests returned
512 	 * by the iterator.
513 	 */
514 	list_t		*ki_triples;
515 } ktest_iter_t;
516 
517 static char *
518 ktest_module_name(nvpair_t *module)
519 {
520 	nvlist_t *desc = fnvpair_value_nvlist(module);
521 	return (fnvlist_lookup_string(desc, KTEST_NAME_KEY));
522 }
523 
524 static nvlist_t *
525 ktest_module_suites(nvpair_t *module)
526 {
527 	nvlist_t *desc = fnvpair_value_nvlist(module);
528 	return (fnvlist_lookup_nvlist(desc, KTEST_MODULE_SUITES_KEY));
529 }
530 
531 static char *
532 ktest_suite_name(nvpair_t *suite)
533 {
534 	nvlist_t *desc = fnvpair_value_nvlist(suite);
535 	return (fnvlist_lookup_string(desc, KTEST_NAME_KEY));
536 }
537 
538 static nvlist_t *
539 ktest_suite_tests(nvpair_t *suite)
540 {
541 	nvlist_t *desc = fnvpair_value_nvlist(suite);
542 	return (fnvlist_lookup_nvlist(desc, KTEST_SUITE_TESTS_KEY));
543 }
544 
545 static char *
546 ktest_test_name(nvpair_t *test)
547 {
548 	nvlist_t *desc = fnvpair_value_nvlist(test);
549 	return (fnvlist_lookup_string(desc, KTEST_NAME_KEY));
550 }
551 
552 static boolean_t
553 ktest_test_requires_input(nvpair_t *test)
554 {
555 	nvlist_t *desc = fnvpair_value_nvlist(test);
556 	return (fnvlist_lookup_boolean_value(desc, KTEST_TEST_INPUT_KEY));
557 }
558 
559 static ktest_iter_t *
560 ktest_iter(nvlist_t *tests, list_t *triples)
561 {
562 	ktest_iter_t *iter = malloc(sizeof (ktest_iter_t));
563 
564 	if (iter == NULL) {
565 		err(EXIT_FAILURE, "failed to allocate test iterator");
566 	}
567 
568 	iter->ki_modules = tests;
569 	iter->ki_module = nvlist_next_nvpair(tests, NULL);
570 
571 	iter->ki_suites = NULL;
572 	iter->ki_suite = NULL;
573 
574 	iter->ki_tests = NULL;
575 	iter->ki_test = NULL;
576 
577 	ktest_test_desc_init(&iter->ki_desc);
578 
579 	iter->ki_triples = triples;
580 	return (iter);
581 }
582 
583 #define	KT_NEXT_TEST(iter)						\
584 	(nvlist_next_nvpair((iter)->ki_tests, (iter)->ki_test))
585 
586 static boolean_t
587 ktest_iter_tests(ktest_iter_t *iter, ktest_test_desc_t *desc)
588 {
589 	if (iter->ki_test == NULL) {
590 		iter->ki_test = KT_NEXT_TEST(iter);
591 	}
592 
593 	for (; iter->ki_test != NULL; iter->ki_test = KT_NEXT_TEST(iter)) {
594 		iter->ki_desc.ktd_test = ktest_test_name(iter->ki_test);
595 		iter->ki_desc.ktd_requires_input =
596 		    ktest_test_requires_input(iter->ki_test);
597 
598 		/*
599 		 * We found a match and are returning control to the
600 		 * ktest_iter_next() caller; but we first need to copy
601 		 * the matching descriptor and move the iterator to
602 		 * the next test in preparation for the next call to
603 		 * ktest_iter_next().
604 		 */
605 		if (ktest_match_any(&iter->ki_desc, iter->ki_triples)) {
606 			*desc = iter->ki_desc;
607 			iter->ki_test = KT_NEXT_TEST(iter);
608 			return (B_TRUE);
609 		}
610 	}
611 
612 	return (B_FALSE);
613 }
614 
615 #define	KT_NEXT_SUITE(iter)						\
616 	(nvlist_next_nvpair((iter)->ki_suites, (iter)->ki_suite))
617 
618 static boolean_t
619 ktest_iter_suites(ktest_iter_t *iter, ktest_test_desc_t *desc)
620 {
621 	if (iter->ki_suite == NULL) {
622 		iter->ki_suite = KT_NEXT_SUITE(iter);
623 	}
624 
625 	for (; iter->ki_suite != NULL; iter->ki_suite = KT_NEXT_SUITE(iter)) {
626 		iter->ki_desc.ktd_suite = ktest_suite_name(iter->ki_suite);
627 
628 		if (!ktest_match_any(&iter->ki_desc, iter->ki_triples)) {
629 			continue;
630 		}
631 
632 		iter->ki_tests = ktest_suite_tests(iter->ki_suite);
633 
634 		if (ktest_iter_tests(iter, desc)) {
635 			/*
636 			 * We've iterated all tests in the suite, move
637 			 * to the next one.
638 			 */
639 			if (iter->ki_test == NULL) {
640 				iter->ki_suite = KT_NEXT_SUITE(iter);
641 			}
642 
643 			return (B_TRUE);
644 		}
645 	}
646 
647 	return (B_FALSE);
648 }
649 
650 #define	KT_NEXT_MOD(iter)						\
651 	(nvlist_next_nvpair((iter)->ki_modules, (iter)->ki_module))
652 
653 static boolean_t
654 ktest_iter_next(ktest_iter_t *iter, ktest_test_desc_t *desc)
655 {
656 	for (; iter->ki_module != NULL; iter->ki_module = KT_NEXT_MOD(iter)) {
657 		ktest_test_desc_init(&iter->ki_desc);
658 		iter->ki_desc.ktd_module = ktest_module_name(iter->ki_module);
659 
660 		if (!ktest_match_any(&iter->ki_desc, iter->ki_triples)) {
661 			continue;
662 		}
663 
664 		iter->ki_suites = ktest_module_suites(iter->ki_module);
665 
666 		if (ktest_iter_suites(iter, desc)) {
667 			/*
668 			 * We've iterated all suites in the module,
669 			 * move to the next one.
670 			 */
671 			if (iter->ki_suite == NULL) {
672 				iter->ki_module = KT_NEXT_MOD(iter);
673 			}
674 
675 			return (B_TRUE);
676 		}
677 	}
678 
679 	return (B_FALSE);
680 }
681 
682 /*
683  * Get a list of tests from the in-kernel ktest registry.
684  */
685 static nvlist_t *
686 ktest_list_tests(int dev)
687 {
688 	int ret = 0;
689 	nvlist_t *tests = NULL;
690 	boolean_t retry = B_FALSE;
691 	ktest_list_op_t klo;
692 	size_t resp_len = 1 * 1024 * 1024;
693 	char *resp = NULL;
694 	uint64_t vsn = 0;
695 
696 	if ((resp = malloc(resp_len)) == NULL) {
697 		err(EXIT_FAILURE, "failed to allocate response buffer");
698 	}
699 
700 	bzero(resp, resp_len);
701 	klo.klo_resp = resp;
702 	klo.klo_resp_len = resp_len;
703 
704 retry:
705 	ret = ioctl(dev, KTEST_IOCTL_LIST_TESTS, &klo);
706 
707 	if (ret == -1 && errno == ENOBUFS && !retry) {
708 		free(resp);
709 		resp_len = klo.klo_resp_len;
710 
711 		if ((resp = malloc(resp_len)) == NULL) {
712 			err(EXIT_FAILURE, "failed to allocate response buffer");
713 		}
714 
715 		bzero(resp, resp_len);
716 		retry = B_TRUE;
717 		goto retry;
718 	} else if (ret == -1) {
719 		err(EXIT_FAILURE, "list ioctl failed");
720 	}
721 
722 	resp_len = klo.klo_resp_len;
723 
724 	if ((ret = nvlist_unpack(resp, resp_len, &tests, 0)) != 0) {
725 		errx(EXIT_FAILURE, "failed to unpack list response: %s",
726 		    strerror(ret));
727 	}
728 
729 	free(resp);
730 
731 	/*
732 	 * Verify that the response is marked with the expected
733 	 * serialization format. Remove the nvpair so that only the
734 	 * modules remain.
735 	 */
736 	if (nvlist_lookup_uint64(tests, KTEST_SER_FMT_KEY, &vsn) != 0) {
737 		errx(EXIT_FAILURE, "invalid list response, missing %s key\n",
738 		    KTEST_SER_FMT_KEY);
739 	}
740 
741 	if (vsn != KTEST_SER_FMT_VSN) {
742 		errx(EXIT_FAILURE,
743 		    "invalid serialization format version: %" PRIu64 "\n", vsn);
744 	}
745 
746 	fnvlist_remove(tests, KTEST_SER_FMT_KEY);
747 	return (tests);
748 }
749 
750 static void
751 ktest_print_tests(nvlist_t *tests, list_t *triples, ofmt_handle_t ofmt)
752 {
753 	ktest_iter_t *iter = ktest_iter(tests, triples);
754 	ktest_test_desc_t desc;
755 
756 	while (ktest_iter_next(iter, &desc)) {
757 		ktest_list_ofmt_t klof;
758 
759 		klof.klof_module = desc.ktd_module;
760 		klof.klof_suite = desc.ktd_suite;
761 		klof.klof_test = desc.ktd_test;
762 		klof.klof_input = desc.ktd_requires_input;
763 		ofmt_print(ofmt, &klof);
764 	}
765 
766 	free(iter);
767 }
768 
769 static void
770 ktest_print_stats(list_t *stats)
771 {
772 	ktest_stats_t *stat;
773 	ofmt_handle_t stats_ofmt;
774 	ofmt_status_t oferr;
775 	boolean_t first = B_FALSE;
776 
777 	oferr = ofmt_open(KTEST_STATS_FIELDS, ktest_stats_ofmt, 0, 0,
778 	    &stats_ofmt);
779 	ofmt_check(oferr, B_FALSE, stats_ofmt, ktest_ofmt_errx, warnx);
780 
781 	for (stat = list_head(stats); stat != NULL;
782 	    stat = list_next(stats, stat)) {
783 		if (!first && stat->ks_type == KTEST_STAT_MOD) {
784 			printf("\n");
785 		}
786 
787 		ofmt_print(stats_ofmt, stat);
788 
789 		if (stat->ks_type == KTEST_STAT_MOD) {
790 			first = B_FALSE;
791 			ktest_print_hr(74);
792 		}
793 	}
794 
795 	ofmt_close(stats_ofmt);
796 }
797 
798 /*
799  * Read file at path into the byte array. The byte array is allocated
800  * as part of this function and ownership is given to the caller via
801  * the bytes argument along with its length returned by 'len'. If an
802  * error occurs while reading, the 'err' string is filled in with the
803  * appropriate error message.
804  *
805  * It might be nice to replace this with kobj_{open,read}_file() in
806  * the ktest kernel module to avoid shuffling bytes between user and
807  * kernel (see devcache which uses these private APIs for the purpose
808  * of reading serialized nvlists).
809  */
810 static boolean_t
811 ktest_read_file(const char *path, uchar_t **bytes, uint64_t *len, char *err)
812 {
813 	FILE *f;
814 	struct stat stats;
815 	uchar_t *tmp_bytes;
816 	uint64_t tmp_len;
817 
818 	*bytes = NULL;
819 	*len = 0;
820 
821 	if ((f = fopen(path, "r")) == NULL) {
822 		(void) strcpy(err, "failed to open input file");
823 		return (B_FALSE);
824 	}
825 
826 	if (fstat(fileno(f), &stats) == -1) {
827 		(void) fclose(f);
828 		(void) strcpy(err, "failed to stat input file");
829 		return (B_FALSE);
830 	}
831 
832 	tmp_len = (uint64_t)stats.st_size;
833 
834 	if ((tmp_bytes = malloc(tmp_len)) == NULL) {
835 		(void) fclose(f);
836 		(void) strcpy(err, "failed to allocate byte array of size");
837 		return (B_FALSE);
838 	}
839 
840 	if (fread(tmp_bytes, sizeof (*tmp_bytes), tmp_len, f) != tmp_len) {
841 		(void) fclose(f);
842 		(void) snprintf(err, KTEST_MAX_LOG_LEN,
843 		    "failed to read %u bytes from input file", tmp_len);
844 		return (B_FALSE);
845 	}
846 
847 	*bytes = tmp_bytes;
848 	*len = tmp_len;
849 	return (B_TRUE);
850 }
851 
852 static boolean_t
853 ktest_run_test(int dev, const ktest_test_desc_t *desc, const char *input_path,
854     ktest_stats_t *mod_stats, ktest_stats_t *suite_stats, ofmt_handle_t ofmt)
855 {
856 	ktest_run_op_t kro;
857 	char err_msg[KTEST_MAX_LOG_LEN];
858 
859 	/*
860 	 * It is up to the caller to ensure that an input path is
861 	 * specified when a test requires it.
862 	 */
863 	if (desc->ktd_requires_input) {
864 		VERIFY(input_path != NULL);
865 	}
866 
867 	bzero(&err_msg, KTEST_MAX_LOG_LEN);
868 	bzero(&kro, sizeof (kro));
869 
870 	/*
871 	 * The module/suite/test come from the kernel's list tests
872 	 * nvlist which we know contain properly sized strings.
873 	 */
874 	(void) strlcpy(kro.kro_module, desc->ktd_module, KTEST_MAX_NAME_LEN);
875 	(void) strlcpy(kro.kro_suite, desc->ktd_suite, KTEST_MAX_NAME_LEN);
876 	(void) strlcpy(kro.kro_test, desc->ktd_test, KTEST_MAX_NAME_LEN);
877 
878 	if (input_path != NULL) {
879 		uchar_t *bytes = NULL;
880 		uint64_t len = 0;
881 
882 		/*
883 		 * The input_path came from the ktest_triple_t which
884 		 * we know contains a properly sized string.
885 		 */
886 		(void) strlcpy(kro.kro_input_path, input_path,
887 		    sizeof (kro.kro_input_path));
888 
889 		/*
890 		 * We treat a failure to read the input file as a test
891 		 * error.
892 		 */
893 		if (!ktest_read_file(input_path, &bytes, &len, err_msg)) {
894 			kro.kro_result.kr_type = KTEST_RESULT_ERROR;
895 			(void) strlcpy(kro.kro_result.kr_msg, err_msg,
896 			    KTEST_MAX_LOG_LEN);
897 			ktest_record_stat(mod_stats, suite_stats,
898 			    &kro.kro_result);
899 			ofmt_print(ofmt, &kro);
900 			return (B_FALSE);
901 		}
902 
903 		/*
904 		 * The input stream must contain at least 1 byte.
905 		 */
906 		if (len == 0) {
907 			kro.kro_result.kr_type = KTEST_RESULT_ERROR;
908 			(void) strcpy(kro.kro_result.kr_msg,
909 			    "zero-length input stream");
910 			ktest_record_stat(mod_stats, suite_stats,
911 			    &kro.kro_result);
912 			ofmt_print(ofmt, &kro);
913 			return (B_FALSE);
914 		}
915 
916 		kro.kro_input_len = len;
917 		kro.kro_input_bytes = bytes;
918 	}
919 
920 	if (ioctl(dev, KTEST_IOCTL_RUN_TEST, &kro) == -1) {
921 		if (input_path != NULL) {
922 			err(EXIT_FAILURE, "failed to run test %s:%s:%s with "
923 			    "input %s", desc->ktd_module, desc->ktd_suite,
924 			    desc->ktd_test, input_path);
925 		} else {
926 			err(EXIT_FAILURE, "failed to run test %s:%s:%s",
927 			    desc->ktd_module, desc->ktd_suite, desc->ktd_test);
928 		}
929 	}
930 
931 	ktest_record_stat(mod_stats, suite_stats, &kro.kro_result);
932 	ofmt_print(ofmt, &kro);
933 	return (kro.kro_result.kr_type == KTEST_RESULT_PASS ||
934 	    kro.kro_result.kr_type == KTEST_RESULT_SKIP);
935 }
936 
937 /*
938  * Run all tests specified in the run list and print the result of
939  * each test. If print_stats is true, the result statistics are
940  * printed as well. A return of true indicates all tests passed. A
941  * return of false indicates one or more tests produced an ERROR or
942  * FAIL result.
943  */
944 static boolean_t
945 ktest_run_tests(int dev, nvlist_t *tests, list_t *run_list, ofmt_handle_t ofmt,
946     boolean_t print_stats)
947 {
948 	ktest_iter_t *iter = ktest_iter(tests, run_list);
949 	ktest_test_desc_t desc;
950 	ktest_stats_t *mod_stats = NULL;
951 	ktest_stats_t *suite_stats = NULL;
952 	list_t stats;
953 	ktest_stats_t *stat = NULL;
954 	boolean_t all_pass = B_TRUE;
955 
956 	ktest_test_desc_init(&desc);
957 	list_create(&stats, sizeof (ktest_stats_t),
958 	    offsetof(ktest_stats_t, ks_node));
959 
960 	while (ktest_iter_next(iter, &desc)) {
961 		/*
962 		 * Either this is our first matching test or we are
963 		 * transitioning to a new module and/or suite. In
964 		 * either case, create new stats structures and add
965 		 * them to the list.
966 		 */
967 		if (mod_stats == NULL ||
968 		    strcmp(mod_stats->ks_name, desc.ktd_module) != 0) {
969 			mod_stats = ktest_stats_new(KTEST_STAT_MOD,
970 			    desc.ktd_module);
971 			list_insert_tail(&stats, mod_stats);
972 		}
973 
974 		if (suite_stats == NULL ||
975 		    strcmp(suite_stats->ks_name, desc.ktd_suite) != 0) {
976 			suite_stats = ktest_stats_new(KTEST_STAT_SUITE,
977 			    desc.ktd_suite);
978 			list_insert_tail(&stats, suite_stats);
979 		}
980 
981 		/*
982 		 * A test that does not require input only has to run
983 		 * once.
984 		 */
985 		if (!desc.ktd_requires_input) {
986 			if (!ktest_run_test(dev, &desc, NULL, mod_stats,
987 			    suite_stats, ofmt)) {
988 				all_pass = B_FALSE;
989 			}
990 			continue;
991 		}
992 
993 		/*
994 		 * A test that requires input may have more than one
995 		 * matching triple. This feature allows a user to
996 		 * specify multiple input streams for the same test
997 		 * where each input stream is a separate run of the
998 		 * test. We iterate the run list; running the test
999 		 * for each triple that matches and has an input path
1000 		 * specified.
1001 		 */
1002 		for (ktest_triple_t *triple = list_head(run_list);
1003 		    triple != NULL;
1004 		    triple = list_next(run_list, triple)) {
1005 			if (ktest_match_triple(&desc, triple) &&
1006 			    triple->ktr_input_path[0] != '\0') {
1007 				if (!ktest_run_test(dev, &desc,
1008 				    triple->ktr_input_path, mod_stats,
1009 				    suite_stats, ofmt)) {
1010 					all_pass = B_FALSE;
1011 				}
1012 			}
1013 		}
1014 	}
1015 
1016 	if (print_stats) {
1017 		printf("\n");
1018 		ktest_print_stats(&stats);
1019 	}
1020 
1021 	while ((stat = list_remove_head(&stats)) != NULL) {
1022 		free(stat);
1023 	}
1024 
1025 	list_destroy(&stats);
1026 	free(iter);
1027 	return (all_pass);
1028 }
1029 
1030 /*
1031  * Attempt to parse the test triple string and return the resulting
1032  * triple struct. This leaves the original triple string untouched.
1033  *
1034  * This function produces a warning when failing to parse a triple,
1035  * this is on purpose. This allows the run file parser to produce an
1036  * error that points out the line number with the bad triple.
1037  */
1038 static ktest_triple_t *
1039 ktest_parse_triple(const char *tstr, uint32_t lineno)
1040 {
1041 	char *cp = NULL, *orig = NULL;
1042 	char *module = NULL;
1043 	char *suite = NULL;
1044 	char *test = NULL;
1045 	ktest_triple_t *triple = NULL;
1046 
1047 	if ((triple = calloc(1, sizeof (*triple))) == NULL) {
1048 		warn("failed to allocate triple");
1049 		return (NULL);
1050 	}
1051 
1052 	triple->ktr_lineno = lineno;
1053 
1054 	if (strnlen(tstr, KTEST_MAX_TRIPLE_LEN) >= KTEST_MAX_TRIPLE_LEN) {
1055 		warnx("triple is too long");
1056 		goto fail;
1057 	}
1058 
1059 	if ((cp = strndup(tstr, KTEST_MAX_TRIPLE_LEN)) == NULL) {
1060 		warn("failed to dup triple string");
1061 		goto fail;
1062 	}
1063 
1064 	orig = cp;
1065 	module = strsep(&cp, KTEST_SEPARATOR);
1066 
1067 	if (strnlen(module, KTEST_MAX_NAME_LEN) >= KTEST_MAX_NAME_LEN) {
1068 		warnx("module pattern too long: %s", module);
1069 		goto fail;
1070 	}
1071 
1072 	if (*module == '\0') {
1073 		module = "*";
1074 	}
1075 
1076 	if (cp == NULL) {
1077 		suite = "*";
1078 		test = "*";
1079 		goto copy;
1080 	}
1081 
1082 	suite = strsep(&cp, KTEST_SEPARATOR);
1083 
1084 	if (strnlen(suite, KTEST_MAX_NAME_LEN) >= KTEST_MAX_NAME_LEN) {
1085 		warnx("suite pattern too long: %s", suite);
1086 		goto fail;
1087 	}
1088 
1089 	if (*suite == '\0') {
1090 		suite = "*";
1091 	}
1092 
1093 	if (cp == NULL) {
1094 		test = "*";
1095 		goto copy;
1096 	}
1097 
1098 	test = cp;
1099 
1100 	if (strstr(cp, KTEST_SEPARATOR) != NULL) {
1101 		warnx("malformed triple, unexpected ':' in test pattern: %s",
1102 		    test);
1103 		goto fail;
1104 	}
1105 
1106 	if (strnlen(test, KTEST_MAX_NAME_LEN) >= KTEST_MAX_NAME_LEN) {
1107 		warnx("test pattern too long: %s", test);
1108 		goto fail;
1109 	}
1110 
1111 	if (*test == '\0') {
1112 		test = "*";
1113 	}
1114 
1115 copy:
1116 	/* We've checked the string lengths, but just in case. */
1117 	(void) strlcpy(triple->ktr_module, module, sizeof (triple->ktr_module));
1118 	(void) strlcpy(triple->ktr_suite, suite, sizeof (triple->ktr_suite));
1119 	(void) strlcpy(triple->ktr_test, test, sizeof (triple->ktr_test));
1120 	free(orig);
1121 	return (triple);
1122 
1123 fail:
1124 	free(orig);
1125 	free(triple);
1126 	return (NULL);
1127 }
1128 
1129 /*
1130  * Attempt to load the run file specified and decode it into a run
1131  * list. Use stdin as the content of the runfile when use_stdin is
1132  * true.
1133  *
1134  * Currently all input files must either be relative to the working
1135  * directory or an absolute path. In the future it would be nice to
1136  * support something like glob(3C) to perform tilde expansion for the
1137  * input file path. Another idea would be to add a search path for
1138  * input files, allowing us to more easily constrain where on the
1139  * filesystem these files are searched for.
1140  */
1141 static void
1142 ktest_load_run_file(const char *path, boolean_t use_stdin, nvlist_t *tests,
1143     list_t *run_list)
1144 {
1145 	FILE *f;
1146 	char *line = NULL;
1147 	size_t cap = 0;
1148 	ssize_t len;
1149 	uint32_t lineno = 0;
1150 	boolean_t one_line = B_FALSE; /* At least one valid line? */
1151 
1152 	if (use_stdin) {
1153 		f = stdin;
1154 	} else {
1155 		if ((f = fopen(path, "r")) == NULL) {
1156 			err(EXIT_FAILURE, "failed to open run file %s", path);
1157 		}
1158 	}
1159 
1160 	while ((len = getline(&line, &cap, f)) != -1) {
1161 		char *input, *lasts, *tstr;
1162 		ktest_triple_t *triple;
1163 
1164 		lineno++;
1165 		/* A line is always at least one character: newline. */
1166 		VERIFY3S(len, >=, 1);
1167 		/* Skip the newline. */
1168 		line[len - 1] = '\0';
1169 
1170 		/* Skip empty lines. */
1171 		if (line[0] == '\0') {
1172 			continue;
1173 		}
1174 
1175 		/*
1176 		 * A valid line consists of either a test triple on
1177 		 * its own or a test triple and an input file
1178 		 * separated by whitespace.
1179 		 */
1180 		tstr = strtok_r(line, " \t", &lasts);
1181 		triple = ktest_parse_triple(tstr, lineno);
1182 
1183 		if (triple == NULL) {
1184 			errx(EXIT_FAILURE, "failed to parse triple %s at line "
1185 			    "%u", tstr, lineno);
1186 		}
1187 
1188 		input = strtok_r(NULL, " \t", &lasts);
1189 
1190 		if (input != NULL) {
1191 			size_t len = strlcpy(triple->ktr_input_path, input,
1192 			    sizeof (triple->ktr_input_path));
1193 			if (len >= sizeof (triple->ktr_input_path)) {
1194 				err(EXIT_FAILURE, "input path at line %u too "
1195 				    "long: %s\n", lineno, input);
1196 			}
1197 		}
1198 
1199 		list_insert_tail(run_list, triple);
1200 		one_line = B_TRUE;
1201 	}
1202 
1203 	/*
1204 	 * If we broke from the loop for a reason other than EOF, then
1205 	 * assume we do not have a full run list and exit.
1206 	 */
1207 	if (ferror(f)) {
1208 		err(EXIT_FAILURE, "failed to read entire runfile");
1209 	}
1210 
1211 	if (!use_stdin) {
1212 		(void) fclose(f);
1213 	}
1214 
1215 	free(line);
1216 
1217 	if (!one_line) {
1218 		errx(EXIT_FAILURE, "no tests specified in: %s", path);
1219 	}
1220 }
1221 
1222 /*
1223  * Is this test triple fully-qualified?
1224  *
1225  * A fully-qualified triple is one where the module, suite, and test
1226  * use no glob characters with the intent that it refers to a single,
1227  * unique test.
1228  */
1229 static boolean_t
1230 ktest_is_fqt(const ktest_triple_t *triple)
1231 {
1232 	return (strpbrk(triple->ktr_module, KTEST_GMATCH_CHARS) == NULL &&
1233 	    strpbrk(triple->ktr_suite, KTEST_GMATCH_CHARS) == NULL &&
1234 	    strpbrk(triple->ktr_test, KTEST_GMATCH_CHARS) == NULL);
1235 }
1236 
1237 /*
1238  * Does this fully-qualified triple refer to a test which requires
1239  * input?
1240  */
1241 static boolean_t
1242 ktest_fqt_requires_input(ktest_triple_t *triple, nvlist_t *tests)
1243 {
1244 	list_t filter;
1245 	ktest_iter_t *iter = NULL;
1246 	ktest_test_desc_t desc;
1247 	/*
1248 	 * Need a local copy of the triple in order to build a filter
1249 	 * list for ktest_iter() because the argument is already a
1250 	 * part of the run list and reusing it would clobber its node
1251 	 * link.
1252 	 */
1253 	ktest_triple_t cp = *triple;
1254 
1255 	VERIFY(ktest_is_fqt(triple));
1256 
1257 	list_create(&filter, sizeof (ktest_triple_t),
1258 	    offsetof(ktest_triple_t, ktr_node));
1259 	list_insert_head(&filter, &cp);
1260 	iter = ktest_iter(tests, &filter);
1261 
1262 	if (!ktest_iter_next(iter, &desc)) {
1263 		return (B_FALSE);
1264 	}
1265 
1266 	return (desc.ktd_requires_input);
1267 }
1268 
1269 /*
1270  * Check if the fully-qualified triple has an input path when it
1271  * should. Return true if the entry is okay and false if there is a
1272  * mismatch between the test descriptor the the triple entry.
1273  */
1274 static boolean_t
1275 ktest_check_fqt_entry(nvlist_t *tests, ktest_triple_t *triple)
1276 {
1277 	boolean_t requires_input = ktest_fqt_requires_input(triple, tests);
1278 
1279 	if (requires_input && strlen(triple->ktr_input_path) == 0) {
1280 		warnx("fully-qualified triple %s:%s:%s at line %u missing "
1281 		    "input for test that requires input", triple->ktr_module,
1282 		    triple->ktr_suite, triple->ktr_test, triple->ktr_lineno);
1283 		return (B_FALSE);
1284 	} else if (!requires_input && strlen(triple->ktr_input_path) != 0) {
1285 		warnx("fully-qualified triple %s:%s:%s at line %u specifies "
1286 		    "input for test that does not require it",
1287 		    triple->ktr_module, triple->ktr_suite, triple->ktr_test,
1288 		    triple->ktr_lineno);
1289 		return (B_FALSE);
1290 	}
1291 
1292 	return (B_TRUE);
1293 }
1294 
1295 /*
1296  * When a test is fully-qualified it could be for the purpose of
1297  * specifying an input stream. We provide this check to catch missing
1298  * input (or input on a test that does not require it) as a benefit to
1299  * the user.
1300  *
1301  * We do not exit immediately upon finding a bad entry; but instead
1302  * print a warning for each bad triple and then exit with failure.
1303  */
1304 static void
1305 ktest_check_fqt_entries(nvlist_t *tests, list_t *run_list)
1306 {
1307 	boolean_t bad_triple = B_FALSE;
1308 
1309 	for (ktest_triple_t *triple = list_head(run_list); triple != NULL;
1310 	    triple = list_next(run_list, triple)) {
1311 		if (ktest_is_fqt(triple)) {
1312 			if (!ktest_check_fqt_entry(tests, triple)) {
1313 				bad_triple = B_TRUE;
1314 			}
1315 		}
1316 	}
1317 
1318 	if (bad_triple) {
1319 		errx(EXIT_FAILURE, "one or more incorrect triples");
1320 	}
1321 }
1322 
1323 /*
1324  * Verify that the run list is acceptable.
1325  */
1326 static void
1327 ktest_verify_run_list(nvlist_t *tests, list_t *run_list)
1328 {
1329 	ktest_check_fqt_entries(tests, run_list);
1330 }
1331 
1332 static boolean_t
1333 ktest_run_cmd(int argc, char *argv[], int ktdev)
1334 {
1335 	char c;
1336 	nvlist_t *tests = NULL;
1337 	list_t run_list;
1338 	char *input_path = NULL;
1339 	boolean_t parsable = B_FALSE;
1340 	boolean_t fields_set = B_FALSE;
1341 	boolean_t print_stats = B_TRUE;
1342 	char *fields = KTEST_RUN_CMD_DEF_FIELDS;
1343 	uint_t oflags = 0;
1344 	ofmt_handle_t ofmt = NULL;
1345 	ofmt_status_t oferr;
1346 	boolean_t all_pass = B_FALSE;
1347 
1348 	while ((c = getopt(argc, argv, ":Ho:pi:")) != -1) {
1349 		switch (c) {
1350 		case 'H':
1351 			oflags |= OFMT_NOHEADER;
1352 			break;
1353 		case 'o':
1354 			fields = optarg;
1355 			fields_set = B_TRUE;
1356 			break;
1357 		case 'p':
1358 			parsable = B_TRUE;
1359 			print_stats = B_FALSE;
1360 			oflags |= OFMT_PARSABLE;
1361 			break;
1362 		case 'i':
1363 			if (input_path != NULL) {
1364 				ktest_usage("cannot specify -i more than once");
1365 				exit(EXIT_USAGE);
1366 			}
1367 
1368 			input_path = optarg;
1369 
1370 			if (strnlen(input_path, MAXPATHLEN) >= MAXPATHLEN) {
1371 				err(EXIT_FAILURE, "input path too long");
1372 			}
1373 
1374 			break;
1375 		case ':':
1376 			ktest_usage("missing argument to -%c", optopt);
1377 			exit(EXIT_USAGE);
1378 
1379 		case '?':
1380 			ktest_usage("unknown run option: -%c", optopt);
1381 			exit(EXIT_USAGE);
1382 		}
1383 	}
1384 
1385 	if (parsable && !fields_set) {
1386 		ktest_usage("must specify -o with -p");
1387 		exit(EXIT_USAGE);
1388 	}
1389 
1390 	oferr = ofmt_open(fields, ktest_run_ofmt, oflags, 0, &ofmt);
1391 	ofmt_check(oferr, parsable, ofmt, ktest_ofmt_errx, warnx);
1392 
1393 	argc -= optind;
1394 	argv += optind;
1395 
1396 	/*
1397 	 * We don't run all tests by default. We assume that as the
1398 	 * library of test modules grows we want to be sure the user
1399 	 * actually wants to run all tests by forcing them to at least
1400 	 * specify the `*` glob.
1401 	 */
1402 	if (argc < 1) {
1403 		ktest_usage("must specify at least one triple");
1404 		exit(EXIT_USAGE);
1405 	}
1406 
1407 	list_create(&run_list, sizeof (ktest_triple_t),
1408 	    offsetof(ktest_triple_t, ktr_node));
1409 
1410 	for (uint_t i = 0; i < argc; i++) {
1411 		ktest_triple_t *triple = ktest_parse_triple(argv[i], 0);
1412 
1413 		if (triple == NULL) {
1414 			errx(EXIT_FAILURE, "failed to parse triple: %s",
1415 			    argv[i]);
1416 		}
1417 
1418 		if (input_path != NULL) {
1419 			/*
1420 			 * The path length was checked during option
1421 			 * parsing.
1422 			 */
1423 			(void) strcpy(triple->ktr_input_path, input_path);
1424 		}
1425 
1426 		list_insert_tail(&run_list, triple);
1427 	}
1428 
1429 	tests = ktest_list_tests(ktdev);
1430 	ktest_verify_run_list(tests, &run_list);
1431 	all_pass = ktest_run_tests(ktdev, tests, &run_list, ofmt, print_stats);
1432 	ofmt_close(ofmt);
1433 	ktest_free_triples(&run_list);
1434 	list_destroy(&run_list);
1435 	nvlist_free(tests);
1436 	return (all_pass);
1437 }
1438 
1439 static boolean_t
1440 ktest_run_file_cmd(int argc, char *argv[], int ktdev)
1441 {
1442 	char c;
1443 	nvlist_t *tests = NULL;
1444 	list_t run_list;
1445 	char *run_file = NULL;
1446 	boolean_t use_stdin = B_FALSE;
1447 	boolean_t parsable = B_FALSE;
1448 	boolean_t fields_set = B_FALSE;
1449 	boolean_t print_stats = B_TRUE;
1450 	char *fields = KTEST_RUN_CMD_DEF_FIELDS;
1451 	uint_t oflags = 0;
1452 	ofmt_handle_t ofmt = NULL;
1453 	ofmt_status_t oferr;
1454 	boolean_t all_pass = B_FALSE;
1455 
1456 	while ((c = getopt(argc, argv, ":Ho:p")) != -1) {
1457 		switch (c) {
1458 		case 'H':
1459 			oflags |= OFMT_NOHEADER;
1460 			break;
1461 		case 'o':
1462 			fields = optarg;
1463 			fields_set = B_TRUE;
1464 			break;
1465 		case 'p':
1466 			parsable = B_TRUE;
1467 			print_stats = B_FALSE;
1468 			oflags |= OFMT_PARSABLE;
1469 			break;
1470 		case ':':
1471 			ktest_usage("missing argument to -%c", optopt);
1472 			exit(EXIT_USAGE);
1473 		case '?':
1474 			ktest_usage("unknown option: -%c", optopt);
1475 			exit(EXIT_USAGE);
1476 		}
1477 	}
1478 
1479 	if (parsable && !fields_set) {
1480 		ktest_usage("must specify -o with -p");
1481 		exit(EXIT_USAGE);
1482 	}
1483 
1484 	oferr = ofmt_open(fields, ktest_run_ofmt, oflags, 0, &ofmt);
1485 	ofmt_check(oferr, parsable, ofmt, ktest_ofmt_errx, warnx);
1486 
1487 	argc -= optind;
1488 	argv += optind;
1489 
1490 	if (argc > 1) {
1491 		ktest_usage("must specify only one run file");
1492 		exit(EXIT_USAGE);
1493 	}
1494 
1495 	/*
1496 	 * Use stdin as the run file when no run file argument is
1497 	 * specified.
1498 	 */
1499 	if (argc == 0) {
1500 		use_stdin = B_TRUE;
1501 	}
1502 
1503 	run_file = argv[0];
1504 	tests = ktest_list_tests(ktdev);
1505 	list_create(&run_list, sizeof (ktest_triple_t),
1506 	    offsetof(ktest_triple_t, ktr_node));
1507 	ktest_load_run_file(run_file, use_stdin, tests, &run_list);
1508 	ktest_verify_run_list(tests, &run_list);
1509 	all_pass = ktest_run_tests(ktdev, tests, &run_list, ofmt, print_stats);
1510 	ofmt_close(ofmt);
1511 	ktest_free_triples(&run_list);
1512 	list_destroy(&run_list);
1513 	nvlist_free(tests);
1514 	return (all_pass);
1515 }
1516 
1517 static void
1518 ktest_list_cmd(int argc, char *argv[], int dev)
1519 {
1520 	char c;
1521 	list_t triples;
1522 	nvlist_t *tests = NULL;
1523 	boolean_t parsable = B_FALSE;
1524 	boolean_t fields_set = B_FALSE;
1525 	char *fields = KTEST_LIST_CMD_DEF_FIELDS;
1526 	uint_t oflags = 0;
1527 	ofmt_handle_t ofmt = NULL;
1528 	ofmt_status_t oferr;
1529 
1530 	list_create(&triples, sizeof (ktest_triple_t),
1531 	    offsetof(ktest_triple_t, ktr_node));
1532 
1533 	while ((c = getopt(argc, argv, ":Ho:p")) != -1) {
1534 		switch (c) {
1535 		case 'H':
1536 			oflags |= OFMT_NOHEADER;
1537 			break;
1538 		case 'o':
1539 			fields = optarg;
1540 			fields_set = B_TRUE;
1541 			break;
1542 		case 'p':
1543 			parsable = B_TRUE;
1544 			oflags |= OFMT_PARSABLE;
1545 			break;
1546 		case ':':
1547 			ktest_usage("missing argument to -%c", optopt);
1548 			exit(EXIT_USAGE);
1549 		case '?':
1550 			ktest_usage("unknown option: -%c", optopt);
1551 			exit(EXIT_USAGE);
1552 		}
1553 	}
1554 
1555 	if (parsable && !fields_set) {
1556 		ktest_usage("must specify -o with -p");
1557 		exit(EXIT_USAGE);
1558 	}
1559 
1560 	oferr = ofmt_open(fields, ktest_list_ofmt, oflags, 0, &ofmt);
1561 	ofmt_check(oferr, parsable, ofmt, ktest_ofmt_errx, warnx);
1562 
1563 	argc -= optind;
1564 	argv += optind;
1565 
1566 	if (argc == 0) {
1567 		list_insert_tail(&triples, ktest_def_triple);
1568 	} else {
1569 		for (uint_t i = 0; i < argc; i++) {
1570 			ktest_triple_t *triple = ktest_parse_triple(argv[i], 0);
1571 
1572 			if (triple == NULL) {
1573 				errx(EXIT_FAILURE, "failed to parse triple: %s",
1574 				    argv[i]);
1575 			}
1576 
1577 			list_insert_tail(&triples, triple);
1578 		}
1579 	}
1580 
1581 	tests = ktest_list_tests(dev);
1582 	ktest_print_tests(tests, &triples, ofmt);
1583 	ofmt_close(ofmt);
1584 	nvlist_free(tests);
1585 	ktest_free_triples(&triples);
1586 	list_destroy(&triples);
1587 }
1588 
1589 static void
1590 ktest_alloc_def_triple()
1591 {
1592 	ktest_def_triple = ktest_parse_triple(KTEST_DEF_TRIPLE, 0);
1593 
1594 	if (ktest_def_triple == NULL) {
1595 		err(EXIT_FAILURE, "failed to initialize default triple");
1596 	}
1597 }
1598 
1599 int
1600 main(int argc, char *argv[])
1601 {
1602 	int fd;
1603 	const char *cmd;
1604 
1605 	ktest_prog = basename(argv[0]);
1606 
1607 	if (getzoneid() != GLOBAL_ZONEID || getuid() != 0) {
1608 		errx(EXIT_FAILURE, "can only be used by root from"
1609 		    " the global zone");
1610 	}
1611 
1612 	if (argc < 2) {
1613 		ktest_usage("no command specified");
1614 		exit(EXIT_USAGE);
1615 	}
1616 
1617 	/*
1618 	 * Peel off program name and command.
1619 	 */
1620 	cmd = argv[1];
1621 	argc -= 2;
1622 	argv += 2;
1623 	optind = 0;
1624 
1625 	if ((fd = open(KTEST_DEV_PATH, O_RDONLY, 0)) == -1) {
1626 		err(EXIT_FAILURE, "failed to open %s", KTEST_DEV_PATH);
1627 	}
1628 
1629 	ktest_alloc_def_triple();
1630 
1631 	if (strncasecmp("list", cmd, KTEST_CMD_SZ) == 0) {
1632 		ktest_list_cmd(argc, argv, fd);
1633 	} else if (strncasecmp("run", cmd, KTEST_CMD_SZ) == 0) {
1634 		if (!ktest_run_cmd(argc, argv, fd)) {
1635 			errx(EXIT_FAILURE, "one or more tests did not pass");
1636 		}
1637 	} else if (strncasecmp("run-file", cmd, KTEST_CMD_SZ) == 0) {
1638 		if (!ktest_run_file_cmd(argc, argv, fd)) {
1639 			errx(EXIT_FAILURE, "one or more tests did not pass");
1640 		}
1641 	} else if (strncasecmp("help", cmd, KTEST_CMD_SZ) == 0) {
1642 		ktest_usage(NULL);
1643 	} else {
1644 		ktest_usage("unknown command: %s", cmd);
1645 		exit(EXIT_USAGE);
1646 	}
1647 
1648 	(void) close(fd);
1649 	return (0);
1650 }
1651