Index: stable/10/etc/mtree/BSD.tests.dist =================================================================== --- stable/10/etc/mtree/BSD.tests.dist (revision 292843) +++ stable/10/etc/mtree/BSD.tests.dist (revision 292844) @@ -1,434 +1,438 @@ # $FreeBSD$ # # Please see the file src/etc/mtree/README before making changes to this file. # /set type=dir uname=root gname=wheel mode=0755 . bin cat .. chown .. date .. dd .. expr .. ls .. mv .. pax .. pkill .. sh builtins .. errors .. execution .. expansion .. parameters .. parser .. set-e .. .. sleep .. test .. .. cddl lib .. sbin .. usr.bin .. usr.sbin .. .. etc rc.d .. .. games .. gnu lib .. usr.bin diff .. .. .. lib atf libatf-c detail .. .. libatf-c++ detail .. .. test-programs .. .. libarchive .. libc c063 .. db .. gen execve .. posix_spawn .. .. hash data .. .. inet .. locale .. net getaddrinfo data .. .. .. + nss + .. regex data .. + .. + resolv .. rpc .. ssp .. stdio .. stdlib .. string .. sys .. time .. tls dso .. .. termios .. ttyio .. .. libcrypt .. libmp .. librt .. libthr dlopen .. .. libutil .. msun .. .. libexec atf atf-check .. atf-sh .. .. .. sbin dhclient .. devd .. growfs .. mdconfig .. .. secure lib .. libexec .. usr.bin .. usr.sbin .. .. share examples tests atf .. plain .. .. .. .. sys acl .. aio .. fifo .. file .. kern acct .. execve .. pipe .. .. kqueue .. mqueue .. netinet .. pjdfstest chflags .. chmod .. chown .. ftruncate .. granular .. link .. mkdir .. mkfifo .. mknod .. open .. rename .. rmdir .. symlink .. truncate .. unlink .. .. posixshm .. vfs .. vm .. .. usr.bin apply .. basename .. bmake archives fmt_44bsd .. fmt_44bsd_mod .. fmt_oldbsd .. .. basic t0 .. t1 .. t2 .. t3 .. .. execution ellipsis .. empty .. joberr .. plus .. .. shell builtin .. meta .. path .. path_select .. replace .. select .. .. suffixes basic .. src_wild1 .. src_wild2 .. .. syntax directive-t0 .. enl .. funny-targets .. semi .. .. sysmk t0 2 1 .. .. mk .. .. t1 2 1 .. .. mk .. .. t2 2 1 .. .. mk .. .. .. variables modifier_M .. modifier_t .. opt_V .. t0 .. .. .. calendar .. cmp .. cpio .. col .. comm .. cut .. dirname .. file2c .. grep .. gzip .. join .. jot .. lastcomm .. limits .. m4 .. ncal .. opensm .. printf .. sed regress.multitest.out .. .. tar .. timeout .. tr .. truncate .. uudecode .. uuencode .. xargs .. yacc yacc .. .. .. usr.sbin etcupdate .. fstyp .. makefs .. newsyslog .. nmtree .. pw .. sa .. .. .. # vim: set expandtab ts=4 sw=4: Index: stable/10/lib/libc/tests/Makefile =================================================================== --- stable/10/lib/libc/tests/Makefile (revision 292843) +++ stable/10/lib/libc/tests/Makefile (revision 292844) @@ -1,33 +1,35 @@ # $FreeBSD$ .include TESTSDIR= ${TESTSBASE}/lib/libc SUBDIR= tls_dso TESTS_SUBDIRS= c063 TESTS_SUBDIRS+= db TESTS_SUBDIRS+= gen TESTS_SUBDIRS+= hash TESTS_SUBDIRS+= inet TESTS_SUBDIRS+= net +TESTS_SUBDIRS+= nss TESTS_SUBDIRS+= regex +TESTS_SUBDIRS+= resolv TESTS_SUBDIRS+= rpc TESTS_SUBDIRS+= stdio TESTS_SUBDIRS+= stdlib TESTS_SUBDIRS+= string TESTS_SUBDIRS+= sys TESTS_SUBDIRS+= termios TESTS_SUBDIRS+= tls TESTS_SUBDIRS+= ttyio .if ${MK_LOCALES} != "no" TESTS_SUBDIRS+= locale .endif .if ${MK_SSP} != "no" TESTS_SUBDIRS+= ssp .endif .include Index: stable/10/lib/libc/tests/nss/Makefile =================================================================== --- stable/10/lib/libc/tests/nss/Makefile (nonexistent) +++ stable/10/lib/libc/tests/nss/Makefile (revision 292844) @@ -0,0 +1,22 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/lib/libc/nss +BINDIR= ${TESTSDIR} + +.PATH: ${.CURDIR:H}/resolv + +FILES+= mach + +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 + +.include Property changes on: stable/10/lib/libc/tests/nss/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10/lib/libc/tests/nss/getaddrinfo_test.c =================================================================== --- stable/10/lib/libc/tests/nss/getaddrinfo_test.c (nonexistent) +++ stable/10/lib/libc/tests/nss/getaddrinfo_test.c (revision 292844) @@ -0,0 +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 "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) +{ + 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 +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) + return; + buflen -= written; + + written = snprintf(buffer, buflen, "%s ", + ai->ai_canonname == NULL ? "(null)" : ai->ai_canonname); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (ai->ai_addr == NULL) { + written = snprintf(buffer, buflen, "(null)"); + buffer += written; + if (written > buflen) + return; + buflen -= written; + } else { + for (i = 0; i < ai->ai_addrlen; i++) { + written = snprintf(buffer, buflen, + i + 1 != ai->ai_addrlen ? "%d." : "%d", + ((unsigned char *)ai->ai_addr)[i]); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (buflen == 0) + return; + } + } + + if (ai->ai_next != NULL) { + written = snprintf(buffer, buflen, ":"); + buffer += written; + if (written > 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; + + 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) +{ + + 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 +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()); +} Property changes on: stable/10/lib/libc/tests/nss/getaddrinfo_test.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10/lib/libc/tests/nss/getgr_test.c =================================================================== --- stable/10/lib/libc/tests/nss/getgr_test.c (nonexistent) +++ stable/10/lib/libc/tests/nss/getgr_test.c (revision 292844) @@ -0,0 +1,541 @@ +/*- + * 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 *)); + 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) + return; + buflen -= written; + + if (grp->gr_mem != NULL) { + if (*(grp->gr_mem) != '\0') { + for (cp = grp->gr_mem; *cp; ++cp) { + written = snprintf(buffer, buflen, " %s",*cp); + buffer += written; + if (written > buflen) + return; + buflen -= written; + + if (buflen == 0) + return; + } + } else + snprintf(buffer, buflen, " nomem"); + } else + snprintf(buffer, buflen, " (null)"); +} + +static int +group_read_snapshot_func(struct group *grp, char *line) +{ + StringList *sl; + char *s, *ps, *ts; + int i; + + printf("1 line read from snapshot:\n%s\n", line); + + i = 0; + sl = NULL; + ps = line; + memset(grp, 0, sizeof(struct group)); + while ((s = strsep(&ps, " ")) != NULL) { + switch (i) { + case 0: + grp->gr_name = strdup(s); + 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); + } + 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) +{ + 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) +{ + /* 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_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_TC_WITHOUT_HEAD(getgrent); +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()); +} Property changes on: stable/10/lib/libc/tests/nss/getgr_test.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10/lib/libc/tests/nss/gethostby_test.c =================================================================== --- stable/10/lib/libc/tests/nss/gethostby_test.c (nonexistent) +++ stable/10/lib/libc/tests/nss/gethostby_test.c (revision 292844) @@ -0,0 +1,1506 @@ +/*- + * 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 *)); + 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 *)); + 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) + 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) + return; + buflen -= written; + + if (buflen == 0) + return; + } + } else { + written = snprintf(buffer, buflen, " noaliases"); + buffer += written; + if (written > buflen) + return; + buflen -= written; + } + } else { + written = snprintf(buffer, buflen, " (null)"); + buffer += written; + if (written > buflen) + return; + buflen -= written; + } + + written = snprintf(buffer, buflen, " : "); + buffer += written; + if (written > 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; + + if (buflen == 0) + return; + } + + if (*(cp + 1) ) { + written = snprintf(buffer, buflen, " "); + buffer += written; + if (written > buflen) + return; + buflen -= written; + } + } + } else { + written = snprintf(buffer, buflen, " noaddrs"); + buffer += written; + if (written > buflen) + return; + buflen -= written; + } + } else { + written = snprintf(buffer, buflen, " (null)"); + buffer += written; + if (written > 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) +{ + +#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) +{ + 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) +{ + 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; i < nitems(result->h_aliases); 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, + 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) { + 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); + 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()); +} Property changes on: stable/10/lib/libc/tests/nss/gethostby_test.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10/lib/libc/tests/nss/getproto_test.c =================================================================== --- stable/10/lib/libc/tests/nss/getproto_test.c (nonexistent) +++ stable/10/lib/libc/tests/nss/getproto_test.c (revision 292844) @@ -0,0 +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 *)); + 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) + 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); + buffer += written; + if (written > 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) +{ + 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 peice (these cases are usually marked as PROBLEM in + * /etc/peices. This functions is needed also when one peice+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) +{ + /* Only correctness can be checked when doing 1-pass test for + * getprotoent(). */ + return (protoent_test_correctness(pe, NULL)); +} + +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()); +} Property changes on: stable/10/lib/libc/tests/nss/getproto_test.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10/lib/libc/tests/nss/getpw_test.c =================================================================== --- stable/10/lib/libc/tests/nss/getpw_test.c (nonexistent) +++ stable/10/lib/libc/tests/nss/getpw_test.c (revision 292844) @@ -0,0 +1,530 @@ +/*- + * 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); +static void dump_passwd(struct passwd *); + +static int passwd_read_snapshot_func(struct passwd *, char *); + +static int passwd_check_ambiguity(struct passwd_test_data *, struct passwd *); +static int passwd_fill_test_data(struct passwd_test_data *); +static int passwd_test_correctness(struct passwd *, void *); +static int passwd_test_getpwnam(struct passwd *, void *); +static int passwd_test_getpwuid(struct passwd *, void *); +static int passwd_test_getpwent(struct passwd *, void *); + +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) +{ + 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); +} + +static void +dump_passwd(struct passwd *pwd) +{ + if (pwd != NULL) { + char buffer[2048]; + sdump_passwd(pwd, buffer, sizeof(buffer)); + printf("%s\n", buffer); + } else + printf("(null)\n"); +} + +static int +passwd_read_snapshot_func(struct passwd *pwd, char *line) +{ + char *s, *ps, *ts; + int i; + +#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) +{ + +#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) +{ + /* 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()); +} Property changes on: stable/10/lib/libc/tests/nss/getpw_test.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10/lib/libc/tests/nss/getrpc_test.c =================================================================== --- stable/10/lib/libc/tests/nss/getrpc_test.c (nonexistent) +++ stable/10/lib/libc/tests/nss/getrpc_test.c (revision 292844) @@ -0,0 +1,560 @@ +/*- + * 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 *)); + 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) + 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); + buffer += written; + if (written > 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) +{ + + 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 peice (these cases are usually marked as PROBLEM in + * /etc/peices. This functions is needed also when one peice+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) +{ + + /* + * Only correctness can be checked when doing 1-pass test for + * getrpcent(). + */ + return (rpcent_test_correctness(rpc, NULL)); +} + +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()); +} Property changes on: stable/10/lib/libc/tests/nss/getrpc_test.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10/lib/libc/tests/nss/getserv_test.c =================================================================== --- stable/10/lib/libc/tests/nss/getserv_test.c (nonexistent) +++ stable/10/lib/libc/tests/nss/getserv_test.c (revision 292844) @@ -0,0 +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 *)); + 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) + 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); + buffer += written; + if (written > 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) +{ + 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) +{ + /* Only correctness can be checked when doing 1-pass test for + * getservent(). */ + return (servent_test_correctness(serv, NULL)); +} + +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()); +} Property changes on: stable/10/lib/libc/tests/nss/getserv_test.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10/lib/libc/tests/nss/getusershell_test.c =================================================================== --- stable/10/lib/libc/tests/nss/getusershell_test.c (nonexistent) +++ stable/10/lib/libc/tests/nss/getusershell_test.c (revision 292844) @@ -0,0 +1,225 @@ +/*- + * 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) +{ + 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 +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()); +} Property changes on: stable/10/lib/libc/tests/nss/getusershell_test.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10/lib/libc/tests/nss/testutil.h =================================================================== --- stable/10/lib/libc/tests/nss/testutil.h (nonexistent) +++ stable/10/lib/libc/tests/nss/testutil.h (revision 292844) @@ -0,0 +1,333 @@ +/*- + * Copyright (c) 2006 Michael Bushkov + * + * 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. + * + * $FreeBSD$ + */ + +#include + +#define DECLARE_TEST_DATA(ent) \ +struct ent##_entry { \ + struct ent data; \ + STAILQ_ENTRY(ent##_entry) entries; \ +}; \ + \ +struct ent##_test_data { \ + void (*clone_func)(struct ent *, struct ent const *); \ + void (*free_func)(struct ent *); \ + \ + STAILQ_HEAD(ent_head, ent##_entry) snapshot_data; \ +}; \ + \ +void __##ent##_test_data_init(struct ent##_test_data *, \ + void (*)(struct ent *, struct ent const *), \ + void (*freef)(struct ent *)); \ +void __##ent##_test_data_destroy(struct ent##_test_data *); \ + \ +void __##ent##_test_data_append(struct ent##_test_data *, struct ent *data);\ +int __##ent##_test_data_foreach(struct ent##_test_data *, \ + int (*)(struct ent *, void *), void *); \ +int __##ent##_test_data_compare(struct ent##_test_data *, \ + struct ent##_test_data *, int (*)(struct ent *, struct ent *, \ + void *), void *); \ +struct ent *__##ent##_test_data_find(struct ent##_test_data *, struct ent *,\ + int (*)(struct ent *, struct ent *, void *), void *); \ +void __##ent##_test_data_clear(struct ent##_test_data *); + +#define TEST_DATA_INIT(ent, td, clonef, freef)\ + __##ent##_test_data_init(td, clonef, freef) +#define TEST_DATA_DESTROY(ent, td) __##ent##_test_data_destroy(td) +#define TEST_DATA_APPEND(ent, td, d) __##ent##_test_data_append(td, d) +#define TEST_DATA_FOREACH(ent, td, f, mdata)\ + __##ent##_test_data_foreach(td, f, mdata) +#define TEST_DATA_COMPARE(ent, td1, td2, fcmp, mdata)\ + __##ent##_test_data_compare(td1, td2, fcmp, mdata); +#define TEST_DATA_FIND(ent, td, d, fcmp, mdata)\ + __##ent##_test_data_find(td, d, fcmp, mdata) +#define TEST_DATA_CLEAR(ent, td) __##ent##_test_data_clear(td) + +#define IMPLEMENT_TEST_DATA(ent) \ +void \ +__##ent##_test_data_init(struct ent##_test_data *td, \ + void (*clonef)(struct ent *, struct ent const *), \ + void (*freef)(struct ent *)) \ +{ \ + ATF_REQUIRE(td != NULL); \ + ATF_REQUIRE(clonef != NULL); \ + ATF_REQUIRE(freef != NULL); \ + \ + memset(td, 0, sizeof(*td)); \ + td->clone_func = clonef; \ + td->free_func = freef; \ + STAILQ_INIT(&td->snapshot_data); \ +} \ + \ +void \ +__##ent##_test_data_destroy(struct ent##_test_data *td) \ +{ \ + __##ent##_test_data_clear(td); \ +} \ + \ +void \ +__##ent##_test_data_append(struct ent##_test_data *td, struct ent *app_data)\ +{ \ + struct ent##_entry *e; \ + \ + ATF_REQUIRE(td != NULL); \ + ATF_REQUIRE(app_data != NULL); \ + \ + e = (struct ent##_entry *)malloc(sizeof(struct ent##_entry)); \ + ATF_REQUIRE(e != NULL); \ + memset(e, 0, sizeof(struct ent##_entry)); \ + \ + td->clone_func(&e->data, app_data); \ + STAILQ_INSERT_TAIL(&td->snapshot_data, e, entries); \ +} \ + \ +int \ +__##ent##_test_data_foreach(struct ent##_test_data *td, \ + int (*forf)(struct ent *, void *), void *mdata) \ +{ \ + struct ent##_entry *e; \ + int rv; \ + \ + ATF_REQUIRE(td != NULL); \ + ATF_REQUIRE(forf != NULL); \ + \ + rv = 0; \ + STAILQ_FOREACH(e, &td->snapshot_data, entries) { \ + rv = forf(&e->data, mdata); \ + if (rv != 0) \ + break; \ + } \ + \ + return (rv); \ +} \ + \ +int \ +__##ent##_test_data_compare(struct ent##_test_data *td1, struct ent##_test_data *td2,\ + int (*cmp_func)(struct ent *, struct ent *, void *), void *mdata)\ +{ \ + struct ent##_entry *e1, *e2; \ + int rv; \ + \ + ATF_REQUIRE(td1 != NULL); \ + ATF_REQUIRE(td2 != NULL); \ + ATF_REQUIRE(cmp_func != NULL); \ + \ + e1 = STAILQ_FIRST(&td1->snapshot_data); \ + e2 = STAILQ_FIRST(&td2->snapshot_data); \ + \ + rv = 0; \ + do { \ + if ((e1 == NULL) || (e2 == NULL)) { \ + if (e1 == e2) \ + return (0); \ + else \ + return (-1); \ + } \ + \ + rv = cmp_func(&e1->data, &e2->data, mdata); \ + e1 = STAILQ_NEXT(e1, entries); \ + e2 = STAILQ_NEXT(e2, entries); \ + } while (rv == 0); \ + \ + return (rv); \ +} \ + \ +struct ent * \ +__##ent##_test_data_find(struct ent##_test_data *td, struct ent *data, \ + int (*cmp)(struct ent *, struct ent *, void *), void *mdata) \ +{ \ + struct ent##_entry *e; \ + struct ent *result; \ + \ + ATF_REQUIRE(td != NULL); \ + ATF_REQUIRE(cmp != NULL); \ + \ + result = NULL; \ + STAILQ_FOREACH(e, &td->snapshot_data, entries) { \ + if (cmp(&e->data, data, mdata) == 0) { \ + result = &e->data; \ + break; \ + } \ + } \ + \ + return (result); \ +} \ + \ + \ +void \ +__##ent##_test_data_clear(struct ent##_test_data *td) \ +{ \ + struct ent##_entry *e; \ + ATF_REQUIRE(td != NULL); \ + \ + while (!STAILQ_EMPTY(&td->snapshot_data)) { \ + e = STAILQ_FIRST(&td->snapshot_data); \ + STAILQ_REMOVE_HEAD(&td->snapshot_data, entries); \ + \ + td->free_func(&e->data); \ + free(e); \ + e = NULL; \ + } \ +} + +#define DECLARE_TEST_FILE_SNAPSHOT(ent) \ +struct ent##_snp_param { \ + FILE *fp; \ + void (*sdump_func)(struct ent *, char *, size_t); \ +}; \ + \ +int __##ent##_snapshot_write_func(struct ent *, void *); \ +int __##ent##_snapshot_write(char const *, struct ent##_test_data *, \ + void (*)(struct ent *, char *, size_t)); \ +int __##ent##_snapshot_read(char const *, struct ent##_test_data *, \ + int (*)(struct ent *, char *)); + +#define TEST_SNAPSHOT_FILE_WRITE(ent, fname, td, f) \ + __##ent##_snapshot_write(fname, td, f) +#define TEST_SNAPSHOT_FILE_READ(ent, fname, td, f) \ + __##ent##_snapshot_read(fname, td, f) + +#define IMPLEMENT_TEST_FILE_SNAPSHOT(ent) \ +int \ +__##ent##_snapshot_write_func(struct ent *data, void *mdata) \ +{ \ + char buffer[1024]; \ + struct ent##_snp_param *param; \ + \ + ATF_REQUIRE(data != NULL); \ + \ + param = (struct ent##_snp_param *)mdata; \ + param->sdump_func(data, buffer, sizeof(buffer)); \ + fputs(buffer, param->fp); \ + fputc('\n', param->fp); \ + \ + return (0); \ +} \ + \ +int \ +__##ent##_snapshot_write(char const *fname, struct ent##_test_data *td, \ + void (*sdump_func)(struct ent *, char *, size_t)) \ +{ \ + struct ent##_snp_param param; \ + \ + ATF_REQUIRE(fname != NULL); \ + ATF_REQUIRE(td != NULL); \ + \ + param.fp = fopen(fname, "w"); \ + if (param.fp == NULL) \ + return (-1); \ + \ + param.sdump_func = sdump_func; \ + __##ent##_test_data_foreach(td, __##ent##_snapshot_write_func, ¶m);\ + fclose(param.fp); \ + \ + return (0); \ +} \ + \ +int \ +__##ent##_snapshot_read(char const *fname, struct ent##_test_data *td, \ + int (*read_func)(struct ent *, char *)) \ +{ \ + char buffer[1024]; \ + struct ent data; \ + char *s; \ + FILE *fi; \ + size_t len; \ + int rv; \ + \ + ATF_REQUIRE(fname != NULL); \ + ATF_REQUIRE(td != NULL); \ + \ + fi = fopen(fname, "r"); \ + if (fi == NULL) \ + return (-1); \ + \ + rv = 0; \ + memset(buffer, 0, sizeof(buffer)); \ + while (!feof(fi)) { \ + s = fgets(buffer, sizeof(buffer), fi); \ + if (s != NULL && s[0] != '#') { \ + len = strlen(s); \ + if (len == 0) \ + continue; \ + if (buffer[len - 1] == '\n') \ + buffer[len -1] = '\0'; \ + \ + rv = read_func(&data, s); \ + if (rv == 0) { \ + __##ent##_test_data_append(td, &data); \ + td->free_func(&data); \ + } else \ + goto fin; \ + } \ + } \ + \ +fin: \ + fclose(fi); \ + return (rv); \ +} + +#define DECLARE_1PASS_TEST(ent) \ +int __##ent##_1pass_test(struct ent##_test_data *, \ + int (*)(struct ent *, void *), \ + void *); + +#define DO_1PASS_TEST(ent, td, f, mdata) \ + __##ent##_1pass_test(td, f, mdata) + +#define IMPLEMENT_1PASS_TEST(ent) \ +int \ +__##ent##_1pass_test(struct ent##_test_data *td, \ + int (*tf)(struct ent *, void *), \ + void *mdata) \ +{ \ + int rv; \ + rv = __##ent##_test_data_foreach(td, tf, mdata); \ + \ + return (rv); \ +} + +#define DECLARE_2PASS_TEST(ent) \ +int __##ent##_2pass_test(struct ent##_test_data *, \ + struct ent##_test_data *, \ + int (*)(struct ent *, struct ent *, void *), void *); + +#define DO_2PASS_TEST(ent, td1, td2, f, mdata) \ + __##ent##_2pass_test(td1, td2, f, mdata) + +#define IMPLEMENT_2PASS_TEST(ent) \ +int \ +__##ent##_2pass_test(struct ent##_test_data *td1, \ + struct ent##_test_data *td2, \ + int (*cmp_func)(struct ent *, struct ent *, void *), \ + void *cmp_mdata) \ +{ \ + int rv; \ + \ + rv = __##ent##_test_data_compare(td1, td2, cmp_func, cmp_mdata); \ + return (rv); \ +} Property changes on: stable/10/lib/libc/tests/nss/testutil.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10/lib/libc/tests/resolv/Makefile =================================================================== --- stable/10/lib/libc/tests/resolv/Makefile (nonexistent) +++ stable/10/lib/libc/tests/resolv/Makefile (revision 292844) @@ -0,0 +1,15 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/lib/libc/resolv +BINDIR= ${TESTSDIR} + +FILES+= mach + +ATF_TESTS_C+= resolv_test + +# Note: this test relies on being dynamically linked. You will get a +# spurious PASS for a statically linked test. +DPADD.resolv_test+= ${LIBPTHREAD} +LDADD.resolv_test+= -lpthread + +.include Property changes on: stable/10/lib/libc/tests/resolv/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/10/lib/libc/tests/resolv/resolv_test.c =================================================================== --- stable/10/lib/libc/tests/resolv/resolv_test.c (nonexistent) +++ stable/10/lib/libc/tests/resolv/resolv_test.c (revision 292844) @@ -0,0 +1,331 @@ +/* $NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $ */ + +/*- + * Copyright (c) 2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ +/* $FreeBSD$ */ +#include +__RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NTHREADS 10 +#define NHOSTS 100 +#define WS " \t\n\r" + +enum method { + METHOD_GETADDRINFO, + METHOD_GETHOSTBY, + METHOD_GETIPNODEBY +}; + +static StringList *hosts = NULL; +static enum method method = METHOD_GETADDRINFO; +static int *ask = NULL; +static int *got = NULL; + +static void load(const char *); +static void resolvone(int); +static void *resolvloop(void *); +static void run(int *); + +static pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER; + +static void +load(const char *fname) +{ + FILE *fp; + size_t len; + char *line; + + if ((fp = fopen(fname, "r")) == NULL) + ATF_REQUIRE(fp != NULL); + while ((line = fgetln(fp, &len)) != NULL) { + char c = line[len]; + char *ptr; + line[len] = '\0'; + for (ptr = strtok(line, WS); ptr; ptr = strtok(NULL, WS)) { + if (ptr == '\0' || ptr[0] == '#') + continue; + sl_add(hosts, strdup(ptr)); + } + line[len] = c; + } + + (void)fclose(fp); +} + +static int +resolv_getaddrinfo(pthread_t self, char *host, int port) +{ + char portstr[6], buf[1024], hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; + struct addrinfo hints, *res; + int error, len; + + snprintf(portstr, sizeof(portstr), "%d", port); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_PASSIVE; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(host, portstr, &hints, &res); + len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", + self, host, error ? "not found" : "ok"); + (void)write(STDOUT_FILENO, buf, len); + if (error == 0) { + memset(hbuf, 0, sizeof(hbuf)); + memset(pbuf, 0, sizeof(pbuf)); + getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), + pbuf, sizeof(pbuf), 0); + len = snprintf(buf, sizeof(buf), + "%p: reverse %s %s\n", self, hbuf, pbuf); + (void)write(STDOUT_FILENO, buf, len); + } + if (error == 0) + freeaddrinfo(res); + return error; +} + +static int +resolv_gethostby(pthread_t self, char *host) +{ + char buf[1024]; + struct hostent *hp, *hp2; + int len; + + hp = gethostbyname(host); + len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", + self, host, (hp == NULL) ? "not found" : "ok"); + (void)write(STDOUT_FILENO, buf, len); + if (hp) { + memcpy(buf, hp->h_addr, hp->h_length); + hp2 = gethostbyaddr(buf, hp->h_length, hp->h_addrtype); + if (hp2) { + len = snprintf(buf, sizeof(buf), + "%p: reverse %s\n", self, hp2->h_name); + (void)write(STDOUT_FILENO, buf, len); + } + } + return hp ? 0 : -1; +} + +static int +resolv_getipnodeby(pthread_t self, char *host) +{ + char buf[1024]; + struct hostent *hp, *hp2; + int len, h_error; + + hp = getipnodebyname(host, AF_INET, 0, &h_error); + len = snprintf(buf, sizeof(buf), "%p: host %s %s\n", + self, host, (hp == NULL) ? "not found" : "ok"); + (void)write(STDOUT_FILENO, buf, len); + if (hp) { + memcpy(buf, hp->h_addr, hp->h_length); + hp2 = getipnodebyaddr(buf, hp->h_length, hp->h_addrtype, + &h_error); + if (hp2) { + len = snprintf(buf, sizeof(buf), + "%p: reverse %s\n", self, hp2->h_name); + (void)write(STDOUT_FILENO, buf, len); + } + if (hp2) + freehostent(hp2); + } + if (hp) + freehostent(hp); + return hp ? 0 : -1; +} + +static void +resolvone(int n) +{ + char buf[1024]; + pthread_t self = pthread_self(); + size_t i = (random() & 0x0fffffff) % hosts->sl_cur; + char *host = hosts->sl_str[i]; + struct addrinfo hints, *res; + int error, len; + + len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n", + self, n, host, (int)i); + (void)write(STDOUT_FILENO, buf, len); + switch (method) { + case METHOD_GETADDRINFO: + error = resolv_getaddrinfo(self, host, i); + break; + case METHOD_GETHOSTBY: + error = resolv_gethostby(self, host); + break; + case METHOD_GETIPNODEBY: + error = resolv_getipnodeby(self, host); + break; + default: + break; + } + pthread_mutex_lock(&stats); + ask[i]++; + got[i] += error == 0; + pthread_mutex_unlock(&stats); +} + +static void * +resolvloop(void *p) +{ + int *nhosts = (int *)p; + if (*nhosts == 0) + return NULL; + do + resolvone(*nhosts); + while (--(*nhosts)); + return NULL; +} + +static void +run(int *nhosts) +{ + pthread_t self; + int rc; + + self = pthread_self(); + rc = pthread_create(&self, NULL, resolvloop, nhosts); + ATF_REQUIRE_MSG(rc == 0, "pthread_create failed: %s", strerror(rc)); +} + +static int +run_tests(const char *hostlist_file, enum method method) +{ + int nthreads = NTHREADS; + int nhosts = NHOSTS; + int i, c, done, *nleft; + hosts = sl_init(); + + srandom(1234); + + load(hostlist_file); + + ATF_REQUIRE_MSG(0 < hosts->sl_cur, "0 hosts in %s", hostlist_file); + + nleft = malloc(nthreads * sizeof(int)); + ATF_REQUIRE(nleft != NULL); + + ask = calloc(hosts->sl_cur, sizeof(int)); + ATF_REQUIRE(ask != NULL); + + got = calloc(hosts->sl_cur, sizeof(int)); + ATF_REQUIRE(got != NULL); + + for (i = 0; i < nthreads; i++) { + nleft[i] = nhosts; + run(&nleft[i]); + } + + for (done = 0; !done;) { + done = 1; + for (i = 0; i < nthreads; i++) { + if (nleft[i] != 0) { + done = 0; + break; + } + } + sleep(1); + } + c = 0; + for (i = 0; i < hosts->sl_cur; i++) { + if (ask[i] != got[i] && got[i] != 0) { + printf("Error: host %s ask %d got %d\n", + hosts->sl_str[i], ask[i], got[i]); + c++; + } + } + free(nleft); + free(ask); + free(got); + sl_free(hosts, 1); + return c; +} + +#define HOSTLIST_FILE "mach" + +#define RUN_TESTS(tc, method) \ +do { \ + char *_hostlist_file; \ + ATF_REQUIRE(0 < asprintf(&_hostlist_file, "%s/%s", \ + atf_tc_get_config_var(tc, "srcdir"), HOSTLIST_FILE)); \ + ATF_REQUIRE(run_tests(_hostlist_file, method) == 0); \ +} while(0) + +ATF_TC(getaddrinfo_test); +ATF_TC_HEAD(getaddrinfo_test, tc) { + atf_tc_set_md_var(tc, "timeout", "450"); +} +ATF_TC_BODY(getaddrinfo_test, tc) +{ + + RUN_TESTS(tc, METHOD_GETADDRINFO); +} + +ATF_TC(gethostby_test); +ATF_TC_HEAD(gethostby_test, tc) { + atf_tc_set_md_var(tc, "timeout", "450"); +} +ATF_TC_BODY(gethostby_test, tc) +{ + + RUN_TESTS(tc, METHOD_GETHOSTBY); +} + +ATF_TC(getipnodeby_test); +ATF_TC_HEAD(getipnodeby_test, tc) { + + atf_tc_set_md_var(tc, "timeout", "450"); +} +ATF_TC_BODY(getipnodeby_test, tc) +{ + + RUN_TESTS(tc, METHOD_GETIPNODEBY); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, getaddrinfo_test); + ATF_TP_ADD_TC(tp, gethostby_test); + ATF_TP_ADD_TC(tp, getipnodeby_test); + + return (atf_no_error()); +} Property changes on: stable/10/lib/libc/tests/resolv/resolv_test.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10/lib/libc/tests/resolv/mach =================================================================== --- stable/10/lib/libc/tests/resolv/mach (nonexistent) +++ stable/10/lib/libc/tests/resolv/mach (revision 292844) @@ -0,0 +1,46 @@ +# $FreeBSD$ +localhost +anoncvs.cirr.com +anoncvs.netbsd.se +antioche.antioche.eu.org +centaurus.4web.cz +chur.math.ntnu.no +console.netbsd.org +cvs.netbsd.org +cvsup.netbsd.se +ftp.chg.ru +ftp.estpak.ee +ftp.fsn.hu +ftp.funet.fi +ftp.netbsd.org +ftp.nluug.nl +ftp.plig.org +ftp.uni-erlangen.de +ftp.xgate.co.kr +gd.tuwien.ac.at +gort.ludd.luth.se +irc.warped.net +knug.youn.co.kr +mail.jp.netbsd.org +mail.netbsd.org +melanoma.cs.rmit.edu.au +mirror.aarnet.edu.au +moon.vub.ac.be +net.bsd.cz +netbsd.3miasto.net +netbsd.4ka.mipt.ru +netbsd.csie.nctu.edu.tw +netbsd.enderunix.org +netbsd.ftp.fu-berlin.de +netbsd.pair.com +netbsdiso.interoute.net.uk +netbsdwww.cs.rmit.edu.au +netbsdwww.interoute.net.uk +ns.netbsd.org +skeleton.phys.spbu.ru +www.en.netbsd.de +www.netbsd.cl +www.netbsd.nl +www.netbsd.org +www.netbsd.ro +zeppo.rediris.es Property changes on: stable/10/lib/libc/tests/resolv/mach ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/10 =================================================================== --- stable/10 (revision 292843) +++ stable/10 (revision 292844) Property changes on: stable/10 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r292317-292318,292323-292324,292665