2 * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <arpa/inet.h>
38 #include <stringlist.h>
48 TEST_GETPROTOBYNUMBER,
49 TEST_GETPROTOENT_2PASS,
53 DECLARE_TEST_DATA(protoent)
54 DECLARE_TEST_FILE_SNAPSHOT(protoent)
55 DECLARE_1PASS_TEST(protoent)
56 DECLARE_2PASS_TEST(protoent)
58 static void clone_protoent(struct protoent *, struct protoent const *);
59 static int compare_protoent(struct protoent *, struct protoent *, void *);
60 static void dump_protoent(struct protoent *);
61 static void free_protoent(struct protoent *);
63 static void sdump_protoent(struct protoent *, char *, size_t);
64 static int protoent_read_snapshot_func(struct protoent *, char *);
66 static int protoent_check_ambiguity(struct protoent_test_data *,
68 static int protoent_fill_test_data(struct protoent_test_data *);
69 static int protoent_test_correctness(struct protoent *, void *);
70 static int protoent_test_getprotobyname(struct protoent *, void *);
71 static int protoent_test_getprotobynumber(struct protoent *, void *);
72 static int protoent_test_getprotoent(struct protoent *, void *);
74 IMPLEMENT_TEST_DATA(protoent)
75 IMPLEMENT_TEST_FILE_SNAPSHOT(protoent)
76 IMPLEMENT_1PASS_TEST(protoent)
77 IMPLEMENT_2PASS_TEST(protoent)
80 clone_protoent(struct protoent *dest, struct protoent const *src)
88 memset(dest, 0, sizeof(struct protoent));
90 if (src->p_name != NULL) {
91 dest->p_name = strdup(src->p_name);
92 assert(dest->p_name != NULL);
95 dest->p_proto = src->p_proto;
97 if (src->p_aliases != NULL) {
99 for (cp = src->p_aliases; *cp; ++cp)
102 dest->p_aliases = calloc(aliases_num + 1, sizeof(char *));
103 assert(dest->p_aliases != NULL);
105 for (cp = src->p_aliases; *cp; ++cp) {
106 dest->p_aliases[cp - src->p_aliases] = strdup(*cp);
107 assert(dest->p_aliases[cp - src->p_aliases] != NULL);
113 free_protoent(struct protoent *pe)
121 for (cp = pe->p_aliases; *cp; ++cp)
127 compare_protoent(struct protoent *pe1, struct protoent *pe2, void *mdata)
134 if ((pe1 == NULL) || (pe2 == NULL))
137 if ((strcmp(pe1->p_name, pe2->p_name) != 0) ||
138 (pe1->p_proto != pe2->p_proto))
144 if ((pe1->p_aliases == NULL) || (pe2->p_aliases == NULL))
147 for (;*c1 && *c2; ++c1, ++c2)
148 if (strcmp(*c1, *c2) != 0)
151 if ((*c1 != NULL) || (*c2 != NULL))
158 printf("following structures are not equal:\n");
167 sdump_protoent(struct protoent *pe, char *buffer, size_t buflen)
172 written = snprintf(buffer, buflen, "%s %d",
173 pe->p_name, pe->p_proto);
175 if (written > (int)buflen)
179 if (pe->p_aliases != NULL) {
180 if (*(pe->p_aliases) != NULL) {
181 for (cp = pe->p_aliases; *cp; ++cp) {
182 written = snprintf(buffer, buflen, " %s", *cp);
184 if (written > (int)buflen)
192 snprintf(buffer, buflen, " noaliases");
194 snprintf(buffer, buflen, " (null)");
198 protoent_read_snapshot_func(struct protoent *pe, char *line)
204 printf("1 line read from snapshot:\n%s\n", line);
209 memset(pe, 0, sizeof(struct protoent));
210 while ( (s = strsep(&ps, " ")) != NULL) {
213 pe->p_name = strdup(s);
214 assert(pe->p_name != NULL);
218 pe->p_proto = (int)strtol(s, &ts, 10);
227 if (strcmp(s, "(null)") == 0)
233 if (strcmp(s, "noaliases") != 0) {
250 memset(pe, 0, sizeof(struct protoent));
255 pe->p_aliases = sl->sl_str;
257 /* NOTE: is it a dirty hack or not? */
263 dump_protoent(struct protoent *result)
265 if (result != NULL) {
267 sdump_protoent(result, buffer, sizeof(buffer));
268 printf("%s\n", buffer);
274 protoent_fill_test_data(struct protoent_test_data *td)
279 while ((pe = getprotoent()) != NULL) {
280 if (protoent_test_correctness(pe, NULL) == 0)
281 TEST_DATA_APPEND(protoent, td, pe);
291 protoent_test_correctness(struct protoent *pe, void *mdata __unused)
293 printf("testing correctness with the following data:\n");
299 if (pe->p_name == NULL)
305 if (pe->p_aliases == NULL)
312 printf("incorrect\n");
317 /* protoent_check_ambiguity() is needed when one port+proto is associated with
318 * more than one piece (these cases are usually marked as PROBLEM in
319 * /etc/peices. This functions is needed also when one piece+proto is
320 * associated with several ports. We have to check all the protoent structures
321 * to make sure that pe really exists and correct */
323 protoent_check_ambiguity(struct protoent_test_data *td, struct protoent *pe)
326 return (TEST_DATA_FIND(protoent, td, pe, compare_protoent,
327 NULL) != NULL ? 0 : -1);
331 protoent_test_getprotobyname(struct protoent *pe_model, void *mdata)
336 printf("testing getprotobyname() with the following data:\n");
337 dump_protoent(pe_model);
339 pe = getprotobyname(pe_model->p_name);
340 if (protoent_test_correctness(pe, NULL) != 0)
343 if ((compare_protoent(pe, pe_model, NULL) != 0) &&
344 (protoent_check_ambiguity((struct protoent_test_data *)mdata, pe)
348 for (alias = pe_model->p_aliases; *alias; ++alias) {
349 pe = getprotobyname(*alias);
351 if (protoent_test_correctness(pe, NULL) != 0)
354 if ((compare_protoent(pe, pe_model, NULL) != 0) &&
355 (protoent_check_ambiguity(
356 (struct protoent_test_data *)mdata, pe) != 0))
370 protoent_test_getprotobynumber(struct protoent *pe_model, void *mdata)
374 printf("testing getprotobyport() with the following data...\n");
375 dump_protoent(pe_model);
377 pe = getprotobynumber(pe_model->p_proto);
378 if ((protoent_test_correctness(pe, NULL) != 0) ||
379 ((compare_protoent(pe, pe_model, NULL) != 0) &&
380 (protoent_check_ambiguity((struct protoent_test_data *)mdata, pe)
391 protoent_test_getprotoent(struct protoent *pe, void *mdata __unused)
393 /* Only correctness can be checked when doing 1-pass test for
395 return (protoent_test_correctness(pe, NULL));
399 run_tests(const char *snapshot_file, enum test_methods method)
401 struct protoent_test_data td, td_snap, td_2pass;
404 TEST_DATA_INIT(protoent, &td, clone_protoent, free_protoent);
405 TEST_DATA_INIT(protoent, &td_snap, clone_protoent, free_protoent);
406 if (snapshot_file != NULL) {
407 if (access(snapshot_file, W_OK | R_OK) != 0) {
409 method = TEST_BUILD_SNAPSHOT;
411 printf("can't access the file %s\n",
418 if (method == TEST_BUILD_SNAPSHOT) {
423 TEST_SNAPSHOT_FILE_READ(protoent, snapshot_file,
424 &td_snap, protoent_read_snapshot_func);
428 rv = protoent_fill_test_data(&td);
432 case TEST_GETPROTOBYNAME:
433 if (snapshot_file == NULL)
434 rv = DO_1PASS_TEST(protoent, &td,
435 protoent_test_getprotobyname, (void *)&td);
437 rv = DO_1PASS_TEST(protoent, &td_snap,
438 protoent_test_getprotobyname, (void *)&td_snap);
440 case TEST_GETPROTOBYNUMBER:
441 if (snapshot_file == NULL)
442 rv = DO_1PASS_TEST(protoent, &td,
443 protoent_test_getprotobynumber, (void *)&td);
445 rv = DO_1PASS_TEST(protoent, &td_snap,
446 protoent_test_getprotobynumber, (void *)&td_snap);
448 case TEST_GETPROTOENT:
449 if (snapshot_file == NULL)
450 rv = DO_1PASS_TEST(protoent, &td,
451 protoent_test_getprotoent, (void *)&td);
453 rv = DO_2PASS_TEST(protoent, &td, &td_snap,
454 compare_protoent, NULL);
456 case TEST_GETPROTOENT_2PASS:
457 TEST_DATA_INIT(protoent, &td_2pass, clone_protoent,
459 rv = protoent_fill_test_data(&td_2pass);
461 rv = DO_2PASS_TEST(protoent, &td, &td_2pass,
462 compare_protoent, NULL);
463 TEST_DATA_DESTROY(protoent, &td_2pass);
465 case TEST_BUILD_SNAPSHOT:
466 if (snapshot_file != NULL)
467 rv = TEST_SNAPSHOT_FILE_WRITE(protoent, snapshot_file,
468 &td, sdump_protoent);
476 TEST_DATA_DESTROY(protoent, &td_snap);
477 TEST_DATA_DESTROY(protoent, &td);
482 #define SNAPSHOT_FILE "snapshot_proto"
484 ATF_TC_WITHOUT_HEAD(build_snapshot);
485 ATF_TC_BODY(build_snapshot, tc)
488 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
491 ATF_TC_WITHOUT_HEAD(getprotoent);
492 ATF_TC_BODY(getprotoent, tc)
495 ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOENT) == 0);
498 ATF_TC_WITHOUT_HEAD(getprotoent_with_snapshot);
499 ATF_TC_BODY(getprotoent_with_snapshot, tc)
502 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
503 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOENT) == 0);
506 ATF_TC_WITHOUT_HEAD(getprotoent_with_two_pass);
507 ATF_TC_BODY(getprotoent_with_two_pass, tc)
510 ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOENT_2PASS) == 0);
513 ATF_TC_WITHOUT_HEAD(getprotobyname);
514 ATF_TC_BODY(getprotobyname, tc)
517 ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOBYNAME) == 0);
520 ATF_TC_WITHOUT_HEAD(getprotobyname_with_snapshot);
521 ATF_TC_BODY(getprotobyname_with_snapshot, tc)
524 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
525 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOBYNAME) == 0);
528 ATF_TC_WITHOUT_HEAD(getprotobynumber);
529 ATF_TC_BODY(getprotobynumber, tc)
532 ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOBYNUMBER) == 0);
535 ATF_TC_WITHOUT_HEAD(getprotobynumber_with_snapshot);
536 ATF_TC_BODY(getprotobynumber_with_snapshot, tc)
539 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
540 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOBYNUMBER) == 0);
546 ATF_TP_ADD_TC(tp, build_snapshot);
547 ATF_TP_ADD_TC(tp, getprotoent);
548 ATF_TP_ADD_TC(tp, getprotoent_with_snapshot);
549 ATF_TP_ADD_TC(tp, getprotoent_with_two_pass);
550 ATF_TP_ADD_TC(tp, getprotobyname);
551 ATF_TP_ADD_TC(tp, getprotobyname_with_snapshot);
552 ATF_TP_ADD_TC(tp, getprotobynumber);
553 ATF_TP_ADD_TC(tp, getprotobynumber_with_snapshot);
555 return (atf_no_error());