f4642dfc17ad799b92d570a9742983ef58b991e4
[dragonfly.git] / usr.bin / dfregress / fe / text / fe_text.c
1 /*
2  * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
20  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/resource.h>
31 #include <sys/time.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34
35 #include <errno.h>
36 #include <signal.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdint.h>
40 #include <string.h>
41 #include <unistd.h>
42
43 #include <err.h>
44
45 #include <libprop/proplib.h>
46
47 #include "parser.h"
48 #include "testcase.h"
49 #include "runlist.h"
50 #include <dfregress.h>
51
52 static int count_by_result[10];
53
54 static void
55 print_row(char c)
56 {
57         int i;
58
59         for (i = 0; i < 80; i++)
60                 printf("%c", c);
61         printf("\n");
62 }
63
64 static void
65 print_header(void)
66 {
67         int i, j;
68
69         i = printf("Test case");
70         for (j = 60 - i; j > 0; j--)
71                 printf(" ");
72         printf("Result\n");
73
74         print_row('-');
75 }
76
77 static char *get_arg_string(prop_dictionary_t testcase)
78 {
79         static char buf[2048];
80         const char **argv;
81         int i;
82
83         buf[0] = '\0';
84
85         argv = testcase_get_args(testcase);
86
87         /* Skip the first argument, since it's just the test's name */
88         for (i = 1; argv[i] != NULL; i++) {
89                 strcat(buf, argv[i]);
90                 if (argv[i+1] != NULL)
91                         strcat(buf, " ");
92         }
93
94         return (i > 1) ? buf : NULL;
95 }
96
97 static void
98 print_summary(prop_array_t runlist)
99 {
100         float total_run;
101         float total_tests;
102
103         total_tests = 0.0 + prop_array_count(runlist);
104         total_run = 0.0 + total_tests - count_by_result[RESULT_BUILDFAIL] -
105             count_by_result[RESULT_PREFAIL] - count_by_result[RESULT_NOTRUN] -
106             count_by_result[RESULT_UNKNOWN];
107
108         printf("\n\n");
109         print_row('=');
110         printf("Summary:\n\n");
111
112
113         printf("Tests not built:\t%d\n", count_by_result[RESULT_BUILDFAIL]);
114
115         printf("Tests not run:\t\t%.0f\n", total_tests - total_run);
116
117         printf("Tests pre-failed:\t%d\n", count_by_result[RESULT_PREFAIL]);
118
119         printf("Tests post-failed:\t%d\n", count_by_result[RESULT_POSTFAIL]);
120
121         printf("Tests passed:\t\t%d\n", count_by_result[RESULT_PASS]);
122
123         printf("Tests failed:\t\t%d\n", count_by_result[RESULT_FAIL]);
124
125         printf("Tests crashed:\t\t%d\n", count_by_result[RESULT_SIGNALLED]);
126
127         printf("Tests timed out:\t%d\n", count_by_result[RESULT_TIMEOUT]);
128
129
130         printf("------\n");
131
132         printf("Run rate:\t\t%.2f\n", total_run/total_tests);
133         printf("Pass rate:\t\t%.2f\n", count_by_result[RESULT_PASS]/total_run);
134 }
135
136 static int
137 runlist_parse_summary(void *arg __unused, prop_dictionary_t testcase)
138 {
139         char *args;
140         int i, j;
141
142         ++count_by_result[testcase_get_result(testcase)];
143         args = get_arg_string(testcase);
144
145         i = printf("%s", testcase_get_name(testcase));
146         if (args != NULL)
147                 i+= printf(" (%s)", args);
148
149         for (j = 60 - i; j > 0; j--)
150                 printf(" ");
151
152         printf("%s\n", testcase_get_result_desc(testcase));
153
154         return 0;
155 }
156
157 static int
158 runlist_parse_detail(void *arg __unused, prop_dictionary_t testcase)
159 {
160         char *args;
161
162         args = get_arg_string(testcase);
163
164         printf("\n");
165         print_row('=');
166
167         printf("Test: %s\n", testcase_get_name(testcase));
168         if (args != NULL)
169                 printf("Command line arguments: %s\n", args);
170
171         printf("Type: %s\n", testcase_get_type_desc(testcase));
172         printf("Result: %s\n", testcase_get_result_desc(testcase));
173
174         switch (testcase_get_result(testcase)) {
175         case RESULT_FAIL:
176                 printf("Exit code: %d\n", testcase_get_exit_value(testcase));
177                 break;
178
179         case RESULT_SIGNALLED:
180                 printf("Signal: %d\n", testcase_get_signal(testcase));
181                 break;
182         };
183
184         print_row('-');
185         printf("driver sysbuf:\n%s\n", testcase_get_sys_buf(testcase));
186         print_row('-');
187         printf("build log:\n%s\n", testcase_get_build_buf(testcase));
188         print_row('-');
189         printf("'pre' log:\n%s\n", testcase_get_precmd_buf(testcase));
190         print_row('-');
191         printf("testcase stdout:\n%s\n", testcase_get_stdout_buf(testcase));
192         print_row('-');
193         printf("testcase stderr:\n%s\n", testcase_get_stderr_buf(testcase));
194         print_row('-');
195         printf("'post' log:\n%s\n", testcase_get_postcmd_buf(testcase));
196         print_row('-');
197         printf("cleanup log:\n%s\n", testcase_get_cleanup_buf(testcase));
198
199         return 0;
200 }
201
202 int
203 main(int argc, char *argv[])
204 {
205         if (argc != 2) {
206                 fprintf(stderr, "Usage: dfr2text <foo.plist>\n");
207                 exit(1);
208         }
209
210         prop_array_t runlist = runlist_load(argv[1]);
211
212         memset(count_by_result, 0, sizeof(count_by_result));
213         print_header();
214         runlist_iterate(runlist, runlist_parse_summary, runlist);
215         print_summary(runlist);
216         printf("\n\nDETAILED RESULTS:\n");
217
218         runlist_iterate(runlist, runlist_parse_detail, runlist);
219         return 0;
220 }
221