PERFORCE change 100389 for review
Michael Bushkov
bushman at FreeBSD.org
Sat Jul 1 10:34:27 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=100389
Change 100389 by bushman at 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); \
More information about the p4-projects
mailing list