On 05/10/2016 11:57 AM, Pavel Březina wrote:
Hi,

Hello Pavel,

patches works as expected. I would like you to rename few things
though... "locals" refers more to a resident and it is not being used in
the meaning of local users and groups. I'd rather use the word "local"
(singular), is_local (where boolean is used).

Addressed.

Please rename the new option into something more similar as
entry_negative_timeou, maybe local_negative_timeout,
unix_negative_timeout or files_negative_timeout...

Addressed.

Its man page description doesn't read well in english (especially the
second sentence). Maybe something like this would be better:

Specifies for how many seconds nss_sss should keep local users and
groups in negative cache before trying to look the up in the back end
again.

Addressed.

Would it be beneficial to add some magic value (say -1) to represent
permanent ncache record?

I don't think so. We haven't such behaviour yet. Permanent negcaching is set item by item by set function. And during discussion about negcaching of local users, the opinion has been that we didn't want it.

But if you know case for it I am open for it.

Can you add some debuggin to is_user_local_by_name and similar functions
so we can see that local ncache timeout was used? Something like:

    if (ret == EOK && pwd_result != NULL) {
        DEBUG(SSSDBG_TRACE_FUNC, "User %s is a local user\n", name);
        is_local = true;
    }

Addressed.

Thank you for review, Pavel.

Regards

--
Petr^4 Čech
>From d3013d2c474f49159330e1916d931efb7d3cf532 Mon Sep 17 00:00:00 2001
From: Petr Cech <[email protected]>
Date: Thu, 5 May 2016 11:16:14 -0400
Subject: [PATCH 1/2] RESPONDERS: Negative caching of local users

This patch adds new option 'neg_cache_locals_timeout' into section
of NSS responder. It allows negative caching of local groups and
users. Default value is 0 which means no caching.

Resolves:
https://fedorahosted.org/sssd/ticket/2928
---
 Makefile.am                                 |  4 ++
 src/confdb/confdb.h                         |  1 +
 src/config/SSSDConfig/__init__.py.in        |  1 +
 src/config/etc/sssd.api.conf                |  1 +
 src/man/sssd.conf.5.xml                     | 13 ++++
 src/responder/common/negcache.c             | 43 +++++++++----
 src/responder/common/negcache.h             |  2 +-
 src/responder/common/negcache_files.c       | 97 +++++++++++++++++++++++++++++
 src/responder/common/negcache_files.h       | 32 ++++++++++
 src/responder/common/responder_common.c     | 22 ++++++-
 src/tests/cmocka/common_mock_resp.c         |  2 +-
 src/tests/cmocka/test_negcache.c            |  4 +-
 src/tests/cmocka/test_responder_cache_req.c |  4 +-
 src/tests/cwrap/Makefile.am                 |  1 +
 14 files changed, 208 insertions(+), 19 deletions(-)
 create mode 100644 src/responder/common/negcache_files.c
 create mode 100644 src/responder/common/negcache_files.h

diff --git a/Makefile.am b/Makefile.am
index dc477249be0dab29cef490cf4fb558b5e8b16d3c..2079fe5639dac3d0a4600831dc5d1ac0d8814cdc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -449,6 +449,7 @@ AM_CPPFLAGS = \
 EXTRA_DIST =
 
 SSSD_RESPONDER_OBJ = \
+    src/responder/common/negcache_files.c \
     src/responder/common/negcache.c \
     src/responder/common/responder_cmd.c \
     src/responder/common/responder_common.c \
@@ -574,6 +575,7 @@ dist_noinst_HEADERS = \
     src/responder/nss/nsssrv_services.h \
     src/responder/nss/nsssrv_mmap_cache.h \
     src/responder/pac/pacsrv.h \
+    src/responder/common/negcache_files.c \
     src/responder/common/negcache.h \
     src/responder/sudo/sudosrv_private.h \
     src/responder/autofs/autofs_private.h \
@@ -1790,6 +1792,7 @@ sss_idmap_tests_LDADD = \
 
 responder_socket_access_tests_SOURCES = \
     src/tests/responder_socket_access-tests.c \
+    src/responder/common/negcache_files.c \
     src/responder/common/negcache.c \
     src/responder/common/responder_common.c \
     src/responder/common/responder_packet.c \
@@ -1887,6 +1890,7 @@ TEST_MOCK_RESP_OBJ = \
      src/tests/cmocka/common_mock_resp_dp.c \
      src/responder/common/responder_packet.c \
      src/responder/common/responder_cmd.c \
+     src/responder/common/negcache_files.c \
      src/responder/common/negcache.c \
      src/responder/common/responder_common.c \
      src/responder/common/responder_cache_req.c
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index c478ef0978b2d1ce302a86a3d536f0447c27fefa..6bffa0bdcd69ace42737f0c28b5199fa36927542 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -84,6 +84,7 @@
 #define CONFDB_RESPONDER_GET_DOMAINS_TIMEOUT "get_domains_timeout"
 #define CONFDB_RESPONDER_CLI_IDLE_TIMEOUT "client_idle_timeout"
 #define CONFDB_RESPONDER_CLI_IDLE_DEFAULT_TIMEOUT 60
+#define CONFDB_RESPONDER_LOCAL_NEG_TIMEOUT "local_negative_timeout"
 
 /* NSS */
 #define CONFDB_NSS_CONF_ENTRY "config/nss"
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 1a0893cbc180394d994b9d97fc0fa863da656549..e80ea7f58fa65597a5c48bb660c4ef2641b9e63f 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -67,6 +67,7 @@ option_strings = {
     'enum_cache_timeout' : _('Enumeration cache timeout length (seconds)'),
     'entry_cache_no_wait_timeout' : _('Entry cache background update timeout length (seconds)'),
     'entry_negative_timeout' : _('Negative cache timeout length (seconds)'),
+    'local_negative_timeout' : _('Files negative cache timeout length (seconds)'),
     'filter_users' : _('Users that SSSD should explicitly ignore'),
     'filter_groups' : _('Groups that SSSD should explicitly ignore'),
     'filter_users_in_groups' : _('Should filtered users appear in groups'),
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
index a15f2bd05c3046f8d76b13b3d8f28f9001d8fded..f65a0d8c37afe71f9396dedf3d8c3f774b9f5119 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -33,6 +33,7 @@ certificate_verification = str, None, false
 enum_cache_timeout = int, None, false
 entry_cache_nowait_percentage = int, None, false
 entry_negative_timeout = int, None, false
+local_negative_timeout = int, None, false
 filter_users = list, str, false
 filter_groups = list, str, false
 filter_users_in_groups = bool, None, false
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 09db9cd32673c911991b335e986692e3d8d856d0..8b0e6069f52633db9a29d252b1f50728ea8b2745 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -577,6 +577,19 @@
                     </listitem>
                 </varlistentry>
                 <varlistentry>
+                    <term>local_negative_timeout (integer)</term>
+                    <listitem>
+                        <para>
+                            Specifies for how many seconds nss_sss should keep
+                            local users and groups in negative cache before
+                            trying to look the up in the back end again.
+                        </para>
+                        <para>
+                            Default: 0
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
                     <term>filter_users, filter_groups (string)</term>
                     <listitem>
                         <para>
diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c
index 1488c12a89e35b06bf00b60a2034ca7f9b64580b..be070079b309162c40af6cfbb1ffa7a4e55189fd 100644
--- a/src/responder/common/negcache.c
+++ b/src/responder/common/negcache.c
@@ -21,6 +21,7 @@
 
 #include "util/util.h"
 #include "confdb/confdb.h"
+#include "responder/common/negcache_files.h"
 #include "responder/common/responder.h"
 #include "responder/common/negcache.h"
 #include <fcntl.h>
@@ -40,6 +41,7 @@
 struct sss_nc_ctx {
     struct tdb_context *tdb;
     uint32_t timeout;
+    uint32_t local_timeout;
 };
 
 typedef int (*ncache_set_byname_fn_t)(struct sss_nc_ctx *, bool,
@@ -60,7 +62,7 @@ static int string_to_tdb_data(char *str, TDB_DATA *ret)
 }
 
 int sss_ncache_init(TALLOC_CTX *memctx,  uint32_t timeout,
-                    struct sss_nc_ctx **_ctx)
+                    uint32_t local_timeout, struct sss_nc_ctx **_ctx)
 {
     struct sss_nc_ctx *ctx;
 
@@ -73,6 +75,7 @@ int sss_ncache_init(TALLOC_CTX *memctx,  uint32_t timeout,
     if (!ctx->tdb) return errno;
 
     ctx->timeout = timeout;
+    ctx->local_timeout = local_timeout;
 
     *_ctx = ctx;
     return EOK;
@@ -139,8 +142,8 @@ done:
     return ret;
 }
 
-static int sss_ncache_set_str(struct sss_nc_ctx *ctx,
-                              char *str, bool permanent)
+static int sss_ncache_set_str(struct sss_nc_ctx *ctx, char *str,
+                              bool permanent, bool is_local)
 {
     TDB_DATA key;
     TDB_DATA data;
@@ -154,7 +157,15 @@ static int sss_ncache_set_str(struct sss_nc_ctx *ctx,
     if (permanent) {
         timest = talloc_strdup(ctx, "0");
     } else {
-        timell = (unsigned long long int)time(NULL) + ctx->timeout;
+        if (is_local == true && ctx->local_timeout > 0) {
+            timell = (unsigned long long int)time(NULL) + ctx->local_timeout;
+        } else {
+            if (ctx->timeout > 0) {
+                timell = (unsigned long long int)time(NULL) + ctx->timeout;
+            } else {
+                return EOK;
+            }
+        }
         timest = talloc_asprintf(ctx, "%llu", timell);
     }
     if (!timest) return ENOMEM;
@@ -300,7 +311,7 @@ static int sss_ncache_set_service_int(struct sss_nc_ctx *ctx, bool permanent,
     str = talloc_asprintf(ctx, "%s/%s/%s", NC_SERVICE_PREFIX, domain, name);
     if (!str) return ENOMEM;
 
-    ret = sss_ncache_set_str(ctx, str, permanent);
+    ret = sss_ncache_set_str(ctx, str, permanent, false);
 
     talloc_free(str);
     return ret;
@@ -446,6 +457,7 @@ int sss_ncache_check_cert(struct sss_nc_ctx *ctx, const char *cert)
 static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent,
                                    const char *domain, const char *name)
 {
+    bool is_local;
     char *str;
     int ret;
 
@@ -454,7 +466,8 @@ static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent,
     str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
     if (!str) return ENOMEM;
 
-    ret = sss_ncache_set_str(ctx, str, permanent);
+    is_local = is_user_local_by_name(name);
+    ret = sss_ncache_set_str(ctx, str, permanent, is_local);
 
     talloc_free(str);
     return ret;
@@ -463,6 +476,7 @@ static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent,
 static int sss_ncache_set_group_int(struct sss_nc_ctx *ctx, bool permanent,
                                     const char *domain, const char *name)
 {
+    bool is_local;
     char *str;
     int ret;
 
@@ -471,7 +485,8 @@ static int sss_ncache_set_group_int(struct sss_nc_ctx *ctx, bool permanent,
     str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
     if (!str) return ENOMEM;
 
-    ret = sss_ncache_set_str(ctx, str, permanent);
+    is_local = is_group_local_by_name(name);
+    ret = sss_ncache_set_str(ctx, str, permanent, is_local);
 
     talloc_free(str);
     return ret;
@@ -488,7 +503,7 @@ static int sss_ncache_set_netgr_int(struct sss_nc_ctx *ctx, bool permanent,
     str = talloc_asprintf(ctx, "%s/%s/%s", NC_NETGROUP_PREFIX, domain, name);
     if (!str) return ENOMEM;
 
-    ret = sss_ncache_set_str(ctx, str, permanent);
+    ret = sss_ncache_set_str(ctx, str, permanent, false);
 
     talloc_free(str);
     return ret;
@@ -535,6 +550,7 @@ int sss_ncache_set_netgr(struct sss_nc_ctx *ctx, bool permanent,
 int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent,
                        struct sss_domain_info *dom, uid_t uid)
 {
+    bool is_local;
     char *str;
     int ret;
 
@@ -546,7 +562,8 @@ int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent,
     }
     if (!str) return ENOMEM;
 
-    ret = sss_ncache_set_str(ctx, str, permanent);
+    is_local = is_user_local_by_uid(uid);
+    ret = sss_ncache_set_str(ctx, str, permanent, is_local);
 
     talloc_free(str);
     return ret;
@@ -555,6 +572,7 @@ int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent,
 int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent,
                        struct sss_domain_info *dom, gid_t gid)
 {
+    bool is_local;
     char *str;
     int ret;
 
@@ -566,7 +584,8 @@ int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent,
     }
     if (!str) return ENOMEM;
 
-    ret = sss_ncache_set_str(ctx, str, permanent);
+    is_local = is_group_local_by_gid(gid);
+    ret = sss_ncache_set_str(ctx, str, permanent, is_local);
 
     talloc_free(str);
     return ret;
@@ -580,7 +599,7 @@ int sss_ncache_set_sid(struct sss_nc_ctx *ctx, bool permanent, const char *sid)
     str = talloc_asprintf(ctx, "%s/%s", NC_SID_PREFIX, sid);
     if (!str) return ENOMEM;
 
-    ret = sss_ncache_set_str(ctx, str, permanent);
+    ret = sss_ncache_set_str(ctx, str, permanent, false);
 
     talloc_free(str);
     return ret;
@@ -595,7 +614,7 @@ int sss_ncache_set_cert(struct sss_nc_ctx *ctx, bool permanent,
     str = talloc_asprintf(ctx, "%s/%s", NC_CERT_PREFIX, cert);
     if (!str) return ENOMEM;
 
-    ret = sss_ncache_set_str(ctx, str, permanent);
+    ret = sss_ncache_set_str(ctx, str, permanent, false);
 
     talloc_free(str);
     return ret;
diff --git a/src/responder/common/negcache.h b/src/responder/common/negcache.h
index 572c723cc5202dac26671458920cb85cdc208fd2..377f97c8b3b20ec5b4a284e08d891737e2e25225 100644
--- a/src/responder/common/negcache.h
+++ b/src/responder/common/negcache.h
@@ -26,7 +26,7 @@ struct sss_nc_ctx;
 
 /* init the in memory negative cache */
 int sss_ncache_init(TALLOC_CTX *memctx, uint32_t timeout,
-                    struct sss_nc_ctx **_ctx);
+                    uint32_t local_timeout, struct sss_nc_ctx **_ctx);
 
 uint32_t sss_ncache_get_timeout(struct sss_nc_ctx *ctx);
 
diff --git a/src/responder/common/negcache_files.c b/src/responder/common/negcache_files.c
new file mode 100644
index 0000000000000000000000000000000000000000..aecffacc11749683a6c2c3f63411284f57c8feef
--- /dev/null
+++ b/src/responder/common/negcache_files.c
@@ -0,0 +1,97 @@
+/*
+   SSSD
+
+   NSS Responder
+
+   Copyright (C) Petr Čech <[email protected]>	2016
+
+   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 <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include "util/util.h"
+#include "responder/common/negcache_files.h"
+
+#define BUFFER_SIZE 16384
+
+bool is_user_local_by_name(const char *name)
+{
+    struct passwd pwd = {0};
+    struct passwd *pwd_result;
+    char buffer[BUFFER_SIZE];
+    bool is_local = false;
+    int ret;
+
+    ret = getpwnam_r(name, &pwd, buffer, BUFFER_SIZE, &pwd_result);
+    if (ret == EOK && pwd_result != NULL) {
+        DEBUG(SSSDBG_TRACE_FUNC, "User %s is a local user\n", name);
+        is_local = true;
+    }
+
+    return is_local;
+}
+
+bool is_user_local_by_uid(uid_t uid)
+{
+    struct passwd pwd = {0};
+    struct passwd *pwd_result;
+    char buffer[BUFFER_SIZE];
+    bool is_local = false;
+    int ret;
+
+    ret = getpwuid_r(uid, &pwd, buffer, BUFFER_SIZE, &pwd_result);
+    if (ret == EOK && pwd_result != NULL) {
+        DEBUG(SSSDBG_TRACE_FUNC, "User with UID %i is a local user\n", uid);
+        is_local = true;
+    }
+
+    return is_local;
+}
+
+bool is_group_local_by_name(const char *name)
+{
+    struct group grp = {0};
+    struct group *grp_result;
+    char buffer[BUFFER_SIZE];
+    bool is_local = false;
+    int ret;
+
+    ret = getgrnam_r(name, &grp, buffer, BUFFER_SIZE, &grp_result);
+    if (ret == EOK && grp_result != NULL) {
+        DEBUG(SSSDBG_TRACE_FUNC, "Group %s is a local group\n", name);
+        is_local = true;
+    }
+
+    return is_local;
+}
+
+bool is_group_local_by_gid(uid_t gid)
+{
+    struct group grp = {0};
+    struct group *grp_result;
+    char buffer[BUFFER_SIZE];
+    bool is_local = false;
+    int ret;
+
+    ret = getgrgid_r(gid, &grp, buffer, BUFFER_SIZE, &grp_result);
+    if (ret == EOK && grp_result != NULL) {
+        DEBUG(SSSDBG_TRACE_FUNC, "Group with GID %i is a local group\n", gid);
+        is_local = true;
+    }
+
+    return is_local;
+}
+
diff --git a/src/responder/common/negcache_files.h b/src/responder/common/negcache_files.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd9c79b8ce574f78506b6ea1eb5ee215a8efbe0a
--- /dev/null
+++ b/src/responder/common/negcache_files.h
@@ -0,0 +1,32 @@
+/*
+   SSSD
+
+   NSS Responder
+
+   Copyright (C) Petr Čech <[email protected]>	2016
+
+   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/>.
+*/
+
+#ifndef _NEGCACHE_FILES_H_
+#define _NEGCACHE_FILES_H_
+
+bool is_user_local_by_name(const char *name);
+bool is_user_local_by_uid(uid_t uid);
+
+bool is_group_local_by_name(const char *name);
+bool is_group_local_by_gid(uid_t gid);
+
+#endif /* _NEGCACHE_FILES_H_ */
+
diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
index 883b22a6548c29738f23a5ccf6747969f4e7146c..f0ddde9c0eeaf53f2b589c99337735ab1101b5ab 100644
--- a/src/responder/common/responder_common.c
+++ b/src/responder/common/responder_common.c
@@ -761,6 +761,7 @@ static errno_t responder_init_ncache(TALLOC_CTX *mem_ctx,
                                      struct sss_nc_ctx **ncache)
 {
     uint32_t neg_timeout;
+    uint32_t locals_timeout;
     int tmp_value;
     int ret;
 
@@ -783,8 +784,27 @@ static errno_t responder_init_ncache(TALLOC_CTX *mem_ctx,
     neg_timeout = tmp_value;
     ret = EOK;
 
+    /* local_timeout */
+    ret = confdb_get_int(cdb, CONFDB_NSS_CONF_ENTRY,
+                         CONFDB_RESPONDER_LOCAL_NEG_TIMEOUT,
+                         0, &tmp_value);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              "Fatal failure of setup negative cache timeout.\n");
+        ret = ENOENT;
+        goto done;
+    }
+
+    if (tmp_value < 0) {
+        ret = EINVAL;
+        goto done;
+    }
+
+    locals_timeout = tmp_value;
+    ret = EOK;
+
     /* negative cache init */
-    ret = sss_ncache_init(mem_ctx, neg_timeout, ncache);
+    ret = sss_ncache_init(mem_ctx, neg_timeout, locals_timeout, ncache);
     if (ret != EOK) {
         DEBUG(SSSDBG_FATAL_FAILURE,
               "Fatal failure of initializing negative cache.\n");
diff --git a/src/tests/cmocka/common_mock_resp.c b/src/tests/cmocka/common_mock_resp.c
index 8bcf18b800d8f64d5ddff9b6524eb209aa88f213..ce73d1b4542946f41003833d81e0f68086fd13e3 100644
--- a/src/tests/cmocka/common_mock_resp.c
+++ b/src/tests/cmocka/common_mock_resp.c
@@ -42,7 +42,7 @@ mock_rctx(TALLOC_CTX *mem_ctx,
         return NULL;
     }
 
-    ret = sss_ncache_init(rctx, 10, &rctx->ncache);
+    ret = sss_ncache_init(rctx, 10, 0, &rctx->ncache);
     if (ret != EOK) {
         talloc_free(rctx);
         return NULL;
diff --git a/src/tests/cmocka/test_negcache.c b/src/tests/cmocka/test_negcache.c
index e309ce6456ddaa425568d263964e7a01a653eaf5..a78341c89cda49fc205e8b48b068f2df1a36229e 100644
--- a/src/tests/cmocka/test_negcache.c
+++ b/src/tests/cmocka/test_negcache.c
@@ -104,7 +104,7 @@ static int setup(void **state)
     ts = talloc(NULL, struct test_state);
     assert_non_null(ts);
 
-    ret  = sss_ncache_init(ts, SHORTSPAN, &ts->ctx);
+    ret  = sss_ncache_init(ts, SHORTSPAN, 0, &ts->ctx);
     assert_int_equal(ret, EOK);
     assert_non_null(ts->ctx);
 
@@ -128,7 +128,7 @@ static void test_sss_ncache_init(void **state)
     memctx = talloc_new(NULL);
     assert_non_null(memctx);
 
-    ret = sss_ncache_init(memctx, SHORTSPAN, &ctx );
+    ret = sss_ncache_init(memctx, SHORTSPAN, 0, &ctx );
     assert_int_equal(ret, EOK);
     assert_non_null(ctx);
 
diff --git a/src/tests/cmocka/test_responder_cache_req.c b/src/tests/cmocka/test_responder_cache_req.c
index 6c13500cef9ec82dde9d97f97f7fb492fe0e3b8f..f30f1eaaddb653a1a5ad325b2838847b1dec1c22 100644
--- a/src/tests/cmocka/test_responder_cache_req.c
+++ b/src/tests/cmocka/test_responder_cache_req.c
@@ -434,7 +434,7 @@ static int test_single_domain_setup(void **state)
                                test_ctx->tctx->dom, NULL);
     assert_non_null(test_ctx->rctx);
 
-    ret = sss_ncache_init(test_ctx, 10, &test_ctx->ncache);
+    ret = sss_ncache_init(test_ctx, 10, 0, &test_ctx->ncache);
     assert_int_equal(ret, EOK);
 
     check_leaks_push(test_ctx);
@@ -480,7 +480,7 @@ static int test_multi_domain_setup(void **state)
                                test_ctx->tctx->dom, NULL);
     assert_non_null(test_ctx->rctx);
 
-    ret = sss_ncache_init(test_ctx, 10, &test_ctx->ncache);
+    ret = sss_ncache_init(test_ctx, 10, 0, &test_ctx->ncache);
     assert_int_equal(ret, EOK);
 
     check_leaks_push(test_ctx);
diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
index a5afb8c020ee00b680aac0680bcf6f6495dd8222..ba30bab6ecc1afbf451707c2af777480cfe6fd0d 100644
--- a/src/tests/cwrap/Makefile.am
+++ b/src/tests/cwrap/Makefile.am
@@ -106,6 +106,7 @@ usertools_tests_LDADD = \
 
 responder_common_tests_SOURCES =\
     test_responder_common.c \
+    ../../../src/responder/common/negcache_files.c \
     ../../../src/responder/common/negcache.c \
     ../../../src/responder/common/responder_common.c \
     ../../../src/responder/common/responder_packet.c \
-- 
2.5.5

>From 7635a6a5115ee91c41760d4ad7a883eed9e27744 Mon Sep 17 00:00:00 2001
From: Petr Cech <[email protected]>
Date: Mon, 9 May 2016 04:03:32 -0400
Subject: [PATCH 2/2] TEST: New tests for negative caching of locals

Negative cache has special timeout for local entities (users, groups).
This patch adds new tests for such behaviour. The tests are based on
cwrap.

Resolves:
https://fedorahosted.org/sssd/ticket/2928
---
 src/tests/cwrap/Makefile.am     |  32 ++
 src/tests/cwrap/group           |   1 +
 src/tests/cwrap/test_negcache.c | 673 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 706 insertions(+)
 create mode 100644 src/tests/cwrap/test_negcache.c

diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
index ba30bab6ecc1afbf451707c2af777480cfe6fd0d..44a0bca7899b6a10f853415ba8225a9f0fe27599 100644
--- a/src/tests/cwrap/Makefile.am
+++ b/src/tests/cwrap/Makefile.am
@@ -35,6 +35,20 @@ SSSD_LIBS = \
     $(OPENLDAP_LIBS) \
     $(TDB_LIBS)
 
+SSSD_RESPONDER_OBJ = \
+    ../../../src/responder/common/negcache_files.c \
+    ../../../src/responder/common/negcache.c \
+    ../../../src/responder/common/responder_cmd.c \
+    ../../../src/responder/common/responder_common.c \
+    ../../../src/responder/common/responder_dp.c \
+    ../../../src/responder/common/responder_packet.c \
+    ../../../src/responder/common/responder_get_domains.c \
+    ../../../src/responder/common/responder_utils.c \
+    ../../../src/responder/common/responder_cache_req.c \
+    ../../../src/monitor/monitor_iface_generated.c \
+    ../../../src/providers/data_provider_iface_generated.c \
+    ../../../src/providers/data_provider_req.c
+
 dist_noinst_DATA = \
     group \
     passwd \
@@ -49,6 +63,7 @@ check_PROGRAMS += \
     server-tests \
     usertools-tests \
     responder_common-tests \
+    negcache-tests \
     $(NULL)
 endif # HAVE_UID_WRAPPER
 endif # HAVE_NSS_WRAPPER
@@ -124,4 +139,21 @@ responder_common_tests_LDADD = \
     $(abs_top_builddir)/libsss_test_common.la \
     $(NULL)
 
+negcache_tests_SOURCES =\
+    $(SSSD_RESPONDER_OBJ) \
+    test_negcache.c \
+    $(NULL)
+negcache_tests_CFLAGS = \
+    $(AM_CFLAGS) \
+    -DBASE_FILE_STEM=\"$(*F)\" \
+    $(NULL)
+negcache_tests_LDADD = \
+    $(CMOCKA_LIBS) \
+    $(SSSD_LIBS) \
+    $(SELINUX_LIBS) \
+    $(abs_top_builddir)/libsss_util.la \
+    $(abs_top_builddir)/libsss_debug.la \
+    $(abs_top_builddir)/libsss_test_common.la \
+    $(NULL)
+
 tests: $(check_PROGRAMS)
diff --git a/src/tests/cwrap/group b/src/tests/cwrap/group
index 61e428c41a3df9d18cd216864d90c7f2603e8820..d0cea659ea030d14a293f5d941f473f8f3786886 100644
--- a/src/tests/cwrap/group
+++ b/src/tests/cwrap/group
@@ -1 +1,2 @@
 sssd:x:123:
+foogroup:x:10001:
diff --git a/src/tests/cwrap/test_negcache.c b/src/tests/cwrap/test_negcache.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee6f102dc8e636c88cf02ad2729cf3571751eb02
--- /dev/null
+++ b/src/tests/cwrap/test_negcache.c
@@ -0,0 +1,673 @@
+/*
+    Authors:
+        Petr Čech <[email protected]>
+
+    Copyright (C) 2016 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 <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <popt.h>
+
+#include "tests/common.h"
+#include "responder/common/negcache.h"
+#include "responder/common/negcache_files.h"
+#include "responder/common/responder.h"
+
+#define TESTS_PATH "tp_" BASE_FILE_STEM
+#define TEST_CONF_DB "test_sysdb_sudorules.ldb"
+#define TEST_DOM_NAME "test_domain.test"
+
+#define TEST_LOCAL_USER_NAME_1 "foobar"
+#define TEST_LOCAL_USER_NAME_2 "sssd"
+
+#define TEST_LOCAL_USER_UID_1 10001
+#define TEST_LOCAL_USER_UID_2 123
+
+#define TEST_LOCAL_GROUP_NAME_1 "foogroup"
+#define TEST_LOCAL_GROUP_NAME_2 "sssd"
+
+#define TEST_LOCAL_GID_1 10001
+#define TEST_LOCAL_GID_2 123
+
+struct test_user {
+    const char *name;
+    uid_t uid;
+    gid_t gid;
+} users[] = { { "test_user1", 1001, 50001 },
+              { "test_user2", 1002, 50002 } };
+
+static void create_users(struct sss_domain_info *domain)
+{
+    errno_t ret;
+
+    for (int i = 0; i < 2; i++) {
+        ret = sysdb_add_user(domain, users[i].name, users[i].uid, users[i].gid,
+                             users[i].name, NULL, "/bin/bash", domain->name,
+                             NULL, 30, time(NULL));
+        assert_int_equal(ret, EOK);
+    }
+}
+
+struct test_group {
+    const char *name;
+    gid_t gid;
+} groups[] = { { "test_group1", 50001 },
+               { "test_group2", 50002 } };
+
+struct ncache_test_ctx {
+    struct sss_test_ctx *tctx;
+    struct sss_nc_ctx *ncache;
+};
+
+static void create_groups(struct sss_domain_info *domain)
+{
+    errno_t ret;
+
+    for (int i = 0; i < 2; i++) {
+        ret = sysdb_add_group(domain, groups[i].name, groups[i].gid,
+                              NULL, 30, time(NULL));
+        assert_int_equal(ret, EOK);
+    }
+}
+
+/* register_cli_protocol_version is required in test since it links with
+ * responder_common.c module
+ */
+struct cli_protocol_version *register_cli_protocol_version(void)
+{
+    static struct cli_protocol_version responder_test_cli_protocol_version[] = {
+        {0, NULL, NULL}
+    };
+
+    return responder_test_cli_protocol_version;
+}
+
+static int test_ncache_setup(void **state)
+{
+    struct ncache_test_ctx *test_ctx;
+
+    assert_true(leak_check_setup());
+
+    test_ctx = talloc_zero(global_talloc_context, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    test_dom_suite_setup(TESTS_PATH);
+
+    test_ctx->tctx = create_dom_test_ctx(test_ctx, TESTS_PATH, TEST_CONF_DB,
+                                         TEST_DOM_NAME, "ipa", NULL);
+    assert_non_null(test_ctx->tctx);
+
+    create_groups(test_ctx->tctx->dom);
+    create_users(test_ctx->tctx->dom);
+
+    check_leaks_push(test_ctx);
+
+    *state = (void *)test_ctx;
+
+    return 0;
+}
+
+static int test_ncache_teardown(void **state)
+{
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+
+    test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME);
+
+    assert_true(check_leaks_pop(test_ctx));
+    talloc_zfree(test_ctx);
+    assert_true(leak_check_teardown());
+
+    return 0;
+}
+
+/* user utils */
+
+static void set_users(struct ncache_test_ctx *test_ctx)
+{
+    int ret;
+
+    ret = sss_ncache_set_user(test_ctx->ncache, false, test_ctx->tctx->dom,
+                              users[0].name);
+    assert_int_equal(ret, EOK);
+
+    ret = sss_ncache_set_user(test_ctx->ncache, false, test_ctx->tctx->dom,
+                              TEST_LOCAL_USER_NAME_1);
+    assert_int_equal(ret, EOK);
+}
+
+static void check_users(struct ncache_test_ctx *test_ctx,
+                        int case_a, int case_b, int case_c, int case_d)
+{
+    int ret;
+
+    ret = sss_ncache_check_user(test_ctx->ncache, test_ctx->tctx->dom,
+                                users[0].name);
+    assert_int_equal(ret, case_a);
+
+    ret = sss_ncache_check_user(test_ctx->ncache, test_ctx->tctx->dom,
+                                users[1].name);
+    assert_int_equal(ret, case_b);
+
+    ret = sss_ncache_check_user(test_ctx->ncache, test_ctx->tctx->dom,
+                                TEST_LOCAL_USER_NAME_1);
+    assert_int_equal(ret, case_c);
+
+    ret = sss_ncache_check_user(test_ctx->ncache, test_ctx->tctx->dom,
+                                TEST_LOCAL_USER_NAME_2);
+    assert_int_equal(ret, case_d);
+}
+
+/* user tests */
+
+void test_ncache_nocache_user(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 0, 0, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_users(test_ctx);
+
+    check_users(test_ctx, ENOENT, ENOENT, ENOENT, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_local_user(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 0, 10, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_users(test_ctx);
+
+    check_users(test_ctx, ENOENT, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_domain_user(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 10, 0, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_users(test_ctx);
+
+    check_users(test_ctx, EEXIST, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_both_user(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 10, 10, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_users(test_ctx);
+
+    check_users(test_ctx, EEXIST, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+/* uid utils */
+
+static void set_uids(struct ncache_test_ctx *test_ctx)
+{
+    int ret;
+
+    ret = sss_ncache_set_uid(test_ctx->ncache, false, test_ctx->tctx->dom,
+                             users[0].uid);
+    assert_int_equal(ret, EOK);
+
+    ret = sss_ncache_set_uid(test_ctx->ncache, false, test_ctx->tctx->dom,
+                             TEST_LOCAL_USER_UID_1);
+    assert_int_equal(ret, EOK);
+}
+
+static void check_uids(struct ncache_test_ctx *test_ctx,
+                       int case_a, int case_b, int case_c, int case_d)
+{
+    int ret;
+
+    ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom,
+                               users[0].uid);
+    assert_int_equal(ret, case_a);
+
+    ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom,
+                               users[1].uid);
+    assert_int_equal(ret, case_b);
+
+    ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom,
+                               TEST_LOCAL_USER_UID_1);
+    assert_int_equal(ret, case_c);
+
+    ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom,
+                               TEST_LOCAL_USER_UID_2);
+    assert_int_equal(ret, case_d);
+}
+
+/* uid tests */
+
+void test_ncache_nocache_uid(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 0, 0, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_uids(test_ctx);
+
+    check_uids(test_ctx, ENOENT, ENOENT, ENOENT, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_local_uid(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 0, 10, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_uids(test_ctx);
+
+    check_uids(test_ctx, ENOENT, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_domain_uid(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 10, 0, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_uids(test_ctx);
+
+    check_uids(test_ctx, EEXIST, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_both_uid(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 10, 10, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_uids(test_ctx);
+
+    check_uids(test_ctx, EEXIST, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+/* group utils */
+
+static void set_groups(struct ncache_test_ctx *test_ctx)
+{
+    int ret;
+
+    ret = sss_ncache_set_group(test_ctx->ncache, false, test_ctx->tctx->dom,
+                               groups[0].name);
+    assert_int_equal(ret, EOK);
+
+    ret = sss_ncache_set_group(test_ctx->ncache, false, test_ctx->tctx->dom,
+                               TEST_LOCAL_GROUP_NAME_1);
+    assert_int_equal(ret, EOK);
+}
+
+static void check_groups(struct ncache_test_ctx *test_ctx,
+                         int case_a, int case_b, int case_c, int case_d)
+{
+    int ret;
+
+    ret = sss_ncache_check_group(test_ctx->ncache, test_ctx->tctx->dom,
+                                 groups[0].name);
+    assert_int_equal(ret, case_a);
+
+    ret = sss_ncache_check_group(test_ctx->ncache, test_ctx->tctx->dom,
+                                 groups[1].name);
+    assert_int_equal(ret, case_b);
+
+    ret = sss_ncache_check_group(test_ctx->ncache, test_ctx->tctx->dom,
+                                 TEST_LOCAL_GROUP_NAME_1);
+    assert_int_equal(ret, case_c);
+
+    ret = sss_ncache_check_group(test_ctx->ncache, test_ctx->tctx->dom,
+                                 TEST_LOCAL_GROUP_NAME_2);
+    assert_int_equal(ret, case_d);
+}
+
+/* group tests */
+
+void test_ncache_nocache_group(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 0, 0, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_groups(test_ctx);
+
+    check_groups(test_ctx, ENOENT, ENOENT, ENOENT, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_local_group(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 0, 10, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_groups(test_ctx);
+
+    check_groups(test_ctx, ENOENT, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_domain_group(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 10, 0, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_groups(test_ctx);
+
+    check_groups(test_ctx, EEXIST, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_both_group(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 10, 10, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_groups(test_ctx);
+
+    check_groups(test_ctx, EEXIST, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+/* gid utils */
+
+static void set_gids(struct ncache_test_ctx *test_ctx)
+{
+    int ret;
+
+    ret = sss_ncache_set_gid(test_ctx->ncache, false, test_ctx->tctx->dom,
+                             users[0].gid);
+    assert_int_equal(ret, EOK);
+
+    ret = sss_ncache_set_gid(test_ctx->ncache, false, test_ctx->tctx->dom,
+                             TEST_LOCAL_GID_1);
+    assert_int_equal(ret, EOK);
+}
+
+static void check_gids(struct ncache_test_ctx *test_ctx,
+                       int case_a, int case_b, int case_c, int case_d)
+{
+    int ret;
+
+    ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom,
+                               users[0].gid);
+    assert_int_equal(ret, case_a);
+
+    ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom,
+                               users[1].gid);
+    assert_int_equal(ret, case_b);
+
+    ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom,
+                               TEST_LOCAL_GID_1);
+    assert_int_equal(ret, case_c);
+
+    ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom,
+                               TEST_LOCAL_GID_2);
+    assert_int_equal(ret, case_d);
+}
+
+/* uid tests */
+
+void test_ncache_nocache_gid(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 0, 0, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_gids(test_ctx);
+
+    check_gids(test_ctx, ENOENT, ENOENT, ENOENT, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_local_gid(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 0, 10, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_gids(test_ctx);
+
+    check_gids(test_ctx, ENOENT, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_domain_gid(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 10, 0, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_gids(test_ctx);
+
+    check_gids(test_ctx, EEXIST, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+void test_ncache_both_gid(void **state)
+{
+    errno_t ret;
+    struct ncache_test_ctx *test_ctx;
+
+    test_ctx = talloc_get_type_abort(*state, struct ncache_test_ctx);
+    assert_non_null(test_ctx);
+
+    ret = sss_ncache_init(test_ctx, 10, 10, &test_ctx->ncache);
+    assert_int_equal(ret, EOK);
+
+    set_gids(test_ctx);
+
+    check_gids(test_ctx, EEXIST, ENOENT, EEXIST, ENOENT);
+
+    talloc_zfree(test_ctx->ncache);
+}
+
+int main(int argc, const char *argv[])
+{
+    int rv;
+    poptContext pc;
+    int opt;
+    struct poptOption long_options[] = {
+        POPT_AUTOHELP
+        SSSD_DEBUG_OPTS
+        POPT_TABLEEND
+    };
+
+    const struct CMUnitTest tests[] = {
+        /* user */
+        cmocka_unit_test_setup_teardown(test_ncache_nocache_user,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_local_user,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_domain_user,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_both_user,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        /* uid */
+        cmocka_unit_test_setup_teardown(test_ncache_nocache_uid,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_local_uid,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_domain_uid,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_both_uid,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        /* group */
+        cmocka_unit_test_setup_teardown(test_ncache_nocache_group,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_local_group,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_domain_group,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_both_group,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        /* gid */
+        cmocka_unit_test_setup_teardown(test_ncache_nocache_gid,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_local_gid,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_domain_gid,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+        cmocka_unit_test_setup_teardown(test_ncache_both_gid,
+                                        test_ncache_setup,
+                                        test_ncache_teardown),
+    };
+
+    /* Set debug level to invalid value so we can deside 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);
+
+    tests_set_cwd();
+    test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME);
+    rv = cmocka_run_group_tests(tests, NULL, NULL);
+
+    return rv;
+}
\ No newline at end of file
-- 
2.5.5

_______________________________________________
sssd-devel mailing list
[email protected]
https://lists.fedorahosted.org/admin/lists/[email protected]

Reply via email to