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$");
49 static enum test_methods method
= TEST_BUILD_SNAPSHOT
;
51 DECLARE_TEST_DATA(passwd
)
52 DECLARE_TEST_FILE_SNAPSHOT(passwd
)
53 DECLARE_1PASS_TEST(passwd
)
54 DECLARE_2PASS_TEST(passwd
)
56 static void clone_passwd(struct passwd
*, struct passwd
const *);
57 static int compare_passwd(struct passwd
*, struct passwd
*, void *);
58 static void free_passwd(struct passwd
*);
60 static void sdump_passwd(struct passwd
*, char *, size_t);
61 static void dump_passwd(struct passwd
*);
63 static int passwd_read_snapshot_func(struct passwd
*, char *);
65 static int passwd_check_ambiguity(struct passwd_test_data
*, struct passwd
*);
66 static int passwd_fill_test_data(struct passwd_test_data
*);
67 static int passwd_test_correctness(struct passwd
*, void *);
68 static int passwd_test_getpwnam(struct passwd
*, void *);
69 static int passwd_test_getpwuid(struct passwd
*, void *);
70 static int passwd_test_getpwent(struct passwd
*, void *);
72 static void usage(void) __attribute__((__noreturn__
));
74 IMPLEMENT_TEST_DATA(passwd
)
75 IMPLEMENT_TEST_FILE_SNAPSHOT(passwd
)
76 IMPLEMENT_1PASS_TEST(passwd
)
77 IMPLEMENT_2PASS_TEST(passwd
)
80 clone_passwd(struct passwd
*dest
, struct passwd
const *src
)
85 memcpy(dest
, src
, sizeof(struct passwd
));
86 if (src
->pw_name
!= NULL
)
87 dest
->pw_name
= strdup(src
->pw_name
);
88 if (src
->pw_passwd
!= NULL
)
89 dest
->pw_passwd
= strdup(src
->pw_passwd
);
90 if (src
->pw_class
!= NULL
)
91 dest
->pw_class
= strdup(src
->pw_class
);
92 if (src
->pw_gecos
!= NULL
)
93 dest
->pw_gecos
= strdup(src
->pw_gecos
);
94 if (src
->pw_dir
!= NULL
)
95 dest
->pw_dir
= strdup(src
->pw_dir
);
96 if (src
->pw_shell
!= NULL
)
97 dest
->pw_shell
= strdup(dest
->pw_shell
);
101 compare_passwd(struct passwd
*pwd1
, struct passwd
*pwd2
, void *mdata
)
103 assert(pwd1
!= NULL
);
104 assert(pwd2
!= NULL
);
109 if ((pwd1
->pw_uid
!= pwd2
->pw_uid
) ||
110 (pwd1
->pw_gid
!= pwd2
->pw_gid
) ||
111 (pwd1
->pw_change
!= pwd2
->pw_change
) ||
112 (pwd1
->pw_expire
!= pwd2
->pw_expire
) ||
113 (pwd1
->pw_fields
!= pwd2
->pw_fields
) ||
114 (strcmp(pwd1
->pw_name
, pwd2
->pw_name
) != 0) ||
115 (strcmp(pwd1
->pw_passwd
, pwd2
->pw_passwd
) != 0) ||
116 (strcmp(pwd1
->pw_class
, pwd2
->pw_class
) != 0) ||
117 (strcmp(pwd1
->pw_gecos
, pwd2
->pw_gecos
) != 0) ||
118 (strcmp(pwd1
->pw_dir
, pwd2
->pw_dir
) != 0) ||
119 (strcmp(pwd1
->pw_shell
, pwd2
->pw_shell
) != 0)
127 free_passwd(struct passwd
*pwd
)
130 free(pwd
->pw_passwd
);
138 sdump_passwd(struct passwd
*pwd
, char *buffer
, size_t buflen
)
140 snprintf(buffer
, buflen
, "%s:%s:%d:%d:%d:%s:%s:%s:%s:%d:%d",
141 pwd
->pw_name
, pwd
->pw_passwd
, pwd
->pw_uid
, pwd
->pw_gid
,
142 pwd
->pw_change
, pwd
->pw_class
, pwd
->pw_gecos
, pwd
->pw_dir
,
143 pwd
->pw_shell
, pwd
->pw_expire
, pwd
->pw_fields
);
147 dump_passwd(struct passwd
*pwd
)
151 sdump_passwd(pwd
, buffer
, sizeof(buffer
));
152 printf("%s\n", buffer
);
158 passwd_read_snapshot_func(struct passwd
*pwd
, char *line
)
164 printf("1 line read from snapshot:\n%s\n", line
);
168 memset(pwd
, 0, sizeof(struct passwd
));
169 while ( (s
= strsep(&ps
, ":")) != NULL
) {
172 pwd
->pw_name
= strdup(s
);
173 assert(pwd
->pw_name
!= NULL
);
176 pwd
->pw_passwd
= strdup(s
);
177 assert(pwd
->pw_passwd
!= NULL
);
180 pwd
->pw_uid
= (uid_t
)strtol(s
, &ts
, 10);
185 pwd
->pw_gid
= (gid_t
)strtol(s
, &ts
, 10);
190 pwd
->pw_change
= (time_t)strtol(s
, &ts
, 10);
195 pwd
->pw_class
= strdup(s
);
196 assert(pwd
->pw_class
!= NULL
);
199 pwd
->pw_gecos
= strdup(s
);
200 assert(pwd
->pw_gecos
!= NULL
);
203 pwd
->pw_dir
= strdup(s
);
204 assert(pwd
->pw_dir
!= NULL
);
207 pwd
->pw_shell
= strdup(s
);
208 assert(pwd
->pw_shell
!= NULL
);
211 pwd
->pw_expire
= (time_t)strtol(s
, &ts
, 10);
216 pwd
->pw_fields
= (int)strtol(s
, &ts
, 10);
229 memset(pwd
, 0, sizeof(struct passwd
));
237 passwd_fill_test_data(struct passwd_test_data
*td
)
242 while ((pwd
= getpwent()) != NULL
) {
243 if (passwd_test_correctness(pwd
, NULL
) == 0)
244 TEST_DATA_APPEND(passwd
, td
, pwd
);
254 passwd_test_correctness(struct passwd
*pwd
, void *mdata
)
257 printf("testing correctness with the following data:\n");
264 if (pwd
->pw_name
== NULL
)
267 if (pwd
->pw_passwd
== NULL
)
270 if (pwd
->pw_class
== NULL
)
273 if (pwd
->pw_gecos
== NULL
)
276 if (pwd
->pw_dir
== NULL
)
279 if (pwd
->pw_shell
== NULL
)
288 printf("incorrect\n");
293 /* passwd_check_ambiguity() is needed here because when doing the getpwent()
294 * calls sequence, records from different nsswitch sources can be different,
295 * though having the same pw_name/pw_uid */
297 passwd_check_ambiguity(struct passwd_test_data
*td
, struct passwd
*pwd
)
300 return (TEST_DATA_FIND(passwd
, td
, pwd
, compare_passwd
,
301 NULL
) != NULL
? 0 : -1);
305 passwd_test_getpwnam(struct passwd
*pwd_model
, void *mdata
)
310 printf("testing getpwnam() with the following data:\n");
311 dump_passwd(pwd_model
);
314 pwd
= getpwnam(pwd_model
->pw_name
);
315 if (passwd_test_correctness(pwd
, NULL
) != 0)
318 if ((compare_passwd(pwd
, pwd_model
, NULL
) != 0) &&
319 (passwd_check_ambiguity((struct passwd_test_data
*)mdata
, pwd
)
335 passwd_test_getpwuid(struct passwd
*pwd_model
, void *mdata
)
340 printf("testing getpwuid() with the following data...\n");
341 dump_passwd(pwd_model
);
344 pwd
= getpwuid(pwd_model
->pw_uid
);
345 if ((passwd_test_correctness(pwd
, NULL
) != 0) ||
346 ((compare_passwd(pwd
, pwd_model
, NULL
) != 0) &&
347 (passwd_check_ambiguity((struct passwd_test_data
*)mdata
, pwd
)
360 passwd_test_getpwent(struct passwd
*pwd
, void *mdata
)
362 /* Only correctness can be checked when doing 1-pass test for
364 return (passwd_test_correctness(pwd
, NULL
));
370 (void)fprintf(stderr
,
371 "Usage: %s -nue2 [-d] [-s <file>]\n",
377 main(int argc
, char **argv
)
379 struct passwd_test_data td
, td_snap
, td_2pass
;
387 snapshot_file
= NULL
;
388 while ((c
= getopt(argc
, argv
, "nue2ds:")) != -1)
394 method
= TEST_GETPWNAM
;
397 method
= TEST_GETPWUID
;
400 method
= TEST_GETPWENT
;
403 method
= TEST_GETPWENT_2PASS
;
406 snapshot_file
= strdup(optarg
);
412 TEST_DATA_INIT(passwd
, &td
, clone_passwd
, free_passwd
);
413 TEST_DATA_INIT(passwd
, &td_snap
, clone_passwd
, free_passwd
);
414 if (snapshot_file
!= NULL
) {
415 if (access(snapshot_file
, W_OK
| R_OK
) != 0) {
417 method
= TEST_BUILD_SNAPSHOT
;
420 printf("can't access the file %s\n",
427 if (method
== TEST_BUILD_SNAPSHOT
) {
432 TEST_SNAPSHOT_FILE_READ(passwd
, snapshot_file
,
433 &td_snap
, passwd_read_snapshot_func
);
437 rv
= passwd_fill_test_data(&td
);
443 if (snapshot_file
== NULL
)
444 rv
= DO_1PASS_TEST(passwd
, &td
,
445 passwd_test_getpwnam
, (void *)&td
);
447 rv
= DO_1PASS_TEST(passwd
, &td_snap
,
448 passwd_test_getpwnam
, (void *)&td_snap
);
451 if (snapshot_file
== NULL
)
452 rv
= DO_1PASS_TEST(passwd
, &td
,
453 passwd_test_getpwuid
, (void *)&td
);
455 rv
= DO_1PASS_TEST(passwd
, &td_snap
,
456 passwd_test_getpwuid
, (void *)&td_snap
);
459 if (snapshot_file
== NULL
)
460 rv
= DO_1PASS_TEST(passwd
, &td
, passwd_test_getpwent
,
463 rv
= DO_2PASS_TEST(passwd
, &td
, &td_snap
,
464 compare_passwd
, NULL
);
466 case TEST_GETPWENT_2PASS
:
467 TEST_DATA_INIT(passwd
, &td_2pass
, clone_passwd
, free_passwd
);
468 rv
= passwd_fill_test_data(&td_2pass
);
470 rv
= DO_2PASS_TEST(passwd
, &td
, &td_2pass
,
471 compare_passwd
, NULL
);
472 TEST_DATA_DESTROY(passwd
, &td_2pass
);
474 case TEST_BUILD_SNAPSHOT
:
475 if (snapshot_file
!= NULL
)
476 rv
= TEST_SNAPSHOT_FILE_WRITE(passwd
, snapshot_file
, &td
,
485 TEST_DATA_DESTROY(passwd
, &td_snap
);
486 TEST_DATA_DESTROY(passwd
, &td
);