Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2010-2014 Joel Rosdahl
3 : : *
4 : : * This program is free software; you can redistribute it and/or modify it
5 : : * under the terms of the GNU General Public License as published by the Free
6 : : * Software Foundation; either version 3 of the License, or (at your option)
7 : : * any later version.
8 : : *
9 : : * This program is distributed in the hope that it will be useful, but WITHOUT
10 : : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 : : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 : : * more details.
13 : : *
14 : : * You should have received a copy of the GNU General Public License along with
15 : : * this program; if not, write to the Free Software Foundation, Inc., 51
16 : : * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 : : */
18 : :
19 : : #include "ccache.h"
20 : : #include "test/framework.h"
21 : : #include "util.h"
22 : :
23 : : #if defined(HAVE_TERMIOS_H)
24 : : #define USE_COLOR
25 : : #include <termios.h>
26 : : #endif
27 : :
28 : : static unsigned total_asserts;
29 : : static unsigned total_tests;
30 : : static unsigned total_suites;
31 : : static unsigned failed_tests;
32 : : static const char *current_suite;
33 : : static const char *current_test;
34 : : static char *dir_before_suite;
35 : : static char *dir_before_test;
36 : : static int verbose;
37 : :
38 : : static const char COLOR_END[] = "\x1b[m";
39 : : static const char COLOR_GREEN[] = "\x1b[32m";
40 : : static const char COLOR_RED[] = "\x1b[31m";
41 : :
42 : : #define COLOR(tty, color) ((tty) ? COLOR_##color : "")
43 : :
44 : : static int
45 : 1 : is_tty(int fd)
46 : : {
47 : : #ifdef USE_COLOR
48 : : struct termios t;
49 : 1 : return tcgetattr(fd, &t) == 0;
50 : : #else
51 : : (void)fd;
52 : : return 0;
53 : : #endif
54 : : }
55 : :
56 : : static const char *
57 : 3 : plural_s(unsigned n)
58 : : {
59 [ - + ]: 3 : return n == 1 ? "" : "s";
60 : : }
61 : :
62 : : int
63 : 1 : cct_run(suite_fn *suites, int verbose_output)
64 : : {
65 : : suite_fn *suite;
66 : 1 : int tty = is_tty(1);
67 : :
68 : 1 : x_unsetenv("GCC_COLORS"); /* Avoid confusing argument processing tests. */
69 : 1 : verbose = verbose_output;
70 : :
71 [ + + ]: 11 : for (suite = suites; *suite; suite++) {
72 : 10 : unsigned test_index = 0;
73 : : while (true) {
74 : 10 : test_index = (*suite)(test_index + 1);
75 [ + - ]: 10 : if (test_index == 0) {
76 : : /* We have reached the end of the suite. */
77 : : break;
78 : : }
79 : 0 : }
80 : : }
81 : :
82 [ + - ]: 1 : if (failed_tests == 0) {
83 [ - + ][ - + ]: 1 : printf("%sPASSED%s: %u assertion%s, %u test%s, %u suite%s\n",
84 : : COLOR(tty, GREEN), COLOR(tty, END),
85 : : total_asserts, plural_s(total_asserts),
86 : : total_tests, plural_s(total_tests),
87 : : total_suites, plural_s(total_suites));
88 : : } else {
89 [ # # ][ # # ]: 0 : printf("%sFAILED%s: %u test%s\n",
90 : : COLOR(tty, RED), COLOR(tty, END),
91 : : failed_tests, plural_s(failed_tests));
92 : : }
93 : 1 : return failed_tests > 0 ? 1 : 0;
94 : : }
95 : :
96 : : void
97 : 10 : cct_suite_begin(const char *name)
98 : : {
99 : 10 : ++total_suites;
100 [ + - ]: 10 : if (verbose) {
101 : 10 : printf("=== SUITE: %s ===\n", name);
102 : : }
103 : 10 : dir_before_suite = gnu_getcwd();
104 : 10 : create_dir(name);
105 : 10 : cct_chdir(name);
106 : 10 : current_suite = name;
107 : 10 : }
108 : :
109 : : void
110 : 10 : cct_suite_end()
111 : : {
112 : 10 : cct_chdir(dir_before_suite);
113 : 10 : free(dir_before_suite);
114 : 10 : dir_before_suite = NULL;
115 : 10 : }
116 : :
117 : : void
118 : 88 : cct_test_begin(const char *name)
119 : : {
120 : 88 : ++total_tests;
121 [ + - ]: 88 : if (verbose) {
122 : 88 : printf("--- TEST: %s ---\n", name);
123 : : }
124 : 88 : dir_before_test = gnu_getcwd();
125 : 88 : create_dir(name);
126 : 88 : cct_chdir(name);
127 : 88 : current_test = name;
128 : :
129 : 88 : putenv("CCACHE_CONFIG_PATH=/dev/null");
130 : 88 : cc_reset();
131 : 88 : }
132 : :
133 : : void
134 : 98 : cct_test_end()
135 : : {
136 [ + + ]: 98 : if (dir_before_test) {
137 : 88 : cct_chdir(dir_before_test);
138 : 88 : free(dir_before_test);
139 : 88 : dir_before_test = NULL;
140 : : }
141 : 98 : }
142 : :
143 : : void
144 : 448 : cct_check_passed(const char *file, int line, const char *what)
145 : : {
146 : 448 : ++total_asserts;
147 [ + - ]: 448 : if (verbose) {
148 : 448 : printf("%s:%d: Passed assertion: %s\n", file, line, what);
149 : : }
150 : 448 : }
151 : :
152 : : void
153 : 0 : cct_check_failed(const char *file, int line, const char *what,
154 : : const char *expected, const char *actual)
155 : : {
156 : 0 : ++total_asserts;
157 : 0 : ++failed_tests;
158 : 0 : fprintf(stderr, "%s:%d: Failed assertion:\n", file, line);
159 : 0 : fprintf(stderr, " Suite: %s\n", current_suite);
160 : 0 : fprintf(stderr, " Test: %s\n", current_test);
161 [ # # ]: 0 : if (expected) {
162 : 0 : fprintf(stderr, " Expression: %s\n", what);
163 [ # # ]: 0 : if (actual) {
164 : 0 : fprintf(stderr, " Expected: %s\n", expected);
165 : 0 : fprintf(stderr, " Actual: %s\n", actual);
166 : : } else {
167 : 0 : fprintf(stderr, " Message: %s\n", expected);
168 : : }
169 : : } else {
170 : 0 : fprintf(stderr, " Assertion: %s\n", what);
171 : : }
172 : 0 : fprintf(stderr, "\n");
173 : 0 : }
174 : :
175 : : bool
176 : 75 : cct_check_int_eq(const char *file, int line, const char *expression,
177 : : int64_t expected, int64_t actual)
178 : : {
179 [ + - ]: 75 : if (expected == actual) {
180 : 75 : cct_check_passed(file, line, expression);
181 : 75 : return true;
182 : : } else {
183 : : #ifdef HAVE_LONG_LONG
184 : 0 : char *exp_str = format("%lld", (long long)expected);
185 : 0 : char *act_str = format("%lld", (long long)actual);
186 : : #else
187 : : char *exp_str = format("%ld", (long)expected);
188 : : char *act_str = format("%ld", (long)actual);
189 : : #endif
190 : 0 : cct_check_failed(file, line, expression, exp_str, act_str);
191 : 0 : free(exp_str);
192 : 0 : free(act_str);
193 : 75 : return false;
194 : : }
195 : : }
196 : :
197 : : bool
198 : 172 : cct_check_str_eq(const char *file, int line, const char *expression,
199 : : const char *expected, const char *actual, bool free1,
200 : : bool free2)
201 : : {
202 : : bool result;
203 : :
204 [ + - ][ + - ]: 344 : if (expected && actual && str_eq(actual, expected)) {
[ + - ]
205 : 172 : cct_check_passed(file, line, expression);
206 : 172 : result = true;
207 : : } else {
208 [ # # ]: 0 : char *exp_str = expected ? format("\"%s\"", expected) : x_strdup("(null)");
209 [ # # ]: 0 : char *act_str = actual ? format("\"%s\"", actual) : x_strdup("(null)");
210 : 0 : cct_check_failed(file, line, expression, exp_str, act_str);
211 : 0 : free(exp_str);
212 : 0 : free(act_str);
213 : 0 : result = false;
214 : : }
215 : :
216 [ + + ]: 172 : if (free1) {
217 : 11 : free((char *)expected);
218 : : }
219 [ + + ]: 172 : if (free2) {
220 : 77 : free((char *)actual);
221 : : }
222 : 172 : return result;
223 : : }
224 : :
225 : : bool
226 : 28 : cct_check_args_eq(const char *file, int line, const char *expression,
227 : : struct args *expected, struct args *actual,
228 : : bool free1, bool free2)
229 : : {
230 : : bool result;
231 : :
232 [ + - ][ + - ]: 56 : if (expected && actual && args_equal(actual, expected)) {
[ + - ]
233 : 28 : cct_check_passed(file, line, expression);
234 : 28 : result = true;
235 : : } else {
236 [ # # ]: 0 : char *exp_str = expected ? args_to_string(expected) : x_strdup("(null)");
237 [ # # ]: 0 : char *act_str = actual ? args_to_string(actual) : x_strdup("(null)");
238 : 0 : cct_check_failed(file, line, expression, exp_str, act_str);
239 : 0 : free(exp_str);
240 : 0 : free(act_str);
241 : 0 : result = false;
242 : : }
243 : :
244 [ + - ]: 28 : if (free1) {
245 : 28 : args_free(expected);
246 : : }
247 [ + - ]: 28 : if (free2) {
248 : 28 : args_free(actual);
249 : : }
250 : 28 : return result;
251 : : }
252 : :
253 : : void
254 : 198 : cct_chdir(const char *path)
255 : : {
256 [ - + ]: 198 : if (chdir(path) != 0) {
257 : 0 : fprintf(stderr, "chdir: %s: %s", path, strerror(errno));
258 : 0 : abort();
259 : : }
260 : 198 : }
261 : :
262 : : void
263 : 2 : cct_wipe(const char *path)
264 : : {
265 : : /* TODO: rewrite using traverse(). */
266 : 2 : char *command = format("rm -rf %s", path);
267 [ - + ]: 2 : if (system(command) != 0) {
268 : 0 : perror(command);
269 : : }
270 : 2 : free(command);
271 : 2 : }
272 : :
273 : : void
274 : 1 : cct_create_fresh_dir(const char *path)
275 : : {
276 : 1 : cct_wipe(path);
277 [ - + ]: 1 : if (mkdir(path, 0777) != 0) {
278 : 0 : fprintf(stderr, "mkdir: %s: %s", path, strerror(errno));;
279 : 0 : abort();
280 : : }
281 : 1 : }
|