xref: /freebsd-src/lib/libc/tests/nss/getgr_test.c (revision d11904b350214943dedb64c7121d4602799d7afd)
108ca345cSEnji Cooper /*-
208ca345cSEnji Cooper  * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
308ca345cSEnji Cooper  * All rights reserved.
408ca345cSEnji Cooper  *
508ca345cSEnji Cooper  * Redistribution and use in source and binary forms, with or without
608ca345cSEnji Cooper  * modification, are permitted provided that the following conditions
708ca345cSEnji Cooper  * are met:
808ca345cSEnji Cooper  * 1. Redistributions of source code must retain the above copyright
908ca345cSEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1008ca345cSEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1108ca345cSEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1208ca345cSEnji Cooper  *    documentation and/or other materials provided with the distribution.
1308ca345cSEnji Cooper  *
1408ca345cSEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1508ca345cSEnji Cooper  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1608ca345cSEnji Cooper  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1708ca345cSEnji Cooper  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1808ca345cSEnji Cooper  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1908ca345cSEnji Cooper  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2008ca345cSEnji Cooper  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2108ca345cSEnji Cooper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2208ca345cSEnji Cooper  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2308ca345cSEnji Cooper  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2408ca345cSEnji Cooper  * SUCH DAMAGE.
2508ca345cSEnji Cooper  *
2608ca345cSEnji Cooper  */
2708ca345cSEnji Cooper 
2808ca345cSEnji Cooper #include <arpa/inet.h>
2908ca345cSEnji Cooper #include <errno.h>
3008ca345cSEnji Cooper #include <grp.h>
3108ca345cSEnji Cooper #include <stdio.h>
3208ca345cSEnji Cooper #include <stdlib.h>
3308ca345cSEnji Cooper #include <string.h>
3408ca345cSEnji Cooper #include <stringlist.h>
3508ca345cSEnji Cooper #include <unistd.h>
3608ca345cSEnji Cooper 
3708ca345cSEnji Cooper #include <atf-c.h>
3808ca345cSEnji Cooper 
3908ca345cSEnji Cooper #include "testutil.h"
4008ca345cSEnji Cooper 
4108ca345cSEnji Cooper enum test_methods {
426e411d8bSMark Johnston 	TEST_GETGRENT,
436e411d8bSMark Johnston 	TEST_GETGRNAM,
446e411d8bSMark Johnston 	TEST_GETGRGID,
456e411d8bSMark Johnston 	TEST_GETGRENT_2PASS,
466e411d8bSMark Johnston 	TEST_GETGRENT_INTERLEAVED_GETGRNAM,
476e411d8bSMark Johnston 	TEST_GETGRENT_INTERLEAVED_GETGRGID,
486e411d8bSMark Johnston 	TEST_BUILD_SNAPSHOT,
4908ca345cSEnji Cooper };
5008ca345cSEnji Cooper 
5108ca345cSEnji Cooper DECLARE_TEST_DATA(group)
5208ca345cSEnji Cooper DECLARE_TEST_FILE_SNAPSHOT(group)
5308ca345cSEnji Cooper DECLARE_1PASS_TEST(group)
5408ca345cSEnji Cooper DECLARE_2PASS_TEST(group)
5508ca345cSEnji Cooper 
5608ca345cSEnji Cooper static void clone_group(struct group *, struct group const *);
5708ca345cSEnji Cooper static int compare_group(struct group *, struct group *, void *);
5808ca345cSEnji Cooper static void dump_group(struct group *);
5908ca345cSEnji Cooper static void free_group(struct group *);
6008ca345cSEnji Cooper 
6108ca345cSEnji Cooper static void sdump_group(struct group *, char *, size_t);
6208ca345cSEnji Cooper static int group_read_snapshot_func(struct group *, char *);
6308ca345cSEnji Cooper 
64ed14c69dSMark Johnston static int group_check_ambiguity(struct group_test_data *, struct group *);
656e411d8bSMark Johnston static int group_fill_test_data(struct group_test_data *,
666e411d8bSMark Johnston     int (*cb)(struct group *, void *));
6708ca345cSEnji Cooper static int group_test_correctness(struct group *, void *);
6808ca345cSEnji Cooper static int group_test_getgrnam(struct group *, void *);
6908ca345cSEnji Cooper static int group_test_getgrgid(struct group *, void *);
7008ca345cSEnji Cooper static int group_test_getgrent(struct group *, void *);
7108ca345cSEnji Cooper 
7208ca345cSEnji Cooper IMPLEMENT_TEST_DATA(group)
7308ca345cSEnji Cooper IMPLEMENT_TEST_FILE_SNAPSHOT(group)
7408ca345cSEnji Cooper IMPLEMENT_1PASS_TEST(group)
7508ca345cSEnji Cooper IMPLEMENT_2PASS_TEST(group)
7608ca345cSEnji Cooper 
7708ca345cSEnji Cooper static void
7808ca345cSEnji Cooper clone_group(struct group *dest, struct group const *src)
7908ca345cSEnji Cooper {
8008ca345cSEnji Cooper 	ATF_REQUIRE(dest != NULL);
8108ca345cSEnji Cooper 	ATF_REQUIRE(src != NULL);
8208ca345cSEnji Cooper 
8308ca345cSEnji Cooper 	char **cp;
8408ca345cSEnji Cooper 	int members_num;
8508ca345cSEnji Cooper 
8608ca345cSEnji Cooper 	memset(dest, 0, sizeof(struct group));
8708ca345cSEnji Cooper 
8808ca345cSEnji Cooper 	if (src->gr_name != NULL) {
8908ca345cSEnji Cooper 		dest->gr_name = strdup(src->gr_name);
9008ca345cSEnji Cooper 		ATF_REQUIRE(dest->gr_name != NULL);
9108ca345cSEnji Cooper 	}
9208ca345cSEnji Cooper 
9308ca345cSEnji Cooper 	if (src->gr_passwd != NULL) {
9408ca345cSEnji Cooper 		dest->gr_passwd = strdup(src->gr_passwd);
9508ca345cSEnji Cooper 		ATF_REQUIRE(dest->gr_passwd != NULL);
9608ca345cSEnji Cooper 	}
9708ca345cSEnji Cooper 	dest->gr_gid = src->gr_gid;
9808ca345cSEnji Cooper 
9908ca345cSEnji Cooper 	if (src->gr_mem != NULL) {
10008ca345cSEnji Cooper 		members_num = 0;
10108ca345cSEnji Cooper 		for (cp = src->gr_mem; *cp; ++cp)
10208ca345cSEnji Cooper 			++members_num;
10308ca345cSEnji Cooper 
1043bdd6cf0SEnji Cooper 		dest->gr_mem = calloc(members_num + 1, sizeof(char *));
10508ca345cSEnji Cooper 		ATF_REQUIRE(dest->gr_mem != NULL);
10608ca345cSEnji Cooper 
10708ca345cSEnji Cooper 		for (cp = src->gr_mem; *cp; ++cp) {
10808ca345cSEnji Cooper 			dest->gr_mem[cp - src->gr_mem] = strdup(*cp);
10908ca345cSEnji Cooper 			ATF_REQUIRE(dest->gr_mem[cp - src->gr_mem] != NULL);
11008ca345cSEnji Cooper 		}
11108ca345cSEnji Cooper 	}
11208ca345cSEnji Cooper }
11308ca345cSEnji Cooper 
11408ca345cSEnji Cooper static void
11508ca345cSEnji Cooper free_group(struct group *grp)
11608ca345cSEnji Cooper {
11708ca345cSEnji Cooper 	char **cp;
11808ca345cSEnji Cooper 
11908ca345cSEnji Cooper 	ATF_REQUIRE(grp != NULL);
12008ca345cSEnji Cooper 
12108ca345cSEnji Cooper 	free(grp->gr_name);
12208ca345cSEnji Cooper 	free(grp->gr_passwd);
12308ca345cSEnji Cooper 
12408ca345cSEnji Cooper 	for (cp = grp->gr_mem; *cp; ++cp)
12508ca345cSEnji Cooper 		free(*cp);
12608ca345cSEnji Cooper 	free(grp->gr_mem);
12708ca345cSEnji Cooper }
12808ca345cSEnji Cooper 
12908ca345cSEnji Cooper static  int
13008ca345cSEnji Cooper compare_group(struct group *grp1, struct group *grp2, void *mdata)
13108ca345cSEnji Cooper {
13208ca345cSEnji Cooper 	char **c1, **c2;
13308ca345cSEnji Cooper 
13408ca345cSEnji Cooper 	if (grp1 == grp2)
13508ca345cSEnji Cooper 		return (0);
13608ca345cSEnji Cooper 
13708ca345cSEnji Cooper 	if (grp1 == NULL || grp2 == NULL)
13808ca345cSEnji Cooper 		goto errfin;
13908ca345cSEnji Cooper 
14008ca345cSEnji Cooper 	if (strcmp(grp1->gr_name, grp2->gr_name) != 0 ||
14108ca345cSEnji Cooper 	    strcmp(grp1->gr_passwd, grp2->gr_passwd) != 0 ||
14208ca345cSEnji Cooper 	    grp1->gr_gid != grp2->gr_gid)
14308ca345cSEnji Cooper 			goto errfin;
14408ca345cSEnji Cooper 
14508ca345cSEnji Cooper 	c1 = grp1->gr_mem;
14608ca345cSEnji Cooper 	c2 = grp2->gr_mem;
14708ca345cSEnji Cooper 
14808ca345cSEnji Cooper 	if (grp1->gr_mem == NULL || grp2->gr_mem == NULL)
14908ca345cSEnji Cooper 		goto errfin;
15008ca345cSEnji Cooper 
15108ca345cSEnji Cooper 	for (; *c1 && *c2; ++c1, ++c2)
15208ca345cSEnji Cooper 		if (strcmp(*c1, *c2) != 0)
15308ca345cSEnji Cooper 			goto errfin;
15408ca345cSEnji Cooper 
155f1897613SBrooks Davis 	if (*c1 != NULL || *c2 != NULL)
15608ca345cSEnji Cooper 		goto errfin;
15708ca345cSEnji Cooper 
15808ca345cSEnji Cooper 	return 0;
15908ca345cSEnji Cooper 
16008ca345cSEnji Cooper errfin:
16108ca345cSEnji Cooper 	if (mdata == NULL) {
16208ca345cSEnji Cooper 		printf("following structures are not equal:\n");
16308ca345cSEnji Cooper 		dump_group(grp1);
16408ca345cSEnji Cooper 		dump_group(grp2);
16508ca345cSEnji Cooper 	}
16608ca345cSEnji Cooper 
16708ca345cSEnji Cooper 	return (-1);
16808ca345cSEnji Cooper }
16908ca345cSEnji Cooper 
17008ca345cSEnji Cooper static void
17108ca345cSEnji Cooper sdump_group(struct group *grp, char *buffer, size_t buflen)
17208ca345cSEnji Cooper {
17308ca345cSEnji Cooper 	char **cp;
17408ca345cSEnji Cooper 	int written;
17508ca345cSEnji Cooper 
1762d22bf63SBryan Drewery 	written = snprintf(buffer, buflen, "%s:%s:%d:",
17708ca345cSEnji Cooper 	    grp->gr_name, grp->gr_passwd, grp->gr_gid);
17808ca345cSEnji Cooper 	buffer += written;
1794a9a8952SEnji Cooper 	if (written > (int)buflen)
18008ca345cSEnji Cooper 		return;
18108ca345cSEnji Cooper 	buflen -= written;
18208ca345cSEnji Cooper 
18308ca345cSEnji Cooper 	if (grp->gr_mem != NULL) {
184f1897613SBrooks Davis 		if (*(grp->gr_mem) != NULL) {
18508ca345cSEnji Cooper 			for (cp = grp->gr_mem; *cp; ++cp) {
1862d22bf63SBryan Drewery 				written = snprintf(buffer, buflen, "%s%s",
1872d22bf63SBryan Drewery 				    cp == grp->gr_mem ? "" : ",", *cp);
18808ca345cSEnji Cooper 				buffer += written;
1894a9a8952SEnji Cooper 				if (written > (int)buflen)
19008ca345cSEnji Cooper 					return;
19108ca345cSEnji Cooper 				buflen -= written;
19208ca345cSEnji Cooper 
19308ca345cSEnji Cooper 				if (buflen == 0)
19408ca345cSEnji Cooper 					return;
19508ca345cSEnji Cooper 			}
19608ca345cSEnji Cooper 		} else
19708ca345cSEnji Cooper 			snprintf(buffer, buflen, "nomem");
19808ca345cSEnji Cooper 	} else
19908ca345cSEnji Cooper 		snprintf(buffer, buflen, "(null)");
20008ca345cSEnji Cooper }
20108ca345cSEnji Cooper 
20208ca345cSEnji Cooper static int
20308ca345cSEnji Cooper group_read_snapshot_func(struct group *grp, char *line)
20408ca345cSEnji Cooper {
20508ca345cSEnji Cooper 	StringList *sl;
20608ca345cSEnji Cooper 	char *s, *ps, *ts;
2072d22bf63SBryan Drewery 	const char *sep;
20808ca345cSEnji Cooper 	int i;
20908ca345cSEnji Cooper 
21008ca345cSEnji Cooper 	printf("1 line read from snapshot:\n%s\n", line);
21108ca345cSEnji Cooper 
21208ca345cSEnji Cooper 	i = 0;
21308ca345cSEnji Cooper 	sl = NULL;
21408ca345cSEnji Cooper 	ps = line;
2152d22bf63SBryan Drewery 	sep = ":";
21608ca345cSEnji Cooper 	memset(grp, 0, sizeof(struct group));
2172d22bf63SBryan Drewery 	while ((s = strsep(&ps, sep)) != NULL) {
21808ca345cSEnji Cooper 		switch (i) {
21908ca345cSEnji Cooper 		case 0:
22008ca345cSEnji Cooper 			grp->gr_name = strdup(s);
22108ca345cSEnji Cooper 			ATF_REQUIRE(grp->gr_name != NULL);
22208ca345cSEnji Cooper 			break;
22308ca345cSEnji Cooper 
22408ca345cSEnji Cooper 		case 1:
22508ca345cSEnji Cooper 			grp->gr_passwd = strdup(s);
22608ca345cSEnji Cooper 			ATF_REQUIRE(grp->gr_passwd != NULL);
22708ca345cSEnji Cooper 			break;
22808ca345cSEnji Cooper 
22908ca345cSEnji Cooper 		case 2:
23008ca345cSEnji Cooper 			grp->gr_gid = (gid_t)strtol(s, &ts, 10);
23108ca345cSEnji Cooper 			if (*ts != '\0') {
23208ca345cSEnji Cooper 				free(grp->gr_name);
23308ca345cSEnji Cooper 				free(grp->gr_passwd);
23408ca345cSEnji Cooper 				grp->gr_name = NULL;
23508ca345cSEnji Cooper 				grp->gr_passwd = NULL;
23608ca345cSEnji Cooper 				return (-1);
23708ca345cSEnji Cooper 			}
2382d22bf63SBryan Drewery 			/* Change to parsing groups. */
2392d22bf63SBryan Drewery 			sep = ",";
24008ca345cSEnji Cooper 			break;
24108ca345cSEnji Cooper 
24208ca345cSEnji Cooper 		default:
24308ca345cSEnji Cooper 			if (sl == NULL) {
24408ca345cSEnji Cooper 				if (strcmp(s, "(null)") == 0)
24508ca345cSEnji Cooper 					return (0);
24608ca345cSEnji Cooper 
24708ca345cSEnji Cooper 				sl = sl_init();
24808ca345cSEnji Cooper 				ATF_REQUIRE(sl != NULL);
24908ca345cSEnji Cooper 
25008ca345cSEnji Cooper 				if (strcmp(s, "nomem") != 0) {
25108ca345cSEnji Cooper 					ts = strdup(s);
25208ca345cSEnji Cooper 					ATF_REQUIRE(ts != NULL);
25308ca345cSEnji Cooper 					sl_add(sl, ts);
25408ca345cSEnji Cooper 				}
25508ca345cSEnji Cooper 			} else {
25608ca345cSEnji Cooper 				ts = strdup(s);
25708ca345cSEnji Cooper 				ATF_REQUIRE(ts != NULL);
25808ca345cSEnji Cooper 				sl_add(sl, ts);
25908ca345cSEnji Cooper 			}
26008ca345cSEnji Cooper 			break;
26108ca345cSEnji Cooper 		}
26208ca345cSEnji Cooper 		++i;
26308ca345cSEnji Cooper 	}
26408ca345cSEnji Cooper 
26508ca345cSEnji Cooper 	if (i < 3) {
26608ca345cSEnji Cooper 		free(grp->gr_name);
26708ca345cSEnji Cooper 		free(grp->gr_passwd);
26808ca345cSEnji Cooper 		memset(grp, 0, sizeof(struct group));
26908ca345cSEnji Cooper 		return (-1);
27008ca345cSEnji Cooper 	}
27108ca345cSEnji Cooper 
27208ca345cSEnji Cooper 	sl_add(sl, NULL);
27308ca345cSEnji Cooper 	grp->gr_mem = sl->sl_str;
27408ca345cSEnji Cooper 
27508ca345cSEnji Cooper 	/* NOTE: is it a dirty hack or not? */
27608ca345cSEnji Cooper 	free(sl);
27708ca345cSEnji Cooper 	return (0);
27808ca345cSEnji Cooper }
27908ca345cSEnji Cooper 
28008ca345cSEnji Cooper static void
28108ca345cSEnji Cooper dump_group(struct group *result)
28208ca345cSEnji Cooper {
28308ca345cSEnji Cooper 	if (result != NULL) {
28408ca345cSEnji Cooper 		char buffer[1024];
28508ca345cSEnji Cooper 		sdump_group(result, buffer, sizeof(buffer));
28608ca345cSEnji Cooper 		printf("%s\n", buffer);
28708ca345cSEnji Cooper 	} else
28808ca345cSEnji Cooper 		printf("(null)\n");
28908ca345cSEnji Cooper }
29008ca345cSEnji Cooper 
29108ca345cSEnji Cooper static int
2926e411d8bSMark Johnston group_fill_test_data(struct group_test_data *td,
2936e411d8bSMark Johnston     int (*cb)(struct group *, void *))
29408ca345cSEnji Cooper {
29508ca345cSEnji Cooper 	struct group *grp;
296*d11904b3SAlan Somers 	const int limit = 1024;
297*d11904b3SAlan Somers 	int count = 0;
29808ca345cSEnji Cooper 
29908ca345cSEnji Cooper 	setgroupent(1);
30008ca345cSEnji Cooper 	while ((grp = getgrent()) != NULL) {
3016e411d8bSMark Johnston 		if (group_test_correctness(grp, NULL) == 0) {
30208ca345cSEnji Cooper 			TEST_DATA_APPEND(group, td, grp);
3036e411d8bSMark Johnston 			if (cb != NULL && cb(grp, td) != 0)
30408ca345cSEnji Cooper 				return (-1);
3056e411d8bSMark Johnston 		} else {
3066e411d8bSMark Johnston 			return (-1);
3076e411d8bSMark Johnston 		}
308*d11904b3SAlan Somers 		if (++count >= limit)
309*d11904b3SAlan Somers 			break;
31008ca345cSEnji Cooper 	}
31108ca345cSEnji Cooper 	endgrent();
31208ca345cSEnji Cooper 
31308ca345cSEnji Cooper 	return (0);
31408ca345cSEnji Cooper }
31508ca345cSEnji Cooper 
31608ca345cSEnji Cooper static int
31791c53523SEnji Cooper group_test_correctness(struct group *grp, void *mdata __unused)
31808ca345cSEnji Cooper {
31908ca345cSEnji Cooper 	printf("testing correctness with the following data:\n");
32008ca345cSEnji Cooper 	dump_group(grp);
32108ca345cSEnji Cooper 
32208ca345cSEnji Cooper 	if (grp == NULL)
32308ca345cSEnji Cooper 		goto errfin;
32408ca345cSEnji Cooper 
32508ca345cSEnji Cooper 	if (grp->gr_name == NULL)
32608ca345cSEnji Cooper 		goto errfin;
32708ca345cSEnji Cooper 
32808ca345cSEnji Cooper 	if (grp->gr_passwd == NULL)
32908ca345cSEnji Cooper 		goto errfin;
33008ca345cSEnji Cooper 
33108ca345cSEnji Cooper 	if (grp->gr_mem == NULL)
33208ca345cSEnji Cooper 		goto errfin;
33308ca345cSEnji Cooper 
33408ca345cSEnji Cooper 	printf("correct\n");
33508ca345cSEnji Cooper 
33608ca345cSEnji Cooper 	return (0);
33708ca345cSEnji Cooper errfin:
33808ca345cSEnji Cooper 	printf("incorrect\n");
33908ca345cSEnji Cooper 
34008ca345cSEnji Cooper 	return (-1);
34108ca345cSEnji Cooper }
34208ca345cSEnji Cooper 
34308ca345cSEnji Cooper /* group_check_ambiguity() is needed here because when doing the getgrent()
34408ca345cSEnji Cooper  * calls sequence, records from different nsswitch sources can be different,
34508ca345cSEnji Cooper  * though having the same pw_name/pw_uid */
34608ca345cSEnji Cooper static int
34708ca345cSEnji Cooper group_check_ambiguity(struct group_test_data *td, struct group *pwd)
34808ca345cSEnji Cooper {
34908ca345cSEnji Cooper 
350ed14c69dSMark Johnston 	return (TEST_DATA_FIND(group, td, pwd, compare_group, NULL) !=
351ed14c69dSMark Johnston 	    NULL ? 0 : -1);
35208ca345cSEnji Cooper }
35308ca345cSEnji Cooper 
35408ca345cSEnji Cooper static int
35508ca345cSEnji Cooper group_test_getgrnam(struct group *grp_model, void *mdata)
35608ca345cSEnji Cooper {
35708ca345cSEnji Cooper 	struct group *grp;
35808ca345cSEnji Cooper 
35908ca345cSEnji Cooper 	printf("testing getgrnam() with the following data:\n");
36008ca345cSEnji Cooper 	dump_group(grp_model);
36108ca345cSEnji Cooper 
36208ca345cSEnji Cooper 	grp = getgrnam(grp_model->gr_name);
36308ca345cSEnji Cooper 	if (group_test_correctness(grp, NULL) != 0)
36408ca345cSEnji Cooper 		goto errfin;
36508ca345cSEnji Cooper 
36608ca345cSEnji Cooper 	if (compare_group(grp, grp_model, NULL) != 0 &&
36708ca345cSEnji Cooper 	    group_check_ambiguity((struct group_test_data *)mdata, grp) != 0)
36808ca345cSEnji Cooper 	    goto errfin;
36908ca345cSEnji Cooper 
37008ca345cSEnji Cooper 	return (0);
37108ca345cSEnji Cooper 
37208ca345cSEnji Cooper errfin:
37308ca345cSEnji Cooper 	return (-1);
37408ca345cSEnji Cooper }
37508ca345cSEnji Cooper 
37608ca345cSEnji Cooper static int
37708ca345cSEnji Cooper group_test_getgrgid(struct group *grp_model, void *mdata)
37808ca345cSEnji Cooper {
37908ca345cSEnji Cooper 	struct group *grp;
38008ca345cSEnji Cooper 
38108ca345cSEnji Cooper 	printf("testing getgrgid() with the following data...\n");
38208ca345cSEnji Cooper 	dump_group(grp_model);
38308ca345cSEnji Cooper 
38408ca345cSEnji Cooper 	grp = getgrgid(grp_model->gr_gid);
38508ca345cSEnji Cooper 	if (group_test_correctness(grp, NULL) != 0 ||
38608ca345cSEnji Cooper 	    (compare_group(grp, grp_model, NULL) != 0 &&
387ed14c69dSMark Johnston 	     group_check_ambiguity((struct group_test_data *)mdata, grp) != 0))
38808ca345cSEnji Cooper 		return (-1);
389ed14c69dSMark Johnston 	else
39008ca345cSEnji Cooper 		return (0);
39108ca345cSEnji Cooper }
39208ca345cSEnji Cooper 
39308ca345cSEnji Cooper static int
39491c53523SEnji Cooper group_test_getgrent(struct group *grp, void *mdata __unused)
39508ca345cSEnji Cooper {
396ed14c69dSMark Johnston 	/*
397ed14c69dSMark Johnston 	 * Only correctness can be checked when doing 1-pass test for
398ed14c69dSMark Johnston 	 * getgrent().
399ed14c69dSMark Johnston 	 */
40008ca345cSEnji Cooper 	return (group_test_correctness(grp, NULL));
40108ca345cSEnji Cooper }
40208ca345cSEnji Cooper 
40308ca345cSEnji Cooper static int
40408ca345cSEnji Cooper run_tests(const char *snapshot_file, enum test_methods method)
40508ca345cSEnji Cooper {
4066e411d8bSMark Johnston 	struct group_test_data td, td_snap, td_2pass, td_interleaved;
40708ca345cSEnji Cooper 	int rv;
40808ca345cSEnji Cooper 
40908ca345cSEnji Cooper 	TEST_DATA_INIT(group, &td, clone_group, free_group);
41008ca345cSEnji Cooper 	TEST_DATA_INIT(group, &td_snap, clone_group, free_group);
41108ca345cSEnji Cooper 	if (snapshot_file != NULL) {
41208ca345cSEnji Cooper 		if (access(snapshot_file, W_OK | R_OK) != 0) {
41308ca345cSEnji Cooper 			if (errno == ENOENT)
41408ca345cSEnji Cooper 				method = TEST_BUILD_SNAPSHOT;
41508ca345cSEnji Cooper 			else {
41608ca345cSEnji Cooper 				printf("can't access the file %s\n",
41708ca345cSEnji Cooper 				    snapshot_file);
41808ca345cSEnji Cooper 
41908ca345cSEnji Cooper 				rv = -1;
42008ca345cSEnji Cooper 				goto fin;
42108ca345cSEnji Cooper 			}
42208ca345cSEnji Cooper 		} else {
42308ca345cSEnji Cooper 			if (method == TEST_BUILD_SNAPSHOT) {
42408ca345cSEnji Cooper 				rv = 0;
42508ca345cSEnji Cooper 				goto fin;
42608ca345cSEnji Cooper 			}
42708ca345cSEnji Cooper 
42808ca345cSEnji Cooper 			TEST_SNAPSHOT_FILE_READ(group, snapshot_file,
42908ca345cSEnji Cooper 				&td_snap, group_read_snapshot_func);
43008ca345cSEnji Cooper 		}
43108ca345cSEnji Cooper 	}
43208ca345cSEnji Cooper 
4336e411d8bSMark Johnston 	rv = group_fill_test_data(&td, NULL);
43408ca345cSEnji Cooper 	if (rv == -1)
43508ca345cSEnji Cooper 		return (-1);
43608ca345cSEnji Cooper 	switch (method) {
43708ca345cSEnji Cooper 	case TEST_GETGRNAM:
43808ca345cSEnji Cooper 		if (snapshot_file == NULL)
43908ca345cSEnji Cooper 			rv = DO_1PASS_TEST(group, &td,
44008ca345cSEnji Cooper 				group_test_getgrnam, (void *)&td);
44108ca345cSEnji Cooper 		else
44208ca345cSEnji Cooper 			rv = DO_1PASS_TEST(group, &td_snap,
44308ca345cSEnji Cooper 				group_test_getgrnam, (void *)&td_snap);
44408ca345cSEnji Cooper 		break;
44508ca345cSEnji Cooper 	case TEST_GETGRGID:
44608ca345cSEnji Cooper 		if (snapshot_file == NULL)
44708ca345cSEnji Cooper 			rv = DO_1PASS_TEST(group, &td,
44808ca345cSEnji Cooper 				group_test_getgrgid, (void *)&td);
44908ca345cSEnji Cooper 		else
45008ca345cSEnji Cooper 			rv = DO_1PASS_TEST(group, &td_snap,
45108ca345cSEnji Cooper 				group_test_getgrgid, (void *)&td_snap);
45208ca345cSEnji Cooper 		break;
45308ca345cSEnji Cooper 	case TEST_GETGRENT:
45408ca345cSEnji Cooper 		if (snapshot_file == NULL)
45508ca345cSEnji Cooper 			rv = DO_1PASS_TEST(group, &td, group_test_getgrent,
45608ca345cSEnji Cooper 				(void *)&td);
45708ca345cSEnji Cooper 		else
45808ca345cSEnji Cooper 			rv = DO_2PASS_TEST(group, &td, &td_snap,
45908ca345cSEnji Cooper 				compare_group, NULL);
46008ca345cSEnji Cooper 		break;
46108ca345cSEnji Cooper 	case TEST_GETGRENT_2PASS:
46208ca345cSEnji Cooper 		TEST_DATA_INIT(group, &td_2pass, clone_group, free_group);
4636e411d8bSMark Johnston 		rv = group_fill_test_data(&td_2pass, NULL);
46408ca345cSEnji Cooper 		if (rv != -1)
46508ca345cSEnji Cooper 			rv = DO_2PASS_TEST(group, &td, &td_2pass,
46608ca345cSEnji Cooper 				compare_group, NULL);
46708ca345cSEnji Cooper 		TEST_DATA_DESTROY(group, &td_2pass);
46808ca345cSEnji Cooper 		break;
4696e411d8bSMark Johnston 	case TEST_GETGRENT_INTERLEAVED_GETGRNAM:
4706e411d8bSMark Johnston 		TEST_DATA_INIT(group, &td_interleaved, clone_group, free_group);
4716e411d8bSMark Johnston 		rv = group_fill_test_data(&td_interleaved, group_test_getgrnam);
4726e411d8bSMark Johnston 		if (rv != -1)
4736e411d8bSMark Johnston 			rv = DO_2PASS_TEST(group, &td, &td_interleaved,
4746e411d8bSMark Johnston 			    compare_group, NULL);
4756e411d8bSMark Johnston 		TEST_DATA_DESTROY(group, &td_interleaved);
4766e411d8bSMark Johnston 		break;
4776e411d8bSMark Johnston 	case TEST_GETGRENT_INTERLEAVED_GETGRGID:
4786e411d8bSMark Johnston 		TEST_DATA_INIT(group, &td_interleaved, clone_group, free_group);
4796e411d8bSMark Johnston 		rv = group_fill_test_data(&td_interleaved, group_test_getgrgid);
4806e411d8bSMark Johnston 		if (rv != -1)
4816e411d8bSMark Johnston 			rv = DO_2PASS_TEST(group, &td, &td_interleaved,
4826e411d8bSMark Johnston 			    compare_group, NULL);
4836e411d8bSMark Johnston 		TEST_DATA_DESTROY(group, &td_interleaved);
4846e411d8bSMark Johnston 		break;
48508ca345cSEnji Cooper 	case TEST_BUILD_SNAPSHOT:
48608ca345cSEnji Cooper 		if (snapshot_file != NULL)
48708ca345cSEnji Cooper 			rv = TEST_SNAPSHOT_FILE_WRITE(group, snapshot_file, &td,
48808ca345cSEnji Cooper 			    sdump_group);
48908ca345cSEnji Cooper 		break;
49008ca345cSEnji Cooper 	default:
49108ca345cSEnji Cooper 		rv = 0;
49208ca345cSEnji Cooper 		break;
49308ca345cSEnji Cooper 	}
49408ca345cSEnji Cooper 
49508ca345cSEnji Cooper fin:
49608ca345cSEnji Cooper 	TEST_DATA_DESTROY(group, &td_snap);
49708ca345cSEnji Cooper 	TEST_DATA_DESTROY(group, &td);
49808ca345cSEnji Cooper 
49908ca345cSEnji Cooper 	return (rv);
50008ca345cSEnji Cooper }
50108ca345cSEnji Cooper 
50208ca345cSEnji Cooper #define	SNAPSHOT_FILE	"snapshot_grp"
50308ca345cSEnji Cooper 
5047532a657SEnji Cooper ATF_TC_WITHOUT_HEAD(getgrent);
50508ca345cSEnji Cooper ATF_TC_BODY(getgrent, tc)
50608ca345cSEnji Cooper {
5077abc1009SMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETGRENT) == 0);
50808ca345cSEnji Cooper }
50908ca345cSEnji Cooper 
51008ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getgrent_with_snapshot);
51108ca345cSEnji Cooper ATF_TC_BODY(getgrent_with_snapshot, tc)
51208ca345cSEnji Cooper {
51308ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
51408ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRENT) == 0);
51508ca345cSEnji Cooper }
51608ca345cSEnji Cooper 
51708ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getgrent_with_two_pass);
51808ca345cSEnji Cooper ATF_TC_BODY(getgrent_with_two_pass, tc)
51908ca345cSEnji Cooper {
5207abc1009SMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETGRENT_2PASS) == 0);
52108ca345cSEnji Cooper }
52208ca345cSEnji Cooper 
52308ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getgrgid);
52408ca345cSEnji Cooper ATF_TC_BODY(getgrgid, tc)
52508ca345cSEnji Cooper {
5267abc1009SMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETGRGID) == 0);
52708ca345cSEnji Cooper }
52808ca345cSEnji Cooper 
52908ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getgrgid_with_snapshot);
53008ca345cSEnji Cooper ATF_TC_BODY(getgrgid_with_snapshot, tc)
53108ca345cSEnji Cooper {
53208ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
53308ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRGID) == 0);
53408ca345cSEnji Cooper }
53508ca345cSEnji Cooper 
53608ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getgrnam);
53708ca345cSEnji Cooper ATF_TC_BODY(getgrnam, tc)
53808ca345cSEnji Cooper {
5397abc1009SMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETGRNAM) == 0);
54008ca345cSEnji Cooper }
54108ca345cSEnji Cooper 
54208ca345cSEnji Cooper ATF_TC_WITHOUT_HEAD(getgrnam_with_snapshot);
54308ca345cSEnji Cooper ATF_TC_BODY(getgrnam_with_snapshot, tc)
54408ca345cSEnji Cooper {
54508ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
54608ca345cSEnji Cooper 	ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRNAM) == 0);
54708ca345cSEnji Cooper }
54808ca345cSEnji Cooper 
5496e411d8bSMark Johnston ATF_TC_WITHOUT_HEAD(getgrent_interleaved_getgrnam);
5506e411d8bSMark Johnston ATF_TC_BODY(getgrent_interleaved_getgrnam, tc)
5516e411d8bSMark Johnston {
5526e411d8bSMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETGRENT_INTERLEAVED_GETGRNAM) == 0);
5536e411d8bSMark Johnston }
5546e411d8bSMark Johnston 
5556e411d8bSMark Johnston ATF_TC_WITHOUT_HEAD(getgrent_interleaved_getgrgid);
5566e411d8bSMark Johnston ATF_TC_BODY(getgrent_interleaved_getgrgid, tc)
5576e411d8bSMark Johnston {
5586e411d8bSMark Johnston 	ATF_REQUIRE(run_tests(NULL, TEST_GETGRENT_INTERLEAVED_GETGRGID) == 0);
5596e411d8bSMark Johnston }
5606e411d8bSMark Johnston 
56108ca345cSEnji Cooper ATF_TP_ADD_TCS(tp)
56208ca345cSEnji Cooper {
56308ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getgrent);
56408ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getgrent_with_snapshot);
56508ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getgrent_with_two_pass);
56608ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getgrgid);
56708ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getgrgid_with_snapshot);
56808ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getgrnam);
56908ca345cSEnji Cooper 	ATF_TP_ADD_TC(tp, getgrnam_with_snapshot);
5706e411d8bSMark Johnston 	ATF_TP_ADD_TC(tp, getgrent_interleaved_getgrnam);
5716e411d8bSMark Johnston 	ATF_TP_ADD_TC(tp, getgrent_interleaved_getgrgid);
57208ca345cSEnji Cooper 
57308ca345cSEnji Cooper 	return (atf_no_error());
57408ca345cSEnji Cooper }
575