ding-libs/tests/sanity/ini_validators_ut_check.c

1109 lines
34 KiB
C
Raw Normal View History

/*
INI LIBRARY
Unit test for the configuration file validators API.
Copyright (C) Michal Zidek <mzidek@redhat.com> 2016
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 <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <check.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/* #define TRACE_LEVEL 7 */
#define TRACE_HOME
#include "trace.h"
#include "ini_configobj.h"
#define TEST_DIR_PATH ""
#define TEST_RULES_FILE TEST_DIR_PATH"test_rules.ini"
static void create_rules_from_str(const char *rules,
struct ini_cfgobj **_rules_obj)
{
FILE *file;
size_t written;
int ret;
/* We want to test actual reading from file using
* ini_rules_read_from_file, so we create the file here */
file = fopen(TEST_RULES_FILE, "w");
fail_if(file == NULL, "fopen() failed: %s", strerror(errno));
written = fwrite(rules, 1, strlen(rules), file);
fail_unless(written == strlen(rules));
/* allow reading */
ret = chmod(TEST_RULES_FILE, 0664);
fail_unless(ret == 0, "chmod() failed: %s", strerror(errno));
fclose(file);
ret = ini_rules_read_from_file(TEST_RULES_FILE, _rules_obj);
fail_unless(ret == 0, "read_rules_from_file() failed: %s", strerror(ret));
}
static struct ini_cfgobj *get_ini_config_from_str(char input_data[],
size_t input_data_len)
{
struct ini_cfgobj *in_cfg;
struct ini_cfgfile *file_ctx;
int ret;
ret = ini_config_create(&in_cfg);
fail_unless(ret == EOK, "Failed to create config. Error %d.\n", ret);
ret = ini_config_file_from_mem(input_data, input_data_len, &file_ctx);
fail_unless(ret == EOK, "Failed to load config. Error %d.\n", ret);
ret = ini_config_parse(file_ctx, INI_STOP_ON_NONE, INI_MV1S_ALLOW, 0,
in_cfg);
fail_unless(ret == EOK, "Failed to parse config. Error %d.\n", ret);
ini_config_file_destroy(file_ctx);
return in_cfg;
}
START_TEST(test_ini_errobj)
{
struct ini_errobj *errobj;
int ret;
const char TEST_MSG1[] = "Test message one.";
const char TEST_MSG2[] = "Test message two.";
const char TEST_MSG3[] = "Test message three.";
ret = ini_errobj_create(NULL);
fail_unless(ret == EINVAL,
"ini_errobj_create(NULL) failed with wrong error [%s]",
strerror(ret));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
/* We just created the errobj, it should be empty */
fail_unless(ini_errobj_no_more_msgs(errobj));
/* Now add three messages, after adding each message,
* check if the errobj has correct content. */
ret = ini_errobj_add_msg(errobj, TEST_MSG1);
fail_if(ret != 0, "ini_errobj_add_msg() failed: %s", strerror(ret));
fail_if(ini_errobj_no_more_msgs(errobj));
ret = strcmp(TEST_MSG1, ini_errobj_get_msg(errobj));
fail_if(ret != 0, "TEST_MSG1 was not found.");
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ret = ini_errobj_add_msg(errobj, TEST_MSG2);
fail_if(ret != 0, "ini_errobj_add_msg() failed: %s", strerror(ret));
ini_errobj_reset(errobj); /* strart from first message */
fail_if(ini_errobj_no_more_msgs(errobj));
ret = strcmp(TEST_MSG1, ini_errobj_get_msg(errobj));
fail_if(ret != 0, "TEST_MSG1 was not found.");
ini_errobj_next(errobj);
fail_if(ini_errobj_no_more_msgs(errobj));
ret = strcmp(TEST_MSG2, ini_errobj_get_msg(errobj));
fail_if(ret != 0, "TEST_MSG2 was not found.");
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ret = ini_errobj_add_msg(errobj, TEST_MSG3);
fail_if(ret != 0, "ini_errobj_add_msg() failed: %s", strerror(ret));
ini_errobj_reset(errobj); /* strart from first message */
fail_if(ini_errobj_no_more_msgs(errobj));
ret = strcmp(TEST_MSG1, ini_errobj_get_msg(errobj));
fail_if(ret != 0, "TEST_MSG1 was not found.");
ini_errobj_next(errobj);
fail_if(ini_errobj_no_more_msgs(errobj));
ret = strcmp(TEST_MSG2, ini_errobj_get_msg(errobj));
fail_if(ret != 0, "TEST_MSG2 was not found.");
ini_errobj_next(errobj);
fail_if(ini_errobj_no_more_msgs(errobj));
ret = strcmp(TEST_MSG3, ini_errobj_get_msg(errobj));
fail_if(ret != 0, "TEST_MSG3 was not found.");
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
}
END_TEST
START_TEST(test_ini_noerror)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
char input_rules[] =
"[rule/always_succeed]\n"
"validator = ini_dummy_noerror\n";
char input_cfg[] =
"[section]\n"
"# Content of this file should not matter\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
START_TEST(test_ini_error)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
const char *errmsg;
char input_rules[] =
"[rule/generate_error]\n"
"validator = ini_dummy_error\n";
char input_wrong_rule[] =
"[rule/generate_error]\n"
"valid = ini_dummy_error\n";
char input_cfg[] =
"[section]\n"
"# Content of this file should not matter\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate exactly one error */
fail_if(ini_errobj_no_more_msgs(errobj));
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg, "[rule/generate_error]: Error");
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ini_rules_destroy(rules_obj);
/* test rule with missing validator */
create_rules_from_str(input_wrong_rule, &rules_obj);
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate exactly one error */
fail_if(ini_errobj_no_more_msgs(errobj));
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg, "Rule 'rule/generate_error' has no validator.");
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ini_rules_destroy(rules_obj);
ini_config_destroy(cfg_obj);
}
END_TEST
START_TEST(test_unknown_validator)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
char input_rules[] =
"[rule/always_succeed]\n"
"validator = nonexistent_validator\n";
char input_cfg[] =
"[section]\n"
"# Content of this file should not matter\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate exactly one error */
fail_if(ini_errobj_no_more_msgs(errobj));
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
static int custom_noerror(const char *rule_name,
struct ini_cfgobj *rules_obj,
struct ini_cfgobj *config_obj,
struct ini_errobj *errobj,
void **data)
{
return 0;
}
static int custom_error(const char *rule_name,
struct ini_cfgobj *rules_obj,
struct ini_cfgobj *config_obj,
struct ini_errobj *errobj,
void **data)
{
return ini_errobj_add_msg(errobj, "Error");
}
START_TEST(test_custom_noerror)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
struct ini_validator *noerror[] = {
&(struct ini_validator){ "custom_noerror", custom_noerror, NULL },
NULL
};
struct ini_validator *missing_name[] = {
&(struct ini_validator){ NULL, custom_noerror, NULL },
&(struct ini_validator){ "custom_noerror", custom_noerror, NULL },
NULL
};
char input_rules[] =
"[rule/custom_succeed]\n"
"validator = custom_noerror\n";
char input_cfg[] =
"[section]\n"
"# Content of this file should not matter\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
/* Pass the custom validator to ini_rules_check() */
ret = ini_rules_check(rules_obj, cfg_obj, noerror, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate no errors */
fail_unless(ini_errobj_no_more_msgs(errobj));
/* Pass wrong external validator to ini_rules_check() */
/* It should be skipped */
ret = ini_rules_check(rules_obj, cfg_obj, missing_name, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate no errors */
fail_unless(ini_errobj_no_more_msgs(errobj), "%s", ini_errobj_get_msg(errobj));
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
START_TEST(test_custom_error)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
struct ini_validator *error[] = {
&(struct ini_validator){ "custom_error", custom_error, NULL },
NULL
};
struct ini_validator *missing_function[] = {
&(struct ini_validator){ "custom_noerror", NULL, NULL },
NULL
};
const char *errmsg;
char input_rules[] =
"[rule/custom_error]\n"
"validator = custom_error\n";
char input_cfg[] =
"[section]\n"
"# Content of this file should not matter\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
/* Pass the custom validator to ini_rules_check() */
ret = ini_rules_check(rules_obj, cfg_obj, error, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate one error */
fail_if(ini_errobj_no_more_msgs(errobj));
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg, "[rule/custom_error]: Error");
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
/* Pass the custom validator to ini_rules_check() */
ret = ini_rules_check(rules_obj, cfg_obj, missing_function, errobj);
/* Should generate one error for missing validator */
fail_if(ini_errobj_no_more_msgs(errobj));
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg,
"Rule 'rule/custom_error' uses unknown validator "
"'custom_error'.");
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ini_rules_destroy(rules_obj);
ini_config_destroy(cfg_obj);
}
END_TEST
START_TEST(test_ini_allowed_options_ok)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
/* Only bar and baz are allowed for foo section */
char input_rules[] =
"[rule/options_for_foo]\n"
"validator = ini_allowed_options\n"
"section_re = ^foo$\n"
"option = bar\n"
"option = baz\n";
/* Should check only foo section, other sections are
* irrelevant and can contain any option */
char input_cfg[] =
"[foo]\n"
"bar = 0\n"
"baz = 0\n"
"[oof]\n"
"opt1 = 1\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate no errors */
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
START_TEST(test_ini_allowed_options_no_section)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
size_t num_err;
const char *errmsg;
/* Ommit section_re to generate error */
char input_rules[] =
"[rule/options_for_foo]\n"
"validator = ini_allowed_options\n"
/* "section_re = ^foo$\n" */
"option = bar\n"
"option = baz\n";
/* section_re without value */
char input_rules2[] =
"[rule/options_for_foo]\n"
"validator = ini_allowed_options\n"
"section_re = \n"
"option = bar\n"
"option = baz\n";
/* Make 4 typos */
char input_cfg[] =
"[foo]\n"
"bar = 0\n"
"baz = 0\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate 2 errors (one from rules_check and one
* from the validator itself) */
fail_if(ini_errobj_no_more_msgs(errobj));
num_err = ini_errobj_count(errobj);
fail_unless(num_err == 2, "Expected 2 errors, got %d", num_err);
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg,
"Rule 'rule/options_for_foo' returned error code '22'");
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg,
"[rule/options_for_foo]: Validator misses 'section_re' "
"parameter");
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ini_rules_destroy(rules_obj);
/* the second test with missing value for section_re */
create_rules_from_str(input_rules2, &rules_obj);
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate 2 errors (one from rules_check and one
* from the validator itself) */
fail_if(ini_errobj_no_more_msgs(errobj));
num_err = ini_errobj_count(errobj);
fail_unless(num_err == 2, "Expected 2 errors, got %d", num_err);
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg,
"Rule 'rule/options_for_foo' returned error code '22'");
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg,
"[rule/options_for_foo]: Validator misses 'section_re' "
"parameter");
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ini_rules_destroy(rules_obj);
ini_config_destroy(cfg_obj);
}
END_TEST
START_TEST(test_ini_allowed_options_wrong_regex)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
size_t num_err;
const char *errmsg;
/* Ommit section_re to generate error */
char input_rules[] =
"[rule/options_for_foo]\n"
"validator = ini_allowed_options\n"
"section_re = ^foo[$\n"
"option = bar\n"
"option = baz\n";
/* Make 4 typos */
char input_cfg[] =
"[foo]\n"
"bar = 0\n"
"baz = 0\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate 2 errors (one from rules_check and one
* from the validator itself) */
fail_if(ini_errobj_no_more_msgs(errobj));
num_err = ini_errobj_count(errobj);
fail_unless(num_err == 2, "Expected 2 errors, got %d", num_err);
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg,
"Rule 'rule/options_for_foo' returned error code '22'");
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
/* Different versions of libc produce slightly different error strings
* in this case. For simplicity compare against all of them. */
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg,
"[rule/options_for_foo]: Cannot compile regular expression "
"from option 'section_re'. "
"Error: 'Unmatched [ or [^'");
if (ret != 0) {
ret = strcmp(errmsg,
"[rule/options_for_foo]: Cannot compile regular "
"expression from option 'section_re'. "
"Error: 'brackets ([ ]) not balanced'");
}
if (ret != 0) {
ret = strcmp(errmsg,
"[rule/options_for_foo]: Cannot compile regular "
"expression from option 'section_re'. "
"Error: 'Unmatched [, [^, [:, [., or [='");
}
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
START_TEST(test_ini_allowed_options_typos)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
size_t num_err;
/* Only bar and baz are allowed for foo section */
char input_rules[] =
"[rule/options_for_foo]\n"
"validator = ini_allowed_options\n"
"section_re = ^foo$\n"
"option = bar\n"
"option = baz\n";
/* Make 4 typos */
char input_cfg[] =
"[foo]\n"
"br = 0\n"
"bra = 0\n"
"abr = 0\n"
"abz = 0\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate 4 errors */
fail_if(ini_errobj_no_more_msgs(errobj));
num_err = ini_errobj_count(errobj);
fail_unless(num_err == 4, "Expected 4 errors, got %d", num_err);
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
START_TEST(test_ini_allowed_sections_str_ok)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
/* Only bar and baz are allowed for foo section */
char input_rules[] =
"[rule/section_list]\n"
"validator = ini_allowed_sections\n"
"section = foo\n"
"section = bar\n";
/* Make 4 typos */
char input_cfg[] =
"[foo]\n"
"br = 0\n"
"bra = 0\n"
"[bar]\n"
"abz = 0\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate 0 errors */
fail_unless(ini_errobj_no_more_msgs(errobj),
"Unexpected errors found: [%s]", ini_errobj_get_msg(errobj));
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
START_TEST(test_ini_allowed_sections_str_typos)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int num_err;
int ret;
/* Only bar and baz are allowed for foo section */
char input_rules[] =
"[rule/section_list]\n"
"validator = ini_allowed_sections\n"
"section = foo\n"
"section = bar\n";
/* Make 4 typos */
char input_cfg[] =
"[fooo]\n"
"br = 0\n"
"bra = 0\n"
"[baar]\n"
"abz = 0\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate 2 errors */
fail_if(ini_errobj_no_more_msgs(errobj),
"Expected 2 errors but none found");
num_err = ini_errobj_count(errobj);
fail_unless(num_err == 2, "Expected 2 errors, got %d", num_err);
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
START_TEST(test_ini_allowed_sections_str_insensitive)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
int i;
/* Only bar and baz are allowed for foo section */
char input_rules_template[] =
"[rule/section_list]\n"
"validator = ini_allowed_sections\n"
"case_insensitive = %s\n"
"section = foo\n"
"section = bar\n";
char input_rules[sizeof(input_rules_template) + 10];
const char *case_insensitive_values[] = { "yes", "Yes", "true", "True",
"1", NULL };
/* Make 4 typos */
char input_cfg[] =
"[FOo]\n"
"br = 0\n"
"bra = 0\n"
"[baR]\n"
"abz = 0\n";
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
for (i = 0; case_insensitive_values[i] != NULL; i++) {
sprintf(input_rules, input_rules_template, case_insensitive_values[i]);
create_rules_from_str(input_rules, &rules_obj);
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0,
"ini_errobj_create() failed for case_insensitive = %s: %s",
case_insensitive_values[i], strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0,
"ini_rules_check() failed for case_insensitive = %s: %s",
case_insensitive_values[i], strerror(ret));
/* Should generate 0 errors */
fail_unless(ini_errobj_no_more_msgs(errobj),
"Unexpected errors found for case_insensitive = %s: [%s]",
case_insensitive_values[i], ini_errobj_get_msg(errobj));
ini_errobj_destroy(&errobj);
ini_rules_destroy(rules_obj);
}
ini_config_destroy(cfg_obj);
}
END_TEST
START_TEST(test_ini_allowed_sections_re_ok)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
char input_rules[] =
"[rule/section_list]\n"
"validator = ini_allowed_sections\n"
"section_re = ^foo*$\n"
"section_re = bar\n";
char input_cfg[] =
"[foooooooooooo]\n"
"br = 0\n"
"bra = 0\n"
"[my_bar]\n"
"abz = 0\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate 0 errors */
fail_unless(ini_errobj_no_more_msgs(errobj), "Unexpected errors found");
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
START_TEST(test_ini_allowed_sections_re_typos)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int num_err;
int ret;
char input_rules[] =
"[rule/section_list]\n"
"validator = ini_allowed_sections\n"
"section_re = ^foo*$\n"
"section_re = bar\n";
/* Make 4 typos */
char input_cfg[] =
"[fooooooOooooo]\n"
"br = 0\n"
"bra = 0\n"
"[my_bra]\n"
"abz = 0\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate 2 errors */
fail_if(ini_errobj_no_more_msgs(errobj),
"Expected 2 errors but none found");
num_err = ini_errobj_count(errobj);
fail_unless(num_err == 2, "Expected 2 errors, got %d", num_err);
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
START_TEST(test_ini_allowed_sections_re_insensitive)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int ret;
/* Only bar and baz are allowed for foo section */
char input_rules[] =
"[rule/section_list]\n"
"validator = ini_allowed_sections\n"
"case_insensitive = yes\n"
"section_re = ^foo*$\n"
"section_re = bar\n";
/* Make 4 typos */
char input_cfg[] =
"[FOoOoOoOoOOOOooo]\n"
"br = 0\n"
"bra = 0\n"
"[my_Bar]\n"
"abz = 0\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate 0 errors */
fail_unless(ini_errobj_no_more_msgs(errobj), "Unexpected errors found");
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
START_TEST(test_ini_allowed_sections_missing_section)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int num_err;
int ret;
const char *errmsg;
/* Only bar and baz are allowed for foo section */
char input_rules[] =
"[rule/section_list]\n"
"validator = ini_allowed_sections\n";
/* Make 4 typos */
char input_cfg[] =
"[fooo]\n"
"br = 0\n"
"bra = 0\n"
"[baar]\n"
"abz = 0\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate 1 errors */
fail_if(ini_errobj_no_more_msgs(errobj),
"Expected 1 errors but none found");
num_err = ini_errobj_count(errobj);
fail_unless(num_err == 1, "Expected 1 errors, got %d", num_err);
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg,
"[rule/section_list]: No allowed sections specified. "
"Use 'section = default' to allow only default section");
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
START_TEST(test_ini_allowed_sections_wrong_regex)
{
struct ini_cfgobj *rules_obj;
struct ini_cfgobj *cfg_obj;
struct ini_errobj *errobj;
int num_err;
int ret;
const char *errmsg;
/* Only bar and baz are allowed for foo section */
char input_rules[] =
"[rule/section_list]\n"
"validator = ini_allowed_sections\n"
"section_re = ^foo\\(*$\n";
/* Make 4 typos */
char input_cfg[] =
"[fooo]\n"
"br = 0\n"
"bra = 0\n"
"[baar]\n"
"abz = 0\n";
create_rules_from_str(input_rules, &rules_obj);
cfg_obj = get_ini_config_from_str(input_cfg, sizeof(input_cfg));
ret = ini_errobj_create(&errobj);
fail_unless(ret == 0, "ini_errobj_create() failed: %s", strerror(ret));
ret = ini_rules_check(rules_obj, cfg_obj, NULL, errobj);
fail_unless(ret == 0, "ini_rules_check() failed: %s", strerror(ret));
/* Should generate 2 errors */
fail_if(ini_errobj_no_more_msgs(errobj),
"Expected 2 errors but none found");
num_err = ini_errobj_count(errobj);
fail_unless(num_err == 2, "Expected 2 errors, got %d", num_err);
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg,
"Rule 'rule/section_list' returned error code '22'");
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg,
"[rule/section_list]: Validator failed to use regex "
"[^foo\\(*$]:[Unmatched ( or \\(]");
if (ret !=0) {
ret = strcmp(errmsg,
"[rule/section_list]: Validator failed to use regex "
"[^foo\\(*$]:[parentheses not balanced]");
}
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
fail_unless(ini_errobj_no_more_msgs(errobj));
ini_errobj_destroy(&errobj);
ini_config_destroy(cfg_obj);
ini_rules_destroy(rules_obj);
}
END_TEST
static Suite *ini_validators_utils_suite(void)
{
Suite *s = suite_create("ini_validators");
TCase *tc_infrastructure = tcase_create("infrastructure");
tcase_add_test(tc_infrastructure, test_ini_errobj);
tcase_add_test(tc_infrastructure, test_ini_noerror);
tcase_add_test(tc_infrastructure, test_ini_error);
tcase_add_test(tc_infrastructure, test_unknown_validator);
tcase_add_test(tc_infrastructure, test_custom_noerror);
tcase_add_test(tc_infrastructure, test_custom_error);
TCase *tc_allowed_options = tcase_create("ini_allowed_options");
tcase_add_test(tc_allowed_options, test_ini_allowed_options_ok);
tcase_add_test(tc_allowed_options, test_ini_allowed_options_no_section);
tcase_add_test(tc_allowed_options, test_ini_allowed_options_wrong_regex);
tcase_add_test(tc_allowed_options, test_ini_allowed_options_typos);
TCase *tc_allowed_sections = tcase_create("ini_allowed_sections");
tcase_add_test(tc_allowed_sections, test_ini_allowed_sections_str_ok);
tcase_add_test(tc_allowed_sections, test_ini_allowed_sections_str_typos);
tcase_add_test(tc_allowed_sections,
test_ini_allowed_sections_str_insensitive);
tcase_add_test(tc_allowed_sections, test_ini_allowed_sections_re_ok);
tcase_add_test(tc_allowed_sections, test_ini_allowed_sections_re_typos);
tcase_add_test(tc_allowed_sections,
test_ini_allowed_sections_re_insensitive);
tcase_add_test(tc_allowed_sections,
test_ini_allowed_sections_missing_section);
tcase_add_test(tc_allowed_sections, test_ini_allowed_sections_wrong_regex);
suite_add_tcase(s, tc_infrastructure);
suite_add_tcase(s, tc_allowed_options);
suite_add_tcase(s, tc_allowed_sections);
return s;
}
int main(void)
{
int number_failed;
Suite *s = ini_validators_utils_suite();
SRunner *sr = srunner_create(s);
/* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
srunner_run_all(sr, CK_ENV);
number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}