PERFORCE change 100398 for review
Michael Bushkov
bushman at FreeBSD.org
Sat Jul 1 16:03:48 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=100398
Change 100398 by bushman at bushman_nss_ldap_cached on 2006/07/01 15:29:47
Regression tests for "passwd" and "group" databases added. Small bug fixes in test-getserv.c
Affected files ...
.. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/Makefile#3 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getgr.c#3 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getgr.t#1 add
.. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getpw.c#3 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getpw.t#1 add
.. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getserv.c#5 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getserv.t#4 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/testutil.h#5 edit
Differences ...
==== //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/Makefile#3 (text+ko) ====
@@ -1,6 +1,6 @@
-# $FreeBSD: src/tools/regression/lib/libc/net/Makefile,v 1.2 2005/02/12 18:09:20 ru Exp $
+# $FreeBSD$
-TESTS= test-getserv
+TESTS= test-getpw test-getgr test-getserv
CFLAGS+= -g -Wall
.PHONY: tests
==== //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getgr.c#3 (text+ko) ====
@@ -1,0 +1,534 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman at freebsd.org>
+ * All rights regrped.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+#include "testutil.h"
+
+enum test_methods {
+ TEST_GETGRENT,
+ TEST_GETGRNAM,
+ TEST_GETGRGID,
+ TEST_GETGRENT_2PASS,
+ TEST_BUILD_SNAPSHOT
+};
+
+static int debug = 0;
+static enum test_methods method = TEST_BUILD_SNAPSHOT;
+
+DECLARE_TEST_DATA(group)
+DECLARE_TEST_FILE_SNAPSHOT(group)
+DECLARE_1PASS_TEST(group)
+DECLARE_2PASS_TEST(group)
+
+static void clone_group(struct group *, struct group const *);
+static int compare_group(struct group *, struct group *, void *);
+static void dump_group(struct group *);
+static void free_group(struct group *);
+
+static void sdump_group(struct group *, char *, size_t);
+static int group_read_snapshot_func(struct group *, char *);
+
+static int group_check_ambiguity(struct group_test_data *,
+ struct group *);
+static int group_fill_test_data(struct group_test_data *);
+static int group_test_correctness(struct group *, void *);
+static int group_test_getgrnam(struct group *, void *);
+static int group_test_getgrgid(struct group *, void *);
+static int group_test_getgrent(struct group *, void *);
+
+static void usage(void) __attribute__((__noreturn__));
+
+IMPLEMENT_TEST_DATA(group)
+IMPLEMENT_TEST_FILE_SNAPSHOT(group)
+IMPLEMENT_1PASS_TEST(group)
+IMPLEMENT_2PASS_TEST(group)
+
+static void
+clone_group(struct group *dest, struct group const *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ char **cp;
+ int members_num;
+
+ memset(dest, 0, sizeof(struct group));
+
+ if (src->gr_name != NULL) {
+ dest->gr_name = strdup(src->gr_name);
+ assert(dest->gr_name != NULL);
+ }
+
+ if (src->gr_passwd != NULL) {
+ dest->gr_passwd = strdup(src->gr_passwd);
+ assert(dest->gr_passwd != NULL);
+ }
+ dest->gr_gid = src->gr_gid;
+
+ if (src->gr_mem != NULL) {
+ members_num = 0;
+ for (cp = src->gr_mem; *cp; ++cp)
+ ++members_num;
+
+ dest->gr_mem = (char **)malloc(
+ (members_num + 1) * (sizeof(char *)));
+ assert(dest->gr_mem != NULL);
+ memset(dest->gr_mem, 0, (members_num+1) * (sizeof(char *)));
+
+ for (cp = src->gr_mem; *cp; ++cp) {
+ dest->gr_mem[cp - src->gr_mem] = strdup(*cp);
+ assert(dest->gr_mem[cp - src->gr_mem] != NULL);
+ }
+ }
+}
+
+static void
+free_group(struct group *grp)
+{
+ char **cp;
+
+ assert(grp != NULL);
+
+ free(grp->gr_name);
+ free(grp->gr_passwd);
+
+ for (cp = grp->gr_mem; *cp; ++cp)
+ free(*cp);
+ free(grp->gr_mem);
+}
+
+static int
+compare_group(struct group *grp1, struct group *grp2, void *mdata)
+{
+ char **c1, **c2;
+
+ if (grp1 == grp2)
+ return (0);
+
+ if ((grp1 == NULL) || (grp2 == NULL))
+ goto errfin;
+
+ if ((strcmp(grp1->gr_name, grp2->gr_name) != 0) ||
+ (strcmp(grp1->gr_passwd, grp2->gr_passwd) != 0) ||
+ (grp1->gr_gid != grp2->gr_gid))
+ goto errfin;
+
+ c1 = grp1->gr_mem;
+ c2 = grp2->gr_mem;
+
+ if ((grp1->gr_mem == NULL) || (grp2->gr_mem == NULL))
+ goto errfin;
+
+ for (;*c1 && *c2; ++c1, ++c2)
+ if (strcmp(*c1, *c2) != 0)
+ goto errfin;
+
+ if ((*c1 != '\0') || (*c2 != '\0'))
+ goto errfin;
+
+ return 0;
+
+errfin:
+ if ((debug) && (mdata == NULL)) {
+ printf("following structures are not equal:\n");
+ dump_group(grp1);
+ dump_group(grp2);
+ }
+
+ return (-1);
+}
+
+static void
+sdump_group(struct group *grp, char *buffer, size_t buflen)
+{
+ char **cp;
+ int written;
+
+ written = snprintf(buffer, buflen, "%s %s %d",
+ grp->gr_name, grp->gr_passwd, grp->gr_gid);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (grp->gr_mem != NULL) {
+ if (*(grp->gr_mem) != '\0') {
+ for (cp = grp->gr_mem; *cp; ++cp) {
+ written = snprintf(buffer, buflen, " %s",*cp);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (buflen == 0)
+ return;
+ }
+ } else
+ snprintf(buffer, buflen, " nomem");
+ } else
+ snprintf(buffer, buflen, " (null)");
+}
+
+static int
+group_read_snapshot_func(struct group *grp, char *line)
+{
+ StringList *sl;
+ char *s, *ps, *ts;
+ int i;
+
+ if (debug)
+ printf("1 line read from snapshot:\n%s\n", line);
+
+ i = 0;
+ sl = NULL;
+ ps = line;
+ memset(grp, 0, sizeof(struct group));
+ while ( (s = strsep(&ps, " ")) != NULL) {
+ switch (i) {
+ case 0:
+ grp->gr_name = strdup(s);
+ assert(grp->gr_name != NULL);
+ break;
+
+ case 1:
+ grp->gr_passwd = strdup(s);
+ assert(grp->gr_passwd != NULL);
+ break;
+
+ case 2:
+ grp->gr_gid = (gid_t)strtol(s, &ts, 10);
+ if (*ts != '\0') {
+ free(grp->gr_name);
+ free(grp->gr_passwd);
+ return (-1);
+ }
+ break;
+
+ default:
+ if (sl == NULL) {
+ if (strcmp(s, "(null)") == 0)
+ return (0);
+
+ sl = sl_init();
+ assert(sl != NULL);
+
+ if (strcmp(s, "nomem") != 0) {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl, ts);
+ }
+ } else {
+ ts = strdup(s);
+ assert(ts != NULL);
+ sl_add(sl, ts);
+ }
+ break;
+ };
+ ++i;
+ }
+
+ if (i < 3) {
+ free(grp->gr_name);
+ free(grp->gr_passwd);
+ memset(grp, 0, sizeof(struct group));
+ return (-1);
+ }
+
+ sl_add(sl, NULL);
+ grp->gr_mem = sl->sl_str;
+
+ /* NOTE: is it a dirty hack or not? */
+ free(sl);
+ return (0);
+}
+
+static void
+dump_group(struct group *result)
+{
+ if (result != NULL) {
+ char buffer[1024];
+ sdump_group(result, buffer, sizeof(buffer));
+ printf("%s\n", buffer);
+ } else
+ printf("(null)\n");
+}
+
+static int
+group_fill_test_data(struct group_test_data *td)
+{
+ struct group *grp;
+
+ setgroupent(1);
+ while ((grp = getgrent()) != NULL) {
+ if (group_test_correctness(grp, NULL) == 0)
+ TEST_DATA_APPEND(group, td, grp);
+ else
+ return (-1);
+ }
+ endgrent();
+
+ return (0);
+}
+
+static int
+group_test_correctness(struct group *grp, void *mdata)
+{
+ if (debug) {
+ printf("testing correctness with the following data:\n");
+ dump_group(grp);
+ }
+
+ if (grp == NULL)
+ goto errfin;
+
+ if (grp->gr_name == NULL)
+ goto errfin;
+
+ if (grp->gr_passwd == NULL)
+ goto errfin;
+
+ if (grp->gr_mem == NULL)
+ goto errfin;
+
+ if (debug)
+ printf("correct\n");
+
+ return (0);
+errfin:
+ if (debug)
+ printf("incorrect\n");
+
+ return (-1);
+}
+
+/* group_check_ambiguity() is needed here because when doing the getgrent()
+ * calls sequence, records from different nsswitch sources can be different,
+ * though having the same pw_name/pw_uid */
+static int
+group_check_ambiguity(struct group_test_data *td, struct group *pwd)
+{
+
+ return (TEST_DATA_FIND(group, td, pwd, compare_group,
+ NULL) != NULL ? 0 : -1);
+}
+
+static int
+group_test_getgrnam(struct group *grp_model, void *mdata)
+{
+ struct group *grp;
+
+ if (debug) {
+ printf("testing getgrnam() with the following data:\n");
+ dump_group(grp_model);
+ }
+
+ grp = getgrnam(grp_model->gr_name);
+ if (group_test_correctness(grp, NULL) != 0)
+ goto errfin;
+
+ if ((compare_group(grp, grp_model, NULL) != 0) &&
+ (group_check_ambiguity((struct group_test_data *)mdata, grp)
+ !=0))
+ goto errfin;
+
+ if (debug)
+ printf("ok\n");
+ return (0);
+
+errfin:
+ if (debug)
+ printf("not ok\n");
+
+ return (-1);
+}
+
+static int
+group_test_getgrgid(struct group *grp_model, void *mdata)
+{
+ struct group *grp;
+
+ if (debug) {
+ printf("testing getgrgid() with the following data...\n");
+ dump_group(grp_model);
+ }
+
+ grp = getgrgid(grp_model->gr_gid);
+ if ((group_test_correctness(grp, NULL) != 0) ||
+ ((compare_group(grp, grp_model, NULL) != 0) &&
+ (group_check_ambiguity((struct group_test_data *)mdata, grp)
+ != 0))) {
+ if (debug)
+ printf("not ok\n");
+ return (-1);
+ } else {
+ if (debug)
+ printf("ok\n");
+ return (0);
+ }
+}
+
+static int
+group_test_getgrent(struct group *grp, void *mdata)
+{
+ /* Only correctness can be checked when doing 1-pass test for
+ * getgrent(). */
+ return (group_test_correctness(grp, NULL));
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s [-dnge2] [-s <file>]\n",
+ getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct group_test_data td, td_snap, td_2pass;
+ char *snapshot_file;
+ int rv;
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ snapshot_file = NULL;
+ while ((c = getopt(argc, argv, "nge2ds:")) != -1)
+ switch (c) {
+ case 'd':
+ debug++;
+ break;
+ case 'n':
+ method = TEST_GETGRNAM;
+ break;
+ case 'g':
+ method = TEST_GETGRGID;
+ break;
+ case 'e':
+ method = TEST_GETGRENT;
+ break;
+ case '2':
+ method = TEST_GETGRENT_2PASS;
+ break;
+ case 's':
+ snapshot_file = strdup(optarg);
+ break;
+ default:
+ usage();
+ }
+
+ TEST_DATA_INIT(group, &td, clone_group, free_group);
+ TEST_DATA_INIT(group, &td_snap, clone_group, free_group);
+ if (snapshot_file != NULL) {
+ if (access(snapshot_file, W_OK | R_OK) != 0) {
+ if (errno == ENOENT)
+ method = TEST_BUILD_SNAPSHOT;
+ else {
+ if (debug)
+ printf("can't access the file %s\n",
+ snapshot_file);
+
+ rv = -1;
+ goto fin;
+ }
+ } else {
+ if (method == TEST_BUILD_SNAPSHOT) {
+ rv = 0;
+ goto fin;
+ }
+
+ TEST_SNAPSHOT_FILE_READ(group, snapshot_file,
+ &td_snap, group_read_snapshot_func);
+ }
+ }
+
+ rv = group_fill_test_data(&td);
+ if (rv == -1)
+ return (-1);
+ switch (method) {
+ case TEST_GETGRNAM:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(group, &td,
+ group_test_getgrnam, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(group, &td_snap,
+ group_test_getgrnam, (void *)&td_snap);
+ break;
+ case TEST_GETGRGID:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(group, &td,
+ group_test_getgrgid, (void *)&td);
+ else
+ rv = DO_1PASS_TEST(group, &td_snap,
+ group_test_getgrgid, (void *)&td_snap);
+ break;
+ case TEST_GETGRENT:
+ if (snapshot_file == NULL)
+ rv = DO_1PASS_TEST(group, &td, group_test_getgrent,
+ (void *)&td);
+ else
+ rv = DO_2PASS_TEST(group, &td, &td_snap,
+ compare_group, NULL);
+ break;
+ case TEST_GETGRENT_2PASS:
+ TEST_DATA_INIT(group, &td_2pass, clone_group, free_group);
+ rv = group_fill_test_data(&td_2pass);
+ if (rv != -1)
+ rv = DO_2PASS_TEST(group, &td, &td_2pass,
+ compare_group, NULL);
+ TEST_DATA_DESTROY(group, &td_2pass);
+ break;
+ case TEST_BUILD_SNAPSHOT:
+ if (snapshot_file != NULL)
+ rv = TEST_SNAPSHOT_FILE_WRITE(group, snapshot_file, &td,
+ sdump_group);
+ break;
+ default:
+ rv = 0;
+ break;
+ };
+
+fin:
+ TEST_DATA_DESTROY(group, &td_snap);
+ TEST_DATA_DESTROY(group, &td);
+ free(snapshot_file);
+ return (rv);
+}
==== //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getpw.c#3 (text+ko) ====
@@ -1,0 +1,489 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman at freebsd.org>
+ * All rights repwded.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "testutil.h"
+
+enum test_methods {
+ TEST_GETPWENT,
+ TEST_GETPWNAM,
+ TEST_GETPWUID,
+ TEST_GETPWENT_2PASS,
+ TEST_BUILD_SNAPSHOT
+};
+
+static int debug = 0;
+static enum test_methods method = TEST_BUILD_SNAPSHOT;
+
+DECLARE_TEST_DATA(passwd)
+DECLARE_TEST_FILE_SNAPSHOT(passwd)
+DECLARE_1PASS_TEST(passwd)
+DECLARE_2PASS_TEST(passwd)
+
+static void clone_passwd(struct passwd *, struct passwd const *);
+static int compare_passwd(struct passwd *, struct passwd *, void *);
+static void free_passwd(struct passwd *);
+
+static void sdump_passwd(struct passwd *, char *, size_t);
+static void dump_passwd(struct passwd *);
+
+static int passwd_read_snapshot_func(struct passwd *, char *);
+
+static int passwd_check_ambiguity(struct passwd_test_data *, struct passwd *);
+static int passwd_fill_test_data(struct passwd_test_data *);
+static int passwd_test_correctness(struct passwd *, void *);
+static int passwd_test_getpwnam(struct passwd *, void *);
+static int passwd_test_getpwuid(struct passwd *, void *);
+static int passwd_test_getpwent(struct passwd *, void *);
+
+static void usage(void) __attribute__((__noreturn__));
+
+IMPLEMENT_TEST_DATA(passwd)
+IMPLEMENT_TEST_FILE_SNAPSHOT(passwd)
+IMPLEMENT_1PASS_TEST(passwd)
+IMPLEMENT_2PASS_TEST(passwd)
+
+static void
+clone_passwd(struct passwd *dest, struct passwd const *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ memcpy(dest, src, sizeof(struct passwd));
+ if (src->pw_name != NULL)
+ dest->pw_name = strdup(src->pw_name);
+ if (src->pw_passwd != NULL)
+ dest->pw_passwd = strdup(src->pw_passwd);
+ if (src->pw_class != NULL)
+ dest->pw_class = strdup(src->pw_class);
+ if (src->pw_gecos != NULL)
+ dest->pw_gecos = strdup(src->pw_gecos);
+ if (src->pw_dir != NULL)
+ dest->pw_dir = strdup(src->pw_dir);
+ if (src->pw_shell != NULL)
+ dest->pw_shell = strdup(dest->pw_shell);
+}
+
+static int
+compare_passwd(struct passwd *pwd1, struct passwd *pwd2, void *mdata)
+{
+ assert(pwd1 != NULL);
+ assert(pwd2 != NULL);
+
+ if (pwd1 == pwd2)
+ return (0);
+
+ if ((pwd1->pw_uid != pwd2->pw_uid) ||
+ (pwd1->pw_gid != pwd2->pw_gid) ||
+ (pwd1->pw_change != pwd2->pw_change) ||
+ (pwd1->pw_expire != pwd2->pw_expire) ||
+ (pwd1->pw_fields != pwd2->pw_fields) ||
+ (strcmp(pwd1->pw_name, pwd2->pw_name) != 0) ||
+ (strcmp(pwd1->pw_passwd, pwd2->pw_passwd) != 0) ||
+ (strcmp(pwd1->pw_class, pwd2->pw_class) != 0) ||
+ (strcmp(pwd1->pw_gecos, pwd2->pw_gecos) != 0) ||
+ (strcmp(pwd1->pw_dir, pwd2->pw_dir) != 0) ||
+ (strcmp(pwd1->pw_shell, pwd2->pw_shell) != 0)
+ )
+ return (-1);
+ else
+ return (0);
+}
+
+static void
+free_passwd(struct passwd *pwd)
+{
+ free(pwd->pw_name);
+ free(pwd->pw_passwd);
+ free(pwd->pw_class);
+ free(pwd->pw_gecos);
+ free(pwd->pw_dir);
+ free(pwd->pw_shell);
+}
+
+static void
+sdump_passwd(struct passwd *pwd, char *buffer, size_t buflen)
+{
+ snprintf(buffer, buflen, "%s:%s:%d:%d:%d:%s:%s:%s:%s:%d:%d",
+ pwd->pw_name, pwd->pw_passwd, pwd->pw_uid, pwd->pw_gid,
+ pwd->pw_change, pwd->pw_class, pwd->pw_gecos, pwd->pw_dir,
+ pwd->pw_shell, pwd->pw_expire, pwd->pw_fields);
+}
+
+static void
+dump_passwd(struct passwd *pwd)
+{
+ if (pwd != NULL) {
+ char buffer[2048];
+ sdump_passwd(pwd, buffer, sizeof(buffer));
+ printf("%s\n", buffer);
+ } else
+ printf("(null)\n");
+}
+
+static int
+passwd_read_snapshot_func(struct passwd *pwd, char *line)
+{
+ char *s, *ps, *ts;
+ int i;
+
+ if (debug)
+ printf("1 line read from snapshot:\n%s\n", line);
+
+ i = 0;
+ ps = line;
+ memset(pwd, 0, sizeof(struct passwd));
+ while ( (s = strsep(&ps, ":")) != NULL) {
+ switch (i) {
+ case 0:
+ pwd->pw_name = strdup(s);
+ assert(pwd->pw_name != NULL);
+ break;
+ case 1:
+ pwd->pw_passwd = strdup(s);
+ assert(pwd->pw_passwd != NULL);
+ break;
+ case 2:
+ pwd->pw_uid = (uid_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ case 3:
+ pwd->pw_gid = (gid_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ case 4:
+ pwd->pw_change = (time_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ case 5:
+ pwd->pw_class = strdup(s);
+ assert(pwd->pw_class != NULL);
+ break;
+ case 6:
+ pwd->pw_gecos = strdup(s);
+ assert(pwd->pw_gecos != NULL);
+ break;
+ case 7:
+ pwd->pw_dir = strdup(s);
+ assert(pwd->pw_dir != NULL);
+ break;
+ case 8:
+ pwd->pw_shell = strdup(s);
+ assert(pwd->pw_shell != NULL);
+ break;
+ case 9:
+ pwd->pw_expire = (time_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ case 10:
+ pwd->pw_fields = (int)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ default:
+ break;
+ };
+ ++i;
+ }
+
+fin:
+ if (i != 11) {
+ free_passwd(pwd);
+ memset(pwd, 0, sizeof(struct passwd));
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+passwd_fill_test_data(struct passwd_test_data *td)
+{
+ struct passwd *pwd;
+
+ setpassent(1);
+ while ((pwd = getpwent()) != NULL) {
+ if (passwd_test_correctness(pwd, NULL) == 0)
+ TEST_DATA_APPEND(passwd, td, pwd);
+ else
+ return (-1);
+ }
+ endpwent();
+
+ return (0);
+}
+
+static int
+passwd_test_correctness(struct passwd *pwd, void *mdata)
+{
+ if (debug) {
+ printf("testing correctness with the following data:\n");
+ dump_passwd(pwd);
+ }
+
+ if (pwd == NULL)
+ return (-1);
+
+ if (pwd->pw_name == NULL)
+ goto errfin;
+
+ if (pwd->pw_passwd == NULL)
+ goto errfin;
+
+ if (pwd->pw_class == NULL)
+ goto errfin;
+
+ if (pwd->pw_gecos == NULL)
+ goto errfin;
+
+ if (pwd->pw_dir == NULL)
+ goto errfin;
+
+ if (pwd->pw_shell == NULL)
+ goto errfin;
+
+ if (debug)
+ printf("correct\n");
+
+ return (0);
+errfin:
+ if (debug)
+ printf("incorrect\n");
+
+ return (-1);
+}
+
+/* passwd_check_ambiguity() is needed here because when doing the getpwent()
+ * calls sequence, records from different nsswitch sources can be different,
+ * though having the same pw_name/pw_uid */
+static int
+passwd_check_ambiguity(struct passwd_test_data *td, struct passwd *pwd)
+{
+
+ return (TEST_DATA_FIND(passwd, td, pwd, compare_passwd,
+ NULL) != NULL ? 0 : -1);
+}
+
+static int
+passwd_test_getpwnam(struct passwd *pwd_model, void *mdata)
+{
+ struct passwd *pwd;
+
+ if (debug) {
+ printf("testing getpwnam() with the following data:\n");
+ dump_passwd(pwd_model);
+ }
+
+ pwd = getpwnam(pwd_model->pw_name);
+ if (passwd_test_correctness(pwd, NULL) != 0)
+ goto errfin;
+
+ if ((compare_passwd(pwd, pwd_model, NULL) != 0) &&
+ (passwd_check_ambiguity((struct passwd_test_data *)mdata, pwd)
+ !=0))
+ goto errfin;
+
+ if (debug)
+ printf("ok\n");
+ return (0);
+
+errfin:
+ if (debug)
+ printf("not ok\n");
+
+ return (-1);
+}
+
+static int
+passwd_test_getpwuid(struct passwd *pwd_model, void *mdata)
+{
+ struct passwd *pwd;
+
+ if (debug) {
+ printf("testing getpwuid() with the following data...\n");
+ dump_passwd(pwd_model);
+ }
+
+ pwd = getpwuid(pwd_model->pw_uid);
+ if ((passwd_test_correctness(pwd, NULL) != 0) ||
+ ((compare_passwd(pwd, pwd_model, NULL) != 0) &&
+ (passwd_check_ambiguity((struct passwd_test_data *)mdata, pwd)
+ != 0))) {
+ if (debug)
+ printf("not ok\n");
+ return (-1);
+ } else {
+ if (debug)
+ printf("ok\n");
+ return (0);
+ }
+}
+
+static int
+passwd_test_getpwent(struct passwd *pwd, void *mdata)
+{
+ /* Only correctness can be checked when doing 1-pass test for
+ * getpwent(). */
+ return (passwd_test_correctness(pwd, NULL));
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s [-dnue2] [-s <file>]\n",
+ getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct passwd_test_data td, td_snap, td_2pass;
+ char *snapshot_file;
+ int rv;
+ int c;
+
+ if (argc < 2)
+ usage();
+
+ snapshot_file = NULL;
+ while ((c = getopt(argc, argv, "nue2ds:")) != -1)
+ switch (c) {
+ case 'd':
+ debug++;
+ break;
+ case 'n':
+ method = TEST_GETPWNAM;
+ break;
+ case 'u':
+ method = TEST_GETPWUID;
+ break;
+ case 'e':
+ method = TEST_GETPWENT;
+ break;
+ case '2':
+ method = TEST_GETPWENT_2PASS;
+ break;
+ case 's':
+ snapshot_file = strdup(optarg);
+ break;
+ default:
+ usage();
+ }
+
+ TEST_DATA_INIT(passwd, &td, clone_passwd, free_passwd);
+ TEST_DATA_INIT(passwd, &td_snap, clone_passwd, free_passwd);
+ if (snapshot_file != NULL) {
+ if (access(snapshot_file, W_OK | R_OK) != 0) {
+ if (errno == ENOENT)
+ method = TEST_BUILD_SNAPSHOT;
+ else {
+ if (debug)
+ printf("can't access the file %s\n",
+ snapshot_file);
+
+ rv = -1;
+ goto fin;
+ }
+ } else {
+ if (method == TEST_BUILD_SNAPSHOT) {
+ rv = 0;
+ goto fin;
+ }
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list