From 5341e1331d984f48ee28118dba05d11dd4f068c4 Mon Sep 17 00:00:00 2001
From: Pallavi Jha <pallavikumarijha@gmail.com>
Date: Mon, 27 Jan 2014 19:31:06 +0545
Subject: [PATCH] cmocka-unit-test-for-functions-getpwuid*-added

---
 Makefile.am                     |   1 +
 src/tests/cmocka/test_nss_srv.c | 368 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 369 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index 9c155d68c7f452bb02a4da154992fa2fca6af273..bf37bd2d78b861b69bdb5d9a3ba5162ebce1ccc2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1310,6 +1310,7 @@ nss_srv_tests_CFLAGS = \
     $(AM_CFLAGS)
 nss_srv_tests_LDFLAGS = \
     -Wl,-wrap,sss_ncache_check_user \
+    -Wl,-wrap,sss_ncache_check_uid \
     -Wl,-wrap,sss_packet_get_body \
     -Wl,-wrap,sss_packet_get_cmd \
     -Wl,-wrap,sss_cmd_send_empty \
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
index 4db108a79df9d3ec5f6f51bb2356f6f36a022a65..34dae58fd9f901faa5dc3212759c5283ad4f2ae8 100644
--- a/src/tests/cmocka/test_nss_srv.c
+++ b/src/tests/cmocka/test_nss_srv.c
@@ -158,6 +158,19 @@ int __wrap_sss_ncache_check_user(struct sss_nc_ctx *ctx, int ttl,
     return ret;
 }
 
+int __real_sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, uid_t uid);
+
+int __wrap_sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, uid_t uid)
+{
+    int ret;
+
+    ret = __real_sss_ncache_check_uid(ctx, ttl, uid);
+    if (ret == EEXIST) {
+        nss_test_ctx->ncache_hit = true;
+    }
+    return ret;
+}
+
 /* Mock input from the client library */
 static void mock_input_user_or_group(const char *username)
 {
@@ -165,6 +178,12 @@ static void mock_input_user_or_group(const char *username)
     will_return(__wrap_sss_packet_get_body, username);
 }
 
+static void mock_input_id(uint8_t *id)
+{
+    will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
+    will_return(__wrap_sss_packet_get_body, id);
+}
+
 static void mock_fill_user(void)
 {
     /* One packet for the entry and one for num entries */
@@ -587,6 +606,343 @@ void test_nss_getpwnam_fqdn_fancy(void **state)
     assert_int_equal(ret, EOK);
 }
 
+/* Check getting cached and valid id from cache. Account callback will
+ * not be called and test_nss_getpwuid_check will make sure the id is
+ * the same as the test entered before starting
+ */
+static int test_nss_getpwuid_check(uint32_t status, uint8_t *body, size_t blen)
+{
+    struct passwd pwd;
+    errno_t ret;
+
+    assert_int_equal(status, EOK);
+
+    ret = parse_user_packet(body, blen, &pwd);
+    assert_int_equal(ret, EOK);
+
+    assert_int_equal(pwd.pw_uid, 101);
+    assert_int_equal(pwd.pw_gid, 401);
+    assert_string_equal(pwd.pw_name, "testuser1");
+    assert_string_equal(pwd.pw_shell, "/bin/sh");
+    assert_string_equal(pwd.pw_passwd, "*");
+    return EOK;
+}
+
+void test_nss_getpwuid(void **state)
+{
+    errno_t ret;
+
+    /* Prime the cache with a valid user */
+    ret = sysdb_add_user(nss_test_ctx->tctx->dom,
+                         "testuser1", 101, 401, "test user1",
+                         "/home/testuser1", "/bin/sh", NULL,
+                         NULL, 300, 0);
+    assert_int_equal(ret, EOK);
+
+    uint8_t id = 101;
+    mock_input_id(&id);
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
+    mock_fill_user();
+
+    /* Query for that id, call a callback when command finishes */
+    set_cmd_cb(test_nss_getpwuid_check);
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with EOK */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    assert_int_equal(ret, EOK);
+}
+
+/* Test that searching for a nonexistent id yields ENOENT.
+ * Account callback will be called
+ */
+void test_nss_getpwuid_neg(void **state)
+{
+    errno_t ret;
+
+    uint8_t id = 102;
+    mock_input_id(&id);
+    mock_account_recv_simple();
+
+    assert_true(nss_test_ctx->ncache_hit == false);
+    
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with ENOENT */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    assert_int_equal(ret, ENOENT);
+    assert_true(nss_test_ctx->ncache_hit == false);
+
+    /* Test that subsequent search for a nonexistent id yields
+     * ENOENT and Account callback is not called, on the other hand
+     * the ncache functions will be called
+     */
+    nss_test_ctx->tctx->done = false;
+
+    mock_input_id(&id);
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with ENOENT */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    assert_int_equal(ret, ENOENT);
+    /* Negative cache was hit this time */
+    assert_true(nss_test_ctx->ncache_hit == true);
+}
+
+static int test_nss_getpwuid_search_acct_cb(void *pvt)
+{
+    errno_t ret;
+    struct nss_test_ctx *ctx = talloc_get_type(pvt, struct nss_test_ctx);
+
+    ret = sysdb_add_user(ctx->tctx->dom,
+                         "exampleuser_search", 107, 987, "example search",
+                         "/home/examplesearch", "/bin/sh", NULL,
+                         NULL, 300, 0);
+    assert_int_equal(ret, EOK);
+
+    return EOK;
+}
+
+static int test_nss_getpwuid_search_check(uint32_t status,
+                                          uint8_t *body, size_t blen)
+{
+    struct passwd pwd;
+    errno_t ret;
+
+    assert_int_equal(status, EOK);
+
+    ret = parse_user_packet(body, blen, &pwd);
+    assert_int_equal(ret, EOK);
+
+    assert_int_equal(pwd.pw_uid, 107);
+    assert_int_equal(pwd.pw_gid, 987);
+    assert_string_equal(pwd.pw_name, "exampleuser_search");
+    assert_string_equal(pwd.pw_shell, "/bin/sh");
+    return EOK;
+}
+
+void test_nss_getpwuid_search(void **state)
+{
+    errno_t ret;
+    struct ldb_result *res;
+
+    uint8_t id = 107;
+    mock_input_id(&id);
+    mock_account_recv(0, 0, NULL, test_nss_getpwuid_search_acct_cb, nss_test_ctx);
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
+    mock_fill_user();
+    set_cmd_cb(test_nss_getpwuid_search_check);
+
+    ret = sysdb_getpwuid(nss_test_ctx, nss_test_ctx->tctx->dom,
+                         107, &res);
+    assert_int_equal(ret, EOK);
+    assert_int_equal(res->count, 0);
+
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with EOK */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    assert_int_equal(ret, EOK);
+
+    /* test_nss_getpwuid_search_check will check the id attributes */
+    ret = sysdb_getpwuid(nss_test_ctx, nss_test_ctx->tctx->dom,
+                         107, &res);
+    assert_int_equal(ret, EOK);
+    assert_int_equal(res->count, 1);
+}
+
+/* Test that searching for an id that is expired in the cache goes to the DP
+ * which updates the record and the NSS responder returns the updated record
+ *
+ * The user's shell attribute is updated.
+ */
+static int test_nss_getpwuid_update_acct_cb(void *pvt)
+{
+    errno_t ret;
+    struct nss_test_ctx *ctx = talloc_get_type(pvt, struct nss_test_ctx);
+
+    ret = sysdb_store_user(ctx->tctx->dom,
+                           "exampleuser_update", NULL, 109, 11000, "example user",
+                           "/home/exampleuser", "/bin/ksh", NULL,
+                           NULL, NULL, 300, 0);
+    assert_int_equal(ret, EOK);
+
+    return EOK;
+}
+
+static int test_nss_getpwuid_update_check(uint32_t status,
+                                          uint8_t *body, size_t blen)
+{
+    struct passwd pwd;
+    errno_t ret;
+
+    assert_int_equal(status, EOK);
+
+    ret = parse_user_packet(body, blen, &pwd);
+    assert_int_equal(ret, EOK);
+
+    assert_int_equal(pwd.pw_uid, 109);
+    assert_int_equal(pwd.pw_gid, 11000);
+    assert_string_equal(pwd.pw_name, "exampleuser_update");
+    assert_string_equal(pwd.pw_shell, "/bin/ksh");
+    return EOK;
+}
+
+void test_nss_getpwuid_update(void **state)
+{
+    errno_t ret;
+    struct ldb_result *res;
+    const char *shell;
+
+    /* Prime the cache with a valid but expired user */
+    ret = sysdb_add_user(nss_test_ctx->tctx->dom,
+                         "exampleuser_update", 109, 11000, "example user",
+                         "/home/exampleuser", "/bin/sh", NULL,
+                         NULL, 1, 1);
+    assert_int_equal(ret, EOK);
+
+    /* Mock client input */
+    uint8_t id = 109;
+    mock_input_id(&id);
+    /* Mock client command */
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
+    /* Call this function when id is updated by the mock DP request */
+    mock_account_recv(0, 0, NULL, test_nss_getpwuid_update_acct_cb, nss_test_ctx);
+    /* Call this function to check what the responder returned to the client */
+    set_cmd_cb(test_nss_getpwuid_update_check);
+    /* Mock output buffer */
+    mock_fill_user();
+
+    /* Fire the command */
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with EOK */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    assert_int_equal(ret, EOK);
+
+    /* Check the user was updated in the cache */
+    ret = sysdb_getpwuid(nss_test_ctx, nss_test_ctx->tctx->dom,
+                         109, &res);
+    assert_int_equal(ret, EOK);
+    assert_int_equal(res->count, 1);
+
+    shell = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SHELL, NULL);
+    assert_string_equal(shell, "/bin/ksh");
+}
+
+/* Check that a FQDN is returned if the domain is FQDN-only and a
+ * FQDN is requested
+ */
+static int test_nss_getpwuid_check_fqdn(uint32_t status,
+                                        uint8_t *body, size_t blen)
+{
+    struct passwd pwd;
+    errno_t ret;
+
+    assert_int_equal(status, EOK);
+
+    nss_test_ctx->cctx->rctx->domains[0].fqnames = false;
+
+    ret = parse_user_packet(body, blen, &pwd);
+    assert_int_equal(ret, EOK);
+
+    assert_int_equal(pwd.pw_uid, 301);
+    assert_int_equal(pwd.pw_gid, 755);
+    assert_string_equal(pwd.pw_name, "exampleuser_fqdn@"TEST_DOM_NAME);
+    assert_string_equal(pwd.pw_shell, "/bin/sh");
+    return EOK;
+}
+
+void test_nss_getpwuid_fqdn(void **state)
+{
+    errno_t ret;
+
+    /* Prime the cache with a valid user */
+    ret = sysdb_add_user(nss_test_ctx->tctx->dom,
+                         "exampleuser_fqdn", 301, 755, "example user",
+                         "/home/exampleuser", "/bin/sh", NULL,
+                         NULL, 300, 0);
+    assert_int_equal(ret, EOK);
+
+    uint8_t id = 301;
+    mock_input_id(&id);
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
+    mock_fill_user();
+
+    /* Query for that user, call a callback when command finishes */
+    set_cmd_cb(test_nss_getpwuid_check_fqdn);
+    nss_test_ctx->cctx->rctx->domains[0].fqnames = true;
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with EOK */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    assert_int_equal(ret, EOK);
+}
+
+/*
+ * Check that FQDN processing is able to handle arbitrarily sized
+ * delimeter
+ */
+static int test_nss_getpwuid_check_fancy_fqdn(uint32_t status,
+                                              uint8_t *body, size_t blen)
+{
+    struct passwd pwd;
+    errno_t ret;
+
+    assert_int_equal(status, EOK);
+
+    nss_test_ctx->cctx->rctx->domains[0].fqnames = false;
+
+    ret = parse_user_packet(body, blen, &pwd);
+    assert_int_equal(ret, EOK);
+
+    assert_int_equal(pwd.pw_uid, 424);
+    assert_int_equal(pwd.pw_gid, 323);
+    assert_string_equal(pwd.pw_name, "exampleuser_fqdn_fancy@@@@@"TEST_DOM_NAME);
+    assert_string_equal(pwd.pw_shell, "/bin/sh");
+    return EOK;
+}
+
+void test_nss_getpwuid_fqdn_fancy(void **state)
+{
+    errno_t ret;
+
+    /* Prime the cache with a valid user */
+    ret = sysdb_add_user(nss_test_ctx->tctx->dom,
+                         "exampleuser_fqdn_fancy", 424, 323, "example user",
+                         "/home/exampleuser", "/bin/sh", NULL,
+                         NULL, 300, 0);
+    assert_int_equal(ret, EOK);
+
+    uint8_t id = 424;
+    mock_input_id(&id);
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
+    mock_fill_user();
+
+    /* Query for that user, call a callback when command finishes */
+    set_cmd_cb(test_nss_getpwuid_check_fancy_fqdn);
+    nss_test_ctx->cctx->rctx->domains[0].fqnames = true;
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
+                          nss_test_ctx->nss_cmds);
+    assert_int_equal(ret, EOK);
+
+    /* Wait until the test finishes with EOK */
+    ret = test_ev_loop(nss_test_ctx->tctx);
+    assert_int_equal(ret, EOK);
+}
+
 /* Testsuite setup and teardown */
 void test_nss_setup(struct sss_test_conf_param params[],
                     void **state)
@@ -1330,16 +1686,28 @@ int main(int argc, const char *argv[])
     const UnitTest tests[] = {
         unit_test_setup_teardown(test_nss_getpwnam,
                                  nss_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getpwuid,
+                                 nss_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_getpwnam_neg,
                                  nss_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getpwuid_neg,
+                                 nss_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_getpwnam_search,
                                  nss_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getpwuid_search,
+                                 nss_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_getpwnam_update,
                                  nss_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getpwuid_update,
+                                 nss_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_getpwnam_fqdn,
                                  nss_fqdn_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getpwuid_fqdn,
+                                 nss_fqdn_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_getpwnam_fqdn_fancy,
                                  nss_fqdn_fancy_test_setup, nss_test_teardown),
+        unit_test_setup_teardown(test_nss_getpwuid_fqdn_fancy,
+                                 nss_fqdn_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_getgrnam_no_members,
                                  nss_test_setup, nss_test_teardown),
         unit_test_setup_teardown(test_nss_getgrnam_members,
-- 
1.8.3.1

