On 02/19/2016 04:33 PM, Lukas Slebodnik wrote:

[...]

>Hello Lukas,
>
>thank you for careful code review. I addressed all comments and I found
>memory leak in original colondb tool. Patch of memory leak is attached in
>patch #1 with brief but explaining description in commit message.
>
>Regards
>--
>Petr^4  Cech
From 2bce55008b3f1a070c224bbb25191408efa42fee Mon Sep 17 00:00:00 2001
>From: Petr Cech<pc...@redhat.com>
>Date: Thu, 18 Feb 2016 06:33:53 -0500
>Subject: [PATCH 1/3] COLONDB: Fix memory leak
>
>man 3 getline says:
>ssize_t getline(char **lineptr, size_t *n, FILE *stream);
>If *lineptr is set to NULL and *n is set 0 before the call, then
>getline() will allocate a buffer for storing the line.  This buffer
>should be freed by the user program even if getline() failed.
>
>This patch fix buffer freeing in case if getline() failed.
>
Nice catch.

ACK
Thank you, Lukas.

From 016afc2aff7b980ba56690b6bafbcab377cf1e80 Mon Sep 17 00:00:00 2001
>From: Petr Cech<pc...@redhat.com>
>Date: Tue, 24 Nov 2015 10:34:10 -0500
>Subject: [PATCH 2/3] COLONDB: Add comments on functions
>
>The colondb API provides three function:
>* sss_colondb_open()
>* sss_colondb_write_field()
>* sss_colondb_read_field()
>
>It is not obvious that sss_colondb_open() add destructor on talloc
>context which close the colondb during free context. And there is
>expectation that SSS_COLONDB_SENTINEL is type of last item in line.
>
>So this patch adds simple lightening comments in doxygen style.
>
>Resolves:
>https://fedorahosted.org/sssd/ticket/2764
>---
ACK
Thanks.

From 036ffc7e61456baa9bbb112452bbcc483e0e07c3 Mon Sep 17 00:00:00 2001
>From: Petr Cech<pc...@redhat.com>
>Date: Fri, 27 Nov 2015 06:39:37 -0500
>Subject: [PATCH 3/3] TEST_TOOLS_COLONDB: Add tests for sss_colondb_*
>
>There are three functions at API of colondb wrapper:
>* sss_colondb_open()
>* sss_colondb_readline()
>* sss_colondb_writeline()
>
>This patch adds tests for all of them.
>
>We test those cases:
>* open nonexisting file for read
>* open nonexisting file for write
>* open existing empty file for read
>* open existing file with records for read
>* open existing empty file for write
>* open existing file with records for write
>* write to empty file
>* write to file with existing records
>* sss_colondb_open()
>* sss_colondb_readline()
>* sss_colondb_write_line()
>* write to empty file and read it
>
>Resolves:
>https://fedorahosted.org/sssd/ticket/2764
I'm not sure that talloc leak checking is properly used in this unit test.

I have rewrote leak checking. I hope I have removed all memory leaks from my tests.

There are leaks in setup functions:
diff --git a/src/tests/cmocka/test_tools_colondb.c 
b/src/tests/cmocka/test_tools_colondb.c
index 11274d9..9cbb17f 100644
--- a/src/tests/cmocka/test_tools_colondb.c
+++ b/src/tests/cmocka/test_tools_colondb.c
@@ -61,7 +61,7 @@ static void create_empty_file(void **state, const char *path, 
const char *name)
      assert_non_null(fp);
      fclose(fp);

-    //talloc_free(tmp_ctx);
+    talloc_free(tmp_ctx);
  }

  static void create_nonempty_file(void **state,
@@ -86,7 +86,7 @@ static void create_nonempty_file(void **state,

      sss_colondb_writeline(db, table);

-    //talloc_free(tmp_ctx);
+    talloc_free(tmp_ctx);
  }


BTW we do not use c++ style comments:-)
It's already in old coding style.
https://www.freeipa.org/page/Coding_Style#Comments

Of course, it was my inattention. Sorry.

and moreover there is a leak in sss_colondb_writeline.
@see attached patch.

I didn't try to find out what's wrong with leak check.
If you you are not able to fix it yourself then
we might take a look at test together to save some time
sending/reviewing patches.

LS


0001-TOOLS-Fix-minor-memory-leak-in-sss_colondb_writeline.patch


 From fd458598cb619ec24ef0d00a47d84c790631257b Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik<lsleb...@redhat.com>
Date: Fri, 19 Feb 2016 16:18:02 +0100
Subject: [PATCH 1/2] TOOLS: Fix minor memory leak in sss_colondb_writeline

The variable line was initialized to NULL.
The we created temporary context tmp_ctx.
We use talloc_asprintf_append to append string to line which is initially
NULL and therefore new context which was not connected to tmp_ctx.
     man 3 talloc_string -> talloc_asprintf_append
---
  src/tools/common/sss_colondb.c | 7 +++++++
  1 file changed, 7 insertions(+)

diff --git a/src/tools/common/sss_colondb.c b/src/tools/common/sss_colondb.c
index 
a1a52c552b949076bdedae58f275d29a176be1e6..e8aeb315c9ed0efde15553e2d741d04c5d895b1a
 100644
--- a/src/tools/common/sss_colondb.c
+++ b/src/tools/common/sss_colondb.c
@@ -202,6 +202,13 @@ errno_t sss_colondb_writeline(struct sss_colondb *db,
          return ENOMEM;
      }

+    line = talloc_strdup(tmp_ctx, "");
+    if (line == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
      for (i = 0; table[i].type != SSS_COLONDB_SENTINEL; i++) {
          switch (table[i].type) {
          case SSS_COLONDB_UINT32:
-- 2.5.0

Nice catch, ACK


During code review there was problem with build on debian, so I did CI tests:
http://sssd-ci.duckdns.org/logs/job/37/59/summary.html


There are 4 patches attached. The first of them is from Lukas. This order of patches is valid.

Regards
--
Petr^4 Cech
>From 297caa2cd2c2fb06436d0032e5713cf96337a40d Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lsleb...@redhat.com>
Date: Fri, 19 Feb 2016 16:18:02 +0100
Subject: [PATCH 1/4] TOOLS: Fix minor memory leak in sss_colondb_writeline

The variable line was initialized to NULL.
The we created temporary context tmp_ctx.
We use talloc_asprintf_append to append string to line which is initially
NULL and therefore new context which was not connected to tmp_ctx.
    man 3 talloc_string -> talloc_asprintf_append
---
 src/tools/common/sss_colondb.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/tools/common/sss_colondb.c b/src/tools/common/sss_colondb.c
index a41b12fb9c097ff0e03da6d1c5cfe2fb24b63d54..b9af5f7e50c1166ca518a4e342637dc62518c567 100644
--- a/src/tools/common/sss_colondb.c
+++ b/src/tools/common/sss_colondb.c
@@ -198,6 +198,13 @@ errno_t sss_colondb_writeline(struct sss_colondb *db,
         return ENOMEM;
     }
 
+    line = talloc_strdup(tmp_ctx, "");
+    if (line == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
     for (i = 0; table[i].type != SSS_COLONDB_SENTINEL; i++) {
         switch (table[i].type) {
         case SSS_COLONDB_UINT32:
-- 
2.5.0

>From b3642eb48bc35928a4f901b912d8a05a31bae73a Mon Sep 17 00:00:00 2001
From: Petr Cech <pc...@redhat.com>
Date: Thu, 18 Feb 2016 06:33:53 -0500
Subject: [PATCH 2/4] TOOLS: Fix memory leak after getline() failed

This patch fixes buffer freeing in case if getline() failed
in function sss_colondb_readline().

ssize_t getline(char **lineptr, size_t *n, FILE *stream);
If *lineptr is set to NULL and *n is set 0 before the call, then
getline() will allocate a buffer for storing the line.  This buffer
should be freed by the user program even if getline() failed.
    man 3 getline

This patch fix buffer freeing in case if getline() failed.

Resolves:
https://fedorahosted.org/sssd/ticket/2764
---
 src/tools/common/sss_colondb.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/tools/common/sss_colondb.c b/src/tools/common/sss_colondb.c
index b9af5f7e50c1166ca518a4e342637dc62518c567..e8aeb315c9ed0efde15553e2d741d04c5d895b1a 100644
--- a/src/tools/common/sss_colondb.c
+++ b/src/tools/common/sss_colondb.c
@@ -121,6 +121,10 @@ errno_t sss_colondb_readline(TALLOC_CTX *mem_ctx,
     readchars = getline(&line, &linelen, db->file);
     if (readchars == -1) {
         /* Nothing was read. */
+
+        free(line);
+        line = NULL;
+
         if (errno != 0) {
             ret = errno;
             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to read line [%d]: %s\n",
-- 
2.5.0

>From 04fb18d9b97a5cbf2fe0addf09c0e0a11bf9989e Mon Sep 17 00:00:00 2001
From: Petr Cech <pc...@redhat.com>
Date: Tue, 24 Nov 2015 10:34:10 -0500
Subject: [PATCH 3/4] TOOLS: Add comments on functions in colondb

The colondb API provides three function:
* sss_colondb_open()
* sss_colondb_write_field()
* sss_colondb_read_field()

It is not obvious that sss_colondb_open() add destructor on talloc
context which close the colondb during free context. And there is
expectation that SSS_COLONDB_SENTINEL is type of last item in line.

So this patch adds simple lightening comments in doxygen style.

Resolves:
https://fedorahosted.org/sssd/ticket/2764
---
 src/tools/common/sss_colondb.h | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/src/tools/common/sss_colondb.h b/src/tools/common/sss_colondb.h
index 6edd99cbe3b9ef5c86a48632ac3fc71e8a3e55fe..cb9040088c65fdbe35c787b8942aaf1b14a2778d 100644
--- a/src/tools/common/sss_colondb.h
+++ b/src/tools/common/sss_colondb.h
@@ -59,14 +59,37 @@ struct sss_colondb_read_field {
     union sss_colondb_read_data data;
 };
 
+/**
+ * Open colon DB and return connection.
+ * @param[in|out] mem_ctx Memory context. Internal sss_colondb_close() is set
+ *                        on destructor of this memory context.
+ * @param[in] mode Open mode of db: SSS_COLONDB_READ or SSS_COLONDB_WRITE.
+ * @param[in] filename Name of file.
+ * @return Pointer to structure holding DB connection, or NULL if fail.
+ */
 struct sss_colondb *sss_colondb_open(TALLOC_CTX *mem_ctx,
                                      enum sss_colondb_mode mode,
                                      const char *filename);
 
+/**
+ * Read line from colon DB.
+ * @param[in|out] mem_ctx Memory context.
+ * @param[in] db  Pointer to structure holding DB connection.
+ * @param[in|out] table Array of expected structure of line. It is expected
+ *                      that last item has SSS_COLONDB_SENTINEL type.
+ * @return EOK if success, else error code.
+ */
 errno_t sss_colondb_readline(TALLOC_CTX *mem_ctx,
                              struct sss_colondb *db,
                              struct sss_colondb_read_field *table);
 
+/**
+ * Write line to colon DB.
+ * @param[in] db Pointer to structure holding DB connection.
+ * @param[in] table Array with data. It is expected that last item has
+ *                  SSS_COLONDB_SENTINEL type.
+ * @return EOK if success, else error code.
+ */
 errno_t sss_colondb_writeline(struct sss_colondb *db,
                               struct sss_colondb_write_field *table);
 
-- 
2.5.0

>From 1e85c2d3dec7958356ddfb3b4b8b221816e4848e Mon Sep 17 00:00:00 2001
From: Petr Cech <pc...@redhat.com>
Date: Fri, 27 Nov 2015 06:39:37 -0500
Subject: [PATCH 4/4] TEST_TOOLS_COLONDB: Add tests for sss_colondb_*

There are three functions at API of colondb wrapper:
 * sss_colondb_open()
 * sss_colondb_readline()
 * sss_colondb_writeline()

This patch adds tests for all of them.

We test those cases:
 * open nonexisting file for read
 * open nonexisting file for write
 * open existing empty file for read
 * open existing file with records for read
 * open existing empty file for write
 * open existing file with records for write
 * write to empty file
 * write to file with existing records
 * sss_colondb_open()
 * sss_colondb_readline()
 * sss_colondb_write_line()
 * write to empty file and read it

Resolves:
https://fedorahosted.org/sssd/ticket/2764
---
 Makefile.am                           |  17 ++
 src/tests/cmocka/test_tools_colondb.c | 471 ++++++++++++++++++++++++++++++++++
 2 files changed, 488 insertions(+)
 create mode 100644 src/tests/cmocka/test_tools_colondb.c

diff --git a/Makefile.am b/Makefile.am
index 8ff3322cd4aaaf8d419b664a18c4e0e67205beb8..4e4f38a5eaf5bfa2cfafa88b9b32848e6c27131b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -241,6 +241,7 @@ if HAVE_CMOCKA
         pam-srv-tests \
         test_ipa_subdom_util \
         test_ipa_subdom_server \
+        test_tools_colondb \
         test_krb5_wait_queue \
         test_cert_utils \
         test_ldap_id_cleanup \
@@ -2576,6 +2577,22 @@ test_ipa_subdom_server_LDADD = \
     libdlopen_test_providers.la \
     $(NULL)
 
+test_tools_colondb_SOURCES = \
+    src/tests/cmocka/test_tools_colondb.c \
+    src/tools/common/sss_colondb.c \
+    $(NULL)
+test_tools_colondb_CFLAGS = \
+    $(AM_CFLAGS) \
+    $(NULL)
+test_tools_colondb_LDFLAGS = \
+    $(NULL)
+test_tools_colondb_LDADD = \
+    $(CMOCKA_LIBS) \
+    $(SSSD_INTERNAL_LTLIBS) \
+    $(POPT_LIBS) \
+    libsss_test_common.la \
+    $(NULL)
+
 test_krb5_wait_queue_SOURCES = \
     src/tests/cmocka/common_mock_be.c \
     src/tests/cmocka/test_krb5_wait_queue.c \
diff --git a/src/tests/cmocka/test_tools_colondb.c b/src/tests/cmocka/test_tools_colondb.c
new file mode 100644
index 0000000000000000000000000000000000000000..123ad39bd75a0206fbf152fd35a10c6113f36bfc
--- /dev/null
+++ b/src/tests/cmocka/test_tools_colondb.c
@@ -0,0 +1,471 @@
+/*
+    Authors:
+        Petr Čech <pc...@redhat.com>
+
+    Copyright (C) 2015 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/>.
+*/
+
+#include <talloc.h>
+#include <errno.h>
+#include <popt.h>
+
+#include "tests/cmocka/common_mock.h"
+#include "src/tools/common/sss_colondb.h"
+
+#define TESTS_PATH "tp_" BASE_FILE_STEM
+#define TESTS_FILE "test_colondb.ldb"
+
+const char *TEST_STRING1 = "white";
+const int TEST_INT1 = 12;
+
+const char *TEST_STRING2 = "black";
+const int TEST_INT2 = 34;
+
+static void create_dir(const char *path)
+{
+    errno_t ret;
+
+    errno = 0;
+    ret = mkdir(path, 0775);
+    assert_int_equal(ret, 0);
+}
+
+static void create_empty_file(void **state, const char *path, const char *name)
+{
+    TALLOC_CTX *tmp_ctx = NULL;
+    char *file_name = NULL;
+    FILE *fp = NULL;
+
+    tmp_ctx = talloc_new(*state);
+    assert_non_null(tmp_ctx);
+
+    create_dir(path);
+
+    file_name = talloc_asprintf(tmp_ctx, "%s/%s", path, name);
+    assert_non_null(file_name);
+
+    fp = fopen(file_name, "w");
+    assert_non_null(fp);
+    fclose(fp);
+
+    talloc_free(tmp_ctx);
+}
+
+static void create_nonempty_file(void **state,
+                                 const char *path, const char *name)
+{
+    TALLOC_CTX *tmp_ctx = NULL;
+    struct sss_colondb *db = NULL;
+    struct sss_colondb_write_field table[] = {
+        { SSS_COLONDB_STRING, { .str = TEST_STRING2 } },
+        { SSS_COLONDB_UINT32, { .uint32 = TEST_INT2 } },
+        { SSS_COLONDB_SENTINEL, { 0 } }
+    };
+
+    tmp_ctx = talloc_new(*state);
+    assert_non_null(tmp_ctx);
+
+    create_empty_file(state, TESTS_PATH, TESTS_FILE);
+
+    db = sss_colondb_open(tmp_ctx, SSS_COLONDB_WRITE,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_non_null(db);
+
+    sss_colondb_writeline(db, table);
+
+    talloc_free(db);
+    talloc_free(tmp_ctx);
+}
+
+static int setup(void **state, int file_state)
+{
+    TALLOC_CTX *test_ctx = NULL;
+
+    assert_true(leak_check_setup());
+
+    check_leaks_push(global_talloc_context);
+    test_ctx = talloc_new(global_talloc_context);
+    assert_non_null(test_ctx);
+
+    switch (file_state) {
+    case 0:
+        break;
+    case 1:
+        create_empty_file(state, TESTS_PATH, TESTS_FILE);
+        break;
+    case 2:
+        create_nonempty_file(state, TESTS_PATH, TESTS_FILE);
+        break;
+    default:
+        break;
+    }
+
+    *state = test_ctx;
+
+    return 0;
+}
+
+static int without_file_setup(void **state)
+{
+    return setup(state, 0);
+}
+
+static int with_empty_file_setup(void **state)
+{
+    return setup(state, 1);
+}
+
+static int with_nonempty_file_setup(void **state)
+{
+    return setup(state, 2);
+}
+
+static int teardown(void **state)
+{
+    errno_t ret;
+
+    errno = 0;
+    ret = unlink(TESTS_PATH "/" TESTS_FILE);
+    if (ret != 0) {
+        assert_int_equal(errno, ENOENT);
+    }
+
+    talloc_zfree(*state);
+    test_dom_suite_cleanup(TESTS_PATH, NULL, NULL);
+    assert_true(check_leaks_pop(global_talloc_context));
+    assert_true(leak_check_teardown());
+
+    return 0;
+}
+
+void test_open_nonexist_for_read(void **state)
+{
+    TALLOC_CTX *test_ctx = NULL;
+    struct sss_colondb *db = NULL;
+
+    test_ctx = talloc_new(*state);
+    check_leaks_push(test_ctx);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_READ,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_null(db);
+    talloc_free(db);
+
+    assert_true(check_leaks_pop(test_ctx));
+}
+
+void test_open_nonexist_for_write(void **state)
+{
+    TALLOC_CTX *test_ctx = NULL;
+    struct sss_colondb *db = NULL;
+
+    test_ctx = talloc_new(*state);
+    check_leaks_push(test_ctx);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_null(db);
+    talloc_free(db);
+
+    assert_true(check_leaks_pop(test_ctx));
+}
+
+void test_open_exist_for_read(void **state)
+{
+    TALLOC_CTX *test_ctx = NULL;
+    struct sss_colondb *db = NULL;
+
+    test_ctx = talloc_new(*state);
+    check_leaks_push(test_ctx);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_READ,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_non_null(db);
+    talloc_free(db);
+
+    assert_true(check_leaks_pop(test_ctx));
+}
+
+void test_open_exist_for_write(void **state)
+{
+    TALLOC_CTX *test_ctx = NULL;
+    struct sss_colondb *db = NULL;
+
+    test_ctx = talloc_new(*state);
+    check_leaks_push(test_ctx);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_non_null(db);
+    talloc_free(db);
+
+    assert_true(check_leaks_pop(test_ctx));
+}
+
+void test_open_nonempty_for_read(void **state)
+{
+    TALLOC_CTX *test_ctx = NULL;
+    struct sss_colondb *db = NULL;
+
+    test_ctx = talloc_new(*state);
+    check_leaks_push(test_ctx);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_READ,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_non_null(db);
+    talloc_free(db);
+
+    assert_true(check_leaks_pop(test_ctx));
+}
+
+void test_open_nonempty_for_write(void **state)
+{
+
+    TALLOC_CTX *test_ctx = NULL;
+    struct sss_colondb *db = NULL;
+
+    test_ctx = talloc_new(*state);
+    check_leaks_push(test_ctx);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_non_null(db);
+    talloc_free(db);
+
+    assert_true(check_leaks_pop(test_ctx));
+}
+
+void test_write_to_empty(void **state)
+{
+    TALLOC_CTX *test_ctx = NULL;
+    struct sss_colondb *db = NULL;
+    struct sss_colondb_write_field table[] = {
+        { SSS_COLONDB_STRING, { .str = TEST_STRING1 } },
+        { SSS_COLONDB_UINT32, { .uint32 = TEST_INT1 } },
+        { SSS_COLONDB_SENTINEL, { 0 } }
+    };
+    errno_t ret;
+
+    test_ctx = talloc_new(*state);
+    check_leaks_push(test_ctx);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_non_null(db);
+
+    ret = sss_colondb_writeline(db, table);
+    assert_int_equal(ret, 0);
+
+    talloc_free(db);
+    assert_true(check_leaks_pop(test_ctx));
+}
+
+void test_write_to_nonempty(void **state)
+{
+    TALLOC_CTX *test_ctx = NULL;
+    struct sss_colondb *db = NULL;
+    struct sss_colondb_write_field table[] = {
+        { SSS_COLONDB_STRING, { .str = TEST_STRING1 } },
+        { SSS_COLONDB_UINT32, { .uint32 = TEST_INT1 } },
+        { SSS_COLONDB_SENTINEL, { 0 } }
+    };
+    errno_t ret;
+
+    test_ctx = talloc_new(*state);
+    check_leaks_push(test_ctx);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_non_null(db);
+
+    ret = sss_colondb_writeline(db, table);
+    assert_int_equal(ret, 0);
+
+    talloc_free(db);
+    assert_true(check_leaks_pop(test_ctx));
+}
+
+void test_read_from_nonempty(void **state)
+{
+    TALLOC_CTX *test_ctx = NULL;
+    TALLOC_CTX *test_ctx_child = NULL;
+    struct sss_colondb *db = NULL;
+    errno_t ret;
+    const char *string;
+    uint32_t number;
+    struct sss_colondb_read_field table[] = {
+        { SSS_COLONDB_STRING, { .str = &string } },
+        { SSS_COLONDB_UINT32, { .uint32 = &number } },
+        { SSS_COLONDB_SENTINEL, { 0 } }
+    };
+
+    test_ctx = talloc_new(*state);
+    check_leaks_push(test_ctx);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_READ,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_non_null(db);
+
+    test_ctx_child = talloc_new(test_ctx);
+
+    ret = sss_colondb_readline(test_ctx_child, db, table);
+    assert_int_equal(ret, 0);
+    assert_string_equal(string, TEST_STRING2);
+    assert_int_equal(number, TEST_INT2);
+
+    talloc_free(test_ctx_child);
+
+    talloc_free(db);
+    assert_true(check_leaks_pop(test_ctx));
+}
+
+void test_read_from_empty(void **state)
+{
+    TALLOC_CTX *test_ctx = NULL;
+    struct sss_colondb *db = NULL;
+    errno_t ret;
+    const char *string;
+    uint32_t number;
+    struct sss_colondb_read_field table[] = {
+        { SSS_COLONDB_STRING, { .str = &string } },
+        { SSS_COLONDB_UINT32, { .uint32 = &number } },
+        { SSS_COLONDB_SENTINEL, { 0 } }
+    };
+
+    test_ctx = talloc_new(*state);
+    check_leaks_push(test_ctx);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_READ,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_non_null(db);
+
+    ret = sss_colondb_readline(test_ctx, db, table);
+    assert_int_equal(ret, EOF);
+
+    talloc_free(db);
+    assert_true(check_leaks_pop(test_ctx));
+}
+
+void test_write_read(void **state)
+{
+    TALLOC_CTX *test_ctx = NULL;
+    TALLOC_CTX *test_ctx_child = NULL;
+    struct sss_colondb *db = NULL;
+    errno_t ret;
+    const char *string;
+    uint32_t number;
+    struct sss_colondb_write_field table_in[] = {
+        { SSS_COLONDB_STRING, { .str = TEST_STRING2 } },
+        { SSS_COLONDB_UINT32, { .uint32 = TEST_INT2 } },
+        { SSS_COLONDB_SENTINEL, { 0 } }
+    };
+    struct sss_colondb_read_field table_out[] = {
+        { SSS_COLONDB_STRING, { .str = &string } },
+        { SSS_COLONDB_UINT32, { .uint32 = &number } },
+        { SSS_COLONDB_SENTINEL, { 0 } }
+    };
+
+    test_ctx = talloc_new(*state);
+    check_leaks_push(test_ctx);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_non_null(db);
+
+    ret = sss_colondb_writeline(db, table_in);
+    assert_int_equal(ret, 0);
+
+    talloc_free(db);
+
+    db = sss_colondb_open(test_ctx, SSS_COLONDB_READ,
+                          TESTS_PATH "/" TESTS_FILE);
+    assert_non_null(db);
+
+    test_ctx_child = talloc_new(test_ctx);
+
+    ret = sss_colondb_readline(test_ctx_child, db, table_out);
+    assert_int_equal(ret, 0);
+    assert_string_equal(string, TEST_STRING2);
+    assert_int_equal(number, TEST_INT2);
+
+    talloc_free(test_ctx_child);
+
+    talloc_free(db);
+    assert_true(check_leaks_pop(test_ctx));
+}
+
+int main(int argc, const char *argv[])
+{
+    poptContext pc;
+    int opt;
+    struct poptOption long_options[] = {
+        POPT_AUTOHELP
+        SSSD_DEBUG_OPTS
+        POPT_TABLEEND
+    };
+
+    const struct CMUnitTest tests[] = {
+        cmocka_unit_test_setup_teardown(test_open_nonexist_for_read,
+                                        without_file_setup, teardown),
+        cmocka_unit_test_setup_teardown(test_open_nonexist_for_write,
+                                        without_file_setup, teardown),
+        cmocka_unit_test_setup_teardown(test_open_exist_for_read,
+                                        with_empty_file_setup, teardown),
+        cmocka_unit_test_setup_teardown(test_open_exist_for_write,
+                                        with_empty_file_setup, teardown),
+        cmocka_unit_test_setup_teardown(test_open_nonempty_for_read,
+                                        with_nonempty_file_setup, teardown),
+        cmocka_unit_test_setup_teardown(test_open_nonempty_for_write,
+                                        with_nonempty_file_setup, teardown),
+
+        cmocka_unit_test_setup_teardown(test_write_to_empty,
+                                        with_empty_file_setup, teardown),
+        cmocka_unit_test_setup_teardown(test_write_to_nonempty,
+                                        with_nonempty_file_setup, teardown),
+
+        cmocka_unit_test_setup_teardown(test_read_from_empty,
+                                        with_empty_file_setup, teardown),
+        cmocka_unit_test_setup_teardown(test_read_from_nonempty,
+                                        with_nonempty_file_setup, teardown),
+
+        cmocka_unit_test_setup_teardown(test_write_read,
+                                        with_empty_file_setup, teardown),
+    };
+
+    /* Set debug level to invalid value so we can decide if -d 0 was used. */
+    debug_level = SSSDBG_INVALID;
+
+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+    while ((opt = poptGetNextOpt(pc)) != -1) {
+        switch (opt) {
+        default:
+            fprintf(stderr, "\nInvalid option %s: %s\n\n", poptBadOption(pc, 0),
+                    poptStrerror(opt));
+            poptPrintUsage(pc, stderr, 0);
+            return 1;
+        }
+    }
+    poptFreeContext(pc);
+
+    DEBUG_CLI_INIT(debug_level);
+
+    /* Even though normally the tests should clean up after themselves
+     * they might not after a failed run. Remove the old db to be sure */
+    tests_set_cwd();
+    test_dom_suite_cleanup(TESTS_PATH, NULL, NULL);
+
+    return cmocka_run_group_tests(tests, NULL, NULL);
+}
-- 
2.5.0

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/admin/lists/sssd-devel@lists.fedorahosted.org

Reply via email to