getrpc_test.c revision 168754
1257378Sbdrewery/*- 2257378Sbdrewery * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> 3257378Sbdrewery * All rights repeed. 4257378Sbdrewery * 5257378Sbdrewery * Redistribution and use in source and binary forms, with or without 6257378Sbdrewery * modification, are permitted provided that the following conditions 7257378Sbdrewery * are met: 8257378Sbdrewery * 1. Redistributions of source code must retain the above copyright 9257378Sbdrewery * notice, this list of conditions and the following disclaimer. 10257378Sbdrewery * 2. Redistributions in binary form must reproduce the above copyright 11257378Sbdrewery * notice, this list of conditions and the following disclaimer in the 12257378Sbdrewery * documentation and/or other materials provided with the distribution. 13257378Sbdrewery * 14257378Sbdrewery * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15257378Sbdrewery * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16257378Sbdrewery * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17257378Sbdrewery * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18257378Sbdrewery * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19257378Sbdrewery * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20257378Sbdrewery * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21257378Sbdrewery * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22257378Sbdrewery * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23257378Sbdrewery * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24257378Sbdrewery * SUCH DAMAGE. 25257378Sbdrewery * 26257378Sbdrewery */ 27263038Sbapt 28257378Sbdrewery#include <sys/cdefs.h> 29257378Sbdrewery__FBSDID("$FreeBSD: head/tools/regression/lib/libc/nss/test-getrpc.c 168754 2007-04-15 11:02:31Z bushman $"); 30257378Sbdrewery 31257378Sbdrewery#include <arpa/inet.h> 32263038Sbapt#include <rpc/rpc.h> 33257378Sbdrewery#include <assert.h> 34257378Sbdrewery#include <errno.h> 35257378Sbdrewery#include <stdio.h> 36257378Sbdrewery#include <stdlib.h> 37257378Sbdrewery#include <string.h> 38263038Sbapt#include <stringlist.h> 39257378Sbdrewery#include <unistd.h> 40257378Sbdrewery#include "testutil.h" 41257378Sbdrewery 42257378Sbdreweryenum test_methods { 43257378Sbdrewery TEST_GETRPCENT, 44263038Sbapt TEST_GETRPCBYNAME, 45257378Sbdrewery TEST_GETRPCBYNUMBER, 46257378Sbdrewery TEST_GETRPCENT_2PASS, 47257378Sbdrewery TEST_BUILD_SNAPSHOT 48257378Sbdrewery}; 49257378Sbdrewery 50257378Sbdrewerystatic int debug = 0; 51257378Sbdrewerystatic enum test_methods method = TEST_BUILD_SNAPSHOT; 52257378Sbdrewery 53257378SbdreweryDECLARE_TEST_DATA(rpcent) 54257378SbdreweryDECLARE_TEST_FILE_SNAPSHOT(rpcent) 55257378SbdreweryDECLARE_1PASS_TEST(rpcent) 56257378SbdreweryDECLARE_2PASS_TEST(rpcent) 57257378Sbdrewery 58257378Sbdrewerystatic void clone_rpcent(struct rpcent *, struct rpcent const *); 59257378Sbdrewerystatic int compare_rpcent(struct rpcent *, struct rpcent *, void *); 60263038Sbaptstatic void dump_rpcent(struct rpcent *); 61257378Sbdrewerystatic void free_rpcent(struct rpcent *); 62257378Sbdrewery 63257378Sbdrewerystatic void sdump_rpcent(struct rpcent *, char *, size_t); 64257378Sbdrewerystatic int rpcent_read_snapshot_func(struct rpcent *, char *); 65257378Sbdrewery 66257378Sbdrewerystatic int rpcent_check_ambiguity(struct rpcent_test_data *, 67257378Sbdrewery struct rpcent *); 68263038Sbaptstatic int rpcent_fill_test_data(struct rpcent_test_data *); 69257378Sbdrewerystatic int rpcent_test_correctness(struct rpcent *, void *); 70257378Sbdrewerystatic int rpcent_test_getrpcbyname(struct rpcent *, void *); 71257378Sbdrewerystatic int rpcent_test_getrpcbynumber(struct rpcent *, void *); 72257378Sbdrewerystatic int rpcent_test_getrpcent(struct rpcent *, void *); 73257378Sbdrewery 74257378Sbdrewerystatic void usage(void) __attribute__((__noreturn__)); 75257378Sbdrewery 76257378SbdreweryIMPLEMENT_TEST_DATA(rpcent) 77263038SbaptIMPLEMENT_TEST_FILE_SNAPSHOT(rpcent) 78263038SbaptIMPLEMENT_1PASS_TEST(rpcent) 79263038SbaptIMPLEMENT_2PASS_TEST(rpcent) 80263038Sbapt 81263038Sbaptstatic void 82257378Sbdreweryclone_rpcent(struct rpcent *dest, struct rpcent const *src) 83257378Sbdrewery{ 84257378Sbdrewery assert(dest != NULL); 85257378Sbdrewery assert(src != NULL); 86257378Sbdrewery 87257378Sbdrewery char **cp; 88263038Sbapt int aliases_num; 89257378Sbdrewery 90257378Sbdrewery memset(dest, 0, sizeof(struct rpcent)); 91257378Sbdrewery 92263038Sbapt if (src->r_name != NULL) { 93263038Sbapt dest->r_name = strdup(src->r_name); 94263038Sbapt assert(dest->r_name != NULL); 95263038Sbapt } 96263038Sbapt 97257378Sbdrewery dest->r_number = src->r_number; 98257378Sbdrewery 99257378Sbdrewery if (src->r_aliases != NULL) { 100257378Sbdrewery aliases_num = 0; 101257378Sbdrewery for (cp = src->r_aliases; *cp; ++cp) 102257378Sbdrewery ++aliases_num; 103257378Sbdrewery 104257378Sbdrewery dest->r_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *))); 105257378Sbdrewery assert(dest->r_aliases != NULL); 106257378Sbdrewery memset(dest->r_aliases, 0, (aliases_num+1) * (sizeof(char *))); 107257378Sbdrewery 108257378Sbdrewery for (cp = src->r_aliases; *cp; ++cp) { 109257378Sbdrewery dest->r_aliases[cp - src->r_aliases] = strdup(*cp); 110257378Sbdrewery assert(dest->r_aliases[cp - src->r_aliases] != NULL); 111263038Sbapt } 112257378Sbdrewery } 113257378Sbdrewery} 114257378Sbdrewery 115257378Sbdrewerystatic void 116257378Sbdreweryfree_rpcent(struct rpcent *rpc) 117257378Sbdrewery{ 118257378Sbdrewery char **cp; 119257378Sbdrewery 120257378Sbdrewery assert(rpc != NULL); 121257378Sbdrewery 122257378Sbdrewery free(rpc->r_name); 123257378Sbdrewery 124257378Sbdrewery for (cp = rpc->r_aliases; *cp; ++cp) 125257378Sbdrewery free(*cp); 126257378Sbdrewery free(rpc->r_aliases); 127257378Sbdrewery} 128257378Sbdrewery 129257378Sbdrewerystatic int 130257378Sbdrewerycompare_rpcent(struct rpcent *rpc1, struct rpcent *rpc2, void *mdata) 131257378Sbdrewery{ 132257378Sbdrewery char **c1, **c2; 133257378Sbdrewery 134257378Sbdrewery if (rpc1 == rpc2) 135257378Sbdrewery return 0; 136257378Sbdrewery 137257378Sbdrewery if ((rpc1 == NULL) || (rpc2 == NULL)) 138257378Sbdrewery goto errfin; 139257378Sbdrewery 140257378Sbdrewery if ((strcmp(rpc1->r_name, rpc2->r_name) != 0) || 141257378Sbdrewery (rpc1->r_number != rpc2->r_number)) 142257378Sbdrewery goto errfin; 143257378Sbdrewery 144257378Sbdrewery c1 = rpc1->r_aliases; 145257378Sbdrewery c2 = rpc2->r_aliases; 146257378Sbdrewery 147257378Sbdrewery if ((rpc1->r_aliases == NULL) || (rpc2->r_aliases == NULL)) 148257378Sbdrewery goto errfin; 149257378Sbdrewery 150263038Sbapt for (;*c1 && *c2; ++c1, ++c2) 151257378Sbdrewery if (strcmp(*c1, *c2) != 0) 152257378Sbdrewery goto errfin; 153257378Sbdrewery 154257378Sbdrewery if ((*c1 != '\0') || (*c2 != '\0')) 155263038Sbapt goto errfin; 156257378Sbdrewery 157263038Sbapt return 0; 158257378Sbdrewery 159257378Sbdreweryerrfin: 160257378Sbdrewery if ((debug) && (mdata == NULL)) { 161257378Sbdrewery printf("following structures are not equal:\n"); 162257378Sbdrewery dump_rpcent(rpc1); 163257378Sbdrewery dump_rpcent(rpc2); 164257378Sbdrewery } 165257378Sbdrewery 166257378Sbdrewery return (-1); 167257378Sbdrewery} 168257378Sbdrewery 169257378Sbdrewerystatic void 170257378Sbdrewerysdump_rpcent(struct rpcent *rpc, char *buffer, size_t buflen) 171257378Sbdrewery{ 172257378Sbdrewery char **cp; 173257378Sbdrewery int written; 174257378Sbdrewery 175257378Sbdrewery written = snprintf(buffer, buflen, "%s %d", 176257378Sbdrewery rpc->r_name, rpc->r_number); 177257378Sbdrewery buffer += written; 178257378Sbdrewery if (written > buflen) 179257378Sbdrewery return; 180257378Sbdrewery buflen -= written; 181257378Sbdrewery 182257378Sbdrewery if (rpc->r_aliases != NULL) { 183257378Sbdrewery if (*(rpc->r_aliases) != '\0') { 184257378Sbdrewery for (cp = rpc->r_aliases; *cp; ++cp) { 185257378Sbdrewery written = snprintf(buffer, buflen, " %s",*cp); 186257378Sbdrewery buffer += written; 187257378Sbdrewery if (written > buflen) 188257378Sbdrewery return; 189257378Sbdrewery buflen -= written; 190257378Sbdrewery 191257378Sbdrewery if (buflen == 0) 192257378Sbdrewery return; 193257378Sbdrewery } 194257378Sbdrewery } else 195257378Sbdrewery snprintf(buffer, buflen, " noaliases"); 196257378Sbdrewery } else 197257378Sbdrewery snprintf(buffer, buflen, " (null)"); 198263038Sbapt} 199263038Sbapt 200263038Sbaptstatic int 201257378Sbdreweryrpcent_read_snapshot_func(struct rpcent *rpc, char *line) 202257378Sbdrewery{ 203257378Sbdrewery StringList *sl; 204263038Sbapt char *s, *ps, *ts; 205263038Sbapt int i; 206263038Sbapt 207257378Sbdrewery if (debug) 208257378Sbdrewery printf("1 line read from snapshot:\n%s\n", line); 209257378Sbdrewery 210257378Sbdrewery i = 0; 211263038Sbapt sl = NULL; 212257378Sbdrewery ps = line; 213257378Sbdrewery memset(rpc, 0, sizeof(struct rpcent)); 214257378Sbdrewery while ( (s = strsep(&ps, " ")) != NULL) { 215257378Sbdrewery switch (i) { 216257378Sbdrewery case 0: 217257378Sbdrewery rpc->r_name = strdup(s); 218257378Sbdrewery assert(rpc->r_name != NULL); 219257378Sbdrewery break; 220257378Sbdrewery 221257378Sbdrewery case 1: 222257378Sbdrewery rpc->r_number = (int)strtol(s, &ts, 10); 223257378Sbdrewery if (*ts != '\0') { 224257378Sbdrewery free(rpc->r_name); 225257378Sbdrewery return (-1); 226257378Sbdrewery } 227257378Sbdrewery break; 228257378Sbdrewery 229257378Sbdrewery default: 230257378Sbdrewery if (sl == NULL) { 231257378Sbdrewery if (strcmp(s, "(null)") == 0) 232257378Sbdrewery return (0); 233257378Sbdrewery 234257378Sbdrewery sl = sl_init(); 235257378Sbdrewery assert(sl != NULL); 236257378Sbdrewery 237257378Sbdrewery if (strcmp(s, "noaliases") != 0) { 238257378Sbdrewery ts = strdup(s); 239257378Sbdrewery assert(ts != NULL); 240257378Sbdrewery sl_add(sl, ts); 241257378Sbdrewery } 242257378Sbdrewery } else { 243257378Sbdrewery ts = strdup(s); 244257378Sbdrewery assert(ts != NULL); 245257378Sbdrewery sl_add(sl, ts); 246257378Sbdrewery } 247257378Sbdrewery break; 248257378Sbdrewery }; 249257378Sbdrewery ++i; 250257378Sbdrewery } 251257378Sbdrewery 252257378Sbdrewery if (i < 3) { 253257378Sbdrewery free(rpc->r_name); 254257378Sbdrewery memset(rpc, 0, sizeof(struct rpcent)); 255257378Sbdrewery return (-1); 256257378Sbdrewery } 257257378Sbdrewery 258257378Sbdrewery sl_add(sl, NULL); 259257378Sbdrewery rpc->r_aliases = sl->sl_str; 260257378Sbdrewery 261257378Sbdrewery /* NOTE: is it a dirty hack or not? */ 262257378Sbdrewery free(sl); 263257378Sbdrewery return (0); 264257378Sbdrewery} 265257378Sbdrewery 266257378Sbdrewerystatic void 267257378Sbdrewerydump_rpcent(struct rpcent *result) 268263038Sbapt{ 269263038Sbapt if (result != NULL) { 270257378Sbdrewery char buffer[1024]; 271257378Sbdrewery sdump_rpcent(result, buffer, sizeof(buffer)); 272257378Sbdrewery printf("%s\n", buffer); 273257378Sbdrewery } else 274257378Sbdrewery printf("(null)\n"); 275257378Sbdrewery} 276257378Sbdrewery 277257378Sbdrewerystatic int 278257378Sbdreweryrpcent_fill_test_data(struct rpcent_test_data *td) 279257378Sbdrewery{ 280257378Sbdrewery struct rpcent *rpc; 281257378Sbdrewery 282 setrpcent(1); 283 while ((rpc = getrpcent()) != NULL) { 284 if (rpcent_test_correctness(rpc, NULL) == 0) 285 TEST_DATA_APPEND(rpcent, td, rpc); 286 else 287 return (-1); 288 } 289 endrpcent(); 290 291 return (0); 292} 293 294static int 295rpcent_test_correctness(struct rpcent *rpc, void *mdata) 296{ 297 if (debug) { 298 printf("testing correctness with the following data:\n"); 299 dump_rpcent(rpc); 300 } 301 302 if (rpc == NULL) 303 goto errfin; 304 305 if (rpc->r_name == NULL) 306 goto errfin; 307 308 if (rpc->r_number < 0) 309 goto errfin; 310 311 if (rpc->r_aliases == NULL) 312 goto errfin; 313 314 if (debug) 315 printf("correct\n"); 316 317 return (0); 318errfin: 319 if (debug) 320 printf("incorrect\n"); 321 322 return (-1); 323} 324 325/* rpcent_check_ambiguity() is needed when one port+rpc is associated with 326 * more than one peice (these cases are usually marked as PROBLEM in 327 * /etc/peices. This functions is needed also when one peice+rpc is 328 * associated with several ports. We have to check all the rpcent structures 329 * to make sure that rpc really exists and correct */ 330static int 331rpcent_check_ambiguity(struct rpcent_test_data *td, struct rpcent *rpc) 332{ 333 334 return (TEST_DATA_FIND(rpcent, td, rpc, compare_rpcent, 335 NULL) != NULL ? 0 : -1); 336} 337 338static int 339rpcent_test_getrpcbyname(struct rpcent *rpc_model, void *mdata) 340{ 341 char **alias; 342 struct rpcent *rpc; 343 344 if (debug) { 345 printf("testing getrpcbyname() with the following data:\n"); 346 dump_rpcent(rpc_model); 347 } 348 349 rpc = getrpcbyname(rpc_model->r_name); 350 if (rpcent_test_correctness(rpc, NULL) != 0) 351 goto errfin; 352 353 if ((compare_rpcent(rpc, rpc_model, NULL) != 0) && 354 (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc) 355 !=0)) 356 goto errfin; 357 358 for (alias = rpc_model->r_aliases; *alias; ++alias) { 359 rpc = getrpcbyname(*alias); 360 361 if (rpcent_test_correctness(rpc, NULL) != 0) 362 goto errfin; 363 364 if ((compare_rpcent(rpc, rpc_model, NULL) != 0) && 365 (rpcent_check_ambiguity( 366 (struct rpcent_test_data *)mdata, rpc) != 0)) 367 goto errfin; 368 } 369 370 if (debug) 371 printf("ok\n"); 372 return (0); 373 374errfin: 375 if (debug) 376 printf("not ok\n"); 377 378 return (-1); 379} 380 381static int 382rpcent_test_getrpcbynumber(struct rpcent *rpc_model, void *mdata) 383{ 384 struct rpcent *rpc; 385 386 if (debug) { 387 printf("testing getrpcbyport() with the following data...\n"); 388 dump_rpcent(rpc_model); 389 } 390 391 rpc = getrpcbynumber(rpc_model->r_number); 392 if ((rpcent_test_correctness(rpc, NULL) != 0) || 393 ((compare_rpcent(rpc, rpc_model, NULL) != 0) && 394 (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc) 395 != 0))) { 396 if (debug) 397 printf("not ok\n"); 398 return (-1); 399 } else { 400 if (debug) 401 printf("ok\n"); 402 return (0); 403 } 404} 405 406static int 407rpcent_test_getrpcent(struct rpcent *rpc, void *mdata) 408{ 409 /* Only correctness can be checked when doing 1-pass test for 410 * getrpcent(). */ 411 return (rpcent_test_correctness(rpc, NULL)); 412} 413 414static void 415usage(void) 416{ 417 (void)fprintf(stderr, 418 "Usage: %s -nve2 [-d] [-s <file>]\n", 419 getprogname()); 420 exit(1); 421} 422 423int 424main(int argc, char **argv) 425{ 426 struct rpcent_test_data td, td_snap, td_2pass; 427 char *snapshot_file; 428 int rv; 429 int c; 430 431 if (argc < 2) 432 usage(); 433 434 snapshot_file = NULL; 435 while ((c = getopt(argc, argv, "nve2ds:")) != -1) 436 switch (c) { 437 case 'd': 438 debug++; 439 break; 440 case 'n': 441 method = TEST_GETRPCBYNAME; 442 break; 443 case 'v': 444 method = TEST_GETRPCBYNUMBER; 445 break; 446 case 'e': 447 method = TEST_GETRPCENT; 448 break; 449 case '2': 450 method = TEST_GETRPCENT_2PASS; 451 break; 452 case 's': 453 snapshot_file = strdup(optarg); 454 break; 455 default: 456 usage(); 457 } 458 459 TEST_DATA_INIT(rpcent, &td, clone_rpcent, free_rpcent); 460 TEST_DATA_INIT(rpcent, &td_snap, clone_rpcent, free_rpcent); 461 if (snapshot_file != NULL) { 462 if (access(snapshot_file, W_OK | R_OK) != 0) { 463 if (errno == ENOENT) 464 method = TEST_BUILD_SNAPSHOT; 465 else { 466 if (debug) 467 printf("can't access the file %s\n", 468 snapshot_file); 469 470 rv = -1; 471 goto fin; 472 } 473 } else { 474 if (method == TEST_BUILD_SNAPSHOT) { 475 rv = 0; 476 goto fin; 477 } 478 479 TEST_SNAPSHOT_FILE_READ(rpcent, snapshot_file, 480 &td_snap, rpcent_read_snapshot_func); 481 } 482 } 483 484 rv = rpcent_fill_test_data(&td); 485 if (rv == -1) 486 return (-1); 487 switch (method) { 488 case TEST_GETRPCBYNAME: 489 if (snapshot_file == NULL) 490 rv = DO_1PASS_TEST(rpcent, &td, 491 rpcent_test_getrpcbyname, (void *)&td); 492 else 493 rv = DO_1PASS_TEST(rpcent, &td_snap, 494 rpcent_test_getrpcbyname, (void *)&td_snap); 495 break; 496 case TEST_GETRPCBYNUMBER: 497 if (snapshot_file == NULL) 498 rv = DO_1PASS_TEST(rpcent, &td, 499 rpcent_test_getrpcbynumber, (void *)&td); 500 else 501 rv = DO_1PASS_TEST(rpcent, &td_snap, 502 rpcent_test_getrpcbynumber, (void *)&td_snap); 503 break; 504 case TEST_GETRPCENT: 505 if (snapshot_file == NULL) 506 rv = DO_1PASS_TEST(rpcent, &td, rpcent_test_getrpcent, 507 (void *)&td); 508 else 509 rv = DO_2PASS_TEST(rpcent, &td, &td_snap, 510 compare_rpcent, NULL); 511 break; 512 case TEST_GETRPCENT_2PASS: 513 TEST_DATA_INIT(rpcent, &td_2pass, clone_rpcent, free_rpcent); 514 rv = rpcent_fill_test_data(&td_2pass); 515 if (rv != -1) 516 rv = DO_2PASS_TEST(rpcent, &td, &td_2pass, 517 compare_rpcent, NULL); 518 TEST_DATA_DESTROY(rpcent, &td_2pass); 519 break; 520 case TEST_BUILD_SNAPSHOT: 521 if (snapshot_file != NULL) 522 rv = TEST_SNAPSHOT_FILE_WRITE(rpcent, snapshot_file, &td, 523 sdump_rpcent); 524 break; 525 default: 526 rv = 0; 527 break; 528 }; 529 530fin: 531 TEST_DATA_DESTROY(rpcent, &td_snap); 532 TEST_DATA_DESTROY(rpcent, &td); 533 free(snapshot_file); 534 return (rv); 535} 536