2 * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <arpa/inet.h>
38 #include <stringlist.h>
51 static enum test_methods method
= TEST_BUILD_SNAPSHOT
;
53 DECLARE_TEST_DATA(group
)
54 DECLARE_TEST_FILE_SNAPSHOT(group
)
55 DECLARE_1PASS_TEST(group
)
56 DECLARE_2PASS_TEST(group
)
58 static void clone_group(struct group
*, struct group
const *);
59 static int compare_group(struct group
*, struct group
*, void *);
60 static void dump_group(struct group
*);
61 static void free_group(struct group
*);
63 static void sdump_group(struct group
*, char *, size_t);
64 static int group_read_snapshot_func(struct group
*, char *);
66 static int group_check_ambiguity(struct group_test_data
*,
68 static int group_fill_test_data(struct group_test_data
*);
69 static int group_test_correctness(struct group
*, void *);
70 static int group_test_getgrnam(struct group
*, void *);
71 static int group_test_getgrgid(struct group
*, void *);
72 static int group_test_getgrent(struct group
*, void *);
74 static void usage(void) __attribute__((__noreturn__
));
76 IMPLEMENT_TEST_DATA(group
)
77 IMPLEMENT_TEST_FILE_SNAPSHOT(group
)
78 IMPLEMENT_1PASS_TEST(group
)
79 IMPLEMENT_2PASS_TEST(group
)
82 clone_group(struct group
*dest
, struct group
const *src
)
90 memset(dest
, 0, sizeof(struct group
));
92 if (src
->gr_name
!= NULL
) {
93 dest
->gr_name
= strdup(src
->gr_name
);
94 assert(dest
->gr_name
!= NULL
);
97 if (src
->gr_passwd
!= NULL
) {
98 dest
->gr_passwd
= strdup(src
->gr_passwd
);
99 assert(dest
->gr_passwd
!= NULL
);
101 dest
->gr_gid
= src
->gr_gid
;
103 if (src
->gr_mem
!= NULL
) {
105 for (cp
= src
->gr_mem
; *cp
; ++cp
)
108 dest
->gr_mem
= (char **)malloc(
109 (members_num
+ 1) * (sizeof(char *)));
110 assert(dest
->gr_mem
!= NULL
);
111 memset(dest
->gr_mem
, 0, (members_num
+1) * (sizeof(char *)));
113 for (cp
= src
->gr_mem
; *cp
; ++cp
) {
114 dest
->gr_mem
[cp
- src
->gr_mem
] = strdup(*cp
);
115 assert(dest
->gr_mem
[cp
- src
->gr_mem
] != NULL
);
121 free_group(struct group
*grp
)
128 free(grp
->gr_passwd
);
130 for (cp
= grp
->gr_mem
; *cp
; ++cp
)
136 compare_group(struct group
*grp1
, struct group
*grp2
, void *mdata
)
143 if ((grp1
== NULL
) || (grp2
== NULL
))
146 if ((strcmp(grp1
->gr_name
, grp2
->gr_name
) != 0) ||
147 (strcmp(grp1
->gr_passwd
, grp2
->gr_passwd
) != 0) ||
148 (grp1
->gr_gid
!= grp2
->gr_gid
))
154 if ((grp1
->gr_mem
== NULL
) || (grp2
->gr_mem
== NULL
))
157 for (;*c1
&& *c2
; ++c1
, ++c2
)
158 if (strcmp(*c1
, *c2
) != 0)
161 if ((*c1
!= '\0') || (*c2
!= '\0'))
167 if ((debug
) && (mdata
== NULL
)) {
168 printf("following structures are not equal:\n");
177 sdump_group(struct group
*grp
, char *buffer
, size_t buflen
)
182 written
= snprintf(buffer
, buflen
, "%s %s %d",
183 grp
->gr_name
, grp
->gr_passwd
, grp
->gr_gid
);
185 if (written
> buflen
)
189 if (grp
->gr_mem
!= NULL
) {
190 if (*(grp
->gr_mem
) != '\0') {
191 for (cp
= grp
->gr_mem
; *cp
; ++cp
) {
192 written
= snprintf(buffer
, buflen
, " %s",*cp
);
194 if (written
> buflen
)
202 snprintf(buffer
, buflen
, " nomem");
204 snprintf(buffer
, buflen
, " (null)");
208 group_read_snapshot_func(struct group
*grp
, char *line
)
215 printf("1 line read from snapshot:\n%s\n", line
);
220 memset(grp
, 0, sizeof(struct group
));
221 while ( (s
= strsep(&ps
, " ")) != NULL
) {
224 grp
->gr_name
= strdup(s
);
225 assert(grp
->gr_name
!= NULL
);
229 grp
->gr_passwd
= strdup(s
);
230 assert(grp
->gr_passwd
!= NULL
);
234 grp
->gr_gid
= (gid_t
)strtol(s
, &ts
, 10);
237 free(grp
->gr_passwd
);
244 if (strcmp(s
, "(null)") == 0)
250 if (strcmp(s
, "nomem") != 0) {
267 free(grp
->gr_passwd
);
268 memset(grp
, 0, sizeof(struct group
));
273 grp
->gr_mem
= sl
->sl_str
;
275 /* NOTE: is it a dirty hack or not? */
281 dump_group(struct group
*result
)
283 if (result
!= NULL
) {
285 sdump_group(result
, buffer
, sizeof(buffer
));
286 printf("%s\n", buffer
);
292 group_fill_test_data(struct group_test_data
*td
)
297 while ((grp
= getgrent()) != NULL
) {
298 if (group_test_correctness(grp
, NULL
) == 0)
299 TEST_DATA_APPEND(group
, td
, grp
);
309 group_test_correctness(struct group
*grp
, void *mdata
)
312 printf("testing correctness with the following data:\n");
319 if (grp
->gr_name
== NULL
)
322 if (grp
->gr_passwd
== NULL
)
325 if (grp
->gr_mem
== NULL
)
334 printf("incorrect\n");
339 /* group_check_ambiguity() is needed here because when doing the getgrent()
340 * calls sequence, records from different nsswitch sources can be different,
341 * though having the same pw_name/pw_uid */
343 group_check_ambiguity(struct group_test_data
*td
, struct group
*pwd
)
346 return (TEST_DATA_FIND(group
, td
, pwd
, compare_group
,
347 NULL
) != NULL
? 0 : -1);
351 group_test_getgrnam(struct group
*grp_model
, void *mdata
)
356 printf("testing getgrnam() with the following data:\n");
357 dump_group(grp_model
);
360 grp
= getgrnam(grp_model
->gr_name
);
361 if (group_test_correctness(grp
, NULL
) != 0)
364 if ((compare_group(grp
, grp_model
, NULL
) != 0) &&
365 (group_check_ambiguity((struct group_test_data
*)mdata
, grp
)
381 group_test_getgrgid(struct group
*grp_model
, void *mdata
)
386 printf("testing getgrgid() with the following data...\n");
387 dump_group(grp_model
);
390 grp
= getgrgid(grp_model
->gr_gid
);
391 if ((group_test_correctness(grp
, NULL
) != 0) ||
392 ((compare_group(grp
, grp_model
, NULL
) != 0) &&
393 (group_check_ambiguity((struct group_test_data
*)mdata
, grp
)
406 group_test_getgrent(struct group
*grp
, void *mdata
)
408 /* Only correctness can be checked when doing 1-pass test for
410 return (group_test_correctness(grp
, NULL
));
416 (void)fprintf(stderr
,
417 "Usage: %s -nge2 [-d] [-s <file>]\n",
423 main(int argc
, char **argv
)
425 struct group_test_data td
, td_snap
, td_2pass
;
433 snapshot_file
= NULL
;
434 while ((c
= getopt(argc
, argv
, "nge2ds:")) != -1)
440 method
= TEST_GETGRNAM
;
443 method
= TEST_GETGRGID
;
446 method
= TEST_GETGRENT
;
449 method
= TEST_GETGRENT_2PASS
;
452 snapshot_file
= strdup(optarg
);
458 TEST_DATA_INIT(group
, &td
, clone_group
, free_group
);
459 TEST_DATA_INIT(group
, &td_snap
, clone_group
, free_group
);
460 if (snapshot_file
!= NULL
) {
461 if (access(snapshot_file
, W_OK
| R_OK
) != 0) {
463 method
= TEST_BUILD_SNAPSHOT
;
466 printf("can't access the file %s\n",
473 if (method
== TEST_BUILD_SNAPSHOT
) {
478 TEST_SNAPSHOT_FILE_READ(group
, snapshot_file
,
479 &td_snap
, group_read_snapshot_func
);
483 rv
= group_fill_test_data(&td
);
488 if (snapshot_file
== NULL
)
489 rv
= DO_1PASS_TEST(group
, &td
,
490 group_test_getgrnam
, (void *)&td
);
492 rv
= DO_1PASS_TEST(group
, &td_snap
,
493 group_test_getgrnam
, (void *)&td_snap
);
496 if (snapshot_file
== NULL
)
497 rv
= DO_1PASS_TEST(group
, &td
,
498 group_test_getgrgid
, (void *)&td
);
500 rv
= DO_1PASS_TEST(group
, &td_snap
,
501 group_test_getgrgid
, (void *)&td_snap
);
504 if (snapshot_file
== NULL
)
505 rv
= DO_1PASS_TEST(group
, &td
, group_test_getgrent
,
508 rv
= DO_2PASS_TEST(group
, &td
, &td_snap
,
509 compare_group
, NULL
);
511 case TEST_GETGRENT_2PASS
:
512 TEST_DATA_INIT(group
, &td_2pass
, clone_group
, free_group
);
513 rv
= group_fill_test_data(&td_2pass
);
515 rv
= DO_2PASS_TEST(group
, &td
, &td_2pass
,
516 compare_group
, NULL
);
517 TEST_DATA_DESTROY(group
, &td_2pass
);
519 case TEST_BUILD_SNAPSHOT
:
520 if (snapshot_file
!= NULL
)
521 rv
= TEST_SNAPSHOT_FILE_WRITE(group
, snapshot_file
, &td
,
530 TEST_DATA_DESTROY(group
, &td_snap
);
531 TEST_DATA_DESTROY(group
, &td
);