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