ding-libs/tests/sanity/ini_valueobj_ut.c
Steeve Goveas f8513f5719 Enable gating for ding-libs
Resolves: rhbz#1962772

sssd-team is added as a recipient
2021-05-28 21:10:08 +05:30

742 lines
19 KiB
C

/*
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;
}