Hi,

I have new version of this patch set.
I fixed CI tests on debian [1]. My thanks belongs to Lukas and Nikolai.


[1] http://sssd-ci.duckdns.org/logs/job/44/04/summary.html


Regards

--
Petr^4 Čech
>From 49700263a32151a723b99b900f17583c97c69bba Mon Sep 17 00:00:00 2001
From: Petr Cech <pc...@redhat.com>
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       | 98 +++++++++++++++++++++++++++++
 src/responder/common/negcache_files.h       | 31 +++++++++
 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 390e58938b123a4043edec3bc4dea0230c0fd298..428db6b40725223fcfeac7bd57ce6588dc80da78 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -452,6 +452,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 \
@@ -577,6 +578,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.h \
     src/responder/common/negcache.h \
     src/responder/sudo/sudosrv_private.h \
     src/responder/autofs/autofs_private.h \
@@ -1799,6 +1801,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 \
@@ -1896,6 +1899,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 a9b1c4362b5c0c6b158830b1bf2ef68db09d8d06..3ed82ca0ac80e7ec7de26ca9cc5c0f37bb55f721 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -85,6 +85,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..a6749635285b6f3b48a8181d59b21762c45adbc0 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 it 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..5a8988f4d288bf61fdc4fb238a4932f98a2122f1
--- /dev/null
+++ b/src/responder/common/negcache_files.c
@@ -0,0 +1,98 @@
+/*
+   SSSD
+
+   NSS Responder
+
+   Copyright (C) Petr Čech <pc...@redhat.com>	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 %"SPRIuid" 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 %"SPRIgid" 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..01d9f0828045ae695f225a32b0933761dd830710
--- /dev/null
+++ b/src/responder/common/negcache_files.h
@@ -0,0 +1,31 @@
+/*
+   SSSD
+
+   NSS Responder
+
+   Copyright (C) Petr Čech <pc...@redhat.com>	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 d8deea2b450ca8a559920c843e3a941e0c3fe8e3 Mon Sep 17 00:00:00 2001
From: Petr Cech <pc...@redhat.com>
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         |  33 ++
 src/tests/cwrap/cwrap_test_setup.sh |   2 +
 src/tests/cwrap/group               |   1 +
 src/tests/cwrap/test_negcache.c     | 675 ++++++++++++++++++++++++++++++++++++
 4 files changed, 711 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..99029d7d1dfd22897db31775b896d0fc21141d25 100644
--- a/src/tests/cwrap/Makefile.am
+++ b/src/tests/cwrap/Makefile.am
@@ -14,6 +14,7 @@ AM_CPPFLAGS = \
 
 TESTS_ENVIRONMENT = \
     CWRAP_TEST_SRCDIR=$(abs_srcdir) \
+    ABS_TOP_BUILDDIR=$(abs_top_builddir) \
     . $(srcdir)/cwrap_test_setup.sh; \
     $(AUX_TESTS_ENVIRONMENT) \
     $(NULL)
@@ -35,6 +36,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 +64,7 @@ check_PROGRAMS += \
     server-tests \
     usertools-tests \
     responder_common-tests \
+    negcache-tests \
     $(NULL)
 endif # HAVE_UID_WRAPPER
 endif # HAVE_NSS_WRAPPER
@@ -124,4 +140,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/cwrap_test_setup.sh b/src/tests/cwrap/cwrap_test_setup.sh
index 0d35cb7e5f94a4ee035bbc794640f1dd79b17649..68d731d2df15da01238c3765134866f9e527ac49 100755
--- a/src/tests/cwrap/cwrap_test_setup.sh
+++ b/src/tests/cwrap/cwrap_test_setup.sh
@@ -15,3 +15,5 @@ export NSS_WRAPPER_PASSWD=$CWRAP_TEST_SRCDIR/passwd
 export NSS_WRAPPER_GROUP=$CWRAP_TEST_SRCDIR/group
 export UID_WRAPPER=1
 export UID_WRAPPER_ROOT=1
+
+export LDB_MODULES_PATH=$ABS_TOP_BUILDDIR/ldb_mod_test_dir
\ No newline at end of file
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..cac357ec565df7432ff5b0c9e28b9b725bbe87bf
--- /dev/null
+++ b/src/tests/cwrap/test_negcache.c
@@ -0,0 +1,675 @@
+/*
+    Authors:
+        Petr Čech <pc...@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 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 TIMEOUT 10000
+
+#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, TIMEOUT, &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, TIMEOUT, 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, TIMEOUT, TIMEOUT, &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, TIMEOUT, &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, TIMEOUT, 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, TIMEOUT, TIMEOUT, &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, TIMEOUT, &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, TIMEOUT, 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, TIMEOUT, TIMEOUT, &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, TIMEOUT, &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, TIMEOUT, 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, TIMEOUT, TIMEOUT, &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
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/admin/lists/sssd-devel@lists.fedorahosted.org

Reply via email to