]> git.proxmox.com Git - mirror_spl-debian.git/blob - cmd/splat.c
Fix two minor compiler warnings
[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 __u32 sub_num, test_num;
320
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 = strtoul(sub_str, NULL, 0);
327 test_num = strtoul(test_str, NULL, 0);
328
329 si = list_iterator_create(subsystems);
330
331 while ((sub = list_next(si))) {
332
333 if (strncmp(sub->sub_desc.name, sub_str, SPLAT_NAME_SIZE) &&
334 sub->sub_desc.id != sub_num)
335 continue;
336
337 ti = list_iterator_create(sub->sub_tests);
338
339 while ((test = list_next(ti))) {
340
341 if (!strncmp(test->test_desc.name, test_str,
342 SPLAT_NAME_SIZE) || test->test_desc.id==test_num) {
343 list_iterator_destroy(ti);
344 list_iterator_destroy(si);
345 return test;
346 }
347 }
348
349 list_iterator_destroy(ti);
350 }
351
352 list_iterator_destroy(si);
353
354 return NULL;
355 }
356
357 static int test_add(cmd_args_t *args, test_t *test)
358 {
359 test_t *tmp;
360
361 tmp = test_copy(test);
362 if (tmp == NULL)
363 return -ENOMEM;
364
365 list_append(args->args_tests, tmp);
366 return 0;
367 }
368
369 static int test_add_all(cmd_args_t *args)
370 {
371 ListIterator si, ti;
372 subsystem_t *sub;
373 test_t *test;
374 int rc;
375
376 si = list_iterator_create(subsystems);
377
378 while ((sub = list_next(si))) {
379 ti = list_iterator_create(sub->sub_tests);
380
381 while ((test = list_next(ti))) {
382 if ((rc = test_add(args, test))) {
383 list_iterator_destroy(ti);
384 list_iterator_destroy(si);
385 return rc;
386 }
387 }
388
389 list_iterator_destroy(ti);
390 }
391
392 list_iterator_destroy(si);
393
394 return 0;
395 }
396
397 static int test_run(cmd_args_t *args, test_t *test)
398 {
399 subsystem_t *sub = test->test_sub;
400 splat_cmd_t *cmd;
401 int rc, cmd_size;
402
403 dev_clear();
404
405 cmd_size = sizeof(*cmd);
406 cmd = (splat_cmd_t *)malloc(cmd_size);
407 if (cmd == NULL)
408 return -ENOMEM;
409
410 memset(cmd, 0, cmd_size);
411 cmd->cmd_magic = SPLAT_CMD_MAGIC;
412 cmd->cmd_subsystem = sub->sub_desc.id;
413 cmd->cmd_test = test->test_desc.id;
414 cmd->cmd_data_size = 0; /* Unused feature */
415
416 fprintf(stdout, "%*s:%-*s ",
417 SPLAT_NAME_SIZE, sub->sub_desc.name,
418 SPLAT_NAME_SIZE, test->test_desc.name);
419 fflush(stdout);
420 rc = ioctl(splatctl_fd, SPLAT_CMD, cmd);
421 if (args->args_do_color) {
422 fprintf(stdout, "%s %s\n", rc ?
423 COLOR_RED "Fail" COLOR_RESET :
424 COLOR_GREEN "Pass" COLOR_RESET,
425 rc ? strerror(errno) : "");
426 } else {
427 fprintf(stdout, "%s %s\n", rc ?
428 "Fail" : "Pass",
429 rc ? strerror(errno) : "");
430 }
431 fflush(stdout);
432 free(cmd);
433
434 if (args->args_verbose) {
435 if ((rc = read(splatctl_fd, splat_buffer,
436 splat_buffer_size - 1)) < 0) {
437 fprintf(stdout, "Error reading results: %d\n", rc);
438 } else {
439 fprintf(stdout, "\n%s\n", splat_buffer);
440 fflush(stdout);
441 }
442 }
443
444 return rc;
445 }
446
447 static int tests_run(cmd_args_t *args)
448 {
449 ListIterator i;
450 test_t *test;
451 int rc;
452
453 fprintf(stdout,
454 "------------------------------ "
455 "Running SPLAT Tests "
456 "------------------------------\n");
457
458 i = list_iterator_create(args->args_tests);
459
460 while ((test = list_next(i))) {
461 rc = test_run(args, test);
462 if (rc && args->args_exit_on_error) {
463 list_iterator_destroy(i);
464 return rc;
465 }
466 }
467
468 list_iterator_destroy(i);
469 return 0;
470 }
471
472 static int args_parse_test(cmd_args_t *args, char *str)
473 {
474 ListIterator si, ti;
475 subsystem_t *s;
476 test_t *t;
477 char *sub_str, *test_str;
478 int sub_num, test_num;
479 int sub_all = 0, test_all = 0;
480 int rc, flag = 0;
481
482 test_str = strchr(str, ':');
483 if (test_str == NULL) {
484 fprintf(stderr, "Test must be of the "
485 "form <subsystem:test>\n");
486 return -EINVAL;
487 }
488
489 sub_str = str;
490 test_str[0] = '\0';
491 test_str = test_str + 1;
492
493 sub_num = strtol(sub_str, NULL, 0);
494 test_num = strtol(test_str, NULL, 0);
495
496 if (!strncasecmp(sub_str, "all", strlen(sub_str)) || (sub_num == -1))
497 sub_all = 1;
498
499 if (!strncasecmp(test_str,"all",strlen(test_str)) || (test_num == -1))
500 test_all = 1;
501
502 si = list_iterator_create(subsystems);
503
504 if (sub_all) {
505 if (test_all) {
506 /* Add all tests from all subsystems */
507 while ((s = list_next(si))) {
508 ti = list_iterator_create(s->sub_tests);
509 while ((t = list_next(ti))) {
510 if ((rc = test_add(args, t))) {
511 list_iterator_destroy(ti);
512 goto error_run;
513 }
514 }
515 list_iterator_destroy(ti);
516 }
517 } else {
518 /* Add a specific test from all subsystems */
519 while ((s = list_next(si))) {
520 if ((t=test_find(s->sub_desc.name,test_str))) {
521 if ((rc = test_add(args, t)))
522 goto error_run;
523
524 flag = 1;
525 }
526 }
527
528 if (!flag)
529 fprintf(stderr, "No tests '%s:%s' could be "
530 "found\n", sub_str, test_str);
531 }
532 } else {
533 if (test_all) {
534 /* Add all tests from a specific subsystem */
535 while ((s = list_next(si))) {
536 if (strncasecmp(sub_str, s->sub_desc.name,
537 strlen(sub_str)))
538 continue;
539
540 ti = list_iterator_create(s->sub_tests);
541 while ((t = list_next(ti))) {
542 if ((rc = test_add(args, t))) {
543 list_iterator_destroy(ti);
544 goto error_run;
545 }
546 }
547 list_iterator_destroy(ti);
548 }
549 } else {
550 /* Add a specific test from a specific subsystem */
551 if ((t = test_find(sub_str, test_str))) {
552 if ((rc = test_add(args, t)))
553 goto error_run;
554 } else {
555 fprintf(stderr, "Test '%s:%s' could not be "
556 "found\n", sub_str, test_str);
557 return -EINVAL;
558 }
559 }
560 }
561
562 list_iterator_destroy(si);
563
564 return 0;
565
566 error_run:
567 list_iterator_destroy(si);
568
569 fprintf(stderr, "Test '%s:%s' not added to run list: %d\n",
570 sub_str, test_str, rc);
571
572 return rc;
573 }
574
575 static void args_fini(cmd_args_t *args)
576 {
577 assert(args != NULL);
578
579 if (args->args_tests != NULL)
580 list_destroy(args->args_tests);
581
582 free(args);
583 }
584
585 static cmd_args_t *
586 args_init(int argc, char **argv)
587 {
588 cmd_args_t *args;
589 int c, rc;
590
591 if (argc == 1) {
592 usage();
593 return (cmd_args_t *) NULL;
594 }
595
596 /* Configure and populate the args structures */
597 args = malloc(sizeof(*args));
598 if (args == NULL)
599 return NULL;
600
601 memset(args, 0, sizeof(*args));
602 args->args_verbose = 0;
603 args->args_do_list = 0;
604 args->args_do_all = 0;
605 args->args_do_color = 1;
606 args->args_exit_on_error = 0;
607 args->args_tests = list_create((ListDelF)test_fini);
608 if (args->args_tests == NULL) {
609 args_fini(args);
610 return NULL;
611 }
612
613 while ((c = getopt_long(argc, argv, shortOpts, longOpts, NULL)) != -1){
614 switch (c) {
615 case 'v': args->args_verbose++; break;
616 case 'l': args->args_do_list = 1; break;
617 case 'a': args->args_do_all = 1; break;
618 case 'c': args->args_do_color = 0; break;
619 case 'x': args->args_exit_on_error = 1; break;
620 case 't':
621 if (args->args_do_all) {
622 fprintf(stderr, "Option -t <subsystem:test> is "
623 "useless when used with -a\n");
624 args_fini(args);
625 return NULL;
626 }
627
628 rc = args_parse_test(args, argv[optind - 1]);
629 if (rc) {
630 args_fini(args);
631 return NULL;
632 }
633 break;
634 case 'h':
635 case '?':
636 usage();
637 args_fini(args);
638 return NULL;
639 default:
640 fprintf(stderr, "Unknown option '%s'\n",
641 argv[optind - 1]);
642 break;
643 }
644 }
645
646 return args;
647 }
648
649 static int
650 dev_clear(void)
651 {
652 splat_cfg_t cfg;
653 int rc;
654
655 memset(&cfg, 0, sizeof(cfg));
656 cfg.cfg_magic = SPLAT_CFG_MAGIC;
657 cfg.cfg_cmd = SPLAT_CFG_BUFFER_CLEAR;
658 cfg.cfg_arg1 = 0;
659
660 rc = ioctl(splatctl_fd, SPLAT_CFG, &cfg);
661 if (rc)
662 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
663 (unsigned long) SPLAT_CFG, cfg.cfg_cmd, errno);
664
665 lseek(splatctl_fd, 0, SEEK_SET);
666
667 return rc;
668 }
669
670 static int
671 dev_size(int size)
672 {
673 splat_cfg_t cfg;
674 int rc;
675
676 memset(&cfg, 0, sizeof(cfg));
677 cfg.cfg_magic = SPLAT_CFG_MAGIC;
678 cfg.cfg_cmd = SPLAT_CFG_BUFFER_SIZE;
679 cfg.cfg_arg1 = size;
680
681 rc = ioctl(splatctl_fd, SPLAT_CFG, &cfg);
682 if (rc) {
683 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
684 (unsigned long) SPLAT_CFG, cfg.cfg_cmd, errno);
685 return rc;
686 }
687
688 return cfg.cfg_rc1;
689 }
690
691 static void
692 dev_fini(void)
693 {
694 if (splat_buffer)
695 free(splat_buffer);
696
697 if (splatctl_fd != -1) {
698 if (close(splatctl_fd) == -1) {
699 fprintf(stderr, "Unable to close %s: %d\n",
700 SPLAT_DEV, errno);
701 }
702 }
703 }
704
705 static int
706 dev_init(void)
707 {
708 ListIterator i;
709 subsystem_t *sub;
710 int rc;
711
712 splatctl_fd = open(SPLAT_DEV, O_RDONLY);
713 if (splatctl_fd == -1) {
714 fprintf(stderr, "Unable to open %s: %d\n"
715 "Is the splat module loaded?\n", SPLAT_DEV, errno);
716 rc = errno;
717 goto error;
718 }
719
720 /* Determine kernel module version string */
721 memset(splat_version, 0, VERSION_SIZE);
722 if ((rc = read(splatctl_fd, splat_version, VERSION_SIZE - 1)) == -1)
723 goto error;
724
725 if ((rc = dev_clear()))
726 goto error;
727
728 if ((rc = dev_size(0)) < 0)
729 goto error;
730
731 splat_buffer_size = rc;
732 splat_buffer = (char *)malloc(splat_buffer_size);
733 if (splat_buffer == NULL) {
734 rc = -ENOMEM;
735 goto error;
736 }
737
738 memset(splat_buffer, 0, splat_buffer_size);
739
740 /* Determine available subsystems */
741 if ((rc = subsystem_setup()) != 0)
742 goto error;
743
744 /* Determine available tests for all subsystems */
745 i = list_iterator_create(subsystems);
746
747 while ((sub = list_next(i))) {
748 if ((rc = test_setup(sub)) != 0) {
749 list_iterator_destroy(i);
750 goto error;
751 }
752 }
753
754 list_iterator_destroy(i);
755 return 0;
756
757 error:
758 if (splatctl_fd != -1) {
759 if (close(splatctl_fd) == -1) {
760 fprintf(stderr, "Unable to close %s: %d\n",
761 SPLAT_DEV, errno);
762 }
763 }
764
765 return rc;
766 }
767
768 int
769 init(void)
770 {
771 int rc = 0;
772
773 /* Allocate the subsystem list */
774 subsystems = list_create((ListDelF)subsystem_fini);
775 if (subsystems == NULL)
776 rc = ENOMEM;
777
778 return rc;
779 }
780
781 void
782 fini(void)
783 {
784 list_destroy(subsystems);
785 }
786
787
788 int
789 main(int argc, char **argv)
790 {
791 cmd_args_t *args = NULL;
792 int rc = 0;
793
794 /* General init */
795 if ((rc = init()))
796 return rc;
797
798 /* Device specific init */
799 if ((rc = dev_init()))
800 goto out;
801
802 /* Argument init and parsing */
803 if ((args = args_init(argc, argv)) == NULL) {
804 rc = -1;
805 goto out;
806 }
807
808 /* Generic kernel version string */
809 if (args->args_verbose)
810 fprintf(stdout, "%s", splat_version);
811
812 /* Print the available test list and exit */
813 if (args->args_do_list) {
814 subsystem_list(subsystems, 0);
815 goto out;
816 }
817
818 /* Add all available test to the list of tests to run */
819 if (args->args_do_all) {
820 if ((rc = test_add_all(args)))
821 goto out;
822 }
823
824 /* Run all the requested tests */
825 if ((rc = tests_run(args)))
826 goto out;
827
828 out:
829 if (args != NULL)
830 args_fini(args);
831
832 dev_fini();
833 fini();
834 return rc;
835 }