bead9d795cae1db715b72bae17c421237f80f9ce
[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_include_string)
611 {
612 chunk_t contents = chunk_from_str(
613 "main {\n"
614 " key1 = val1\n"
615 " key2 = val2\n"
616 " none = x\n"
617 " sub1 {\n"
618 " include this/does/not/exist.conf\n"
619 " include = value\n"
620 " key2 = value2\n"
621 " include \"" include2 "\"\n"
622 " }\n"
623 "}\n"
624 "include \"" include1 "\"");
625
626 create_settings(contents);
627 verify_include();
628 }
629 END_TEST
630
631 START_TEST(test_load_files)
632 {
633 chunk_t contents = chunk_from_str(
634 "main {\n"
635 " key1 = val1\n"
636 " key2 = val2\n"
637 " key3 = val3\n"
638 " none = x\n"
639 " sub1 {\n"
640 " include = value\n"
641 " key2 = v2\n"
642 " sub1 {\n"
643 " key = val\n"
644 " }\n"
645 " }\n"
646 "}");
647 char *val1, *val2, *val3;
648
649 create_settings(contents);
650
651 val1 = settings->get_str(settings, "main.key1", NULL);
652 val2 = settings->get_str(settings, "main.sub1.key2", NULL);
653 /* loading the same file twice should not change anything, with... */
654 ck_assert(settings->load_files(settings, path, TRUE));
655 ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
656 ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
657 /* ...or without merging */
658 ck_assert(settings->load_files(settings, path, FALSE));
659 ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
660 ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
661
662 val1 = settings->get_str(settings, "main.key2", NULL);
663 val2 = settings->get_str(settings, "main.key3", NULL);
664 val3 = settings->get_str(settings, "main.none", NULL);
665 /* only pointers for modified settings should change, but still be valid */
666 ck_assert(settings->load_files(settings, include1, FALSE));
667 ck_assert(val1 != settings->get_str(settings, "main.key2", NULL));
668 ck_assert_str_eq(val1, "val2");
669 ck_assert(val2 == settings->get_str(settings, "main.key3", NULL));
670 ck_assert(val3 != settings->get_str(settings, "main.none", NULL));
671 ck_assert_str_eq(val3, "x");
672
673 settings->destroy(settings);
674 create_settings(contents);
675
676 ck_assert(settings->load_files(settings, include1, TRUE));
677 verify_include();
678
679 ck_assert(settings->load_files(settings, include2, FALSE));
680 verify_null("main.key1");
681 verify_string("v2", "key2");
682 verify_string("val", "sub1.key");
683 verify_null("main.sub1.key3");
684 }
685 END_TEST
686
687 START_TEST(test_load_files_section)
688 {
689 chunk_t contents = chunk_from_str(
690 "main {\n"
691 " key1 = val1\n"
692 " key2 = val2\n"
693 " none = x\n"
694 " sub1 {\n"
695 " include = value\n"
696 " key2 = value2\n"
697 " }\n"
698 "}");
699
700 create_settings(contents);
701
702 ck_assert(settings->load_files_section(settings, include1, TRUE, ""));
703 ck_assert(settings->load_files_section(settings, include2, TRUE, "main.sub1"));
704 verify_include();
705
706 /* non existing files are a failure here */
707 ck_assert(!settings->load_files_section(settings, include1".conf", TRUE, ""));
708 verify_include();
709
710 #ifndef WIN32
711 /* unreadable files are too (only fails when not running as root) */
712 if (getuid() != 0)
713 {
714 ck_assert(chunk_write(contents, include1".no", 0444, TRUE));
715 ck_assert(!settings->load_files_section(settings, include1".no", TRUE, ""));
716 unlink(include1".no");
717 verify_include();
718 }
719 #endif
720
721 ck_assert(settings->load_files_section(settings, include2, FALSE, "main"));
722 verify_null("main.key1");
723 verify_string("v2", "main.key2");
724 verify_string("val", "main.sub1.key");
725 verify_null("main.sub1.key3");
726 verify_null("main.sub2.sub3");
727
728 ck_assert(settings->load_files_section(settings, include2, TRUE, "main.sub2"));
729 verify_string("v2", "main.sub2.key2");
730 verify_string("val", "main.sub2.sub1.key");
731 }
732 END_TEST
733
734 START_TEST(test_order_kv)
735 {
736 chunk_t base = chunk_from_str(
737 "main {\n"
738 " key1 = val1\n"
739 " key2 = val2\n"
740 " key3 = val3\n"
741 "}");
742 chunk_t include = chunk_from_str(
743 "main {\n"
744 " key0 = val0\n"
745 " key3 = val3\n"
746 " key1 = val1\n"
747 "}");
748 linked_list_t *keys, *values;
749
750 create_settings(base);
751 ck_assert(chunk_write(include, include1, 0022, TRUE));
752
753 keys = linked_list_create_with_items("key1", "key2", "key3", NULL);
754 values = linked_list_create_with_items("val1", "val2", "val3", NULL);
755 verify_key_values(keys, values, "main");
756
757 /* the original order is maintained if the settings are merged */
758 ck_assert(settings->load_files(settings, include1, TRUE));
759 keys = linked_list_create_with_items("key1", "key2", "key3", "key0", NULL);
760 values = linked_list_create_with_items("val1", "val2", "val3", "val0", NULL);
761 verify_key_values(keys, values, "main");
762
763 /* but the new order is adopted if the settings are replaced */
764 ck_assert(settings->load_files(settings, include1, FALSE));
765 keys = linked_list_create_with_items("key0", "key3", "key1", NULL);
766 values = linked_list_create_with_items("val0", "val3", "val1", NULL);
767 verify_key_values(keys, values, "main");
768
769 unlink(include1);
770 }
771 END_TEST
772
773 START_TEST(test_order_section)
774 {
775 chunk_t base = chunk_from_str(
776 "main {\n"
777 " sub1 {\n"
778 " }\n"
779 " sub2 {\n"
780 " }\n"
781 " sub3 {\n"
782 " }\n"
783 "}");
784 chunk_t include = chunk_from_str(
785 "main {\n"
786 " sub0 {\n"
787 " }\n"
788 " sub3 {\n"
789 " }\n"
790 " sub1 {\n"
791 " }\n"
792 "}");
793 linked_list_t *sections;
794
795 create_settings(base);
796 ck_assert(chunk_write(include, include1, 0022, TRUE));
797
798 sections = linked_list_create_with_items("sub1", "sub2", "sub3", NULL);
799 verify_sections(sections, "main");
800
801 /* the original order is maintained if the settings are merged */
802 ck_assert(settings->load_files(settings, include1, TRUE));
803 sections = linked_list_create_with_items("sub1", "sub2", "sub3", "sub0", NULL);
804 verify_sections(sections, "main");
805
806 /* but the new order is adopted if the settings are replaced */
807 ck_assert(settings->load_files(settings, include1, FALSE));
808 sections = linked_list_create_with_items("sub0", "sub3", "sub1", NULL);
809 verify_sections(sections, "main");
810
811 unlink(include1);
812 }
813 END_TEST
814
815
816 START_TEST(test_load_string)
817 {
818 char *content =
819 "main {\n"
820 " key1 = val1\n"
821 " key2 = val2\n"
822 " key3 = val3\n"
823 " none = x\n"
824 " sub1 {\n"
825 " include = value\n"
826 " key2 = v2\n"
827 " sub1 {\n"
828 " key = val\n"
829 " }\n"
830 " }\n"
831 "}";
832 char *val1, *val2, *val3;
833
834 settings = settings_create_string(content);
835
836 val1 = settings->get_str(settings, "main.key1", NULL);
837 val2 = settings->get_str(settings, "main.sub1.key2", NULL);
838 /* loading the same content twice should not change anything, with... */
839 ck_assert(settings->load_string(settings, content, TRUE));
840 ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
841 ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
842 /* ...or without merging */
843 ck_assert(settings->load_string(settings, content, FALSE));
844 ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
845 ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
846
847 val1 = settings->get_str(settings, "main.key2", NULL);
848 val2 = settings->get_str(settings, "main.key3", NULL);
849 val3 = settings->get_str(settings, "main.none", NULL);
850 /* only pointers for modified settings should change, but still be valid */
851 ck_assert(settings->load_string(settings, include_content1, FALSE));
852 ck_assert(val1 != settings->get_str(settings, "main.key2", NULL));
853 ck_assert_str_eq(val1, "val2");
854 ck_assert(val2 == settings->get_str(settings, "main.key3", NULL));
855 ck_assert(val3 != settings->get_str(settings, "main.none", NULL));
856 ck_assert_str_eq(val3, "x");
857
858 settings->destroy(settings);
859 settings = settings_create_string(content);
860 ck_assert(settings);
861
862 ck_assert(settings->load_string(settings, include_content1, TRUE));
863 verify_include();
864
865 ck_assert(settings->load_string(settings, include_content2, FALSE));
866 verify_null("main.key1");
867 verify_string("v2", "key2");
868 verify_string("val", "sub1.key");
869 verify_null("main.sub1.key3");
870 }
871 END_TEST
872
873
874 START_TEST(test_load_string_section)
875 {
876 char *content =
877 "main {\n"
878 " key1 = val1\n"
879 " key2 = val2\n"
880 " none = x\n"
881 " sub1 {\n"
882 " include = value\n"
883 " key2 = value2\n"
884 " }\n"
885 "}";
886
887 settings = settings_create_string(content);
888
889 ck_assert(settings->load_string_section(settings, include_content1, TRUE, ""));
890 ck_assert(settings->load_string_section(settings, include_content2, TRUE, "main.sub1"));
891 verify_include();
892
893 /* invalid strings are a failure */
894 ck_assert(!settings->load_string_section(settings, "conf {", TRUE, ""));
895 /* NULL or empty strings are OK though */
896 ck_assert(settings->load_string_section(settings, "", TRUE, ""));
897 ck_assert(settings->load_string_section(settings, NULL, TRUE, ""));
898 verify_include();
899
900 ck_assert(settings->load_string_section(settings, include_content2, FALSE, "main"));
901 verify_null("main.key1");
902 verify_string("v2", "main.key2");
903 verify_string("val", "main.sub1.key");
904 verify_null("main.sub1.key3");
905 verify_null("main.sub2.sub3");
906
907 ck_assert(settings->load_string_section(settings, include_content2, TRUE, "main.sub2"));
908 verify_string("v2", "main.sub2.key2");
909 verify_string("val", "main.sub2.sub1.key");
910 }
911 END_TEST
912
913 START_SETUP(setup_fallback_config)
914 {
915 create_settings(chunk_from_str(
916 "main {\n"
917 " key1 = val1\n"
918 " sub1 {\n"
919 " key1 = val1\n"
920 " }\n"
921 "}\n"
922 "sub {\n"
923 " key1 = subval1\n"
924 " key2 = subval2\n"
925 " subsub {\n"
926 " subkey1 = subsubval1\n"
927 " }\n"
928 "}\n"
929 "base {\n"
930 " key1 = baseval1\n"
931 " key2 = baseval2\n"
932 " sub1 {\n"
933 " key1 = subbase1\n"
934 " key2 = subbase2\n"
935 " key3 = subbase3\n"
936 " subsub {\n"
937 " subkey1 = subsubbaseval1\n"
938 " subkey2 = subsubbaseval2\n"
939 " }\n"
940 " }\n"
941 " sub2 {\n"
942 " key4 = subbase4\n"
943 " }\n"
944 "}"));
945 }
946 END_SETUP
947
948 START_TEST(test_add_fallback)
949 {
950 linked_list_t *keys, *values;
951
952 settings->add_fallback(settings, "main.sub1", "sub");
953 verify_string("val1", "main.sub1.key1");
954 verify_string("subval2", "main.sub1.key2");
955 verify_string("subsubval1", "main.sub1.subsub.subkey1");
956
957 /* fallbacks are preserved even if the complete config is replaced */
958 settings->load_files(settings, path, FALSE);
959 verify_string("val1", "main.sub1.key1");
960 verify_string("subval2", "main.sub1.key2");
961 verify_string("subsubval1", "main.sub1.subsub.subkey1");
962
963 keys = linked_list_create_with_items("sub1", NULL);
964 verify_sections(keys, "main");
965 keys = linked_list_create_with_items("subsub", NULL);
966 verify_sections(keys, "main.sub1");
967
968 keys = linked_list_create_with_items("key1", NULL);
969 values = linked_list_create_with_items("val1", NULL);
970 verify_key_values(keys, values, "main");
971
972 keys = linked_list_create_with_items("key1", "key2", NULL);
973 values = linked_list_create_with_items("val1", "subval2", NULL);
974 verify_key_values(keys, values, "main.sub1");
975
976 keys = linked_list_create_with_items("subkey1", NULL);
977 values = linked_list_create_with_items("subsubval1", NULL);
978 verify_key_values(keys, values, "main.sub1.subsub");
979
980 settings->add_fallback(settings, "main", "base");
981 verify_string("val1", "main.key1");
982 verify_string("baseval2", "main.key2");
983 verify_string("val1", "main.sub1.key1");
984 verify_string("subval2", "main.sub1.key2");
985 verify_string("subsubval1", "main.sub1.subsub.subkey1");
986 verify_string("subsubbaseval2", "main.sub1.subsub.subkey2");
987 verify_string("subbase3", "main.sub1.key3");
988 verify_string("subbase4", "main.sub2.key4");
989
990
991 keys = linked_list_create_with_items("sub1", "sub2", NULL);
992 verify_sections(keys, "main");
993 keys = linked_list_create_with_items("subsub", NULL);
994 verify_sections(keys, "main.sub1");
995
996 keys = linked_list_create_with_items("key1", "key2", NULL);
997 values = linked_list_create_with_items("val1", "baseval2", NULL);
998 verify_key_values(keys, values, "main");
999
1000 keys = linked_list_create_with_items("key1", "key2", "key3", NULL);
1001 values = linked_list_create_with_items("val1", "subval2", "subbase3", NULL);
1002 verify_key_values(keys, values, "main.sub1");
1003
1004 keys = linked_list_create_with_items("subkey1", "subkey2", NULL);
1005 values = linked_list_create_with_items("subsubval1", "subsubbaseval2", NULL);
1006 verify_key_values(keys, values, "main.sub1.subsub");
1007
1008 settings->set_str(settings, "main.sub1.key2", "val2");
1009 verify_string("val2", "main.sub1.key2");
1010 settings->set_str(settings, "main.sub1.subsub.subkey2", "val2");
1011 verify_string("val2", "main.sub1.subsub.subkey2");
1012 verify_string("subsubval1", "main.sub1.subsub.subkey1");
1013 }
1014 END_TEST
1015
1016 START_TEST(test_add_fallback_printf)
1017 {
1018 settings->add_fallback(settings, "%s.sub1", "sub", "main");
1019 verify_string("val1", "main.sub1.key1");
1020 verify_string("subval2", "main.sub1.key2");
1021 verify_string("subsubval1", "main.sub1.subsub.subkey1");
1022
1023 settings->add_fallback(settings, "%s.%s2", "%s.%s1", "main", "sub");
1024 verify_string("val1", "main.sub2.key1");
1025 verify_string("subval2", "main.sub2.key2");
1026 verify_string("subsubval1", "main.sub2.subsub.subkey1");
1027 }
1028 END_TEST
1029
1030 START_SETUP(setup_string_config)
1031 {
1032 create_settings(chunk_from_str(
1033 "string = \" with accurate\twhite\\tspace\"\n"
1034 "special = \"all { special } characters # can be used.\"\n"
1035 "newlines = \"can be encoded explicitly\\nor implicitly\n"
1036 "or \\\n"
1037 "escaped\"\n"
1038 "quotes = \"\\\"and\\\" slashes \\\\ can \\\\ be\" # escaped too\n"
1039 "multiple = \"strings\" are \"combined\"\n"
1040 ));
1041 }
1042 END_SETUP
1043
1044 START_TEST(test_strings)
1045 {
1046 verify_string(" with accurate\twhite\tspace", "string");
1047 verify_string("all { special } characters # can be used.", "special");
1048 verify_string("can be encoded explicitly\nor implicitly\nor escaped", "newlines");
1049 verify_string("\"and\" slashes \\ can \\ be", "quotes");
1050 verify_string("strings are combined", "multiple");
1051 }
1052 END_TEST
1053
1054 START_TEST(test_valid)
1055 {
1056 chunk_t contents;
1057
1058 contents = chunk_from_str(
1059 "single = value");
1060 ck_assert(chunk_write(contents, path, 0022, TRUE));
1061 ck_assert(settings->load_files(settings, path, FALSE));
1062 verify_string("value", "single");
1063
1064 contents = chunk_from_str(
1065 "singleline { single = value }");
1066 ck_assert(chunk_write(contents, path, 0022, TRUE));
1067 ck_assert(settings->load_files(settings, path, FALSE));
1068 verify_string("value", "singleline.single");
1069
1070 contents = chunk_from_str(
1071 "singleline { sub { sub1 = val1 } single = value }");
1072 ck_assert(chunk_write(contents, path, 0022, TRUE));
1073 ck_assert(settings->load_files(settings, path, FALSE));
1074 verify_string("val1", "singleline.sub.sub1");
1075
1076 contents = chunk_from_str(
1077 "newline\n { single = value }");
1078 ck_assert(chunk_write(contents, path, 0022, TRUE));
1079 ck_assert(settings->load_files(settings, path, FALSE));
1080 verify_string("value", "newline.single");
1081
1082 contents = chunk_from_str(
1083 "section {\n"
1084 " include # without pattern produces a warning, but is fine\n"
1085 "}\n");
1086 ck_assert(chunk_write(contents, path, 0022, TRUE));
1087 ck_assert(settings->load_files(settings, path, FALSE));
1088 }
1089 END_TEST
1090
1091 START_TEST(test_invalid)
1092 {
1093 chunk_t contents;
1094
1095 contents = chunk_from_str(
1096 "{\n"
1097 " no = section name\n"
1098 "}\n");
1099 ck_assert(chunk_write(contents, path, 0022, TRUE));
1100 ck_assert(!settings->load_files(settings, path, FALSE));
1101
1102 contents = chunk_from_str(
1103 "no {\n"
1104 " = key name\n"
1105 "}\n");
1106 ck_assert(chunk_write(contents, path, 0022, TRUE));
1107 ck_assert(!settings->load_files(settings, path, FALSE));
1108
1109 contents = chunk_from_str(
1110 "unterminated {\n"
1111 " not = valid\n");
1112 ck_assert(chunk_write(contents, path, 0022, TRUE));
1113 ck_assert(!settings->load_files(settings, path, FALSE));
1114
1115 contents = chunk_from_str(
1116 "unterminated {\n"
1117 " strings = \"are invalid\n");
1118 ck_assert(chunk_write(contents, path, 0022, TRUE));
1119 ck_assert(!settings->load_files(settings, path, FALSE));
1120
1121 contents = chunk_from_str(
1122 "spaces in name {}");
1123 ck_assert(chunk_write(contents, path, 0022, TRUE));
1124 ck_assert(!settings->load_files(settings, path, FALSE));
1125
1126 contents = chunk_from_str(
1127 "only = a single setting = per line");
1128 ck_assert(chunk_write(contents, path, 0022, TRUE));
1129 ck_assert(!settings->load_files(settings, path, FALSE));
1130 }
1131 END_TEST
1132
1133 Suite *settings_suite_create()
1134 {
1135 Suite *s;
1136 TCase *tc;
1137
1138 s = suite_create("settings");
1139
1140 tc = tcase_create("get/set_str (basic behavior)");
1141 tcase_add_checked_fixture(tc, setup_base_config, teardown_config);
1142 tcase_add_test(tc, test_get_str);
1143 tcase_add_test(tc, test_get_str_printf);
1144 tcase_add_test(tc, test_set_str);
1145 tcase_add_test(tc, test_set_str_printf);
1146 tcase_add_test(tc, test_set_default_str);
1147 suite_add_tcase(s, tc);
1148
1149 tc = tcase_create("get/set_bool");
1150 tcase_add_checked_fixture(tc, setup_bool_config, teardown_config);
1151 tcase_add_test(tc, test_get_bool);
1152 tcase_add_test(tc, test_set_bool);
1153 suite_add_tcase(s, tc);
1154
1155 tc = tcase_create("get/set_int");
1156 tcase_add_checked_fixture(tc, setup_int_config, teardown_config);
1157 tcase_add_test(tc, test_get_int);
1158 tcase_add_test(tc, test_set_int);
1159 suite_add_tcase(s, tc);
1160
1161 tc = tcase_create("get/set_double");
1162 tcase_add_checked_fixture(tc, setup_double_config, teardown_config);
1163 tcase_add_test(tc, test_get_double);
1164 tcase_add_test(tc, test_set_double);
1165 suite_add_tcase(s, tc);
1166
1167 tc = tcase_create("get/set_time");
1168 tcase_add_checked_fixture(tc, setup_time_config, teardown_config);
1169 tcase_add_test(tc, test_get_time);
1170 tcase_add_test(tc, test_set_time);
1171 suite_add_tcase(s, tc);
1172
1173 tc = tcase_create("section enumerator");
1174 tcase_add_checked_fixture(tc, setup_base_config, teardown_config);
1175 tcase_add_test(tc, test_section_enumerator);
1176 suite_add_tcase(s, tc);
1177
1178 tc = tcase_create("key/value enumerator");
1179 tcase_add_checked_fixture(tc, setup_base_config, teardown_config);
1180 tcase_add_test(tc, test_key_value_enumerator);
1181 suite_add_tcase(s, tc);
1182
1183 tc = tcase_create("include/load_files[_section]");
1184 tcase_add_checked_fixture(tc, setup_include_config, teardown_include_config);
1185 tcase_add_test(tc, test_include);
1186 tcase_add_test(tc, test_include_string);
1187 tcase_add_test(tc, test_load_files);
1188 tcase_add_test(tc, test_load_files_section);
1189 tcase_add_test(tc, test_order_kv);
1190 tcase_add_test(tc, test_order_section);
1191 suite_add_tcase(s, tc);
1192
1193 tc = tcase_create("load_string[_section]");
1194 tcase_add_checked_fixture(tc, setup_include_config, teardown_config);
1195 tcase_add_test(tc, test_load_string);
1196 tcase_add_test(tc, test_load_string_section);
1197 suite_add_tcase(s, tc);
1198
1199 tc = tcase_create("fallback");
1200 tcase_add_checked_fixture(tc, setup_fallback_config, teardown_config);
1201 tcase_add_test(tc, test_add_fallback);
1202 tcase_add_test(tc, test_add_fallback_printf);
1203 suite_add_tcase(s, tc);
1204
1205 tc = tcase_create("strings");
1206 tcase_add_checked_fixture(tc, setup_string_config, teardown_config);
1207 tcase_add_test(tc, test_strings);
1208 suite_add_tcase(s, tc);
1209
1210 tc = tcase_create("valid/invalid data");
1211 tcase_add_checked_fixture(tc, setup_base_config, teardown_config);
1212 tcase_add_test(tc, test_valid);
1213 tcase_add_test(tc, test_invalid);
1214 suite_add_tcase(s, tc);
1215
1216 return s;
1217 }