Blob Blame History Raw
From 7c04e712e8abafdbed02065a66b1589fa53b8f35 Mon Sep 17 00:00:00 2001
From: Alexander Scheel <ascheel@redhat.com>
Date: Wed, 26 Jul 2017 13:35:45 -0400
Subject: [PATCH] INI: Test INI_MS_DETECT non-exclusive behavior
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This adds test cases for the non-exclusive behavior of INI_MS_DETECT.

Signed-off-by: Alexander Scheel <ascheel@redhat.com>
Reviewed-by: Michal Židek <mzidek@redhat.com>

Merges: https://pagure.io/SSSD/ding-libs/issue/3167
(cherry picked from commit e322192d1711677e78b197915b1a12537a0e510b)
---
 Makefile.am                |   6 ++
 ini/ini_augment_ut_check.c | 250 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 256 insertions(+)
 create mode 100644 ini/ini_augment_ut_check.c

diff --git a/Makefile.am b/Makefile.am
index 65528a8..29d0dd6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -70,11 +70,13 @@ libpath_utils_la_LDFLAGS = \
 
 if HAVE_CHECK
     check_PROGRAMS += path_utils_ut \
+                      ini_augment_ut_check \
                       ini_configmod_ut_check \
                       ini_parse_ut_check \
                       ini_validators_ut_check \
                       $(NULL)
     TESTS += path_utils_ut \
+             ini_augment_ut_check \
              ini_configmod_ut_check \
              ini_parse_ut_check \
              ini_validators_ut_check \
@@ -349,6 +351,10 @@ ini_configmod_ut_SOURCES = ini/ini_configmod_ut.c
 ini_configmod_ut_LDADD = libini_config.la libcollection.la \
                          libbasicobjects.la libpath_utils.la libref_array.la
 
+ini_augment_ut_check_SOURCES = ini/ini_augment_ut_check.c
+ini_augment_ut_check_CFLAGS = $(AM_CFLAGS) $(CHECK_CFLAGS)
+ini_augment_ut_check_LDADD = libini_config.la $(CHECK_LIBS)
+
 ini_configmod_ut_check_SOURCES = ini/ini_configmod_ut_check.c
 ini_configmod_ut_check_CFLAGS = $(AM_CFLAGS) $(CHECK_CFLAGS)
 ini_configmod_ut_check_LDADD = libini_config.la libcollection.la \
diff --git a/ini/ini_augment_ut_check.c b/ini/ini_augment_ut_check.c
new file mode 100644
index 0000000..be475a3
--- /dev/null
+++ b/ini/ini_augment_ut_check.c
@@ -0,0 +1,250 @@
+/*
+    INI LIBRARY
+
+    Check based unit test for ini_config_augment.
+
+    Copyright (C) Alexander Scheel <ascheel@redhat.com> 2017
+
+    INI Library is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    INI Library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with INI Library.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <check.h>
+
+/* #define TRACE_LEVEL 7 */
+#define TRACE_HOME
+#include "trace.h"
+#include "ini_configobj.h"
+#include "ini_config_priv.h"
+
+static int write_to_file(char *path, char *text)
+{
+    FILE *f = fopen(path, "w");
+    int bytes = 0;
+    if (f == NULL)
+        return 1;
+
+    bytes = fprintf(f, "%s", text);
+    if (bytes != strlen(text)) {
+        return 1;
+    }
+
+    return fclose(f);
+}
+
+static int exists_array(const char *needle, char **haystack, uint32_t count)
+{
+    uint32_t i = 0;
+
+    for (i = 0; i < count; i++) {
+        fprintf(stderr, "%s == %s?\n", needle, haystack[i]);
+        if (strcmp(needle, haystack[i]) == 0) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+START_TEST(test_ini_augment_merge_sections)
+{
+    char base_path[PATH_MAX];
+    char augment_path[PATH_MAX];
+
+    char config_base[] =
+        "[section]\n"
+        "key1 = first\n"
+        "key2 = exists\n";
+
+    char config_augment[] =
+        "[section]\n"
+        "key1 = augment\n"
+        "key3 = exists\n";
+
+    char *builddir;
+
+    uint32_t flags[3] = { INI_MS_DETECT , INI_MS_DETECT | INI_MS_PRESERVE,
+                          INI_MS_DETECT | INI_MS_OVERWRITE };
+
+    int expected_attributes_counts[3] = { 3, 2, 2 };
+    const char *test_sections[3] = { "section", "section", "section" };
+    const char *test_attributes[3] = { "key3", "key1", "key1" };
+    const char *test_attribute_values[3] = {"exists", "first", "augment" };
+
+    int ret;
+    int iter;
+
+    builddir = getenv("builddir");
+    if (builddir == NULL) {
+        builddir = strdup(".");
+    }
+
+    snprintf(base_path, PATH_MAX, "%s/tmp_augment_base.conf", builddir);
+    snprintf(augment_path, PATH_MAX, "%s/tmp_augment_augment.conf", builddir);
+
+    ret = write_to_file(base_path, config_base);
+    fail_unless(ret == 0, "Failed to write %s: ret %d.\n", base_path, ret);
+
+    write_to_file(augment_path, config_augment);
+    fail_unless(ret == 0, "Failed to write %s: ret %d.\n", augment_path, ret);
+
+    for (iter = 0; iter < 3; iter++) {
+        uint32_t merge_flags = flags[iter];
+        int expected_attributes_count = expected_attributes_counts[iter];
+        const char *test_section = test_sections[iter];
+        const char *test_attribute = test_attributes[iter];
+        const char *test_attribute_value = test_attribute_values[iter];
+        struct ini_cfgobj *in_cfg;
+        struct ini_cfgobj *result_cfg;
+        struct ini_cfgfile *file_ctx;
+        struct ref_array *error_list;
+        struct ref_array *success_list;
+
+        char **sections;
+        int sections_count;
+
+        char **attributes;
+        int attributes_count;
+
+        struct value_obj *val;
+        char *val_str;
+
+        /* Match only augment.conf */
+        const char *m_patterns[] = { "^tmp_augment_augment.conf$", NULL };
+
+        /* Match all sections */
+        const char *m_sections[] = { ".*", NULL };
+
+        /* Create config collection */
+        ret = ini_config_create(&in_cfg);
+        fail_unless(ret == EOK, "Failed to create collection. Error %d\n",
+                    ret);
+
+        /* Open base.conf */
+        ret = ini_config_file_open(base_path, 0, &file_ctx);
+        fail_unless(ret == EOK, "Failed to open file. Error %d\n", ret);
+
+        /* Seed in_cfg with base.conf */
+        ret = ini_config_parse(file_ctx, 1, 0, 0, in_cfg);
+        fail_unless(ret == EOK, "Failed to parse file context. Error %d\n",
+                    ret);
+
+        /* Update base.conf with augment.conf */
+        ret = ini_config_augment(in_cfg,
+                                 builddir,
+                                 m_patterns,
+                                 m_sections,
+                                 NULL,
+                                 INI_STOP_ON_NONE,
+                                 0,
+                                 INI_PARSE_NOSPACE|INI_PARSE_NOTAB,
+                                 merge_flags,
+                                 &result_cfg,
+                                 &error_list,
+                                 &success_list);
+        /* We always expect EEXIST due to DETECT being set. */
+        fail_unless(ret == EEXIST,
+                    "Failed to augment context. Error %d\n", ret);
+
+        if (result_cfg) {
+            ini_config_destroy(in_cfg);
+            in_cfg = result_cfg;
+            result_cfg = NULL;
+        }
+
+        /* Get a list of sections from the resulting cfg. */
+        sections = ini_get_section_list(in_cfg, &sections_count, &ret);
+        fail_unless(ret == EOK, "Failed to get section list. Error %d\n", ret);
+
+        /* Validate that the tested section exists. */
+        ret = exists_array(test_section, sections, sections_count);
+        fail_if(ret == 0, "Failed to find expected section.\n");
+
+        /* Get a list of attributes from the resulting cfg. */
+        attributes = ini_get_attribute_list(in_cfg, test_section,
+                                            &attributes_count,
+                                            &ret);
+        fail_unless(ret == EOK, "Failed to get attribute list. Error %d\n",
+                    ret);
+
+        /* Validate that the expected number of attributes exist. This
+         * distinguishes MERGE from PRESERVE/OVERWRITE. */
+        fail_unless(expected_attributes_count == attributes_count,
+                    "Expected %d attributes, but received %d.\n",
+                    expected_attributes_count, attributes_count);
+
+        /* Validate that the test attribute exists. This distinguishes
+         * PRESERVE from OVERWRITE. */
+        ret = exists_array(test_attribute, attributes, attributes_count);
+        fail_if(ret == 0, "Failed to find expected attribute.\n");
+
+        ret = ini_get_config_valueobj(test_section, test_attribute, in_cfg,
+                                        0, &val);
+        fail_unless(ret == EOK, "Failed to load value object. Error %d\n",
+                    ret);
+
+        val_str = ini_get_string_config_value(val, &ret);
+        fail_unless(ret == EOK, "Failed to get config value. Error %d\n", ret);
+
+        /* Validate the value of the test attribute. */
+        ret = strcmp(val_str, test_attribute_value);
+
+        fail_unless(ret == 0, "Attribute %s didn't have expected value of "
+                    "(%s): saw %s\n", test_attribute, test_attribute_value,
+                    val_str);
+
+        /* Cleanup */
+        free(val_str);
+        ini_free_attribute_list(attributes);
+        ini_free_section_list(sections);
+        ref_array_destroy(error_list);
+        ini_config_file_destroy(file_ctx);
+        ref_array_destroy(success_list);
+        ini_config_destroy(in_cfg);
+        ini_config_destroy(result_cfg);
+    }
+
+    remove(base_path);
+    remove(augment_path);
+    free(builddir);
+}
+END_TEST
+
+static Suite *ini_augment_suite(void)
+{
+    Suite *s = suite_create("ini_augment_suite");
+
+    TCase *tc_augment = tcase_create("ini_augment");
+    tcase_add_test(tc_augment, test_ini_augment_merge_sections);
+
+    suite_add_tcase(s, tc_augment);
+
+    return s;
+}
+
+int main(void)
+{
+    int number_failed;
+
+    Suite *s = ini_augment_suite();
+    SRunner *sr = srunner_create(s);
+    srunner_run_all(sr, CK_ENV);
+    number_failed = srunner_ntests_failed(sr);
+    srunner_free(sr);
+    return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
-- 
2.13.2