diff options
Diffstat (limited to 'src/libstrongswan/tests/suites/test_settings.c')
-rw-r--r-- | src/libstrongswan/tests/suites/test_settings.c | 435 |
1 files changed, 298 insertions, 137 deletions
diff --git a/src/libstrongswan/tests/suites/test_settings.c b/src/libstrongswan/tests/suites/test_settings.c index 096465191..b9d429a24 100644 --- a/src/libstrongswan/tests/suites/test_settings.c +++ b/src/libstrongswan/tests/suites/test_settings.c @@ -17,12 +17,16 @@ #include <unistd.h> -#include <utils/settings.h> +#include <settings/settings.h> #include <utils/chunk.h> #include <utils/utils.h> #include <collections/linked_list.h> +#ifdef WIN32 +static char *path = "C:\\Windows\\Temp\\strongswan-settings-test"; +#else static char *path = "/tmp/strongswan-settings-test"; +#endif static settings_t *settings; static void create_settings(chunk_t contents) @@ -39,6 +43,7 @@ START_SETUP(setup_base_config) " # this gets overridden below\n" " key2 = val2\n" " none = \n" + " empty = \"\"\n" " sub1 {\n" " key = value\n" " key2 = value2\n" @@ -51,7 +56,8 @@ START_SETUP(setup_base_config) " sub% {\n" " id = %any\n" " }\n" - " key2 = with spaces\n" + " key2 = with space\n" + " key3 = \"string with\\nnewline\"\n" "}\n" "out = side\n" "other {\n" @@ -79,7 +85,9 @@ START_TEST(test_get_str) verify_string("val1", "main.key1"); verify_string("val1", "main..key1"); verify_string("val1", ".main.key1"); - verify_string("with spaces", "main.key2"); + verify_string("", "main.empty"); + verify_string("with space", "main.key2"); + verify_string("string with\nnewline", "main.key3"); verify_string("value", "main.sub1.key"); verify_string("value2", "main.sub1.key2"); verify_string("bar", "main.sub1.subsub.foo"); @@ -88,10 +96,8 @@ START_TEST(test_get_str) verify_string("side", "out"); verify_string("other val", "other.key1"); - /* FIXME: should this rather be undefined i.e. return the default value? */ - verify_string("", "main.none"); - - verify_null("main.key3"); + verify_null("main.none"); + verify_null("main.key4"); verify_null("other.sub"); } END_TEST @@ -125,16 +131,35 @@ START_TEST(test_get_str_printf) * probably document it at least */ verify_null("main.%s%u.key%d", "sub", 1, 2); - verify_null("%s.%s%d", "main", "key", 3); + verify_null("%s.%s%d", "main", "key", 4); } END_TEST START_TEST(test_set_str) { + char *val1, *val2; + + val1 = settings->get_str(settings, "main.key1", NULL); + ck_assert_str_eq("val1", val1); settings->set_str(settings, "main.key1", "val"); verify_string("val", "main.key1"); + /* the pointer we got before is still valid */ + ck_assert_str_eq("val1", val1); + + val2 = settings->get_str(settings, "main.key1", NULL); + ck_assert_str_eq("val", val2); settings->set_str(settings, "main.key1", "longer value"); verify_string("longer value", "main.key1"); + /* the pointers we got before are still valid */ + ck_assert_str_eq("val1", val1); + ck_assert_str_eq("val", val2); + + val1 = settings->get_str(settings, "main.key1", NULL); + settings->set_str(settings, "main.key1", "longer value"); + val2 = settings->get_str(settings, "main.key1", NULL); + /* setting the same string should should get us the same pointer */ + ck_assert(val1 == val2); + settings->set_str(settings, "main", "main val"); verify_string("main val", "main"); settings->set_str(settings, "main.sub1.new", "added"); @@ -183,6 +208,7 @@ START_SETUP(setup_bool_config) " key7 = disabled\n" " key8 = 0\n" " key9 = 5\n" + " empty = \"\"\n" " none = \n" " foo = bar\n" "}")); @@ -203,6 +229,8 @@ START_TEST(test_get_bool) verify_bool(FALSE, TRUE, "main.key7"); verify_bool(FALSE, TRUE, "main.key8"); + verify_bool(FALSE, FALSE, "main.empty"); + verify_bool(TRUE, TRUE, "main.empty"); verify_bool(FALSE, FALSE, "main.none"); verify_bool(TRUE, TRUE, "main.none"); verify_bool(FALSE, FALSE, "main.foo"); @@ -237,9 +265,9 @@ START_SETUP(setup_int_config) create_settings(chunk_from_str( "main {\n" " key1 = 5\n" - " # gets cut off\n" " key2 = 5.5\n" " key3 = -42\n" + " empty = \"\"\n" " none = \n" " foo1 = bar\n" " foo2 = bar13\n" @@ -254,14 +282,14 @@ END_SETUP START_TEST(test_get_int) { verify_int(5, 0, "main.key1"); - verify_int(5, 0, "main.key2"); + verify_int(0, 0, "main.key2"); verify_int(-42, 0, "main.key3"); - /* FIXME: do we want this behavior? */ - verify_int(0, 11, "main.none"); - verify_int(0, 11, "main.foo1"); - verify_int(0, 11, "main.foo2"); - verify_int(13, 11, "main.foo3"); + verify_int(11, 11, "main.empty"); + verify_int(11, 11, "main.none"); + verify_int(11, 11, "main.foo1"); + verify_int(11, 11, "main.foo2"); + verify_int(11, 11, "main.foo3"); verify_int(13, 13, "main.key4"); verify_int(-13, -13, "main"); @@ -291,6 +319,7 @@ START_SETUP(setup_double_config) " key2 = 5.5\n" " key3 = -42\n" " key4 = -42.5\n" + " empty = \"\"\n" " none = \n" " foo1 = bar\n" " foo2 = bar13.5\n" @@ -309,11 +338,11 @@ START_TEST(test_get_double) verify_double(-42, 0, "main.key3"); verify_double(-42.5, 0, "main.key4"); - /* FIXME: do we want this behavior? */ - verify_double(0, 11.5, "main.none"); - verify_double(0, 11.5, "main.foo1"); - verify_double(0, 11.5, "main.foo2"); - verify_double(13.5, 11.5, "main.foo3"); + verify_double(11.5, 11.5, "main.empty"); + verify_double(11.5, 11.5, "main.none"); + verify_double(11.5, 11.5, "main.foo1"); + verify_double(11.5, 11.5, "main.foo2"); + verify_double(11.5, 11.5, "main.foo3"); verify_double(11.5, 11.5, "main.key5"); verify_double(-11.5, -11.5, "main"); @@ -341,10 +370,12 @@ START_SETUP(setup_time_config) { create_settings(chunk_from_str( "main {\n" + " key0 = 5\n" " key1 = 5s\n" " key2 = 5m\n" - " key3 = 5h\n" - " key4 = 5d\n" + " key3 = 5 h\n" + " key4 = 5\td\n" + " empty = \"\"\n" " none = \n" " foo1 = bar\n" " foo2 = bar13\n" @@ -358,16 +389,17 @@ END_SETUP START_TEST(test_get_time) { + verify_time(5, 0, "main.key0"); verify_time(5, 0, "main.key1"); verify_time(300, 0, "main.key2"); verify_time(18000, 0, "main.key3"); verify_time(432000, 0, "main.key4"); - /* FIXME: do we want this behavior? */ - verify_time(0, 11, "main.none"); - verify_time(0, 11, "main.foo1"); - verify_time(0, 11, "main.foo2"); - verify_time(13, 11, "main.foo3"); + verify_time(11, 11, "main.empty"); + verify_time(11, 11, "main.none"); + verify_time(11, 11, "main.foo1"); + verify_time(11, 11, "main.foo2"); + verify_time(11, 11, "main.foo3"); verify_time(11, 11, "main.key5"); verify_time(11, 11, "main"); @@ -387,37 +419,21 @@ START_TEST(test_set_time) } END_TEST -static bool verify_section(linked_list_t *verifier, char *section) -{ - enumerator_t *enumerator; - char *current; - bool result = FALSE; - - enumerator = verifier->create_enumerator(verifier); - while (enumerator->enumerate(enumerator, ¤t)) - { - if (streq(current, section)) - { - verifier->remove_at(verifier, enumerator); - result = TRUE; - break; - } - } - enumerator->destroy(enumerator); - return result; -} - static void verify_sections(linked_list_t *verifier, char *parent) { - enumerator_t *enumerator; - char *section; + enumerator_t *enumerator, *ver; + char *section, *current; enumerator = settings->create_section_enumerator(settings, parent); - while (enumerator->enumerate(enumerator, §ion)) + ver = verifier->create_enumerator(verifier); + while (enumerator->enumerate(enumerator, §ion) && + ver->enumerate(ver, ¤t)) { - ck_assert(verify_section(verifier, section)); + ck_assert_str_eq(section, current); + verifier->remove_at(verifier, ver); } enumerator->destroy(enumerator); + ver->destroy(ver); ck_assert_int_eq(0, verifier->get_count(verifier)); verifier->destroy(verifier); } @@ -429,8 +445,8 @@ START_TEST(test_section_enumerator) verifier = linked_list_create_with_items("sub1", "sub%", NULL); verify_sections(verifier, "main"); - settings->set_str(settings, "main.sub2.new", "added"); - verifier = linked_list_create_with_items("sub1", "sub%", "sub2", NULL); + settings->set_str(settings, "main.sub0.new", "added"); + verifier = linked_list_create_with_items("sub1", "sub%", "sub0", NULL); verify_sections(verifier, "main"); verifier = linked_list_create_with_items("subsub", NULL); @@ -447,44 +463,27 @@ START_TEST(test_section_enumerator) } END_TEST -static bool verify_key_value(linked_list_t *keys, linked_list_t *values, - char *key, char *value) +static void verify_key_values(linked_list_t *keys, linked_list_t *values, + char *parent) { - enumerator_t *enum_keys, *enum_values; - char *current_key, *current_value; - bool result = FALSE; + enumerator_t *enumerator, *enum_keys, *enum_values; + char *key, *value, *current_key, *current_value; + enumerator = settings->create_key_value_enumerator(settings, parent); enum_keys = keys->create_enumerator(keys); enum_values = values->create_enumerator(values); - while (enum_keys->enumerate(enum_keys, ¤t_key) && + while (enumerator->enumerate(enumerator, &key, &value) && + enum_keys->enumerate(enum_keys, ¤t_key) && enum_values->enumerate(enum_values, ¤t_value)) { - if (streq(current_key, key)) - { - ck_assert_str_eq(current_value, value); - keys->remove_at(keys, enum_keys); - values->remove_at(values, enum_values); - result = TRUE; - break; - } + ck_assert_str_eq(current_key, key); + ck_assert_str_eq(current_value, value); + keys->remove_at(keys, enum_keys); + values->remove_at(values, enum_values); } + enumerator->destroy(enumerator); enum_keys->destroy(enum_keys); enum_values->destroy(enum_values); - return result; -} - -static void verify_key_values(linked_list_t *keys, linked_list_t *values, - char *parent) -{ - enumerator_t *enumerator; - char *key, *value; - - enumerator = settings->create_key_value_enumerator(settings, parent); - while (enumerator->enumerate(enumerator, &key, &value)) - { - ck_assert(verify_key_value(keys, values, key, value)); - } - enumerator->destroy(enumerator); ck_assert_int_eq(0, keys->get_count(keys)); keys->destroy(keys); values->destroy(values); @@ -494,8 +493,8 @@ START_TEST(test_key_value_enumerator) { linked_list_t *keys, *values; - keys = linked_list_create_with_items("key1", "key2", "none", NULL); - values = linked_list_create_with_items("val1", "with spaces", "", NULL); + keys = linked_list_create_with_items("key1", "key2", "empty", "key3", NULL); + values = linked_list_create_with_items("val1", "with space", "", "string with\nnewline", NULL); verify_key_values(keys, values, "main"); keys = linked_list_create_with_items("key", "key2", "subsub", NULL); @@ -522,8 +521,13 @@ START_TEST(test_key_value_enumerator) } END_TEST -#define include1 "/tmp/strongswan-settings-test-include1" -#define include2 "/tmp/strongswan-settings-test-include2" +#ifdef WIN32 +# define include1 "C:\\Windows\\Temp\\strongswan-settings-test-include1" +# define include2 "C:\\Windows\\Temp\\strongswan-settings-test-include2" +#else +# define include1 "/tmp/strongswan-settings-test-include1" +# define include2 "/tmp/strongswan-settings-test-include2" +#endif START_SETUP(setup_include_config) { @@ -531,6 +535,7 @@ START_SETUP(setup_include_config) "main {\n" " key1 = n1\n" " key2 = n2\n" + " key3 = val3\n" " none = \n" " sub1 {\n" " key3 = value\n" @@ -563,13 +568,15 @@ static void verify_include() { verify_string("n1", "main.key1"); verify_string("v2", "main.key2"); - verify_string("", "main.none"); + verify_string("val3", "main.key3"); verify_string("val", "main.sub1.key"); verify_string("v2", "main.sub1.key2"); verify_string("val", "main.sub1.sub1.key"); verify_string("value", "main.sub1.key3"); verify_string("value", "main.sub1.include"); verify_string("val3", "main.sub2.sub3"); + + verify_null("main.none"); } START_TEST(test_include) @@ -580,13 +587,13 @@ START_TEST(test_include) " key2 = val2\n" " none = x\n" " sub1 {\n" + " include this/does/not/exist.conf\n" " include = value\n" " key2 = value2\n" " include " include2 "\n" " }\n" "}\n" - "# currently there must be a newline after include statements\n" - "include " include1 "\n"); + "include " include1); create_settings(contents); verify_include(); @@ -599,6 +606,7 @@ START_TEST(test_load_files) "main {\n" " key1 = val1\n" " key2 = val2\n" + " key3 = val3\n" " none = x\n" " sub1 {\n" " include = value\n" @@ -608,7 +616,33 @@ START_TEST(test_load_files) " }\n" " }\n" "}"); + char *val1, *val2, *val3; + + create_settings(contents); + + val1 = settings->get_str(settings, "main.key1", NULL); + val2 = settings->get_str(settings, "main.sub1.key2", NULL); + /* loading the same file twice should not change anything, with... */ + ck_assert(settings->load_files(settings, path, TRUE)); + ck_assert(val1 == settings->get_str(settings, "main.key1", NULL)); + ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL)); + /* ...or without merging */ + ck_assert(settings->load_files(settings, path, FALSE)); + ck_assert(val1 == settings->get_str(settings, "main.key1", NULL)); + ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL)); + + val1 = settings->get_str(settings, "main.key2", NULL); + val2 = settings->get_str(settings, "main.key3", NULL); + val3 = settings->get_str(settings, "main.none", NULL); + /* only pointers for modified settings should change, but still be valid */ + ck_assert(settings->load_files(settings, include1, FALSE)); + ck_assert(val1 != settings->get_str(settings, "main.key2", NULL)); + ck_assert_str_eq(val1, "val2"); + ck_assert(val2 == settings->get_str(settings, "main.key3", NULL)); + ck_assert(val3 != settings->get_str(settings, "main.none", NULL)); + ck_assert_str_eq(val3, "x"); + settings->destroy(settings); create_settings(contents); ck_assert(settings->load_files(settings, include1, TRUE)); @@ -641,15 +675,20 @@ START_TEST(test_load_files_section) ck_assert(settings->load_files_section(settings, include2, TRUE, "main.sub1")); verify_include(); - /* non existing files are no failure */ - ck_assert(settings->load_files_section(settings, include1".conf", TRUE, "")); + /* non existing files are a failure here */ + ck_assert(!settings->load_files_section(settings, include1".conf", TRUE, "")); verify_include(); - /* unreadable files are */ - ck_assert(chunk_write(contents, include1".no", 0444, TRUE)); - ck_assert(!settings->load_files_section(settings, include1".no", TRUE, "")); - unlink(include1".no"); - verify_include(); +#ifndef WIN32 + /* unreadable files are too (only fails when not running as root) */ + if (getuid() != 0) + { + ck_assert(chunk_write(contents, include1".no", 0444, TRUE)); + ck_assert(!settings->load_files_section(settings, include1".no", TRUE, "")); + unlink(include1".no"); + verify_include(); + } +#endif ck_assert(settings->load_files_section(settings, include2, FALSE, "main")); verify_null("main.key1"); @@ -664,6 +703,87 @@ START_TEST(test_load_files_section) } END_TEST +START_TEST(test_order_kv) +{ + chunk_t base = chunk_from_str( + "main {\n" + " key1 = val1\n" + " key2 = val2\n" + " key3 = val3\n" + "}"); + chunk_t include = chunk_from_str( + "main {\n" + " key0 = val0\n" + " key3 = val3\n" + " key1 = val1\n" + "}"); + linked_list_t *keys, *values; + + create_settings(base); + ck_assert(chunk_write(include, include1, 0022, TRUE)); + + keys = linked_list_create_with_items("key1", "key2", "key3", NULL); + values = linked_list_create_with_items("val1", "val2", "val3", NULL); + verify_key_values(keys, values, "main"); + + /* the original order is maintained if the settings are merged */ + ck_assert(settings->load_files(settings, include1, TRUE)); + keys = linked_list_create_with_items("key1", "key2", "key3", "key0", NULL); + values = linked_list_create_with_items("val1", "val2", "val3", "val0", NULL); + verify_key_values(keys, values, "main"); + + /* but the new order is adopted if the settings are replaced */ + ck_assert(settings->load_files(settings, include1, FALSE)); + keys = linked_list_create_with_items("key0", "key3", "key1", NULL); + values = linked_list_create_with_items("val0", "val3", "val1", NULL); + verify_key_values(keys, values, "main"); + + unlink(include1); +} +END_TEST + +START_TEST(test_order_section) +{ + chunk_t base = chunk_from_str( + "main {\n" + " sub1 {\n" + " }\n" + " sub2 {\n" + " }\n" + " sub3 {\n" + " }\n" + "}"); + chunk_t include = chunk_from_str( + "main {\n" + " sub0 {\n" + " }\n" + " sub3 {\n" + " }\n" + " sub1 {\n" + " }\n" + "}"); + linked_list_t *sections; + + create_settings(base); + ck_assert(chunk_write(include, include1, 0022, TRUE)); + + sections = linked_list_create_with_items("sub1", "sub2", "sub3", NULL); + verify_sections(sections, "main"); + + /* the original order is maintained if the settings are merged */ + ck_assert(settings->load_files(settings, include1, TRUE)); + sections = linked_list_create_with_items("sub1", "sub2", "sub3", "sub0", NULL); + verify_sections(sections, "main"); + + /* but the new order is adopted if the settings are replaced */ + ck_assert(settings->load_files(settings, include1, FALSE)); + sections = linked_list_create_with_items("sub0", "sub3", "sub1", NULL); + verify_sections(sections, "main"); + + unlink(include1); +} +END_TEST + START_SETUP(setup_fallback_config) { create_settings(chunk_from_str( @@ -781,57 +901,85 @@ START_TEST(test_add_fallback_printf) } END_TEST -START_SETUP(setup_invalid_config) +START_SETUP(setup_string_config) { create_settings(chunk_from_str( - "# section without name\n" - "{\n" - " key1 = val1\n" - "}\n" - "main {\n" - " key2 = val2\n" - " # value without key\n" - " = val3\n" - " key4 = val4\n" - " # key without value does not change it\n" - " key4\n" - " # subsection without name\n" - " {\n" - " key5 = val5\n" - " }\n" - " # empty include pattern\n" - " include\n" - " key6 = val6\n" - "}")); + "string = \" with accurate\twhitespace\"\n" + "special = \"all { special } characters # can be used.\"\n" + "unterminated = \"is fine\n" + "but = produces a warning\n" + "newlines = \"can either be encoded\\nor\\\n" + "escaped\"\n" + "quotes = \"\\\"and\\\" slashes \\\\ can \\\\ be\" # escaped too\n" + "multiple = \"strings\" are \"combined\"\n" + )); } END_SETUP -START_TEST(test_invalid) +START_TEST(test_strings) +{ + verify_string(" with accurate\twhitespace", "string"); + verify_string("all { special } characters # can be used.", "special"); + verify_string("is fine", "unterminated"); + verify_string("produces a warning", "but"); + verify_string("can either be encoded\nor\nescaped", "newlines"); + verify_string("\"and\" slashes \\ can \\ be", "quotes"); + verify_string("strings are combined", "multiple"); +} +END_TEST + +START_TEST(test_valid) { - linked_list_t *keys, *values; chunk_t contents; - verify_null("key1"); - verify_null(".key1"); - verify_null("%s.key1", ""); - verify_string("val2", "main.key2"); - verify_string("val4", "main.key4"); - verify_null("main..key5"); - verify_string("val6", "main.key6"); + contents = chunk_from_str( + "single = value"); + ck_assert(chunk_write(contents, path, 0022, TRUE)); + ck_assert(settings->load_files(settings, path, FALSE)); + verify_string("value", "single"); - keys = linked_list_create_with_items("main", NULL); - verify_sections(keys, ""); + contents = chunk_from_str( + "singleline { single = value }"); + ck_assert(chunk_write(contents, path, 0022, TRUE)); + ck_assert(settings->load_files(settings, path, FALSE)); + verify_string("value", "singleline.single"); - keys = linked_list_create_with_items(NULL); - verify_sections(keys, "main"); + contents = chunk_from_str( + "singleline { sub { sub1 = val1 } single = value }"); + ck_assert(chunk_write(contents, path, 0022, TRUE)); + ck_assert(settings->load_files(settings, path, FALSE)); + verify_string("val1", "singleline.sub.sub1"); - keys = linked_list_create_with_items("key2", "key4", "key6", NULL); - values = linked_list_create_with_items("val2", "val4", "val6", NULL); - verify_key_values(keys, values, "main"); + contents = chunk_from_str( + "newline\n { single = value }"); + ck_assert(chunk_write(contents, path, 0022, TRUE)); + ck_assert(settings->load_files(settings, path, FALSE)); + verify_string("value", "newline.single"); + + contents = chunk_from_str( + "section {\n" + " include # without pattern produces a warning, but is fine\n" + "}\n"); + ck_assert(chunk_write(contents, path, 0022, TRUE)); + ck_assert(settings->load_files(settings, path, FALSE)); +} +END_TEST + +START_TEST(test_invalid) +{ + chunk_t contents; + + contents = chunk_from_str( + "{\n" + " no = section name\n" + "}\n"); + ck_assert(chunk_write(contents, path, 0022, TRUE)); + ck_assert(!settings->load_files(settings, path, FALSE)); - /* FIXME: we should probably fix this */ contents = chunk_from_str( - "requires = newline"); + "no {\n" + " = key name\n" + "}\n"); ck_assert(chunk_write(contents, path, 0022, TRUE)); ck_assert(!settings->load_files(settings, path, FALSE)); @@ -842,7 +990,12 @@ START_TEST(test_invalid) ck_assert(!settings->load_files(settings, path, FALSE)); contents = chunk_from_str( - "singleline { not = valid }\n"); + "spaces in name {}"); + ck_assert(chunk_write(contents, path, 0022, TRUE)); + ck_assert(!settings->load_files(settings, path, FALSE)); + + contents = chunk_from_str( + "only = a single setting = per line"); ck_assert(chunk_write(contents, path, 0022, TRUE)); ck_assert(!settings->load_files(settings, path, FALSE)); } @@ -903,6 +1056,8 @@ Suite *settings_suite_create() tcase_add_test(tc, test_include); tcase_add_test(tc, test_load_files); tcase_add_test(tc, test_load_files_section); + tcase_add_test(tc, test_order_kv); + tcase_add_test(tc, test_order_section); suite_add_tcase(s, tc); tc = tcase_create("fallback"); @@ -911,8 +1066,14 @@ Suite *settings_suite_create() tcase_add_test(tc, test_add_fallback_printf); suite_add_tcase(s, tc); - tc = tcase_create("invalid data"); - tcase_add_checked_fixture(tc, setup_invalid_config, teardown_config); + tc = tcase_create("strings"); + tcase_add_checked_fixture(tc, setup_string_config, teardown_config); + tcase_add_test(tc, test_strings); + suite_add_tcase(s, tc); + + tc = tcase_create("valid/invalid data"); + tcase_add_checked_fixture(tc, setup_base_config, teardown_config); + tcase_add_test(tc, test_valid); tcase_add_test(tc, test_invalid); suite_add_tcase(s, tc); |