1 /* Solaris Porting Layer Aggressive Test (SPLAT) userspace interface */
11 #include <sys/ioctl.h>
13 #include <sys/types.h>
19 static const char shortOpts
[] = "hvlat:xc";
20 static const struct option longOpts
[] = {
21 { "help", no_argument
, 0, 'h' },
22 { "verbose", no_argument
, 0, 'v' },
23 { "list", no_argument
, 0, 'l' },
24 { "all", no_argument
, 0, 'a' },
25 { "test", required_argument
, 0, 't' },
26 { "exit", no_argument
, 0, 'x' },
27 { "nocolor", no_argument
, 0, 'c' },
31 #define VERSION_SIZE 64
33 static List subsystems
; /* Subsystem/tests */
34 static int splatctl_fd
; /* Control file descriptor */
35 static char splat_version
[VERSION_SIZE
]; /* Kernel version string */
36 static char *splat_buffer
= NULL
; /* Scratch space area */
37 static int splat_buffer_size
= 0; /* Scratch space size */
40 static void test_list(List
, int);
41 static int dev_clear(void);
42 static void subsystem_fini(subsystem_t
*);
43 static void test_fini(test_t
*);
46 static int usage(void) {
47 fprintf(stderr
, "usage: splat [hvla] [-t <subsystem:<tests>>]\n");
49 " --help -h This help\n"
50 " --verbose -v Increase verbosity\n"
51 " --list -l List all tests in all subsystems\n"
52 " --all -a Run all tests in all subsystems\n"
53 " --test -t <sub:test> Run 'test' in subsystem 'sub'\n"
54 " --exit -x Exit on first test error\n"
55 " --nocolor -c Do not colorize output\n");
58 " splat -t kmem:all # Runs all kmem tests\n"
59 " splat -t taskq:0x201 # Run taskq test 0x201\n");
64 static subsystem_t
*subsystem_init(splat_user_t
*desc
)
68 sub
= (subsystem_t
*)malloc(sizeof(*sub
));
72 memcpy(&sub
->sub_desc
, desc
, sizeof(*desc
));
74 sub
->sub_tests
= list_create((ListDelF
)test_fini
);
75 if (sub
->sub_tests
== NULL
) {
83 static void subsystem_fini(subsystem_t
*sub
)
89 static int subsystem_setup(void)
92 int i
, rc
, size
, cfg_size
;
96 /* Aquire the number of registered subsystems */
97 cfg_size
= sizeof(*cfg
);
98 cfg
= (splat_cfg_t
*)malloc(cfg_size
);
102 memset(cfg
, 0, cfg_size
);
103 cfg
->cfg_magic
= SPLAT_CFG_MAGIC
;
104 cfg
->cfg_cmd
= SPLAT_CFG_SUBSYSTEM_COUNT
;
106 rc
= ioctl(splatctl_fd
, SPLAT_CFG
, cfg
);
108 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
109 (unsigned long) SPLAT_CFG
, cfg
->cfg_cmd
, errno
);
117 /* Based on the newly aquired number of subsystems allocate enough
118 * memory to get the descriptive information for them all. */
119 cfg_size
= sizeof(*cfg
) + size
* sizeof(splat_user_t
);
120 cfg
= (splat_cfg_t
*)malloc(cfg_size
);
124 memset(cfg
, 0, cfg_size
);
125 cfg
->cfg_magic
= SPLAT_CFG_MAGIC
;
126 cfg
->cfg_cmd
= SPLAT_CFG_SUBSYSTEM_LIST
;
127 cfg
->cfg_data
.splat_subsystems
.size
= size
;
129 rc
= ioctl(splatctl_fd
, SPLAT_CFG
, cfg
);
131 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
132 (unsigned long) SPLAT_CFG
, cfg
->cfg_cmd
, errno
);
137 /* Add the new subsystems in to the global list */
139 for (i
= 0; i
< size
; i
++) {
140 desc
= &(cfg
->cfg_data
.splat_subsystems
.descs
[i
]);
142 sub
= subsystem_init(desc
);
144 fprintf(stderr
, "Error initializing subsystem: %s\n",
150 list_append(subsystems
, sub
);
157 /* XXX - Commented out until we sort the lists */
159 static int subsystem_compare(const void *l_arg
, const void *r_arg
, void *private)
161 const subsystem_t
*l
= l_arg
;
162 const subsystem_t
*r
= r_arg
;
164 if (l
->sub_desc
.id
> r
->sub_desc
.id
)
167 if (l
->sub_desc
.id
< r
->sub_desc
.id
)
174 static void subsystem_list(List l
, int indent
)
180 "------------------------------ "
181 "Available SPLAT Tests "
182 "------------------------------\n");
184 i
= list_iterator_create(l
);
186 while ((sub
= list_next(i
))) {
187 fprintf(stdout
, "%*s0x%0*x %-*s ---- %s ----\n",
190 SPLAT_NAME_SIZE
+ 7, sub
->sub_desc
.name
,
192 test_list(sub
->sub_tests
, indent
+ 7);
195 list_iterator_destroy(i
);
198 static test_t
*test_init(subsystem_t
*sub
, splat_user_t
*desc
)
202 test
= (test_t
*)malloc(sizeof(*test
));
206 test
->test_sub
= sub
;
207 memcpy(&test
->test_desc
, desc
, sizeof(*desc
));
212 static void test_fini(test_t
*test
)
214 assert(test
!= NULL
);
218 static int test_setup(subsystem_t
*sub
)
225 /* Aquire the number of registered tests for the give subsystem */
226 cfg
= (splat_cfg_t
*)malloc(sizeof(*cfg
));
230 memset(cfg
, 0, sizeof(*cfg
));
231 cfg
->cfg_magic
= SPLAT_CFG_MAGIC
;
232 cfg
->cfg_cmd
= SPLAT_CFG_TEST_COUNT
;
233 cfg
->cfg_arg1
= sub
->sub_desc
.id
; /* Subsystem of interest */
235 rc
= ioctl(splatctl_fd
, SPLAT_CFG
, cfg
);
237 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
238 (unsigned long) SPLAT_CFG
, cfg
->cfg_cmd
, errno
);
246 /* Based on the newly aquired number of tests allocate enough
247 * memory to get the descriptive information for them all. */
248 cfg
= (splat_cfg_t
*)malloc(sizeof(*cfg
) + size
* sizeof(splat_user_t
));
252 memset(cfg
, 0, sizeof(*cfg
) + size
* sizeof(splat_user_t
));
253 cfg
->cfg_magic
= SPLAT_CFG_MAGIC
;
254 cfg
->cfg_cmd
= SPLAT_CFG_TEST_LIST
;
255 cfg
->cfg_arg1
= sub
->sub_desc
.id
; /* Subsystem of interest */
256 cfg
->cfg_data
.splat_tests
.size
= size
;
258 rc
= ioctl(splatctl_fd
, SPLAT_CFG
, cfg
);
260 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
261 (unsigned long) SPLAT_CFG
, cfg
->cfg_cmd
, errno
);
266 /* Add the new tests in to the relevant subsystems */
268 for (i
= 0; i
< size
; i
++) {
269 desc
= &(cfg
->cfg_data
.splat_tests
.descs
[i
]);
271 test
= test_init(sub
, desc
);
273 fprintf(stderr
, "Error initializing test: %s\n",
279 list_append(sub
->sub_tests
, test
);
286 /* XXX - Commented out until we sort the lists */
288 static int test_compare(const void *l_arg
, const void *r_arg
, void *private)
290 const test_t
*l
= l_arg
;
291 const test_t
*r
= r_arg
;
293 if (l
->test_desc
.id
> r
->test_desc
.id
)
296 if (l
->test_desc
.id
< r
->test_desc
.id
)
303 static test_t
*test_copy(test_t
*test
)
305 return test_init(test
->test_sub
, &test
->test_desc
);
308 static void test_list(List l
, int indent
)
313 i
= list_iterator_create(l
);
315 while ((test
= list_next(i
)))
316 fprintf(stdout
, "%*s0x%0*x %-*s %-*s\n",
318 04, test
->test_desc
.id
,
319 SPLAT_NAME_SIZE
, test
->test_desc
.name
,
320 SPLAT_DESC_SIZE
, test
->test_desc
.desc
);
322 list_iterator_destroy(i
);
325 static test_t
*test_find(char *sub_str
, char *test_str
)
330 int sub_num
, test_num
;
332 /* No error checking here because it may not be a number, it's
333 * perfectly OK for it to be a string. Since we're just using
334 * it for comparison purposes this is all very safe.
336 sub_num
= strtol(sub_str
, NULL
, 0);
337 test_num
= strtol(test_str
, NULL
, 0);
339 si
= list_iterator_create(subsystems
);
341 while ((sub
= list_next(si
))) {
343 if (strncmp(sub
->sub_desc
.name
, sub_str
, SPLAT_NAME_SIZE
) &&
344 sub
->sub_desc
.id
!= sub_num
)
347 ti
= list_iterator_create(sub
->sub_tests
);
349 while ((test
= list_next(ti
))) {
351 if (!strncmp(test
->test_desc
.name
, test_str
,
352 SPLAT_NAME_SIZE
) || test
->test_desc
.id
== test_num
) {
353 list_iterator_destroy(ti
);
354 list_iterator_destroy(si
);
359 list_iterator_destroy(ti
);
362 list_iterator_destroy(si
);
367 static int test_add(cmd_args_t
*args
, test_t
*test
)
371 tmp
= test_copy(test
);
375 list_append(args
->args_tests
, tmp
);
379 static int test_add_all(cmd_args_t
*args
)
386 si
= list_iterator_create(subsystems
);
388 while ((sub
= list_next(si
))) {
389 ti
= list_iterator_create(sub
->sub_tests
);
391 while ((test
= list_next(ti
))) {
392 if ((rc
= test_add(args
, test
))) {
393 list_iterator_destroy(ti
);
394 list_iterator_destroy(si
);
399 list_iterator_destroy(ti
);
402 list_iterator_destroy(si
);
407 static int test_run(cmd_args_t
*args
, test_t
*test
)
409 subsystem_t
*sub
= test
->test_sub
;
415 cmd_size
= sizeof(*cmd
);
416 cmd
= (splat_cmd_t
*)malloc(cmd_size
);
420 memset(cmd
, 0, cmd_size
);
421 cmd
->cmd_magic
= SPLAT_CMD_MAGIC
;
422 cmd
->cmd_subsystem
= sub
->sub_desc
.id
;
423 cmd
->cmd_test
= test
->test_desc
.id
;
424 cmd
->cmd_data_size
= 0; /* Unused feature */
426 fprintf(stdout
, "%*s:%-*s ",
427 SPLAT_NAME_SIZE
, sub
->sub_desc
.name
,
428 SPLAT_NAME_SIZE
, test
->test_desc
.name
);
430 rc
= ioctl(splatctl_fd
, SPLAT_CMD
, cmd
);
431 if (args
->args_do_color
) {
432 fprintf(stdout
, "%s %s\n", rc
?
433 COLOR_RED
"Fail" COLOR_RESET
:
434 COLOR_GREEN
"Pass" COLOR_RESET
,
435 rc
? strerror(errno
) : "");
437 fprintf(stdout
, "%s %s\n", rc
?
439 rc
? strerror(errno
) : "");
444 if (args
->args_verbose
) {
445 if ((rc
= read(splatctl_fd
, splat_buffer
, splat_buffer_size
- 1)) < 0) {
446 fprintf(stdout
, "Error reading results: %d\n", rc
);
448 fprintf(stdout
, "\n%s\n", splat_buffer
);
456 static int tests_run(cmd_args_t
*args
)
463 "------------------------------ "
464 "Running SPLAT Tests "
465 "------------------------------\n");
467 i
= list_iterator_create(args
->args_tests
);
469 while ((test
= list_next(i
))) {
470 rc
= test_run(args
, test
);
471 if (rc
&& args
->args_exit_on_error
) {
472 list_iterator_destroy(i
);
477 list_iterator_destroy(i
);
481 static int args_parse_test(cmd_args_t
*args
, char *str
)
486 char *sub_str
, *test_str
;
487 int sub_num
, test_num
;
488 int sub_all
= 0, test_all
= 0;
491 test_str
= strchr(str
, ':');
492 if (test_str
== NULL
) {
493 fprintf(stderr
, "Test must be of the "
494 "form <subsystem:test>\n");
500 test_str
= test_str
+ 1;
502 sub_num
= strtol(sub_str
, NULL
, 0);
503 test_num
= strtol(test_str
, NULL
, 0);
505 if (!strncasecmp(sub_str
, "all", strlen(sub_str
)) || (sub_num
== -1))
508 if (!strncasecmp(test_str
, "all", strlen(test_str
)) || (test_num
== -1))
511 si
= list_iterator_create(subsystems
);
515 /* Add all tests from all subsystems */
516 while ((s
= list_next(si
))) {
517 ti
= list_iterator_create(s
->sub_tests
);
518 while ((t
= list_next(ti
))) {
519 if ((rc
= test_add(args
, t
))) {
520 list_iterator_destroy(ti
);
524 list_iterator_destroy(ti
);
527 /* Add a specific test from all subsystems */
528 while ((s
= list_next(si
))) {
529 if ((t
= test_find(s
->sub_desc
.name
,test_str
))) {
530 if ((rc
= test_add(args
, t
)))
538 fprintf(stderr
, "No tests '%s:%s' could be "
539 "found\n", sub_str
, test_str
);
543 /* Add all tests from a specific subsystem */
544 while ((s
= list_next(si
))) {
545 if (strncasecmp(sub_str
, s
->sub_desc
.name
,
549 ti
= list_iterator_create(s
->sub_tests
);
550 while ((t
= list_next(ti
))) {
551 if ((rc
= test_add(args
, t
))) {
552 list_iterator_destroy(ti
);
556 list_iterator_destroy(ti
);
559 /* Add a specific test from a specific subsystem */
560 if ((t
= test_find(sub_str
, test_str
))) {
561 if ((rc
= test_add(args
, t
)))
564 fprintf(stderr
, "Test '%s:%s' could not be "
565 "found\n", sub_str
, test_str
);
571 list_iterator_destroy(si
);
576 list_iterator_destroy(si
);
578 fprintf(stderr
, "Test '%s:%s' not added to run list: %d\n",
579 sub_str
, test_str
, rc
);
584 static void args_fini(cmd_args_t
*args
)
586 assert(args
!= NULL
);
588 if (args
->args_tests
!= NULL
)
589 list_destroy(args
->args_tests
);
595 args_init(int argc
, char **argv
)
602 return (cmd_args_t
*) NULL
;
605 /* Configure and populate the args structures */
606 args
= malloc(sizeof(*args
));
610 memset(args
, 0, sizeof(*args
));
611 args
->args_verbose
= 0;
612 args
->args_do_list
= 0;
613 args
->args_do_all
= 0;
614 args
->args_do_color
= 1;
615 args
->args_exit_on_error
= 0;
616 args
->args_tests
= list_create((ListDelF
)test_fini
);
617 if (args
->args_tests
== NULL
) {
622 while ((c
= getopt_long(argc
, argv
, shortOpts
, longOpts
, NULL
)) != -1){
624 case 'v': args
->args_verbose
++; break;
625 case 'l': args
->args_do_list
= 1; break;
626 case 'a': args
->args_do_all
= 1; break;
627 case 'c': args
->args_do_color
= 0; break;
628 case 'x': args
->args_exit_on_error
= 1; break;
630 if (args
->args_do_all
) {
631 fprintf(stderr
, "Option -t <subsystem:test> is "
632 "useless when used with -a\n");
637 rc
= args_parse_test(args
, argv
[optind
- 1]);
649 fprintf(stderr
, "Unknown option '%s'\n",
664 memset(&cfg
, 0, sizeof(cfg
));
665 cfg
.cfg_magic
= SPLAT_CFG_MAGIC
;
666 cfg
.cfg_cmd
= SPLAT_CFG_BUFFER_CLEAR
;
669 rc
= ioctl(splatctl_fd
, SPLAT_CFG
, &cfg
);
671 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
672 (unsigned long) SPLAT_CFG
, cfg
.cfg_cmd
, errno
);
674 lseek(splatctl_fd
, 0, SEEK_SET
);
685 memset(&cfg
, 0, sizeof(cfg
));
686 cfg
.cfg_magic
= SPLAT_CFG_MAGIC
;
687 cfg
.cfg_cmd
= SPLAT_CFG_BUFFER_SIZE
;
690 rc
= ioctl(splatctl_fd
, SPLAT_CFG
, &cfg
);
692 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
693 (unsigned long) SPLAT_CFG
, cfg
.cfg_cmd
, errno
);
706 if (splatctl_fd
!= -1) {
707 if (close(splatctl_fd
) == -1) {
708 fprintf(stderr
, "Unable to close %s: %d\n",
721 splatctl_fd
= open(SPLAT_DEV
, O_RDONLY
);
722 if (splatctl_fd
== -1) {
723 fprintf(stderr
, "Unable to open %s: %d\n"
724 "Is the splat module loaded?\n", SPLAT_DEV
, errno
);
729 /* Determine kernel module version string */
730 memset(splat_version
, 0, VERSION_SIZE
);
731 if ((rc
= read(splatctl_fd
, splat_version
, VERSION_SIZE
- 1)) == -1)
734 if ((rc
= dev_clear()))
737 if ((rc
= dev_size(0)) < 0)
740 splat_buffer_size
= rc
;
741 splat_buffer
= (char *)malloc(splat_buffer_size
);
742 if (splat_buffer
== NULL
) {
747 memset(splat_buffer
, 0, splat_buffer_size
);
749 /* Determine available subsystems */
750 if ((rc
= subsystem_setup()) != 0)
753 /* Determine available tests for all subsystems */
754 i
= list_iterator_create(subsystems
);
756 while ((sub
= list_next(i
))) {
757 if ((rc
= test_setup(sub
)) != 0) {
758 list_iterator_destroy(i
);
763 list_iterator_destroy(i
);
767 if (splatctl_fd
!= -1) {
768 if (close(splatctl_fd
) == -1) {
769 fprintf(stderr
, "Unable to close %s: %d\n",
782 /* Allocate the subsystem list */
783 subsystems
= list_create((ListDelF
)subsystem_fini
);
784 if (subsystems
== NULL
)
793 list_destroy(subsystems
);
798 main(int argc
, char **argv
)
800 cmd_args_t
*args
= NULL
;
807 /* Device specific init */
808 if ((rc
= dev_init()))
811 /* Argument init and parsing */
812 if ((args
= args_init(argc
, argv
)) == NULL
) {
817 /* Generic kernel version string */
818 if (args
->args_verbose
)
819 fprintf(stdout
, "%s", splat_version
);
821 /* Print the available test list and exit */
822 if (args
->args_do_list
) {
823 subsystem_list(subsystems
, 0);
827 /* Add all available test to the list of tests to run */
828 if (args
->args_do_all
) {
829 if ((rc
= test_add_all(args
)))
833 /* Run all the requested tests */
834 if ((rc
= tests_run(args
)))