Date: Sat, 1 Jul 2006 10:34:26 GMT From: Michael Bushkov <bushman@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 100389 for review Message-ID: <200607011034.k61AYQxd064935@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=100389 Change 100389 by bushman@bushman_nss_ldap_cached on 2006/07/01 10:33:42 getservent() test finished. It's code should be used to extend testutil.h and as the base for other nss regressions, Affected files ... .. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/Makefile#2 edit .. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getgr.c#2 edit .. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getpw.c#2 edit .. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getserv.c#2 edit .. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getserv.t#2 edit .. //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/testutil.h#2 edit Differences ... ==== //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/Makefile#2 (text+ko) ==== ==== //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getgr.c#2 (text+ko) ==== ==== //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getpw.c#2 (text+ko) ==== ==== //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getserv.c#2 (text+ko) ==== @@ -30,17 +30,20 @@ #include <arpa/inet.h> #include <assert.h> +#include <errno.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stringlist.h> #include <unistd.h> #include "testutil.h" enum test_methods { TEST_GETSERVENT, TEST_GETSERVBYNAME, - TEST_GETSERVBYPORT + TEST_GETSERVBYPORT, + TEST_GETSERVENT_2PASS }; static int debug = 0; @@ -48,17 +51,29 @@ DECLARE_TEST_DATA(servent) +static int check_servent_ambiguity_func(struct servent *, void *); + static void clone_servent(struct servent *, struct servent const *); -static int compare_servent(struct servent *, struct servent *); +static int compare_servent(struct servent *, struct servent *, void *); static void dump_servent(struct servent *); static void free_servent(struct servent *); -static int servent_1pass_test(int (*)(struct servent *)); +static void sdump_servent(struct servent *, char *, size_t); +static int servent_1pass_test(int (*)(struct servent *, void *)); static int servent_2pass_test(); +static int servent_check_ambiguity(struct servent_test_data *, + struct servent *); static void servent_fill_test_data(struct servent_test_data *); -static int servent_test_correctness(struct servent *); -static int servent_test_getservbyname(struct servent *); -static int servent_test_getservbyport(struct servent *); +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 *); + +static int servent_read_snapshot_func(struct servent *, char *); +static int servent_read_snapshot(char const *, struct servent_test_data *); +static int servent_write_snapshot(char const *, struct servent_test_data *); +static int servent_write_snapshot_func(struct servent *, void *); + static void usage(void) __attribute__((__noreturn__)); IMPLEMENT_TEST_DATA(servent) @@ -108,7 +123,7 @@ } static int -compare_servent(struct servent *serv1, struct servent *serv2) +compare_servent(struct servent *serv1, struct servent *serv2, void *mdata) { char **c1, **c2; @@ -125,6 +140,10 @@ 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; @@ -135,7 +154,7 @@ return 0; errfin: - if (debug) { + if ((debug) && (mdata == NULL)) { printf("following structures are not equal:\n"); dump_servent(serv1); dump_servent(serv2); @@ -144,22 +163,43 @@ 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 void dump_servent(struct servent *result) { - printf("=struct servent (located by %p) dump\n", (void *)result); - printf("\tname: %s\n", result->s_name); - printf("\tport: %d\n", ntohs(result->s_port)); - printf("\tproto: %s\n", result->s_proto); - - if (*(result->s_aliases)!='\0') { - char ** cp; - - printf("\taliases:\n"); - for (cp=result->s_aliases; *cp; ++cp) - printf("\t\t%s\n",*cp); - } else - printf("\tno aliases\n"); + char buffer[1024]; + sdump_servent(result, buffer, sizeof(buffer)); + printf("%s\n", buffer); } static void @@ -175,22 +215,81 @@ } static int -servent_test_correctness(struct servent *serv) +servent_build_snapshot(char const *fname) +{ + struct servent_test_data td; + int rv; + + if (debug) + printf("building snapshot file %s\n", fname); + + test_data_init(&td, clone_servent, free_servent); + + servent_fill_test_data(&td); + rv = servent_write_snapshot(fname, &td); + + test_data_destroy(&td); + + if (debug) + printf("%s\n", rv == 0 ? "ok" : "not ok"); + return (rv); +} + +static int +servent_test_correctness(struct servent *serv, void *mdata) { if (debug) { printf("testing correctness with the following data:\n"); dump_servent(serv); } - FUNC_RET_CHECK(serv->s_name != NULL); - FUNC_RET_CHECK(serv->s_proto != NULL); - FUNC_RET_CHECK(ntohs(serv->s_port >= 0)); - FUNC_RET_CHECK(serv->s_aliases != NULL); + 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; + + if (debug) + printf("ok\n"); + + return (0); +errfin: + if (debug) + printf("not ok\n"); + + return (-1); +} + +static int +check_servent_ambiguity_func(struct servent *serv, void *mdata) +{ + + assert(serv != NULL); + assert(mdata != NULL); + + return (!compare_servent(serv, (struct servent *)mdata, mdata)); +} + +/* 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 (0); + return (test_data_foreach(td, check_servent_ambiguity_func, + (void *)serv) == 0 ? -1 : 0); } static int -servent_test_getservbyname(struct servent *serv_model) +servent_test_getservbyname(struct servent *serv_model, void *mdata) { char **alias; struct servent *serv; @@ -201,18 +300,32 @@ } serv = getservbyname(serv_model->s_name, serv_model->s_proto); - FUNC_RET_CHECK(compare_servent(serv, serv_model) == 0); + 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); - FUNC_RET_CHECK(compare_servent(serv, serv_model) == 0); + if ((compare_servent(serv, serv_model, NULL) != 0) && + (servent_check_ambiguity( + (struct servent_test_data *)mdata, serv) != 0)) + goto errfin; } + if (debug) + printf("ok\n"); return (0); + +errfin: + if (debug) + printf("not ok\n"); + + return (-1); } static int -servent_test_getservbyport(struct servent *serv_model) +servent_test_getservbyport(struct servent *serv_model, void *mdata) { struct servent *serv; @@ -222,11 +335,29 @@ } serv = getservbyport(serv_model->s_port, serv_model->s_proto); - return (compare_servent(serv, serv_model)); + if ((compare_servent(serv, serv_model, NULL) != 0) && + (servent_check_ambiguity((struct servent_test_data *)mdata, serv) + != 0)) { + if (debug) + printf("not ok\n"); + return (-1); + } else { + if (debug) + printf("ok\n"); + return (0); + } +} + +static int +servent_test_getservent(struct servent *serv, void *mdata) +{ + /* Only correctness should be checked when doing 1-pass test for + * getservent(). Correctness is always checked in servent_1pass_test */ + return (0); } static int -servent_1pass_test(int (*tf)(struct servent *)) +servent_1pass_test(int (*tf)(struct servent *, void *)) { struct servent_test_data td; int rv; @@ -234,10 +365,10 @@ test_data_init(&td, clone_servent, free_servent); servent_fill_test_data(&td); - rv = test_data_foreach(&td, servent_test_correctness); + rv = test_data_foreach(&td, servent_test_correctness, NULL); if (rv != 0) goto fin; - rv = test_data_foreach(&td, tf); + rv = test_data_foreach(&td, tf, (void *)&td); fin: test_data_destroy(&td); @@ -246,6 +377,32 @@ } static int +servent_snapshot_1pass_test(char const *fname, + int (*tf)(struct servent *, void *)) +{ + struct servent_test_data td; + int rv; + + test_data_init(&td, clone_servent, free_servent); + rv = servent_read_snapshot(fname, &td); + if (rv != 0) { + if (debug) + printf("error reading snapshot file %s\n", fname); + goto fin; + } + + rv = test_data_foreach(&td, servent_test_correctness, NULL); + if (rv != 0) + goto fin; + rv = test_data_foreach(&td, tf, (void *)&td); + +fin: + test_data_destroy(&td); + + return (rv); +} + +static int servent_2pass_test() { struct servent_test_data td1, td2; @@ -259,19 +416,200 @@ if (debug) printf("testing equality of two getservent() result-sets\n"); - rv = test_data_compare(&td1, &td2, compare_servent); + rv = test_data_compare(&td1, &td2, compare_servent, NULL); test_data_destroy(&td1); test_data_destroy(&td2); + + if (debug) + printf("%s\n", rv == 0 ? "ok" : "not ok"); + return (rv); +} + +static int +servent_snapshot_2pass_test(char const *fname) +{ + struct servent_test_data td1, td2; + int rv; + test_data_init(&td1, clone_servent, free_servent); + test_data_init(&td2, clone_servent, free_servent); + + rv = servent_read_snapshot(fname, &td1); + if (rv != 0) { + if (debug) + printf("error reading snapshot file %s\n", fname); + goto fin; + } + servent_fill_test_data(&td2); + + if (debug) + printf("testing equality of snapshot and current result-set\n"); + rv = test_data_compare(&td1, &td2, compare_servent, NULL); + +fin: + test_data_destroy(&td1); + test_data_destroy(&td2); + + if (debug) + printf("%s\n", rv == 0 ? "ok" : "not ok"); return (rv); } +static int +servent_write_snapshot_func(struct servent *serv, void *mdata) +{ + char buffer[1024]; + FILE *fo; + + assert(serv != NULL); + assert(mdata != NULL); + + fo = (FILE *)mdata; + sdump_servent(serv, buffer, sizeof(buffer)); + fputs(buffer, fo); + fputc('\n', fo); + + return (0); +} + +static int +servent_write_snapshot(char const *fname, struct servent_test_data *td) +{ + FILE *fo; + + assert(fname != NULL); + assert(td != NULL); + + fo = fopen(fname, "w"); + if (fo == NULL) + return (-1); + + test_data_foreach(td, servent_write_snapshot_func, (void *)fo); + fclose(fo); + + return (0); +} + +static int +servent_read_snapshot_func(struct servent *serv, char *line) +{ + StringList *sl; + char *s, *ps, *ts; + int i; + + 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); + assert(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); + assert(serv->s_proto != NULL); + 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(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 int +servent_read_snapshot(char const *fname, struct servent_test_data *td) +{ + char buffer[1024]; + struct servent serv; + char *s; + FILE *fi; + size_t len; + int rv; + + assert(fname != NULL); + assert(td != NULL); + + fi = fopen(fname, "r"); + if (fi == NULL) + return (-1); + + memset(buffer, 0, sizeof(buffer)); + while (!feof(fi)) { + s = fgets(buffer, sizeof(buffer), fi); + if (s != NULL) { + len = strlen(s); + if (len == 0) + continue; + if (buffer[len - 1] == '\n') + buffer[len -1] = '\0'; + + rv = servent_read_snapshot_func(&serv, s); + if (rv == 0) { + if (debug) { + printf("1 line read from snapshot:\n"); + dump_servent(&serv); + } + test_data_append(td, &serv); + td->free_func(&serv); + } + } + } + + fclose(fi); + + return (0); +} + static void usage(void) { (void)fprintf(stderr, - "Usage: %s [-dnpe]\n", + "Usage: %s [-dnpe2]\n", getprogname()); exit(1); } @@ -279,13 +617,15 @@ int main(int argc, char **argv) { + char *snapshot_file; int rv; int c; if (argc < 2) usage(); - while ((c = getopt(argc, argv, "nped")) != -1) + snapshot_file = NULL; + while ((c = getopt(argc, argv, "npe2ds:")) != -1) switch (c) { case 'd': debug++; @@ -299,24 +639,62 @@ case 'e': method = TEST_GETSERVENT; break; + case '2': + method = TEST_GETSERVENT_2PASS; + break; + case 's': + snapshot_file = strdup(optarg); + break; default: usage(); } + if (snapshot_file != NULL) { + if (access(snapshot_file, W_OK | R_OK) != 0) { + if (errno == ENOENT) { + rv = servent_build_snapshot(snapshot_file); + goto fin; + } else { + if (debug) + printf("can't access the file %s\n", + snapshot_file); + + rv = -1; + goto fin; + } + } + } + switch (method) { case TEST_GETSERVBYNAME: - rv = servent_1pass_test(servent_test_getservbyname); + if (snapshot_file == NULL) + rv = servent_1pass_test(servent_test_getservbyname); + else + rv = servent_snapshot_1pass_test(snapshot_file, + servent_test_getservbyname); break; case TEST_GETSERVBYPORT: - rv = servent_1pass_test(servent_test_getservbyport); + if (snapshot_file == NULL) + rv = servent_1pass_test(servent_test_getservbyport); + else + rv = servent_snapshot_1pass_test(snapshot_file, + servent_test_getservbyport); break; case TEST_GETSERVENT: + if (snapshot_file == NULL) + rv = servent_1pass_test(servent_test_getservent); + else + rv = servent_snapshot_2pass_test(snapshot_file); + break; + case TEST_GETSERVENT_2PASS: rv = servent_2pass_test(); break; default: rv = -1; break; }; - + +fin: + free(snapshot_file); return (rv); } ==== //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/test-getserv.t#2 (text+ko) ==== @@ -18,7 +18,8 @@ make $executable 2>&1 > /dev/null -echo 1..3 -do_test 1 'getservbyname()' '-n' -do_test 2 'getservbyport()' '-p' -do_test 3 'getservent()' '-e' +echo 1..4 +do_test 1 'getservbyname()' '-n' +do_test 2 'getservbyport()' '-p' +do_test 3 'getservent()' '-e' +do_test 4 'getservent() 2-pass' '-2' ==== //depot/projects/soc2006/nss_ldap_cached/src/tools/regression/lib/libc/nss/testutil.h#2 (text+ko) ==== @@ -28,19 +28,17 @@ #include <sys/queue.h> -#define FUNC_RET_CHECK(x) { if (!(x)) return (-1); } - #define DECLARE_TEST_DATA(ent) \ struct ent##_entry { \ struct ent data; \ - SLIST_ENTRY(ent##_entry) entries; \ + STAILQ_ENTRY(ent##_entry) entries; \ }; \ \ struct ent##_test_data { \ void (*clone_func)(struct ent *, struct ent const *); \ void (*free_func)(struct ent *); \ \ - SLIST_HEAD(ent_head, ent##_entry) snapshot_data; \ + STAILQ_HEAD(ent_head, ent##_entry) snapshot_data; \ }; \ \ static void test_data_init(struct ent##_test_data *, \ @@ -48,9 +46,11 @@ static void test_data_destroy(struct ent##_test_data *); \ \ static void test_data_append(struct ent##_test_data *, struct ent *data);\ -static int test_data_foreach(struct ent##_test_data *, int (*)(struct ent *));\ +static int test_data_foreach(struct ent##_test_data *, int (*)(struct ent *,\ + void *), void *); \ static int test_data_compare(struct ent##_test_data *, \ - struct ent##_test_data *, int (*)(struct ent *, struct ent *)); + struct ent##_test_data *, int (*)(struct ent *, struct ent *, \ + void *), void *); #define IMPLEMENT_TEST_DATA(ent) \ static void \ @@ -65,7 +65,7 @@ memset(td, 0, sizeof(*td)); \ td->clone_func = clonef; \ td->free_func = freef; \ - SLIST_INIT(&td->snapshot_data); \ + STAILQ_INIT(&td->snapshot_data); \ } \ \ static void \ @@ -74,9 +74,9 @@ struct ent##_entry *e; \ assert(td != NULL); \ \ - while (!SLIST_EMPTY(&td->snapshot_data)) { \ - e = SLIST_FIRST(&td->snapshot_data); \ - SLIST_REMOVE_HEAD(&td->snapshot_data, entries); \ + 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); \ @@ -96,11 +96,12 @@ memset(e, 0, sizeof(struct ent##_entry)); \ \ td->clone_func(&e->data, app_data); \ - SLIST_INSERT_HEAD(&td->snapshot_data, e, entries); \ + STAILQ_INSERT_TAIL(&td->snapshot_data, e, entries); \ } \ \ static int \ -test_data_foreach(struct ent##_test_data *td, int (*forf)(struct ent *))\ +test_data_foreach(struct ent##_test_data *td, \ + int (*forf)(struct ent *, void *), void *mdata) \ { \ struct ent##_entry *e; \ int rv; \ @@ -109,8 +110,8 @@ assert(forf != NULL); \ \ rv = 0; \ - SLIST_FOREACH(e, &td->snapshot_data, entries) { \ - rv = forf(&e->data); \ + STAILQ_FOREACH(e, &td->snapshot_data, entries) { \ + rv = forf(&e->data, mdata); \ if (rv != 0) \ break; \ } \ @@ -120,7 +121,7 @@ \ static int \ test_data_compare(struct ent##_test_data *td1, struct ent##_test_data *td2,\ - int (*cmp_func)(struct ent *, struct ent *)) \ + int (*cmp_func)(struct ent *, struct ent *, void *), void *mdata)\ { \ struct ent##_entry *e1, *e2; \ int rv; \ @@ -129,8 +130,8 @@ assert(td2 != NULL); \ assert(cmp_func != NULL); \ \ - e1 = SLIST_FIRST(&td1->snapshot_data); \ - e2 = SLIST_FIRST(&td2->snapshot_data); \ + e1 = STAILQ_FIRST(&td1->snapshot_data); \ + e2 = STAILQ_FIRST(&td2->snapshot_data); \ \ rv = 0; \ do { \ @@ -141,9 +142,9 @@ return (-1); \ } \ \ - rv = cmp_func(&e1->data, &e2->data); \ - e1 = SLIST_NEXT(e1, entries); \ - e2 = SLIST_NEXT(e2, entries); \ + rv = cmp_func(&e1->data, &e2->data, mdata); \ + e1 = STAILQ_NEXT(e1, entries); \ + e2 = STAILQ_NEXT(e2, entries); \ } while (rv == 0); \ \ return (rv); \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200607011034.k61AYQxd064935>