From 7c04e712e8abafdbed02065a66b1589fa53b8f35 Mon Sep 17 00:00:00 2001 From: Alexander Scheel 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 Reviewed-by: Michal Židek 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 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 . +*/ + +#include "config.h" + +#include +#include +#include +#include + +/* #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, §ions_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