getrpc_test.c revision 292323
1/*- 2 * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 13 * 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 24 * SUCH DAMAGE. 25 * 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD: head/lib/libc/tests/nss/getrpc_test.c 292323 2015-12-16 08:09:03Z ngie $"); 30 31#include <arpa/inet.h> 32#include <rpc/rpc.h> 33#include <errno.h> 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37#include <stringlist.h> 38#include <unistd.h> 39 40#include <atf-c.h> 41 42#include "testutil.h" 43 44enum test_methods { 45 TEST_GETRPCENT, 46 TEST_GETRPCBYNAME, 47 TEST_GETRPCBYNUMBER, 48 TEST_GETRPCENT_2PASS, 49 TEST_BUILD_SNAPSHOT 50}; 51 52DECLARE_TEST_DATA(rpcent) 53DECLARE_TEST_FILE_SNAPSHOT(rpcent) 54DECLARE_1PASS_TEST(rpcent) 55DECLARE_2PASS_TEST(rpcent) 56 57static void clone_rpcent(struct rpcent *, struct rpcent const *); 58static int compare_rpcent(struct rpcent *, struct rpcent *, void *); 59static void dump_rpcent(struct rpcent *); 60static void free_rpcent(struct rpcent *); 61 62static void sdump_rpcent(struct rpcent *, char *, size_t); 63static int rpcent_read_snapshot_func(struct rpcent *, char *); 64 65static int rpcent_check_ambiguity(struct rpcent_test_data *, 66 struct rpcent *); 67static int rpcent_fill_test_data(struct rpcent_test_data *); 68static int rpcent_test_correctness(struct rpcent *, void *); 69static int rpcent_test_getrpcbyname(struct rpcent *, void *); 70static int rpcent_test_getrpcbynumber(struct rpcent *, void *); 71static int rpcent_test_getrpcent(struct rpcent *, void *); 72 73static void usage(void) __attribute__((__noreturn__)); 74 75IMPLEMENT_TEST_DATA(rpcent) 76IMPLEMENT_TEST_FILE_SNAPSHOT(rpcent) 77IMPLEMENT_1PASS_TEST(rpcent) 78IMPLEMENT_2PASS_TEST(rpcent) 79 80static void 81clone_rpcent(struct rpcent *dest, struct rpcent const *src) 82{ 83 ATF_REQUIRE(dest != NULL); 84 ATF_REQUIRE(src != NULL); 85 86 char **cp; 87 int aliases_num; 88 89 memset(dest, 0, sizeof(struct rpcent)); 90 91 if (src->r_name != NULL) { 92 dest->r_name = strdup(src->r_name); 93 ATF_REQUIRE(dest->r_name != NULL); 94 } 95 96 dest->r_number = src->r_number; 97 98 if (src->r_aliases != NULL) { 99 aliases_num = 0; 100 for (cp = src->r_aliases; *cp; ++cp) 101 ++aliases_num; 102 103 dest->r_aliases = calloc(1, (aliases_num + 1) * sizeof(char *)); 104 ATF_REQUIRE(dest->r_aliases != NULL); 105 106 for (cp = src->r_aliases; *cp; ++cp) { 107 dest->r_aliases[cp - src->r_aliases] = strdup(*cp); 108 ATF_REQUIRE(dest->r_aliases[cp - src->r_aliases] != NULL); 109 } 110 } 111} 112 113static void 114free_rpcent(struct rpcent *rpc) 115{ 116 char **cp; 117 118 ATF_REQUIRE(rpc != NULL); 119 120 free(rpc->r_name); 121 122 for (cp = rpc->r_aliases; *cp; ++cp) 123 free(*cp); 124 free(rpc->r_aliases); 125} 126 127static int 128compare_rpcent(struct rpcent *rpc1, struct rpcent *rpc2, void *mdata) 129{ 130 char **c1, **c2; 131 132 if (rpc1 == rpc2) 133 return 0; 134 135 if ((rpc1 == NULL) || (rpc2 == NULL)) 136 goto errfin; 137 138 if ((strcmp(rpc1->r_name, rpc2->r_name) != 0) || 139 (rpc1->r_number != rpc2->r_number)) 140 goto errfin; 141 142 c1 = rpc1->r_aliases; 143 c2 = rpc2->r_aliases; 144 145 if ((rpc1->r_aliases == NULL) || (rpc2->r_aliases == NULL)) 146 goto errfin; 147 148 for (;*c1 && *c2; ++c1, ++c2) 149 if (strcmp(*c1, *c2) != 0) 150 goto errfin; 151 152 if ((*c1 != '\0') || (*c2 != '\0')) 153 goto errfin; 154 155 return 0; 156 157errfin: 158 if (mdata == NULL) { 159 printf("following structures are not equal:\n"); 160 dump_rpcent(rpc1); 161 dump_rpcent(rpc2); 162 } 163 164 return (-1); 165} 166 167static void 168sdump_rpcent(struct rpcent *rpc, char *buffer, size_t buflen) 169{ 170 char **cp; 171 int written; 172 173 written = snprintf(buffer, buflen, "%s %d", 174 rpc->r_name, rpc->r_number); 175 buffer += written; 176 if (written > buflen) 177 return; 178 buflen -= written; 179 180 if (rpc->r_aliases != NULL) { 181 if (*(rpc->r_aliases) != '\0') { 182 for (cp = rpc->r_aliases; *cp; ++cp) { 183 written = snprintf(buffer, buflen, " %s",*cp); 184 buffer += written; 185 if (written > buflen) 186 return; 187 buflen -= written; 188 189 if (buflen == 0) 190 return; 191 } 192 } else 193 snprintf(buffer, buflen, " noaliases"); 194 } else 195 snprintf(buffer, buflen, " (null)"); 196} 197 198static int 199rpcent_read_snapshot_func(struct rpcent *rpc, char *line) 200{ 201 StringList *sl; 202 char *s, *ps, *ts; 203 int i; 204 205 printf("1 line read from snapshot:\n%s\n", line); 206 207 i = 0; 208 sl = NULL; 209 ps = line; 210 memset(rpc, 0, sizeof(struct rpcent)); 211 while ((s = strsep(&ps, " ")) != NULL) { 212 switch (i) { 213 case 0: 214 rpc->r_name = strdup(s); 215 ATF_REQUIRE(rpc->r_name != NULL); 216 break; 217 218 case 1: 219 rpc->r_number = (int)strtol(s, &ts, 10); 220 if (*ts != '\0') { 221 free(rpc->r_name); 222 return (-1); 223 } 224 break; 225 226 default: 227 if (sl == NULL) { 228 if (strcmp(s, "(null)") == 0) 229 return (0); 230 231 sl = sl_init(); 232 ATF_REQUIRE(sl != NULL); 233 234 if (strcmp(s, "noaliases") != 0) { 235 ts = strdup(s); 236 ATF_REQUIRE(ts != NULL); 237 sl_add(sl, ts); 238 } 239 } else { 240 ts = strdup(s); 241 ATF_REQUIRE(ts != NULL); 242 sl_add(sl, ts); 243 } 244 break; 245 } 246 i++; 247 } 248 249 if (i < 3) { 250 free(rpc->r_name); 251 memset(rpc, 0, sizeof(struct rpcent)); 252 return (-1); 253 } 254 255 sl_add(sl, NULL); 256 rpc->r_aliases = sl->sl_str; 257 258 /* NOTE: is it a dirty hack or not? */ 259 free(sl); 260 return (0); 261} 262 263static void 264dump_rpcent(struct rpcent *result) 265{ 266 if (result != NULL) { 267 char buffer[1024]; 268 sdump_rpcent(result, buffer, sizeof(buffer)); 269 printf("%s\n", buffer); 270 } else 271 printf("(null)\n"); 272} 273 274static int 275rpcent_fill_test_data(struct rpcent_test_data *td) 276{ 277 struct rpcent *rpc; 278 279 setrpcent(1); 280 while ((rpc = getrpcent()) != NULL) { 281 if (rpcent_test_correctness(rpc, NULL) == 0) 282 TEST_DATA_APPEND(rpcent, td, rpc); 283 else 284 return (-1); 285 } 286 endrpcent(); 287 288 return (0); 289} 290 291static int 292rpcent_test_correctness(struct rpcent *rpc, void *mdata) 293{ 294 295 printf("testing correctness with the following data:\n"); 296 dump_rpcent(rpc); 297 298 if (rpc == NULL) 299 goto errfin; 300 301 if (rpc->r_name == NULL) 302 goto errfin; 303 304 if (rpc->r_number < 0) 305 goto errfin; 306 307 if (rpc->r_aliases == NULL) 308 goto errfin; 309 310 printf("correct\n"); 311 312 return (0); 313errfin: 314 printf("incorrect\n"); 315 316 return (-1); 317} 318 319/* rpcent_check_ambiguity() is needed when one port+rpc is associated with 320 * more than one peice (these cases are usually marked as PROBLEM in 321 * /etc/peices. This functions is needed also when one peice+rpc is 322 * associated with several ports. We have to check all the rpcent structures 323 * to make sure that rpc really exists and correct */ 324static int 325rpcent_check_ambiguity(struct rpcent_test_data *td, struct rpcent *rpc) 326{ 327 328 return (TEST_DATA_FIND(rpcent, td, rpc, compare_rpcent, 329 NULL) != NULL ? 0 : -1); 330} 331 332static int 333rpcent_test_getrpcbyname(struct rpcent *rpc_model, void *mdata) 334{ 335 char **alias; 336 struct rpcent *rpc; 337 338 printf("testing getrpcbyname() with the following data:\n"); 339 dump_rpcent(rpc_model); 340 341 rpc = getrpcbyname(rpc_model->r_name); 342 if (rpcent_test_correctness(rpc, NULL) != 0) 343 goto errfin; 344 345 if ((compare_rpcent(rpc, rpc_model, NULL) != 0) && 346 (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc) 347 !=0)) 348 goto errfin; 349 350 for (alias = rpc_model->r_aliases; *alias; ++alias) { 351 rpc = getrpcbyname(*alias); 352 353 if (rpcent_test_correctness(rpc, NULL) != 0) 354 goto errfin; 355 356 if ((compare_rpcent(rpc, rpc_model, NULL) != 0) && 357 (rpcent_check_ambiguity( 358 (struct rpcent_test_data *)mdata, rpc) != 0)) 359 goto errfin; 360 } 361 362 printf("ok\n"); 363 return (0); 364 365errfin: 366 printf("not ok\n"); 367 368 return (-1); 369} 370 371static int 372rpcent_test_getrpcbynumber(struct rpcent *rpc_model, void *mdata) 373{ 374 struct rpcent *rpc; 375 376 printf("testing getrpcbyport() with the following data...\n"); 377 dump_rpcent(rpc_model); 378 379 rpc = getrpcbynumber(rpc_model->r_number); 380 if (rpcent_test_correctness(rpc, NULL) != 0 || 381 (compare_rpcent(rpc, rpc_model, NULL) != 0 && 382 rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc) 383 != 0)) { 384 printf("not ok\n"); 385 return (-1); 386 } else { 387 printf("ok\n"); 388 return (0); 389 } 390} 391 392static int 393rpcent_test_getrpcent(struct rpcent *rpc, void *mdata) 394{ 395 396 /* 397 * Only correctness can be checked when doing 1-pass test for 398 * getrpcent(). 399 */ 400 return (rpcent_test_correctness(rpc, NULL)); 401} 402 403int 404run_tests(const char *snapshot_file, enum test_methods method) 405{ 406 struct rpcent_test_data td, td_snap, td_2pass; 407 int rv; 408 409 TEST_DATA_INIT(rpcent, &td, clone_rpcent, free_rpcent); 410 TEST_DATA_INIT(rpcent, &td_snap, clone_rpcent, free_rpcent); 411 if (snapshot_file != NULL) { 412 if (access(snapshot_file, W_OK | R_OK) != 0) { 413 if (errno == ENOENT) 414 method = TEST_BUILD_SNAPSHOT; 415 else { 416 printf("can't access the file %s\n", 417 snapshot_file); 418 419 rv = -1; 420 goto fin; 421 } 422 } else { 423 if (method == TEST_BUILD_SNAPSHOT) { 424 rv = 0; 425 goto fin; 426 } 427 428 TEST_SNAPSHOT_FILE_READ(rpcent, snapshot_file, 429 &td_snap, rpcent_read_snapshot_func); 430 } 431 } 432 433 rv = rpcent_fill_test_data(&td); 434 if (rv == -1) 435 return (-1); 436 switch (method) { 437 case TEST_GETRPCBYNAME: 438 if (snapshot_file == NULL) 439 rv = DO_1PASS_TEST(rpcent, &td, 440 rpcent_test_getrpcbyname, (void *)&td); 441 else 442 rv = DO_1PASS_TEST(rpcent, &td_snap, 443 rpcent_test_getrpcbyname, (void *)&td_snap); 444 break; 445 case TEST_GETRPCBYNUMBER: 446 if (snapshot_file == NULL) 447 rv = DO_1PASS_TEST(rpcent, &td, 448 rpcent_test_getrpcbynumber, (void *)&td); 449 else 450 rv = DO_1PASS_TEST(rpcent, &td_snap, 451 rpcent_test_getrpcbynumber, (void *)&td_snap); 452 break; 453 case TEST_GETRPCENT: 454 if (snapshot_file == NULL) 455 rv = DO_1PASS_TEST(rpcent, &td, rpcent_test_getrpcent, 456 (void *)&td); 457 else 458 rv = DO_2PASS_TEST(rpcent, &td, &td_snap, 459 compare_rpcent, NULL); 460 break; 461 case TEST_GETRPCENT_2PASS: 462 TEST_DATA_INIT(rpcent, &td_2pass, clone_rpcent, free_rpcent); 463 rv = rpcent_fill_test_data(&td_2pass); 464 if (rv != -1) 465 rv = DO_2PASS_TEST(rpcent, &td, &td_2pass, 466 compare_rpcent, NULL); 467 TEST_DATA_DESTROY(rpcent, &td_2pass); 468 break; 469 case TEST_BUILD_SNAPSHOT: 470 if (snapshot_file != NULL) 471 rv = TEST_SNAPSHOT_FILE_WRITE(rpcent, snapshot_file, &td, 472 sdump_rpcent); 473 break; 474 default: 475 rv = 0; 476 break; 477 } 478 479fin: 480 TEST_DATA_DESTROY(rpcent, &td_snap); 481 TEST_DATA_DESTROY(rpcent, &td); 482 483 return (rv); 484} 485 486#define SNAPSHOT_FILE "snapshot_rpc" 487 488ATF_TC_WITHOUT_HEAD(build_snapshot); 489ATF_TC_BODY(build_snapshot, tc) 490{ 491 492 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); 493} 494 495ATF_TC_WITHOUT_HEAD(getrpcbyname); 496ATF_TC_BODY(getrpcbyname, tc) 497{ 498 499 ATF_REQUIRE(run_tests(NULL, TEST_GETRPCBYNAME) == 0); 500} 501 502ATF_TC_WITHOUT_HEAD(getrpcbyname_with_snapshot); 503ATF_TC_BODY(getrpcbyname_with_snapshot, tc) 504{ 505 506 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); 507 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCBYNAME) == 0); 508} 509 510ATF_TC_WITHOUT_HEAD(getrpcbynumber); 511ATF_TC_BODY(getrpcbynumber, tc) 512{ 513 514 ATF_REQUIRE(run_tests(NULL, TEST_GETRPCBYNUMBER) == 0); 515} 516 517ATF_TC_WITHOUT_HEAD(getrpcbynumber_with_snapshot); 518ATF_TC_BODY(getrpcbynumber_with_snapshot, tc) 519{ 520 521 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); 522 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCBYNUMBER) == 0); 523} 524 525ATF_TC_WITHOUT_HEAD(getrpcbyent); 526ATF_TC_BODY(getrpcbyent, tc) 527{ 528 529 ATF_REQUIRE(run_tests(NULL, TEST_GETRPCENT) == 0); 530} 531 532ATF_TC_WITHOUT_HEAD(getrpcbyent_with_snapshot); 533ATF_TC_BODY(getrpcbyent_with_snapshot, tc) 534{ 535 536 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0); 537 ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCENT) == 0); 538} 539 540ATF_TC_WITHOUT_HEAD(getrpcbyent_with_two_pass); 541ATF_TC_BODY(getrpcbyent_with_two_pass, tc) 542{ 543 544 ATF_REQUIRE(run_tests(NULL, TEST_GETRPCENT_2PASS) == 0); 545} 546 547ATF_TP_ADD_TCS(tp) 548{ 549 550 ATF_TP_ADD_TC(tp, build_snapshot); 551 ATF_TP_ADD_TC(tp, getrpcbyname); 552 ATF_TP_ADD_TC(tp, getrpcbyname_with_snapshot); 553 ATF_TP_ADD_TC(tp, getrpcbynumber); 554 ATF_TP_ADD_TC(tp, getrpcbynumber_with_snapshot); 555 ATF_TP_ADD_TC(tp, getrpcbyent); 556 ATF_TP_ADD_TC(tp, getrpcbyent_with_snapshot); 557 ATF_TP_ADD_TC(tp, getrpcbyent_with_two_pass); 558 559 return (atf_no_error()); 560} 561