Imported Upstream version 3.4
[platform/upstream/ccache.git] / unittest / test_conf.c
1 // Copyright (C) 2011-2018 Joel Rosdahl
2 //
3 // This program is free software; you can redistribute it and/or modify it
4 // under the terms of the GNU General Public License as published by the Free
5 // Software Foundation; either version 3 of the License, or (at your option)
6 // any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but WITHOUT
9 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 // more details.
12 //
13 // You should have received a copy of the GNU General Public License along with
14 // this program; if not, write to the Free Software Foundation, Inc., 51
15 // Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
17 #include "../src/conf.h"
18 #include "framework.h"
19 #include "util.h"
20
21 #define N_CONFIG_ITEMS 31
22 static struct {
23         char *descr;
24         const char *origin;
25 } received_conf_items[N_CONFIG_ITEMS];
26 static size_t n_received_conf_items = 0;
27
28 static void
29 conf_item_receiver(const char *descr, const char *origin, void *context)
30 {
31         (void)context;
32         received_conf_items[n_received_conf_items].descr = x_strdup(descr);
33         received_conf_items[n_received_conf_items].origin = origin;
34         ++n_received_conf_items;
35 }
36
37 static void
38 free_received_conf_items(void)
39 {
40         while (n_received_conf_items > 0) {
41                 --n_received_conf_items;
42                 free(received_conf_items[n_received_conf_items].descr);
43         }
44 }
45
46 TEST_SUITE(conf)
47
48 TEST(conf_create)
49 {
50         struct conf *conf = conf_create();
51         CHECK_STR_EQ("", conf->base_dir);
52         CHECK_STR_EQ_FREE1(format("%s/.ccache", get_home_directory()),
53                            conf->cache_dir);
54         CHECK_INT_EQ(2, conf->cache_dir_levels);
55         CHECK_STR_EQ("", conf->compiler);
56         CHECK_STR_EQ("mtime", conf->compiler_check);
57         CHECK(!conf->compression);
58         CHECK_INT_EQ(6, conf->compression_level);
59         CHECK_STR_EQ("", conf->cpp_extension);
60         CHECK(conf->direct_mode);
61         CHECK(!conf->disable);
62         CHECK_STR_EQ("", conf->extra_files_to_hash);
63         CHECK(!conf->hard_link);
64         CHECK(conf->hash_dir);
65         CHECK_STR_EQ("", conf->ignore_headers_in_manifest);
66         CHECK(!conf->keep_comments_cpp);
67         CHECK_FLOAT_EQ(0.8f, conf->limit_multiple);
68         CHECK_STR_EQ("", conf->log_file);
69         CHECK_INT_EQ(0, conf->max_files);
70         CHECK_INT_EQ((uint64_t)5 * 1000 * 1000 * 1000, conf->max_size);
71         CHECK_STR_EQ("", conf->path);
72         CHECK_STR_EQ("", conf->prefix_command);
73         CHECK_STR_EQ("", conf->prefix_command_cpp);
74         CHECK(!conf->read_only);
75         CHECK(!conf->read_only_direct);
76         CHECK(!conf->recache);
77         CHECK(conf->run_second_cpp);
78         CHECK_INT_EQ(0, conf->sloppiness);
79         CHECK(conf->stats);
80         CHECK_STR_EQ("", conf->temporary_dir);
81         CHECK_INT_EQ(UINT_MAX, conf->umask);
82         CHECK(!conf->unify);
83         conf_free(conf);
84 }
85
86 TEST(conf_read_valid_config)
87 {
88         struct conf *conf = conf_create();
89         char *errmsg, *user;
90         putenv("USER=rabbit");
91         user = getenv("USER");
92         CHECK_STR_EQ("rabbit", user);
93         create_file(
94           "ccache.conf",
95 #ifndef _WIN32
96           "base_dir =  /$USER/foo/${USER} \n"
97 #else
98           "base_dir = C:/$USER/foo/${USER}\n"
99 #endif
100           "cache_dir=\n"
101           "cache_dir = $USER$/${USER}/.ccache\n"
102           "\n"
103           "\n"
104           "  #A comment\n"
105           " cache_dir_levels = 4\n"
106           "\t compiler = foo\n"
107           "compiler_check = none\n"
108           "compression=true\n"
109           "compression_level= 2\n"
110           "cpp_extension = .foo\n"
111           "direct_mode = false\n"
112           "disable = true\n"
113           "extra_files_to_hash = a:b c:$USER\n"
114           "hard_link = true\n"
115           "hash_dir = false\n"
116           "ignore_headers_in_manifest = a:b/c\n"
117           "keep_comments_cpp = true\n"
118           "limit_multiple = 1.0\n"
119           "log_file = $USER${USER} \n"
120           "max_files = 17\n"
121           "max_size = 123M\n"
122           "path = $USER.x\n"
123           "prefix_command = x$USER\n"
124           "prefix_command_cpp = y\n"
125           "read_only = true\n"
126           "read_only_direct = true\n"
127           "recache = true\n"
128           "run_second_cpp = false\n"
129           "sloppiness =     file_macro   ,time_macros,  include_file_mtime,include_file_ctime,file_stat_matches,pch_defines ,  no_system_headers  \n"
130           "stats = false\n"
131           "temporary_dir = ${USER}_foo\n"
132           "umask = 777\n"
133           "unify = true"); // Note: no newline.
134         CHECK(conf_read(conf, "ccache.conf", &errmsg));
135         CHECK(!errmsg);
136
137 #ifndef _WIN32
138         CHECK_STR_EQ_FREE1(format("/%s/foo/%s", user, user), conf->base_dir);
139 #else
140         CHECK_STR_EQ_FREE1(format("C:/%s/foo/%s", user, user), conf->base_dir);
141 #endif
142         CHECK_STR_EQ_FREE1(format("%s$/%s/.ccache", user, user), conf->cache_dir);
143         CHECK_INT_EQ(4, conf->cache_dir_levels);
144         CHECK_STR_EQ("foo", conf->compiler);
145         CHECK_STR_EQ("none", conf->compiler_check);
146         CHECK(conf->compression);
147         CHECK_INT_EQ(2, conf->compression_level);
148         CHECK_STR_EQ(".foo", conf->cpp_extension);
149         CHECK(!conf->direct_mode);
150         CHECK(conf->disable);
151         CHECK_STR_EQ_FREE1(format("a:b c:%s", user), conf->extra_files_to_hash);
152         CHECK(conf->hard_link);
153         CHECK(!conf->hash_dir);
154         CHECK_STR_EQ("a:b/c", conf->ignore_headers_in_manifest);
155         CHECK(conf->keep_comments_cpp);
156         CHECK_FLOAT_EQ(1.0, conf->limit_multiple);
157         CHECK_STR_EQ_FREE1(format("%s%s", user, user), conf->log_file);
158         CHECK_INT_EQ(17, conf->max_files);
159         CHECK_INT_EQ(123 * 1000 * 1000, conf->max_size);
160         CHECK_STR_EQ_FREE1(format("%s.x", user), conf->path);
161         CHECK_STR_EQ_FREE1(format("x%s", user), conf->prefix_command);
162         CHECK_STR_EQ("y", conf->prefix_command_cpp);
163         CHECK(conf->read_only);
164         CHECK(conf->read_only_direct);
165         CHECK(conf->recache);
166         CHECK(!conf->run_second_cpp);
167         CHECK_INT_EQ(SLOPPY_INCLUDE_FILE_MTIME|SLOPPY_INCLUDE_FILE_CTIME|
168                      SLOPPY_FILE_MACRO|SLOPPY_TIME_MACROS|
169                      SLOPPY_FILE_STAT_MATCHES|SLOPPY_NO_SYSTEM_HEADERS|
170                      SLOPPY_PCH_DEFINES,
171                      conf->sloppiness);
172         CHECK(!conf->stats);
173         CHECK_STR_EQ_FREE1(format("%s_foo", user), conf->temporary_dir);
174         CHECK_INT_EQ(0777, conf->umask);
175         CHECK(conf->unify);
176
177         conf_free(conf);
178 }
179
180 TEST(conf_read_with_missing_equal_sign)
181 {
182         struct conf *conf = conf_create();
183         char *errmsg;
184         create_file("ccache.conf", "no equal sign");
185         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
186         CHECK_STR_EQ_FREE2("ccache.conf:1: missing equal sign",
187                            errmsg);
188         conf_free(conf);
189 }
190
191 TEST(conf_read_with_bad_config_key)
192 {
193         struct conf *conf = conf_create();
194         char *errmsg;
195         create_file("ccache.conf", "# Comment\nfoo = bar");
196         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
197         CHECK_STR_EQ_FREE2("ccache.conf:2: unknown configuration option \"foo\"",
198                            errmsg);
199         conf_free(conf);
200 }
201
202 TEST(conf_read_invalid_bool)
203 {
204         struct conf *conf = conf_create();
205         char *errmsg;
206
207         create_file("ccache.conf", "disable=");
208         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
209         CHECK_STR_EQ_FREE2("ccache.conf:1: not a boolean value: \"\"",
210                            errmsg);
211
212         create_file("ccache.conf", "disable=foo");
213         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
214         CHECK_STR_EQ_FREE2("ccache.conf:1: not a boolean value: \"foo\"",
215                            errmsg);
216         conf_free(conf);
217 }
218
219 TEST(conf_read_invalid_env_string)
220 {
221         struct conf *conf = conf_create();
222         char *errmsg;
223         create_file("ccache.conf", "base_dir = ${foo");
224         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
225         CHECK_STR_EQ_FREE2("ccache.conf:1: syntax error: missing '}' after \"foo\"",
226                            errmsg);
227         // Other cases tested in test_util.c.
228         conf_free(conf);
229 }
230
231 TEST(conf_read_empty_umask)
232 {
233         struct conf *conf = conf_create();
234         char *errmsg;
235         create_file("ccache.conf", "umask = ");
236         CHECK(conf_read(conf, "ccache.conf", &errmsg));
237         CHECK_INT_EQ(conf->umask, UINT_MAX);
238         conf_free(conf);
239 }
240
241 TEST(conf_read_invalid_size)
242 {
243         struct conf *conf = conf_create();
244         char *errmsg;
245         create_file("ccache.conf", "max_size = foo");
246         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
247         CHECK_STR_EQ_FREE2("ccache.conf:1: invalid size: \"foo\"",
248                            errmsg);
249         // Other cases tested in test_util.c.
250         conf_free(conf);
251 }
252
253 TEST(conf_read_invalid_sloppiness)
254 {
255         struct conf *conf = conf_create();
256         char *errmsg;
257         create_file("ccache.conf", "sloppiness = file_macro, foo");
258         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
259         CHECK_STR_EQ_FREE2("ccache.conf:1: unknown sloppiness: \"foo\"",
260                            errmsg);
261         conf_free(conf);
262 }
263
264 TEST(conf_read_invalid_unsigned)
265 {
266         struct conf *conf = conf_create();
267         char *errmsg;
268
269         create_file("ccache.conf", "max_files =");
270         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
271         CHECK_STR_EQ_FREE2("ccache.conf:1: invalid unsigned integer: \"\"",
272                            errmsg);
273
274         create_file("ccache.conf", "max_files = -42");
275         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
276         CHECK_STR_EQ_FREE2("ccache.conf:1: invalid unsigned integer: \"-42\"",
277                            errmsg);
278
279         create_file("ccache.conf", "max_files = foo");
280         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
281         CHECK_STR_EQ_FREE2("ccache.conf:1: invalid unsigned integer: \"foo\"",
282                            errmsg);
283
284         conf_free(conf);
285 }
286
287 TEST(verify_absolute_base_dir)
288 {
289         struct conf *conf = conf_create();
290         char *errmsg;
291
292         create_file("ccache.conf", "base_dir = relative/path");
293         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
294         CHECK_STR_EQ_FREE2("ccache.conf:1: not an absolute path: \"relative/path\"",
295                            errmsg);
296
297         create_file("ccache.conf", "base_dir =");
298         CHECK(conf_read(conf, "ccache.conf", &errmsg));
299
300         conf_free(conf);
301 }
302
303 TEST(verify_dir_levels)
304 {
305         struct conf *conf = conf_create();
306         char *errmsg;
307
308         create_file("ccache.conf", "cache_dir_levels = 0");
309         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
310         CHECK_STR_EQ_FREE2(
311           "ccache.conf:1: cache directory levels must be between 1 and 8",
312           errmsg);
313         create_file("ccache.conf", "cache_dir_levels = 9");
314         CHECK(!conf_read(conf, "ccache.conf", &errmsg));
315         CHECK_STR_EQ_FREE2(
316           "ccache.conf:1: cache directory levels must be between 1 and 8",
317           errmsg);
318
319         conf_free(conf);
320 }
321
322 TEST(conf_update_from_environment)
323 {
324         struct conf *conf = conf_create();
325         char *errmsg;
326
327         putenv("CCACHE_COMPRESS=1");
328         CHECK(conf_update_from_environment(conf, &errmsg));
329         CHECK(conf->compression);
330
331         x_unsetenv("CCACHE_COMPRESS");
332         putenv("CCACHE_NOCOMPRESS=1");
333         CHECK(conf_update_from_environment(conf, &errmsg));
334         CHECK(!conf->compression);
335
336         conf_free(conf);
337 }
338
339 TEST(conf_set_new_value)
340 {
341         char *errmsg;
342         char *data;
343
344         create_file("ccache.conf", "path = vanilla\n");
345         CHECKM(conf_set_value_in_file("ccache.conf", "stats", "chocolate", &errmsg),
346                errmsg);
347         data = read_text_file("ccache.conf", 0);
348         CHECK(data);
349         CHECK_STR_EQ_FREE2("path = vanilla\nstats = chocolate\n", data);
350 }
351
352 TEST(conf_set_existing_value)
353 {
354         char *errmsg;
355         char *data;
356
357         create_file("ccache.conf", "path = chocolate\nstats = chocolate\n");
358         CHECKM(conf_set_value_in_file("ccache.conf", "path", "vanilla", &errmsg),
359                errmsg);
360         data = read_text_file("ccache.conf", 0);
361         CHECK(data);
362         CHECK_STR_EQ_FREE2("path = vanilla\nstats = chocolate\n", data);
363 }
364
365 TEST(conf_print_items)
366 {
367         size_t i;
368         struct conf conf = {
369                 "bd",
370                 "cd",
371                 7,
372                 "c",
373                 "cc",
374                 true,
375                 8,
376                 "ce",
377                 false,
378                 true,
379                 "efth",
380                 true,
381                 .hash_dir = false,
382                 "ihim",
383                 true,
384                 0.0,
385                 "lf",
386                 4711,
387                 98.7 * 1000 * 1000,
388                 "p",
389                 "pc",
390                 "pcc",
391                 true,
392                 true,
393                 true,
394                 .run_second_cpp = false,
395                 SLOPPY_FILE_MACRO|SLOPPY_INCLUDE_FILE_MTIME|
396                 SLOPPY_INCLUDE_FILE_CTIME|SLOPPY_TIME_MACROS|
397                 SLOPPY_FILE_STAT_MATCHES|SLOPPY_PCH_DEFINES|
398                 SLOPPY_NO_SYSTEM_HEADERS,
399                 false,
400                 "td",
401                 022,
402                 true,
403                 NULL
404         };
405         size_t n = 0;
406
407         conf.item_origins = x_malloc(N_CONFIG_ITEMS * sizeof(char *));
408         for (i = 0; i < N_CONFIG_ITEMS; ++i) {
409 #ifndef __MINGW32__
410                 conf.item_origins[i] = format("origin%zu", i);
411 #else
412                 conf.item_origins[i] = format("origin%u", (unsigned) i);
413 #endif
414         }
415
416         conf_print_items(&conf, conf_item_receiver, NULL);
417         CHECK_INT_EQ(N_CONFIG_ITEMS, n_received_conf_items);
418         CHECK_STR_EQ("base_dir = bd", received_conf_items[n++].descr);
419         CHECK_STR_EQ("cache_dir = cd", received_conf_items[n++].descr);
420         CHECK_STR_EQ("cache_dir_levels = 7", received_conf_items[n++].descr);
421         CHECK_STR_EQ("compiler = c", received_conf_items[n++].descr);
422         CHECK_STR_EQ("compiler_check = cc", received_conf_items[n++].descr);
423         CHECK_STR_EQ("compression = true", received_conf_items[n++].descr);
424         CHECK_STR_EQ("compression_level = 8", received_conf_items[n++].descr);
425         CHECK_STR_EQ("cpp_extension = ce", received_conf_items[n++].descr);
426         CHECK_STR_EQ("direct_mode = false", received_conf_items[n++].descr);
427         CHECK_STR_EQ("disable = true", received_conf_items[n++].descr);
428         CHECK_STR_EQ("extra_files_to_hash = efth", received_conf_items[n++].descr);
429         CHECK_STR_EQ("hard_link = true", received_conf_items[n++].descr);
430         CHECK_STR_EQ("hash_dir = false", received_conf_items[n++].descr);
431         CHECK_STR_EQ("ignore_headers_in_manifest = ihim",
432                      received_conf_items[n++].descr);
433         CHECK_STR_EQ("keep_comments_cpp = true", received_conf_items[n++].descr);
434         CHECK_STR_EQ("limit_multiple = 0.0", received_conf_items[n++].descr);
435         CHECK_STR_EQ("log_file = lf", received_conf_items[n++].descr);
436         CHECK_STR_EQ("max_files = 4711", received_conf_items[n++].descr);
437         CHECK_STR_EQ("max_size = 98.7M", received_conf_items[n++].descr);
438         CHECK_STR_EQ("path = p", received_conf_items[n++].descr);
439         CHECK_STR_EQ("prefix_command = pc", received_conf_items[n++].descr);
440         CHECK_STR_EQ("prefix_command_cpp = pcc", received_conf_items[n++].descr);
441         CHECK_STR_EQ("read_only = true", received_conf_items[n++].descr);
442         CHECK_STR_EQ("read_only_direct = true", received_conf_items[n++].descr);
443         CHECK_STR_EQ("recache = true", received_conf_items[n++].descr);
444         CHECK_STR_EQ("run_second_cpp = false", received_conf_items[n++].descr);
445         CHECK_STR_EQ("sloppiness = file_macro, include_file_mtime,"
446                      " include_file_ctime, time_macros, pch_defines,"
447                      " file_stat_matches, no_system_headers",
448                      received_conf_items[n++].descr);
449         CHECK_STR_EQ("stats = false", received_conf_items[n++].descr);
450         CHECK_STR_EQ("temporary_dir = td", received_conf_items[n++].descr);
451         CHECK_STR_EQ("umask = 022", received_conf_items[n++].descr);
452         CHECK_STR_EQ("unify = true", received_conf_items[n++].descr);
453
454         for (i = 0; i < N_CONFIG_ITEMS; ++i) {
455 #ifndef __MINGW32__
456                 char *expected = format("origin%zu", i);
457 #else
458                 char *expected = format("origin%u", (unsigned) i);
459 #endif
460                 CHECK_STR_EQ_FREE1(expected, received_conf_items[i].origin);
461         }
462
463         free_received_conf_items();
464         free(conf.item_origins);
465 }
466
467 TEST_SUITE_END