Compare commits

...

10 Commits

Author SHA1 Message Date
Alexey Tikhonov cdc33cf04b Resolves: rhbz#2048667 - Request to add libdhash-devel package into CRB (spec-file update to fix rpminspect warnings) 2023-05-18 10:50:52 +00:00
Alexey Tikhonov ec96671f5c Resolves: rhbz#2048667 - Request to add libdhash-devel package into CRB 2022-05-11 20:14:18 +02:00
Alexey Tikhonov 37a9f0f6a1 Resolves: rhbz#1938708 - review of important potential issues detected by static analyzers in ding-libs-0.6.1-47.el9 2021-08-10 14:32:16 +02:00
Mohan Boddu ca01f05d4d Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
Signed-off-by: Mohan Boddu <mboddu@redhat.com>
2021-08-09 19:48:53 +00:00
Alexey Tikhonov 72820db11b Resolves: rhbz#1962772 - Add gating tests for ding-libs in RHEL 9 2021-06-01 15:31:34 +02:00
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
Mohan Boddu 8114919277 - Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
Signed-off-by: Mohan Boddu <mboddu@redhat.com>
2021-04-15 23:05:08 +00:00
DistroBaker bacb23b570 Merged update from upstream sources
This is an automated DistroBaker update from upstream sources.
If you do not know what this is about or would like to opt out,
contact the OSCI team.

Source: https://src.fedoraproject.org/rpms/ding-libs.git#bc648d4069b455bd56a0361b4533b264194fee1c
2021-02-03 12:59:40 +01:00
Petr Šabata ea7d5246c3 Bump for gcc11
Signed-off-by: Petr Šabata <contyk@redhat.com>
2020-12-18 21:45:26 +01:00
Petr Šabata 59faf7cede RHEL 9.0.0 Alpha bootstrap
The content of this branch was automatically imported from Fedora ELN
with the following as its source:
https://src.fedoraproject.org/rpms/ding-libs#0f0dd65bd45abeb79cc9dcc86f2e5a1fcf30b251
2020-10-14 23:39:09 +02:00
29 changed files with 10270 additions and 0 deletions

1
.ding-libs.metadata Normal file
View File

@ -0,0 +1 @@
dab4c855b065bd728021437af81ae726c31c5272 ding-libs-0.6.1.tar.gz

9
.gitignore vendored
View File

@ -0,0 +1,9 @@
/ding-libs-0.1.2.tar.gz
/ding-libs-0.1.3.tar.gz
/ding-libs-0.2.91.tar.gz
/ding-libs-0.3.0.tar.gz
/ding-libs-0.3.0.1.tar.gz
/ding-libs-0.4.0.tar.gz
/ding-libs-0.5.0.tar.gz
/ding-libs-0.6.0.tar.gz
/ding-libs-0.6.1.tar.gz

View File

@ -0,0 +1,40 @@
From ec6817736968fb4683b9df0bd932c1a86dec0ba8 Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikhono@redhat.com>
Date: Wed, 4 Aug 2021 19:22:19 +0200
Subject: [PATCH 4/6] INI: fix check for error code
In case of fail `asprintf()` returns -1, not 1.
Fixes following covscan issues:
```
Error: RESOURCE_LEAK (CWE-772): [#def1]
ding-libs-0.6.1/ini/ini_configmod.c:869: alloc_arg: "asprintf" allocates memory that is stored into "strval". [Note: The source code implementation of the function has been overridden by a builtin model.]
ding-libs-0.6.1/ini/ini_configmod.c:873: leaked_storage: Variable "strval" going out of scope leaks the storage it points to.
# 871| TRACE_ERROR_NUMBER("Asprintf failed.", ret);
# 872| /* The main reason is propbaly memory allocation */
# 873|-> return ENOMEM;
# 874| }
# 875|
```
Reviewed-by: Pawel Polawski <ppolawsk@redhat.com>
---
ini/ini_configmod.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ini/ini_configmod.c b/ini/ini_configmod.c
index da4175c..88a7133 100644
--- a/ini/ini_configmod.c
+++ b/ini/ini_configmod.c
@@ -867,7 +867,7 @@ int ini_config_add_double_value(struct ini_cfgobj *ini_config,
TRACE_FLOW_ENTRY();
ret = asprintf(&strval, "%f", value);
- if (ret == 1) {
+ if (ret == -1) {
TRACE_ERROR_NUMBER("Asprintf failed.", ret);
/* The main reason is propbaly memory allocation */
return ENOMEM;
--
2.26.3

View File

@ -0,0 +1,58 @@
From 82ee1cff9d7401f4381cfa574f8b102625b06a31 Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikhono@redhat.com>
Date: Thu, 5 Aug 2021 18:02:57 +0200
Subject: [PATCH 5/6] PATH_UTILS: suppress false positive warnings
Warnings are false positives: every such `strncpy` is followed
by an explicit check that result is NULL-terminated.
Reviewed-by: Pawel Polawski <ppolawsk@redhat.com>
---
path_utils/path_utils.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/path_utils/path_utils.c b/path_utils/path_utils.c
index 61605ab..5203cc9 100644
--- a/path_utils/path_utils.c
+++ b/path_utils/path_utils.c
@@ -116,6 +116,7 @@ int get_basename(char *base_name, size_t base_name_size, const char *path)
if (!path) return EINVAL;
if (!base_name || base_name_size < 1) return ENOBUFS;
+ /* coverity[buffer_size_warning : SUPPRESS] */ /* false positive warning */
strncpy(tmp_path, path, sizeof(tmp_path));
if (tmp_path[sizeof(tmp_path)-1] != '\0') return ENOBUFS;
strncpy(base_name, basename(tmp_path), base_name_size);
@@ -137,6 +138,7 @@ int get_dirname(char *dir_path, size_t dir_path_size, const char *path)
if (!path) return EINVAL;
if (!dir_path || dir_path_size < 1) return ENOBUFS;
+ /* coverity[buffer_size_warning : SUPPRESS] */ /* false positive warning */
strncpy(tmp_path, path, sizeof(tmp_path));
if (tmp_path[sizeof(tmp_path)-1] != '\0') return ENOBUFS;
strncpy(dir_path, dirname(tmp_path), dir_path_size);
@@ -161,11 +163,13 @@ int get_directory_and_base_name(char *dir_path, size_t dir_path_size,
if (!dir_path || dir_path_size < 1) return ENOBUFS;
if (!base_name || base_name_size < 1) return ENOBUFS;
+ /* coverity[buffer_size_warning : SUPPRESS] */ /* false positive warning */
strncpy(tmp_path, path, sizeof(tmp_path));
if (tmp_path[sizeof(tmp_path)-1] != '\0') return ENOBUFS;
strncpy(base_name, basename(tmp_path), base_name_size);
if (base_name[base_name_size-1] != '\0') return ENOBUFS;
+ /* coverity[buffer_size_warning : SUPPRESS] */ /* false positive warning */
strncpy(tmp_path, path, sizeof(tmp_path));
if (tmp_path[sizeof(tmp_path)-1] != '\0') return ENOBUFS;
strncpy(dir_path, dirname(tmp_path), dir_path_size);
@@ -528,6 +532,7 @@ int find_existing_directory_ancestor(char *ancestor, size_t ancestor_size, const
if (!ancestor || ancestor_size < 1) return ENOBUFS;
*ancestor = 0;
+ /* coverity[buffer_size_warning : SUPPRESS] */ /* false positive warning */
strncpy(dir_path, path, sizeof(dir_path));
if (dir_path[sizeof(dir_path)-1] != '\0') return ENOBUFS;
--
2.26.3

View File

@ -0,0 +1,28 @@
From 584dc25f2c31f4d8e5cf7154e0362e4d2504779c Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikhono@redhat.com>
Date: Thu, 5 Aug 2021 18:48:23 +0200
Subject: [PATCH 6/6] INI: suppress false positive coverity warning
`get_str_cfg_array()` returns `char **array` that is composed of pointers
to slices of `copy` so `copy` can't be freed here.
Reviewed-by: Pawel Polawski <ppolawsk@redhat.com>
---
ini/ini_get_array.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/ini/ini_get_array.c b/ini/ini_get_array.c
index 30ed423..95d0b05 100644
--- a/ini/ini_get_array.c
+++ b/ini/ini_get_array.c
@@ -164,6 +164,7 @@ static char **get_str_cfg_array(struct collection_item *item,
/* If count is 0 the copy needs to be freed */
if (count == 0) free(copy);
TRACE_FLOW_STRING("get_str_cfg_array", "Exit");
+ /* coverity[leaked_storage : SUPPRESS] */ /* false positive warning */
return array;
}
--
2.26.3

View File

@ -0,0 +1,47 @@
From 72c19bd018b107ecf5a80963b433e9922f7243fd Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn@redhat.com>
Date: Wed, 3 Jan 2018 18:03:44 +0100
Subject: [PATCH 01/11] INI: Fix detection of error messages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
libc on BSD returns different error messages.
Reviewed-by: Michal Židek <mzidek@redhat.com>
---
ini/ini_validators_ut_check.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/ini/ini_validators_ut_check.c b/ini/ini_validators_ut_check.c
index fa7105a..9ecde75 100644
--- a/ini/ini_validators_ut_check.c
+++ b/ini/ini_validators_ut_check.c
@@ -607,6 +607,12 @@ START_TEST(test_ini_allowed_options_wrong_regex)
"[rule/options_for_foo]: Cannot compile regular expression "
"from option 'section_re'. "
"Error: 'Unmatched [ or [^'");
+ if (ret != 0) {
+ ret = strcmp(errmsg,
+ "[rule/options_for_foo]: Cannot compile regular expression "
+ "from option 'section_re'. "
+ "Error: 'brackets ([ ]) not balanced'");
+ }
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
@@ -1028,6 +1034,11 @@ START_TEST(test_ini_allowed_sections_wrong_regex)
ret = strcmp(errmsg,
"[rule/section_list]: Validator failed to use regex "
"[^foo\\(*$]:[Unmatched ( or \\(]");
+ if (ret !=0) {
+ ret = strcmp(errmsg,
+ "[rule/section_list]: Validator failed to use regex "
+ "[^foo\\(*$]:[parentheses not balanced]");
+ }
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
--
2.9.5

View File

@ -0,0 +1,34 @@
From 8509cfaa757c0f8cc4d79357613f46d2fd9ee878 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
Date: Wed, 15 Nov 2017 18:31:47 +0100
Subject: [PATCH] INI: Remove definiton of TRACE_LEVEL
Macros TRACE_LEVEL 7 and TRACE_HOME should only be defined
in testing builds where we want debug messages to be generated.
The macros are leftovers from the previous patch where they
were improperly added for debug purposes.
Resolves:
https://pagure.io/SSSD/ding-libs/issue/3182
Reviewed-by: Robbie Harwood <rharwood@redhat.com>
(cherry picked from commit a731d8c8c515e7e42a4fb448e0ecb6934d5bf99b)
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
---
ini/ini_augment.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/ini/ini_augment.c b/ini/ini_augment.c
index 9d83ad9..5a5a173 100644
--- a/ini/ini_augment.c
+++ b/ini/ini_augment.c
@@ -32,8 +32,6 @@
#include <sys/types.h>
#include <regex.h>
#include <unistd.h>
-#define TRACE_LEVEL 7
-#define TRACE_HOME
#include "trace.h"
#include "collection.h"
#include "collection_tools.h"

View File

@ -0,0 +1,96 @@
From 781fdebda1d9e62e224630efb8d4dd5da8fe5f69 Mon Sep 17 00:00:00 2001
From: Alexander Scheel <alexander.m.scheel@gmail.com>
Date: Mon, 30 Oct 2017 12:43:19 -0500
Subject: [PATCH] INI: Silence ini_augment match failures
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Resolves:
https://pagure.io/SSSD/ding-libs/issue/3182
Reviewed-by: Michal Židek <mzidek@redhat.com>
Signed-off-by: Alexander Scheel <alexander.m.scheel@gmail.com>
Merges: https://pagure.io/SSSD/ding-libs/pull-request/3183
(cherry picked from commit be9ca3a2c26b061d1f22bd4a09009bba7a01f67b)
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
---
ini/ini.d/merge.validator | 11 -----------
ini/ini_augment.c | 13 +++++++------
2 files changed, 7 insertions(+), 17 deletions(-)
diff --git a/ini/ini.d/merge.validator b/ini/ini.d/merge.validator
index 1defe8e..017c1cb 100644
--- a/ini/ini.d/merge.validator
+++ b/ini/ini.d/merge.validator
@@ -1,17 +1,8 @@
-File %s%s/merge.validator did not match provided patterns. Skipping.
-File %s%s/real8.conf did not match provided patterns. Skipping.
-File %s%s/new_line.conf did not match provided patterns. Skipping.
-File %s%s/real32be.conf did not match provided patterns. Skipping.
-File %s%s/real32le.conf did not match provided patterns. Skipping.
-File %s%s/real16be.conf did not match provided patterns. Skipping.
-File %s%s/real16le.conf did not match provided patterns. Skipping.
-File %s%s/foo.conf.in did not match provided patterns. Skipping.
Errors detected while parsing: %s%s/comment.conf.
Error (9) on line 22: Invalid space character at the beginning of the line.
Error (9) on line 24: Invalid space character at the beginning of the line.
Error (9) on line 26: Invalid space character at the beginning of the line.
Error (15) on line 32: Incomplete comment at the end of the file.
-No sections found in file %s%s/comment.conf. Skipping.
Section [section_a] found in file %s%s/first.conf is not allowed.
Section [section_c] found in file %s%s/first.conf is not allowed.
Section [section_b] found in file %s%s/first.conf is not allowed.
@@ -42,7 +33,6 @@ Error (9) on line 1: Invalid space character at the beginning of the line.
Error (9) on line 2: Invalid space character at the beginning of the line.
Error (9) on line 3: Invalid space character at the beginning of the line.
Error (9) on line 4: Invalid space character at the beginning of the line.
-No sections found in file %s%s/space.conf. Skipping.
Section [info] found in file %s%s/symbols.conf is not allowed.
Section [languages] found in file %s%s/symbols.conf is not allowed.
Section [text] found in file %s%s/symbols.conf is not allowed.
@@ -55,6 +45,5 @@ Error (9) on line 15: Invalid space character at the beginning of the line.
Error (9) on line 16: Invalid space character at the beginning of the line.
Error (9) on line 26: Invalid space character at the beginning of the line.
Error (9) on line 35: Invalid space character at the beginning of the line.
-No sections found in file %s%s/test.conf. Skipping.
%s%s/ipa.conf
%s%s/real.conf
diff --git a/ini/ini_augment.c b/ini/ini_augment.c
index af5c0b6..9d83ad9 100644
--- a/ini/ini_augment.c
+++ b/ini/ini_augment.c
@@ -32,6 +32,8 @@
#include <sys/types.h>
#include <regex.h>
#include <unistd.h>
+#define TRACE_LEVEL 7
+#define TRACE_HOME
#include "trace.h"
#include "collection.h"
#include "collection_tools.h"
@@ -456,10 +458,9 @@ static int ini_aug_construct_list(char *dirname ,
}
}
else {
- ini_aug_add_string(ra_err,
- "File %s did not match provided patterns."
- " Skipping.",
- fullname);
+ TRACE_INFO_STRING("File did not match provided patterns."
+ " Skipping:",
+ fullname);
}
}
@@ -609,8 +610,8 @@ static int ini_aug_match_sec(struct ini_cfgobj *snip_cfg,
/* Just in case check that we processed anything */
if (section_count == 0) {
- ini_aug_add_string(ra_err, "No sections found in file %s. Skipping.",
- snip_name);
+ TRACE_INFO_STRING("No sections found in file. Skipping:",
+ snip_name);
*skip = true;
TRACE_FLOW_EXIT();
return EOK;

View File

@ -0,0 +1,49 @@
From 9f9a3ded23cc2bb917468939b745cc498cec523a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
Date: Wed, 1 Aug 2018 17:48:10 +0200
Subject: [PATCH] validators_ut_check: Fix fail with new glibc
Error message was slightly change from previous version
of glibc which caused fails in validators unit tests.
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
ini/ini_validators_ut_check.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/ini/ini_validators_ut_check.c b/ini/ini_validators_ut_check.c
index 9ecde75..3af8551 100644
--- a/ini/ini_validators_ut_check.c
+++ b/ini/ini_validators_ut_check.c
@@ -602,6 +602,8 @@ START_TEST(test_ini_allowed_options_wrong_regex)
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
+ /* Different versions of libc produce slightly different error strings
+ * in this case. For simplicity compare against all of them. */
errmsg = ini_errobj_get_msg(errobj);
ret = strcmp(errmsg,
"[rule/options_for_foo]: Cannot compile regular expression "
@@ -609,10 +611,17 @@ START_TEST(test_ini_allowed_options_wrong_regex)
"Error: 'Unmatched [ or [^'");
if (ret != 0) {
ret = strcmp(errmsg,
- "[rule/options_for_foo]: Cannot compile regular expression "
- "from option 'section_re'. "
+ "[rule/options_for_foo]: Cannot compile regular "
+ "expression from option 'section_re'. "
"Error: 'brackets ([ ]) not balanced'");
}
+
+ if (ret != 0) {
+ ret = strcmp(errmsg,
+ "[rule/options_for_foo]: Cannot compile regular "
+ "expression from option 'section_re'. "
+ "Error: 'Unmatched [, [^, [:, [., or [='");
+ }
fail_unless(ret == 0, "Got msg: [%s]", errmsg);
ini_errobj_next(errobj);
--
2.9.5

529
ding-libs.spec Normal file
View File

@ -0,0 +1,529 @@
Name: ding-libs
Version: 0.6.1
Release: 53%{?dist}
Summary: "Ding is not GLib" assorted utility libraries
License: LGPLv3+
URL: https://pagure.io/SSSD/ding-libs
Source0: https://releases.pagure.org/SSSD/ding-libs/%{name}-%{version}.tar.gz
# If a new upstream release changes some, but not all of these
# version numbers, remember to keep the Release tag in order to
# allow clean upgrades!
%global path_utils_version 0.2.1
%global dhash_version 0.5.0
%global collection_version 0.7.0
%global ref_array_version 0.1.5
%global basicobjects_version 0.1.1
%global ini_config_version 1.3.1
### Patches ###
Patch0: INI-Silence-ini_augment-match-failures.patch
Patch1: INI-Remove-definiton-of-TRACE_LEVEL.patch
Patch2: INI-Fix-detection-of-error-messages.patch
Patch3: TEST-validators_ut_check-Fix-fail-with-new-glibc.patch
Patch4: 0004-INI-fix-check-for-error-code.patch
Patch5: 0005-PATH_UTILS-suppress-false-positive-warnings.patch
Patch6: 0006-INI-suppress-false-positive-coverity-warning.patch
### Dependencies ###
# ding-libs is a meta-package that will pull in all of its own
# sub-packages
Requires: libpath_utils = %{path_utils_version}-%{release}
Requires: libdhash = %{dhash_version}-%{release}
Requires: libcollection = %{collection_version}-%{release}
Requires: libref_array = %{ref_array_version}-%{release}
Requires: libbasicobjects = %{basicobjects_version}-%{release}
Requires: libini_config = %{ini_config_version}-%{release}
### Build Dependencies ###
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: gcc
BuildRequires: git
BuildRequires: libtool
BuildRequires: m4
BuildRequires: doxygen
BuildRequires: pkgconfig
BuildRequires: check-devel
BuildRequires: make
%description
A meta-package that pulls in libcollection, libdhash, libini_config,
librefarray libbasicobjects, and libpath_utils.
%package devel
Summary: Development packages for ding-libs
License: LGPLv3+
# ding-libs is a meta-package that will pull in all of its own
# sub-packages
Requires: libpath_utils-devel = %{path_utils_version}-%{release}
Requires: libdhash-devel = %{dhash_version}-%{release}
Requires: libcollection-devel = %{collection_version}-%{release}
Requires: libref_array-devel = %{ref_array_version}-%{release}
Requires: libbasicobjects-devel = %{basicobjects_version}-%{release}
Requires: libini_config-devel = %{ini_config_version}-%{release}
%description devel
A meta-package that pulls in development libraries for libcollection,
libdhash, libini_config, librefarray and libpath_utils.
##############################################################################
# Path Utils
##############################################################################
%package -n libpath_utils
Summary: Filesystem Path Utilities
License: LGPLv3+
Version: %{path_utils_version}
%description -n libpath_utils
Utility functions to manipulate filesystem pathnames
%package -n libpath_utils-devel
Summary: Development files for libpath_utils
Requires: libpath_utils = %{path_utils_version}-%{release}
License: LGPLv3+
Version: %{path_utils_version}
%description -n libpath_utils-devel
Utility functions to manipulate filesystem pathnames
%ldconfig_scriptlets -n libpath_utils
%files -n libpath_utils
%doc COPYING COPYING.LESSER
%{_libdir}/libpath_utils.so.1
%{_libdir}/libpath_utils.so.1.0.1
%files -n libpath_utils-devel
%{_includedir}/path_utils.h
%{_libdir}/libpath_utils.so
%{_libdir}/pkgconfig/path_utils.pc
%doc path_utils/README.path_utils
%doc path_utils/doc/html/
##############################################################################
# dhash
##############################################################################
%package -n libdhash
Summary: Dynamic hash table
License: LGPLv3+
Version: %{dhash_version}
%description -n libdhash
A hash table which will dynamically resize to achieve optimal storage & access
time properties
%package -n libdhash-devel
Summary: Development files for libdhash
Requires: libdhash = %{dhash_version}-%{release}
License: LGPLv3+
Version: %{dhash_version}
%description -n libdhash-devel
A hash table which will dynamically resize to achieve optimal storage & access
time properties
%ldconfig_scriptlets -n libdhash
%files -n libdhash
%doc COPYING COPYING.LESSER
%{_libdir}/libdhash.so.1
%{_libdir}/libdhash.so.1.1.0
%files -n libdhash-devel
%{_includedir}/dhash.h
%{_libdir}/libdhash.so
%{_libdir}/pkgconfig/dhash.pc
%doc dhash/README.dhash
%doc dhash/examples/*.c
##############################################################################
# collection
##############################################################################
%package -n libcollection
Summary: Collection data-type for C
License: LGPLv3+
Version: %{collection_version}
%description -n libcollection
A data-type to collect data in a hierarchical structure for easy iteration
and serialization
%package -n libcollection-devel
Summary: Development files for libcollection
License: LGPLv3+
Requires: libcollection = %{collection_version}-%{release}
Version: %{collection_version}
%description -n libcollection-devel
A data-type to collect data in a hierarchical structure for easy iteration
and serialization
%ldconfig_scriptlets -n libcollection
%files -n libcollection
%doc COPYING
%doc COPYING.LESSER
%{_libdir}/libcollection.so.*
%files -n libcollection-devel
%{_includedir}/collection.h
%{_includedir}/collection_tools.h
%{_includedir}/collection_queue.h
%{_includedir}/collection_stack.h
%{_libdir}/libcollection.so
%{_libdir}/pkgconfig/collection.pc
%doc collection/doc/html/
##############################################################################
# ref_array
##############################################################################
%package -n libref_array
Summary: A refcounted array for C
License: LGPLv3+
Version: %{ref_array_version}
%description -n libref_array
A dynamically-growing, reference-counted array
%package -n libref_array-devel
Summary: Development files for libref_array
Requires: libref_array = %{ref_array_version}-%{release}
License: LGPLv3+
Version: %{ref_array_version}
%description -n libref_array-devel
A dynamically-growing, reference-counted array
%ldconfig_scriptlets -n libref_array
%files -n libref_array
%doc COPYING
%doc COPYING.LESSER
%{_libdir}/libref_array.so.1
%{_libdir}/libref_array.so.1.2.1
%files -n libref_array-devel
%{_includedir}/ref_array.h
%{_libdir}/libref_array.so
%{_libdir}/pkgconfig/ref_array.pc
%doc refarray/README.ref_array
%doc refarray/doc/html/
##############################################################################
# basicobjects
##############################################################################
%package -n libbasicobjects
Summary: Basic object types for C
License: GPLv3+
Version: %{basicobjects_version}
%description -n libbasicobjects
Basic object types
%package -n libbasicobjects-devel
Summary: Development files for libbasicobjects
License: GPLv3+
Version: %{basicobjects_version}
Requires: libbasicobjects = %{basicobjects_version}-%{release}
%description -n libbasicobjects-devel
Basic object types
%ldconfig_scriptlets -n libbasicobjects
%files -n libbasicobjects
%doc COPYING
%doc COPYING.LESSER
%{_libdir}/libbasicobjects.so.0
%{_libdir}/libbasicobjects.so.0.1.0
%files -n libbasicobjects-devel
%{_includedir}/simplebuffer.h
%{_libdir}/libbasicobjects.so
%{_libdir}/pkgconfig/basicobjects.pc
##############################################################################
# ini_config
##############################################################################
%package -n libini_config
Summary: INI file parser for C
License: LGPLv3+
Requires: libcollection = %{collection_version}-%{release}
Requires: libref_array = %{ref_array_version}-%{release}
Requires: libbasicobjects = %{basicobjects_version}-%{release}
Requires: libpath_utils = %{path_utils_version}-%{release}
Version: %{ini_config_version}
%description -n libini_config
Library to process config files in INI format into a libcollection data
structure
%package -n libini_config-devel
Summary: Development files for libini_config
License: LGPLv3+
Requires: libini_config = %{ini_config_version}-%{release}
Requires: libcollection-devel = %{collection_version}-%{release}
Requires: libref_array-devel = %{ref_array_version}-%{release}
Requires: libbasicobjects-devel = %{basicobjects_version}-%{release}
Version: %{ini_config_version}
%description -n libini_config-devel
Library to process config files in INI format into a libcollection data
structure
%ldconfig_scriptlets -n libini_config
%files -n libini_config
%doc COPYING
%doc COPYING.LESSER
%{_libdir}/libini_config.so.5
%{_libdir}/libini_config.so.5.2.1
%files -n libini_config-devel
%{_includedir}/ini_config.h
%{_includedir}/ini_configobj.h
%{_includedir}/ini_valueobj.h
%{_includedir}/ini_comment.h
%{_includedir}/ini_configmod.h
%{_libdir}/libini_config.so
%{_libdir}/pkgconfig/ini_config.pc
%doc ini/doc/html/
##############################################################################
# Build steps
##############################################################################
%prep
%autosetup -S git
%build
autoreconf -ivf
%configure \
--disable-static
make %{?_smp_mflags} all docs
%check
make %{?_smp_mflags} check
%install
make install DESTDIR=$RPM_BUILD_ROOT
# Remove .la files created by libtool
rm -f $RPM_BUILD_ROOT/%{_libdir}/*.la
# Remove the example files from the output directory
# We will copy them directly from the source directory
# for packaging
rm -f \
$RPM_BUILD_ROOT/usr/share/doc/ding-libs/README.* \
$RPM_BUILD_ROOT/usr/share/doc/ding-libs/examples/dhash_example.c \
$RPM_BUILD_ROOT/usr/share/doc/ding-libs/examples/dhash_test.c
# Remove document install script. RPM is handling this
rm -f */doc/html/installdox
%changelog
* Wed May 11 2022 Alexey Tikhonov <atikhono@redhat.com> - 0.6.1-52
- Resolves: rhbz#2048667 - Request to add libdhash-devel package into CRB
* Tue Aug 10 2021 Alexey Tikhonov <atikhono@redhat.com> - 0.6.1-51
- Resolves: rhbz#1938708 - review of important potential issues detected by static analyzers in ding-libs-0.6.1-47.el9
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 0.6.1-50
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Tue Jun 01 2021 Alexey Tikhonov <atikhono@redhat.com> - 0.6.1-49
- Resolves: rhbz#1962772 - Add gating tests for ding-libs in RHEL 9
* Thu Apr 15 2021 Mohan Boddu <mboddu@redhat.com> - 0.6.1-48
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.1-47
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Sat Aug 01 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.1-46
- Second attempt - Rebuilt for
https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.1-45
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.1-44
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Wed Jul 24 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.1-43
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.1-42
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Tue Aug 14 2018 Michal Židek <mzidek@redhat.com> - 0.6.1-41
- Resolves: rhbz#1603785 - ding-libs: FTBFS in Fedora rawhide
* Fri Jul 20 2018 Jakub Hrozek <jhrozek@redhat.com> - 0.6.1-40
- BuildRequires: gcc
- Resolves: rhbz#1603785 - ding-libs: FTBFS in Fedora rawhide
* Thu Jul 12 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.1-39
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.1-38
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Sun Feb 04 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 0.6.1-37
- Switch to %%ldconfig_scriptlets
* Thu Nov 16 2017 Robbie Harwood <rharwood@redhat.com> - 0.6.1-36
- INI: Remove definiton of TRACE_LEVEL
* Tue Nov 14 2017 Robbie Harwood <rharwood@redhat.com> - 0.6.1-35
- INI: Silence ini_augment match failures
* Wed Oct 04 2017 Lukas Slebodnik <lslebodn@redhat.com> - 0.6.1-34
- New upstream release 0.6.1
* Wed Aug 09 2017 Robbie Harwood <rharwood@redhat.com> - 0.6.0-33
- Backport INI merge detection support
- Migrate to autosetup
* Wed Aug 02 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.0-32
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.0-31
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.6.0-30
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
* Thu Jun 23 2016 Jakub Hrozek <jhrozek@redhat.com> - 0.6.0-29
- New upstream release 0.6.0
- https://fedorahosted.org/sssd/wiki/Releases/DingNotes-0.6.0
* Wed Feb 03 2016 Fedora Release Engineering <releng@fedoraproject.org> - 0.5.0-28
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
* Wed Aug 26 2015 Robbie Harwood <rharwood@redhat.com> - 0.5.0-27
- Merge most changes from the upstream spec file
* Wed Aug 26 2015 Robbie Harwood <rharwood@redhat.com> - 0.5.0-26
- New upstream release 0.5.0
- https://fedorahosted.org/sssd/wiki/Releases/DingNotes-0.5.0
* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.0-25
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
* Sat Aug 16 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.0-24
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.0-23
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
* Thu May 29 2014 Jakub Hrozek <jhrozek@redhat.com> 0.4.0-22
- New upstream release 0.4.0
- https://fedorahosted.org/sssd/wiki/Releases/DingNotes-0.4.0
* Sat Jan 18 2014 Peter Robinson <pbrobinson@fedoraproject.org> 0.3.0.1-21
- Fix FTBFS on rawhide
- update spec
* Fri Sep 27 2013 Jakub Hrozek <jhrozek@redhat.com> - 0.3.0.1-20
- Merge Doxygen patch from f19 branch to avoid regressions
* Fri Sep 27 2013 Jakub Hrozek <jhrozek@redhat.com> - 0.3.0.1-19
- Apply a patch by Dmitri Pal to strip trailing whitespace
* Sat Aug 03 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.3.0.1-18
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
* Thu May 23 2013 Jakub Hrozek <jhrozek@redhat.com> - 0.3.0.1-17
- Apply patch by Ondrej Kos to bump libtool version info
* Fri Apr 05 2013 Jakub Hrozek <jhrozek@redhat.com> - 0.3.0.1-16
- Fix libiniconfig_devel Requires
* Thu Apr 04 2013 Jakub Hrozek <jhrozek@redhat.com> - 0.3.0.1-15
- Increase the release number to -13 to allow clean upgrade path from
0.2 since some of the components kept their version the same in 0.3
* Mon Apr 01 2013 Stephen Gallagher <sgallagh@redhat.com> - 0.3.0.1-3
- Bumping revision to fix build glitch
* Fri Mar 29 2013 Jakub Hrozek <jhrozek@redhat.com> - 0.3.0.1-1
- New upstream release 0.3.0.1
- https://fedorahosted.org/sssd/wiki/Releases/DingNotes-0.3.0.1
- obsoletes patch0001
* Thu Mar 28 2013 Jakub Hrozek <jhrozek@redhat.com> - 0.3.0-2
- Remove cast to allow INI to work on 32bits
* Thu Mar 28 2013 Jakub Hrozek <jhrozek@redhat.com> - 0.3.0-1
- New upstream release 0.3.0
- https://fedorahosted.org/sssd/wiki/Releases/DingNotes-0.3.0
* Mon Mar 25 2013 Jakub Hrozek <jhrozek@redhat.com> - 0.2.91-14
- include a patch to get rid of autoreconf warnings
- run autoreconf before configure
- Resolves: #925258
* Wed Feb 13 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.2.91-13
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
* Wed Oct 31 2012 Ondrej Kos <okos@redhat.com> - 0.2.91-12
- Fixes missing devel dependency
* Wed Jul 18 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.2.91-11
- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
* Mon May 28 2012 Jan Zeleny <jzeleny@redhat.com> - 0.2.91-10
- a bunch of fixes in spec file
* Fri May 25 2012 Jan Zeleny <jzeleny@redhat.com> - 0.2.91-9
- Bumped the release number to 9 for smooth upgrade
* Fri May 25 2012 Jan Zeleny <jzeleny@redhat.com> - 0.2.91-1
- Rebase to 0.3.0beta1, changelog available at
https://fedorahosted.org/sssd/wiki/Releases/DingNotes-0.2.91
* Tue Mar 06 2012 Stephen Gallagher <sgallagh@redhat.com> - 0.1.3-8
- Make path_concat return empty string on ENOBUFS
* Tue Mar 06 2012 Stephen Gallagher <sgallagh@redhat.com> - 0.1.3-7
- Fix off-by-one bug in path_concat()
- Resolves: rhbz#799347 - path_utils:test_path_concat_neg fails on 64-bit big
endians
* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.1.3-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
* Thu Sep 15 2011 Stephen Gallagher <sgallagh@redhat.com> - 0.1.3-5
- New upstream release 0.1.3
- Fixes a serious issue with libdhash and large initial hash sizes
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.1.2-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
* Fri Oct 15 2010 Stephen Gallagher <sgallagh@redhat.com> - 0.1.2-3
- New upsteam release 0.1.2
- Fixes a serious issue with libdhash where hash_enter() would never update
- existing entries for a key.
* Thu Sep 23 2010 Stephen Gallagher <sgallagh@redhat.com> - 0.1.1-2
- Fix invalid source URL
* Thu Sep 23 2010 Stephen Gallagher <sgallagh@redhat.com> - 0.1.1-1
- Initial release of ding-libs

7
gating.yaml Normal file
View File

@ -0,0 +1,7 @@
# recipients: sssd-team
--- !Policy
product_versions:
- rhel-9
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

1
sources Normal file
View File

@ -0,0 +1 @@
SHA512 (ding-libs-0.6.1.tar.gz) = 335a0925bfa7cc113e86c91ad3f2c8aac12711879d5c9b62660140a4b749335a74024c987fcd2304dd78176362997b3e0ebd745193aaffab7a368e2873118628

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