unit-tests: Add unit tests for settings_t.load_string[_section]
[strongswan.git] / src / libstrongswan / tests / suites / test_settings.c
1 /*
2 * Copyright (C) 2014 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "test_suite.h"
17
18 #include <unistd.h>
19
20 #include <settings/settings.h>
21 #include <utils/chunk.h>
22 #include <utils/utils.h>
23 #include <collections/linked_list.h>
24
25 #ifdef WIN32
26 static char *path = "C:\\Windows\\Temp\\strongswan-settings-test";
27 #else
28 static char *path = "/tmp/strongswan-settings-test";
29 #endif
30 static settings_t *settings;
31
32 static void create_settings(chunk_t contents)
33 {
34 ck_assert(chunk_write(contents, path, 0022, TRUE));
35 settings = settings_create(path);
36 }
37
38 START_SETUP(setup_base_config)
39 {
40 create_settings(chunk_from_str(
41 "main {\n"
42 " key1 = val1\n"
43 " # this gets overridden below\n"
44 " key2 = val2\n"
45 " none = \n"
46 " empty = \"\"\n"
47 " sub1 {\n"
48 " key = value\n"
49 " key2 = value2\n"
50 " subsub {\n"
51 " foo = bar\n"
52 " }\n"
53 " # subsub is a section and a value\n"
54 " subsub = section value\n"
55 " }\n"
56 " sub% {\n"
57 " id = %any\n"
58 " }\n"
59 " key2 = with space\n"
60 " key3 = \"string with\\nnewline\"\n"
61 " key4 = \"multi line\n"
62 "string\"\n"
63 " key5 = \"escaped \\\n"
64 "newline\"\n"
65 "}\n"
66 "out = side\n"
67 "other {\n"
68 " key1 = other val\n"
69 " empty {\n"
70 " }\n"
71 "}"));
72 }
73 END_SETUP
74
75 START_TEARDOWN(teardown_config)
76 {
77 settings->destroy(settings);
78 unlink(path);
79 }
80 END_TEARDOWN
81
82 #define verify_string(expected, key, ...) \
83 ck_assert_str_eq(expected, settings->get_str(settings, key, NULL, ##__VA_ARGS__))
84 #define verify_null(key, ...) \
85 ck_assert(!settings->get_str(settings, key, NULL, ##__VA_ARGS__))
86
87 START_TEST(test_get_str)
88 {
89 verify_string("val1", "main.key1");
90 verify_string("val1", "main..key1");
91 verify_string("val1", ".main.key1");
92 verify_string("", "main.empty");
93 verify_string("with space", "main.key2");
94 verify_string("string with\nnewline", "main.key3");
95 verify_string("multi line\nstring", "main.key4");
96 verify_string("escaped newline", "main.key5");
97 verify_string("value", "main.sub1.key");
98 verify_string("value2", "main.sub1.key2");
99 verify_string("bar", "main.sub1.subsub.foo");
100 verify_string("section value", "main.sub1.subsub");
101 verify_string("%any", "main.sub%%.id");
102 verify_string("side", "out");
103 verify_string("other val", "other.key1");
104
105 verify_null("main.none");
106 verify_null("main.key6");
107 verify_null("other.sub");
108 }
109 END_TEST
110
111 enum {
112 KEY1,
113 SUB1
114 } settings_test_enum;
115
116 enum_name_t *test_settings_test_names;
117
118 ENUM_BEGIN(test_settings_test_names, KEY1, SUB1,
119 "key1", "sub1");
120 ENUM_END(test_settings_test_names, SUB1);
121
122 START_TEST(test_get_str_printf)
123 {
124 verify_string("val1", "%s.key1", "main");
125 verify_string("val1", "%s.%s", "main", "key1");
126 verify_string("val1", "%s.%N", "main", test_settings_test_names, KEY1);
127 verify_string("val1", "%s.%s%d", "main", "key", 1);
128 verify_string("bar", "%s.sub1.%s.foo", "main", "subsub");
129 verify_string("bar", "%s.%N.%s.foo", "main", test_settings_test_names, SUB1, "subsub");
130 verify_string("bar", "%s.sub%d.%s.foo", "main", 1, "subsub");
131 verify_string("%any", "%s.sub%%.id", "main");
132
133 /* FIXME: this is a bit inconsistent, while this works */
134 verify_string("value2", "main.%s%u.key2", "sub", 1);
135 /* this won't because no argument is consumed for %u so key1 will be tried
136 * granted, we never actually used any other specifiers, but we should
137 * probably document it at least */
138 verify_null("main.%s%u.key%d", "sub", 1, 2);
139
140 verify_null("%s.%s%d", "main", "key", 6);
141 }
142 END_TEST
143
144 START_TEST(test_set_str)
145 {
146 char *val1, *val2;
147
148 val1 = settings->get_str(settings, "main.key1", NULL);
149 ck_assert_str_eq("val1", val1);
150 settings->set_str(settings, "main.key1", "val");
151 verify_string("val", "main.key1");
152 /* the pointer we got before is still valid */
153 ck_assert_str_eq("val1", val1);
154
155 val2 = settings->get_str(settings, "main.key1", NULL);
156 ck_assert_str_eq("val", val2);
157 settings->set_str(settings, "main.key1", "longer value");
158 verify_string("longer value", "main.key1");
159 /* the pointers we got before are still valid */
160 ck_assert_str_eq("val1", val1);
161 ck_assert_str_eq("val", val2);
162
163 val1 = settings->get_str(settings, "main.key1", NULL);
164 settings->set_str(settings, "main.key1", "longer value");
165 val2 = settings->get_str(settings, "main.key1", NULL);
166 /* setting the same string should should get us the same pointer */
167 ck_assert(val1 == val2);
168
169 settings->set_str(settings, "main", "main val");
170 verify_string("main val", "main");
171 settings->set_str(settings, "main.sub1.new", "added");
172 verify_string("added", "main.sub1.new");
173 settings->set_str(settings, "main.sub2.newsub.foo", "bar");
174 verify_string("bar", "main.sub2.newsub.foo");
175 settings->set_str(settings, "new.newsub.foo", "bar");
176 verify_string("bar", "new.newsub.foo");
177 settings->set_str(settings, "main.key1", NULL);
178 verify_null("main.key1");
179 }
180 END_TEST
181
182 START_TEST(test_set_str_printf)
183 {
184 settings->set_str(settings, "%s.key1", "val", "main");
185 verify_string("val", "main.key1");
186 settings->set_str(settings, "main.%N.new", "added", test_settings_test_names, SUB1);
187 verify_string("added", "main.sub1.new");
188 settings->set_str(settings, "main.%s%d.newsub.%s", "bar", "sub", 2, "foo");
189 verify_string("bar", "main.sub2.newsub.foo");
190 }
191 END_TEST
192
193 START_TEST(test_set_default_str)
194 {
195 settings->set_default_str(settings, "main.key1", "default");
196 verify_string("val1", "main.key1");
197 settings->set_default_str(settings, "main.sub1.new", "added");
198 verify_string("added", "main.sub1.new");
199 settings->set_str(settings, "main.sub1.new", "changed");
200 verify_string("changed", "main.sub1.new");
201 }
202 END_TEST
203
204 START_SETUP(setup_bool_config)
205 {
206 create_settings(chunk_from_str(
207 "main {\n"
208 " key1 = yes\n"
209 " key2 = true\n"
210 " key3 = Enabled\n"
211 " key4 = 1\n"
212 " key5 = no\n"
213 " key6 = FALSE\n"
214 " key7 = disabled\n"
215 " key8 = 0\n"
216 " key9 = 5\n"
217 " empty = \"\"\n"
218 " none = \n"
219 " foo = bar\n"
220 "}"));
221 }
222 END_SETUP
223
224 #define verify_bool(expected, def, key, ...) \
225 ck_assert(expected == settings->get_bool(settings, key, def, ##__VA_ARGS__))
226
227 START_TEST(test_get_bool)
228 {
229 verify_bool(TRUE, FALSE, "main.key1");
230 verify_bool(TRUE, FALSE, "main.key2");
231 verify_bool(TRUE, FALSE, "main.key3");
232 verify_bool(TRUE, FALSE, "main.key4");
233 verify_bool(FALSE, TRUE, "main.key5");
234 verify_bool(FALSE, TRUE, "main.key6");
235 verify_bool(FALSE, TRUE, "main.key7");
236 verify_bool(FALSE, TRUE, "main.key8");
237
238 verify_bool(FALSE, FALSE, "main.empty");
239 verify_bool(TRUE, TRUE, "main.empty");
240 verify_bool(FALSE, FALSE, "main.none");
241 verify_bool(TRUE, TRUE, "main.none");
242 verify_bool(FALSE, FALSE, "main.foo");
243 verify_bool(TRUE, TRUE, "main.foo");
244
245 verify_bool(FALSE, FALSE, "main.key9");
246 verify_bool(TRUE, TRUE, "main.key9");
247 verify_bool(FALSE, FALSE, "main");
248 verify_bool(TRUE, TRUE, "main");
249
250 }
251 END_TEST
252
253 START_TEST(test_set_bool)
254 {
255 settings->set_str(settings, "main.key1", "no");
256 verify_bool(FALSE, TRUE, "main.key1");
257 settings->set_bool(settings, "main.key2", FALSE);
258 verify_bool(FALSE, TRUE, "main.key2");
259 settings->set_str(settings, "main.key3", NULL);
260 verify_bool(FALSE, FALSE, "main.key3");
261 verify_bool(TRUE, TRUE, "main.key3");
262 settings->set_bool(settings, "main.key5", TRUE);
263 verify_bool(TRUE, FALSE, "main.key5");
264 settings->set_bool(settings, "main.new", TRUE);
265 verify_bool(TRUE, FALSE, "main.new");
266 }
267 END_TEST
268
269 START_SETUP(setup_int_config)
270 {
271 create_settings(chunk_from_str(
272 "main {\n"
273 " key1 = 5\n"
274 " key2 = 5.5\n"
275 " key3 = -42\n"
276 " empty = \"\"\n"
277 " none = \n"
278 " foo1 = bar\n"
279 " foo2 = bar13\n"
280 " foo3 = 13bar\n"
281 "}"));
282 }
283 END_SETUP
284
285 #define verify_int(expected, def, key, ...) \
286 ck_assert_int_eq(expected, settings->get_int(settings, key, def, ##__VA_ARGS__))
287
288 START_TEST(test_get_int)
289 {
290 verify_int(5, 0, "main.key1");
291 verify_int(0, 0, "main.key2");
292 verify_int(-42, 0, "main.key3");
293
294 verify_int(11, 11, "main.empty");
295 verify_int(11, 11, "main.none");
296 verify_int(11, 11, "main.foo1");
297 verify_int(11, 11, "main.foo2");
298 verify_int(11, 11, "main.foo3");
299
300 verify_int(13, 13, "main.key4");
301 verify_int(-13, -13, "main");
302 }
303 END_TEST
304
305 START_TEST(test_set_int)
306 {
307 settings->set_str(settings, "main.key1", "13");
308 verify_int(13, 0, "main.key1");
309 settings->set_int(settings, "main.key2", 6);
310 verify_int(6, 0, "main.key2");
311 settings->set_int(settings, "main.key3", -6);
312 verify_int(-6, 0, "main.key3");
313 settings->set_str(settings, "main.key3", NULL);
314 verify_int(15, 15, "main.key3");
315 settings->set_int(settings, "main.new", 314);
316 verify_int(314, 0, "main.new");
317 }
318 END_TEST
319
320 START_SETUP(setup_double_config)
321 {
322 create_settings(chunk_from_str(
323 "main {\n"
324 " key1 = 5\n"
325 " key2 = 5.5\n"
326 " key3 = -42\n"
327 " key4 = -42.5\n"
328 " empty = \"\"\n"
329 " none = \n"
330 " foo1 = bar\n"
331 " foo2 = bar13.5\n"
332 " foo3 = 13.5bar\n"
333 "}"));
334 }
335 END_SETUP
336
337 #define verify_double(expected, def, key, ...) \
338 ck_assert(expected == settings->get_double(settings, key, def, ##__VA_ARGS__))
339
340 START_TEST(test_get_double)
341 {
342 verify_double(5, 0, "main.key1");
343 verify_double(5.5, 0, "main.key2");
344 verify_double(-42, 0, "main.key3");
345 verify_double(-42.5, 0, "main.key4");
346
347 verify_double(11.5, 11.5, "main.empty");
348 verify_double(11.5, 11.5, "main.none");
349 verify_double(11.5, 11.5, "main.foo1");
350 verify_double(11.5, 11.5, "main.foo2");
351 verify_double(11.5, 11.5, "main.foo3");
352
353 verify_double(11.5, 11.5, "main.key5");
354 verify_double(-11.5, -11.5, "main");
355 }
356 END_TEST
357
358 START_TEST(test_set_double)
359 {
360 settings->set_str(settings, "main.key1", "5.5");
361 verify_double(5.5, 0, "main.key1");
362 settings->set_double(settings, "main.key2", 13);
363 verify_double(13, 0, "main.key2");
364 settings->set_double(settings, "main.key3", -13.5);
365 verify_double(-13.5, 0, "main.key3");
366 settings->set_double(settings, "main.key4", 11.5);
367 verify_double(11.5, 0, "main.key4");
368 settings->set_str(settings, "main.key4", NULL);
369 verify_double(42.5, 42.5, "main.key4");
370 settings->set_double(settings, "main.new", 3.14);
371 verify_double(3.14, 0, "main.new");
372 }
373 END_TEST
374
375 START_SETUP(setup_time_config)
376 {
377 create_settings(chunk_from_str(
378 "main {\n"
379 " key0 = 5\n"
380 " key1 = 5s\n"
381 " key2 = 5m\n"
382 " key3 = 5 h\n"
383 " key4 = 5\td\n"
384 " empty = \"\"\n"
385 " none = \n"
386 " foo1 = bar\n"
387 " foo2 = bar13\n"
388 " foo3 = 13bar\n"
389 "}"));
390 }
391 END_SETUP
392
393 #define verify_time(expected, def, key, ...) \
394 ck_assert_int_eq(expected, settings->get_time(settings, key, def, ##__VA_ARGS__))
395
396 START_TEST(test_get_time)
397 {
398 verify_time(5, 0, "main.key0");
399 verify_time(5, 0, "main.key1");
400 verify_time(300, 0, "main.key2");
401 verify_time(18000, 0, "main.key3");
402 verify_time(432000, 0, "main.key4");
403
404 verify_time(11, 11, "main.empty");
405 verify_time(11, 11, "main.none");
406 verify_time(11, 11, "main.foo1");
407 verify_time(11, 11, "main.foo2");
408 verify_time(11, 11, "main.foo3");
409
410 verify_time(11, 11, "main.key5");
411 verify_time(11, 11, "main");
412 }
413 END_TEST
414
415 START_TEST(test_set_time)
416 {
417 settings->set_str(settings, "main.key1", "15m");
418 verify_time(900, 0, "main.key1");
419 settings->set_time(settings, "main.key2", 15);
420 verify_time(15, 0, "main.key2");
421 settings->set_str(settings, "main.key3", NULL);
422 verify_time(300, 300, "main.key3");
423 settings->set_time(settings, "main.new", 314);
424 verify_time(314, 0, "main.new");
425 }
426 END_TEST
427
428 static void verify_sections(linked_list_t *verifier, char *parent)
429 {
430 enumerator_t *enumerator, *ver;
431 char *section, *current;
432
433 enumerator = settings->create_section_enumerator(settings, parent);
434 ver = verifier->create_enumerator(verifier);
435 while (enumerator->enumerate(enumerator, &section) &&
436 ver->enumerate(ver, &current))
437 {
438 ck_assert_str_eq(section, current);
439 verifier->remove_at(verifier, ver);
440 }
441 enumerator->destroy(enumerator);
442 ver->destroy(ver);
443 ck_assert_int_eq(0, verifier->get_count(verifier));
444 verifier->destroy(verifier);
445 }
446
447 START_TEST(test_section_enumerator)
448 {
449 linked_list_t *verifier;
450
451 verifier = linked_list_create_with_items("sub1", "sub%", NULL);
452 verify_sections(verifier, "main");
453
454 settings->set_str(settings, "main.sub0.new", "added");
455 verifier = linked_list_create_with_items("sub1", "sub%", "sub0", NULL);
456 verify_sections(verifier, "main");
457
458 verifier = linked_list_create_with_items("subsub", NULL);
459 verify_sections(verifier, "main.sub1");
460
461 verifier = linked_list_create_with_items(NULL);
462 verify_sections(verifier, "main.sub%%");
463
464 verifier = linked_list_create_with_items(NULL);
465 verify_sections(verifier, "main.key1");
466
467 verifier = linked_list_create_with_items(NULL);
468 verify_sections(verifier, "main.unknown");
469 }
470 END_TEST
471
472 static void verify_key_values(linked_list_t *keys, linked_list_t *values,
473 char *parent)
474 {
475 enumerator_t *enumerator, *enum_keys, *enum_values;
476 char *key, *value, *current_key, *current_value;
477
478 enumerator = settings->create_key_value_enumerator(settings, parent);
479 enum_keys = keys->create_enumerator(keys);
480 enum_values = values->create_enumerator(values);
481 while (enumerator->enumerate(enumerator, &key, &value) &&
482 enum_keys->enumerate(enum_keys, &current_key) &&
483 enum_values->enumerate(enum_values, &current_value))
484 {
485 ck_assert_str_eq(current_key, key);
486 ck_assert_str_eq(current_value, value);
487 keys->remove_at(keys, enum_keys);
488 values->remove_at(values, enum_values);
489 }
490 enumerator->destroy(enumerator);
491 enum_keys->destroy(enum_keys);
492 enum_values->destroy(enum_values);
493 ck_assert_int_eq(0, keys->get_count(keys));
494 keys->destroy(keys);
495 values->destroy(values);
496 }
497
498 START_TEST(test_key_value_enumerator)
499 {
500 linked_list_t *keys, *values;
501
502 keys = linked_list_create_with_items("key1", "key2", "empty", "key3", NULL);
503 values = linked_list_create_with_items("val1", "with space", "", "string with\nnewline", NULL);
504 verify_key_values(keys, values, "main");
505
506 keys = linked_list_create_with_items("key", "key2", "subsub", NULL);
507 values = linked_list_create_with_items("value", "value2", "section value", NULL);
508 verify_key_values(keys, values, "main.sub1");
509
510 settings->set_str(settings, "main.sub2.new", "added");
511 keys = linked_list_create_with_items("new", NULL);
512 values = linked_list_create_with_items("added", NULL);
513 verify_key_values(keys, values, "main.sub2");
514
515 keys = linked_list_create_with_items(NULL);
516 values = linked_list_create_with_items(NULL);
517 verify_key_values(keys, values, "other.empty");
518
519 settings->set_str(settings, "other.empty.new", "added");
520 keys = linked_list_create_with_items("new", NULL);
521 values = linked_list_create_with_items("added", NULL);
522 verify_key_values(keys, values, "other.empty");
523
524 keys = linked_list_create_with_items(NULL);
525 values = linked_list_create_with_items(NULL);
526 verify_key_values(keys, values, "main.unknown");
527 }
528 END_TEST
529
530 #ifdef WIN32
531 # define include1 "C:\\Windows\\Temp\\strongswan-settings-test-include1"
532 # define include2 "C:\\Windows\\Temp\\strongswan-settings-test-include2"
533 #else
534 # define include1 "/tmp/strongswan-settings-test-include1"
535 # define include2 "/tmp/strongswan-settings-test-include2"
536 #endif
537
538 static char *include_content1 =
539 "main {\n"
540 " key1 = n1\n"
541 " key2 = n2\n"
542 " key3 = val3\n"
543 " none = \n"
544 " sub1 {\n"
545 " key3 = value\n"
546 " }\n"
547 " sub2 {\n"
548 " sub3 = val3\n"
549 " }\n"
550 " include " include2 "\n"
551 "}";
552 static char *include_content2 =
553 "key2 = v2\n"
554 "sub1 {\n"
555 " key = val\n"
556 "}";
557
558 START_SETUP(setup_include_config)
559 {
560 ck_assert(chunk_write(chunk_from_str(include_content1), include1, 0022, TRUE));
561 ck_assert(chunk_write(chunk_from_str(include_content2), include2, 0022, TRUE));
562 }
563 END_SETUP
564
565 START_TEARDOWN(teardown_include_config)
566 {
567 settings->destroy(settings);
568 unlink(include2);
569 unlink(include1);
570 unlink(path);
571 }
572 END_TEARDOWN
573
574 static void verify_include()
575 {
576 verify_string("n1", "main.key1");
577 verify_string("v2", "main.key2");
578 verify_string("val3", "main.key3");
579 verify_string("val", "main.sub1.key");
580 verify_string("v2", "main.sub1.key2");
581 verify_string("val", "main.sub1.sub1.key");
582 verify_string("value", "main.sub1.key3");
583 verify_string("value", "main.sub1.include");
584 verify_string("val3", "main.sub2.sub3");
585
586 verify_null("main.none");
587 }
588
589 START_TEST(test_include)
590 {
591 chunk_t contents = chunk_from_str(
592 "main {\n"
593 " key1 = val1\n"
594 " key2 = val2\n"
595 " none = x\n"
596 " sub1 {\n"
597 " include this/does/not/exist.conf\n"
598 " include = value\n"
599 " key2 = value2\n"
600 " include " include2 "\n"
601 " }\n"
602 "}\n"
603 "include " include1);
604
605 create_settings(contents);
606 verify_include();
607 }
608 END_TEST
609
610 START_TEST(test_load_files)
611 {
612 chunk_t contents = chunk_from_str(
613 "main {\n"
614 " key1 = val1\n"
615 " key2 = val2\n"
616 " key3 = val3\n"
617 " none = x\n"
618 " sub1 {\n"
619 " include = value\n"
620 " key2 = v2\n"
621 " sub1 {\n"
622 " key = val\n"
623 " }\n"
624 " }\n"
625 "}");
626 char *val1, *val2, *val3;
627
628 create_settings(contents);
629
630 val1 = settings->get_str(settings, "main.key1", NULL);
631 val2 = settings->get_str(settings, "main.sub1.key2", NULL);
632 /* loading the same file twice should not change anything, with... */
633 ck_assert(settings->load_files(settings, path, TRUE));
634 ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
635 ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
636 /* ...or without merging */
637 ck_assert(settings->load_files(settings, path, FALSE));
638 ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
639 ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
640
641 val1 = settings->get_str(settings, "main.key2", NULL);
642 val2 = settings->get_str(settings, "main.key3", NULL);
643 val3 = settings->get_str(settings, "main.none", NULL);
644 /* only pointers for modified settings should change, but still be valid */
645 ck_assert(settings->load_files(settings, include1, FALSE));
646 ck_assert(val1 != settings->get_str(settings, "main.key2", NULL));
647 ck_assert_str_eq(val1, "val2");
648 ck_assert(val2 == settings->get_str(settings, "main.key3", NULL));
649 ck_assert(val3 != settings->get_str(settings, "main.none", NULL));
650 ck_assert_str_eq(val3, "x");
651
652 settings->destroy(settings);
653 create_settings(contents);
654
655 ck_assert(settings->load_files(settings, include1, TRUE));
656 verify_include();
657
658 ck_assert(settings->load_files(settings, include2, FALSE));
659 verify_null("main.key1");
660 verify_string("v2", "key2");
661 verify_string("val", "sub1.key");
662 verify_null("main.sub1.key3");
663 }
664 END_TEST
665
666 START_TEST(test_load_files_section)
667 {
668 chunk_t contents = chunk_from_str(
669 "main {\n"
670 " key1 = val1\n"
671 " key2 = val2\n"
672 " none = x\n"
673 " sub1 {\n"
674 " include = value\n"
675 " key2 = value2\n"
676 " }\n"
677 "}");
678
679 create_settings(contents);
680
681 ck_assert(settings->load_files_section(settings, include1, TRUE, ""));
682 ck_assert(settings->load_files_section(settings, include2, TRUE, "main.sub1"));
683 verify_include();
684
685 /* non existing files are a failure here */
686 ck_assert(!settings->load_files_section(settings, include1".conf", TRUE, ""));
687 verify_include();
688
689 #ifndef WIN32
690 /* unreadable files are too (only fails when not running as root) */
691 if (getuid() != 0)
692 {
693 ck_assert(chunk_write(contents, include1".no", 0444, TRUE));
694 ck_assert(!settings->load_files_section(settings, include1".no", TRUE, ""));
695 unlink(include1".no");
696 verify_include();
697 }
698 #endif
699
700 ck_assert(settings->load_files_section(settings, include2, FALSE, "main"));
701 verify_null("main.key1");
702 verify_string("v2", "main.key2");
703 verify_string("val", "main.sub1.key");
704 verify_null("main.sub1.key3");
705 verify_null("main.sub2.sub3");
706
707 ck_assert(settings->load_files_section(settings, include2, TRUE, "main.sub2"));
708 verify_string("v2", "main.sub2.key2");
709 verify_string("val", "main.sub2.sub1.key");
710 }
711 END_TEST
712
713 START_TEST(test_order_kv)
714 {
715 chunk_t base = chunk_from_str(
716 "main {\n"
717 " key1 = val1\n"
718 " key2 = val2\n"
719 " key3 = val3\n"
720 "}");
721 chunk_t include = chunk_from_str(
722 "main {\n"
723 " key0 = val0\n"
724 " key3 = val3\n"
725 " key1 = val1\n"
726 "}");
727 linked_list_t *keys, *values;
728
729 create_settings(base);
730 ck_assert(chunk_write(include, include1, 0022, TRUE));
731
732 keys = linked_list_create_with_items("key1", "key2", "key3", NULL);
733 values = linked_list_create_with_items("val1", "val2", "val3", NULL);
734 verify_key_values(keys, values, "main");
735
736 /* the original order is maintained if the settings are merged */
737 ck_assert(settings->load_files(settings, include1, TRUE));
738 keys = linked_list_create_with_items("key1", "key2", "key3", "key0", NULL);
739 values = linked_list_create_with_items("val1", "val2", "val3", "val0", NULL);
740 verify_key_values(keys, values, "main");
741
742 /* but the new order is adopted if the settings are replaced */
743 ck_assert(settings->load_files(settings, include1, FALSE));
744 keys = linked_list_create_with_items("key0", "key3", "key1", NULL);
745 values = linked_list_create_with_items("val0", "val3", "val1", NULL);
746 verify_key_values(keys, values, "main");
747
748 unlink(include1);
749 }
750 END_TEST
751
752 START_TEST(test_order_section)
753 {
754 chunk_t base = chunk_from_str(
755 "main {\n"
756 " sub1 {\n"
757 " }\n"
758 " sub2 {\n"
759 " }\n"
760 " sub3 {\n"
761 " }\n"
762 "}");
763 chunk_t include = chunk_from_str(
764 "main {\n"
765 " sub0 {\n"
766 " }\n"
767 " sub3 {\n"
768 " }\n"
769 " sub1 {\n"
770 " }\n"
771 "}");
772 linked_list_t *sections;
773
774 create_settings(base);
775 ck_assert(chunk_write(include, include1, 0022, TRUE));
776
777 sections = linked_list_create_with_items("sub1", "sub2", "sub3", NULL);
778 verify_sections(sections, "main");
779
780 /* the original order is maintained if the settings are merged */
781 ck_assert(settings->load_files(settings, include1, TRUE));
782 sections = linked_list_create_with_items("sub1", "sub2", "sub3", "sub0", NULL);
783 verify_sections(sections, "main");
784
785 /* but the new order is adopted if the settings are replaced */
786 ck_assert(settings->load_files(settings, include1, FALSE));
787 sections = linked_list_create_with_items("sub0", "sub3", "sub1", NULL);
788 verify_sections(sections, "main");
789
790 unlink(include1);
791 }
792 END_TEST
793
794
795 START_TEST(test_load_string)
796 {
797 char *content =
798 "main {\n"
799 " key1 = val1\n"
800 " key2 = val2\n"
801 " key3 = val3\n"
802 " none = x\n"
803 " sub1 {\n"
804 " include = value\n"
805 " key2 = v2\n"
806 " sub1 {\n"
807 " key = val\n"
808 " }\n"
809 " }\n"
810 "}";
811 char *val1, *val2, *val3;
812
813 settings = settings_create_string(content);
814
815 val1 = settings->get_str(settings, "main.key1", NULL);
816 val2 = settings->get_str(settings, "main.sub1.key2", NULL);
817 /* loading the same content twice should not change anything, with... */
818 ck_assert(settings->load_string(settings, content, TRUE));
819 ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
820 ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
821 /* ...or without merging */
822 ck_assert(settings->load_string(settings, content, FALSE));
823 ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
824 ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
825
826 val1 = settings->get_str(settings, "main.key2", NULL);
827 val2 = settings->get_str(settings, "main.key3", NULL);
828 val3 = settings->get_str(settings, "main.none", NULL);
829 /* only pointers for modified settings should change, but still be valid */
830 ck_assert(settings->load_string(settings, include_content1, FALSE));
831 ck_assert(val1 != settings->get_str(settings, "main.key2", NULL));
832 ck_assert_str_eq(val1, "val2");
833 ck_assert(val2 == settings->get_str(settings, "main.key3", NULL));
834 ck_assert(val3 != settings->get_str(settings, "main.none", NULL));
835 ck_assert_str_eq(val3, "x");
836
837 settings->destroy(settings);
838 settings = settings_create_string(content);
839 ck_assert(settings);
840
841 ck_assert(settings->load_string(settings, include_content1, TRUE));
842 verify_include();
843
844 ck_assert(settings->load_string(settings, include_content2, FALSE));
845 verify_null("main.key1");
846 verify_string("v2", "key2");
847 verify_string("val", "sub1.key");
848 verify_null("main.sub1.key3");
849 }
850 END_TEST
851
852
853 START_TEST(test_load_string_section)
854 {
855 char *content =
856 "main {\n"
857 " key1 = val1\n"
858 " key2 = val2\n"
859 " none = x\n"
860 " sub1 {\n"
861 " include = value\n"
862 " key2 = value2\n"
863 " }\n"
864 "}";
865
866 settings = settings_create_string(content);
867
868 ck_assert(settings->load_string_section(settings, include_content1, TRUE, ""));
869 ck_assert(settings->load_string_section(settings, include_content2, TRUE, "main.sub1"));
870 verify_include();
871
872 /* invalid strings are a failure */
873 ck_assert(!settings->load_string_section(settings, "conf {", TRUE, ""));
874 /* NULL or empty strings are OK though */
875 ck_assert(settings->load_string_section(settings, "", TRUE, ""));
876 ck_assert(settings->load_string_section(settings, NULL, TRUE, ""));
877 verify_include();
878
879 ck_assert(settings->load_string_section(settings, include_content2, FALSE, "main"));
880 verify_null("main.key1");
881 verify_string("v2", "main.key2");
882 verify_string("val", "main.sub1.key");
883 verify_null("main.sub1.key3");
884 verify_null("main.sub2.sub3");
885
886 ck_assert(settings->load_string_section(settings, include_content2, TRUE, "main.sub2"));
887 verify_string("v2", "main.sub2.key2");
888 verify_string("val", "main.sub2.sub1.key");
889 }
890 END_TEST
891
892 START_SETUP(setup_fallback_config)
893 {
894 create_settings(chunk_from_str(
895 "main {\n"
896 " key1 = val1\n"
897 " sub1 {\n"
898 " key1 = val1\n"
899 " }\n"
900 "}\n"
901 "sub {\n"
902 " key1 = subval1\n"
903 " key2 = subval2\n"
904 " subsub {\n"
905 " subkey1 = subsubval1\n"
906 " }\n"
907 "}\n"
908 "base {\n"
909 " key1 = baseval1\n"
910 " key2 = baseval2\n"
911 " sub1 {\n"
912 " key1 = subbase1\n"
913 " key2 = subbase2\n"
914 " key3 = subbase3\n"
915 " subsub {\n"
916 " subkey1 = subsubbaseval1\n"
917 " subkey2 = subsubbaseval2\n"
918 " }\n"
919 " }\n"
920 " sub2 {\n"
921 " key4 = subbase4\n"
922 " }\n"
923 "}"));
924 }
925 END_SETUP
926
927 START_TEST(test_add_fallback)
928 {
929 linked_list_t *keys, *values;
930
931 settings->add_fallback(settings, "main.sub1", "sub");
932 verify_string("val1", "main.sub1.key1");
933 verify_string("subval2", "main.sub1.key2");
934 verify_string("subsubval1", "main.sub1.subsub.subkey1");
935
936 /* fallbacks are preserved even if the complete config is replaced */
937 settings->load_files(settings, path, FALSE);
938 verify_string("val1", "main.sub1.key1");
939 verify_string("subval2", "main.sub1.key2");
940 verify_string("subsubval1", "main.sub1.subsub.subkey1");
941
942 keys = linked_list_create_with_items("sub1", NULL);
943 verify_sections(keys, "main");
944 keys = linked_list_create_with_items("subsub", NULL);
945 verify_sections(keys, "main.sub1");
946
947 keys = linked_list_create_with_items("key1", NULL);
948 values = linked_list_create_with_items("val1", NULL);
949 verify_key_values(keys, values, "main");
950
951 keys = linked_list_create_with_items("key1", "key2", NULL);
952 values = linked_list_create_with_items("val1", "subval2", NULL);
953 verify_key_values(keys, values, "main.sub1");
954
955 keys = linked_list_create_with_items("subkey1", NULL);
956 values = linked_list_create_with_items("subsubval1", NULL);
957 verify_key_values(keys, values, "main.sub1.subsub");
958
959 settings->add_fallback(settings, "main", "base");
960 verify_string("val1", "main.key1");
961 verify_string("baseval2", "main.key2");
962 verify_string("val1", "main.sub1.key1");
963 verify_string("subval2", "main.sub1.key2");
964 verify_string("subsubval1", "main.sub1.subsub.subkey1");
965 verify_string("subsubbaseval2", "main.sub1.subsub.subkey2");
966 verify_string("subbase3", "main.sub1.key3");
967 verify_string("subbase4", "main.sub2.key4");
968
969
970 keys = linked_list_create_with_items("sub1", "sub2", NULL);
971 verify_sections(keys, "main");
972 keys = linked_list_create_with_items("subsub", NULL);
973 verify_sections(keys, "main.sub1");
974
975 keys = linked_list_create_with_items("key1", "key2", NULL);
976 values = linked_list_create_with_items("val1", "baseval2", NULL);
977 verify_key_values(keys, values, "main");
978
979 keys = linked_list_create_with_items("key1", "key2", "key3", NULL);
980 values = linked_list_create_with_items("val1", "subval2", "subbase3", NULL);
981 verify_key_values(keys, values, "main.sub1");
982
983 keys = linked_list_create_with_items("subkey1", "subkey2", NULL);
984 values = linked_list_create_with_items("subsubval1", "subsubbaseval2", NULL);
985 verify_key_values(keys, values, "main.sub1.subsub");
986
987 settings->set_str(settings, "main.sub1.key2", "val2");
988 verify_string("val2", "main.sub1.key2");
989 settings->set_str(settings, "main.sub1.subsub.subkey2", "val2");
990 verify_string("val2", "main.sub1.subsub.subkey2");
991 verify_string("subsubval1", "main.sub1.subsub.subkey1");
992 }
993 END_TEST
994
995 START_TEST(test_add_fallback_printf)
996 {
997 settings->add_fallback(settings, "%s.sub1", "sub", "main");
998 verify_string("val1", "main.sub1.key1");
999 verify_string("subval2", "main.sub1.key2");
1000 verify_string("subsubval1", "main.sub1.subsub.subkey1");
1001
1002 settings->add_fallback(settings, "%s.%s2", "%s.%s1", "main", "sub");
1003 verify_string("val1", "main.sub2.key1");
1004 verify_string("subval2", "main.sub2.key2");
1005 verify_string("subsubval1", "main.sub2.subsub.subkey1");
1006 }
1007 END_TEST
1008
1009 START_SETUP(setup_string_config)
1010 {
1011 create_settings(chunk_from_str(
1012 "string = \" with accurate\twhitespace\"\n"
1013 "special = \"all { special } characters # can be used.\"\n"
1014 "newlines = \"can be encoded explicitly\\nor implicitly\n"
1015 "or \\\n"
1016 "escaped\"\n"
1017 "quotes = \"\\\"and\\\" slashes \\\\ can \\\\ be\" # escaped too\n"
1018 "multiple = \"strings\" are \"combined\"\n"
1019 ));
1020 }
1021 END_SETUP
1022
1023 START_TEST(test_strings)
1024 {
1025 verify_string(" with accurate\twhitespace", "string");
1026 verify_string("all { special } characters # can be used.", "special");
1027 verify_string("can be encoded explicitly\nor implicitly\nor escaped", "newlines");
1028 verify_string("\"and\" slashes \\ can \\ be", "quotes");
1029 verify_string("strings are combined", "multiple");
1030 }
1031 END_TEST
1032
1033 START_TEST(test_valid)
1034 {
1035 chunk_t contents;
1036
1037 contents = chunk_from_str(
1038 "single = value");
1039 ck_assert(chunk_write(contents, path, 0022, TRUE));
1040 ck_assert(settings->load_files(settings, path, FALSE));
1041 verify_string("value", "single");
1042
1043 contents = chunk_from_str(
1044 "singleline { single = value }");
1045 ck_assert(chunk_write(contents, path, 0022, TRUE));
1046 ck_assert(settings->load_files(settings, path, FALSE));
1047 verify_string("value", "singleline.single");
1048
1049 contents = chunk_from_str(
1050 "singleline { sub { sub1 = val1 } single = value }");
1051 ck_assert(chunk_write(contents, path, 0022, TRUE));
1052 ck_assert(settings->load_files(settings, path, FALSE));
1053 verify_string("val1", "singleline.sub.sub1");
1054
1055 contents = chunk_from_str(
1056 "newline\n { single = value }");
1057 ck_assert(chunk_write(contents, path, 0022, TRUE));
1058 ck_assert(settings->load_files(settings, path, FALSE));
1059 verify_string("value", "newline.single");
1060
1061 contents = chunk_from_str(
1062 "section {\n"
1063 " include # without pattern produces a warning, but is fine\n"
1064 "}\n");
1065 ck_assert(chunk_write(contents, path, 0022, TRUE));
1066 ck_assert(settings->load_files(settings, path, FALSE));
1067 }
1068 END_TEST
1069
1070 START_TEST(test_invalid)
1071 {
1072 chunk_t contents;
1073
1074 contents = chunk_from_str(
1075 "{\n"
1076 " no = section name\n"
1077 "}\n");
1078 ck_assert(chunk_write(contents, path, 0022, TRUE));
1079 ck_assert(!settings->load_files(settings, path, FALSE));
1080
1081 contents = chunk_from_str(
1082 "no {\n"
1083 " = key name\n"
1084 "}\n");
1085 ck_assert(chunk_write(contents, path, 0022, TRUE));
1086 ck_assert(!settings->load_files(settings, path, FALSE));
1087
1088 contents = chunk_from_str(
1089 "unterminated {\n"
1090 " not = valid\n");
1091 ck_assert(chunk_write(contents, path, 0022, TRUE));
1092 ck_assert(!settings->load_files(settings, path, FALSE));
1093
1094 contents = chunk_from_str(
1095 "unterminated {\n"
1096 " strings = \"are invalid\n");
1097 ck_assert(chunk_write(contents, path, 0022, TRUE));
1098 ck_assert(!settings->load_files(settings, path, FALSE));
1099
1100 contents = chunk_from_str(
1101 "spaces in name {}");
1102 ck_assert(chunk_write(contents, path, 0022, TRUE));
1103 ck_assert(!settings->load_files(settings, path, FALSE));
1104
1105 contents = chunk_from_str(
1106 "only = a single setting = per line");
1107 ck_assert(chunk_write(contents, path, 0022, TRUE));
1108 ck_assert(!settings->load_files(settings, path, FALSE));
1109 }
1110 END_TEST
1111
1112 Suite *settings_suite_create()
1113 {
1114 Suite *s;
1115 TCase *tc;
1116
1117 s = suite_create("settings");
1118
1119 tc = tcase_create("get/set_str (basic behavior)");
1120 tcase_add_checked_fixture(tc, setup_base_config, teardown_config);
1121 tcase_add_test(tc, test_get_str);
1122 tcase_add_test(tc, test_get_str_printf);
1123 tcase_add_test(tc, test_set_str);
1124 tcase_add_test(tc, test_set_str_printf);
1125 tcase_add_test(tc, test_set_default_str);
1126 suite_add_tcase(s, tc);
1127
1128 tc = tcase_create("get/set_bool");
1129 tcase_add_checked_fixture(tc, setup_bool_config, teardown_config);
1130 tcase_add_test(tc, test_get_bool);
1131 tcase_add_test(tc, test_set_bool);
1132 suite_add_tcase(s, tc);
1133
1134 tc = tcase_create("get/set_int");
1135 tcase_add_checked_fixture(tc, setup_int_config, teardown_config);
1136 tcase_add_test(tc, test_get_int);
1137 tcase_add_test(tc, test_set_int);
1138 suite_add_tcase(s, tc);
1139
1140 tc = tcase_create("get/set_double");
1141 tcase_add_checked_fixture(tc, setup_double_config, teardown_config);
1142 tcase_add_test(tc, test_get_double);
1143 tcase_add_test(tc, test_set_double);
1144 suite_add_tcase(s, tc);
1145
1146 tc = tcase_create("get/set_time");
1147 tcase_add_checked_fixture(tc, setup_time_config, teardown_config);
1148 tcase_add_test(tc, test_get_time);
1149 tcase_add_test(tc, test_set_time);
1150 suite_add_tcase(s, tc);
1151
1152 tc = tcase_create("section enumerator");
1153 tcase_add_checked_fixture(tc, setup_base_config, teardown_config);
1154 tcase_add_test(tc, test_section_enumerator);
1155 suite_add_tcase(s, tc);
1156
1157 tc = tcase_create("key/value enumerator");
1158 tcase_add_checked_fixture(tc, setup_base_config, teardown_config);
1159 tcase_add_test(tc, test_key_value_enumerator);
1160 suite_add_tcase(s, tc);
1161
1162 tc = tcase_create("include/load_files[_section]");
1163 tcase_add_checked_fixture(tc, setup_include_config, teardown_include_config);
1164 tcase_add_test(tc, test_include);
1165 tcase_add_test(tc, test_load_files);
1166 tcase_add_test(tc, test_load_files_section);
1167 tcase_add_test(tc, test_order_kv);
1168 tcase_add_test(tc, test_order_section);
1169 suite_add_tcase(s, tc);
1170
1171 tc = tcase_create("load_string[_section]");
1172 tcase_add_checked_fixture(tc, setup_include_config, teardown_config);
1173 tcase_add_test(tc, test_load_string);
1174 tcase_add_test(tc, test_load_string_section);
1175 suite_add_tcase(s, tc);
1176
1177 tc = tcase_create("fallback");
1178 tcase_add_checked_fixture(tc, setup_fallback_config, teardown_config);
1179 tcase_add_test(tc, test_add_fallback);
1180 tcase_add_test(tc, test_add_fallback_printf);
1181 suite_add_tcase(s, tc);
1182
1183 tc = tcase_create("strings");
1184 tcase_add_checked_fixture(tc, setup_string_config, teardown_config);
1185 tcase_add_test(tc, test_strings);
1186 suite_add_tcase(s, tc);
1187
1188 tc = tcase_create("valid/invalid data");
1189 tcase_add_checked_fixture(tc, setup_base_config, teardown_config);
1190 tcase_add_test(tc, test_valid);
1191 tcase_add_test(tc, test_invalid);
1192 suite_add_tcase(s, tc);
1193
1194 return s;
1195 }