Path: blob/main/lib/libc/tests/nss/getproto_test.c
39491 views
/*-1* Copyright (c) 2006 Michael Bushkov <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*25*/2627#include <arpa/inet.h>28#include <assert.h>29#include <errno.h>30#include <netdb.h>31#include <stdio.h>32#include <stdlib.h>33#include <string.h>34#include <stringlist.h>35#include <unistd.h>3637#include <atf-c.h>3839#include "testutil.h"4041enum test_methods {42TEST_GETPROTOENT,43TEST_GETPROTOBYNAME,44TEST_GETPROTOBYNUMBER,45TEST_GETPROTOENT_2PASS,46TEST_BUILD_SNAPSHOT47};4849DECLARE_TEST_DATA(protoent)50DECLARE_TEST_FILE_SNAPSHOT(protoent)51DECLARE_1PASS_TEST(protoent)52DECLARE_2PASS_TEST(protoent)5354static void clone_protoent(struct protoent *, struct protoent const *);55static int compare_protoent(struct protoent *, struct protoent *, void *);56static void dump_protoent(struct protoent *);57static void free_protoent(struct protoent *);5859static void sdump_protoent(struct protoent *, char *, size_t);60static int protoent_read_snapshot_func(struct protoent *, char *);6162static int protoent_check_ambiguity(struct protoent_test_data *,63struct protoent *);64static int protoent_fill_test_data(struct protoent_test_data *);65static int protoent_test_correctness(struct protoent *, void *);66static int protoent_test_getprotobyname(struct protoent *, void *);67static int protoent_test_getprotobynumber(struct protoent *, void *);68static int protoent_test_getprotoent(struct protoent *, void *);6970IMPLEMENT_TEST_DATA(protoent)71IMPLEMENT_TEST_FILE_SNAPSHOT(protoent)72IMPLEMENT_1PASS_TEST(protoent)73IMPLEMENT_2PASS_TEST(protoent)7475static void76clone_protoent(struct protoent *dest, struct protoent const *src)77{78assert(dest != NULL);79assert(src != NULL);8081char **cp;82int aliases_num;8384memset(dest, 0, sizeof(struct protoent));8586if (src->p_name != NULL) {87dest->p_name = strdup(src->p_name);88assert(dest->p_name != NULL);89}9091dest->p_proto = src->p_proto;9293if (src->p_aliases != NULL) {94aliases_num = 0;95for (cp = src->p_aliases; *cp; ++cp)96++aliases_num;9798dest->p_aliases = calloc(aliases_num + 1, sizeof(char *));99assert(dest->p_aliases != NULL);100101for (cp = src->p_aliases; *cp; ++cp) {102dest->p_aliases[cp - src->p_aliases] = strdup(*cp);103assert(dest->p_aliases[cp - src->p_aliases] != NULL);104}105}106}107108static void109free_protoent(struct protoent *pe)110{111char **cp;112113assert(pe != NULL);114115free(pe->p_name);116117for (cp = pe->p_aliases; *cp; ++cp)118free(*cp);119free(pe->p_aliases);120}121122static int123compare_protoent(struct protoent *pe1, struct protoent *pe2, void *mdata)124{125char **c1, **c2;126127if (pe1 == pe2)128return 0;129130if ((pe1 == NULL) || (pe2 == NULL))131goto errfin;132133if ((strcmp(pe1->p_name, pe2->p_name) != 0) ||134(pe1->p_proto != pe2->p_proto))135goto errfin;136137c1 = pe1->p_aliases;138c2 = pe2->p_aliases;139140if ((pe1->p_aliases == NULL) || (pe2->p_aliases == NULL))141goto errfin;142143for (;*c1 && *c2; ++c1, ++c2)144if (strcmp(*c1, *c2) != 0)145goto errfin;146147if ((*c1 != NULL) || (*c2 != NULL))148goto errfin;149150return 0;151152errfin:153if (mdata == NULL) {154printf("following structures are not equal:\n");155dump_protoent(pe1);156dump_protoent(pe2);157}158159return (-1);160}161162static void163sdump_protoent(struct protoent *pe, char *buffer, size_t buflen)164{165char **cp;166int written;167168written = snprintf(buffer, buflen, "%s %d",169pe->p_name, pe->p_proto);170buffer += written;171if (written > (int)buflen)172return;173buflen -= written;174175if (pe->p_aliases != NULL) {176if (*(pe->p_aliases) != NULL) {177for (cp = pe->p_aliases; *cp; ++cp) {178written = snprintf(buffer, buflen, " %s", *cp);179buffer += written;180if (written > (int)buflen)181return;182buflen -= written;183184if (buflen == 0)185return;186}187} else188snprintf(buffer, buflen, " noaliases");189} else190snprintf(buffer, buflen, " (null)");191}192193static int194protoent_read_snapshot_func(struct protoent *pe, char *line)195{196StringList *sl;197char *s, *ps, *ts;198int i;199200printf("1 line read from snapshot:\n%s\n", line);201202i = 0;203sl = NULL;204ps = line;205memset(pe, 0, sizeof(struct protoent));206while ( (s = strsep(&ps, " ")) != NULL) {207switch (i) {208case 0:209pe->p_name = strdup(s);210assert(pe->p_name != NULL);211break;212213case 1:214pe->p_proto = (int)strtol(s, &ts, 10);215if (*ts != '\0') {216free(pe->p_name);217return (-1);218}219break;220221default:222if (sl == NULL) {223if (strcmp(s, "(null)") == 0)224return (0);225226sl = sl_init();227assert(sl != NULL);228229if (strcmp(s, "noaliases") != 0) {230ts = strdup(s);231assert(ts != NULL);232sl_add(sl, ts);233}234} else {235ts = strdup(s);236assert(ts != NULL);237sl_add(sl, ts);238}239break;240}241++i;242}243244if (i < 3) {245free(pe->p_name);246memset(pe, 0, sizeof(struct protoent));247return (-1);248}249250sl_add(sl, NULL);251pe->p_aliases = sl->sl_str;252253/* NOTE: is it a dirty hack or not? */254free(sl);255return (0);256}257258static void259dump_protoent(struct protoent *result)260{261if (result != NULL) {262char buffer[1024];263sdump_protoent(result, buffer, sizeof(buffer));264printf("%s\n", buffer);265} else266printf("(null)\n");267}268269static int270protoent_fill_test_data(struct protoent_test_data *td)271{272struct protoent *pe;273274setprotoent(1);275while ((pe = getprotoent()) != NULL) {276if (protoent_test_correctness(pe, NULL) == 0)277TEST_DATA_APPEND(protoent, td, pe);278else279return (-1);280}281endprotoent();282283return (0);284}285286static int287protoent_test_correctness(struct protoent *pe, void *mdata __unused)288{289printf("testing correctness with the following data:\n");290dump_protoent(pe);291292if (pe == NULL)293goto errfin;294295if (pe->p_name == NULL)296goto errfin;297298if (pe->p_proto < 0)299goto errfin;300301if (pe->p_aliases == NULL)302goto errfin;303304printf("correct\n");305306return (0);307errfin:308printf("incorrect\n");309310return (-1);311}312313/* protoent_check_ambiguity() is needed when one port+proto is associated with314* more than one piece (these cases are usually marked as PROBLEM in315* /etc/peices. This functions is needed also when one piece+proto is316* associated with several ports. We have to check all the protoent structures317* to make sure that pe really exists and correct */318static int319protoent_check_ambiguity(struct protoent_test_data *td, struct protoent *pe)320{321322return (TEST_DATA_FIND(protoent, td, pe, compare_protoent,323NULL) != NULL ? 0 : -1);324}325326static int327protoent_test_getprotobyname(struct protoent *pe_model, void *mdata)328{329char **alias;330struct protoent *pe;331332printf("testing getprotobyname() with the following data:\n");333dump_protoent(pe_model);334335pe = getprotobyname(pe_model->p_name);336if (protoent_test_correctness(pe, NULL) != 0)337goto errfin;338339if ((compare_protoent(pe, pe_model, NULL) != 0) &&340(protoent_check_ambiguity((struct protoent_test_data *)mdata, pe)341!=0))342goto errfin;343344for (alias = pe_model->p_aliases; *alias; ++alias) {345pe = getprotobyname(*alias);346347if (protoent_test_correctness(pe, NULL) != 0)348goto errfin;349350if ((compare_protoent(pe, pe_model, NULL) != 0) &&351(protoent_check_ambiguity(352(struct protoent_test_data *)mdata, pe) != 0))353goto errfin;354}355356printf("ok\n");357return (0);358359errfin:360printf("not ok\n");361362return (-1);363}364365static int366protoent_test_getprotobynumber(struct protoent *pe_model, void *mdata)367{368struct protoent *pe;369370printf("testing getprotobyport() with the following data...\n");371dump_protoent(pe_model);372373pe = getprotobynumber(pe_model->p_proto);374if ((protoent_test_correctness(pe, NULL) != 0) ||375((compare_protoent(pe, pe_model, NULL) != 0) &&376(protoent_check_ambiguity((struct protoent_test_data *)mdata, pe)377!= 0))) {378printf("not ok\n");379return (-1);380} else {381printf("ok\n");382return (0);383}384}385386static int387protoent_test_getprotoent(struct protoent *pe, void *mdata __unused)388{389/* Only correctness can be checked when doing 1-pass test for390* getprotoent(). */391return (protoent_test_correctness(pe, NULL));392}393394static int395run_tests(const char *snapshot_file, enum test_methods method)396{397struct protoent_test_data td, td_snap, td_2pass;398int rv;399400TEST_DATA_INIT(protoent, &td, clone_protoent, free_protoent);401TEST_DATA_INIT(protoent, &td_snap, clone_protoent, free_protoent);402if (snapshot_file != NULL) {403if (access(snapshot_file, W_OK | R_OK) != 0) {404if (errno == ENOENT)405method = TEST_BUILD_SNAPSHOT;406else {407printf("can't access the file %s\n",408snapshot_file);409410rv = -1;411goto fin;412}413} else {414if (method == TEST_BUILD_SNAPSHOT) {415rv = 0;416goto fin;417}418419TEST_SNAPSHOT_FILE_READ(protoent, snapshot_file,420&td_snap, protoent_read_snapshot_func);421}422}423424rv = protoent_fill_test_data(&td);425if (rv == -1)426return (-1);427switch (method) {428case TEST_GETPROTOBYNAME:429if (snapshot_file == NULL)430rv = DO_1PASS_TEST(protoent, &td,431protoent_test_getprotobyname, (void *)&td);432else433rv = DO_1PASS_TEST(protoent, &td_snap,434protoent_test_getprotobyname, (void *)&td_snap);435break;436case TEST_GETPROTOBYNUMBER:437if (snapshot_file == NULL)438rv = DO_1PASS_TEST(protoent, &td,439protoent_test_getprotobynumber, (void *)&td);440else441rv = DO_1PASS_TEST(protoent, &td_snap,442protoent_test_getprotobynumber, (void *)&td_snap);443break;444case TEST_GETPROTOENT:445if (snapshot_file == NULL)446rv = DO_1PASS_TEST(protoent, &td,447protoent_test_getprotoent, (void *)&td);448else449rv = DO_2PASS_TEST(protoent, &td, &td_snap,450compare_protoent, NULL);451break;452case TEST_GETPROTOENT_2PASS:453TEST_DATA_INIT(protoent, &td_2pass, clone_protoent,454free_protoent);455rv = protoent_fill_test_data(&td_2pass);456if (rv != -1)457rv = DO_2PASS_TEST(protoent, &td, &td_2pass,458compare_protoent, NULL);459TEST_DATA_DESTROY(protoent, &td_2pass);460break;461case TEST_BUILD_SNAPSHOT:462if (snapshot_file != NULL)463rv = TEST_SNAPSHOT_FILE_WRITE(protoent, snapshot_file,464&td, sdump_protoent);465break;466default:467rv = 0;468break;469}470471fin:472TEST_DATA_DESTROY(protoent, &td_snap);473TEST_DATA_DESTROY(protoent, &td);474475return (rv);476}477478#define SNAPSHOT_FILE "snapshot_proto"479480ATF_TC_WITHOUT_HEAD(build_snapshot);481ATF_TC_BODY(build_snapshot, tc)482{483484ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);485}486487ATF_TC_WITHOUT_HEAD(getprotoent);488ATF_TC_BODY(getprotoent, tc)489{490491ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOENT) == 0);492}493494ATF_TC_WITHOUT_HEAD(getprotoent_with_snapshot);495ATF_TC_BODY(getprotoent_with_snapshot, tc)496{497498ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);499ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOENT) == 0);500}501502ATF_TC_WITHOUT_HEAD(getprotoent_with_two_pass);503ATF_TC_BODY(getprotoent_with_two_pass, tc)504{505506ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOENT_2PASS) == 0);507}508509ATF_TC_WITHOUT_HEAD(getprotobyname);510ATF_TC_BODY(getprotobyname, tc)511{512513ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOBYNAME) == 0);514}515516ATF_TC_WITHOUT_HEAD(getprotobyname_with_snapshot);517ATF_TC_BODY(getprotobyname_with_snapshot, tc)518{519520ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);521ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOBYNAME) == 0);522}523524ATF_TC_WITHOUT_HEAD(getprotobynumber);525ATF_TC_BODY(getprotobynumber, tc)526{527528ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOBYNUMBER) == 0);529}530531ATF_TC_WITHOUT_HEAD(getprotobynumber_with_snapshot);532ATF_TC_BODY(getprotobynumber_with_snapshot, tc)533{534535ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);536ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOBYNUMBER) == 0);537}538539ATF_TP_ADD_TCS(tp)540{541542ATF_TP_ADD_TC(tp, build_snapshot);543ATF_TP_ADD_TC(tp, getprotoent);544ATF_TP_ADD_TC(tp, getprotoent_with_snapshot);545ATF_TP_ADD_TC(tp, getprotoent_with_two_pass);546ATF_TP_ADD_TC(tp, getprotobyname);547ATF_TP_ADD_TC(tp, getprotobyname_with_snapshot);548ATF_TP_ADD_TC(tp, getprotobynumber);549ATF_TP_ADD_TC(tp, getprotobynumber_with_snapshot);550551return (atf_no_error());552}553554555