Enable gating for ding-libs by adding tests

Resolves: RHELMISC-3929
This commit is contained in:
Jakub Vávra 2024-11-04 15:02:03 +01:00
parent 1319809255
commit 288517db7c
17 changed files with 9371 additions and 0 deletions

37
tests/sanity/Makefile Normal file
View File

@ -0,0 +1,37 @@
tests: collection_ut.c collection_queue_ut.c collection_stack_ut.c \
dhash_ut_check.c ini_augment_ut_check.c ini_comment_ut.c \
ini_configmod_ut_check.c ini_parse_ut_check.c \
ini_validators_ut_check.c ini_valueobj_ut.c path_utils_ut.c \
ref_array_ut.c simplebuffer_ut.c
gcc collection_ut.c -lcollection -o collection_ut
gcc collection_queue_ut.c -lcollection -o collection_queue_ut
gcc collection_stack_ut.c -lcollection -o collection_stack_ut
gcc dhash_ut_check.c -ldhash -lcheck -o dhash_ut_check
gcc ini_augment_ut_check.c -lini_config -lcollection -lcheck -lref_array \
-o ini_augment_ut_check
gcc ini_comment_ut.c -lini_config -lcheck -o ini_comment_ut
gcc ini_configmod_ut_check.c -lbasicobjects -lcheck -lini_config \
-o ini_configmod_ut_check
gcc ini_parse_ut_check.c -lcheck -lini_config -o ini_parse_ut_check
gcc ini_validators_ut_check.c -lini_config -lcheck \
-o ini_validators_ut_check
gcc ini_valueobj_ut.c -lini_config -lbasicobjects -o ini_valueobj_ut
gcc path_utils_ut.c -lpath_utils -lcheck -o path_utils_ut
gcc ref_array_ut.c -lref_array -o ref_array_ut
gcc simplebuffer_ut.c -lbasicobjects -o simplebuffer_ut
run: tests
./collection_ut || exit 1
./collection_queue_ut || exit 2
./collection_stack_ut || exit 3
./dhash_ut_check || exit 4
./ini_augment_ut_check || exit 5
./ini_comment_ut || exit 6
./ini_configmod_ut_check || exit 7
./ini_parse_ut_check || exit 8
./ini_validators_ut_check || exit 9
./ini_valueobj_ut || exit 10
./path_utils_ut || exit 11
./ref_array_ut || exit 12
./simplebuffer_ut || exit 13
echo ALL TESTS PASSED

View File

@ -0,0 +1,212 @@
/*
QUEUE INTERFACE
Queue unit test.
Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
Collection 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.
Collection 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 Collection Library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#define TRACE_HOME
#include "trace.h"
#include "collection_queue.h"
#include "collection_tools.h"
typedef int (*test_fn)(void);
int verbose = 0;
#define COLOUT(foo) \
do { \
if (verbose) foo; \
} while(0)
static int queue_test(void)
{
struct collection_item *queue = NULL;
char binary_dump[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
struct collection_item *item = NULL;
int i;
unsigned count;
int error = EOK;
TRACE_FLOW_STRING("queue_test","Entry.");
COLOUT(printf("\n\nQUEUE TEST!!!.\n\n\n"));
if((error = col_create_queue(&queue)) ||
(error = col_enqueue_str_property(queue, "item1","value 1" ,0)) ||
(error = col_enqueue_int_property(queue, "item2", -1)) ||
(error = col_enqueue_unsigned_property(queue, "item3", 1)) ||
(error = col_enqueue_long_property(queue, "item4", 100)) ||
(error = col_enqueue_ulong_property(queue, "item5", 1000)) ||
(error = col_enqueue_double_property(queue, "item6", 1.1)) ||
(error = col_enqueue_bool_property(queue, "item7", 1)) ||
(error = col_enqueue_binary_property(queue, "item8", binary_dump, sizeof(binary_dump)))) {
printf("Failed to enqueue property. Error %d\n", error);
col_destroy_collection(queue);
return error;
}
COLOUT(col_debug_collection(queue,COL_TRAVERSE_DEFAULT));
error = col_get_collection_count(queue, &count);
if (error) {
printf("Failed to get count. Error %d\n", error);
col_destroy_collection(queue);
return error;
}
count--;
COLOUT(printf("Rotate the queue.\n"));
for (i = 0; i < count; i++) {
if ((error = col_dequeue_item(queue, &item)) ||
(error = col_enqueue_item(queue, item))) {
printf("Failed to dequeue or enqueue items. Error %d\n", error);
col_destroy_collection(queue);
return error;
}
COLOUT(col_debug_collection(queue,COL_TRAVERSE_DEFAULT));
}
col_destroy_collection(queue);
TRACE_FLOW_NUMBER("queue_test. Returning", error);
COLOUT(printf("\n\nEND OF QUEUE TEST!!!.\n\n\n"));
return error;
}
static int empty_test(void)
{
struct collection_item *queue = NULL;
struct collection_item *item = NULL;
int i;
unsigned count;
int error = EOK;
TRACE_FLOW_STRING("empty_test","Entry.");
COLOUT(printf("\n\nEMPTY QUEUE TEST!!!.\n\n\n"));
if((error = col_create_queue(&queue)) ||
(error = col_enqueue_str_property(queue, "item1","value 1" ,0)) ||
(error = col_enqueue_int_property(queue, "item2", -1)) ||
(error = col_enqueue_unsigned_property(queue, "item3", 1))) {
printf("Failed to enqueue property. Error %d\n", error);
col_destroy_collection(queue);
return error;
}
COLOUT(col_debug_collection(queue,COL_TRAVERSE_DEFAULT));
error = col_get_collection_count(queue, &count);
if (error) {
printf("Failed to get count. Error %d\n", error);
col_destroy_collection(queue);
return error;
}
count--;
COLOUT(printf("Empty the queue.\n"));
for (i = 0; i < count; i++) {
if ((error = col_dequeue_item(queue, &item))) {
printf("Failed to dequeue or enqueue items. Error %d\n", error);
col_destroy_collection(queue);
return error;
}
col_delete_item(item);
COLOUT(col_debug_collection(queue,COL_TRAVERSE_DEFAULT));
}
COLOUT(printf("Add elements again.\n"));
if((error = col_enqueue_str_property(queue, "item1","value 1" ,0)) ||
(error = col_enqueue_int_property(queue, "item2", -1)) ||
(error = col_enqueue_unsigned_property(queue, "item3", 1))) {
printf("Failed to enqueue property. Error %d\n", error);
col_destroy_collection(queue);
return error;
}
COLOUT(col_debug_collection(queue,COL_TRAVERSE_DEFAULT));
error = col_get_collection_count(queue, &count);
if (error) {
printf("Failed to get count. Error %d\n", error);
col_destroy_collection(queue);
return error;
}
count--;
COLOUT(printf("Empty the queue again.\n"));
for (i = 0; i < count; i++) {
if ((error = col_dequeue_item(queue, &item))) {
printf("Failed to dequeue or enqueue items. Error %d\n", error);
col_destroy_collection(queue);
return error;
}
col_delete_item(item);
COLOUT(col_debug_collection(queue,COL_TRAVERSE_DEFAULT));
}
col_destroy_collection(queue);
TRACE_FLOW_NUMBER("empty_test. Returning", error);
COLOUT(printf("\n\nEND OF QUEUE TEST!!!.\n\n\n"));
return error;
}
/* Main function of the unit test */
int main(int argc, char *argv[])
{
int error = 0;
test_fn tests[] = { queue_test,
empty_test,
NULL };
test_fn t;
int i = 0;
if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = 1;
printf("Start\n");
while ((t = tests[i++])) {
error = t();
if (error) {
printf("Failed!\n");
return error;
}
}
printf("Success!\n");
return 0;
}

View File

@ -0,0 +1,129 @@
/*
STACK INTERFACE
Stack unit test.
Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
Collection 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.
Collection 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 Collection Library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#define TRACE_HOME
#include "trace.h"
#include "collection_stack.h"
#include "collection_tools.h"
typedef int (*test_fn)(void);
int verbose = 0;
#define COLOUT(foo) \
do { \
if (verbose) foo; \
} while(0)
static int stack_test(void)
{
struct collection_item *stack = NULL;
char binary_dump[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
struct collection_item *item1 = NULL;
struct collection_item *item2 = NULL;
int error = EOK;
TRACE_FLOW_STRING("stack_test", "Entry.");
COLOUT(printf("\n\nSTACK TEST!!!.\n\n\n"));
if ((error = col_create_stack(&stack)) ||
(error = col_push_str_property(stack, "item1", "value 1", 0)) ||
(error = col_push_int_property(stack, "item2", -1)) ||
(error = col_push_unsigned_property(stack, "item3", 1)) ||
(error = col_push_long_property(stack, "item4", 100)) ||
(error = col_push_ulong_property(stack, "item5", 1000)) ||
(error = col_push_double_property(stack, "item6", 1.1)) ||
(error = col_push_bool_property(stack, "item7", 1)) ||
(error = col_push_binary_property(stack, "item8", binary_dump, sizeof(binary_dump)))) {
printf("Failed to push property. Error %d\n", error);
col_destroy_collection(stack);
return error;
}
COLOUT(col_debug_collection(stack, COL_TRAVERSE_DEFAULT));
COLOUT(printf("Swapping last two items by popping and pushing them back.\n"));
if ((error = col_pop_item(stack, &item1)) ||
(error = col_pop_item(stack, &item2))) {
printf("Failed to pop items. Error %d\n", error);
col_destroy_collection(stack);
return error;
}
COLOUT(printf("\nPopped two last items.\n"));
COLOUT(col_debug_collection(stack, COL_TRAVERSE_DEFAULT));
COLOUT(printf("\nLast item.\n"));
COLOUT(col_debug_item(item1));
COLOUT(printf("\nPrevious item.\n"));
COLOUT(col_debug_item(item2));
if ((error = col_push_item(stack, item1)) ||
(error = col_push_item(stack, item2))) {
printf("Failed to pop or push items. Error %d\n", error);
col_destroy_collection(stack);
return error;
}
COLOUT(printf("\n\nPushed two items again in reverse order.\n\n"));
COLOUT(col_debug_collection(stack, COL_TRAVERSE_DEFAULT));
col_destroy_collection(stack);
TRACE_FLOW_NUMBER("stack_test. Returning", error);
COLOUT(printf("\n\nEND OF STACK TEST!!!.\n\n"));
return error;
}
/* Main function of the unit test */
int main(int argc, char *argv[])
{
int error = 0;
test_fn tests[] = { stack_test,
NULL };
test_fn t;
int i = 0;
if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = 1;
printf("Start\n");
while ((t = tests[i++])) {
error = t();
if (error) {
printf("Failed!\n");
return error;
}
}
printf("Success!\n");
return 0;
}

2259
tests/sanity/collection_ut.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,224 @@
/*
Authors:
Michal Zidek <mzidek@redhat.com>
Copyright (C) 2016 Red Hat
This program 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.
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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <check.h>
/* #define TRACE_LEVEL 7 */
#define TRACE_HOME
#include "dhash.h"
#define HTABLE_SIZE 128
int verbose = 0;
/* There must be no warnings generated during this test
* without having to cast the key value. */
START_TEST(test_key_const_string)
{
hash_table_t *htable;
int ret;
hash_value_t ret_val;
hash_value_t enter_val1;
hash_value_t enter_val2;
hash_key_t key;
enter_val1.type = HASH_VALUE_INT;
enter_val1.i = 1;
enter_val2.type = HASH_VALUE_INT;
enter_val2.i = 2;
key.type = HASH_KEY_CONST_STRING;
key.c_str = "constant";
ret = hash_create(HTABLE_SIZE, &htable, NULL, NULL);
fail_unless(ret == 0);
/* The table is empty, lookup should return error */
ret = hash_lookup(htable, &key, &ret_val);
fail_unless(ret == HASH_ERROR_KEY_NOT_FOUND);
/* Deleting with non-existing key should return error */
ret = hash_delete(htable, &key);
fail_unless(ret == HASH_ERROR_KEY_NOT_FOUND);
ret = hash_enter(htable, &key, &enter_val1);
fail_unless(ret == 0);
hash_lookup(htable, &key, &ret_val);
fail_unless(ret == 0);
fail_unless(ret_val.i == 1);
/* Overwrite the entry */
ret = hash_enter(htable, &key, &enter_val2);
fail_unless(ret == 0);
hash_lookup(htable, &key, &ret_val);
fail_unless(ret == 0);
fail_unless(ret_val.i == 2);
ret = hash_delete(htable, &key);
fail_unless(ret == 0);
/* Delete again with the same key */
ret = hash_delete(htable, &key);
fail_unless(ret == HASH_ERROR_KEY_NOT_FOUND);
ret = hash_destroy(htable);
fail_unless(ret == 0);
}
END_TEST
START_TEST(test_key_string)
{
hash_table_t *htable;
int ret;
hash_value_t ret_val;
hash_value_t enter_val1;
hash_value_t enter_val2;
hash_key_t key;
char str[] = "non_constant";
enter_val1.type = HASH_VALUE_INT;
enter_val1.i = 1;
enter_val2.type = HASH_VALUE_INT;
enter_val2.i = 2;
key.type = HASH_KEY_STRING;
key.str = str;
ret = hash_create(HTABLE_SIZE, &htable, NULL, NULL);
fail_unless(ret == 0);
/* The table is empty, lookup should return error */
ret = hash_lookup(htable, &key, &ret_val);
fail_unless(ret == HASH_ERROR_KEY_NOT_FOUND);
/* Deleting with non-existing key should return error */
ret = hash_delete(htable, &key);
fail_unless(ret == HASH_ERROR_KEY_NOT_FOUND);
ret = hash_enter(htable, &key, &enter_val1);
fail_unless(ret == 0);
hash_lookup(htable, &key, &ret_val);
fail_unless(ret == 0);
fail_unless(ret_val.i == 1);
/* Overwrite the entry */
ret = hash_enter(htable, &key, &enter_val2);
fail_unless(ret == 0);
hash_lookup(htable, &key, &ret_val);
fail_unless(ret == 0);
fail_unless(ret_val.i == 2);
ret = hash_delete(htable, &key);
fail_unless(ret == 0);
/* Delete again with the same key */
ret = hash_delete(htable, &key);
fail_unless(ret == HASH_ERROR_KEY_NOT_FOUND);
ret = hash_destroy(htable);
fail_unless(ret == 0);
}
END_TEST
START_TEST(test_key_ulong)
{
hash_table_t *htable;
int ret;
hash_value_t ret_val;
hash_value_t enter_val1;
hash_value_t enter_val2;
hash_key_t key;
enter_val1.type = HASH_VALUE_INT;
enter_val1.i = 1;
enter_val2.type = HASH_VALUE_INT;
enter_val2.i = 2;
key.type = HASH_KEY_ULONG;
key.ul = 68ul;
ret = hash_create(HTABLE_SIZE, &htable, NULL, NULL);
fail_unless(ret == 0);
/* The table is empty, lookup should return error */
ret = hash_lookup(htable, &key, &ret_val);
fail_unless(ret == HASH_ERROR_KEY_NOT_FOUND);
/* Deleting with non-existing key should return error */
ret = hash_delete(htable, &key);
fail_unless(ret == HASH_ERROR_KEY_NOT_FOUND);
ret = hash_enter(htable, &key, &enter_val1);
fail_unless(ret == 0);
hash_lookup(htable, &key, &ret_val);
fail_unless(ret == 0);
fail_unless(ret_val.i == 1);
/* Overwrite the entry */
ret = hash_enter(htable, &key, &enter_val2);
fail_unless(ret == 0);
hash_lookup(htable, &key, &ret_val);
fail_unless(ret == 0);
fail_unless(ret_val.i == 2);
ret = hash_delete(htable, &key);
fail_unless(ret == 0);
/* Delete again with the same key */
ret = hash_delete(htable, &key);
fail_unless(ret == HASH_ERROR_KEY_NOT_FOUND);
ret = hash_destroy(htable);
fail_unless(ret == 0);
}
END_TEST
static Suite *dhash_suite(void)
{
Suite *s = suite_create("");
TCase *tc_basic = tcase_create("dhash API tests");
tcase_add_test(tc_basic, test_key_const_string);
tcase_add_test(tc_basic, test_key_string);
tcase_add_test(tc_basic, test_key_ulong);
suite_add_tcase(s, tc_basic);
return s;
}
int main(void)
{
int number_failed;
Suite *s = dhash_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;
}

View File

@ -0,0 +1,3 @@
#!/bin/bash
make run

View File

@ -0,0 +1,341 @@
/*
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 <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";
const 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 = ".";
}
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);
}
END_TEST
START_TEST(test_ini_augment_empty_dir)
{
int ret;
struct ini_cfgobj *ini_cfg;
struct ini_cfgfile *file_ctx;
struct value_obj *vo;
const char *patterns[] = { ".*", NULL };
const char *sections[] = { ".*", NULL };
char **section_list;
char **attrs_list;
struct ini_cfgobj *result_cfg = NULL;
int size;
char empty_dir_path[PATH_MAX] = {0};
const char *builddir;
int32_t val;
char base_cfg[] =
"[section_one]\n"
"one = 1\n";
builddir = getenv("builddir");
if (builddir == NULL) {
builddir = ".";
}
ret = snprintf(empty_dir_path, PATH_MAX, "%s/tmp_empty_dir", builddir);
fail_if(ret > PATH_MAX || ret < 0, "snprintf failed\n");
ret = ini_config_file_from_mem(base_cfg, strlen(base_cfg),
&file_ctx);
fail_unless(ret == EOK, "Failed to load config. Error %d.\n", ret);
ret = ini_config_create(&ini_cfg);
fail_unless(ret == EOK, "Failed to create config. Error %d.\n", ret);
ret = ini_config_parse(file_ctx, INI_STOP_ON_ERROR, INI_MV1S_ALLOW, 0,
ini_cfg);
fail_unless(ret == EOK, "Failed to parse configuration. Error %d.\n", ret);
/* Create an empty directory */
ret = mkdir(empty_dir_path, 0700);
if (ret == -1) {
ret = errno;
fail_if(ret != EEXIST,
"Failed to create empty directory. Error %d.\n", errno);
}
ret = ini_config_augment(ini_cfg,
empty_dir_path,
patterns,
sections,
NULL,
INI_STOP_ON_ANY,
INI_MV1S_OVERWRITE,
INI_PARSE_NOWRAP,
INI_MV2S_OVERWRITE,
&result_cfg,
NULL,
NULL);
fail_unless(ret == EOK);
/* If the snippet directory is empty, result_cfg should be the original
* ini_cfg and not NULL */
fail_if(result_cfg == NULL);
/* Now check if the content of result_cfg is what we expected */
section_list = ini_get_section_list(result_cfg, &size, NULL);
fail_unless(size == 1);
fail_unless(strcmp(section_list[0], "section_one") == 0);
attrs_list = ini_get_attribute_list(result_cfg, section_list[0],
&size, NULL);
fail_unless(size == 1);
fail_unless(strcmp(attrs_list[0], "one") == 0);
ret = ini_get_config_valueobj(section_list[0],
attrs_list[0],
result_cfg,
INI_GET_FIRST_VALUE,
&vo);
fail_unless(ret == 0);
val = ini_get_int32_config_value(vo, 1, 100, NULL);
fail_unless(val == 1, "Expected attribute value not found.\n");
ini_free_attribute_list(attrs_list);
ini_free_section_list(section_list);
ini_config_destroy(result_cfg);
ini_config_destroy(ini_cfg);
ini_config_file_destroy(file_ctx);
remove(empty_dir_path);
}
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);
tcase_add_test(tc_augment, test_ini_augment_empty_dir);
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;
}

View File

@ -0,0 +1,428 @@
/*
INI LIBRARY
Unit test for the comment object.
Copyright (C) Dmitri Pal <dpal@redhat.com> 2010
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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TRACE_HOME
#include "trace.h"
#include "ini_comment.h"
int verbose = 0;
#define INIOUT(foo) \
do { \
if (verbose) foo; \
} while(0)
typedef int (*test_fn)(void);
static int file_test(void)
{
int error = EOK;
struct ini_comment *ic = NULL;
if ((error = ini_comment_create(&ic)) ||
(error = ini_comment_build(ic, ";Line 0")) ||
(error = ini_comment_build(ic, ";Line 1")) ||
(error = ini_comment_build(ic, ";Line 2"))) {
printf("Failed to create comment object %d\n",
error);
ini_comment_destroy(ic);
return error;
}
INIOUT(printf("<==== Comment ====>\n"));
INIOUT(ini_comment_print(ic, stdout));
INIOUT(printf("<=================>\n"));
ini_comment_destroy(ic);
return error;
}
static int construct_test(void)
{
int error = EOK;
struct ini_comment *ic = NULL;
const char *comments[] = { ";Line1", ";Line2", ";Line3", NULL };
error = ini_comment_construct(comments,
0,
&ic);
if (error) {
printf("Failed to create comment object %d\n",
error);
return error;
}
INIOUT(printf("<==== Constructed Comment 1 ====>\n"));
INIOUT(ini_comment_print(ic, stdout));
INIOUT(printf("<=================>\n"));
ini_comment_destroy(ic);
error = ini_comment_construct(comments,
2,
&ic);
if (error) {
printf("Failed to create comment object %d\n",
error);
return error;
}
INIOUT(printf("<==== Constructed Comment 2 ====>\n"));
INIOUT(ini_comment_print(ic, stdout));
INIOUT(printf("<=================>\n"));
ini_comment_destroy(ic);
return error;
}
static int alter_test(void)
{
int error = EOK;
struct ini_comment *ic = NULL;
uint32_t i, num = 0;
char *line = NULL;
const char *expected[] = { ";Line 0 inserted",
";Line 1 inserted",
"",
"",
";Line 3 replaced",
"",
";Line 4" };
if ((error = ini_comment_create(&ic)) ||
(error = ini_comment_build(ic, ";Line 0")) ||
(error = ini_comment_build(ic, NULL)) ||
(error = ini_comment_build(ic, ";Line 2")) ||
(error = ini_comment_build(ic, ";Line 3")) ||
(error = ini_comment_build(ic, ""))) {
printf("Failed to create comment object\n");
ini_comment_destroy(ic);
return error;
}
INIOUT(printf("<==== Comment ====>\n"));
INIOUT(ini_comment_print(ic, stdout));
INIOUT(printf("<=================>\n"));
if ((error = ini_comment_append(ic, ";Line 4")) ||
(error = ini_comment_clear(ic, 2)) ||
(error = ini_comment_replace(ic, 3, ";Line 3 replaced")) ||
(error = ini_comment_remove(ic, 0)) ||
(error = ini_comment_insert(ic, 0, ";Line 0 inserted")) ||
(error = ini_comment_insert(ic, 1, ";Line 1 inserted"))) {
printf("Failed to create comment object\n");
ini_comment_destroy(ic);
return error;
}
INIOUT(printf("<==== Comment ====>\n"));
INIOUT(ini_comment_print(ic, stdout));
INIOUT(printf("<=================>\n"));
error = ini_comment_get_numlines(ic, &num);
if (error) {
printf("Failed to get number of lines.\n");
ini_comment_destroy(ic);
return error;
}
for (i = 0; i < num; i++) {
error = ini_comment_get_line(ic, i, &line, NULL);
if (error) {
printf("Failed to get line.\n");
ini_comment_destroy(ic);
return error;
}
if (strcmp(line, expected[i]) != 0) {
printf("Lines do not match.\n");
printf("GOT: %s\n", line);
printf("EXP: %s\n", expected[i]);
ini_comment_destroy(ic);
return error;
}
}
INIOUT(printf("\n\nSwap test\n\n"));
if ((error = ini_comment_swap(ic, 0 , 6)) ||
(error = ini_comment_swap(ic, 1 , 5)) ||
(error = ini_comment_swap(ic, 2 , 4))) {
printf("Failed to swap lines.\n");
ini_comment_destroy(ic);
return error;
}
for (i = 0; i < num; i++) {
error = ini_comment_get_line(ic, i, &line, NULL);
if (error) {
printf("Failed to get line.\n");
ini_comment_destroy(ic);
return error;
}
if (strcmp(line, expected[6 - i]) != 0) {
printf("Lines do not match.\n");
printf("GOT: %s\n", line);
printf("EXP: %s\n", expected[6 - i]);
ini_comment_destroy(ic);
return error;
}
}
ini_comment_destroy(ic);
return error;
}
static int copy_test(void)
{
int error = EOK;
struct ini_comment *ic = NULL;
struct ini_comment *ic_copy = NULL;
char *line = NULL;
char *line_copy = NULL;
uint32_t i, num = 0;
INIOUT(printf("\n\nCopy test\n\n"));
if ((error = ini_comment_create(&ic)) ||
(error = ini_comment_build(ic, ";Line 0")) ||
(error = ini_comment_build(ic, ";Line 1")) ||
(error = ini_comment_build(ic, ";Line 2"))) {
printf("Failed to create comment object %d\n",
error);
ini_comment_destroy(ic);
return error;
}
INIOUT(printf("<==== Comment ====>\n"));
INIOUT(ini_comment_print(ic, stdout));
INIOUT(printf("<=================>\n"));
if ((error = ini_comment_copy(ic, &ic_copy))) {
printf("Failed to create comment object %d\n",
error);
ini_comment_destroy(ic);
return error;
}
INIOUT(printf("<==== Comment Copy====>\n"));
INIOUT(ini_comment_print(ic_copy, stdout));
INIOUT(printf("<=================>\n"));
error = ini_comment_get_numlines(ic, &num);
if (error) {
printf("Failed to get number of lines.\n");
ini_comment_destroy(ic);
ini_comment_destroy(ic_copy);
return error;
}
for (i = 0; i < num; i++) {
error = ini_comment_get_line(ic, i, &line, NULL);
if (error) {
printf("Failed to get line.\n");
ini_comment_destroy(ic);
ini_comment_destroy(ic_copy);
return error;
}
error = ini_comment_get_line(ic_copy, i, &line_copy, NULL);
if (error) {
printf("Failed to get line.\n");
ini_comment_destroy(ic);
ini_comment_destroy(ic_copy);
return error;
}
if (strcmp(line, line_copy) != 0) {
printf("Lines do not match.\n");
printf("Source: %s\n", line);
printf("Copy: %s\n", line_copy);
ini_comment_destroy(ic);
ini_comment_destroy(ic_copy);
return -1;
}
}
ini_comment_destroy(ic);
ini_comment_destroy(ic_copy);
return error;
}
static int add_test(void)
{
int error = EOK;
struct ini_comment *ic = NULL;
struct ini_comment *ic_to_add = NULL;
struct ini_comment *ic_cmp = NULL;
uint32_t i, num1 = 0, num2 = 0;
char *line1 = NULL;
char *line2 = NULL;
INIOUT(printf("\n\nAdd test\n\n"));
if ((error = ini_comment_create(&ic)) ||
(error = ini_comment_build(ic, ";Line 0")) ||
(error = ini_comment_build(ic, ";Line 1")) ||
(error = ini_comment_build(ic, ";Line 2"))) {
printf("Failed to create comment object %d\n",
error);
ini_comment_destroy(ic);
return error;
}
INIOUT(printf("<==== Comment ====>\n"));
INIOUT(ini_comment_print(ic, stdout));
INIOUT(printf("<=================>\n"));
if ((error = ini_comment_create(&ic_to_add)) ||
(error = ini_comment_build(ic_to_add, ";Line 3")) ||
(error = ini_comment_build(ic_to_add, ";Line 4")) ||
(error = ini_comment_build(ic_to_add, ";Line 5"))) {
printf("Failed to create comment object %d\n",
error);
ini_comment_destroy(ic);
return error;
}
INIOUT(printf("<==== Comment To Add ====>\n"));
INIOUT(ini_comment_print(ic_to_add, stdout));
INIOUT(printf("<=================>\n"));
error = ini_comment_add(ic_to_add, ic);
if (error) {
printf("Failed to add one comment to another.\n");
ini_comment_destroy(ic);
ini_comment_destroy(ic_to_add);
return error;
}
INIOUT(printf("<==== Merged Comment ====>\n"));
INIOUT(ini_comment_print(ic, stdout));
INIOUT(printf("<=================>\n"));
if ((error = ini_comment_create(&ic_cmp)) ||
(error = ini_comment_build(ic_cmp, ";Line 0")) ||
(error = ini_comment_build(ic_cmp, ";Line 1")) ||
(error = ini_comment_build(ic_cmp, ";Line 2")) ||
(error = ini_comment_build(ic_cmp, ";Line 3")) ||
(error = ini_comment_build(ic_cmp, ";Line 4")) ||
(error = ini_comment_build(ic_cmp, ";Line 5"))) {
printf("Failed to create comment object %d\n",
error);
ini_comment_destroy(ic_cmp);
return error;
}
ini_comment_destroy(ic_to_add);
error = ini_comment_get_numlines(ic, &num1);
if (error) {
printf("Failed to get number of lines.\n");
ini_comment_destroy(ic);
ini_comment_destroy(ic_cmp);
return error;
}
error = ini_comment_get_numlines(ic, &num2);
if (error) {
printf("Failed to get number of lines.\n");
ini_comment_destroy(ic);
ini_comment_destroy(ic_cmp);
return error;
}
if (num1 != num2) {
printf("Sizes are different.\n");
ini_comment_destroy(ic);
ini_comment_destroy(ic_cmp);
return -1;
}
for (i = 0; i < num1; i++) {
line1 = NULL;
error = ini_comment_get_line(ic, i, &line1, NULL);
if (error) {
printf("Failed to get line.\n");
ini_comment_destroy(ic);
ini_comment_destroy(ic_cmp);
return error;
}
line2 = NULL;
error = ini_comment_get_line(ic_cmp, i, &line2, NULL);
if (error) {
printf("Failed to get line.\n");
ini_comment_destroy(ic);
ini_comment_destroy(ic_cmp);
return error;
}
if (strcmp(line1, line2) != 0) {
printf("Lines do not match.\n");
printf("1st: %s\n", line1);
printf("2nd: %s\n", line2);
ini_comment_destroy(ic);
ini_comment_destroy(ic_cmp);
return -1;
}
}
ini_comment_destroy(ic);
ini_comment_destroy(ic_cmp);
return error;
}
int main(int argc, char *argv[])
{
int error = EOK;
test_fn tests[] = { file_test,
alter_test,
copy_test,
add_test,
construct_test,
NULL };
test_fn t;
int i = 0;
char *var;
if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = 1;
else {
var = getenv("COMMON_TEST_VERBOSE");
if (var) verbose = 1;
}
INIOUT(printf("Start\n"));
while ((t = tests[i++])) {
error = t();
if (error) {
INIOUT(printf("Failed with error %d!\n", error));
return error;
}
}
INIOUT(printf("Success!\n"));
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,306 @@
/*
INI LIBRARY
Check based unit test for ini parser.
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 <stdlib.h>
#include <check.h>
/* #define TRACE_LEVEL 7 */
#define TRACE_HOME
#include "trace.h"
#include "ini_configobj.h"
#define TEST_DIR_PATH ""
START_TEST(test_ini_parse_non_kvp)
{
int ret;
struct ini_cfgobj *ini_cfg;
int value;
struct ini_cfgfile *file_ctx;
struct value_obj *vo;
char non_kvp_cfg[] =
"[section_before]\n"
"one = 1\n"
"[section_non_kvp]\n"
"two = 2\n"
"non_kvp\n"
"three = 3\n"
"=nonkvp\n"
"[section_after]\n"
"four = 4\n";
ret = ini_config_file_from_mem(non_kvp_cfg, strlen(non_kvp_cfg),
&file_ctx);
fail_unless(ret == EOK, "Failed to load config. Error %d.\n", ret);
/* First try without the INI_PARSE_IGNORE_NON_KVP. This should fail
* with error. */
ret = ini_config_create(&ini_cfg);
fail_unless(ret == EOK, "Failed to create config. Error %d.\n", ret);
ret = ini_config_parse(file_ctx, INI_STOP_ON_ERROR, INI_MV1S_ALLOW, 0,
ini_cfg);
fail_if(ret != 5, "Expected error was not found.\n");
ini_config_destroy(ini_cfg);
ini_config_file_destroy(file_ctx);
/* Now try with INI_PARSE_IGNORE_NON_KVP. We should have no errors
* and all the surounding configuration should be valid */
ret = ini_config_file_from_mem(non_kvp_cfg, strlen(non_kvp_cfg),
&file_ctx);
fail_unless(ret == EOK, "Failed to load config. Error %d.\n", ret);
ret = ini_config_create(&ini_cfg);
fail_unless(ret == EOK, "Failed to create config. Error %d.\n", ret);
ret = ini_config_parse(file_ctx, INI_STOP_ON_ERROR, INI_MV1S_ALLOW,
INI_PARSE_IGNORE_NON_KVP,
ini_cfg);
fail_unless(ret == EOK, "ini_config_parse returned %d\n", ret);
/* Now check if the surrounding configuration is OK */
/* section_before */
ret = ini_get_config_valueobj("section_before", "one", ini_cfg,
INI_GET_FIRST_VALUE, &vo);
fail_unless(ret == EOK, "ini_get_config_valueobj returned %d\n: %s", ret,
strerror(ret));
value = ini_get_int_config_value(vo, 1, -1, &ret);
fail_unless(ret == EOK, "ini_get_int_config_value returned %d\n: %s", ret,
strerror(ret));
fail_unless(ret == EOK);
fail_if(value != 1, "Expected value 1 got %d\n", value);
/* section_non_kvp */
ret = ini_get_config_valueobj("section_non_kvp", "two", ini_cfg,
INI_GET_FIRST_VALUE, &vo);
fail_unless(ret == EOK);
value = ini_get_int_config_value(vo, 1, -1, &ret);
fail_unless(ret == EOK);
fail_if(value != 2, "Expected value 2 got %d\n", value);
ret = ini_get_config_valueobj("section_non_kvp", "three", ini_cfg,
INI_GET_FIRST_VALUE, &vo);
fail_unless(ret == EOK);
value = ini_get_int_config_value(vo, 1, -1, &ret);
fail_unless(ret == EOK);
fail_if(value != 3, "Expected value 3 got %d\n", value);
/* section_after */
ret = ini_get_config_valueobj("section_after", "four", ini_cfg,
INI_GET_FIRST_VALUE, &vo);
fail_unless(ret == EOK);
value = ini_get_int_config_value(vo, 1, -1, &ret);
fail_unless(ret == EOK);
fail_if(value != 4, "Expected value 4 got %d\n", value);
ini_config_destroy(ini_cfg);
ini_config_file_destroy(file_ctx);
}
END_TEST
START_TEST(test_ini_parse_section_key_conflict)
{
/*
* This tests the behavior of ini_config_parse to ensure correct handling
* of conflicts between sections and keys of the same name. There are
* three possibilities for conflict:
*
* 1. Inside a section, between the section name and a key name
* 2. Between a default-section key name and a section name
* 3. Between a key name in a different section and a section name
*
* In case (1), parsing finished without an error. However, when
* trying to select a value object inside a section, the returned
* object was an unchecked cast from the section's data, and not the
* attribute's data. In cases (2) and (3), the parser segfaulted while
* trying to merge a section with an attribute.
*/
char config1[] =
"[a]\n"
"a=a\n";
char config2[] =
"a=b\n"
"[a]\n"
"c=d\n";
char config3[] =
"[a]\n"
"b=c\n"
"[b]\n"
"a=d\n";
char *file_contents[] = {config1, config2, config3, NULL};
size_t iter;
struct ini_cfgobj *ini_config = NULL;
struct ini_cfgfile *file_ctx = NULL;
int ret;
int i;
int j;
char **sections = NULL;
int sections_count = 0;
int sections_error = 0;
char **attributes = NULL;
int attributes_count = 0;
int attributes_error = 0;
struct value_obj *val = NULL;
char *val_str = NULL;
for (iter = 0; file_contents[iter] != NULL; iter++) {
ret = ini_config_create(&ini_config);
fail_unless(ret == EOK, "Failed to create config. Error %d.\n", ret);
ret = ini_config_file_from_mem(file_contents[iter],
strlen(file_contents[iter]),
&file_ctx);
fail_unless(ret == EOK, "Failed to load file. Error %d.\n", ret);
ret = ini_config_parse(file_ctx, 1, 0, 0, ini_config);
fail_unless(ret == EOK, "Failed to parse file. Error %d.\n", ret);
sections = ini_get_section_list(ini_config, &sections_count,
&sections_error);
fail_unless(sections_error == EOK,
"Failed to get sections. Error %d.\n",
sections_error);
for (i = 0; i < sections_count; i++) {
attributes = ini_get_attribute_list(ini_config,
sections[i],
&attributes_count,
&attributes_error);
fail_unless(attributes_error == EOK,
"Failed to get attributes. Error %d.\n",
attributes_error);
for (j = 0; j < attributes_count; j++) {
ret = ini_get_config_valueobj(sections[i], attributes[j],
ini_config, 0, &val);
fail_unless(ret == EOK,
"Failed to get attribute. Error %d.\n",
ret);
val_str = ini_get_string_config_value(val, &ret);
fail_unless(ret == EOK,
"Failed to get attribute as string. Error %d.\n",
ret);
fail_unless(val_str != NULL,
"Failed to get attribute as string: was NULL.\n");
free(val_str);
}
ini_free_attribute_list(attributes);
}
ini_free_section_list(sections);
ini_config_file_destroy(file_ctx);
ini_config_destroy(ini_config);
}
}
END_TEST
/* Maybe we should test even bigger values? */
#define VALUE_LEN 10000
/* The +100 is space for section name and key name. */
#define CFGBUF_LEN (VALUE_LEN + 100)
START_TEST(test_ini_long_value)
{
int ret;
struct ini_cfgobj *ini_cfg;
struct ini_cfgfile *file_ctx;
struct value_obj *vo;
char big_val_cfg[CFGBUF_LEN] = {0};
char value[VALUE_LEN] = {0};
char *value_got;
/* The value is just a lot of As ending with '\0'*/
memset(value, 'A', VALUE_LEN - 1);
/* Create config file */
ret = snprintf(big_val_cfg, CFGBUF_LEN, "[section]\nkey=%s", value);
ret = ini_config_file_from_mem(big_val_cfg, strlen(big_val_cfg),
&file_ctx);
fail_unless(ret == EOK, "Failed to load config. Error %d.\n", ret);
ret = ini_config_create(&ini_cfg);
fail_unless(ret == EOK, "Failed to create config. Error %d.\n", ret);
ret = ini_config_parse(file_ctx, INI_STOP_ON_ERROR, INI_MV1S_ALLOW, 0,
ini_cfg);
fail_if(ret != 0, "Failed to parse config. Error %d.\n", ret);
ret = ini_get_config_valueobj("section", "key", ini_cfg,
INI_GET_FIRST_VALUE, &vo);
fail_unless(ret == EOK, "ini_get_config_valueobj returned %d\n: %s", ret,
strerror(ret));
value_got = ini_get_string_config_value(vo, &ret);
fail_unless(ret == EOK, "ini_get_int_config_value returned %d\n: %s", ret,
strerror(ret));
fail_unless(strcmp(value, value_got) == 0, "Expected and found values differ!\n");
free(value_got);
ini_config_destroy(ini_cfg);
ini_config_file_destroy(file_ctx);
}
END_TEST
static Suite *ini_parse_suite(void)
{
Suite *s = suite_create("ini_parse_suite");
TCase *tc_parse = tcase_create("ini_parse");
tcase_add_test(tc_parse, test_ini_parse_non_kvp);
tcase_add_test(tc_parse, test_ini_parse_section_key_conflict);
tcase_add_test(tc_parse, test_ini_long_value);
suite_add_tcase(s, tc_parse);
return s;
}
int main(void)
{
int number_failed;
Suite *s = ini_parse_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;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,741 @@
/*
INI LIBRARY
Unit test for the value object.
Copyright (C) Dmitri Pal <dpal@redhat.com> 2010
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 <errno.h> /* for errors */
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include "ini_valueobj.h"
#define TRACE_HOME
#include "trace.h"
#define TEST_SIZE 80
int verbose = 0;
#define VOOUT(foo) \
do { \
if (verbose) foo; \
} while(0)
typedef int (*test_fn)(void);
static int create_comment(int i, struct ini_comment **ic)
{
int error = EOK;
const char *template = ";Line 0 of the value %d";
char comment[TEST_SIZE];
struct ini_comment *new_ic = NULL;
TRACE_FLOW_ENTRY();
snprintf(comment, TEST_SIZE, template, i);
if ((error = ini_comment_create(&new_ic)) ||
(error = ini_comment_build(new_ic, comment)) ||
(error = ini_comment_build(new_ic, NULL)) ||
(error = ini_comment_build(new_ic, "#This is the second line")) ||
(error = ini_comment_build(new_ic, ";This is the third line")) ||
(error = ini_comment_build(new_ic, ""))) {
printf("Failed to create comment object. Error %d.\n", error);
ini_comment_destroy(new_ic);
return -1;
}
*ic = new_ic;
TRACE_FLOW_EXIT();
return EOK;
}
/* Save value to the file */
/* NOTE: might be moved into the API in future */
static int save_value(FILE *ff, const char *key, struct value_obj *vo)
{
int error = EOK;
struct simplebuffer *sbobj = NULL;
uint32_t left = 0;
TRACE_FLOW_ENTRY();
error = simplebuffer_alloc(&sbobj);
if (error) {
TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error);
return error;
}
/* Serialize */
error = value_serialize(vo, key, sbobj);
if (error) {
printf("Failed to serialize a value object %d.\n", error);
simplebuffer_free(sbobj);
return error;
}
/* Add CR */
error = simplebuffer_add_cr(sbobj);
if (error) {
TRACE_ERROR_NUMBER("Failed to add CR", error);
simplebuffer_free(sbobj);
return error;
}
/* Save */
left = simplebuffer_get_len(sbobj);
while (left > 0) {
error = simplebuffer_write(fileno(ff), sbobj, &left);
if (error) {
printf("Failed to write value object %d.\n", error);
simplebuffer_free(sbobj);
return error;
}
}
simplebuffer_free(sbobj);
TRACE_FLOW_EXIT();
return EOK;
}
/* Test to create value object using arrays */
static int other_create_test(FILE *ff, struct value_obj **vo)
{
int error = EOK;
struct value_obj *new_vo = NULL;
struct ref_array *raw_lines;
struct ref_array *raw_lengths;
struct ini_comment *ic = NULL;
struct ini_comment *ic2 = NULL;
char *val;
const char *vallines[] = { "Domain1,",
" Domain2 ,",
" Domain3 " };
const char *fullstr;
const char *expected = "Domain1, Domain2 , Domain3";
int i;
uint32_t origin = 0;
uint32_t line = 0;
uint32_t len = 0;
uint32_t expected_len = 0;
TRACE_FLOW_ENTRY();
/* Create a pair of arrays */
error = value_create_arrays(&raw_lines,
&raw_lengths);
if (error) {
printf("Failed to create arrays %d.\n", error);
return error;
}
for (i=0; i< 3; i++) {
errno = 0;
val = strdup(vallines[i]);
if (val == NULL) {
error = errno;
printf("Failed to dup memory %d.\n", error);
value_destroy_arrays(raw_lines,
raw_lengths);
return error;
}
/* Add line to the arrays */
error = value_add_to_arrays(val,
strlen(val),
raw_lines,
raw_lengths);
if (error) {
printf("Failed to add to arrays %d.\n", error);
value_destroy_arrays(raw_lines,
raw_lengths);
return error;
}
}
/* Create a comment */
error = create_comment(1000, &ic);
if (error) {
printf("Failed to create comment %d.\n", error);
value_destroy_arrays(raw_lines,
raw_lengths);
return error;
}
/* Create object */
error = value_create_from_refarray(raw_lines,
raw_lengths,
1,
INI_VALUE_READ,
3,
70,
ic,
&new_vo);
if (error) {
printf("Failed to create comment %d.\n", error);
value_destroy_arrays(raw_lines,
raw_lengths);
ini_comment_destroy(ic);
return error;
}
/* Save value to the file */
error = save_value(ff, "baz", new_vo);
if (error) {
printf("Failed to save value to file %d.\n", error);
value_destroy(new_vo);
return error;
}
/* Now do assertions and modifications to the object */
/* NOTE: Below this line do not need to free arrays or comment
* they became internal parts of the value object
* and will be freed as a part of it.
*/
/* Get concatenated value */
error = value_get_concatenated(new_vo,
&fullstr);
if (error) {
printf("Failed to get the string %d.\n", error);
value_destroy(new_vo);
return error;
}
/* Get length of the concatenated value */
value_get_concatenated_len(new_vo, &len);
expected_len = strlen(expected);
if ((len != expected_len) ||
(strncmp(fullstr, expected, expected_len + 1) != 0)) {
printf("The expected value is different.\n");
printf("The expected value is %s\n", expected);
printf("The real value is %s\n", fullstr);
printf("The expected len is %d, real %d.\n", expected_len, len);
value_destroy(new_vo);
return EINVAL;
}
/* Get value's origin */
error = value_get_origin(new_vo, &origin);
if (error) {
printf("Failed to get origin %d.\n", error);
value_destroy(new_vo);
return error;
}
if (origin != INI_VALUE_READ) {
printf("The expected origin is different.\n%d\n", origin);
value_destroy(new_vo);
return EINVAL;
}
/* Get value's line */
error = value_get_line(new_vo, &line);
if (error) {
printf("Failed to get origin %d.\n", error);
value_destroy(new_vo);
return error;
}
if (line != 1) {
printf("The expected line is different.\n%d\n", origin);
value_destroy(new_vo);
return EINVAL;
}
/* Get comment from the value */
ic = NULL;
error = value_extract_comment(new_vo, &ic);
if (error) {
printf("Failed to extract comment %d.\n", error);
value_destroy(new_vo);
return error;
}
if (ic == NULL) {
printf("The expected comment to be there.\n");
value_destroy(new_vo);
return error;
}
VOOUT(ini_comment_print(ic, stdout));
/* Get comment again */
ic2 = NULL;
error = value_extract_comment(new_vo, &ic2);
if (error) {
printf("Failed to extract comment %d.\n", error);
value_destroy(new_vo);
ini_comment_destroy(ic);
return error;
}
if (ic2 != NULL) {
printf("The expected NO comment to be there.\n");
value_destroy(new_vo);
ini_comment_destroy(ic);
/* No free for ic2 since it is the same object */
/* But this should not happen anyways -
* it will be coding error.
*/
return EINVAL;
}
/* Put comment back */
error = value_put_comment(new_vo, ic);
if (error) {
printf("Failed to put comment back %d.\n", error);
value_destroy(new_vo);
ini_comment_destroy(ic);
return error;
}
/* Save value to the file */
error = save_value(ff, "bar", new_vo);
if (error) {
printf("Failed to save value to file %d.\n", error);
value_destroy(new_vo);
return error;
}
*vo = new_vo;
TRACE_FLOW_EXIT();
return EOK;
}
/* Modify the value object */
static int modify_test(FILE *ff, struct value_obj *vo)
{
int error = EOK;
const char *strval = "Domain100, Domain200, Domain300";
TRACE_FLOW_ENTRY();
/* Update key length */
error = value_set_keylen(vo, strlen("foobar"));
if (error) {
printf("Failed to change key length %d.\n", error);
return error;
}
/* Update value */
error = value_update(vo,
strval,
strlen(strval),
INI_VALUE_CREATED,
10);
if (error) {
printf("Failed to update value %d.\n", error);
return error;
}
/* Save value to the file */
error = save_value(ff, "foobar", vo);
if (error) {
printf("Failed to save value to file %d.\n", error);
return error;
}
TRACE_FLOW_EXIT();
return EOK;
}
static int vo_basic_test(void)
{
int error = EOK;
const char *strvalue = "Test multi_word_value_that_will_"
"be_split_between_several_lines_!";
/* Other testing can be done with the following string:
* const char *strvalue = "Test multi word value that "
* "will be split between several lines";
*/
struct value_obj *vo = NULL;
uint32_t wrap = 0;
struct ini_comment *ic = NULL;
FILE *ff = NULL;
TRACE_FLOW_ENTRY();
errno = 0;
ff = fopen("test.ini","wt");
if (ff == NULL) {
error = errno;
printf("Failed to open file. Error %d.\n", error);
return error;
}
for (wrap = 0; wrap < 80; wrap++) {
ic = NULL;
error = create_comment(wrap, &ic);
if (error) {
printf("Failed to create a new comment object %d.\n", error);
fclose(ff);
return error;
}
vo = NULL;
error = value_create_new(strvalue,
strlen(strvalue),
INI_VALUE_CREATED,
3,
wrap,
ic,
&vo);
if (error) {
printf("Failed to create a new value object %d.\n", error);
ini_comment_destroy(ic);
fclose(ff);
return error;
}
error = save_value(ff, "key", vo);
if (error) {
printf("Failed to save value to file %d.\n", error);
value_destroy(vo);
fclose(ff);
return error;
}
value_destroy(vo);
}
vo = NULL;
/* Run other create test here */
error = other_create_test(ff, &vo);
if (error) {
printf("Create test failed %d.\n", error);
fclose(ff);
return error;
}
/* Run modify test here */
error = modify_test(ff, vo);
if (error) {
printf("Modify test failed %d.\n", error);
fclose(ff);
value_destroy(vo);
return error;
}
value_destroy(vo);
ic = NULL;
error = create_comment(100, &ic);
if (error) {
printf("Failed to create a new comment object %d.\n", error);
fclose(ff);
return error;
}
ini_comment_print(ic, ff);
ini_comment_destroy(ic);
fclose(ff);
TRACE_FLOW_EXIT();
return EOK;
}
static int vo_copy_test(void)
{
int error = EOK;
const char *strvalue = "Test multi word value that "
"will be split between several lines";
struct value_obj *vo = NULL;
struct value_obj *vo_copy = NULL;
uint32_t wrap = 0;
struct ini_comment *ic = NULL;
FILE *ff = NULL;
char comment[100];
TRACE_FLOW_ENTRY();
VOOUT(printf("Copy test\n"));
errno = 0;
ff = fopen("test.ini","a");
if (ff == NULL) {
error = errno;
printf("Failed to open file. Error %d.\n", error);
return error;
}
error = ini_comment_create(&ic);
if (error) {
printf("Failed to create comment object\n");
fclose(ff);
return -1;
}
error = ini_comment_append(ic, "#This is a copy test!");
if (error) {
printf("Failed to add a line to the comment %d.\n", error);
ini_comment_destroy(ic);
fclose(ff);
return error;
}
error = ini_comment_append(ic, "#Replacable comment line");
if (error) {
printf("Failed to add a line to the comment %d.\n", error);
ini_comment_destroy(ic);
fclose(ff);
return error;
}
error = value_create_new(strvalue,
strlen(strvalue),
INI_VALUE_CREATED,
3,
20,
ic,
&vo);
if (error) {
printf("Failed to create a new value object %d.\n", error);
ini_comment_destroy(ic);
fclose(ff);
return error;
}
error = save_value(ff, "key", vo);
if (error) {
printf("Failed to save value to file %d.\n", error);
value_destroy(vo);
fclose(ff);
return error;
}
for (wrap = 0; wrap < 80; wrap++) {
TRACE_INFO_NUMBER("Iteration:", wrap);
vo_copy = NULL;
error = value_copy(vo, &vo_copy);
if (error) {
printf("Failed to create a new value object %d.\n", error);
value_destroy(vo);
fclose(ff);
return error;
}
error = value_set_boundary(vo_copy, wrap);
if (error) {
printf("Failed to set boundary %d.\n", error);
value_destroy(vo);
value_destroy(vo_copy);
fclose(ff);
return error;
}
/* Get comment from the value */
ic = NULL;
error = value_extract_comment(vo_copy, &ic);
if (error) {
printf("Failed to extract comment %d.\n", error);
value_destroy(vo);
value_destroy(vo_copy);
fclose(ff);
return error;
}
/* Replace comment in the value */
snprintf(comment, TEST_SIZE, ";This is value with boundary %d", wrap);
VOOUT(printf("Comment: %s\n", comment));
error = ini_comment_replace(ic, 1, comment);
if (error) {
printf("Failed to replace comment %d.\n", error);
value_destroy(vo);
value_destroy(vo_copy);
fclose(ff);
return error;
}
/* Set comment into the value */
error = value_put_comment(vo_copy, ic);
if (error) {
printf("Failed to set comment %d.\n", error);
value_destroy(vo);
value_destroy(vo_copy);
fclose(ff);
return error;
}
error = save_value(ff, "key", vo_copy);
if (error) {
printf("Failed to save value to file %d.\n", error);
value_destroy(vo);
value_destroy(vo_copy);
fclose(ff);
return error;
}
value_destroy(vo_copy);
}
value_destroy(vo);
fclose(ff);
TRACE_FLOW_EXIT();
return EOK;
}
static int vo_show_test(void)
{
VOOUT(system("cat test.ini"));
return EOK;
}
static int vo_mc_test(void)
{
int error = EOK;
struct value_obj *vo1 = NULL;
struct value_obj *vo2 = NULL;
struct ini_comment *ic = NULL;
TRACE_FLOW_ENTRY();
VOOUT(printf("<=== Merge Comment Test ===>\n"));
error = create_comment(1, &ic);
if (error) {
printf("Failed to create a new comment object %d.\n", error);
return error;
}
error = value_create_new("test1",
5,
INI_VALUE_CREATED,
3,
80,
ic,
&vo1);
if (error) {
printf("Failed to create the first value object %d.\n", error);
ini_comment_destroy(ic);
return error;
}
error = create_comment(2, &ic);
if (error) {
printf("Failed to create a new comment object %d.\n", error);
value_destroy(vo1);
return error;
}
error = value_create_new("test2",
5,
INI_VALUE_CREATED,
3,
80,
ic,
&vo2);
if (error) {
printf("Failed to create the second value object %d.\n", error);
ini_comment_destroy(ic);
value_destroy(vo1);
return error;
}
/* Merge comment from one value into another */
error = value_merge_comment(vo2, vo1);
if (error) {
printf("Failed to merge comments %d.\n", error);
value_destroy(vo1);
value_destroy(vo2);
return error;
}
value_destroy(vo2);
VOOUT(printf("<=== Key ===>\n"));
VOOUT(value_print("key", vo1));
error = value_extract_comment(vo1, &ic);
if (error) {
printf("Failed to extract comment %d.\n", error);
value_destroy(vo1);
return error;
}
value_destroy(vo1);
VOOUT(printf("<=== Comment ===>\n"));
VOOUT(ini_comment_print(ic, stdout));
ini_comment_destroy(ic);
TRACE_FLOW_EXIT();
return EOK;
}
/* Main function of the unit test */
int main(int argc, char *argv[])
{
int error = 0;
test_fn tests[] = { vo_basic_test,
vo_copy_test,
vo_show_test,
vo_mc_test,
NULL };
test_fn t;
int i = 0;
char *var;
if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = 1;
else {
var = getenv("COMMON_TEST_VERBOSE");
if (var) verbose = 1;
}
VOOUT(printf("Start\n"));
while ((t = tests[i++])) {
error = t();
if (error) {
VOOUT(printf("Failed with error %d!\n", error));
return error;
}
}
VOOUT(printf("Success!\n"));
return 0;
}

View File

@ -0,0 +1,768 @@
/*
path_utils - unit tests
Authors:
Jakub Hrozek <jhrozek@redhat.com>
Copyright (C) 2009 Red Hat
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/>.
*/
#define _GNU_SOURCE
#include <check.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include "path_utils.h"
#define fail_unless_str_equal(a, b) do { \
fail_unless(strcmp(a, b) == 0, \
"The strings '%s' and '%s' are different, expected same", \
a, b); \
} while(0);
#define DIR_TEMPLATE "test-directory-list-dir-XXXXXX"
#define SUBDIR "test-directory-list-subdir"
#define SUBSUBDIR "test-directory-list-subsubdir"
char *dlist_dir;
char *dlist_subdir;
char *dlist_subsubdir;
/**** get_dirname ****/
START_TEST(test_dirname)
{
char p[PATH_MAX];
char cwd[PATH_MAX];
fail_unless(get_dirname(p, PATH_MAX, "/foo/bar") == SUCCESS);
fail_unless_str_equal(p, "/foo");
fail_unless(get_dirname(p, PATH_MAX, "/") == SUCCESS);
fail_unless_str_equal(p, "/");
fail_unless(get_dirname(p, PATH_MAX, "/foo") == SUCCESS);
fail_unless_str_equal(p, "/");
fail_unless(get_dirname(p, PATH_MAX, "//foo//bar") == SUCCESS);
fail_unless_str_equal(p, "//foo");
fail_unless(get_dirname(p, PATH_MAX, "//foo//") == SUCCESS);
fail_unless(!strcmp(p, "/") || !strcmp(p, "//"));
fail_unless(get_dirname(p, PATH_MAX, "foo//bar") == SUCCESS);
fail_unless_str_equal(p, "foo");
fail_unless(get_dirname(p, PATH_MAX, "foo//////bar") == SUCCESS);
fail_unless_str_equal(p, "foo");
/* if pathname does not contain a slash, dirname returns cwd */
fail_if(getcwd(cwd, PATH_MAX) == NULL, "getcwd failed");
fail_unless(get_dirname(p, PATH_MAX, "foo") == SUCCESS);
fail_unless_str_equal(p, cwd);
fail_unless(get_dirname(p, PATH_MAX, ".") == SUCCESS);
fail_unless_str_equal(p, cwd);
fail_unless(get_dirname(p, PATH_MAX, "..") == SUCCESS);
fail_unless_str_equal(p, cwd);
fail_unless(get_dirname(p, PATH_MAX, "") == SUCCESS);
fail_unless_str_equal(p, cwd);
}
END_TEST
START_TEST(test_dirname_neg)
{
char neg[3];
char p[PATH_MAX];
fail_if(get_dirname(neg, 3, "/foo/bar") == SUCCESS);
fail_unless(get_dirname(p, PATH_MAX, NULL) == EINVAL);
}
END_TEST
/**** get_basename ****/
START_TEST(test_basename)
{
char p[PATH_MAX];
char cwd[PATH_MAX];
fail_unless(get_basename(p, PATH_MAX, "/foo/bar") == SUCCESS);
fail_unless_str_equal(p, "bar");
fail_unless(get_basename(p, PATH_MAX, "/foo/") == SUCCESS);
fail_unless_str_equal(p, "foo");
fail_unless(get_basename(p, PATH_MAX, "foo") == SUCCESS);
fail_unless_str_equal(p, "foo");
fail_unless(get_basename(p, PATH_MAX, "/") == SUCCESS);
fail_unless_str_equal(p, "/");
fail_if(getcwd(cwd, PATH_MAX) == NULL, "getcwd failed");
fail_unless(get_basename(p, PATH_MAX, ".") == SUCCESS);
fail_unless_str_equal(p, cwd);
fail_unless(get_basename(p, PATH_MAX, "") == SUCCESS);
fail_unless_str_equal(p, cwd);
}
END_TEST
START_TEST(test_basename_neg)
{
char neg[3];
char p[PATH_MAX];
fail_if(get_basename(neg, 3, "/foo/bar") == SUCCESS);
fail_unless(get_basename(p, PATH_MAX, NULL) == EINVAL);
}
END_TEST
/**** is_absolute_path ****/
START_TEST(test_is_absolute_path)
{
fail_unless(is_absolute_path("") == false);
fail_unless(is_absolute_path("foo/bar") == false);
fail_unless(is_absolute_path("/foo/bar") == true);
fail_unless(is_absolute_path("/foo") == true);
fail_unless(is_absolute_path("/") == true);
}
END_TEST
/**** get_dirname_and_basename ****/
/* Just a couple of basic tests - get_dirname_and_basename()
* uses get_dirname() and get_basename() under the hood which
* are tested enough in their specific tests
*/
START_TEST(test_dirname_and_basename)
{
char dir[PATH_MAX];
char base[PATH_MAX];
char cwd[PATH_MAX];
int ret;
ret = get_directory_and_base_name(dir, PATH_MAX, base, PATH_MAX, "/foo/bar");
fail_unless(ret == SUCCESS);
fail_unless_str_equal(dir, "/foo");
fail_unless_str_equal(base, "bar");
ret = get_directory_and_base_name(dir, PATH_MAX, base, PATH_MAX, "/foo");
fail_unless(ret == SUCCESS);
fail_unless_str_equal(dir, "/");
fail_unless_str_equal(base, "foo");
ret = get_directory_and_base_name(dir, PATH_MAX, base, PATH_MAX, "/");
fail_unless(ret == SUCCESS);
fail_unless_str_equal(dir, "/");
fail_unless_str_equal(base, "/");
fail_if(getcwd(cwd, PATH_MAX) == NULL, "getcwd failed");
ret = get_directory_and_base_name(dir, PATH_MAX, base, PATH_MAX, "foo");
fail_unless(ret == SUCCESS);
fail_unless_str_equal(dir, cwd);
fail_unless_str_equal(base, "foo");
ret = get_directory_and_base_name(dir, PATH_MAX, base, PATH_MAX, "");
fail_unless(ret == SUCCESS);
fail_unless_str_equal(dir, cwd);
fail_unless_str_equal(base, "");
ret = get_directory_and_base_name(dir, PATH_MAX, base, PATH_MAX, ".");
fail_unless(ret == SUCCESS);
fail_unless_str_equal(dir, cwd);
fail_unless_str_equal(base, "");
}
END_TEST
START_TEST(test_dirname_and_basename_neg)
{
char dir[PATH_MAX];
char base[PATH_MAX];
int ret;
ret = get_directory_and_base_name(dir, PATH_MAX, base, PATH_MAX, NULL);
fail_unless(ret == EINVAL);
}
END_TEST
/**** path_concat ****/
START_TEST(test_path_concat)
{
char p[PATH_MAX];
char p2[9];
fail_unless(path_concat(p, PATH_MAX, "/foo", "bar") == SUCCESS);
fail_unless_str_equal(p, "/foo/bar");
fail_unless(path_concat(p, PATH_MAX, "/foo", "/bar") == SUCCESS);
fail_unless_str_equal(p, "/foo/bar");
fail_unless(path_concat(p, PATH_MAX, "/foo/", "/bar") == SUCCESS);
fail_unless_str_equal(p, "/foo/bar");
fail_unless(path_concat(p, PATH_MAX, "/foo", "") == SUCCESS);
fail_unless_str_equal(p, "/foo");
fail_unless(path_concat(p, PATH_MAX, "foo", NULL) == SUCCESS);
fail_unless_str_equal(p, "foo");
fail_unless(path_concat(p, PATH_MAX, "", "foo") == SUCCESS);
fail_unless_str_equal(p, "foo");
fail_unless(path_concat(p, PATH_MAX, "/", "foo") == SUCCESS);
fail_unless_str_equal(p, "/foo");
fail_unless(path_concat(p, PATH_MAX, "/foo", "/") == SUCCESS);
fail_unless_str_equal(p, "/foo/");
fail_unless(path_concat(p, PATH_MAX, "/foo", "bar/") == SUCCESS);
fail_unless_str_equal(p, "/foo/bar/");
fail_unless(path_concat(p, PATH_MAX, NULL, "foo") == SUCCESS);
fail_unless_str_equal(p, "foo");
/* on-by-one */
fail_unless(path_concat(p2, 9, "/foo", "bar") == SUCCESS);
fail_unless_str_equal(p2, "/foo/bar");
}
END_TEST
START_TEST(test_path_concat_neg)
{
char small[3];
char small2[5];
char small3[7];
char p2[10];
/* these two test different conditions */
/* Test if head is longer than the buffer */
fail_unless(path_concat(small, 3, "/foo", "bar") == ENOBUFS);
/* On ENOBUFS, path should be empty */
fail_unless_str_equal(small, "");
/* Test if head is the same length as the buffer */
fail_unless(path_concat(small2, 5, "/foo", "bar") == ENOBUFS);
/* On ENOBUFS, path should be empty */
fail_unless_str_equal(small2, "");
/* Test if head+tail is the longer than the buffer */
fail_unless(path_concat(small3, 7, "/foo", "bar") == ENOBUFS);
/* On ENOBUFS, path should be empty */
fail_unless_str_equal(small3, "");
/* off-by-one */
/* Fill with garbage data for now */
memset(p2, 'Z', 9);
p2[9] = '\0';
fail_unless(path_concat(p2, 8, "/foo", "bar") == ENOBUFS);
/* Make sure we don't write past the end of the buffer */
fail_unless(p2[8] == 'Z', "Got [%d]", p2[8]);
/* On ENOBUFS, path should be empty */
fail_unless_str_equal(p2, "");
}
END_TEST
/**** make_path_absolute ****/
START_TEST(test_make_path_absolute)
{
char p[PATH_MAX];
char p2[PATH_MAX];
char cwd[PATH_MAX];
char *buf;
size_t buf_len;
fail_unless(make_path_absolute(p, PATH_MAX, "/foo") == SUCCESS);
fail_unless_str_equal(p, "/foo");
fail_if(getcwd(cwd, PATH_MAX) == NULL, "getcwd failed");
fail_unless(make_path_absolute(p, PATH_MAX, "foo") == SUCCESS);
snprintf(p2, PATH_MAX, "%s/foo", cwd);
fail_unless_str_equal(p, p2);
fail_unless(make_path_absolute(p, PATH_MAX, "") == SUCCESS);
fail_unless_str_equal(p, cwd);
/* on-by-one; 2 = terminating null + path delimeter */
buf_len = strlen(cwd) + strlen("foo") + 2;
buf = malloc(buf_len);
fail_if(buf == NULL);
fail_unless(make_path_absolute(buf, buf_len, "foo") == SUCCESS);
free(buf);
}
END_TEST
START_TEST(test_make_path_absolute_neg)
{
char small[1];
char cwd[PATH_MAX];
char *small2;
int small_len;
fail_unless(make_path_absolute(small, 1, "/foo") == ENOBUFS);
fail_unless(make_path_absolute(NULL, 1, "/foo") == ENOBUFS);
/* off-by-one */
fail_if(getcwd(cwd, PATH_MAX) == NULL, "getcwd failed");
small_len = strlen(cwd) + strlen("foo") + 1;
small2 = malloc(small_len);
fail_if(small2 == NULL);
fail_unless(make_path_absolute(small2, small_len, "foo") == ENOBUFS);
free(small2);
/* just enough space for cwd */
small_len = strlen(cwd) + 1;
small2 = malloc(small_len);
fail_if(small2 == NULL);
fail_unless(make_path_absolute(small2, small_len, "foo") == ENOBUFS);
free(small2);
}
END_TEST
/**** make_normalized_absolute_path ****/
START_TEST(test_make_normalized_absolute_path)
{
char p[PATH_MAX];
char p2[PATH_MAX];
char cwd[PATH_MAX];
fail_if(getcwd(cwd, PATH_MAX) == NULL, "getcwd failed");
fail_unless(make_normalized_absolute_path(p, PATH_MAX, "foo/baz/../bar") == SUCCESS);
snprintf(p2, PATH_MAX, "%s/foo/bar", cwd);
fail_unless_str_equal(p, p2);
fail_unless(make_normalized_absolute_path(p, PATH_MAX, "/foo/../bar") == SUCCESS);
fail_unless_str_equal(p, "/bar");
fail_unless(make_normalized_absolute_path(p, PATH_MAX, "/foo/../baz/../bar") == SUCCESS);
fail_unless_str_equal(p, "/bar");
}
END_TEST
START_TEST(test_make_normalized_absolute_path_neg)
{
char small[1];
fail_unless(make_path_absolute(small, 1, "/foo") == ENOBUFS);
fail_unless(make_path_absolute(NULL, 1, "/foo") == ENOBUFS);
}
END_TEST
/**** split_path ****/
START_TEST(test_split_path)
{
char **array;
int n;
array = split_path("/foo/bar", &n);
fail_if(array == NULL);
fail_unless(n == 3);
if (array) {
fail_unless_str_equal(array[0], "/");
fail_unless_str_equal(array[1], "foo");
fail_unless_str_equal(array[2], "bar");
free(array);
}
array = split_path("/foo/../bar", &n);
fail_if(array == NULL);
fail_unless(n == 4);
if (array) {
fail_unless_str_equal(array[0], "/");
fail_unless_str_equal(array[1], "foo");
fail_unless_str_equal(array[2], "..");
fail_unless_str_equal(array[3], "bar");
free(array);
}
array = split_path("/foo/bar", NULL);
fail_if(array == NULL);
if (array) {
fail_unless_str_equal(array[0], "/");
fail_unless_str_equal(array[1], "foo");
fail_unless_str_equal(array[2], "bar");
free(array);
}
array = split_path("foo/bar", &n);
fail_if(array == NULL);
fail_unless(n == 2);
if (array) {
fail_unless_str_equal(array[0], "foo");
fail_unless_str_equal(array[1], "bar");
free(array);
}
array = split_path(".", &n);
fail_if(array == NULL);
fail_unless(n == 1);
if (array) {
fail_unless_str_equal(array[0], ".");
free(array);
}
array = split_path("foo", &n);
fail_if(array == NULL);
fail_unless(n == 1);
if (array) {
fail_unless_str_equal(array[0], "foo");
free(array);
}
/* one might expect { "" } or outright NULL, but we agreed not to
* do changes beyond bugfixes at this point */
array = split_path("", &n);
fail_if(array == NULL);
fail_unless(n == 0);
if (array) {
fail_unless(array[0] == NULL);
free(array);
}
}
END_TEST
START_TEST(test_split_path_neg)
{
char **array;
int n;
array = split_path(NULL, &n);
fail_unless(array == NULL);
array = split_path(NULL, NULL);
fail_unless(array == NULL);
}
END_TEST
/**** normalize_path ****/
START_TEST(test_normalize_path)
{
char norm[PATH_MAX];
char small[8];
fail_unless(normalize_path(norm, PATH_MAX, "/foo/../bar") == SUCCESS);
fail_unless_str_equal(norm, "/bar");
fail_unless(normalize_path(norm, PATH_MAX, "/foo/../baz/../bar") == SUCCESS);
fail_unless_str_equal(norm, "/bar");
fail_unless(normalize_path(norm, PATH_MAX, "foo/baz/../bar") == SUCCESS);
fail_unless_str_equal(norm, "foo/bar");
fail_unless(normalize_path(norm, PATH_MAX, "/foo/./bar") == SUCCESS);
fail_unless_str_equal(norm, "/foo/bar");
fail_unless(normalize_path(norm, PATH_MAX, "/foo//bar") == SUCCESS);
fail_unless_str_equal(norm, "/foo/bar");
fail_unless(normalize_path(norm, PATH_MAX, "/foo//bar") == SUCCESS);
fail_unless_str_equal(norm, "/foo/bar");
fail_unless(normalize_path(norm, PATH_MAX, "") == SUCCESS);
fail_unless_str_equal(norm, ".");
fail_unless(normalize_path(norm, PATH_MAX, "/../..") == SUCCESS);
fail_unless_str_equal(norm, "/");
/* on-by-one */
fail_unless(normalize_path(small, 8, "foo/baz/../bar") == SUCCESS);
fail_unless_str_equal(small, "foo/bar");
}
END_TEST
START_TEST(test_normalize_path_neg)
{
char norm[PATH_MAX];
char small[4];
fail_unless(normalize_path(norm, PATH_MAX, "foo/../..") == PATH_UTILS_ERROR_NOT_FULLY_NORMALIZED);
/* with a buffer of 4 chars, this would test off-by-one error */
fail_unless(normalize_path(small, 4, "/foo/../bar") == ENOBUFS);
}
END_TEST
/**** common_path_prefix ****/
START_TEST(test_common_path_prefix)
{
char common[PATH_MAX];
char small[5];
int count;
fail_unless(common_path_prefix(common, PATH_MAX, &count, "/usr/lib", "/usr/share") == SUCCESS);
fail_unless_str_equal(common, "/usr");
fail_unless(count == 2);
fail_unless(common_path_prefix(common, PATH_MAX, NULL, "/usr/lib", "/usr/share") == SUCCESS);
fail_unless_str_equal(common, "/usr");
fail_unless(common_path_prefix(common, PATH_MAX, &count, "/usr/lib", "/usr/lab") == SUCCESS);
fail_unless_str_equal(common, "/usr");
fail_unless(count == 2);
fail_unless(common_path_prefix(common, PATH_MAX, &count, "foo", "bar") == SUCCESS);
fail_unless_str_equal(common, "");
fail_unless(count == 0);
fail_unless(common_path_prefix(common, PATH_MAX, &count, "/", "/") == SUCCESS);
fail_unless_str_equal(common, "/");
fail_unless(count == 1);
fail_unless(common_path_prefix(common, PATH_MAX, &count, NULL, "/usr/share") == SUCCESS);
fail_unless_str_equal(common, "");
fail_unless(count == 0);
/* on-by-one */
fail_unless(common_path_prefix(small, 5, NULL, "/usr/lib", "/usr/share") == SUCCESS);
fail_unless_str_equal(small, "/usr");
}
END_TEST
START_TEST(test_common_path_prefix_neg)
{
char small[1];
char small2[4];
int count;
fail_unless(common_path_prefix(small, 1, &count, "/usr/lib", "/usr/share") == ENOBUFS);
fail_unless(common_path_prefix(NULL, PATH_MAX, &count, "/usr/lib", "/usr/share") == ENOBUFS);
/* off-by-one */
fail_unless(common_path_prefix(small2, 4, NULL, "/usr/lib", "/usr/share") == ENOBUFS);
}
END_TEST
/**** find_existing_directory_ancestor ****/
START_TEST(test_find_existing_directory_ancestor)
{
char p[PATH_MAX];
char cwd[PATH_MAX];
fail_unless(find_existing_directory_ancestor(p, PATH_MAX, "/etc/passwd") == SUCCESS);
fail_unless_str_equal(p, "/etc");
/* if pathname does not contain a slash, the parent is cwd */
fail_if(getcwd(cwd, PATH_MAX) == NULL, "getcwd failed");
fail_unless(find_existing_directory_ancestor(p, PATH_MAX, "foo/bar") == SUCCESS);
fail_unless_str_equal(p, cwd);
}
END_TEST
START_TEST(test_find_existing_directory_ancestor_neg)
{
char small[4];
fail_unless(find_existing_directory_ancestor(small, 4, "/etc/passwd") == ENOBUFS);
fail_unless(find_existing_directory_ancestor(NULL, 4, "/etc/passwd") == ENOBUFS);
}
END_TEST
/**** directory_list ****/
static void setup_directory_list(void)
{
char *s = NULL;
int ret;
s = strdup(DIR_TEMPLATE);
fail_unless(s != NULL, "strdup failed\n");
if (!s) return;
dlist_dir = mkdtemp(s);
fail_unless(dlist_dir != NULL, "mkstemp failed [%d][%s]", errno, strerror(errno));
ret = asprintf(&dlist_subdir, "%s/%s", dlist_dir, SUBDIR);
fail_unless(ret != 1, "strdup failed\n");
ret = mkdir(dlist_subdir, 0700);
fail_unless(ret != -1, "mkdir %s failed [%d][%s]", dlist_subdir, errno, strerror(errno));
ret = asprintf(&dlist_subsubdir, "%s/%s", dlist_subdir, SUBSUBDIR);
fail_unless(ret != 1, "strdup failed\n");
ret = mkdir(dlist_subsubdir, 0700);
fail_unless(ret != -1, "mkdir %s failed [%d][%s]", dlist_subsubdir, errno, strerror(errno));
}
static void teardown_directory_list(void)
{
int ret;
if (dlist_subsubdir) {
ret = rmdir(dlist_subsubdir);
fail_unless(ret != -1, "unlink %s failed [%d][%s]", dlist_subsubdir, errno, strerror(errno));
free(dlist_subsubdir);
dlist_subsubdir = NULL;
}
if (dlist_subdir) {
ret = rmdir(dlist_subdir);
fail_unless(ret != -1, "unlink %s failed [%d][%s]", dlist_subdir, errno, strerror(errno));
free(dlist_subdir);
dlist_subdir = NULL;
}
if (dlist_dir) {
ret = rmdir(dlist_dir);
fail_unless(ret != -1, "unlink %s failed [%d][%s]", dlist_dir, errno, strerror(errno));
free(dlist_dir);
dlist_dir = NULL;
}
}
static bool dirlist_cb_nonrecursive(const char *directory,
const char *base_name,
const char *path,
struct stat *info,
void *user_data)
{
int *data = (int *) user_data;
fail_unless_str_equal(path, dlist_subdir);
fail_unless(*data == 123);
return true;
}
static bool dirlist_cb_recursive(const char *directory, const char *base_name,
const char *path, struct stat *info,
void *user_data)
{
bool *seen_child = (bool *) user_data;
static bool seen_parent = false;
if (!seen_parent) {
fail_unless_str_equal(path, dlist_subdir);
seen_parent = true;
} else {
*seen_child = true;
fail_unless_str_equal(path, dlist_subsubdir);
seen_parent = false;
}
return true;
}
START_TEST(test_directory_list)
{
int data = 123;
bool seen_child;
fail_unless(directory_list(dlist_dir, false, dirlist_cb_nonrecursive, &data) == SUCCESS);
seen_child = false;
fail_unless(directory_list(dlist_dir, true, dirlist_cb_recursive, &seen_child) == SUCCESS);
fail_unless(seen_child == true);
seen_child = false;
fail_unless(directory_list(dlist_dir, false, dirlist_cb_recursive, &seen_child) == SUCCESS);
fail_unless(seen_child == false);
}
END_TEST
START_TEST(test_directory_list_neg)
{
fail_if(directory_list("/not/here", false, dirlist_cb_nonrecursive, NULL) == SUCCESS);
fail_if(directory_list("/etc/passwd", false, dirlist_cb_nonrecursive, NULL) == SUCCESS);
}
END_TEST
/**** is_ancestor_path ****/
START_TEST(test_is_ancestor_path)
{
fail_unless(is_ancestor_path("/a/b/c", "/a/b/c/d") == true);
/* equal, not ancestor */
fail_unless(is_ancestor_path("/a/b/c/d", "/a/b/c/d") == false);
fail_unless(is_ancestor_path("/a/x/c", "/a/b/c/d") == false);
fail_unless(is_ancestor_path(NULL, "/a/b/c/d") == false);
fail_unless(is_ancestor_path("/a/x/c", NULL) == false);
fail_unless(is_ancestor_path(NULL, NULL) == false);
fail_unless(is_ancestor_path("", "") == false);
}
END_TEST
static Suite *path_utils_suite(void)
{
Suite *s = suite_create("path_utils");
TCase *tc_path_utils = tcase_create("path_utils");
TCase *tc_directory_list = tcase_create("path_utils_directory_list");
tcase_add_test(tc_path_utils, test_dirname);
tcase_add_test(tc_path_utils, test_dirname_neg);
tcase_add_test(tc_path_utils, test_basename);
tcase_add_test(tc_path_utils, test_basename_neg);
tcase_add_test(tc_path_utils, test_dirname_and_basename);
tcase_add_test(tc_path_utils, test_dirname_and_basename_neg);
tcase_add_test(tc_path_utils, test_is_absolute_path);
tcase_add_test(tc_path_utils, test_path_concat);
tcase_add_test(tc_path_utils, test_path_concat_neg);
tcase_add_test(tc_path_utils, test_split_path);
tcase_add_test(tc_path_utils, test_split_path_neg);
tcase_add_test(tc_path_utils, test_make_path_absolute);
tcase_add_test(tc_path_utils, test_make_path_absolute_neg);
tcase_add_test(tc_path_utils, test_normalize_path);
tcase_add_test(tc_path_utils, test_normalize_path_neg);
tcase_add_test(tc_path_utils, test_make_normalized_absolute_path);
tcase_add_test(tc_path_utils, test_make_normalized_absolute_path_neg);
tcase_add_test(tc_path_utils, test_common_path_prefix);
tcase_add_test(tc_path_utils, test_common_path_prefix_neg);
tcase_add_test(tc_path_utils, test_find_existing_directory_ancestor);
tcase_add_test(tc_path_utils, test_find_existing_directory_ancestor_neg);
tcase_add_test(tc_path_utils, test_is_ancestor_path);
tcase_add_checked_fixture(tc_directory_list,
setup_directory_list,
teardown_directory_list);
tcase_add_test(tc_directory_list, test_directory_list);
tcase_add_test(tc_directory_list, test_directory_list_neg);
suite_add_tcase(s, tc_path_utils);
suite_add_tcase(s, tc_directory_list);
return s;
}
int main(void)
{
int number_failed;
Suite *s = path_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;
}

775
tests/sanity/ref_array_ut.c Normal file
View File

@ -0,0 +1,775 @@
/*
REF ARRAY
Implementation of the dynamic array with reference count.
Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
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 <errno.h> /* for errors */
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ref_array.h"
#define TRACE_HOME
#include "trace.h"
int verbose = 0;
#define RAOUT(foo) \
do { \
if (verbose) foo; \
} while(0)
typedef int (*test_fn)(void);
/* Basic test */
static int ref_array_basic_test(void)
{
const char *line1 = "line1";
const char *line2 = "line2";
const char *line3 = "line3";
const char *line4 = "line4";
const char *line5 = "line5";
const char *line6 = "line6";
uint32_t i;
struct ref_array *ra;
struct ref_array *ra2;
int error = EOK;
uint32_t len = 0;
uint32_t other_len = 0;
char *ret;
char *elem;
void *ptr;
error = ref_array_create(&ra, sizeof(char *), 1, NULL, NULL);
if (error) {
printf("Failed to create array %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line1);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 1 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line2);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 2 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line3);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 3 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line4);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 4 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line5);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 5 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line6);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 6 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
RAOUT(printf("\n\nTest 1 - Printing lines.\n\n"));
error = ref_array_getlen(ra, &other_len);
if (error) {
ref_array_destroy(ra);
printf("Failed to get length %d\n", error);
return error;
}
len = ref_array_len(ra);
if (len != other_len) {
ref_array_destroy(ra);
printf("Lengths do not match:\n");
printf("Len : %d\n", len);
printf("Get Len: %d\n", other_len);
return EFAULT;
}
for (i = 0; i < len; i++) {
ref_array_get(ra, i, &ret);
RAOUT(printf("%s\n", ret));
}
RAOUT(printf("\n\nTest 2 - Creating reference and then printing lines.\n\n"));
ra2 = ref_array_getref(ra);
ref_array_destroy(ra);
for (i = 0; i < len; i++) {
ret = *((char **)ref_array_get(ra2, i, NULL));
RAOUT(printf("%s\n", ret));
}
RAOUT(printf("\n\nTest 3 - Get elements with copying.\n\n"));
for (i = 0; i < len; i++) {
ref_array_get(ra2, i, &ret);
RAOUT(printf("%s\n", ret));
}
RAOUT(printf("\n\nTest 4a - Get elements with copying and assignment.\n\n"));
/* This is a bad practice to use one variable
* as a parameter and as an acceptor for the return value.
* See next example for a better way to do it.
*/
for (i = 0; i < len; i++) {
ret = *((char **)ref_array_get(ra2, i, &ret));
RAOUT(printf("%s\n", ret));
}
RAOUT(printf("\n\nTest 4b - Get elements with copying and assignment.\n\n"));
for (i = 0; i < len; i++) {
ret = *((char **)ref_array_get(ra2, i, &elem));
RAOUT(printf("%s\n", ret));
RAOUT(printf("%s\n", elem));
if (strcmp(ret, elem) != 0) {
ref_array_destroy(ra2);
printf("\nRetrieved strings were expected to be same,\n");
printf("but they are not:\n");
printf("By pointer:[%s]\nAs element:[%s]\n", ret, elem);
return EFAULT;
}
}
RAOUT(printf("\n\nTest 5 - While loop up.\n\n"));
i = 0;
for (;;) {
ptr = ref_array_get(ra2, i, &ret);
if (ptr) {
RAOUT(printf("%s\n", ret));
i++;
}
else break;
}
RAOUT(printf("\n\nTest 6 - While loop down.\n\n"));
i = len - 1;
for (;;) {
ptr = ref_array_get(ra2, i, &ret);
if (ptr) {
RAOUT(printf("%s\n", ret));
i--;
}
else break;
}
RAOUT(printf("\n\nDone!!!\n\n"));
ref_array_destroy(ra2);
return EOK;
}
static void array_cleanup(void *elem,
ref_array_del_enum type,
void *data)
{
RAOUT(printf("%s%s\n", (char *)data, *((char **)elem)));
free(*((char **)elem));
}
/* Free test */
static int ref_array_free_test(void)
{
const char *line1 = "line1";
const char *line2 = "line2";
const char *line3 = "line3";
const char *line4 = "line4";
char text[] = "Deleting: ";
char *str;
uint32_t i;
struct ref_array *ra;
int error = EOK;
char *ret;
void *ptr;
error = ref_array_create(&ra, sizeof(char *), 1, array_cleanup, (char *)text);
if (error) {
printf("Failed to create array %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
str = strdup(line1);
error = ref_array_append(ra, &str);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 1 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
str = strdup(line2);
error = ref_array_append(ra, &str);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 2 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
str = strdup(line3);
error = ref_array_append(ra, &str);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 3 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
str = strdup(line4);
error = ref_array_append(ra, &str);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 4 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
i = 0;
for (;;) {
ptr = ref_array_get(ra, i, &ret);
if (ptr) {
RAOUT(printf("%s\n", ret));
i++;
}
else break;
}
RAOUT(printf("\n\nDone!!!\n\n"));
ref_array_destroy(ra);
return EOK;
}
static int ref_array_adv_test(void)
{
int error = EOK;
const char *lines[] = { "line0",
"line1",
"line2",
"line3",
"line4",
"line5",
"line6",
"line7",
"line8",
"line9" };
char text[] = "Deleting: ";
char *str;
uint32_t i;
struct ref_array *ra;
char *ret;
void *ptr;
int expected[] = { 0, 1, 7, 8, 9 };
int expected2[] = { 1, 7, 8, 9, 0 };
error = ref_array_create(&ra,
sizeof(char *),
1,
array_cleanup,
(char *)text);
if (error) {
printf("Failed to create array %d\n", error);
return error;
}
for (i = 0; i < 5;i++) {
str = strdup(lines[i]);
error = ref_array_append(ra, &str);
if (error) {
ref_array_destroy(ra);
printf("Failed to append line %d, error %d\n",
i, error);
return error;
}
}
RAOUT(printf("\nInitial array.\n"));
i = 0;
for (;;) {
ptr = ref_array_get(ra, i, &ret);
if (ptr) {
RAOUT(printf("%s\n", ret));
i++;
}
else break;
}
/* Try to remove invalid entry */
error = ref_array_remove(ra, 1000);
if (error != ERANGE) {
ref_array_destroy(ra);
printf("Removing entry expected error got success.\n");
return -1;
}
/* Try to insert invalid entry */
error = ref_array_insert(ra, 1000, &text);
if (error != ERANGE) {
ref_array_destroy(ra);
printf("Inserting entry expected error got success.\n");
return -1;
}
/* Try to replace invalid entry */
error = ref_array_replace(ra, 1000, &text);
if (error != ERANGE) {
ref_array_destroy(ra);
printf("Replacing entry expected error got success.\n");
return -1;
}
/* Insert several entries */
for (i = 9; i > 4; i--) {
str = strdup(lines[i]);
error = ref_array_insert(ra, 9 - i, &str);
if (error) {
ref_array_destroy(ra);
free(str);
printf("Failed to insert line %d, error %d\n",
i, error);
return error;
}
}
/* Displpay array contents */
RAOUT(printf("\nArray with inserted values.\n"));
i = 0;
for (;;) {
ptr = ref_array_get(ra, i, &ret);
if (ptr) {
RAOUT(printf("%s\n", ret));
i++;
}
else break;
}
/* Replace everything */
for (i = 0; i < 10;i++) {
str = strdup(lines[i]);
error = ref_array_replace(ra, i, &str);
if (error) {
ref_array_destroy(ra);
free(str);
printf("Failed to replace line %d, error %d\n",
i, error);
return error;
}
}
/* Displpay array contents */
RAOUT(printf("\nArray with replaced values.\n"));
i = 0;
for (;;) {
ptr = ref_array_get(ra, i, &ret);
if (ptr) {
RAOUT(printf("%s\n", ret));
i++;
}
else break;
}
/* Reset */
ref_array_reset(ra);
/* Displpay array contents */
RAOUT(printf("\nEmpty array.\n"));
i = 0;
for (;;) {
ptr = ref_array_get(ra, i, &ret);
if (ptr) {
RAOUT(printf("%s\n", ret));
i++;
}
else break;
}
/* Add everything */
for (i = 0; i < 10;i++) {
str = strdup(lines[i]);
error = ref_array_insert(ra, i, &str);
if (error) {
ref_array_destroy(ra);
free(str);
printf("Failed to insert into array %d\n", error);
return error;
}
}
/* Displpay array contents */
RAOUT(printf("\nAll added back.\n"));
i = 0;
for (;;) {
ptr = ref_array_get(ra, i, &ret);
if (ptr) {
RAOUT(printf("%s\n", ret));
i++;
}
else break;
}
/* Remove part */
for (i = 0; i < 5;i++) {
error = ref_array_remove(ra, 2);
if (error) {
ref_array_destroy(ra);
printf("Failed to remive item from array %d\n", error);
return error;
}
}
/* Displpay array contents */
RAOUT(printf("\nCleaned array.\n"));
i = 0;
for (;;) {
ptr = ref_array_get(ra, i, &ret);
if (ptr) {
RAOUT(printf("%s\n", ret));
i++;
}
else break;
}
RAOUT(printf("\n\nChecking for expected contents\n\n"));
i = 0;
for (;;) {
ptr = ref_array_get(ra, i, &ret);
if (ptr) {
RAOUT(printf("Comparing:\n[%s]\n[%s]\n\n",
ret, lines[expected[i]]));
if (strcmp(ret, lines[expected[i]]) != 0) {
printf("Unexpected contents of the array.\n");
ref_array_destroy(ra);
return -1;
}
i++;
}
else break;
}
RAOUT(printf("\n\nSwap test\n\n"));
if ((error = ref_array_swap(ra, 0, 1)) ||
(error = ref_array_swap(ra, 1, 2)) ||
(error = ref_array_swap(ra, 2, 3)) ||
(error = ref_array_swap(ra, 3, 4))) {
ref_array_destroy(ra);
printf("Failed to to swap %d\n", error);
return error;
}
i = 0;
for (;;) {
ptr = ref_array_get(ra, i, &ret);
if (ptr) {
RAOUT(printf("Comparing:\n[%s]\n[%s]\n\n",
ret, lines[expected2[i]]));
if (strcmp(ret, lines[expected2[i]]) != 0) {
printf("Unexpected contents of the array.\n");
ref_array_destroy(ra);
return -1;
}
i++;
}
else break;
}
RAOUT(printf("\n\nDone!!!\n\n"));
ref_array_destroy(ra);
return EOK;
}
static int copy_cb(void *elem,
void *new_elem)
{
char *ne = NULL;
ne = strdup(*((char **)elem));
*((char **)new_elem) = ne;
RAOUT(printf("Source: %s\nCopy:%s\n", *((char **)elem), ne));
return EOK;
}
static int ref_array_copy_test(void)
{
const char *line1 = "line1";
const char *line2 = "line2";
const char *line3 = "line3";
const char *line4 = "line4";
const char *line5 = "line5";
const char *line6 = "line6";
uint32_t i;
struct ref_array *ra;
struct ref_array *ra2;
int error = EOK;
uint32_t len = 6;
char text[] = "Deleting: ";
error = ref_array_create(&ra, sizeof(char *), 1, NULL, NULL);
if (error) {
printf("Failed to create array %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line1);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 1 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line2);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 2 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line3);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 3 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line4);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 4 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line5);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 5 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
error = ref_array_append(ra, &line6);
if (error) {
ref_array_destroy(ra);
printf("Failed to append to array line 6 %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 0));
RAOUT(printf("\n\nCopy lines.\n\n"));
error = ref_array_copy(ra, copy_cb, array_cleanup, (char *)text, &ra2);
if (error) {
ref_array_destroy(ra);
printf("Failed to copy array %d\n", error);
return error;
}
for (i = 0; i < len; i++) {
if (strcmp(*((char **)ref_array_get(ra, i, NULL)),
*((char **)ref_array_get(ra2, i, NULL))) != 0) {
printf("\nRetrieved strings were expected to be same,\n");
printf("but they are not:\n");
printf("First:[%s]\nSecond:[%s]\n",
*((char **)ref_array_get(ra, i, NULL)),
*((char **)ref_array_get(ra2, i, NULL)));
ref_array_destroy(ra);
ref_array_destroy(ra2);
return EFAULT;
}
}
RAOUT(printf("\n\nSource array.\n\n"));
RAOUT(ref_array_debug(ra, 0));
ref_array_destroy(ra);
RAOUT(printf("\n\nAbout to destroy a copy.\n\n"));
RAOUT(ref_array_debug(ra2, 0));
ref_array_destroy(ra2);
RAOUT(printf("\n\nDone!!!\n\n"));
return EOK;
}
static int ref_array_copy_num_test(void)
{
uint32_t i,j,k;
struct ref_array *ra;
struct ref_array *ra2;
int error = EOK;
uint32_t len = 5;
error = ref_array_create(&ra, sizeof(uint32_t), 1, NULL, NULL);
if (error) {
printf("Failed to create array %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 1));
for (i = 0; i < len; i++) {
error = ref_array_append(ra, &i);
if (error) {
ref_array_destroy(ra);
printf("Failed to append number to array %d\n", error);
return error;
}
RAOUT(ref_array_debug(ra, 1));
}
RAOUT(printf("\n\nCopy num test.\n\n"));
error = ref_array_copy(ra, NULL, NULL, NULL, &ra2);
if (error) {
ref_array_destroy(ra);
printf("Failed to copy array %d\n", error);
return error;
}
for (i = 0; i < len; i++) {
j = *((uint32_t *)(ref_array_get(ra, i, NULL)));
k = *((uint32_t *)(ref_array_get(ra2, i, NULL)));
if (j != k) {
printf("\nRetrieved values were expected to be same,\n");
printf("but they are not:\n");
printf("First:[%d]\nSecond:[%d]\n", j, k);
ref_array_destroy(ra);
ref_array_destroy(ra2);
return EFAULT;
}
}
ref_array_destroy(ra);
ref_array_destroy(ra2);
RAOUT(printf("\n\nDone!!!\n\n"));
return EOK;
}
/* Main function of the unit test */
int main(int argc, char *argv[])
{
int error = 0;
test_fn tests[] = { ref_array_basic_test,
ref_array_free_test,
ref_array_adv_test,
ref_array_copy_test,
ref_array_copy_num_test,
NULL };
test_fn t;
int i = 0;
char *var;
if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = 1;
else {
var = getenv("COMMON_TEST_VERBOSE");
if (var) verbose = 1;
}
RAOUT(printf("Start\n"));
while ((t = tests[i++])) {
error = t();
if (error) {
RAOUT(printf("Failed with error %d!\n", error));
return error;
}
}
RAOUT(printf("Success!\n"));
return 0;
}

View File

@ -0,0 +1,145 @@
/*
Simple buffer UNIT test
Basic buffer manipulation routines.
Copyright (C) Dmitri Pal <dpal@redhat.com> 2010
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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#define TRACE_HOME
#include "trace.h"
#include "simplebuffer.h"
int verbose = 0;
#define BOOUT(foo) \
do { \
if (verbose) foo; \
} while(0)
static int simple_test(void)
{
int error = EOK;
struct simplebuffer *data = NULL;
char str1[] = "test string 1";
char str2[] = "test string 2";
const char str3[] = "test string 3";
uint32_t left = 0;
int i;
const unsigned char *buf;
BOOUT(printf("Simple test start.\n"));
error = simplebuffer_alloc(&data);
if (error) {
printf("Failed to allocate object %d\n", error);
return error;
}
error = simplebuffer_add_raw(data,
(void *)str1,
strlen(str1),
1);
if (error) {
printf("Failed to add string to an object %d\n", error);
simplebuffer_free(data);
return error;
}
error = simplebuffer_add_cr(data);
if (error) {
printf("Failed to add CR to an object %d\n", error);
simplebuffer_free(data);
return error;
}
error = simplebuffer_add_raw(data,
(void *)str2,
strlen(str2),
1);
if (error) {
printf("Failed to add string to an object %d\n", error);
simplebuffer_free(data);
return error;
}
error = simplebuffer_add_cr(data);
if (error) {
printf("Failed to add CR to an object %d\n", error);
simplebuffer_free(data);
return error;
}
error = simplebuffer_add_str(data,
str3,
strlen(str3),
1);
if (error) {
printf("Failed to add string to an object %d\n", error);
simplebuffer_free(data);
return error;
}
left = simplebuffer_get_len(data);
buf = simplebuffer_get_buf(data);
BOOUT(for(i = 0; i < left; i++) {
printf("%02d: %02X\n", i, buf[i]);
});
if (verbose) {
while (left > 0) {
error = simplebuffer_write(1, data, &left);
if (error) {
printf("Failed to write to output %d\n", error);
simplebuffer_free(data);
return error;
}
}
}
BOOUT(printf("\n[%s]\n", simplebuffer_get_buf(data)));
BOOUT(printf("Length: %d\n", simplebuffer_get_len(data)));
simplebuffer_free(data);
BOOUT(printf("Simple test end.\n"));
return error;
}
int main(int argc, char *argv[])
{
int error = EOK;
if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = 1;
BOOUT(printf("Start\n"));
if ((error = simple_test())) {
printf("Test failed! Error %d.\n", error);
return -1;
}
BOOUT(printf("Success!\n"));
return 0;
}

175
tests/sanity/trace.h Normal file
View File

@ -0,0 +1,175 @@
/*
COMMON TRACE
Common header file for tracing.
Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
This program 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.
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 Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMMON_TRACE_H
#define COMMON_TRACE_H
#ifdef TRACE_LEVEL
#define HAVE_TRACE
#include <stdio.h>
/* The trace level is a bit mask */
#define TRACE_FLOW 0x0000001 /* - trace messages that are entry exit into functions */
#define TRACE_ERROR 0x0000002 /* - trace messages that are errors */
#define TRACE_INFO 0x0000004 /* - trace things that are informational */
#ifdef TRACE_HOME /* Define this in the module that contains main */
unsigned trace_level = TRACE_LEVEL;
#else
extern unsigned trace_level;
#endif /* TRACE_HOME */
#endif /* TRACE_LEVEL */
#ifdef HAVE_TRACE
/* Tracing strings */
#define TRACE_STRING(level, msg, str) \
do { \
if (level & trace_level) { \
printf("[DEBUG] %40s (%4d) %s%s %s\n", \
__FILE__, __LINE__, \
(level == TRACE_ERROR) ? "ERROR-> " : "", \
(msg != NULL) ? msg : "MISSING MESSAGE", \
(str != NULL) ? str : "(null)"); \
} \
} while(0)
/* Tracing unsigned numbers */
#define TRACE_NUMBER(level, msg, num) \
do { \
if (level & trace_level) { \
printf("[DEBUG] %40s (%4d) %s%s %lu\n", \
__FILE__, __LINE__, \
(level == TRACE_ERROR) ? "ERROR-> " : "", \
(msg != NULL) ? msg : "MISSING MESSAGE", \
(unsigned long int)(num)); \
} \
} while(0)
/* Tracing signed numbers */
#define TRACE_SNUMBER(level, msg, num) \
do { \
if (level & trace_level) { \
printf("[DEBUG] %40s (%4d) %s%s %ld\n", \
__FILE__, __LINE__, \
(level == TRACE_ERROR) ? "ERROR-> " : "", \
(msg != NULL) ? msg : "MISSING MESSAGE", \
(long int)(num)); \
} \
} while(0)
/* Tracing long numbers */
#define TRACE_LNUMBER(level, msg, num) \
do { \
if (level & trace_level) { \
printf("[DEBUG] %40s (%4d) %s%s %llu\n", \
__FILE__, __LINE__, \
(level == TRACE_ERROR) ? "ERROR-> " : "", \
(msg != NULL) ? msg : "MISSING MESSAGE", \
(unsigned long long int)(num)); \
} \
} while(0)
/* Tracing signed long numbers */
#define TRACE_SLNUMBER(level, msg, num) \
do { \
if (level & trace_level) { \
printf("[DEBUG] %40s (%4d) %s%s %lld\n", \
__FILE__, __LINE__, \
(level == TRACE_ERROR) ? "ERROR-> " : "", \
(msg != NULL) ? msg : "MISSING MESSAGE", \
(long long int)(num)); \
} \
} while(0)
/* Tracing doubles */
#define TRACE_DOUBLE(level, msg, num) \
do { \
if (level & trace_level) { \
printf("[DEBUG] %40s (%4d) %s%s %e\n", \
__FILE__, __LINE__, \
(level == TRACE_ERROR) ? "ERROR-> " : "", \
(msg != NULL) ? msg : "MISSING MESSAGE", \
(double)(num)); \
} \
} while(0)
#define TRACE_RETURN(flow, val) \
do { \
char mstr[200]; \
sprintf(mstr, "%s returning:", __FUNCTION__); \
flow(mstr, val); \
} while(0)
/* Assertion */
#define TRACE_ASSERT(expression) expression ? : printf("ASSERTION FAILED\n")
#else /* HAVE_TRACE */
/* Noop in case the tracing is disabled */
#define TRACE_STRING(level, msg, str)
#define TRACE_NUMBER(level, msg, num)
#define TRACE_SNUMBER(level, msg, num)
#define TRACE_LNUMBER(level, msg, num)
#define TRACE_SLNUMBER(level, msg, num)
#define TRACE_DOUBLE(level, msg, num)
#define TRACE_RETURN(flow, val)
#define TRACE_ASSERT(expression)
#endif /* HAVE_TRACE */
/* Convenience wrappers for strings */
#define TRACE_FLOW_STRING(msg, str) TRACE_STRING(TRACE_FLOW, msg, str)
#define TRACE_ERROR_STRING(msg, str) TRACE_STRING(TRACE_ERROR, msg, str)
#define TRACE_INFO_STRING(msg, str) TRACE_STRING(TRACE_INFO, msg, str)
/* Convenience wrappers for unsigned numbers */
#define TRACE_FLOW_NUMBER(msg, num) TRACE_NUMBER(TRACE_FLOW, msg, num)
#define TRACE_ERROR_NUMBER(msg, num) TRACE_NUMBER(TRACE_ERROR, msg, num)
#define TRACE_INFO_NUMBER(msg, num) TRACE_NUMBER(TRACE_INFO, msg, num)
/* Convenience wrappers for signed numbers */
#define TRACE_FLOW_SNUMBER(msg, num) TRACE_SNUMBER(TRACE_FLOW, msg, num)
#define TRACE_ERROR_SNUMBER(msg, num) TRACE_SNUMBER(TRACE_ERROR, msg, num)
#define TRACE_INFO_SNUMBER(msg, num) TRACE_SNUMBER(TRACE_INFO, msg, num)
/* Convenience wrappers for 64-bit long unsigned numbers */
#define TRACE_FLOW_LNUMBER(msg, num) TRACE_LNUMBER(TRACE_FLOW, msg, num)
#define TRACE_ERROR_LNUMBER(msg, num) TRACE_LNUMBER(TRACE_ERROR, msg, num)
#define TRACE_INFO_LNUMBER(msg, num) TRACE_LNUMBER(TRACE_INFO, msg, num)
/* Convenience wrappers for 64-bit long signed numbers */
#define TRACE_FLOW_SLNUMBER(msg, num) TRACE_SLNUMBER(TRACE_FLOW, msg, num)
#define TRACE_ERROR_SLNUMBER(msg, num) TRACE_SLNUMBER(TRACE_ERROR, msg, num)
#define TRACE_INFO_SLNUMBER(msg, num) TRACE_SLNUMBER(TRACE_INFO, msg, num)
/* Convenience wrappers for numbers */
#define TRACE_FLOW_DOUBLE(msg, num) TRACE_DOUBLE(TRACE_FLOW, msg, num)
#define TRACE_ERROR_DOUBLE(msg, num) TRACE_DOUBLE(TRACE_ERROR, msg, num)
#define TRACE_INFO_DOUBLE(msg, num) TRACE_DOUBLE(TRACE_INFO, msg, num)
/* Some other nice wrappers for function entry and exit */
#define TRACE_FLOW_ENTRY() TRACE_FLOW_STRING(__FUNCTION__, "Entry")
#define TRACE_FLOW_EXIT() TRACE_FLOW_STRING(__FUNCTION__, "Exit")
#define TRACE_FLOW_RETURN(val) TRACE_RETURN(TRACE_FLOW_NUMBER, val)
#endif /* COMMON_TRACE_H */

28
tests/tests.yml Normal file
View File

@ -0,0 +1,28 @@
- hosts: localhost
roles:
- role: standard-test-basic
tags:
- classic
tests:
- sanity:
dir: sanity
run: ./ding-libs-tests.sh
required_packages:
- check
- check-devel
- libbasicobjects
- libbasicobjects-devel
- libref_array
- libref_array-devel
- libcollection
- libcollection-devel
- libdhash
- libdhash-devel
- libconfig
- libconfig-devel
- libini_config
- libini_config-devel
- libpath_utils
- libpath_utils-devel
- make
- gcc