1 /*
2 * Check: a unit test framework for C
3 * Copyright (C) 2001, 2002 Arien Malec
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 */
20
21 #include "libcompat/libcompat.h"
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26
27 #include "internal-check.h"
28 #include "check_list.h"
29 #include "check_impl.h"
30 #include "check_str.h"
31 #include "check_print.h"
32
33 static void srunner_fprint_summary (FILE * file, SRunner * sr,
34 enum print_output print_mode);
35 static void srunner_fprint_results (FILE * file, SRunner * sr,
36 enum print_output print_mode);
37
38
39 void
srunner_print(SRunner * sr,enum print_output print_mode)40 srunner_print (SRunner * sr, enum print_output print_mode)
41 {
42 srunner_fprint (stdout, sr, print_mode);
43 }
44
45 void
srunner_fprint(FILE * file,SRunner * sr,enum print_output print_mode)46 srunner_fprint (FILE * file, SRunner * sr, enum print_output print_mode)
47 {
48 if (print_mode == CK_ENV) {
49 print_mode = get_env_printmode ();
50 }
51
52 srunner_fprint_summary (file, sr, print_mode);
53 srunner_fprint_results (file, sr, print_mode);
54 }
55
56 static void
srunner_fprint_summary(FILE * file,SRunner * sr,enum print_output print_mode)57 srunner_fprint_summary (FILE * file, SRunner * sr, enum print_output print_mode)
58 {
59 #if ENABLE_SUBUNIT
60 if (print_mode == CK_SUBUNIT)
61 return;
62 #endif
63
64 if (print_mode >= CK_MINIMAL) {
65 char *str;
66
67 str = sr_stat_str (sr);
68 fprintf (file, "%s\n", str);
69 free (str);
70 }
71 return;
72 }
73
74 static void
srunner_fprint_results(FILE * file,SRunner * sr,enum print_output print_mode)75 srunner_fprint_results (FILE * file, SRunner * sr, enum print_output print_mode)
76 {
77 List *resultlst;
78
79 #if ENABLE_SUBUNIT
80 if (print_mode == CK_SUBUNIT)
81 return;
82 #endif
83
84 resultlst = sr->resultlst;
85
86 for (check_list_front (resultlst); !check_list_at_end (resultlst);
87 check_list_advance (resultlst)) {
88 TestResult *tr = (TestResult *) check_list_val (resultlst);
89
90 tr_fprint (file, tr, print_mode);
91 }
92 return;
93 }
94
95 void
fprint_xml_esc(FILE * file,const char * str)96 fprint_xml_esc (FILE * file, const char *str)
97 {
98 /* The valid XML characters are as follows:
99 * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
100 * Characters that are outside of ASCII must be encoded. Further, the
101 * following special characters:
102 * " ' < > &
103 * must be encoded. We assume that the incoming string may be a multibyte
104 * character.
105 */
106
107 for (; *str != '\0'; str++) {
108 char next = *str;
109
110 /* handle special characters that must be escaped */
111 if (next == '"' || next == '\'' || next == '<' || next == '>'
112 || next == '&') {
113 switch (next) {
114 case '"':
115 fputs (""", file);
116 break;
117 case '\'':
118 fputs ("'", file);
119 break;
120 case '<':
121 fputs ("<", file);
122 break;
123 case '>':
124 fputs (">", file);
125 break;
126 case '&':
127 fputs ("&", file);
128 break;
129 }
130 }
131 /* printable ASCII */
132 else if (next >= ' ' && next <= '~') {
133 fputc (next, file);
134 }
135 /* Non-printable character */
136 else if (next == 0x9 || next == 0xA || next == 0xD || next >= 0x20) {
137 fprintf (file, "&#x%X;", next);
138 }
139 /* If it did not get printed, it is not a valid XML character */
140 }
141 }
142
143 void
tr_fprint(FILE * file,TestResult * tr,enum print_output print_mode)144 tr_fprint (FILE * file, TestResult * tr, enum print_output print_mode)
145 {
146 if (print_mode == CK_ENV) {
147 print_mode = get_env_printmode ();
148 }
149
150 if ((print_mode >= CK_VERBOSE && tr->rtype == CK_PASS) ||
151 (tr->rtype != CK_PASS && print_mode >= CK_NORMAL)) {
152 char *trstr = tr_str (tr);
153
154 fprintf (file, "%s\n", trstr);
155 free (trstr);
156 }
157 }
158
159 void
tr_xmlprint(FILE * file,TestResult * tr,enum print_output print_mode CK_ATTRIBUTE_UNUSED)160 tr_xmlprint (FILE * file, TestResult * tr,
161 enum print_output print_mode CK_ATTRIBUTE_UNUSED)
162 {
163 char result[10];
164 char *path_name = NULL;
165 char *file_name = NULL;
166 char *slash = NULL;
167
168 switch (tr->rtype) {
169 case CK_PASS:
170 snprintf (result, sizeof (result), "%s", "success");
171 break;
172 case CK_FAILURE:
173 snprintf (result, sizeof (result), "%s", "failure");
174 break;
175 case CK_ERROR:
176 snprintf (result, sizeof (result), "%s", "error");
177 break;
178 case CK_TEST_RESULT_INVALID:
179 default:
180 abort ();
181 break;
182 }
183
184 if (tr->file) {
185 slash = strrchr (tr->file, '/');
186 if (slash == NULL) {
187 slash = strrchr (tr->file, '\\');
188 }
189
190 if (slash == NULL) {
191 path_name = strdup (".");
192 file_name = tr->file;
193 } else {
194 path_name = strdup (tr->file);
195 path_name[slash - tr->file] = 0; /* Terminate the temporary string. */
196 file_name = slash + 1;
197 }
198 }
199
200
201 fprintf (file, " <test result=\"%s\">\n", result);
202 fprintf (file, " <path>%s</path>\n",
203 (path_name == NULL ? "" : path_name));
204 fprintf (file, " <fn>%s:%d</fn>\n",
205 (file_name == NULL ? "" : file_name), tr->line);
206 fprintf (file, " <id>%s</id>\n", tr->tname);
207 fprintf (file, " <iteration>%d</iteration>\n", tr->iter);
208 fprintf (file, " <duration>%d.%06d</duration>\n",
209 tr->duration < 0 ? -1 : tr->duration / US_PER_SEC,
210 tr->duration < 0 ? 0 : tr->duration % US_PER_SEC);
211 fprintf (file, " <description>");
212 fprint_xml_esc (file, tr->tcname);
213 fprintf (file, "</description>\n");
214 fprintf (file, " <message>");
215 fprint_xml_esc (file, tr->msg);
216 fprintf (file, "</message>\n");
217 fprintf (file, " </test>\n");
218
219 free (path_name);
220 }
221
222 enum print_output
get_env_printmode(void)223 get_env_printmode (void)
224 {
225 char *env = getenv ("CK_VERBOSITY");
226
227 if (env == NULL)
228 return CK_NORMAL;
229 if (strcmp (env, "silent") == 0)
230 return CK_SILENT;
231 if (strcmp (env, "minimal") == 0)
232 return CK_MINIMAL;
233 if (strcmp (env, "verbose") == 0)
234 return CK_VERBOSE;
235 return CK_NORMAL;
236 }
237