]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
settings: Adopt the new order of sections and settings when replacing configs
authorTobias Brunner <tobias@strongswan.org>
Tue, 29 Apr 2014 14:04:43 +0000 (16:04 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 15 May 2014 09:28:09 +0000 (11:28 +0200)
src/libstrongswan/settings/settings_types.c
src/libstrongswan/tests/suites/test_settings.c

index 253d06808a37b9aa45d2ced6d8f9fa7d5e8a8de6..1256762379e810a4879ff84c3ff27cda2f13553c 100644 (file)
@@ -199,10 +199,13 @@ void settings_section_extend(section_t *base, section_t *extension,
        enumerator_t *enumerator;
        section_t *section;
        kv_t *kv;
+       array_t *sections = NULL, *kvs = NULL;
        int idx;
 
        if (purge)
-       {       /* remove sections and settings in base not found in extension */
+       {       /* remove sections and settings in base not found in extension, the
+                * others are removed too (from the _order list) so they can be inserted
+                * in the order found in extension */
                enumerator = array_create_enumerator(base->sections_order);
                while (enumerator->enumerate(enumerator, (void**)&section))
                {
@@ -212,32 +215,49 @@ void settings_section_extend(section_t *base, section_t *extension,
                                idx = array_bsearch(base->sections, section->name,
                                                                        settings_section_find, NULL);
                                if (section_purge(section, contents))
-                               {
+                               {       /* only remove them if we can purge them */
                                        array_remove(base->sections, idx, NULL);
                                        array_remove_at(base->sections_order, enumerator);
                                        settings_section_destroy(section, contents);
                                }
                        }
+                       else
+                       {
+                               array_remove_at(base->sections_order, enumerator);
+                               array_insert_create(&sections, ARRAY_TAIL, section);
+                               array_sort(sections, settings_section_sort, NULL);
+                       }
                }
                enumerator->destroy(enumerator);
 
-               enumerator = array_create_enumerator(base->kv_order);
-               while (enumerator->enumerate(enumerator, (void**)&kv))
+               while (array_remove(base->kv_order, 0, &kv))
                {
                        if (array_bsearch(extension->kv, kv->key, settings_kv_find,
                                                          NULL) == -1)
                        {
                                idx = array_bsearch(base->kv, kv->key, settings_kv_find, NULL);
                                array_remove(base->kv, idx, NULL);
-                               array_remove_at(base->kv_order, enumerator);
                                settings_kv_destroy(kv, contents);
                        }
+                       else
+                       {
+                               array_insert_create(&kvs, ARRAY_TAIL, kv);
+                               array_sort(kvs, settings_kv_sort, NULL);
+                       }
                }
-               enumerator->destroy(enumerator);
        }
 
        while (array_remove(extension->sections_order, 0, &section))
        {
+               idx = array_bsearch(sections, section->name,
+                                                       settings_section_find, NULL);
+               if (idx != -1)
+               {
+                       section_t *existing;
+
+                       array_remove(sections, idx, &existing);
+                       array_insert(base->sections_order, ARRAY_TAIL, existing);
+               }
                idx = array_bsearch(extension->sections, section->name,
                                                        settings_section_find, NULL);
                array_remove(extension->sections, idx, NULL);
@@ -246,10 +266,20 @@ void settings_section_extend(section_t *base, section_t *extension,
 
        while (array_remove(extension->kv_order, 0, &kv))
        {
+               idx = array_bsearch(kvs, kv->key, settings_kv_find, NULL);
+               if (idx != -1)
+               {
+                       kv_t *existing;
+
+                       array_remove(kvs, idx, &existing);
+                       array_insert(base->kv_order, ARRAY_TAIL, existing);
+               }
                idx = array_bsearch(extension->kv, kv->key, settings_kv_find, NULL);
                array_remove(extension->kv, idx, NULL);
                settings_kv_add(base, kv, contents);
        }
+       array_destroy(sections);
+       array_destroy(kvs);
 }
 
 /*
index 77fef12ad44018f62ed3a65b844313171720c160..e504b95a1b1765a9d61809bd19eec0e7ffc868c2 100644 (file)
@@ -694,6 +694,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(
@@ -811,7 +892,6 @@ START_TEST(test_add_fallback_printf)
 }
 END_TEST
 
-
 START_SETUP(setup_string_config)
 {
        create_settings(chunk_from_str(
@@ -967,6 +1047,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");