test_nss_srv.c revision 1f3127e88a87953f059c9a70d3582ae1719594b1
/*
Authors:
Jakub Hrozek <jhrozek@redhat.com>
Copyright (C) 2013 Red Hat
SSSD tests: NSS responder tests
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <talloc.h>
#include <tevent.h>
#include <errno.h>
#include <popt.h>
#include "tests/cmocka/common_mock.h"
#include "tests/cmocka/common_mock_resp.h"
#include "responder/common/negcache.h"
#include "responder/nss/nsssrv_private.h"
#include "sss_client/idmap/sss_nss_idmap.h"
#include "util/util_sss_idmap.h"
#define TESTS_PATH "tests_nss"
#define TEST_CONF_DB "test_nss_conf.ldb"
#define TEST_DOM_NAME "nss_test"
#define TEST_SUBDOM_NAME "test.sub"
#define TEST_ID_PROVIDER "ldap"
struct nss_test_ctx {
struct sss_test_ctx *tctx;
struct sss_domain_info *subdom;
struct sss_cmd_table *nss_cmds;
bool ncache_hit;
};
struct nss_test_ctx *nss_test_ctx;
/* Mock NSS structure */
struct nss_ctx *
{
enum idmap_error_code err;
if (!nctx) {
return NULL;
}
return NULL;
}
if (err != IDMAP_SUCCESS) {
return NULL;
}
return nctx;
}
/* Mock reading requests from a client. Use values passed from mock
* instead
*/
{
if (wtype == WRAP_CALL_REAL) {
}
if (len == 0) {
}
return;
}
/* Mock returning result to client. Terminate the unit test instead. */
{
}
{
}
{
return sss_mock_type(enum sss_cli_command);
}
{
return EOK;
}
/* Intercept negative cache lookups */
{
int ret;
nss_test_ctx->ncache_hit = true;
}
return ret;
}
{
int ret;
nss_test_ctx->ncache_hit = true;
}
return ret;
}
/* Mock input from the client library */
static void mock_input_user_or_group(const char *username)
{
}
{
}
static void mock_fill_user(void)
{
/* One packet for the entry and one for num entries */
}
static void mock_fill_group_with_members(unsigned members)
{
unsigned i;
if (members == 0) return;
/* Member header , one per member */
for (i=0; i<members; i++) {
}
}
{
/* Sequence of null terminated strings (name, passwd, gecos, dir, shell) */
return EOK;
}
{
unsigned i;
if (*nmem > 0) {
for (i = 0; i < *nmem; i++) {
}
}
/* Make sure we exactly matched the end of the packet */
return EOK;
}
/* ====================== The tests =============================== */
/* Check getting cached and valid user from cache. Account callback will
* not be called and test_nss_getpwnam_check will make sure the user is
* the same as the test entered before starting
*/
{
return EOK;
}
void test_nss_getpwnam(void **state)
{
/* Prime the cache with a valid user */
"testuser", 123, 456, "test user",
NULL, 300, 0);
mock_input_user_or_group("testuser");
/* Query for that user, call a callback when command finishes */
/* Wait until the test finishes with EOK */
}
/* Test that searching for a nonexistant user yields ENOENT.
* Account callback will be called
*/
void test_nss_getpwnam_neg(void **state)
{
mock_input_user_or_group("testuser_neg");
/* Wait until the test finishes with ENOENT */
/* Test that subsequent search for a nonexistent user yields
* ENOENT and Account callback is not called, on the other hand
* the ncache functions will be called
*/
mock_input_user_or_group("testuser_neg");
/* Wait until the test finishes with ENOENT */
/* Negative cache was hit this time */
}
static int test_nss_getpwnam_search_acct_cb(void *pvt)
{
"testuser_search", 567, 890, "test search",
NULL, 300, 0);
return EOK;
}
{
return EOK;
}
void test_nss_getpwnam_search(void **state)
{
struct ldb_result *res;
mock_input_user_or_group("testuser_search");
"testuser_search", &res);
/* Wait until the test finishes with EOK */
/* test_nss_getpwnam_search_check will check the user attributes */
"testuser_search", &res);
}
/* Test that searching for a user 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_getpwnam_update_acct_cb(void *pvt)
{
return EOK;
}
{
return EOK;
}
void test_nss_getpwnam_update(void **state)
{
struct ldb_result *res;
const char *shell;
/* Prime the cache with a valid but expired user */
"testuser_update", 10, 11, "test user",
/* Mock client input */
mock_input_user_or_group("testuser_update");
/* Mock client command */
/* Call this function when user is updated by the mock DP request */
/* Call this function to check what the responder returned to the client */
/* Mock output buffer */
/* Fire the command */
/* Wait until the test finishes with EOK */
/* Check the user was updated in the cache */
"testuser_update", &res);
}
/* Check that a FQDN is returned if the domain is FQDN-only and a
* FQDN is requested
*/
{
return EOK;
}
void test_nss_getpwnam_fqdn(void **state)
{
/* Prime the cache with a valid user */
"testuser_fqdn", 124, 457, "test user",
NULL, 300, 0);
/* Query for that user, call a callback when command finishes */
/* Wait until the test finishes with EOK */
}
/*
* Check that FQDN processing is able to handle arbitrarily sized
* delimeter
*/
{
return EOK;
}
void test_nss_getpwnam_fqdn_fancy(void **state)
{
/* Prime the cache with a valid user */
"testuser_fqdn_fancy", 125, 458, "test user",
NULL, 300, 0);
/* Query for that user, call a callback when command finishes */
/* Wait until the test finishes with 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
*/
{
return EOK;
}
void test_nss_getpwuid(void **state)
{
/* Prime the cache with a valid user */
"testuser1", 101, 401, "test user1",
NULL, 300, 0);
/* Query for that id, call a callback when command finishes */
/* Wait until the test finishes with EOK */
}
/* Test that searching for a nonexistent id yields ENOENT.
* Account callback will be called
*/
void test_nss_getpwuid_neg(void **state)
{
/* Wait until the test finishes with ENOENT */
/* 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
*/
/* Wait until the test finishes with ENOENT */
/* Negative cache was hit this time */
}
static int test_nss_getpwuid_search_acct_cb(void *pvt)
{
"exampleuser_search", 107, 987, "example search",
NULL, 300, 0);
return EOK;
}
{
return EOK;
}
void test_nss_getpwuid_search(void **state)
{
struct ldb_result *res;
107, &res);
/* Wait until the test finishes with EOK */
/* test_nss_getpwuid_search_check will check the id attributes */
107, &res);
}
/* 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)
{
return EOK;
}
{
return EOK;
}
void test_nss_getpwuid_update(void **state)
{
struct ldb_result *res;
const char *shell;
/* Prime the cache with a valid but expired user */
"exampleuser_update", 109, 11000, "example user",
/* Mock client input */
/* Mock client command */
/* Call this function when id is updated by the mock DP request */
/* Call this function to check what the responder returned to the client */
/* Mock output buffer */
/* Fire the command */
/* Wait until the test finishes with EOK */
/* Check the user was updated in the cache */
109, &res);
}
/* Testsuite setup and teardown */
void **state)
{
/* FIXME - perhaps this should be folded into sssd_domain_init or stricty
* used together
*/
/* Initialize the NSS responder */
/* Create client context */
}
{
int i;
for (i = 0; i < nmem; i++) {
}
return EOK;
}
{
int ret;
.gr_gid = 1123,
};
assert_int_equal(nmem, 0);
return EOK;
}
/* Test that requesting a valid, cached group with no members returns a valid
* group structure
*/
void test_nss_getgrnam_no_members(void **state)
{
/* Prime the cache with a valid group */
"testgroup", 1123,
NULL, 300, 0);
mock_input_user_or_group("testgroup");
/* Query for that group, call a callback when command finishes */
/* Wait until the test finishes with EOK */
}
{
int ret;
.gr_gid = 1124,
};
return EOK;
}
/* Test that requesting a valid, cached group with some members returns a valid
* group structure with those members present
*/
void test_nss_getgrnam_members(void **state)
{
/* Prime the cache with a valid group and some members */
"testgroup_members", 1124,
NULL, 300, 0);
"testmember1", 2001, 456, "test member1",
NULL, 300, 0);
"testmember2", 2002, 456, "test member2",
NULL, 300, 0);
"testgroup_members", "testmember1",
SYSDB_MEMBER_USER, false);
"testgroup_members", "testmember2",
SYSDB_MEMBER_USER, false);
mock_input_user_or_group("testgroup_members");
/* Query for that group, call a callback when command finishes */
/* Wait until the test finishes with EOK */
}
{
int ret;
"testmember2@"TEST_DOM_NAME };
.gr_gid = 1124,
};
return EOK;
}
/* Test that requesting a valid, cached group with some members returns a valid
* group structure with those members present as fully qualified names
*/
void test_nss_getgrnam_members_fqdn(void **state)
{
/* Query for that group, call a callback when command finishes */
/* Wait until the test finishes with EOK */
/* Restore FQDN settings */
}
{
int ret;
"submember2@"TEST_SUBDOM_NAME };
.gr_gid = 2124,
};
return EOK;
}
/* Test that requesting a valid, cached group with some members returns a valid
* group structure with those members present as fully qualified names
*/
void test_nss_getgrnam_members_subdom(void **state)
{
/* Add a group from a subdomain and two members from the same subdomain
*/
"testsubdomgroup@"TEST_SUBDOM_NAME,
"submember1@"TEST_SUBDOM_NAME,
4001, 456, "test subdomain member1",
NULL, 300, 0);
"submember2@"TEST_SUBDOM_NAME,
2002, 456, "test subdomain member2",
NULL, 300, 0);
"testsubdomgroup@"TEST_SUBDOM_NAME,
"submember1@"TEST_SUBDOM_NAME,
SYSDB_MEMBER_USER, false);
"testsubdomgroup@"TEST_SUBDOM_NAME,
"submember2@"TEST_SUBDOM_NAME,
SYSDB_MEMBER_USER, false);
/* Query for that group, call a callback when command finishes */
/* Wait until the test finishes with EOK */
/* Restore FQDN settings */
}
{
int ret;
const char *exp_members[] = { "testmember1",
"testmember2",
"submember1@"TEST_SUBDOM_NAME };
.gr_gid = 1124,
};
return EOK;
}
void test_nss_getgrnam_mix_dom(void **state)
{
const char *group_strdn = NULL;
/* Add a subdomain user to a parent domain group */
"testgroup_members");
add_groups[0] = group_strdn;
"submember1@"TEST_SUBDOM_NAME,
add_groups, NULL);
mock_input_user_or_group("testgroup_members");
/* Query for that group, call a callback when command finishes */
/* Wait until the test finishes with EOK */
}
{
int ret;
"testmember2@"TEST_DOM_NAME,
"submember1@"TEST_SUBDOM_NAME };
.gr_gid = 1124,
};
return EOK;
}
void test_nss_getgrnam_mix_dom_fqdn(void **state)
{
/* Query for that group, call a callback when command finishes */
/* Wait until the test finishes with EOK */
/* Restore FQDN settings */
}
{
int ret;
"submember2@"TEST_SUBDOM_NAME,
"testmember1@"TEST_DOM_NAME };
.gr_gid = 2124,
};
return EOK;
}
void test_nss_getgrnam_mix_subdom(void **state)
{
const char *group_strdn = NULL;
/* Add a subdomain user to a parent domain group */
"testsubdomgroup@"TEST_SUBDOM_NAME);
add_groups[0] = group_strdn;
"testmember1",
add_groups, NULL);
/* Query for that group, call a callback when command finishes */
/* Wait until the test finishes with EOK */
}
{
const char *name;
enum sss_id_type type;
char *expected_result = sss_mock_ptr_type(char *);
if (expected_result == NULL) {
assert_int_equal(blen, 0);
} else {
}
return EOK;
}
void test_nss_well_known_getnamebysid(void **state)
{
/* Wait until the test finishes with EOK */
}
void test_nss_well_known_getnamebysid_special(void **state)
{
/* Wait until the test finishes with EOK */
}
void test_nss_well_known_getnamebysid_non_existing(void **state)
{
/* Wait until the test finishes with EOK */
}
void test_nss_well_known_getidbysid_failure(void **state)
{
/* Wait until the test finishes with EOK */
}
void test_nss_well_known_getsidbyname(void **state)
{
/* Wait until the test finishes with EOK */
}
void test_nss_well_known_getsidbyname_nonexisting(void **state)
{
/* Wait until the test finishes with EOK */
}
void test_nss_well_known_getsidbyname_special(void **state)
{
/* Wait until the test finishes with EOK */
}
void nss_test_setup(void **state)
{
struct sss_test_conf_param params[] = {
{ "enumerate", "false" },
};
}
void nss_fqdn_test_setup(void **state)
{
struct sss_test_conf_param params[] = {
{ "enumerate", "false" },
{ "full_name_format", "%1$s@%2$s" },
};
}
void nss_subdom_test_setup(void **state)
{
struct sss_domain_info *subdomain;
false, false, NULL);
false, false, NULL);
}
void nss_fqdn_fancy_test_setup(void **state)
{
struct sss_test_conf_param params[] = {
{ "enumerate", "false" },
{ "full_name_format", "%1$s@@@@@%2$s" },
};
}
void nss_test_teardown(void **state)
{
}
{
int rv;
int no_cleanup = 0;
int opt;
struct poptOption long_options[] = {
_("Do not delete the test database after a test run"), NULL },
};
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */
switch(opt) {
default:
return 1;
}
}
/* Even though normally the tests should clean up after themselves
* they might not after a failed run. Remove the old db to be sure */
if (rv == 0 && !no_cleanup) {
}
return rv;
}