]> git.proxmox.com Git - mirror_spl.git/blob - src/cmd/splat.c
Initial commit. All spl source written up to this point wrapped
[mirror_spl.git] / src / cmd / splat.c
1 /* Kernel ZFS Test (KZT) user space command interface */
2
3 #include <stdlib.h>
4 #include <stddef.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <getopt.h>
9 #include <assert.h>
10 #include <fcntl.h>
11 #include <libuutil.h>
12 #include <sys/ioctl.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16 #include "splat.h"
17
18 #undef ioctl
19
20 static const char shortOpts[] = "hvlat:xc";
21 static const struct option longOpts[] = {
22 { "help", no_argument, 0, 'h' },
23 { "verbose", no_argument, 0, 'v' },
24 { "list", no_argument, 0, 'l' },
25 { "all", no_argument, 0, 'a' },
26 { "test", required_argument, 0, 't' },
27 { "exit", no_argument, 0, 'x' },
28 { "nocolor", no_argument, 0, 'c' },
29 { 0, 0, 0, 0 }
30 };
31
32 static uu_list_t *subsystems; /* Subsystem/tests */
33 static uu_list_pool_t *subsystem_pool; /* Subsystem pool */
34 static uu_list_pool_t *test_pool; /* Test pool */
35 static int kztctl_fd; /* Control file descriptor */
36 static char kzt_version[KZT_VERSION_SIZE]; /* Kernel version string */
37 static char *kzt_buffer = NULL; /* Scratch space area */
38 static int kzt_buffer_size = 0; /* Scratch space size */
39
40
41 static void test_list(uu_list_t *, int);
42 static int dev_clear(void);
43
44
45 static int usage(void) {
46 fprintf(stderr, "usage: kzt [hvla] [-t <subsystem:<tests>>]\n");
47 fprintf(stderr,
48 " --help -h This help\n"
49 " --verbose -v Increase verbosity\n"
50 " --list -l List all tests in all subsystems\n"
51 " --all -a Run all tests in all subsystems\n"
52 " --test -t <sub:test> Run 'test' in subsystem 'sub'\n"
53 " --exit -x Exit on first test error\n"
54 " --nocolor -c Do not colorize output\n");
55 fprintf(stderr, "\n"
56 "Examples:\n"
57 " kzt -t kmem:all # Runs all kmem tests\n"
58 " kzt -t taskq:0x201 # Run taskq test 0x201\n");
59
60 return 0;
61 }
62
63 static subsystem_t *subsystem_init(kzt_user_t *desc)
64 {
65 subsystem_t *sub;
66
67 sub = (subsystem_t *)malloc(sizeof(*sub));
68 if (sub == NULL)
69 return NULL;
70
71 memcpy(&sub->sub_desc, desc, sizeof(*desc));
72 uu_list_node_init(sub, &sub->sub_node, subsystem_pool);
73
74 sub->sub_tests = uu_list_create(test_pool, NULL, 0);
75 if (sub->sub_tests == NULL) {
76 free(sub);
77 return NULL;
78 }
79
80 return sub;
81 }
82
83 static void subsystem_fini(subsystem_t *sub)
84 {
85 assert(sub != NULL);
86
87 uu_list_node_fini(sub, &sub->sub_node, subsystem_pool);
88 free(sub);
89 }
90
91 static int subsystem_setup(void)
92 {
93 kzt_cfg_t *cfg;
94 int i, rc, size, cfg_size;
95 subsystem_t *sub;
96 kzt_user_t *desc;
97
98 /* Aquire the number of registered subsystems */
99 cfg_size = sizeof(*cfg);
100 cfg = (kzt_cfg_t *)malloc(cfg_size);
101 if (cfg == NULL)
102 return -ENOMEM;
103
104 memset(cfg, 0, cfg_size);
105 cfg->cfg_magic = KZT_CFG_MAGIC;
106 cfg->cfg_cmd = KZT_CFG_SUBSYSTEM_COUNT;
107
108 rc = ioctl(kztctl_fd, KZT_CFG, cfg);
109 if (rc) {
110 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
111 (unsigned long) KZT_CFG, cfg->cfg_cmd, errno);
112 free(cfg);
113 return rc;
114 }
115
116 size = cfg->cfg_rc1;
117 free(cfg);
118
119 /* Based on the newly aquired number of subsystems allocate enough
120 * memory to get the descriptive information for them all. */
121 cfg_size = sizeof(*cfg) + size * sizeof(kzt_user_t);
122 cfg = (kzt_cfg_t *)malloc(cfg_size);
123 if (cfg == NULL)
124 return -ENOMEM;
125
126 memset(cfg, 0, cfg_size);
127 cfg->cfg_magic = KZT_CFG_MAGIC;
128 cfg->cfg_cmd = KZT_CFG_SUBSYSTEM_LIST;
129 cfg->cfg_data.kzt_subsystems.size = size;
130
131 rc = ioctl(kztctl_fd, KZT_CFG, cfg);
132 if (rc) {
133 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
134 (unsigned long) KZT_CFG, cfg->cfg_cmd, errno);
135 free(cfg);
136 return rc;
137 }
138
139 /* Add the new subsystems in to the global list */
140 size = cfg->cfg_rc1;
141 for (i = 0; i < size; i++) {
142 desc = &(cfg->cfg_data.kzt_subsystems.descs[i]);
143
144 sub = subsystem_init(desc);
145 if (sub == NULL) {
146 fprintf(stderr, "Error initializing subsystem: %s\n",
147 desc->name);
148 free(cfg);
149 return -ENOMEM;
150 }
151
152 uu_list_insert(subsystems, sub, 0);
153 }
154
155 free(cfg);
156 return 0;
157 }
158
159 static int subsystem_compare(const void *l_arg, const void *r_arg, void *private)
160 {
161 const subsystem_t *l = l_arg;
162 const subsystem_t *r = r_arg;
163
164 if (l->sub_desc.id > r->sub_desc.id)
165 return 1;
166
167 if (l->sub_desc.id < r->sub_desc.id)
168 return -1;
169
170 return 0;
171 }
172
173 static void subsystem_list(uu_list_t *list, int indent)
174 {
175 subsystem_t *sub;
176
177 fprintf(stdout,
178 "------------------------------- "
179 "Available KZT Tests "
180 "-------------------------------\n");
181
182 for (sub = uu_list_first(list); sub != NULL;
183 sub = uu_list_next(list, sub)) {
184 fprintf(stdout, "%*s0x%0*x %-*s ---- %s ----\n",
185 indent, "",
186 4, sub->sub_desc.id,
187 KZT_NAME_SIZE + 7, sub->sub_desc.name,
188 sub->sub_desc.desc);
189 test_list(sub->sub_tests, indent + 7);
190 }
191 }
192
193 static test_t *test_init(subsystem_t *sub, kzt_user_t *desc)
194 {
195 test_t *test;
196
197 test = (test_t *)malloc(sizeof(*test));
198 if (test == NULL)
199 return NULL;
200
201 test->test_sub = sub;
202 memcpy(&test->test_desc, desc, sizeof(*desc));
203 uu_list_node_init(test, &test->test_node, test_pool);
204
205 return test;
206 }
207
208 static void test_fini(test_t *test)
209 {
210 assert(test != NULL);
211
212 uu_list_node_fini(test, &test->test_node, test_pool);
213 free(test);
214 }
215
216 static int test_setup(subsystem_t *sub)
217 {
218 kzt_cfg_t *cfg;
219 int i, rc, size;
220 test_t *test;
221 kzt_user_t *desc;
222
223 /* Aquire the number of registered tests for the give subsystem */
224 cfg = (kzt_cfg_t *)malloc(sizeof(*cfg));
225 if (cfg == NULL)
226 return -ENOMEM;
227
228 memset(cfg, 0, sizeof(*cfg));
229 cfg->cfg_magic = KZT_CFG_MAGIC;
230 cfg->cfg_cmd = KZT_CFG_TEST_COUNT;
231 cfg->cfg_arg1 = sub->sub_desc.id; /* Subsystem of interest */
232
233 rc = ioctl(kztctl_fd, KZT_CFG, cfg);
234 if (rc) {
235 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
236 (unsigned long) KZT_CFG, cfg->cfg_cmd, errno);
237 free(cfg);
238 return rc;
239 }
240
241 size = cfg->cfg_rc1;
242 free(cfg);
243
244 /* Based on the newly aquired number of tests allocate enough
245 * memory to get the descriptive information for them all. */
246 cfg = (kzt_cfg_t *)malloc(sizeof(*cfg) + size * sizeof(kzt_user_t));
247 if (cfg == NULL)
248 return -ENOMEM;
249
250 memset(cfg, 0, sizeof(*cfg) + size * sizeof(kzt_user_t));
251 cfg->cfg_magic = KZT_CFG_MAGIC;
252 cfg->cfg_cmd = KZT_CFG_TEST_LIST;
253 cfg->cfg_arg1 = sub->sub_desc.id; /* Subsystem of interest */
254 cfg->cfg_data.kzt_tests.size = size;
255
256 rc = ioctl(kztctl_fd, KZT_CFG, cfg);
257 if (rc) {
258 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
259 (unsigned long) KZT_CFG, cfg->cfg_cmd, errno);
260 free(cfg);
261 return rc;
262 }
263
264 /* Add the new tests in to the relevant subsystems */
265 size = cfg->cfg_rc1;
266 for (i = 0; i < size; i++) {
267 desc = &(cfg->cfg_data.kzt_tests.descs[i]);
268
269 test = test_init(sub, desc);
270 if (test == NULL) {
271 fprintf(stderr, "Error initializing test: %s\n",
272 desc->name);
273 free(cfg);
274 return -ENOMEM;
275 }
276
277 uu_list_insert(sub->sub_tests, test, 0);
278 }
279
280 free(cfg);
281 return 0;
282 }
283
284 static int test_compare(const void *l_arg, const void *r_arg, void *private)
285 {
286 const test_t *l = l_arg;
287 const test_t *r = r_arg;
288
289 if (l->test_desc.id > r->test_desc.id)
290 return 1;
291
292 if (l->test_desc.id < r->test_desc.id)
293 return -1;
294
295 return 0;
296 }
297
298 static test_t *test_copy(test_t *test)
299 {
300 return test_init(test->test_sub, &test->test_desc);
301 }
302
303 static void test_list(uu_list_t *list, int indent)
304 {
305 test_t *test;
306
307 for (test = uu_list_first(list); test != NULL;
308 test = uu_list_next(list, test))
309 fprintf(stdout, "%*s0x%0*x %-*s %-*s\n",
310 indent, "",
311 04, test->test_desc.id,
312 KZT_NAME_SIZE, test->test_desc.name,
313 KZT_DESC_SIZE, test->test_desc.desc);
314 }
315
316 static test_t *test_find(char *sub_str, char *test_str)
317 {
318 subsystem_t *sub;
319 test_t *test;
320 int sub_num, test_num;
321
322 /* No error checking here because it may not be a number, it's
323 * perfectly OK for it to be a string. Since we're just using
324 * it for comparison purposes this is all very safe.
325 */
326 sub_num = strtol(sub_str, NULL, 0);
327 test_num = strtol(test_str, NULL, 0);
328
329 for (sub = uu_list_first(subsystems); sub != NULL;
330 sub = uu_list_next(subsystems, sub)) {
331
332 if (strncmp(sub->sub_desc.name, sub_str, KZT_NAME_SIZE) &&
333 sub->sub_desc.id != sub_num)
334 continue;
335
336 for (test = uu_list_first(sub->sub_tests); test != NULL;
337 test = uu_list_next(sub->sub_tests, test)) {
338
339 if (!strncmp(test->test_desc.name, test_str,
340 KZT_NAME_SIZE) || test->test_desc.id == test_num)
341 return test;
342 }
343 }
344
345 return NULL;
346 }
347
348 static int test_add(cmd_args_t *args, test_t *test)
349 {
350 test_t *tmp;
351
352 tmp = test_copy(test);
353 if (tmp == NULL)
354 return -ENOMEM;
355
356 uu_list_insert(args->args_tests, tmp, 0);
357 return 0;
358 }
359
360 static int test_add_all(cmd_args_t *args)
361 {
362 subsystem_t *sub;
363 test_t *test;
364 int rc;
365
366 for (sub = uu_list_first(subsystems); sub != NULL;
367 sub = uu_list_next(subsystems, sub)) {
368
369 for (test = uu_list_first(sub->sub_tests); test != NULL;
370 test = uu_list_next(sub->sub_tests, test)) {
371
372 if (rc = test_add(args, test))
373 return rc;
374 }
375 }
376
377 return 0;
378 }
379
380 static int test_run(cmd_args_t *args, test_t *test)
381 {
382 subsystem_t *sub = test->test_sub;
383 kzt_cmd_t *cmd;
384 int rc, cmd_size;
385
386 dev_clear();
387
388 cmd_size = sizeof(*cmd);
389 cmd = (kzt_cmd_t *)malloc(cmd_size);
390 if (cmd == NULL)
391 return -ENOMEM;
392
393 memset(cmd, 0, cmd_size);
394 cmd->cmd_magic = KZT_CMD_MAGIC;
395 cmd->cmd_subsystem = sub->sub_desc.id;
396 cmd->cmd_test = test->test_desc.id;
397 cmd->cmd_data_size = 0; /* Unused feature */
398
399 fprintf(stdout, "%*s:%-*s ",
400 KZT_NAME_SIZE, sub->sub_desc.name,
401 KZT_NAME_SIZE, test->test_desc.name);
402 fflush(stdout);
403 rc = ioctl(kztctl_fd, KZT_CMD, cmd);
404 if (args->args_do_color) {
405 fprintf(stdout, "%s %s\n", rc ?
406 COLOR_RED "Fail" COLOR_RESET :
407 COLOR_GREEN "Pass" COLOR_RESET,
408 rc ? strerror(errno) : "");
409 } else {
410 fprintf(stdout, "%s %s\n", rc ?
411 "Fail" : "Pass",
412 rc ? strerror(errno) : "");
413 }
414 fflush(stdout);
415 free(cmd);
416
417 if (args->args_verbose) {
418 if ((rc = read(kztctl_fd, kzt_buffer, kzt_buffer_size - 1)) < 0) {
419 fprintf(stdout, "Error reading results: %d\n", rc);
420 } else {
421 fprintf(stdout, "\n%s\n", kzt_buffer);
422 fflush(stdout);
423 }
424 }
425
426 return rc;
427 }
428
429 static int tests_run(cmd_args_t *args)
430 {
431 test_t *test;
432 int rc;
433
434 fprintf(stdout,
435 "------------------------------- "
436 "Running KZT Tests "
437 "-------------------------------\n");
438
439 for (test = uu_list_first(args->args_tests); test != NULL;
440 test = uu_list_next(args->args_tests, test)) {
441
442 rc = test_run(args, test);
443 if (rc && args->args_exit_on_error)
444 return rc;
445 }
446
447 return 0;
448 }
449
450 static int args_parse_test(cmd_args_t *args, char *str)
451 {
452 subsystem_t *s;
453 test_t *t;
454 char *sub_str, *test_str;
455 int sub_num, test_num;
456 int sub_all = 0, test_all = 0;
457 int rc, flag = 0;
458
459 test_str = strchr(str, ':');
460 if (test_str == NULL) {
461 fprintf(stderr, "Test must be of the "
462 "form <subsystem:test>\n");
463 return -EINVAL;
464 }
465
466 sub_str = str;
467 test_str[0] = '\0';
468 test_str = test_str + 1;
469
470 sub_num = strtol(sub_str, NULL, 0);
471 test_num = strtol(test_str, NULL, 0);
472
473 if (!strncasecmp(sub_str, "all", strlen(sub_str)) || (sub_num == -1))
474 sub_all = 1;
475
476 if (!strncasecmp(test_str, "all", strlen(test_str)) || (test_num == -1))
477 test_all = 1;
478
479 if (sub_all) {
480 if (test_all) {
481 /* Add all tests from all subsystems */
482 for (s = uu_list_first(subsystems); s != NULL;
483 s = uu_list_next(subsystems, s))
484 for (t = uu_list_first(s->sub_tests);t != NULL;
485 t = uu_list_next(s->sub_tests, t))
486 if (rc = test_add(args, t))
487 goto error_run;
488 } else {
489 /* Add a specific test from all subsystems */
490 for (s = uu_list_first(subsystems); s != NULL;
491 s = uu_list_next(subsystems, s)) {
492 if (t = test_find(s->sub_desc.name,test_str)) {
493 if (rc = test_add(args, t))
494 goto error_run;
495
496 flag = 1;
497 }
498 }
499
500 if (!flag)
501 fprintf(stderr, "No tests '%s:%s' could be "
502 "found\n", sub_str, test_str);
503 }
504 } else {
505 if (test_all) {
506 /* Add all tests from a specific subsystem */
507 for (s = uu_list_first(subsystems); s != NULL;
508 s = uu_list_next(subsystems, s)) {
509 if (strncasecmp(sub_str, s->sub_desc.name,
510 strlen(sub_str)))
511 continue;
512
513 for (t = uu_list_first(s->sub_tests);t != NULL;
514 t = uu_list_next(s->sub_tests, t))
515 if (rc = test_add(args, t))
516 goto error_run;
517 }
518 } else {
519 /* Add a specific test from a specific subsystem */
520 if (t = test_find(sub_str, test_str)) {
521 if (rc = test_add(args, t))
522 goto error_run;
523 } else {
524 fprintf(stderr, "Test '%s:%s' could not be "
525 "found\n", sub_str, test_str);
526 return -EINVAL;
527 }
528 }
529 }
530
531 return 0;
532
533 error_run:
534 fprintf(stderr, "Test '%s:%s' not added to run list: %d\n",
535 sub_str, test_str, rc);
536 return rc;
537 }
538
539 static void args_fini(cmd_args_t *args)
540 {
541 struct cmd_test *ptr1, *ptr2;
542
543 assert(args != NULL);
544
545
546
547 if (args->args_tests != NULL) {
548 uu_list_destroy(args->args_tests);
549 }
550
551 free(args);
552 }
553
554 static cmd_args_t *
555 args_init(int argc, char **argv)
556 {
557 cmd_args_t *args;
558 int c, rc;
559
560 if (argc == 1) {
561 usage();
562 return (cmd_args_t *) NULL;
563 }
564
565 /* Configure and populate the args structures */
566 args = malloc(sizeof(*args));
567 if (args == NULL)
568 return NULL;
569
570 memset(args, 0, sizeof(*args));
571 args->args_verbose = 0;
572 args->args_do_list = 0;
573 args->args_do_all = 0;
574 args->args_do_color = 1;
575 args->args_exit_on_error = 0;
576 args->args_tests = uu_list_create(test_pool, NULL, 0);
577 if (args->args_tests == NULL) {
578 args_fini(args);
579 return NULL;
580 }
581
582 while ((c = getopt_long(argc, argv, shortOpts, longOpts, NULL)) != -1){
583 switch (c) {
584 case 'v': args->args_verbose++; break;
585 case 'l': args->args_do_list = 1; break;
586 case 'a': args->args_do_all = 1; break;
587 case 'c': args->args_do_color = 0; break;
588 case 'x': args->args_exit_on_error = 1; break;
589 case 't':
590 if (args->args_do_all) {
591 fprintf(stderr, "Option -t <subsystem:test> is "
592 "useless when used with -a\n");
593 args_fini(args);
594 return NULL;
595 }
596
597 rc = args_parse_test(args, argv[optind - 1]);
598 if (rc) {
599 args_fini(args);
600 return NULL;
601 }
602 break;
603 case 'h':
604 case '?':
605 usage();
606 args_fini(args);
607 return NULL;
608 default:
609 fprintf(stderr, "Unknown option '%s'\n",
610 argv[optind - 1]);
611 break;
612 }
613 }
614
615 return args;
616 }
617
618 static int
619 dev_clear(void)
620 {
621 kzt_cfg_t cfg;
622 int rc;
623
624 memset(&cfg, 0, sizeof(cfg));
625 cfg.cfg_magic = KZT_CFG_MAGIC;
626 cfg.cfg_cmd = KZT_CFG_BUFFER_CLEAR;
627 cfg.cfg_arg1 = 0;
628
629 rc = ioctl(kztctl_fd, KZT_CFG, &cfg);
630 if (rc)
631 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
632 (unsigned long) KZT_CFG, cfg.cfg_cmd, errno);
633
634 lseek(kztctl_fd, 0, SEEK_SET);
635
636 return rc;
637 }
638
639 static int
640 dev_size(int size)
641 {
642 kzt_cfg_t cfg;
643 int rc;
644
645 memset(&cfg, 0, sizeof(cfg));
646 cfg.cfg_magic = KZT_CFG_MAGIC;
647 cfg.cfg_cmd = KZT_CFG_BUFFER_SIZE;
648 cfg.cfg_arg1 = size;
649
650 rc = ioctl(kztctl_fd, KZT_CFG, &cfg);
651 if (rc) {
652 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
653 (unsigned long) KZT_CFG, cfg.cfg_cmd, errno);
654 return rc;
655 }
656
657 return cfg.cfg_rc1;
658 }
659
660 static void
661 dev_fini(void)
662 {
663 if (kzt_buffer)
664 free(kzt_buffer);
665
666 if (kztctl_fd != -1) {
667 if (close(kztctl_fd) == -1) {
668 fprintf(stderr, "Unable to close %s: %d\n",
669 KZT_DEV, errno);
670 }
671 }
672 }
673
674 static int
675 dev_init(void)
676 {
677 subsystem_t *sub;
678 int rc;
679
680 kztctl_fd = open(KZT_DEV, O_RDONLY);
681 if (kztctl_fd == -1) {
682 fprintf(stderr, "Unable to open %s: %d\n"
683 "Is the kzt module loaded?\n", KZT_DEV, errno);
684 rc = errno;
685 goto error;
686 }
687
688 /* Determine kernel module version string */
689 memset(kzt_version, 0, KZT_VERSION_SIZE);
690 if ((rc = read(kztctl_fd, kzt_version, KZT_VERSION_SIZE - 1)) == -1)
691 goto error;
692
693 if (rc = dev_clear())
694 goto error;
695
696 if ((rc = dev_size(0)) < 0)
697 goto error;
698
699 kzt_buffer_size = rc;
700 kzt_buffer = (char *)malloc(kzt_buffer_size);
701 if (kzt_buffer == NULL) {
702 rc = -ENOMEM;
703 goto error;
704 }
705
706 memset(kzt_buffer, 0, kzt_buffer_size);
707
708 /* Determine available subsystems */
709 if ((rc = subsystem_setup()) != 0)
710 goto error;
711
712 /* Determine available tests for all subsystems */
713 for (sub = uu_list_first(subsystems); sub != NULL;
714 sub = uu_list_next(subsystems, sub))
715 if ((rc = test_setup(sub)) != 0)
716 goto error;
717
718 return 0;
719
720 error:
721 if (kztctl_fd != -1) {
722 if (close(kztctl_fd) == -1) {
723 fprintf(stderr, "Unable to close %s: %d\n",
724 KZT_DEV, errno);
725 }
726 }
727
728 return rc;
729 }
730
731 int
732 init(void)
733 {
734 int rc;
735
736 /* Configure the subsystem pool */
737 subsystem_pool = uu_list_pool_create("sub_pool", sizeof(subsystem_t),
738 offsetof(subsystem_t, sub_node),
739 subsystem_compare, 0);
740 if (subsystem_pool == NULL)
741 return -ENOMEM;
742
743 /* Configure the test pool */
744 test_pool = uu_list_pool_create("test_pool", sizeof(test_t),
745 offsetof(test_t, test_node),
746 test_compare, 0);
747 if (test_pool == NULL) {
748 uu_list_pool_destroy(subsystem_pool);
749 return -ENOMEM;
750 }
751
752 /* Allocate the subsystem list */
753 subsystems = uu_list_create(subsystem_pool, NULL, 0);
754 if (subsystems == NULL) {
755 uu_list_pool_destroy(test_pool);
756 uu_list_pool_destroy(subsystem_pool);
757 return -ENOMEM;
758 }
759
760 return 0;
761 }
762
763 void
764 fini(void)
765 {
766 /* XXX - Cleanup destroy lists release memory */
767
768 /* XXX - Remove contents of list first */
769 uu_list_destroy(subsystems);
770 }
771
772
773 int
774 main(int argc, char **argv)
775 {
776 cmd_args_t *args = NULL;
777 int rc = 0;
778
779 /* General init */
780 if (rc = init())
781 return rc;
782
783 /* Device specific init */
784 if (rc = dev_init())
785 goto out;
786
787 /* Argument init and parsing */
788 if ((args = args_init(argc, argv)) == NULL) {
789 rc = -1;
790 goto out;
791 }
792
793 /* Generic kernel version string */
794 if (args->args_verbose)
795 fprintf(stdout, "%s", kzt_version);
796
797 /* Print the available test list and exit */
798 if (args->args_do_list) {
799 subsystem_list(subsystems, 0);
800 goto out;
801 }
802
803 /* Add all available test to the list of tests to run */
804 if (args->args_do_all) {
805 if (rc = test_add_all(args))
806 goto out;
807 }
808
809 /* Run all the requested tests */
810 if (rc = tests_run(args))
811 goto out;
812
813 out:
814 if (args != NULL)
815 args_fini(args);
816
817 dev_fini();
818 fini();
819 return rc;
820 }
821