1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-26 21:57:41 +03:00

ctdb-common: Add config file parsing code

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
This commit is contained in:
Amitay Isaacs 2017-12-13 19:41:16 +11:00 committed by Martin Schwenke
parent 77539b479e
commit 702504118f
5 changed files with 2319 additions and 2 deletions

1259
ctdb/common/conf.c Normal file

File diff suppressed because it is too large Load Diff

473
ctdb/common/conf.h Normal file
View File

@ -0,0 +1,473 @@
/*
Configuration file handling on top of tini
Copyright (C) Amitay Isaacs 2017
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CTDB_CONF_H__
#define __CTDB_CONF_H__
#include <stdio.h>
#include <stdbool.h>
#include <talloc.h>
/**
* @file conf.h
*
* @brief Configuration file handling with sections and key-value pairs
*
* CTDB settings can be written in a configuration file ctdb.conf (similar to
* samba's smb.conf). Various daemons and tools will consult the configuration
* file for runtime settings.
*
* The configuration will be organized in sections depending on various
* components. Each section will have various configuration options in the form
* of key-value pairs.
*
* [section1]
* key1 = value1
* ...
*
* [section2]
* key2 = value2
* ...
*
* ...
*
*/
/**
* @brief Abstract data structure holding the configuration options
*/
struct conf_context;
/**
* @brief configuration option update mode
*
* When a value of configuration option is changed, update mode is set
* appropriately.
*
* CONF_MODE_API - value modified using set functions
* CONF_MODE_LOAD - value modified via conf_load
* CONF_MODE_RELOAD - value modified via conf_reload
*/
enum conf_update_mode {
CONF_MODE_API,
CONF_MODE_LOAD,
CONF_MODE_RELOAD,
};
/**
* @brief configuration option type
*/
enum conf_type {
CONF_STRING,
CONF_INTEGER,
CONF_BOOLEAN,
};
/**
* @brief Configuration section validation function
*
* Check if all the configuration options are consistent with each-other
*/
typedef bool (*conf_validate_section_fn)(struct conf_context *conf,
const char *section,
enum conf_update_mode mode);
/**
* @brief Configuration option validation function for string
*
* Check if a configuration option value is valid
*/
typedef bool (*conf_validate_string_option_fn)(const char *key,
const char *old_value,
const char *new_value,
enum conf_update_mode mode);
/**
* @brief Configuration option validation function for integer
*
* Check if a configuration option value is valid
*/
typedef bool (*conf_validate_integer_option_fn)(const char *key,
int old_value,
int new_value,
enum conf_update_mode mode);
/**
* @brief Configuration option validation function for boolean
*
* Check if a configuration option value is valid
*/
typedef bool (*conf_validate_boolean_option_fn)(const char *key,
bool old_value,
bool new_value,
enum conf_update_mode mode);
/**
* @brief Initialize configuration option database
*
* This return a new configuration options context. Freeing this context will
* free up all the memory associated with the configuration options.
*
* @param[in] mem_ctx Talloc memory context
* @param[in] result The new configuration options context
* @return 0 on success, errno on failure
*/
int conf_init(TALLOC_CTX *mem_ctx, struct conf_context **result);
/**
* @brief Define a section for organizing configuration options
*
* This functions creates a section to organize configuration option. The
* section names are case-insensitive and are always stored in lower case.
*
* @param[in] conf The configuration options context
* @param[in] section The name of the section
* @param[in] validate The validation function for configuration options
*/
void conf_define_section(struct conf_context *conf,
const char *section,
conf_validate_section_fn validate);
/**
* @brief Define a configuration option which has a string value
*
* This functions adds a new configuration option organized under a given
* section. Configuration options are case-insensitive and are always stored
* in lower case.
*
* @param[in] conf The configuration options context
* @param[in] section The name of the section
* @param[in] key The name of the configuration option
* @param[in] default_value The default value for the configuration option
* @param[in] validate The validation function for the configuration option
*/
void conf_define_string(struct conf_context *conf,
const char *section,
const char *key,
const char *default_value,
conf_validate_string_option_fn validate);
/**
* @brief Define a configuration option which has an integer value
*
* This functions adds a new configuration option organized under a given
* section. Configuration options are case-insensitive and are always stored
* in lower case.
*
* @param[in] conf The configuration options context
* @param[in] section The name of the section
* @param[in] key The name of the configuration option
* @param[in] default_value The default value for the configuration option
* @param[in] validate The validation function for the configuration option
*/
void conf_define_integer(struct conf_context *conf,
const char *section,
const char *key,
const int default_value,
conf_validate_integer_option_fn validate);
/**
* @brief Define a configuration option which has an boolean value
*
* This functions adds a new configuration option organized under a given
* section. Configuration options are case-insensitive and are always stored
* in lower case.
*
* @param[in] conf The configuration options context
* @param[in] section The name of the section
* @param[in] key The name of the configuration option
* @param[in] default_value The default value for the configuration option
* @param[in] validate The validation function for the configuration option
*/
void conf_define_boolean(struct conf_context *conf,
const char *section,
const char *key,
const bool default_value,
conf_validate_boolean_option_fn validate);
/**
* @brief Assign user-accessible pointer for string option
*
* This pointer can be used for accessing the value of configuration option
* directly without requiring a function call.
*
* @param[in] conf The configuration options context
* @param[in] section The name of the section
* @param[in] key The name of the configuration option
* @param[in] ptr User-accessible pointer to the value
*/
void conf_assign_string_pointer(struct conf_context *conf,
const char *section,
const char *key,
const char **ptr);
/**
* @brief Assign user-accessible pointer for integer option
*
* This pointer can be used for accessing the value of configuration option
* directly without requiring a function call.
*
* @param[in] conf The configuration options context
* @param[in] section The name of the section
* @param[in] key The name of the configuration option
* @param[in] ptr User-accessible pointer to the value
*/
void conf_assign_integer_pointer(struct conf_context *conf,
const char *section,
const char *key,
int *ptr);
/**
* @brief Assign user-accessible pointer for boolean option
*
* This pointer can be used for accessing the value of configuration option
* directly without requiring a function call.
*
* @param[in] conf The configuration options context
* @param[in] section The name of the section
* @param[in] key The name of the configuration option
* @param[in] ptr User-accessible pointer to the value
* @return true on success, false on failure
*/
void conf_assign_boolean_pointer(struct conf_context *conf,
const char *section,
const char *key,
bool *ptr);
/**
* @brief Query a configuration option
*
* This function checks if a configuration option is defined or not.
*
* @param[in] conf The configuration options context
* @param[in] section The name of the section
* @param[in] key The name of the configuration option
* @param[out] type The type of the configuration option
* @return true on success, false if section/option is not defined
*/
bool conf_query(struct conf_context *conf,
const char *section,
const char *key,
enum conf_type *type);
/**
* @brief Check if the defined configuration options are valid
*
* This function must be called after creating configuration options
* to confirm that all the option definitions are valid.
*
* @param[in] conf The configuration options context
* @return true on success, false on failure
*/
bool conf_valid(struct conf_context *conf);
/**
* @brief Set the default values for all configuration options
*
* This function resets all the configuration options to their default values.
*
* @param[in] conf The connfiguration options context
*/
void conf_set_defaults(struct conf_context *conf);
/**
* @brief Load the values for configuration option values from a file
*
* This function will update the values of the configuration options from those
* specified in a file. This function will fail in case it encounters an
* undefined option. Any sections which are not defined, will be ignored.
*
* This function will call validation function (if specified) before updating
* the value of a configuration option. After updating all the values for a
* section, the validation for section (if specified) will be called. If any
* of the validation functions return error, then all the configuration
* options will be reset to their previous values.
*
* @param[in] conf The configuration options context
* @param[in] filename The configuration file
* @param[in] skip_unknown Whether unknown config options should be ignored
* @return 0 on success, errno on failure
*/
int conf_load(struct conf_context *conf,
const char *filename,
bool ignore_unknown);
/**
* @brief Reload the values for configuration options
*
* This function will re-load the values of the configuration options. This
* function can be called only after succesful call to conf_load().
*
* @see conf_load
*
* @param[in] conf The configuration options context
* @return 0 on success, errno on failure.
*/
int conf_reload(struct conf_context *conf);
/**
* @brief Set the string value of a configuration option
*
* This function can be used to update the value of a configuration option.
* This will call the validation function for that option (if defined) and
* the section validation function (if defined).
*
* If a user-defined storage pointer is provided, then the value of a
* configuration option should not be changed via that pointer.
*
* @param[in] conf The configuration options context
* @param[in] section The name of a section
* @param[in] key The name of a configuration option
* @param[in] str_val The string value
* @return 0 on success, errno in case of failure
*/
int conf_set_string(struct conf_context *conf,
const char *section,
const char *key,
const char *str_val);
/**
* @brief Set the integer value of a configuration option
*
* This function can be used to update the value of a configuration option.
* This will call the validation function for that option (if defined) and
* the section validation function (if defined).
*
* If a user-defined storage pointer is provided, then the value of a
* configuration option should not be changed via that pointer.
*
* @param[in] conf The configuration options context
* @param[in] section The name of a section
* @param[in] key The name of a configuration option
* @param[in] int_val The integer value
* @return 0 on success, errno in case of failure
*/
int conf_set_integer(struct conf_context *conf,
const char *section,
const char *key,
int int_val);
/**
* @brief Set the boolean value of a configuration option
*
* This function can be used to update the value of a configuration option.
* This will call the validation function for that option (if defined) and
* the section validation function (if defined).
*
* If a user-defined storage pointer is provided, then the value of a
* configuration option should not be changed via that pointer.
*
* @param[in] conf The configuration options context
* @param[in] section The name of a section
* @param[in] key The name of a configuration option
* @param[in] bool_val The boolean value
* @return 0 on success, errno in case of failure
*/
int conf_set_boolean(struct conf_context *conf,
const char *section,
const char *key,
bool bool_val);
/**
* @brief Get the string value of a configuration option
*
* This function can be used to fetch the current value of a configuration
* option.
*
* If a user-defined storage pointer is provided, then the value of a
* configuration option can be accessed directly via that pointer.
*
* @param[in] conf The configuration options context
* @param[in] section The name of a section
* @param[in] key The name of a configuration option
* @param[out] str_val The string value of the configuration option
* @param[out] is_default True if the value is default value
* @return 0 on success, errno in case of failure
*/
int conf_get_string(struct conf_context *conf,
const char *section,
const char *key,
const char **str_val,
bool *is_default);
/**
* @brief Get the integer value of a configuration option
*
* This function can be used to fetch the current value of a configuration
* option.
*
* If a user-defined storage pointer is provided, then the value of a
* configuration option can be accessed directly via that pointer.
*
* @param[in] conf The configuration options context
* @param[in] section The name of a section
* @param[in] key The name of a configuration option
* @param[out] int_val The integer value of the configuration option
* @param[out] is_default True if the value is default value
* @return 0 on success, errno in case of failure
*/
int conf_get_integer(struct conf_context *conf,
const char *section,
const char *key,
int *int_val,
bool *is_default);
/**
* @brief Get the boolean value of a configuration option
*
* This function can be used to fetch the current value of a configuration
* option.
*
* If a user-defined storage pointer is provided, then the value of a
* configuration option can be accessed directly via that pointer.
*
* @param[in] conf The configuration options context
* @param[in] section The name of a section
* @param[in] key The name of a configuration option
* @param[out] bool_val The boolean value of the configuration option
* @param[out] is_default True if the value is default value
* @return 0 on success, errno in case of failure
*/
int conf_get_boolean(struct conf_context *conf,
const char *section,
const char *key,
bool *bool_val,
bool *is_default);
/**
* @brief Dump the configuration in a file
*
* All the configuration options are dumped with their current values.
* If an option has a default value, then it is commented.
*
* Here is a sample output:
*
* [section1]
* key1 = value1
* key2 = value2
* # key3 = default_value3
* [section2]
* key4 = value4
*
* @param[in] conf The configuration options context
* @param[in] fp File pointer
*/
void conf_dump(struct conf_context *conf, FILE *fp);
#endif /* __CTDB_CONF_H__ */

124
ctdb/tests/cunit/conf_test_001.sh Executable file
View File

@ -0,0 +1,124 @@
#!/bin/sh
. "${TEST_SCRIPTS_DIR}/unit.sh"
conffile="${TEST_VAR_DIR}/config.$$"
remove_files ()
{
rm -f "$conffile"
}
test_cleanup remove_files
ok_null
unit_test conf_test 1
ok <<EOF
conf: unknown section [section1]
EOF
unit_test conf_test 2
ok <<EOF
conf: option "key1" already exists
EOF
unit_test conf_test 3
ok <<EOF
conf: option "key1" already exists
EOF
unit_test conf_test 4
ok_null
unit_test conf_test 5
ok_null
unit_test conf_test 6
ok <<EOF
conf: validation for option "key1" failed
conf: validation for option "key2" failed
conf: validation for option "key3" failed
EOF
unit_test conf_test 7
cat > "$conffile" <<EOF
[section1]
EOF
required_result 22 <<EOF
conf: validation for section [section1] failed
[section1]
# key1 = default
EOF
unit_test conf_test 8 "$conffile"
cat > "$conffile" <<EOF
[section1]
key1 = unknown
EOF
required_result 22 <<EOF
conf: validation for section [section1] failed
[section1]
# key1 = default
EOF
unit_test conf_test 8 "$conffile"
cat > "$conffile" <<EOF
[section1]
key1 = value2
key2 = 20 # comment
key3 = false
EOF
ok <<EOF
[section1]
key1 = value2
key2 = 20
key3 = false
EOF
unit_test conf_test 9 "$conffile"
cat > "$conffile" <<EOF
[section1]
key1 = value2
EOF
ok <<EOF
[section1]
key1 = value2
# key2 = 10
key3 = false # temporary
EOF
unit_test conf_test 9 "$conffile"
cat > "$conffile" <<EOF
[section2]
foo = bar
EOF
required_result 22 <<EOF
conf: unknown section [section2]
[section1]
# key1 = value1
# key2 = 10
key3 = false # temporary
EOF
unit_test conf_test 10 "$conffile"
cat > "$conffile" <<EOF
[section1]
key1 = value2
foo = bar
key2 = 20
EOF
required_result 2 <<EOF
[section1]
# key1 = value1
# key2 = 10
key3 = false # temporary
EOF
unit_test conf_test 10 "$conffile"

460
ctdb/tests/src/conf_test.c Normal file
View File

@ -0,0 +1,460 @@
/*
Configuration file handling on top of tini
Copyright (C) Amitay Isaacs 2017
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "replace.h"
#include <assert.h>
#include "common/conf.c"
static void test1(void)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct conf_context *conf;
int ret;
bool status;
ret = conf_init(mem_ctx, &conf);
assert(ret == 0);
assert(conf != NULL);
conf_define_section(conf, "section1", NULL);
status = conf_valid(conf);
assert(status == true);
conf_define_section(conf, NULL, NULL);
status = conf_valid(conf);
assert(status == false);
talloc_free(mem_ctx);
}
static void test2(void)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct conf_context *conf;
int ret;
bool status;
ret = conf_init(mem_ctx, &conf);
assert(ret == 0);
assert(conf != NULL);
conf_define_string(conf, "section1", "key1", "default", NULL);
status = conf_valid(conf);
assert(status == false);
talloc_free(mem_ctx);
}
static void test3(void)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct conf_context *conf;
int ret;
bool status;
ret = conf_init(mem_ctx, &conf);
assert(ret == 0);
assert(conf != NULL);
conf_define_section(conf, "section1", NULL);
status = conf_valid(conf);
assert(status == true);
conf_define_string(conf, "section1", "key1", NULL, NULL);
status = conf_valid(conf);
assert(status == true);
conf_define_string(conf, "section1", "key1", "value1", NULL);
status = conf_valid(conf);
assert(status == false);
talloc_free(mem_ctx);
}
static void test4(void)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct conf_context *conf;
int ret;
bool status;
ret = conf_init(mem_ctx, &conf);
assert(ret == 0);
assert(conf != NULL);
conf_define_section(conf, "section1", NULL);
status = conf_valid(conf);
assert(status == true);
conf_define_string(conf, "section1", "key1", NULL, NULL);
status = conf_valid(conf);
assert(status == true);
conf_define_integer(conf, "section1", "key1", 10, NULL);
status = conf_valid(conf);
assert(status == false);
talloc_free(mem_ctx);
}
static void test5(void)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct conf_context *conf;
enum conf_type type;
int ret;
bool status;
const char *s_val;
int i_val;
bool b_val;
ret = conf_init(mem_ctx, &conf);
assert(ret == 0);
assert(conf != NULL);
conf_define_section(conf, "section1", NULL);
status = conf_valid(conf);
assert(status == true);
conf_define_string(conf, "section1", "key1", "value1", NULL);
conf_define_integer(conf, "section1", "key2", 10, NULL);
conf_define_boolean(conf, "section1", "key3", true, NULL);
conf_assign_string_pointer(conf, "section1", "key1", &s_val);
conf_assign_integer_pointer(conf, "section1", "key2", &i_val);
conf_assign_boolean_pointer(conf, "section1", "key3", &b_val);
status = conf_valid(conf);
assert(status == true);
status = conf_query(conf, "section1", "key1", &type);
assert(status == true);
assert(type == CONF_STRING);
status = conf_query(conf, "section1", "key2", &type);
assert(status == true);
assert(type == CONF_INTEGER);
status = conf_query(conf, "section1", "key3", &type);
assert(status == true);
assert(type == CONF_BOOLEAN);
assert(strcmp(s_val, "value1") == 0);
assert(i_val == 10);
assert(b_val == true);
conf_set_defaults(conf);
assert(strcmp(s_val, "value1") == 0);
assert(i_val == 10);
assert(b_val == true);
talloc_free(mem_ctx);
}
static void test6(void)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct conf_context *conf;
int ret;
bool status;
const char *s_val, *s2_val;
int i_val, i2_val;
bool b_val, b2_val, is_default;
ret = conf_init(mem_ctx, &conf);
assert(ret == 0);
assert(conf != NULL);
conf_define_section(conf, "section1", NULL);
status = conf_valid(conf);
assert(status == true);
conf_define_string(conf, "section1", "key1", "default", NULL);
conf_define_integer(conf, "section1", "key2", 10, NULL);
conf_define_boolean(conf, "section1", "key3", true, NULL);
conf_assign_string_pointer(conf, "section1", "key1", &s_val);
conf_assign_integer_pointer(conf, "section1", "key2", &i_val);
conf_assign_boolean_pointer(conf, "section1", "key3", &b_val);
status = conf_valid(conf);
assert(status == true);
is_default = false;
ret = conf_get_string(conf, "section1", "key1", &s2_val, &is_default);
assert(ret == 0);
assert(strcmp(s2_val, "default") == 0);
assert(is_default == true);
is_default = false;
ret = conf_get_integer(conf, "section1", "key2", &i2_val, &is_default);
assert(ret == 0);
assert(i2_val == 10);
assert(is_default == true);
is_default = false;
ret = conf_get_boolean(conf, "section1", "key3", &b2_val, &is_default);
assert(ret == 0);
assert(b2_val == true);
assert(is_default == true);
ret = conf_set_string(conf, "section1", "key1", "foobar");
assert(ret == 0);
ret = conf_set_integer(conf, "section1", "key2", 20);
assert(ret == 0);
ret = conf_set_boolean(conf, "section1", "key3", false);
assert(ret == 0);
assert(strcmp(s_val, "foobar") == 0);
assert(i_val == 20);
assert(b_val == false);
is_default = true;
ret = conf_get_string(conf, "section1", "key1", &s2_val, &is_default);
assert(ret == 0);
assert(strcmp(s2_val, "foobar") == 0);
assert(is_default == false);
is_default = true;
ret = conf_get_integer(conf, "section1", "key2", &i2_val, &is_default);
assert(ret == 0);
assert(i2_val == 20);
assert(is_default == false);
is_default = true;
ret = conf_get_boolean(conf, "section1", "key3", &b2_val, &is_default);
assert(ret == 0);
assert(b2_val == false);
assert(is_default == false);
conf_set_defaults(conf);
assert(strcmp(s_val, "default") == 0);
assert(i_val == 10);
assert(b_val == true);
talloc_free(mem_ctx);
}
static bool test7_validate_string(const char *key,
const char *old_value, const char *new_value,
enum conf_update_mode mode)
{
return false;
}
static bool test7_validate_integer(const char *key,
int old_value, int new_value,
enum conf_update_mode mode)
{
return false;
}
static bool test7_validate_boolean(const char *key,
bool old_value, bool new_value,
enum conf_update_mode mode)
{
return false;
}
static void test7(void)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct conf_context *conf;
int ret;
bool status;
const char *s_val, *s2_val;
int i_val, i2_val;
bool b_val, b2_val;
ret = conf_init(mem_ctx, &conf);
assert(ret == 0);
assert(conf != NULL);
conf_define_section(conf, "section1", NULL);
status = conf_valid(conf);
assert(status == true);
conf_define_string(conf, "section1", "key1", "default",
test7_validate_string);
conf_define_integer(conf, "section1", "key2", 10,
test7_validate_integer);
conf_define_boolean(conf, "section1", "key3", true,
test7_validate_boolean);
conf_assign_string_pointer(conf, "section1", "key1", &s_val);
conf_assign_integer_pointer(conf, "section1", "key2", &i_val);
conf_assign_boolean_pointer(conf, "section1", "key3", &b_val);
status = conf_valid(conf);
assert(status == true);
ret = conf_set_string(conf, "section1", "key1", "foobar");
assert(ret == EINVAL);
ret = conf_set_integer(conf, "section1", "key2", 20);
assert(ret == EINVAL);
ret = conf_set_boolean(conf, "section1", "key3", false);
assert(ret == EINVAL);
assert(strcmp(s_val, "default") == 0);
assert(i_val == 10);
assert(b_val == true);
ret = conf_get_string(conf, "section1", "key2", &s2_val, NULL);
assert(ret == EINVAL);
ret = conf_get_integer(conf, "section1", "key3", &i2_val, NULL);
assert(ret == EINVAL);
ret = conf_get_boolean(conf, "section1", "key1", &b2_val, NULL);
assert(ret == EINVAL);
talloc_free(mem_ctx);
}
static bool test8_validate(struct conf_context *conf,
const char *section,
enum conf_update_mode mode)
{
return false;
}
static void test8(const char *filename)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct conf_context *conf;
int ret;
bool status;
ret = conf_init(mem_ctx, &conf);
assert(ret == 0);
assert(conf != NULL);
conf_define_section(conf, "section1", test8_validate);
status = conf_valid(conf);
assert(status == true);
conf_define_string(conf, "section1", "key1", "default", NULL);
status = conf_valid(conf);
assert(status == true);
ret = conf_load(conf, filename, true);
conf_dump(conf, stdout);
talloc_free(mem_ctx);
exit(ret);
}
static void test9(const char *filename, bool ignore_unknown)
{
TALLOC_CTX *mem_ctx = talloc_new(NULL);
struct conf_context *conf;
int ret;
bool status;
ret = conf_init(mem_ctx, &conf);
assert(ret == 0);
assert(conf != NULL);
conf_define_section(conf, "section1", NULL);
conf_define_string(conf, "section1", "key1", "value1", NULL);
conf_define_integer(conf, "section1", "key2", 10, NULL);
conf_define_boolean(conf, "section1", "key3", true, NULL);
status = conf_valid(conf);
assert(status == true);
conf_set_boolean(conf, "section1", "key3", false);
ret = conf_load(conf, filename, ignore_unknown);
conf_dump(conf, stdout);
talloc_free(mem_ctx);
exit(ret);
}
int main(int argc, const char **argv)
{
int num;
if (argc < 2) {
fprintf(stderr, "Usage: %s <testnum> [<config>]\n", argv[0]);
exit(1);
}
num = atoi(argv[1]);
if (num > 7 && argc != 3) {
fprintf(stderr, "Usage: %s <testnum> [<config>]\n", argv[0]);
exit(1);
}
switch (num) {
case 1:
test1();
break;
case 2:
test2();
break;
case 3:
test3();
break;
case 4:
test4();
break;
case 5:
test5();
break;
case 6:
test6();
break;
case 7:
test7();
break;
case 8:
test8(argv[2]);
break;
case 9:
test9(argv[2], true);
break;
case 10:
test9(argv[2], false);
break;
}
return 0;
}

View File

@ -400,7 +400,7 @@ def build(bld):
pidfile.c run_proc.c
hash_count.c run_event.c
sock_client.c version.c
cmdline.c path.c
cmdline.c path.c conf.c
'''),
deps='''samba-util sys_rw tevent-util
replace talloc tevent tdb popt''')
@ -756,7 +756,8 @@ def build(bld):
'sock_io_test',
'hash_count_test',
'run_event_test',
'cmdline_test'
'cmdline_test',
'conf_test',
]
for target in ctdb_unit_tests: