Index: stable/11/lib/libc/tests/nss/Makefile =================================================================== --- stable/11/lib/libc/tests/nss/Makefile (revision 319298) +++ stable/11/lib/libc/tests/nss/Makefile (revision 319299) @@ -1,26 +1,27 @@ # $FreeBSD$ +.PATH: ${.CURDIR:H}/resolv + PACKAGE= tests TESTSDIR= ${TESTSBASE}/lib/libc/nss BINDIR= ${TESTSDIR} -.PATH: ${.CURDIR:H}/resolv - -${PACKAGE}FILES+= mach - -WARNS?= 1 -CFLAGS+= -I${SRCTOP}/tests - ATF_TESTS_C+= getaddrinfo_test ATF_TESTS_C+= getgr_test ATF_TESTS_C+= gethostby_test TEST_METADATA.gethostby_test= timeout="1200" ATF_TESTS_C+= getpw_test ATF_TESTS_C+= getproto_test ATF_TESTS_C+= getrpc_test ATF_TESTS_C+= getserv_test ATF_TESTS_C+= getusershell_test + +${PACKAGE}FILES+= mach + +WARNS?= 1 + +CFLAGS+= -I${SRCTOP}/tests .include Index: stable/11/lib/libc/tests/nss/getaddrinfo_test.c =================================================================== --- stable/11/lib/libc/tests/nss/getaddrinfo_test.c (revision 319298) +++ stable/11/lib/libc/tests/nss/getaddrinfo_test.c (revision 319299) @@ -1,556 +1,556 @@ /*- * Copyright (c) 2006 Michael Bushkov * All rights reserved. * * 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 __FBSDID("$FreeBSD$"); -#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include "freebsd_test_suite/macros.h" #include "testutil.h" enum test_methods { TEST_GETADDRINFO, TEST_BUILD_SNAPSHOT }; static struct addrinfo hints; static enum test_methods method = TEST_GETADDRINFO; DECLARE_TEST_DATA(addrinfo) DECLARE_TEST_FILE_SNAPSHOT(addrinfo) DECLARE_2PASS_TEST(addrinfo) static void clone_addrinfo(struct addrinfo *, struct addrinfo const *); static int compare_addrinfo(struct addrinfo *, struct addrinfo *, void *); static void dump_addrinfo(struct addrinfo *); static void sdump_addrinfo(struct addrinfo *, char *, size_t); IMPLEMENT_TEST_DATA(addrinfo) IMPLEMENT_TEST_FILE_SNAPSHOT(addrinfo) IMPLEMENT_2PASS_TEST(addrinfo) static void clone_addrinfo(struct addrinfo *dest, struct addrinfo const *src) { ATF_REQUIRE(dest != NULL); ATF_REQUIRE(src != NULL); memcpy(dest, src, sizeof(struct addrinfo)); if (src->ai_canonname != NULL) dest->ai_canonname = strdup(src->ai_canonname); if (src->ai_addr != NULL) { dest->ai_addr = malloc(src->ai_addrlen); ATF_REQUIRE(dest->ai_addr != NULL); memcpy(dest->ai_addr, src->ai_addr, src->ai_addrlen); } if (src->ai_next != NULL) { dest->ai_next = malloc(sizeof(struct addrinfo)); ATF_REQUIRE(dest->ai_next != NULL); clone_addrinfo(dest->ai_next, src->ai_next); } } static int compare_addrinfo_(struct addrinfo *ai1, struct addrinfo *ai2) { if ((ai1 == NULL) || (ai2 == NULL)) return (-1); if (ai1->ai_flags != ai2->ai_flags || ai1->ai_family != ai2->ai_family || ai1->ai_socktype != ai2->ai_socktype || ai1->ai_protocol != ai2->ai_protocol || ai1->ai_addrlen != ai2->ai_addrlen || ((ai1->ai_addr == NULL || ai2->ai_addr == NULL) && ai1->ai_addr != ai2->ai_addr) || ((ai1->ai_canonname == NULL || ai2->ai_canonname == NULL) && ai1->ai_canonname != ai2->ai_canonname)) return (-1); if (ai1->ai_canonname != NULL && strcmp(ai1->ai_canonname, ai2->ai_canonname) != 0) return (-1); if (ai1->ai_addr != NULL && memcmp(ai1->ai_addr, ai2->ai_addr, ai1->ai_addrlen) != 0) return (-1); if (ai1->ai_next == NULL && ai2->ai_next == NULL) return (0); else return (compare_addrinfo_(ai1->ai_next, ai2->ai_next)); } static int -compare_addrinfo(struct addrinfo *ai1, struct addrinfo *ai2, void *mdata) +compare_addrinfo(struct addrinfo *ai1, struct addrinfo *ai2, + void *mdata __unused) { int rv; printf("testing equality of 2 addrinfo structures\n"); rv = compare_addrinfo_(ai1, ai2); if (rv == 0) printf("equal\n"); else { dump_addrinfo(ai1); dump_addrinfo(ai2); printf("not equal\n"); } return (rv); } -void +static void free_addrinfo(struct addrinfo *ai) { if (ai == NULL) return; free(ai->ai_addr); free(ai->ai_canonname); free_addrinfo(ai->ai_next); } void sdump_addrinfo(struct addrinfo *ai, char *buffer, size_t buflen) { int written, i; written = snprintf(buffer, buflen, "%d %d %d %d %d ", ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol, ai->ai_addrlen); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; written = snprintf(buffer, buflen, "%s ", ai->ai_canonname == NULL ? "(null)" : ai->ai_canonname); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; if (ai->ai_addr == NULL) { written = snprintf(buffer, buflen, "(null)"); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; } else { - for (i = 0; i < ai->ai_addrlen; i++) { + for (i = 0; i < (int)ai->ai_addrlen; i++) { written = snprintf(buffer, buflen, - i + 1 != ai->ai_addrlen ? "%d." : "%d", + i + 1 != (int)ai->ai_addrlen ? "%d." : "%d", ((unsigned char *)ai->ai_addr)[i]); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; if (buflen == 0) return; } } if (ai->ai_next != NULL) { written = snprintf(buffer, buflen, ":"); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; sdump_addrinfo(ai->ai_next, buffer, buflen); } } void dump_addrinfo(struct addrinfo *result) { if (result != NULL) { char buffer[2048]; sdump_addrinfo(result, buffer, sizeof(buffer)); printf("%s\n", buffer); } else printf("(null)\n"); } static int addrinfo_read_snapshot_addr(char *addr, unsigned char *result, size_t len) { char *s, *ps, *ts; ps = addr; while ((s = strsep(&ps, ".")) != NULL) { if (len == 0) return (-1); *result = (unsigned char)strtol(s, &ts, 10); ++result; if (*ts != '\0') return (-1); --len; } if (len != 0) return (-1); else return (0); } static int addrinfo_read_snapshot_ai(struct addrinfo *ai, char *line) { char *s, *ps, *ts; int i, rv, *pi; rv = 0; i = 0; ps = line; memset(ai, 0, sizeof(struct addrinfo)); while ((s = strsep(&ps, " ")) != NULL) { switch (i) { case 0: case 1: case 2: case 3: pi = &ai->ai_flags + i; *pi = (int)strtol(s, &ts, 10); if (*ts != '\0') goto fin; break; case 4: ai->ai_addrlen = (socklen_t)strtol(s, &ts, 10); if (*ts != '\0') goto fin; break; case 5: if (strcmp(s, "(null)") != 0) { ai->ai_canonname = strdup(s); ATF_REQUIRE(ai->ai_canonname != NULL); } break; case 6: if (strcmp(s, "(null)") != 0) { ai->ai_addr = calloc(1, ai->ai_addrlen); ATF_REQUIRE(ai->ai_addr != NULL); rv = addrinfo_read_snapshot_addr(s, (unsigned char *)ai->ai_addr, ai->ai_addrlen); if (rv != 0) goto fin; } break; default: /* NOTE: should not be reachable */ rv = -1; goto fin; } ++i; } fin: if (i != 7 || rv != 0) { free_addrinfo(ai); ai = NULL; return (-1); } return (0); } static int addrinfo_read_snapshot_func(struct addrinfo *ai, char *line) { struct addrinfo *ai2; char *s, *ps; - int i, rv; + int rv; printf("1 line read from snapshot:\n%s\n", line); rv = 0; - i = 0; ps = line; s = strsep(&ps, ":"); if (s == NULL) return (-1); rv = addrinfo_read_snapshot_ai(ai, s); if (rv != 0) return (-1); ai2 = ai; while ((s = strsep(&ps, ":")) != NULL) { ai2->ai_next = calloc(1, sizeof(struct addrinfo)); ATF_REQUIRE(ai2->ai_next != NULL); rv = addrinfo_read_snapshot_ai(ai2->ai_next, s); if (rv != 0) { free_addrinfo(ai); ai = NULL; return (-1); } ai2 = ai2->ai_next; } return (0); } static int -addrinfo_test_correctness(struct addrinfo *ai, void *mdata) +addrinfo_test_correctness(struct addrinfo *ai, void *mdata __unused) { printf("testing correctness with the following data:\n"); dump_addrinfo(ai); if (ai == NULL) goto errfin; if (!(ai->ai_family >= 0 && ai->ai_family < AF_MAX)) goto errfin; if (ai->ai_socktype != 0 && ai->ai_socktype != SOCK_STREAM && ai->ai_socktype != SOCK_DGRAM && ai->ai_socktype != SOCK_RAW) goto errfin; if (ai->ai_protocol != 0 && ai->ai_protocol != IPPROTO_UDP && ai->ai_protocol != IPPROTO_TCP) goto errfin; if ((ai->ai_flags & ~(AI_CANONNAME | AI_NUMERICHOST | AI_PASSIVE)) != 0) goto errfin; if (ai->ai_addrlen != ai->ai_addr->sa_len || ai->ai_family != ai->ai_addr->sa_family) goto errfin; printf("correct\n"); return (0); errfin: printf("incorrect\n"); return (-1); } static int addrinfo_read_hostlist_func(struct addrinfo *ai, char *line) { struct addrinfo *result; int rv; printf("resolving %s: ", line); rv = getaddrinfo(line, NULL, &hints, &result); if (rv == 0) { printf("found\n"); rv = addrinfo_test_correctness(result, NULL); if (rv != 0) { freeaddrinfo(result); result = NULL; return (rv); } clone_addrinfo(ai, result); freeaddrinfo(result); result = NULL; } else { printf("not found\n"); memset(ai, 0, sizeof(struct addrinfo)); } return (0); } -void +static void run_tests(char *hostlist_file, char *snapshot_file, int ai_family) { struct addrinfo_test_data td, td_snap; int rv; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = ai_family; hints.ai_flags = AI_CANONNAME; if (snapshot_file != NULL) method = TEST_BUILD_SNAPSHOT; TEST_DATA_INIT(addrinfo, &td, clone_addrinfo, free_addrinfo); TEST_DATA_INIT(addrinfo, &td_snap, clone_addrinfo, free_addrinfo); ATF_REQUIRE_MSG(access(hostlist_file, R_OK) == 0, "can't access the hostlist file %s\n", hostlist_file); printf("building host lists from %s\n", hostlist_file); rv = TEST_SNAPSHOT_FILE_READ(addrinfo, hostlist_file, &td, addrinfo_read_hostlist_func); if (rv != 0) goto fin; if (snapshot_file != NULL) { if (access(snapshot_file, W_OK | R_OK) != 0) { if (errno == ENOENT) method = TEST_BUILD_SNAPSHOT; else { printf("can't access the snapshot " "file %s\n", snapshot_file); rv = -1; goto fin; } } else { rv = TEST_SNAPSHOT_FILE_READ(addrinfo, snapshot_file, &td_snap, addrinfo_read_snapshot_func); if (rv != 0) { printf("error reading snapshot file: %s\n", strerror(errno)); goto fin; } } } switch (method) { case TEST_GETADDRINFO: if (snapshot_file != NULL) ATF_CHECK(DO_2PASS_TEST(addrinfo, &td, &td_snap, compare_addrinfo, NULL) == 0); break; case TEST_BUILD_SNAPSHOT: if (snapshot_file != NULL) { ATF_CHECK(TEST_SNAPSHOT_FILE_WRITE(addrinfo, snapshot_file, &td, sdump_addrinfo) == 0); } break; default: break; } fin: TEST_DATA_DESTROY(addrinfo, &td_snap); TEST_DATA_DESTROY(addrinfo, &td); free(hostlist_file); free(snapshot_file); } #define HOSTLIST_FILE "mach" #define RUN_TESTS(tc, snapshot_file, ai_family) do { \ char *_hostlist_file; \ char *_snapshot_file; \ ATF_REQUIRE(0 < asprintf(&_hostlist_file, "%s/%s", \ atf_tc_get_config_var(tc, "srcdir"), HOSTLIST_FILE)); \ if (snapshot_file == NULL) \ _snapshot_file = NULL; \ else { \ _snapshot_file = strdup(snapshot_file); \ ATF_REQUIRE(_snapshot_file != NULL); \ } \ run_tests(_hostlist_file, _snapshot_file, ai_family); \ } while(0) ATF_TC_WITHOUT_HEAD(pf_unspec); ATF_TC_BODY(pf_unspec, tc) { RUN_TESTS(tc, NULL, AF_UNSPEC); } ATF_TC_WITHOUT_HEAD(pf_unspec_with_snapshot); ATF_TC_BODY(pf_unspec_with_snapshot, tc) { RUN_TESTS(tc, "snapshot_ai", AF_UNSPEC); } ATF_TC_WITHOUT_HEAD(pf_inet); ATF_TC_BODY(pf_inet, tc) { ATF_REQUIRE_FEATURE("inet"); RUN_TESTS(tc, NULL, AF_INET); } ATF_TC_WITHOUT_HEAD(pf_inet_with_snapshot); ATF_TC_BODY(pf_inet_with_snapshot, tc) { ATF_REQUIRE_FEATURE("inet"); RUN_TESTS(tc, "snapshot_ai4", AF_INET); } ATF_TC_WITHOUT_HEAD(pf_inet6); ATF_TC_BODY(pf_inet6, tc) { ATF_REQUIRE_FEATURE("inet6"); RUN_TESTS(tc, NULL, AF_INET6); } ATF_TC_WITHOUT_HEAD(pf_inet6_with_snapshot); ATF_TC_BODY(pf_inet6_with_snapshot, tc) { ATF_REQUIRE_FEATURE("inet6"); RUN_TESTS(tc, "snapshot_ai6", AF_INET6); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, pf_unspec); ATF_TP_ADD_TC(tp, pf_unspec_with_snapshot); ATF_TP_ADD_TC(tp, pf_inet); ATF_TP_ADD_TC(tp, pf_inet_with_snapshot); ATF_TP_ADD_TC(tp, pf_inet6); ATF_TP_ADD_TC(tp, pf_inet6_with_snapshot); return (atf_no_error()); } Index: stable/11/lib/libc/tests/nss/getgr_test.c =================================================================== --- stable/11/lib/libc/tests/nss/getgr_test.c (revision 319298) +++ stable/11/lib/libc/tests/nss/getgr_test.c (revision 319299) @@ -1,546 +1,544 @@ /*- * Copyright (c) 2006 Michael Bushkov * All rights reserved. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "testutil.h" enum test_methods { TEST_GETGRENT = 1, TEST_GETGRNAM = 2, TEST_GETGRGID = 4, TEST_GETGRENT_2PASS = 8, TEST_BUILD_SNAPSHOT = 16, }; -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 *); 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) { ATF_REQUIRE(dest != NULL); ATF_REQUIRE(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); ATF_REQUIRE(dest->gr_name != NULL); } if (src->gr_passwd != NULL) { dest->gr_passwd = strdup(src->gr_passwd); ATF_REQUIRE(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 = calloc(1, (members_num + 1) * sizeof(char *)); + dest->gr_mem = calloc(members_num + 1, sizeof(char *)); ATF_REQUIRE(dest->gr_mem != NULL); for (cp = src->gr_mem; *cp; ++cp) { dest->gr_mem[cp - src->gr_mem] = strdup(*cp); ATF_REQUIRE(dest->gr_mem[cp - src->gr_mem] != NULL); } } } static void free_group(struct group *grp) { char **cp; ATF_REQUIRE(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 (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) + if (written > (int)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%s", cp == grp->gr_mem ? "" : ",", *cp); buffer += written; - if (written > buflen) + if (written > (int)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; const char *sep; int i; printf("1 line read from snapshot:\n%s\n", line); i = 0; sl = NULL; ps = line; sep = ":"; memset(grp, 0, sizeof(struct group)); while ((s = strsep(&ps, sep)) != NULL) { switch (i) { case 0: grp->gr_name = strdup(s); ATF_REQUIRE(grp->gr_name != NULL); break; case 1: grp->gr_passwd = strdup(s); ATF_REQUIRE(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); grp->gr_name = NULL; grp->gr_passwd = NULL; return (-1); } /* Change to parsing groups. */ sep = ","; break; default: if (sl == NULL) { if (strcmp(s, "(null)") == 0) return (0); sl = sl_init(); ATF_REQUIRE(sl != NULL); if (strcmp(s, "nomem") != 0) { ts = strdup(s); ATF_REQUIRE(ts != NULL); sl_add(sl, ts); } } else { ts = strdup(s); ATF_REQUIRE(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) +group_test_correctness(struct group *grp, void *mdata __unused) { 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; printf("correct\n"); return (0); errfin: 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; 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; return (0); errfin: return (-1); } static int group_test_getgrgid(struct group *grp_model, void *mdata) { struct group *grp; 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)) { return (-1); } else { return (0); } } static int -group_test_getgrent(struct group *grp, void *mdata) +group_test_getgrent(struct group *grp, void *mdata __unused) { /* Only correctness can be checked when doing 1-pass test for * getgrent(). */ return (group_test_correctness(grp, NULL)); } static int run_tests(const char *snapshot_file, enum test_methods method) { struct group_test_data td, td_snap, td_2pass; int rv; 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 { 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); return (rv); } #define SNAPSHOT_FILE "snapshot_grp" ATF_TC_WITHOUT_HEAD(getgrent); ATF_TC_BODY(getgrent, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRENT) == 0); } ATF_TC_WITHOUT_HEAD(getgrent_with_snapshot); ATF_TC_BODY(getgrent_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRENT) == 0); } ATF_TC_WITHOUT_HEAD(getgrent_with_two_pass); ATF_TC_BODY(getgrent_with_two_pass, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRENT_2PASS) == 0); } ATF_TC_WITHOUT_HEAD(getgrgid); ATF_TC_BODY(getgrgid, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRGID) == 0); } ATF_TC_WITHOUT_HEAD(getgrgid_with_snapshot); ATF_TC_BODY(getgrgid_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRGID) == 0); } ATF_TC_WITHOUT_HEAD(getgrnam); ATF_TC_BODY(getgrnam, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRNAM) == 0); } ATF_TC_WITHOUT_HEAD(getgrnam_with_snapshot); ATF_TC_BODY(getgrnam_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRNAM) == 0); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, getgrent); ATF_TP_ADD_TC(tp, getgrent_with_snapshot); ATF_TP_ADD_TC(tp, getgrent_with_two_pass); ATF_TP_ADD_TC(tp, getgrgid); ATF_TP_ADD_TC(tp, getgrgid_with_snapshot); ATF_TP_ADD_TC(tp, getgrnam); ATF_TP_ADD_TC(tp, getgrnam_with_snapshot); return (atf_no_error()); } Index: stable/11/lib/libc/tests/nss/gethostby_test.c =================================================================== --- stable/11/lib/libc/tests/nss/gethostby_test.c (revision 319298) +++ stable/11/lib/libc/tests/nss/gethostby_test.c (revision 319299) @@ -1,1506 +1,1505 @@ /*- * Copyright (c) 2006 Michael Bushkov * All rights reserved. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include "freebsd_test_suite/macros.h" #include "testutil.h" enum test_methods { TEST_GETHOSTBYNAME2, TEST_GETHOSTBYADDR, TEST_GETHOSTBYNAME2_GETADDRINFO, TEST_GETHOSTBYADDR_GETNAMEINFO, TEST_BUILD_SNAPSHOT, TEST_BUILD_ADDR_SNAPSHOT }; static int ipnode_flags = 0; static int af_type = AF_INET; static bool use_ipnode_functions; DECLARE_TEST_DATA(hostent) DECLARE_TEST_FILE_SNAPSHOT(hostent) DECLARE_1PASS_TEST(hostent) DECLARE_2PASS_TEST(hostent) /* These stubs will use gethostby***() or getipnodeby***() functions, * depending on the use_ipnode_functions global variable value */ static struct hostent *__gethostbyname2(const char *, int); static struct hostent *__gethostbyaddr(const void *, socklen_t, int); static void __freehostent(struct hostent *); static void clone_hostent(struct hostent *, struct hostent const *); static int compare_hostent(struct hostent *, struct hostent *, void *); static void dump_hostent(struct hostent *); static void free_hostent(struct hostent *); static int is_hostent_equal(struct hostent *, struct addrinfo *); static void sdump_hostent(struct hostent *, char *, size_t); static int hostent_read_hostlist_func(struct hostent *, char *); static int hostent_read_snapshot_addr(char *, unsigned char *, size_t); static int hostent_read_snapshot_func(struct hostent *, char *); static int hostent_test_correctness(struct hostent *, void *); static int hostent_test_gethostbyaddr(struct hostent *, void *); static int hostent_test_getaddrinfo_eq(struct hostent *, void *); static int hostent_test_getnameinfo_eq(struct hostent *, void *); -static void usage(void) __attribute__((__noreturn__)); - IMPLEMENT_TEST_DATA(hostent) IMPLEMENT_TEST_FILE_SNAPSHOT(hostent) IMPLEMENT_1PASS_TEST(hostent) IMPLEMENT_2PASS_TEST(hostent) static struct hostent * __gethostbyname2(const char *name, int af) { struct hostent *he; int error; if (use_ipnode_functions) { error = 0; he = getipnodebyname(name, af, ipnode_flags, &error); if (he == NULL) errno = error; } else he = gethostbyname2(name, af); return (he); } static struct hostent * __gethostbyaddr(const void *addr, socklen_t len, int af) { struct hostent *he; int error; if (use_ipnode_functions) { error = 0; he = getipnodebyaddr(addr, len, af, &error); if (he == NULL) errno = error; } else he = gethostbyaddr(addr, len, af); return (he); } static void __freehostent(struct hostent *he) { /* NOTE: checking for he != NULL - just in case */ if (use_ipnode_functions && he != NULL) freehostent(he); } static void clone_hostent(struct hostent *dest, struct hostent const *src) { ATF_REQUIRE(dest != NULL); ATF_REQUIRE(src != NULL); char **cp; int aliases_num; int addrs_num; size_t offset; memset(dest, 0, sizeof(struct hostent)); if (src->h_name != NULL) { dest->h_name = strdup(src->h_name); ATF_REQUIRE(dest->h_name != NULL); } dest->h_addrtype = src->h_addrtype; dest->h_length = src->h_length; if (src->h_aliases != NULL) { aliases_num = 0; for (cp = src->h_aliases; *cp; ++cp) ++aliases_num; - dest->h_aliases = calloc(1, (aliases_num + 1) * - sizeof(char *)); + dest->h_aliases = calloc(aliases_num + 1, sizeof(char *)); ATF_REQUIRE(dest->h_aliases != NULL); for (cp = src->h_aliases; *cp; ++cp) { dest->h_aliases[cp - src->h_aliases] = strdup(*cp); ATF_REQUIRE(dest->h_aliases[cp - src->h_aliases] != NULL); } } if (src->h_addr_list != NULL) { addrs_num = 0; for (cp = src->h_addr_list; *cp; ++cp) ++addrs_num; - dest->h_addr_list = calloc(1, (addrs_num + 1) * sizeof(char *)); + dest->h_addr_list = calloc(addrs_num + 1, sizeof(char *)); ATF_REQUIRE(dest->h_addr_list != NULL); for (cp = src->h_addr_list; *cp; ++cp) { offset = cp - src->h_addr_list; dest->h_addr_list[offset] = malloc(src->h_length); ATF_REQUIRE(dest->h_addr_list[offset] != NULL); memcpy(dest->h_addr_list[offset], src->h_addr_list[offset], src->h_length); } } } static void free_hostent(struct hostent *ht) { char **cp; ATF_REQUIRE(ht != NULL); free(ht->h_name); if (ht->h_aliases != NULL) { for (cp = ht->h_aliases; *cp; ++cp) free(*cp); free(ht->h_aliases); } if (ht->h_addr_list != NULL) { for (cp = ht->h_addr_list; *cp; ++cp) free(*cp); free(ht->h_addr_list); } } static int compare_hostent(struct hostent *ht1, struct hostent *ht2, void *mdata) { char **c1, **c2, **ct, **cb; int b; if (ht1 == ht2) return 0; if (ht1 == NULL || ht2 == NULL) goto errfin; if (ht1->h_name == NULL || ht2->h_name == NULL) goto errfin; if (ht1->h_addrtype != ht2->h_addrtype || ht1->h_length != ht2->h_length || strcmp(ht1->h_name, ht2->h_name) != 0) goto errfin; c1 = ht1->h_aliases; c2 = ht2->h_aliases; if ((ht1->h_aliases == NULL || ht2->h_aliases == NULL) && ht1->h_aliases != ht2->h_aliases) goto errfin; if (c1 != NULL && c2 != NULL) { cb = c1; for (;*c1; ++c1) { b = 0; for (ct = c2; *ct; ++ct) { if (strcmp(*c1, *ct) == 0) { b = 1; break; } } if (b == 0) { printf("h1 aliases item can't be found in h2 " "aliases\n"); goto errfin; } } c1 = cb; for (;*c2; ++c2) { b = 0; for (ct = c1; *ct; ++ct) { if (strcmp(*c2, *ct) == 0) { b = 1; break; } } if (b == 0) { printf("h2 aliases item can't be found in h1 " "aliases\n"); goto errfin; } } } c1 = ht1->h_addr_list; c2 = ht2->h_addr_list; if ((ht1->h_addr_list == NULL || ht2->h_addr_list== NULL) && ht1->h_addr_list != ht2->h_addr_list) goto errfin; if (c1 != NULL && c2 != NULL) { cb = c1; for (; *c1; ++c1) { b = 0; for (ct = c2; *ct; ++ct) { if (memcmp(*c1, *ct, ht1->h_length) == 0) { b = 1; break; } } if (b == 0) { printf("h1 addresses item can't be found in " "h2 addresses\n"); goto errfin; } } c1 = cb; for (; *c2; ++c2) { b = 0; for (ct = c1; *ct; ++ct) { if (memcmp(*c2, *ct, ht1->h_length) == 0) { b = 1; break; } } if (b == 0) { printf("h2 addresses item can't be found in " "h1 addresses\n"); goto errfin; } } } return 0; errfin: if (mdata == NULL) { printf("following structures are not equal:\n"); dump_hostent(ht1); dump_hostent(ht2); } return (-1); } static int check_addrinfo_for_name(struct addrinfo *ai, char const *name) { struct addrinfo *ai2; for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) { if (strcmp(ai2->ai_canonname, name) == 0) return (0); } return (-1); } static int check_addrinfo_for_addr(struct addrinfo *ai, char const *addr, socklen_t addrlen, int af) { struct addrinfo *ai2; for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) { if (af != ai2->ai_family) continue; switch (af) { case AF_INET: if (memcmp(addr, (void *)&((struct sockaddr_in *)ai2->ai_addr)->sin_addr, MIN(addrlen, ai2->ai_addrlen)) == 0) return (0); break; case AF_INET6: if (memcmp(addr, (void *)&((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr, MIN(addrlen, ai2->ai_addrlen)) == 0) return (0); break; default: break; } } return (-1); } static int is_hostent_equal(struct hostent *he, struct addrinfo *ai) { char **cp; int rv; #ifdef DEBUG printf("checking equality of he and ai\n"); #endif rv = check_addrinfo_for_name(ai, he->h_name); if (rv != 0) { printf("not equal - he->h_name couldn't be found\n"); return (rv); } for (cp = he->h_addr_list; *cp; ++cp) { rv = check_addrinfo_for_addr(ai, *cp, he->h_length, he->h_addrtype); if (rv != 0) { printf("not equal - one of he->h_addr_list couldn't be found\n"); return (rv); } } #ifdef DEBUG printf("equal\n"); #endif return (0); } static void sdump_hostent(struct hostent *ht, char *buffer, size_t buflen) { char **cp; size_t i; int written; written = snprintf(buffer, buflen, "%s %d %d", ht->h_name, ht->h_addrtype, ht->h_length); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; if (ht->h_aliases != NULL) { if (*(ht->h_aliases) != NULL) { for (cp = ht->h_aliases; *cp; ++cp) { written = snprintf(buffer, buflen, " %s",*cp); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; if (buflen == 0) return; } } else { written = snprintf(buffer, buflen, " noaliases"); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; } } else { written = snprintf(buffer, buflen, " (null)"); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; } written = snprintf(buffer, buflen, " : "); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; if (ht->h_addr_list != NULL) { if (*(ht->h_addr_list) != NULL) { for (cp = ht->h_addr_list; *cp; ++cp) { - for (i = 0; i < ht->h_length; ++i ) { - written = snprintf(buffer, buflen, - i + 1 != ht->h_length ? "%d." : "%d", - (unsigned char)(*cp)[i]); - buffer += written; - if (written > buflen) - return; - buflen -= written; + for (i = 0; i < (size_t)ht->h_length; ++i) { + written = snprintf(buffer, buflen, + i + 1 != (size_t)ht->h_length ? + "%d." : "%d", + (unsigned char)(*cp)[i]); + buffer += written; + if (written > (int)buflen) + return; + buflen -= written; - if (buflen == 0) - return; - } + if (buflen == 0) + return; + } - if (*(cp + 1) ) { - written = snprintf(buffer, buflen, " "); - buffer += written; - if (written > buflen) - return; - buflen -= written; - } + if (*(cp + 1)) { + written = snprintf(buffer, buflen, + " "); + buffer += written; + if (written > (int)buflen) + return; + buflen -= written; + } } } else { written = snprintf(buffer, buflen, " noaddrs"); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; } } else { written = snprintf(buffer, buflen, " (null)"); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; } } static int hostent_read_hostlist_func(struct hostent *he, char *line) { struct hostent *result; int rv; #ifdef DEBUG printf("resolving %s: ", line); #endif result = __gethostbyname2(line, af_type); if (result != NULL) { #ifdef DEBUG printf("found\n"); #endif rv = hostent_test_correctness(result, NULL); if (rv != 0) { __freehostent(result); return (rv); } clone_hostent(he, result); __freehostent(result); } else { #ifdef DEBUG printf("not found\n"); #endif memset(he, 0, sizeof(struct hostent)); he->h_name = strdup(line); ATF_REQUIRE(he->h_name != NULL); } return (0); } static int hostent_read_snapshot_addr(char *addr, unsigned char *result, size_t len) { char *s, *ps, *ts; ps = addr; while ( (s = strsep(&ps, ".")) != NULL) { if (len == 0) return (-1); *result = (unsigned char)strtol(s, &ts, 10); ++result; if (*ts != '\0') return (-1); --len; } if (len != 0) return (-1); else return (0); } static int hostent_read_snapshot_func(struct hostent *ht, char *line) { StringList *sl1, *sl2; char *s, *ps, *ts; int i, rv; #ifdef DEBUG printf("1 line read from snapshot:\n%s\n", line); #endif rv = 0; i = 0; sl1 = sl2 = NULL; ps = line; memset(ht, 0, sizeof(struct hostent)); while ((s = strsep(&ps, " ")) != NULL) { switch (i) { case 0: ht->h_name = strdup(s); ATF_REQUIRE(ht->h_name != NULL); break; case 1: ht->h_addrtype = (int)strtol(s, &ts, 10); if (*ts != '\0') goto fin; break; case 2: ht->h_length = (int)strtol(s, &ts, 10); if (*ts != '\0') goto fin; break; case 3: if (sl1 == NULL) { if (strcmp(s, "(null)") == 0) return (0); sl1 = sl_init(); ATF_REQUIRE(sl1 != NULL); if (strcmp(s, "noaliases") != 0) { ts = strdup(s); ATF_REQUIRE(ts != NULL); sl_add(sl1, ts); } } else { if (strcmp(s, ":") == 0) ++i; else { ts = strdup(s); ATF_REQUIRE(ts != NULL); sl_add(sl1, ts); } } break; case 4: if (sl2 == NULL) { if (strcmp(s, "(null)") == 0) return (0); sl2 = sl_init(); ATF_REQUIRE(sl2 != NULL); if (strcmp(s, "noaddrs") != 0) { ts = calloc(1, ht->h_length); ATF_REQUIRE(ts != NULL); rv = hostent_read_snapshot_addr(s, (unsigned char *)ts, ht->h_length); sl_add(sl2, ts); if (rv != 0) goto fin; } } else { ts = calloc(1, ht->h_length); ATF_REQUIRE(ts != NULL); rv = hostent_read_snapshot_addr(s, (unsigned char *)ts, ht->h_length); sl_add(sl2, ts); if (rv != 0) goto fin; } break; default: break; } if (i != 3 && i != 4) ++i; } fin: if (sl1 != NULL) { sl_add(sl1, NULL); ht->h_aliases = sl1->sl_str; } if (sl2 != NULL) { sl_add(sl2, NULL); ht->h_addr_list = sl2->sl_str; } if ((i != 4) || (rv != 0)) { free_hostent(ht); memset(ht, 0, sizeof(struct hostent)); return (-1); } /* NOTE: is it a dirty hack or not? */ free(sl1); free(sl2); return (0); } static void dump_hostent(struct hostent *result) { if (result != NULL) { char buffer[1024]; sdump_hostent(result, buffer, sizeof(buffer)); printf("%s\n", buffer); } else printf("(null)\n"); } static int -hostent_test_correctness(struct hostent *ht, void *mdata) +hostent_test_correctness(struct hostent *ht, void *mdata __unused) { #ifdef DEBUG printf("testing correctness with the following data:\n"); dump_hostent(ht); #endif if (ht == NULL) goto errfin; if (ht->h_name == NULL) goto errfin; if (!((ht->h_addrtype >= 0) && (ht->h_addrtype < AF_MAX))) goto errfin; if ((ht->h_length != sizeof(struct in_addr)) && (ht->h_length != sizeof(struct in6_addr))) goto errfin; if (ht->h_aliases == NULL) goto errfin; if (ht->h_addr_list == NULL) goto errfin; #ifdef DEBUG printf("correct\n"); #endif return (0); errfin: printf("incorrect\n"); return (-1); } static int hostent_test_gethostbyaddr(struct hostent *he, void *mdata) { struct hostent *result; struct hostent_test_data *addr_test_data; int rv; addr_test_data = (struct hostent_test_data *)mdata; /* We should omit unresolved hostents */ if (he->h_addr_list != NULL) { char **cp; for (cp = he->h_addr_list; *cp; ++cp) { #ifdef DEBUG printf("doing reverse lookup for %s\n", he->h_name); #endif result = __gethostbyaddr(*cp, he->h_length, he->h_addrtype); if (result == NULL) { #ifdef DEBUG printf("%s: warning: reverse lookup failed " "for %s: %s\n", __func__, he->h_name, strerror(errno)); #endif continue; } rv = hostent_test_correctness(result, NULL); if (rv != 0) { __freehostent(result); return (rv); } if (addr_test_data != NULL) TEST_DATA_APPEND(hostent, addr_test_data, result); __freehostent(result); } } return (0); } static int -hostent_test_getaddrinfo_eq(struct hostent *he, void *mdata) +hostent_test_getaddrinfo_eq(struct hostent *he, void *mdata __unused) { struct addrinfo *ai, hints; int rv; ai = NULL; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = af_type; hints.ai_flags = AI_CANONNAME; printf("using getaddrinfo() to resolve %s\n", he->h_name); /* struct hostent *he was not resolved */ if (he->h_addr_list == NULL) { /* We can be sure that he->h_name is not NULL */ rv = getaddrinfo(he->h_name, NULL, &hints, &ai); if (rv == 0) { printf("not ok - shouldn't have been resolved\n"); return (-1); } } else { rv = getaddrinfo(he->h_name, NULL, &hints, &ai); if (rv != 0) { printf("not ok - should have been resolved\n"); return (-1); } rv = is_hostent_equal(he, ai); if (rv != 0) { printf("not ok - addrinfo and hostent are not equal\n"); return (-1); } } return (0); } static int -hostent_test_getnameinfo_eq(struct hostent *he, void *mdata) +hostent_test_getnameinfo_eq(struct hostent *he, void *mdata __unused) { char **cp; char buffer[NI_MAXHOST]; struct sockaddr_in sin; struct sockaddr_in6 sin6; struct sockaddr *saddr; struct hostent *result; int i, rv; if (he->h_addr_list == NULL) return (0); for (cp = he->h_addr_list; *cp; ++cp) { #ifdef DEBUG printf("doing reverse lookup for %s\n", he->h_name); #endif result = __gethostbyaddr(*cp, he->h_length, he->h_addrtype); if (result != NULL) { rv = hostent_test_correctness(result, NULL); if (rv != 0) { __freehostent(result); return (rv); } } else printf("%s: warning: reverse lookup failed " "for %s: %s\n", __func__, he->h_name, strerror(errno)); switch (he->h_addrtype) { case AF_INET: memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_len = sizeof(struct sockaddr_in); sin.sin_family = AF_INET; memcpy(&sin.sin_addr, *cp, he->h_length); saddr = (struct sockaddr *)&sin; break; case AF_INET6: memset(&sin6, 0, sizeof(struct sockaddr_in6)); sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; memcpy(&sin6.sin6_addr, *cp, he->h_length); saddr = (struct sockaddr *)&sin6; break; default: printf("warning: %d family is unsupported\n", he->h_addrtype); continue; } ATF_REQUIRE(saddr != NULL); rv = getnameinfo(saddr, saddr->sa_len, buffer, sizeof(buffer), NULL, 0, NI_NAMEREQD); if (rv != 0 && result != NULL) { printf("getnameinfo() didn't make the reverse " "lookup, when it should have (%s)\n", gai_strerror(rv)); return (rv); } if (rv == 0 && result == NULL) { printf("getnameinfo() made the " "reverse lookup, when it shouldn't have\n"); return (rv); } if (rv != 0 && result == NULL) { #ifdef DEBUG printf("both getnameinfo() and ***byaddr() failed as " "expected\n"); #endif continue; } #ifdef DEBUG printf("comparing %s with %s\n", result->h_name, buffer); #endif /* * An address might reverse resolve to hostname alias or the * official hostname, e.g. moon.vub.ac.be. */ bool found_a_match; if (strcmp(result->h_name, buffer) == 0) { found_a_match = true; #ifdef DEBUG printf("matched official hostname\n"); #endif } else { for (i = 0; result->h_aliases[i] != NULL; i++) { printf("[%d] resolved: %s\n", i, result->h_aliases[i]); if (strcmp(result->h_aliases[i], buffer) == 0) { printf("matched hostname alias\n"); found_a_match = true; break; } } } __freehostent(result); if (found_a_match) { #ifdef DEBUG printf("getnameinfo() and ***byaddr() results are " "equal\n"); #endif } else { printf("getnameinfo() and ***byaddr() results are not " "equal for %s\n", he->h_name); return (-1); } } return (0); } -int -run_tests(const char *hostlist_file, const char *snapshot_file, int af_type, +static int +run_tests(const char *hostlist_file, const char *snapshot_file, int _af_type, enum test_methods method, bool use_ipv6_mapping) { struct hostent_test_data td, td_addr, td_snap; res_state statp; int rv = -2; - switch (af_type) { + switch (_af_type) { case AF_INET: ATF_REQUIRE_FEATURE("inet"); ATF_REQUIRE(!use_ipv6_mapping); break; case AF_INET6: ATF_REQUIRE_FEATURE("inet6"); break; default: - atf_tc_fail("unhandled address family: %d", af_type); + atf_tc_fail("unhandled address family: %d", _af_type); break; } if (!use_ipnode_functions) { statp = __res_state(); if (statp == NULL || ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1)) { printf("error: can't init res_state\n"); return (-1); } if (use_ipv6_mapping) statp->options |= RES_USE_INET6; else statp->options &= ~RES_USE_INET6; } TEST_DATA_INIT(hostent, &td, clone_hostent, free_hostent); TEST_DATA_INIT(hostent, &td_addr, clone_hostent, free_hostent); TEST_DATA_INIT(hostent, &td_snap, clone_hostent, free_hostent); if (access(hostlist_file, R_OK) != 0) { printf("can't access the hostlist file %s\n", hostlist_file); rv = -1; goto fin; } #ifdef DEBUG printf("building host lists from %s\n", hostlist_file); #endif rv = TEST_SNAPSHOT_FILE_READ(hostent, hostlist_file, &td, hostent_read_hostlist_func); if (rv != 0) { printf("failed to read the host list file: %s\n", hostlist_file); goto fin; } if (snapshot_file != NULL) { if (access(snapshot_file, W_OK | R_OK) != 0) { if (errno == ENOENT) { if (method != TEST_GETHOSTBYADDR) method = TEST_BUILD_SNAPSHOT; else method = TEST_BUILD_ADDR_SNAPSHOT; } else { printf("can't access the snapshot file %s\n", snapshot_file); rv = -1; goto fin; } } else { rv = TEST_SNAPSHOT_FILE_READ(hostent, snapshot_file, &td_snap, hostent_read_snapshot_func); if (rv != 0) { printf("error reading snapshot file\n"); goto fin; } } } switch (method) { case TEST_GETHOSTBYNAME2: if (snapshot_file != NULL) rv = DO_2PASS_TEST(hostent, &td, &td_snap, compare_hostent, NULL); break; case TEST_GETHOSTBYADDR: rv = DO_1PASS_TEST(hostent, &td, hostent_test_gethostbyaddr, (void *)&td_addr); if (rv != 0) goto fin; if (snapshot_file != NULL) rv = DO_2PASS_TEST(hostent, &td_addr, &td_snap, compare_hostent, NULL); break; case TEST_GETHOSTBYNAME2_GETADDRINFO: rv = DO_1PASS_TEST(hostent, &td, hostent_test_getaddrinfo_eq, NULL); break; case TEST_GETHOSTBYADDR_GETNAMEINFO: rv = DO_1PASS_TEST(hostent, &td, hostent_test_getnameinfo_eq, NULL); break; case TEST_BUILD_SNAPSHOT: if (snapshot_file != NULL) { rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file, &td, sdump_hostent); } break; case TEST_BUILD_ADDR_SNAPSHOT: if (snapshot_file != NULL) { rv = DO_1PASS_TEST(hostent, &td, hostent_test_gethostbyaddr, (void *)&td_addr); if (rv != 0) goto fin; rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file, &td_addr, sdump_hostent); } break; default: rv = 0; break; } fin: TEST_DATA_DESTROY(hostent, &td_snap); TEST_DATA_DESTROY(hostent, &td_addr); TEST_DATA_DESTROY(hostent, &td); return (rv); } #define HOSTLIST_FILE "mach" #define _RUN_TESTS(tc, snapshot_file, af_type, method, use_ipv6_mapping) \ do { \ char *_hostlist_file; \ char *_snapshot_file; \ ATF_REQUIRE(0 < asprintf(&_hostlist_file, "%s/%s", \ atf_tc_get_config_var(tc, "srcdir"), HOSTLIST_FILE)); \ if (snapshot_file == NULL) \ _snapshot_file = NULL; \ else { \ _snapshot_file = strdup(snapshot_file); \ ATF_REQUIRE(_snapshot_file != NULL); \ } \ ATF_REQUIRE(run_tests(_hostlist_file, _snapshot_file, af_type, \ method, use_ipv6_mapping) == 0); \ } while(0) #define RUN_HOST_TESTS(tc, snapshot_file, af_type, method, use_ipv6_mapping) \ do { \ use_ipnode_functions = false; \ _RUN_TESTS(tc, snapshot_file, af_type, method, use_ipv6_mapping); \ } while(0) #define RUN_IPNODE_TESTS(tc, snapshot_file, af_type, method, use_ipv6_mapping) \ do { \ use_ipnode_functions = true; \ _RUN_TESTS(tc, snapshot_file, af_type, method, use_ipv6_mapping); \ } while(0) ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv4); ATF_TC_BODY(gethostbyaddr_ipv4, tc) { RUN_HOST_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYADDR, false); } ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv4_with_snapshot); ATF_TC_BODY(gethostbyaddr_ipv4_with_snapshot, tc) { RUN_HOST_TESTS(tc, "snapshot_htaddr4", AF_INET, TEST_GETHOSTBYADDR, false); } ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv6); ATF_TC_BODY(gethostbyaddr_ipv6, tc) { RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, false); } ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv6_AI_V4MAPPED); ATF_TC_BODY(gethostbyaddr_ipv6_AI_V4MAPPED, tc) { ipnode_flags = AI_V4MAPPED; RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, true); } ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv6_with_snapshot); ATF_TC_BODY(gethostbyaddr_ipv6_with_snapshot, tc) { RUN_HOST_TESTS(tc, "snapshot_htaddr6", AF_INET6, TEST_GETHOSTBYADDR, false); } ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv6_with_snapshot_AI_V4MAPPED); ATF_TC_BODY(gethostbyaddr_ipv6_with_snapshot_AI_V4MAPPED, tc) { ipnode_flags = AI_V4MAPPED; RUN_HOST_TESTS(tc, "snapshot_htaddr6map", AF_INET6, TEST_GETHOSTBYADDR, true); } ATF_TC_WITHOUT_HEAD(gethostbyname2_getaddrinfo_ipv4); ATF_TC_BODY(gethostbyname2_getaddrinfo_ipv4, tc) { RUN_HOST_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYNAME2_GETADDRINFO, false); } ATF_TC_WITHOUT_HEAD(gethostbyname2_getaddrinfo_ipv6); ATF_TC_BODY(gethostbyname2_getaddrinfo_ipv6, tc) { RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2_GETADDRINFO, false); } ATF_TC_WITHOUT_HEAD(gethostbyaddr_getnameinfo_ipv4); ATF_TC_BODY(gethostbyaddr_getnameinfo_ipv4, tc) { RUN_HOST_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYADDR_GETNAMEINFO, false); } ATF_TC_WITHOUT_HEAD(gethostbyaddr_getnameinfo_ipv6); ATF_TC_BODY(gethostbyaddr_getnameinfo_ipv6, tc) { RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR_GETNAMEINFO, false); } ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv4); ATF_TC_BODY(gethostbyname2_ipv4, tc) { RUN_HOST_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv4_with_snapshot); ATF_TC_BODY(gethostbyname2_ipv4_with_snapshot, tc) { RUN_HOST_TESTS(tc, "snapshot_htname4", AF_INET, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv6); ATF_TC_BODY(gethostbyname2_ipv6, tc) { RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv6_AI_V4MAPPED); ATF_TC_BODY(gethostbyname2_ipv6_AI_V4MAPPED, tc) { ipnode_flags = AI_V4MAPPED; RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, true); } ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv6_with_snapshot); ATF_TC_BODY(gethostbyname2_ipv6_with_snapshot, tc) { RUN_HOST_TESTS(tc, "snapshot_htname6", AF_INET6, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv6_with_snapshot_AI_V4MAPPED); ATF_TC_BODY(gethostbyname2_ipv6_with_snapshot_AI_V4MAPPED, tc) { ipnode_flags = AI_V4MAPPED; RUN_HOST_TESTS(tc, "snapshot_htname6map", AF_INET6, TEST_GETHOSTBYNAME2, true); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv4); ATF_TC_BODY(getipnodebyaddr_ipv4, tc) { RUN_IPNODE_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYADDR, false); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv4_with_snapshot); ATF_TC_BODY(getipnodebyaddr_ipv4_with_snapshot, tc) { RUN_IPNODE_TESTS(tc, "snapshot_ipnodeaddr4", AF_INET, TEST_GETHOSTBYADDR, false); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_getnameinfo_ipv4); ATF_TC_BODY(getipnodebyaddr_getnameinfo_ipv4, tc) { RUN_IPNODE_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYADDR_GETNAMEINFO, false); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6); ATF_TC_BODY(getipnodebyaddr_ipv6, tc) { RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, false); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_AI_V4MAPPED); ATF_TC_BODY(getipnodebyaddr_ipv6_AI_V4MAPPED, tc) { ipnode_flags = AI_V4MAPPED; RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, true); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_AI_V4MAPPED_CFG); ATF_TC_BODY(getipnodebyaddr_ipv6_AI_V4MAPPED_CFG, tc) { ipnode_flags = AI_V4MAPPED_CFG; RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, true); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_AI_V4MAPPED_CFG_AI_ALL); ATF_TC_BODY(getipnodebyaddr_ipv6_AI_V4MAPPED_CFG_AI_ALL, tc) { ipnode_flags = AI_V4MAPPED_CFG | AI_ALL; RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, true); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_with_snapshot); ATF_TC_BODY(getipnodebyaddr_ipv6_with_snapshot, tc) { RUN_IPNODE_TESTS(tc, "snapshot_ipnodeaddr6", AF_INET6, TEST_GETHOSTBYADDR, false); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED); ATF_TC_BODY(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED, tc) { ipnode_flags = AI_V4MAPPED; RUN_IPNODE_TESTS(tc, "snapshot_ipnodeaddr6_AI_V4MAPPED", AF_INET6, TEST_GETHOSTBYADDR, true); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG); ATF_TC_BODY(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG, tc) { ipnode_flags = AI_V4MAPPED_CFG; RUN_IPNODE_TESTS(tc, "snapshot_ipnodeaddr6_AI_V4MAPPED_CFG", AF_INET6, TEST_GETHOSTBYADDR, true); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL); ATF_TC_BODY(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL, tc) { ipnode_flags = AI_V4MAPPED_CFG | AI_ALL; RUN_IPNODE_TESTS(tc, "snapshot_ipnodeaddr6_AI_V4MAPPED_CFG_AI_ALL", AF_INET6, TEST_GETHOSTBYADDR, true); } ATF_TC_WITHOUT_HEAD(getipnodebyaddr_getnameinfo_ipv6); ATF_TC_BODY(getipnodebyaddr_getnameinfo_ipv6, tc) { RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR_GETNAMEINFO, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv4); ATF_TC_BODY(getipnodebyname_ipv4, tc) { RUN_IPNODE_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv4_with_snapshot); ATF_TC_BODY(getipnodebyname_ipv4_with_snapshot, tc) { RUN_IPNODE_TESTS(tc, "snapshot_ipnodename4", AF_INET, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv4_AI_ADDRCONFIG); ATF_TC_BODY(getipnodebyname_ipv4_AI_ADDRCONFIG, tc) { ipnode_flags = AI_ADDRCONFIG; RUN_IPNODE_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv4_with_snapshot_AI_ADDRCONFIG); ATF_TC_BODY(getipnodebyname_ipv4_with_snapshot_AI_ADDRCONFIG, tc) { ipnode_flags = AI_ADDRCONFIG; RUN_IPNODE_TESTS(tc, "snapshot_ipnodename4_AI_ADDRCONFIG", AF_INET, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_getaddrinfo_ipv4); ATF_TC_BODY(getipnodebyname_getaddrinfo_ipv4, tc) { RUN_IPNODE_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYNAME2_GETADDRINFO, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6); ATF_TC_BODY(getipnodebyname_ipv6, tc) { RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot); ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot, tc) { RUN_IPNODE_TESTS(tc, "snapshot_ipnodename6", AF_INET6, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_AI_ADDRCONFIG); ATF_TC_BODY(getipnodebyname_ipv6_AI_ADDRCONFIG, tc) { ipnode_flags = AI_ADDRCONFIG; RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_AI_V4MAPPED); ATF_TC_BODY(getipnodebyname_ipv6_AI_V4MAPPED, tc) { ipnode_flags = AI_V4MAPPED; RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, true); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_AI_V4MAPPED_CFG); ATF_TC_BODY(getipnodebyname_ipv6_AI_V4MAPPED_CFG, tc) { ipnode_flags = AI_V4MAPPED_CFG; RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, true); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ADDRCONFIG); ATF_TC_BODY(getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ADDRCONFIG, tc) { ipnode_flags = AI_V4MAPPED_CFG | AI_ADDRCONFIG; RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ALL); ATF_TC_BODY(getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ALL, tc) { ipnode_flags = AI_V4MAPPED_CFG | AI_ALL; RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, true); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED); ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED, tc) { ipnode_flags = AI_V4MAPPED; RUN_IPNODE_TESTS(tc, "snapshot_ipnodename6_AI_V4MAPPED", AF_INET6, TEST_GETHOSTBYNAME2, true); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG); ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG, tc) { ipnode_flags = AI_V4MAPPED_CFG; RUN_IPNODE_TESTS(tc, "snapshot_ipnodename6_AI_V4MAPPED_CFG", AF_INET6, TEST_GETHOSTBYNAME2, true); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ADDRCONFIG); ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ADDRCONFIG, tc) { ipnode_flags = AI_V4MAPPED_CFG | AI_ADDRCONFIG; RUN_IPNODE_TESTS(tc, "snapshot_ipnodename6_AI_V4MAPPED_CFG_AI_ADDRCONFIG", AF_INET6, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL); ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL, tc) { ipnode_flags = AI_V4MAPPED_CFG | AI_ALL; RUN_IPNODE_TESTS(tc, "snapshot_ipnodename6_AI_V4MAPPED_CFG_AI_ALL", AF_INET6, TEST_GETHOSTBYNAME2, true); } ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot_AI_ADDRCONFIG); ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot_AI_ADDRCONFIG, tc) { ipnode_flags = AI_ADDRCONFIG; RUN_IPNODE_TESTS(tc, "snapshot_ipnodename6_AI_ADDRCONFIG", AF_INET6, TEST_GETHOSTBYNAME2, false); } ATF_TC_WITHOUT_HEAD(getipnodebyname_getaddrinfo_ipv6); ATF_TC_BODY(getipnodebyname_getaddrinfo_ipv6, tc) { RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2_GETADDRINFO, false); } ATF_TP_ADD_TCS(tp) { /* gethostbyaddr */ ATF_TP_ADD_TC(tp, gethostbyaddr_ipv4); ATF_TP_ADD_TC(tp, gethostbyaddr_ipv4_with_snapshot); ATF_TP_ADD_TC(tp, gethostbyaddr_ipv6); ATF_TP_ADD_TC(tp, gethostbyaddr_ipv6_AI_V4MAPPED); /* XXX */ ATF_TP_ADD_TC(tp, gethostbyaddr_ipv6_with_snapshot); ATF_TP_ADD_TC(tp, gethostbyaddr_ipv6_with_snapshot_AI_V4MAPPED); ATF_TP_ADD_TC(tp, gethostbyaddr_getnameinfo_ipv4); ATF_TP_ADD_TC(tp, gethostbyaddr_getnameinfo_ipv6); /* gethostbyname2 */ ATF_TP_ADD_TC(tp, gethostbyname2_getaddrinfo_ipv4); ATF_TP_ADD_TC(tp, gethostbyname2_getaddrinfo_ipv6); ATF_TP_ADD_TC(tp, gethostbyname2_ipv4); ATF_TP_ADD_TC(tp, gethostbyname2_ipv4_with_snapshot); ATF_TP_ADD_TC(tp, gethostbyname2_ipv6); ATF_TP_ADD_TC(tp, gethostbyname2_ipv6_AI_V4MAPPED); ATF_TP_ADD_TC(tp, gethostbyname2_ipv6_with_snapshot); ATF_TP_ADD_TC(tp, gethostbyname2_ipv6_with_snapshot_AI_V4MAPPED); /* getipnodebyaddr */ ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv4); ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv4_with_snapshot); ATF_TP_ADD_TC(tp, getipnodebyaddr_getnameinfo_ipv4); ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6); ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_AI_V4MAPPED); ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_AI_V4MAPPED_CFG); ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_AI_V4MAPPED_CFG_AI_ALL); ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_with_snapshot); ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED); ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG); ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL); ATF_TP_ADD_TC(tp, getipnodebyaddr_getnameinfo_ipv6); /* getipnodebyname */ ATF_TP_ADD_TC(tp, getipnodebyname_ipv4); ATF_TP_ADD_TC(tp, getipnodebyname_ipv4_with_snapshot); ATF_TP_ADD_TC(tp, getipnodebyname_ipv4_AI_ADDRCONFIG); ATF_TP_ADD_TC(tp, getipnodebyname_ipv4_with_snapshot_AI_ADDRCONFIG); ATF_TP_ADD_TC(tp, getipnodebyname_getaddrinfo_ipv4); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_AI_ADDRCONFIG); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_AI_V4MAPPED); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_AI_V4MAPPED_CFG); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ADDRCONFIG); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ALL); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ADDRCONFIG); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL); ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot_AI_ADDRCONFIG); ATF_TP_ADD_TC(tp, getipnodebyname_getaddrinfo_ipv6); return (atf_no_error()); } Index: stable/11/lib/libc/tests/nss/getproto_test.c =================================================================== --- stable/11/lib/libc/tests/nss/getproto_test.c (revision 319298) +++ stable/11/lib/libc/tests/nss/getproto_test.c (revision 319299) @@ -1,556 +1,556 @@ /*- * Copyright (c) 2006 Michael Bushkov * All rights reserved. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include "testutil.h" enum test_methods { TEST_GETPROTOENT, TEST_GETPROTOBYNAME, TEST_GETPROTOBYNUMBER, TEST_GETPROTOENT_2PASS, TEST_BUILD_SNAPSHOT }; DECLARE_TEST_DATA(protoent) DECLARE_TEST_FILE_SNAPSHOT(protoent) DECLARE_1PASS_TEST(protoent) DECLARE_2PASS_TEST(protoent) static void clone_protoent(struct protoent *, struct protoent const *); static int compare_protoent(struct protoent *, struct protoent *, void *); static void dump_protoent(struct protoent *); static void free_protoent(struct protoent *); static void sdump_protoent(struct protoent *, char *, size_t); static int protoent_read_snapshot_func(struct protoent *, char *); static int protoent_check_ambiguity(struct protoent_test_data *, struct protoent *); static int protoent_fill_test_data(struct protoent_test_data *); static int protoent_test_correctness(struct protoent *, void *); static int protoent_test_getprotobyname(struct protoent *, void *); static int protoent_test_getprotobynumber(struct protoent *, void *); static int protoent_test_getprotoent(struct protoent *, void *); IMPLEMENT_TEST_DATA(protoent) IMPLEMENT_TEST_FILE_SNAPSHOT(protoent) IMPLEMENT_1PASS_TEST(protoent) IMPLEMENT_2PASS_TEST(protoent) static void clone_protoent(struct protoent *dest, struct protoent const *src) { assert(dest != NULL); assert(src != NULL); char **cp; int aliases_num; memset(dest, 0, sizeof(struct protoent)); if (src->p_name != NULL) { dest->p_name = strdup(src->p_name); assert(dest->p_name != NULL); } dest->p_proto = src->p_proto; if (src->p_aliases != NULL) { aliases_num = 0; for (cp = src->p_aliases; *cp; ++cp) ++aliases_num; - dest->p_aliases = calloc(1, (aliases_num+1) * sizeof(char *)); + dest->p_aliases = calloc(aliases_num + 1, sizeof(char *)); assert(dest->p_aliases != NULL); for (cp = src->p_aliases; *cp; ++cp) { dest->p_aliases[cp - src->p_aliases] = strdup(*cp); assert(dest->p_aliases[cp - src->p_aliases] != NULL); } } } static void free_protoent(struct protoent *pe) { char **cp; assert(pe != NULL); free(pe->p_name); for (cp = pe->p_aliases; *cp; ++cp) free(*cp); free(pe->p_aliases); } static int compare_protoent(struct protoent *pe1, struct protoent *pe2, void *mdata) { char **c1, **c2; if (pe1 == pe2) return 0; if ((pe1 == NULL) || (pe2 == NULL)) goto errfin; if ((strcmp(pe1->p_name, pe2->p_name) != 0) || (pe1->p_proto != pe2->p_proto)) goto errfin; c1 = pe1->p_aliases; c2 = pe2->p_aliases; if ((pe1->p_aliases == NULL) || (pe2->p_aliases == 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 (mdata == NULL) { printf("following structures are not equal:\n"); dump_protoent(pe1); dump_protoent(pe2); } return (-1); } static void sdump_protoent(struct protoent *pe, char *buffer, size_t buflen) { char **cp; int written; written = snprintf(buffer, buflen, "%s %d", pe->p_name, pe->p_proto); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; if (pe->p_aliases != NULL) { if (*(pe->p_aliases) != '\0') { for (cp = pe->p_aliases; *cp; ++cp) { - written = snprintf(buffer, buflen, " %s",*cp); + written = snprintf(buffer, buflen, " %s", *cp); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; if (buflen == 0) return; } } else snprintf(buffer, buflen, " noaliases"); } else snprintf(buffer, buflen, " (null)"); } static int protoent_read_snapshot_func(struct protoent *pe, char *line) { StringList *sl; char *s, *ps, *ts; int i; printf("1 line read from snapshot:\n%s\n", line); i = 0; sl = NULL; ps = line; memset(pe, 0, sizeof(struct protoent)); while ( (s = strsep(&ps, " ")) != NULL) { switch (i) { case 0: pe->p_name = strdup(s); assert(pe->p_name != NULL); break; case 1: pe->p_proto = (int)strtol(s, &ts, 10); if (*ts != '\0') { free(pe->p_name); return (-1); } break; default: if (sl == NULL) { if (strcmp(s, "(null)") == 0) return (0); sl = sl_init(); assert(sl != NULL); if (strcmp(s, "noaliases") != 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(pe->p_name); memset(pe, 0, sizeof(struct protoent)); return (-1); } sl_add(sl, NULL); pe->p_aliases = sl->sl_str; /* NOTE: is it a dirty hack or not? */ free(sl); return (0); } static void dump_protoent(struct protoent *result) { if (result != NULL) { char buffer[1024]; sdump_protoent(result, buffer, sizeof(buffer)); printf("%s\n", buffer); } else printf("(null)\n"); } static int protoent_fill_test_data(struct protoent_test_data *td) { struct protoent *pe; setprotoent(1); while ((pe = getprotoent()) != NULL) { if (protoent_test_correctness(pe, NULL) == 0) TEST_DATA_APPEND(protoent, td, pe); else return (-1); } endprotoent(); return (0); } static int -protoent_test_correctness(struct protoent *pe, void *mdata) +protoent_test_correctness(struct protoent *pe, void *mdata __unused) { printf("testing correctness with the following data:\n"); dump_protoent(pe); if (pe == NULL) goto errfin; if (pe->p_name == NULL) goto errfin; if (pe->p_proto < 0) goto errfin; if (pe->p_aliases == NULL) goto errfin; printf("correct\n"); return (0); errfin: printf("incorrect\n"); return (-1); } /* protoent_check_ambiguity() is needed when one port+proto is associated with * more than one piece (these cases are usually marked as PROBLEM in * /etc/peices. This functions is needed also when one piece+proto is * associated with several ports. We have to check all the protoent structures * to make sure that pe really exists and correct */ static int protoent_check_ambiguity(struct protoent_test_data *td, struct protoent *pe) { return (TEST_DATA_FIND(protoent, td, pe, compare_protoent, NULL) != NULL ? 0 : -1); } static int protoent_test_getprotobyname(struct protoent *pe_model, void *mdata) { char **alias; struct protoent *pe; printf("testing getprotobyname() with the following data:\n"); dump_protoent(pe_model); pe = getprotobyname(pe_model->p_name); if (protoent_test_correctness(pe, NULL) != 0) goto errfin; if ((compare_protoent(pe, pe_model, NULL) != 0) && (protoent_check_ambiguity((struct protoent_test_data *)mdata, pe) !=0)) goto errfin; for (alias = pe_model->p_aliases; *alias; ++alias) { pe = getprotobyname(*alias); if (protoent_test_correctness(pe, NULL) != 0) goto errfin; if ((compare_protoent(pe, pe_model, NULL) != 0) && (protoent_check_ambiguity( (struct protoent_test_data *)mdata, pe) != 0)) goto errfin; } printf("ok\n"); return (0); errfin: printf("not ok\n"); return (-1); } static int protoent_test_getprotobynumber(struct protoent *pe_model, void *mdata) { struct protoent *pe; printf("testing getprotobyport() with the following data...\n"); dump_protoent(pe_model); pe = getprotobynumber(pe_model->p_proto); if ((protoent_test_correctness(pe, NULL) != 0) || ((compare_protoent(pe, pe_model, NULL) != 0) && (protoent_check_ambiguity((struct protoent_test_data *)mdata, pe) != 0))) { printf("not ok\n"); return (-1); } else { printf("ok\n"); return (0); } } static int -protoent_test_getprotoent(struct protoent *pe, void *mdata) +protoent_test_getprotoent(struct protoent *pe, void *mdata __unused) { /* Only correctness can be checked when doing 1-pass test for * getprotoent(). */ return (protoent_test_correctness(pe, NULL)); } -int +static int run_tests(const char *snapshot_file, enum test_methods method) { struct protoent_test_data td, td_snap, td_2pass; int rv; TEST_DATA_INIT(protoent, &td, clone_protoent, free_protoent); TEST_DATA_INIT(protoent, &td_snap, clone_protoent, free_protoent); if (snapshot_file != NULL) { if (access(snapshot_file, W_OK | R_OK) != 0) { if (errno == ENOENT) method = TEST_BUILD_SNAPSHOT; else { 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(protoent, snapshot_file, &td_snap, protoent_read_snapshot_func); } } rv = protoent_fill_test_data(&td); if (rv == -1) return (-1); switch (method) { case TEST_GETPROTOBYNAME: if (snapshot_file == NULL) rv = DO_1PASS_TEST(protoent, &td, protoent_test_getprotobyname, (void *)&td); else rv = DO_1PASS_TEST(protoent, &td_snap, protoent_test_getprotobyname, (void *)&td_snap); break; case TEST_GETPROTOBYNUMBER: if (snapshot_file == NULL) rv = DO_1PASS_TEST(protoent, &td, protoent_test_getprotobynumber, (void *)&td); else rv = DO_1PASS_TEST(protoent, &td_snap, protoent_test_getprotobynumber, (void *)&td_snap); break; case TEST_GETPROTOENT: if (snapshot_file == NULL) rv = DO_1PASS_TEST(protoent, &td, protoent_test_getprotoent, (void *)&td); else rv = DO_2PASS_TEST(protoent, &td, &td_snap, compare_protoent, NULL); break; case TEST_GETPROTOENT_2PASS: TEST_DATA_INIT(protoent, &td_2pass, clone_protoent, free_protoent); rv = protoent_fill_test_data(&td_2pass); if (rv != -1) rv = DO_2PASS_TEST(protoent, &td, &td_2pass, compare_protoent, NULL); TEST_DATA_DESTROY(protoent, &td_2pass); break; case TEST_BUILD_SNAPSHOT: if (snapshot_file != NULL) rv = TEST_SNAPSHOT_FILE_WRITE(protoent, snapshot_file, &td, sdump_protoent); break; default: rv = 0; break; } fin: TEST_DATA_DESTROY(protoent, &td_snap); TEST_DATA_DESTROY(protoent, &td); return (rv); } #define SNAPSHOT_FILE "snapshot_proto" ATF_TC_WITHOUT_HEAD(build_snapshot); ATF_TC_BODY(build_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); } ATF_TC_WITHOUT_HEAD(getprotoent); ATF_TC_BODY(getprotoent, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOENT) == 0); } ATF_TC_WITHOUT_HEAD(getprotoent_with_snapshot); ATF_TC_BODY(getprotoent_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOENT) == 0); } ATF_TC_WITHOUT_HEAD(getprotoent_with_two_pass); ATF_TC_BODY(getprotoent_with_two_pass, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOENT_2PASS) == 0); } ATF_TC_WITHOUT_HEAD(getprotobyname); ATF_TC_BODY(getprotobyname, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOBYNAME) == 0); } ATF_TC_WITHOUT_HEAD(getprotobyname_with_snapshot); ATF_TC_BODY(getprotobyname_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOBYNAME) == 0); } ATF_TC_WITHOUT_HEAD(getprotobynumber); ATF_TC_BODY(getprotobynumber, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOBYNUMBER) == 0); } ATF_TC_WITHOUT_HEAD(getprotobynumber_with_snapshot); ATF_TC_BODY(getprotobynumber_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOBYNUMBER) == 0); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, build_snapshot); ATF_TP_ADD_TC(tp, getprotoent); ATF_TP_ADD_TC(tp, getprotoent_with_snapshot); ATF_TP_ADD_TC(tp, getprotoent_with_two_pass); ATF_TP_ADD_TC(tp, getprotobyname); ATF_TP_ADD_TC(tp, getprotobyname_with_snapshot); ATF_TP_ADD_TC(tp, getprotobynumber); ATF_TP_ADD_TC(tp, getprotobynumber_with_snapshot); return (atf_no_error()); } Index: stable/11/lib/libc/tests/nss/getpw_test.c =================================================================== --- stable/11/lib/libc/tests/nss/getpw_test.c (revision 319298) +++ stable/11/lib/libc/tests/nss/getpw_test.c (revision 319299) @@ -1,530 +1,532 @@ /*- * Copyright (c) 2006 Michael Bushkov * All rights reserved. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "testutil.h" enum test_methods { TEST_GETPWENT, TEST_GETPWNAM, TEST_GETPWUID, TEST_GETPWENT_2PASS, TEST_BUILD_SNAPSHOT }; -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); +#ifdef DEBUG static void dump_passwd(struct passwd *); +#endif 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 *); 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) { ATF_REQUIRE(dest != NULL); ATF_REQUIRE(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) +compare_passwd(struct passwd *pwd1, struct passwd *pwd2, void *mdata __unused) { ATF_REQUIRE(pwd1 != NULL); ATF_REQUIRE(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:%jd:%s:%s:%s:%s:%jd:%d", pwd->pw_name, pwd->pw_passwd, pwd->pw_uid, pwd->pw_gid, (uintmax_t)pwd->pw_change, pwd->pw_class, pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell, (uintmax_t)pwd->pw_expire, pwd->pw_fields); } +#ifdef DEBUG 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"); } +#endif static int passwd_read_snapshot_func(struct passwd *pwd, char *line) { char *s, *ps, *ts; int i; #ifdef DEBUG printf("1 line read from snapshot:\n%s\n", line); #endif i = 0; ps = line; memset(pwd, 0, sizeof(struct passwd)); while ((s = strsep(&ps, ":")) != NULL) { switch (i) { case 0: pwd->pw_name = strdup(s); ATF_REQUIRE(pwd->pw_name != NULL); break; case 1: pwd->pw_passwd = strdup(s); ATF_REQUIRE(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); ATF_REQUIRE(pwd->pw_class != NULL); break; case 6: pwd->pw_gecos = strdup(s); ATF_REQUIRE(pwd->pw_gecos != NULL); break; case 7: pwd->pw_dir = strdup(s); ATF_REQUIRE(pwd->pw_dir != NULL); break; case 8: pwd->pw_shell = strdup(s); ATF_REQUIRE(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) +passwd_test_correctness(struct passwd *pwd, void *mdata __unused) { #ifdef DEBUG printf("testing correctness with the following data:\n"); dump_passwd(pwd); #endif 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; #ifdef DEBUG printf("correct\n"); #endif return (0); errfin: #ifdef DEBUG printf("incorrect\n"); #endif 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; #ifdef DEBUG printf("testing getpwnam() with the following data:\n"); dump_passwd(pwd_model); #endif 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; #ifdef DEBUG printf("ok\n"); #endif return (0); errfin: #ifdef DEBUG printf("not ok\n"); #endif return (-1); } static int passwd_test_getpwuid(struct passwd *pwd_model, void *mdata) { struct passwd *pwd; #ifdef DEBUG printf("testing getpwuid() with the following data...\n"); dump_passwd(pwd_model); #endif 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))) { #ifdef DEBUG printf("not ok\n"); #endif return (-1); } else { #ifdef DEBUG printf("ok\n"); #endif return (0); } } static int -passwd_test_getpwent(struct passwd *pwd, void *mdata) +passwd_test_getpwent(struct passwd *pwd, void *mdata __unused) { /* Only correctness can be checked when doing 1-pass test for * getpwent(). */ return (passwd_test_correctness(pwd, NULL)); } static int run_tests(const char *snapshot_file, enum test_methods method) { struct passwd_test_data td, td_snap, td_2pass; int rv; 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 { 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(passwd, snapshot_file, &td_snap, passwd_read_snapshot_func); } } rv = passwd_fill_test_data(&td); if (rv == -1) return (-1); switch (method) { case TEST_GETPWNAM: if (snapshot_file == NULL) rv = DO_1PASS_TEST(passwd, &td, passwd_test_getpwnam, (void *)&td); else rv = DO_1PASS_TEST(passwd, &td_snap, passwd_test_getpwnam, (void *)&td_snap); break; case TEST_GETPWUID: if (snapshot_file == NULL) rv = DO_1PASS_TEST(passwd, &td, passwd_test_getpwuid, (void *)&td); else rv = DO_1PASS_TEST(passwd, &td_snap, passwd_test_getpwuid, (void *)&td_snap); break; case TEST_GETPWENT: if (snapshot_file == NULL) rv = DO_1PASS_TEST(passwd, &td, passwd_test_getpwent, (void *)&td); else rv = DO_2PASS_TEST(passwd, &td, &td_snap, compare_passwd, NULL); break; case TEST_GETPWENT_2PASS: TEST_DATA_INIT(passwd, &td_2pass, clone_passwd, free_passwd); rv = passwd_fill_test_data(&td_2pass); if (rv != -1) rv = DO_2PASS_TEST(passwd, &td, &td_2pass, compare_passwd, NULL); TEST_DATA_DESTROY(passwd, &td_2pass); break; case TEST_BUILD_SNAPSHOT: if (snapshot_file != NULL) rv = TEST_SNAPSHOT_FILE_WRITE(passwd, snapshot_file, &td, sdump_passwd); break; default: rv = 0; break; } fin: TEST_DATA_DESTROY(passwd, &td_snap); TEST_DATA_DESTROY(passwd, &td); return (rv); } #define SNAPSHOT_FILE "snapshot_pwd" ATF_TC_WITHOUT_HEAD(build_snapshot); ATF_TC_BODY(build_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); } ATF_TC_WITHOUT_HEAD(getpwent); ATF_TC_BODY(getpwent, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWENT) == 0); } ATF_TC_WITHOUT_HEAD(getpwent_with_snapshot); ATF_TC_BODY(getpwent_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWENT) == 0); } ATF_TC_WITHOUT_HEAD(getpwent_with_two_pass); ATF_TC_BODY(getpwent_with_two_pass, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWENT_2PASS) == 0); } ATF_TC_WITHOUT_HEAD(getpwnam); ATF_TC_BODY(getpwnam, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWNAM) == 0); } ATF_TC_WITHOUT_HEAD(getpwnam_with_snapshot); ATF_TC_BODY(getpwnam_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWNAM) == 0); } ATF_TC_WITHOUT_HEAD(getpwuid); ATF_TC_BODY(getpwuid, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWUID) == 0); } ATF_TC_WITHOUT_HEAD(getpwuid_with_snapshot); ATF_TC_BODY(getpwuid_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWUID) == 0); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, build_snapshot); ATF_TP_ADD_TC(tp, getpwent); ATF_TP_ADD_TC(tp, getpwent_with_snapshot); ATF_TP_ADD_TC(tp, getpwent_with_two_pass); ATF_TP_ADD_TC(tp, getpwnam); ATF_TP_ADD_TC(tp, getpwnam_with_snapshot); ATF_TP_ADD_TC(tp, getpwuid); ATF_TP_ADD_TC(tp, getpwuid_with_snapshot); return (atf_no_error()); } Index: stable/11/lib/libc/tests/nss/getrpc_test.c =================================================================== --- stable/11/lib/libc/tests/nss/getrpc_test.c (revision 319298) +++ stable/11/lib/libc/tests/nss/getrpc_test.c (revision 319299) @@ -1,560 +1,558 @@ /*- * Copyright (c) 2006 Michael Bushkov * All rights reserved. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "testutil.h" enum test_methods { TEST_GETRPCENT, TEST_GETRPCBYNAME, TEST_GETRPCBYNUMBER, TEST_GETRPCENT_2PASS, TEST_BUILD_SNAPSHOT }; DECLARE_TEST_DATA(rpcent) DECLARE_TEST_FILE_SNAPSHOT(rpcent) DECLARE_1PASS_TEST(rpcent) DECLARE_2PASS_TEST(rpcent) static void clone_rpcent(struct rpcent *, struct rpcent const *); static int compare_rpcent(struct rpcent *, struct rpcent *, void *); static void dump_rpcent(struct rpcent *); static void free_rpcent(struct rpcent *); static void sdump_rpcent(struct rpcent *, char *, size_t); static int rpcent_read_snapshot_func(struct rpcent *, char *); static int rpcent_check_ambiguity(struct rpcent_test_data *, struct rpcent *); static int rpcent_fill_test_data(struct rpcent_test_data *); static int rpcent_test_correctness(struct rpcent *, void *); static int rpcent_test_getrpcbyname(struct rpcent *, void *); static int rpcent_test_getrpcbynumber(struct rpcent *, void *); static int rpcent_test_getrpcent(struct rpcent *, void *); -static void usage(void) __attribute__((__noreturn__)); - IMPLEMENT_TEST_DATA(rpcent) IMPLEMENT_TEST_FILE_SNAPSHOT(rpcent) IMPLEMENT_1PASS_TEST(rpcent) IMPLEMENT_2PASS_TEST(rpcent) static void clone_rpcent(struct rpcent *dest, struct rpcent const *src) { ATF_REQUIRE(dest != NULL); ATF_REQUIRE(src != NULL); char **cp; int aliases_num; memset(dest, 0, sizeof(struct rpcent)); if (src->r_name != NULL) { dest->r_name = strdup(src->r_name); ATF_REQUIRE(dest->r_name != NULL); } dest->r_number = src->r_number; if (src->r_aliases != NULL) { aliases_num = 0; for (cp = src->r_aliases; *cp; ++cp) ++aliases_num; - dest->r_aliases = calloc(1, (aliases_num + 1) * sizeof(char *)); + dest->r_aliases = calloc(aliases_num + 1, sizeof(char *)); ATF_REQUIRE(dest->r_aliases != NULL); for (cp = src->r_aliases; *cp; ++cp) { dest->r_aliases[cp - src->r_aliases] = strdup(*cp); ATF_REQUIRE(dest->r_aliases[cp - src->r_aliases] != NULL); } } } static void free_rpcent(struct rpcent *rpc) { char **cp; ATF_REQUIRE(rpc != NULL); free(rpc->r_name); for (cp = rpc->r_aliases; *cp; ++cp) free(*cp); free(rpc->r_aliases); } static int compare_rpcent(struct rpcent *rpc1, struct rpcent *rpc2, void *mdata) { char **c1, **c2; if (rpc1 == rpc2) return 0; if ((rpc1 == NULL) || (rpc2 == NULL)) goto errfin; if ((strcmp(rpc1->r_name, rpc2->r_name) != 0) || (rpc1->r_number != rpc2->r_number)) goto errfin; c1 = rpc1->r_aliases; c2 = rpc2->r_aliases; if ((rpc1->r_aliases == NULL) || (rpc2->r_aliases == 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 (mdata == NULL) { printf("following structures are not equal:\n"); dump_rpcent(rpc1); dump_rpcent(rpc2); } return (-1); } static void sdump_rpcent(struct rpcent *rpc, char *buffer, size_t buflen) { char **cp; int written; written = snprintf(buffer, buflen, "%s %d", rpc->r_name, rpc->r_number); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; if (rpc->r_aliases != NULL) { if (*(rpc->r_aliases) != '\0') { for (cp = rpc->r_aliases; *cp; ++cp) { - written = snprintf(buffer, buflen, " %s",*cp); + written = snprintf(buffer, buflen, " %s", *cp); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; if (buflen == 0) return; } } else snprintf(buffer, buflen, " noaliases"); } else snprintf(buffer, buflen, " (null)"); } static int rpcent_read_snapshot_func(struct rpcent *rpc, char *line) { StringList *sl; char *s, *ps, *ts; int i; printf("1 line read from snapshot:\n%s\n", line); i = 0; sl = NULL; ps = line; memset(rpc, 0, sizeof(struct rpcent)); while ((s = strsep(&ps, " ")) != NULL) { switch (i) { case 0: rpc->r_name = strdup(s); ATF_REQUIRE(rpc->r_name != NULL); break; case 1: rpc->r_number = (int)strtol(s, &ts, 10); if (*ts != '\0') { free(rpc->r_name); return (-1); } break; default: if (sl == NULL) { if (strcmp(s, "(null)") == 0) return (0); sl = sl_init(); ATF_REQUIRE(sl != NULL); if (strcmp(s, "noaliases") != 0) { ts = strdup(s); ATF_REQUIRE(ts != NULL); sl_add(sl, ts); } } else { ts = strdup(s); ATF_REQUIRE(ts != NULL); sl_add(sl, ts); } break; } i++; } if (i < 3) { free(rpc->r_name); memset(rpc, 0, sizeof(struct rpcent)); return (-1); } sl_add(sl, NULL); rpc->r_aliases = sl->sl_str; /* NOTE: is it a dirty hack or not? */ free(sl); return (0); } static void dump_rpcent(struct rpcent *result) { if (result != NULL) { char buffer[1024]; sdump_rpcent(result, buffer, sizeof(buffer)); printf("%s\n", buffer); } else printf("(null)\n"); } static int rpcent_fill_test_data(struct rpcent_test_data *td) { struct rpcent *rpc; setrpcent(1); while ((rpc = getrpcent()) != NULL) { if (rpcent_test_correctness(rpc, NULL) == 0) TEST_DATA_APPEND(rpcent, td, rpc); else return (-1); } endrpcent(); return (0); } static int -rpcent_test_correctness(struct rpcent *rpc, void *mdata) +rpcent_test_correctness(struct rpcent *rpc, void *mdata __unused) { printf("testing correctness with the following data:\n"); dump_rpcent(rpc); if (rpc == NULL) goto errfin; if (rpc->r_name == NULL) goto errfin; if (rpc->r_number < 0) goto errfin; if (rpc->r_aliases == NULL) goto errfin; printf("correct\n"); return (0); errfin: printf("incorrect\n"); return (-1); } /* rpcent_check_ambiguity() is needed when one port+rpc is associated with * more than one piece (these cases are usually marked as PROBLEM in * /etc/peices. This functions is needed also when one piece+rpc is * associated with several ports. We have to check all the rpcent structures * to make sure that rpc really exists and correct */ static int rpcent_check_ambiguity(struct rpcent_test_data *td, struct rpcent *rpc) { return (TEST_DATA_FIND(rpcent, td, rpc, compare_rpcent, NULL) != NULL ? 0 : -1); } static int rpcent_test_getrpcbyname(struct rpcent *rpc_model, void *mdata) { char **alias; struct rpcent *rpc; printf("testing getrpcbyname() with the following data:\n"); dump_rpcent(rpc_model); rpc = getrpcbyname(rpc_model->r_name); if (rpcent_test_correctness(rpc, NULL) != 0) goto errfin; if ((compare_rpcent(rpc, rpc_model, NULL) != 0) && (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc) !=0)) goto errfin; for (alias = rpc_model->r_aliases; *alias; ++alias) { rpc = getrpcbyname(*alias); if (rpcent_test_correctness(rpc, NULL) != 0) goto errfin; if ((compare_rpcent(rpc, rpc_model, NULL) != 0) && (rpcent_check_ambiguity( (struct rpcent_test_data *)mdata, rpc) != 0)) goto errfin; } printf("ok\n"); return (0); errfin: printf("not ok\n"); return (-1); } static int rpcent_test_getrpcbynumber(struct rpcent *rpc_model, void *mdata) { struct rpcent *rpc; printf("testing getrpcbyport() with the following data...\n"); dump_rpcent(rpc_model); rpc = getrpcbynumber(rpc_model->r_number); if (rpcent_test_correctness(rpc, NULL) != 0 || (compare_rpcent(rpc, rpc_model, NULL) != 0 && rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc) != 0)) { printf("not ok\n"); return (-1); } else { printf("ok\n"); return (0); } } static int -rpcent_test_getrpcent(struct rpcent *rpc, void *mdata) +rpcent_test_getrpcent(struct rpcent *rpc, void *mdata __unused) { /* * Only correctness can be checked when doing 1-pass test for * getrpcent(). */ return (rpcent_test_correctness(rpc, NULL)); } -int +static int run_tests(const char *snapshot_file, enum test_methods method) { struct rpcent_test_data td, td_snap, td_2pass; int rv; TEST_DATA_INIT(rpcent, &td, clone_rpcent, free_rpcent); TEST_DATA_INIT(rpcent, &td_snap, clone_rpcent, free_rpcent); if (snapshot_file != NULL) { if (access(snapshot_file, W_OK | R_OK) != 0) { if (errno == ENOENT) method = TEST_BUILD_SNAPSHOT; else { 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(rpcent, snapshot_file, &td_snap, rpcent_read_snapshot_func); } } rv = rpcent_fill_test_data(&td); if (rv == -1) return (-1); switch (method) { case TEST_GETRPCBYNAME: if (snapshot_file == NULL) rv = DO_1PASS_TEST(rpcent, &td, rpcent_test_getrpcbyname, (void *)&td); else rv = DO_1PASS_TEST(rpcent, &td_snap, rpcent_test_getrpcbyname, (void *)&td_snap); break; case TEST_GETRPCBYNUMBER: if (snapshot_file == NULL) rv = DO_1PASS_TEST(rpcent, &td, rpcent_test_getrpcbynumber, (void *)&td); else rv = DO_1PASS_TEST(rpcent, &td_snap, rpcent_test_getrpcbynumber, (void *)&td_snap); break; case TEST_GETRPCENT: if (snapshot_file == NULL) rv = DO_1PASS_TEST(rpcent, &td, rpcent_test_getrpcent, (void *)&td); else rv = DO_2PASS_TEST(rpcent, &td, &td_snap, compare_rpcent, NULL); break; case TEST_GETRPCENT_2PASS: TEST_DATA_INIT(rpcent, &td_2pass, clone_rpcent, free_rpcent); rv = rpcent_fill_test_data(&td_2pass); if (rv != -1) rv = DO_2PASS_TEST(rpcent, &td, &td_2pass, compare_rpcent, NULL); TEST_DATA_DESTROY(rpcent, &td_2pass); break; case TEST_BUILD_SNAPSHOT: if (snapshot_file != NULL) rv = TEST_SNAPSHOT_FILE_WRITE(rpcent, snapshot_file, &td, sdump_rpcent); break; default: rv = 0; break; } fin: TEST_DATA_DESTROY(rpcent, &td_snap); TEST_DATA_DESTROY(rpcent, &td); return (rv); } #define SNAPSHOT_FILE "snapshot_rpc" ATF_TC_WITHOUT_HEAD(build_snapshot); ATF_TC_BODY(build_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); } ATF_TC_WITHOUT_HEAD(getrpcbyname); ATF_TC_BODY(getrpcbyname, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETRPCBYNAME) == 0); } ATF_TC_WITHOUT_HEAD(getrpcbyname_with_snapshot); ATF_TC_BODY(getrpcbyname_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCBYNAME) == 0); } ATF_TC_WITHOUT_HEAD(getrpcbynumber); ATF_TC_BODY(getrpcbynumber, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETRPCBYNUMBER) == 0); } ATF_TC_WITHOUT_HEAD(getrpcbynumber_with_snapshot); ATF_TC_BODY(getrpcbynumber_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCBYNUMBER) == 0); } ATF_TC_WITHOUT_HEAD(getrpcbyent); ATF_TC_BODY(getrpcbyent, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETRPCENT) == 0); } ATF_TC_WITHOUT_HEAD(getrpcbyent_with_snapshot); ATF_TC_BODY(getrpcbyent_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCENT) == 0); } ATF_TC_WITHOUT_HEAD(getrpcbyent_with_two_pass); ATF_TC_BODY(getrpcbyent_with_two_pass, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETRPCENT_2PASS) == 0); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, build_snapshot); ATF_TP_ADD_TC(tp, getrpcbyname); ATF_TP_ADD_TC(tp, getrpcbyname_with_snapshot); ATF_TP_ADD_TC(tp, getrpcbynumber); ATF_TP_ADD_TC(tp, getrpcbynumber_with_snapshot); ATF_TP_ADD_TC(tp, getrpcbyent); ATF_TP_ADD_TC(tp, getrpcbyent_with_snapshot); ATF_TP_ADD_TC(tp, getrpcbyent_with_two_pass); return (atf_no_error()); } Index: stable/11/lib/libc/tests/nss/getserv_test.c =================================================================== --- stable/11/lib/libc/tests/nss/getserv_test.c (revision 319298) +++ stable/11/lib/libc/tests/nss/getserv_test.c (revision 319299) @@ -1,570 +1,570 @@ /*- * Copyright (c) 2006 Michael Bushkov * All rights reserved. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "testutil.h" enum test_methods { TEST_GETSERVENT, TEST_GETSERVBYNAME, TEST_GETSERVBYPORT, TEST_GETSERVENT_2PASS, TEST_BUILD_SNAPSHOT }; DECLARE_TEST_DATA(servent) DECLARE_TEST_FILE_SNAPSHOT(servent) DECLARE_1PASS_TEST(servent) DECLARE_2PASS_TEST(servent) static void clone_servent(struct servent *, struct servent const *); static int compare_servent(struct servent *, struct servent *, void *); static void dump_servent(struct servent *); static void free_servent(struct servent *); static void sdump_servent(struct servent *, char *, size_t); static int servent_read_snapshot_func(struct servent *, char *); static int servent_check_ambiguity(struct servent_test_data *, struct servent *); static int servent_fill_test_data(struct servent_test_data *); static int servent_test_correctness(struct servent *, void *); static int servent_test_getservbyname(struct servent *, void *); static int servent_test_getservbyport(struct servent *, void *); static int servent_test_getservent(struct servent *, void *); IMPLEMENT_TEST_DATA(servent) IMPLEMENT_TEST_FILE_SNAPSHOT(servent) IMPLEMENT_1PASS_TEST(servent) IMPLEMENT_2PASS_TEST(servent) static void clone_servent(struct servent *dest, struct servent const *src) { ATF_REQUIRE(dest != NULL); ATF_REQUIRE(src != NULL); char **cp; int aliases_num; memset(dest, 0, sizeof(struct servent)); if (src->s_name != NULL) { dest->s_name = strdup(src->s_name); ATF_REQUIRE(dest->s_name != NULL); } if (src->s_proto != NULL) { dest->s_proto = strdup(src->s_proto); ATF_REQUIRE(dest->s_proto != NULL); } dest->s_port = src->s_port; if (src->s_aliases != NULL) { aliases_num = 0; for (cp = src->s_aliases; *cp; ++cp) ++aliases_num; - dest->s_aliases = calloc(1, (aliases_num + 1) * sizeof(char *)); + dest->s_aliases = calloc(aliases_num + 1, sizeof(char *)); ATF_REQUIRE(dest->s_aliases != NULL); for (cp = src->s_aliases; *cp; ++cp) { dest->s_aliases[cp - src->s_aliases] = strdup(*cp); ATF_REQUIRE(dest->s_aliases[cp - src->s_aliases] != NULL); } } } static void free_servent(struct servent *serv) { char **cp; ATF_REQUIRE(serv != NULL); free(serv->s_name); free(serv->s_proto); for (cp = serv->s_aliases; *cp; ++cp) free(*cp); free(serv->s_aliases); } static int compare_servent(struct servent *serv1, struct servent *serv2, void *mdata) { char **c1, **c2; if (serv1 == serv2) return 0; if ((serv1 == NULL) || (serv2 == NULL)) goto errfin; if ((strcmp(serv1->s_name, serv2->s_name) != 0) || (strcmp(serv1->s_proto, serv2->s_proto) != 0) || (serv1->s_port != serv2->s_port)) goto errfin; c1 = serv1->s_aliases; c2 = serv2->s_aliases; if ((serv1->s_aliases == NULL) || (serv2->s_aliases == 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 (mdata == NULL) { printf("following structures are not equal:\n"); dump_servent(serv1); dump_servent(serv2); } return (-1); } static void sdump_servent(struct servent *serv, char *buffer, size_t buflen) { char **cp; int written; written = snprintf(buffer, buflen, "%s %d %s", serv->s_name, ntohs(serv->s_port), serv->s_proto); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; if (serv->s_aliases != NULL) { if (*(serv->s_aliases) != '\0') { for (cp = serv->s_aliases; *cp; ++cp) { - written = snprintf(buffer, buflen, " %s",*cp); + written = snprintf(buffer, buflen, " %s", *cp); buffer += written; - if (written > buflen) + if (written > (int)buflen) return; buflen -= written; if (buflen == 0) return; } } else snprintf(buffer, buflen, " noaliases"); } else snprintf(buffer, buflen, " (null)"); } static int servent_read_snapshot_func(struct servent *serv, char *line) { StringList *sl; char *s, *ps, *ts; int i; printf("1 line read from snapshot:\n%s\n", line); i = 0; sl = NULL; ps = line; memset(serv, 0, sizeof(struct servent)); while ( (s = strsep(&ps, " ")) != NULL) { switch (i) { case 0: serv->s_name = strdup(s); ATF_REQUIRE(serv->s_name != NULL); break; case 1: serv->s_port = htons( (int)strtol(s, &ts, 10)); if (*ts != '\0') { free(serv->s_name); return (-1); } break; case 2: serv->s_proto = strdup(s); ATF_REQUIRE(serv->s_proto != NULL); break; default: if (sl == NULL) { if (strcmp(s, "(null)") == 0) return (0); sl = sl_init(); ATF_REQUIRE(sl != NULL); if (strcmp(s, "noaliases") != 0) { ts = strdup(s); ATF_REQUIRE(ts != NULL); sl_add(sl, ts); } } else { ts = strdup(s); ATF_REQUIRE(ts != NULL); sl_add(sl, ts); } break; } ++i; } if (i < 3) { free(serv->s_name); free(serv->s_proto); memset(serv, 0, sizeof(struct servent)); return (-1); } sl_add(sl, NULL); serv->s_aliases = sl->sl_str; /* NOTE: is it a dirty hack or not? */ free(sl); return (0); } static void dump_servent(struct servent *result) { if (result != NULL) { char buffer[1024]; sdump_servent(result, buffer, sizeof(buffer)); printf("%s\n", buffer); } else printf("(null)\n"); } static int servent_fill_test_data(struct servent_test_data *td) { struct servent *serv; setservent(1); while ((serv = getservent()) != NULL) { if (servent_test_correctness(serv, NULL) == 0) TEST_DATA_APPEND(servent, td, serv); else return (-1); } endservent(); return (0); } static int -servent_test_correctness(struct servent *serv, void *mdata) +servent_test_correctness(struct servent *serv, void *mdata __unused) { printf("testing correctness with the following data:\n"); dump_servent(serv); if (serv == NULL) goto errfin; if (serv->s_name == NULL) goto errfin; if (serv->s_proto == NULL) goto errfin; if (ntohs(serv->s_port < 0)) goto errfin; if (serv->s_aliases == NULL) goto errfin; printf("correct\n"); return (0); errfin: printf("incorrect\n"); return (-1); } /* servent_check_ambiguity() is needed when one port+proto is associated with * more than one service (these cases are usually marked as PROBLEM in * /etc/services. This functions is needed also when one service+proto is * associated with several ports. We have to check all the servent structures * to make sure that serv really exists and correct */ static int servent_check_ambiguity(struct servent_test_data *td, struct servent *serv) { return (TEST_DATA_FIND(servent, td, serv, compare_servent, NULL) != NULL ? 0 : -1); } static int servent_test_getservbyname(struct servent *serv_model, void *mdata) { char **alias; struct servent *serv; printf("testing getservbyname() with the following data:\n"); dump_servent(serv_model); serv = getservbyname(serv_model->s_name, serv_model->s_proto); if (servent_test_correctness(serv, NULL) != 0) goto errfin; if ((compare_servent(serv, serv_model, NULL) != 0) && (servent_check_ambiguity((struct servent_test_data *)mdata, serv) !=0)) goto errfin; for (alias = serv_model->s_aliases; *alias; ++alias) { serv = getservbyname(*alias, serv_model->s_proto); if (servent_test_correctness(serv, NULL) != 0) goto errfin; if ((compare_servent(serv, serv_model, NULL) != 0) && (servent_check_ambiguity( (struct servent_test_data *)mdata, serv) != 0)) goto errfin; } printf("ok\n"); return (0); errfin: printf("not ok\n"); return (-1); } static int servent_test_getservbyport(struct servent *serv_model, void *mdata) { struct servent *serv; printf("testing getservbyport() with the following data...\n"); dump_servent(serv_model); serv = getservbyport(serv_model->s_port, serv_model->s_proto); if ((servent_test_correctness(serv, NULL) != 0) || ((compare_servent(serv, serv_model, NULL) != 0) && (servent_check_ambiguity((struct servent_test_data *)mdata, serv) != 0))) { printf("not ok\n"); return (-1); } else { printf("ok\n"); return (0); } } static int -servent_test_getservent(struct servent *serv, void *mdata) +servent_test_getservent(struct servent *serv, void *mdata __unused) { /* Only correctness can be checked when doing 1-pass test for * getservent(). */ return (servent_test_correctness(serv, NULL)); } -int +static int run_tests(const char *snapshot_file, enum test_methods method) { struct servent_test_data td, td_snap, td_2pass; int rv; TEST_DATA_INIT(servent, &td, clone_servent, free_servent); TEST_DATA_INIT(servent, &td_snap, clone_servent, free_servent); if (snapshot_file != NULL) { if (access(snapshot_file, W_OK | R_OK) != 0) { if (errno == ENOENT) method = TEST_BUILD_SNAPSHOT; else { 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(servent, snapshot_file, &td_snap, servent_read_snapshot_func); } } rv = servent_fill_test_data(&td); if (rv == -1) return (-1); switch (method) { case TEST_GETSERVBYNAME: if (snapshot_file == NULL) rv = DO_1PASS_TEST(servent, &td, servent_test_getservbyname, (void *)&td); else rv = DO_1PASS_TEST(servent, &td_snap, servent_test_getservbyname, (void *)&td_snap); break; case TEST_GETSERVBYPORT: if (snapshot_file == NULL) rv = DO_1PASS_TEST(servent, &td, servent_test_getservbyport, (void *)&td); else rv = DO_1PASS_TEST(servent, &td_snap, servent_test_getservbyport, (void *)&td_snap); break; case TEST_GETSERVENT: if (snapshot_file == NULL) rv = DO_1PASS_TEST(servent, &td, servent_test_getservent, (void *)&td); else rv = DO_2PASS_TEST(servent, &td, &td_snap, compare_servent, NULL); break; case TEST_GETSERVENT_2PASS: TEST_DATA_INIT(servent, &td_2pass, clone_servent, free_servent); rv = servent_fill_test_data(&td_2pass); if (rv != -1) rv = DO_2PASS_TEST(servent, &td, &td_2pass, compare_servent, NULL); TEST_DATA_DESTROY(servent, &td_2pass); break; case TEST_BUILD_SNAPSHOT: if (snapshot_file != NULL) rv = TEST_SNAPSHOT_FILE_WRITE(servent, snapshot_file, &td, sdump_servent); break; default: rv = 0; break; } fin: TEST_DATA_DESTROY(servent, &td_snap); TEST_DATA_DESTROY(servent, &td); return (rv); } #define SNAPSHOT_FILE "snapshot_serv" ATF_TC_WITHOUT_HEAD(build_snapshot); ATF_TC_BODY(build_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); } ATF_TC_WITHOUT_HEAD(getservbyname); ATF_TC_BODY(getservbyname, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETSERVBYNAME) == 0); } ATF_TC_WITHOUT_HEAD(getservbyname_with_snapshot); ATF_TC_BODY(getservbyname_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETSERVBYNAME) == 0); } ATF_TC_WITHOUT_HEAD(getservbyport); ATF_TC_BODY(getservbyport, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETSERVBYPORT) == 0); } ATF_TC_WITHOUT_HEAD(getservbyport_with_snapshot); ATF_TC_BODY(getservbyport_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETSERVBYPORT) == 0); } ATF_TC_WITHOUT_HEAD(getservbyent); ATF_TC_BODY(getservbyent, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETSERVENT) == 0); } ATF_TC_WITHOUT_HEAD(getservbyent_with_snapshot); ATF_TC_BODY(getservbyent_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETSERVENT) == 0); } ATF_TC_WITHOUT_HEAD(getservbyent_with_two_pass); ATF_TC_BODY(getservbyent_with_two_pass, tc) { ATF_REQUIRE(run_tests(NULL, TEST_GETSERVENT_2PASS) == 0); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, build_snapshot); ATF_TP_ADD_TC(tp, getservbyent); ATF_TP_ADD_TC(tp, getservbyent_with_snapshot); ATF_TP_ADD_TC(tp, getservbyent_with_two_pass); ATF_TP_ADD_TC(tp, getservbyname); ATF_TP_ADD_TC(tp, getservbyname_with_snapshot); ATF_TP_ADD_TC(tp, getservbyport); ATF_TP_ADD_TC(tp, getservbyport_with_snapshot); return (atf_no_error()); } Index: stable/11/lib/libc/tests/nss/getusershell_test.c =================================================================== --- stable/11/lib/libc/tests/nss/getusershell_test.c (revision 319298) +++ stable/11/lib/libc/tests/nss/getusershell_test.c (revision 319299) @@ -1,225 +1,224 @@ /*- * Copyright (c) 2006 Michael Bushkov * All rights reserved. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "testutil.h" enum test_methods { TEST_GETUSERSHELL, TEST_BUILD_SNAPSHOT }; struct usershell { char *path; }; -static enum test_methods method = TEST_GETUSERSHELL; - DECLARE_TEST_DATA(usershell) DECLARE_TEST_FILE_SNAPSHOT(usershell) DECLARE_2PASS_TEST(usershell) static void clone_usershell(struct usershell *, struct usershell const *); static int compare_usershell(struct usershell *, struct usershell *, void *); static void free_usershell(struct usershell *); static void sdump_usershell(struct usershell *, char *, size_t); static void dump_usershell(struct usershell *); IMPLEMENT_TEST_DATA(usershell) IMPLEMENT_TEST_FILE_SNAPSHOT(usershell) IMPLEMENT_2PASS_TEST(usershell) static void clone_usershell(struct usershell *dest, struct usershell const *src) { assert(dest != NULL); assert(src != NULL); if (src->path != NULL) { dest->path = strdup(src->path); assert(dest->path != NULL); } } static int -compare_usershell(struct usershell *us1, struct usershell *us2, void *mdata) +compare_usershell(struct usershell *us1, struct usershell *us2, + void *mdata __unused) { int rv; assert(us1 != NULL); assert(us2 != NULL); dump_usershell(us1); dump_usershell(us2); if (us1 == us2) return (0); rv = strcmp(us1->path, us2->path); if (rv != 0) { printf("following structures are not equal:\n"); dump_usershell(us1); dump_usershell(us2); } return (rv); } static void free_usershell(struct usershell *us) { free(us->path); } static void sdump_usershell(struct usershell *us, char *buffer, size_t buflen) { snprintf(buffer, buflen, "%s", us->path); } static void dump_usershell(struct usershell *us) { if (us != NULL) { char buffer[2048]; sdump_usershell(us, buffer, sizeof(buffer)); printf("%s\n", buffer); } else printf("(null)\n"); } static int usershell_read_snapshot_func(struct usershell *us, char *line) { us->path = strdup(line); ATF_REQUIRE(us->path != NULL); return (0); } -int +static int run_tests(const char *snapshot_file, enum test_methods method) { struct usershell_test_data td, td_snap; struct usershell ushell; int rv; rv = 0; TEST_DATA_INIT(usershell, &td, clone_usershell, free_usershell); TEST_DATA_INIT(usershell, &td_snap, clone_usershell, free_usershell); setusershell(); while ((ushell.path = getusershell()) != NULL) { printf("usershell found:\n"); dump_usershell(&ushell); TEST_DATA_APPEND(usershell, &td, &ushell); } endusershell(); if (snapshot_file != NULL) { if (access(snapshot_file, W_OK | R_OK) != 0) { if (errno == ENOENT) method = TEST_BUILD_SNAPSHOT; else { printf("can't access the snapshot file %s\n", snapshot_file); rv = -1; goto fin; } } else { rv = TEST_SNAPSHOT_FILE_READ(usershell, snapshot_file, &td_snap, usershell_read_snapshot_func); if (rv != 0) { printf("error reading snapshot file\n"); goto fin; } } } switch (method) { case TEST_GETUSERSHELL: rv = DO_2PASS_TEST(usershell, &td, &td_snap, compare_usershell, NULL); break; case TEST_BUILD_SNAPSHOT: if (snapshot_file != NULL) { rv = TEST_SNAPSHOT_FILE_WRITE(usershell, snapshot_file, &td, sdump_usershell); } break; default: rv = 0; break; } fin: TEST_DATA_DESTROY(usershell, &td_snap); TEST_DATA_DESTROY(usershell, &td); return (rv); } #define SNAPSHOT_FILE "snapshot_usershell" ATF_TC_WITHOUT_HEAD(getusershell_with_snapshot); ATF_TC_BODY(getusershell_with_snapshot, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); } ATF_TC_WITHOUT_HEAD(getusershell_with_two_pass); ATF_TC_BODY(getusershell_with_two_pass, tc) { ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETUSERSHELL) == 0); } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, getusershell_with_snapshot); ATF_TP_ADD_TC(tp, getusershell_with_two_pass); return (atf_no_error()); } Index: stable/11 =================================================================== --- stable/11 (revision 319298) +++ stable/11 (revision 319299) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r319027-319031,319033-319046