>From badbf490741154e404ee3bd10a3dfb1c2b045aba Mon Sep 17 00:00:00 2001
From: Pavel Reichl <preichl@redhat.com>
Date: Tue, 4 Nov 2014 08:52:54 +0000
Subject: [PATCH] SYSDB: sysdb_get_bool() return ENOENT & unit tests

sysdb_get_bool() return ENOENT if no result is found.
Unit test for sysdb_get_bool() & sysdb_set_bool() was added.

This patch also fixes ldap_setup_enumeration() to handle ENOENT returned by
sysdb_has_enumerated().

Resolves:
https://fedorahosted.org/sssd/ticket/1991
---
 src/db/sysdb.c                    |  9 +++++-
 src/providers/ldap/ldap_id_enum.c |  6 +++-
 src/tests/sysdb-tests.c           | 62 ++++++++++++++++++++++++++++++++++++---
 3 files changed, 71 insertions(+), 6 deletions(-)

diff --git a/src/db/sysdb.c b/src/db/sysdb.c
index 1f02585e747dda6aadde772f76f30d3d69c4cfc0..61a2240016b5cb77e6fbbc3286fd1a194c5a0b48 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -1508,6 +1508,7 @@ errno_t sysdb_get_bool(struct sysdb_ctx *sysdb,
     errno_t ret;
     int lret;
     const char *attrs[2] = {attr_name, NULL};
+    struct ldb_message_element *el;
 
     tmp_ctx = talloc_new(NULL);
     if (tmp_ctx == NULL) {
@@ -1530,7 +1531,7 @@ errno_t sysdb_get_bool(struct sysdb_ctx *sysdb,
          * to contain this attribute.
          */
         *value = false;
-        ret = EOK;
+        ret = ENOENT;
         goto done;
     } else if (res->count != 1) {
         DEBUG(SSSDBG_CRIT_FAILURE,
@@ -1539,6 +1540,12 @@ errno_t sysdb_get_bool(struct sysdb_ctx *sysdb,
         goto done;
     }
 
+    el = ldb_msg_find_element(res->msgs[0], attr_name);
+    if (el == NULL || el->num_values == 0) {
+        ret = ENOENT;
+        goto done;
+    }
+
     *value = ldb_msg_find_attr_as_bool(res->msgs[0], attr_name, false);
 
     ret = EOK;
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c
index 9ffa3e5d9737048e2f4508cea4edc28d6f8cda48..13d2a62544b3956165ef9eb480fb5b813c890fd4 100644
--- a/src/providers/ldap/ldap_id_enum.c
+++ b/src/providers/ldap/ldap_id_enum.c
@@ -41,7 +41,11 @@ errno_t ldap_setup_enumeration(struct be_ctx *be_ctx,
     struct ldap_enum_ctx *ectx;
 
     ret = sysdb_has_enumerated(sdom->dom, &has_enumerated);
-    if (ret != EOK) {
+    if (ret == ENOENT) {
+        /* default value */
+        has_enumerated = false;
+        ret = EOK;
+    } else if (ret != EOK) {
         return ret;
     }
 
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 26835d9eb3647c99a8cf50d98143088dc0655f10..bbfc88b3e351c96131bd58e06c3ba6d7803c733b 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -3474,6 +3474,58 @@ START_TEST (test_sysdb_memberof_user_cleanup)
 }
 END_TEST
 
+START_TEST (test_sysdb_set_get_bool)
+{
+    struct sysdb_test_ctx *test_ctx;
+    struct ldb_dn *dn, *ne_dn;
+    bool value;
+    int ret;
+    const char *attr_val = "BOOL_VALUE";
+
+    /* Setup */
+    ret = setup_sysdb_tests(&test_ctx);
+    if (ret != EOK) {
+        fail("Could not set up the test");
+        return;
+    }
+
+    dn = sysdb_domain_dn(test_ctx, test_ctx->domain);
+    fail_unless(dn != NULL);
+
+    /* attribute is not created yet */
+    ret = sysdb_get_bool(test_ctx->sysdb, dn, attr_val,
+                         &value);
+    fail_unless(ret == ENOENT,
+                "sysdb_get_bool returned %d:[%s], but ENOENT is expected",
+                ret, sss_strerror(ret));
+
+    /* add attribute */
+    ret = sysdb_set_bool(test_ctx->sysdb, dn, test_ctx->domain->name,
+                         attr_val, true);
+    fail_unless(ret == EOK);
+
+    /* successfully obtain attribute */
+    ret = sysdb_get_bool(test_ctx->sysdb, dn, attr_val,
+                         &value);
+    fail_unless(ret == EOK, "sysdb_get_bool failed %d:[%s]",
+                ret, sss_strerror(ret));
+    fail_unless(value == true);
+
+    /* use non-existing DN */
+    ne_dn = ldb_dn_new_fmt(test_ctx, test_ctx->sysdb->ldb, SYSDB_DOM_BASE,
+                        "non-existing domain");
+    fail_unless(ne_dn != NULL);
+    ret = sysdb_get_bool(test_ctx->sysdb, ne_dn, attr_val,
+                         &value);
+    fail_unless(ret == ENOENT,
+                "sysdb_get_bool returned %d:[%s], but ENOENT is expected",
+                ret, sss_strerror(ret));
+
+    /* free ctx */
+    talloc_free(test_ctx);
+}
+END_TEST
+
 START_TEST (test_sysdb_attrs_to_list)
 {
     struct sysdb_attrs *attrs_list[3];
@@ -4907,10 +4959,9 @@ START_TEST(test_sysdb_has_enumerated)
     fail_if(ret != EOK, "Could not set up the test");
 
     ret = sysdb_has_enumerated(test_ctx->domain, &enumerated);
-    fail_if(ret != EOK, "Error [%d][%s] checking enumeration",
-                        ret, strerror(ret));
-
-    fail_if(enumerated, "Enumeration should default to false");
+    fail_if(ret != ENOENT,
+            "Error [%d][%s] checking enumeration ENOENT is expected",
+            ret, strerror(ret));
 
     ret = sysdb_set_enumerated(test_ctx->domain, true);
     fail_if(ret != EOK, "Error [%d][%s] setting enumeration",
@@ -6231,6 +6282,9 @@ Suite *create_sysdb_suite(void)
     tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
                         MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
 
+    /* Misc */
+    tcase_add_test(tc_sysdb, test_sysdb_set_get_bool);
+
     /* Ghost users tests */
     tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_group_with_ghosts,
                         MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
-- 
1.9.3

