1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** NAME 79** 80** client.c 81** 82** FACILITY: 83** 84** Remote Procedure Call (RPC) 85** 86** ABSTRACT: 87** 88** Client application code for performance and system exerciser. 89** 90** 91*/ 92 93#include <perf_c.h> 94#include <string.h> 95#include <malloc.h> 96#include <sys/time.h> 97#ifndef NO_TIMES 98#include <sys/times.h> 99#include <unistd.h> 100#endif /* NO_TIMES */ 101#include <stdlib.h> 102#include <sys/wait.h> 103 104 105typedef struct 106{ 107 unsigned short ifspec_vers; 108 unsigned short opcnt; 109 unsigned long vers; 110 idl_uuid_t id; 111 unsigned short stub_rtl_if_vers; 112} rpc_if_rep_t, *rpc_if_rep_p_t; 113 114static void looping_test(); 115static void brd_test(); 116static void unreg_test(); 117static void forwarding_test(); 118static void exception_test(); 119static void shutdown_test(); 120static void callback_test(); 121static void generic_test(); 122static void context_test(); 123static void static_cancel_test(); 124static void stats_test(); 125static void inq_if_ids_test(); 126static void one_shot_test(); 127 128#define SHUTMODE_MGR 1 129#define SHUTMODE_NO_MGR 2 130#define SHUTMODE_MGMT 3 131 132struct tinfo_t 133{ 134 void (*proc)(); 135 char *name; 136 char *usage; 137} tinfo[] = 138 { 139 /* 0 */ {looping_test, "Null call", 140 "host passes calls/pass verify? idempotent?"}, 141 /* 1 */ {looping_test, "Variable length input arg", 142 "host passes calls/pass verify? idempotent? nbytes"}, 143 /* 2 */ {looping_test, "Variable length output arg", 144 "host passes calls/pass verify? idempotent? nbytes"}, 145 /* 3 */ {brd_test, "Broadcast", 146 "family"}, 147 /* 4 */ {looping_test, "Maybe", 148 "host passes calls/pass"}, 149 /* 5 */ {brd_test, "Broadcast/maybe", 150 "family"}, 151 /* 6 */ {looping_test, "Floating point", 152 "host passes calls/pass verify? idempotent?"}, 153 /* 7 */ {unreg_test, "Unregistered interface", 154 "host"}, 155 /* 8 */ {forwarding_test, "Forwarding", 156 "host global?"}, 157 /* 9 */ {exception_test, "Exception", 158 "host"}, 159 /* 10 */ {looping_test, "Slow call", 160 "host passes calls/pass verify? idempotent? seconds [mode]"}, 161 /* 11 */ {shutdown_test, "Shutdown", 162 "host[+ep] [mode [secs]] (1=manager, 2=no manager, 3=management)"}, 163 /* 12 */ {callback_test, "Callback (UNSUPPORTED!)", 164 "host passes callbacks/pass idempotent?"}, 165 /* 13 */ {generic_test, "Generic interface", 166 "host"}, 167 /* 14 */ {context_test, "Context test", 168 "host passes die? seconds"}, 169 /* 15 */ {static_cancel_test, "Static Cancel", 170 "host passes idempotent? [seconds [cancel-timeout-seconds]]"}, 171 /* 16 */ {stats_test, "Statistics", 172 "[host+ep]"}, 173 /* 17 */ {inq_if_ids_test, "Interface identifiers", 174 "[host+ep]"}, 175 /* 18 */ {one_shot_test, "One shot", 176 "host[+ep] forward? idempotent?"}, 177 }; 178 179#define N_TESTS (int)(sizeof tinfo / sizeof (struct tinfo_t)) 180 181 182#ifdef _POSIX_THREADS 183 184#define MAX_TASKS 40 185 186idl_boolean multithread = false; 187idl_boolean use_shared_handle = false; 188int n_tasks; 189pthread_mutex_t global_mutex; 190 191#endif 192 193idl_boolean authenticate; 194unsigned32 authn_level; 195idl_char *auth_principal; 196unsigned32 authn_protocol; 197unsigned32 authz_protocol; 198 199idl_boolean debug = false; 200idl_boolean stats = false; 201idl_boolean use_obj = false; 202idl_boolean compat_mode = false; 203signed32 timeout = -1; 204signed32 cancel_timeout = -1; 205 206int recreate_binding_freq = 0; /* "infinity" */ 207int reset_binding_freq = 0; /* "infinity" */ 208 209int wait_point = -1; 210int wait_time; 211 212unsigned32 socket_buf_size = 0; /* os default */ 213 214int verbose = 1; 215 216#ifdef NO_TIMES 217struct msec_time 218{ 219 unsigned long msec; 220 unsigned short usec; 221}; 222#else 223struct msec_time 224{ 225 struct tms ptime; 226 struct timeval elapsed; 227 unsigned long r_msec; 228 unsigned long r_usec; 229 unsigned long u_msec; 230 unsigned long s_msec; 231}; 232 233static long clock_ticks; 234#endif /* NO_TIMES */ 235 236#ifndef NO_GETTIMEOFDAY 237 238#define GETTIMEOFDAY(t) \ 239{ \ 240 struct timezone tz; \ 241 \ 242 gettimeofday(t, &tz); \ 243} 244 245#else 246 247struct timeval 248{ 249 unsigned long tv_sec; 250 unsigned long tv_usec; 251}; 252 253#define GETTIMEOFDAY(t) \ 254{ \ 255 (t)->tv_sec = time(NULL); \ 256 (t)->tv_usec = 0; \ 257} 258 259#endif 260 261 262/* 263 * Print how to use this program 264 */ 265void usage (test) 266 267int test; 268 269{ 270 int i; 271 272 if (test != -1) 273 { 274 fprintf (stderr, "usage: client <flags> %d %s\n", 275 test, tinfo[test].usage); 276 } 277 else 278 { 279 fprintf (stderr, "usage: client [-Dis] [-d <debug switches>] [(-m|M) <nthreads>]\n"); 280 fprintf (stderr, " [-t <timeout>] [-c <timeout>] [-w <wait point>,<wait secs>]\n"); 281 fprintf (stderr, " [-p <authn proto>,<authz proto>[,<level>[,<principal>]]]\n"); 282 fprintf (stderr, " [-r <frequency>] [-R <frequency>] [-v <verbose level>]\n"); 283 fprintf (stderr, " [-f <opt>] [-B <bufsize>]\n"); 284 fprintf (stderr, " test# ...\n"); 285 fprintf (stderr, " -d: Turns on NCK runtime debug output\n"); 286 fprintf (stderr, " -D: Turns on default NCK runtime debug output\n"); 287 fprintf (stderr, " -t: Set communications timeout (0-10)\n"); 288 fprintf (stderr, " -c: Set cancel timeout (seconds)\n"); 289 fprintf (stderr, " -B: Set CN TCP socket buffer (bytes)\n"); 290 fprintf (stderr, " -f: Repeat test after fork, <opt> can be:\n"); 291 fprintf (stderr, " 1: Repeat test in the original and child processes\n"); 292 fprintf (stderr, " 2: Repeat test in the original process only\n"); 293 fprintf (stderr, " 3: Repeat test in the child process only\n"); 294 fprintf (stderr, " 4: Repeat test in the child and grandchild processes\n"); 295 fprintf (stderr, " 5: Repeat test in the grandchild process only\n"); 296 fprintf (stderr, " 6: Run test in the child process only\n"); 297 fprintf (stderr, " -s: Prints statistics at end of test\n"); 298 fprintf (stderr, " -w: Causes client to wait at specified point for specified time\n"); 299 fprintf (stderr, " -o: Use perf object in bindings (default is no object)\n"); 300 fprintf (stderr, " -1: Avoid doing certain things that NCS 1.5 can't do\n"); 301 fprintf (stderr, " -r: Reset bindings every <frequency> calls in a single pass\n"); 302 fprintf (stderr, " -R: Recreate bindings every <frequency> calls in a single pass\n"); 303#ifdef _POSIX_THREADS 304 fprintf (stderr, 305 " -m: Causes nthreads tasks to run at same time (tasking systems only)\n"); 306 fprintf (stderr, 307 " -M: Same as -m but use a shared binding handle (tasking systems only)\n"); 308#endif 309 fprintf (stderr, 310 " -i: Causes statistics to be dumped at end of run\n"); 311 fprintf (stderr, 312 " -p: Authenticate using <authn proto>/<authz proto> at <level> to <principal>\n"); 313 fprintf (stderr, 314 " <level> and <principal> may be omitted\n"); 315#ifndef NO_TIMES 316 fprintf (stderr, "CLK_TCK: %ld ticks/sec\n", clock_ticks); 317#endif /* NO_TIMES */ 318 fprintf (stderr, "\n"); 319 320 for (i = 0; i < N_TESTS; i++) 321 { 322 fprintf(stderr, " test #%d: %s test\n usage: client %d %s\n", 323 i, tinfo[i].name, i, tinfo[i].usage); 324 } 325 } 326 327 exit(1); 328} 329 330/* 331 * If the specified point is a wait point, then sleep for the specified amount 332 * of time. 333 */ 334 335static void check_wait_point(point) 336 337int point; 338 339{ 340 if (wait_point == point) 341 { 342 printf("...wait point %d: sleeping for %d seconds\n", point, wait_time); 343 SLEEP(wait_time); 344 } 345} 346 347#ifdef NO_TIMES 348/* 349 * Take a starting time and an iteration count, and produce an average 350 * time per iteration based on the current time. 351 */ 352 353static void end_timing(start_time, iterations, avg_time) 354 355struct timeval *start_time; 356unsigned long iterations; 357struct msec_time *avg_time; 358 359{ 360 struct timeval elapsed_time; 361 unsigned long elapsed_usec; 362 363 GETTIMEOFDAY(&elapsed_time); 364 365 if (elapsed_time.tv_usec < start_time->tv_usec) 366 { 367 elapsed_time.tv_sec--; 368 elapsed_time.tv_usec += 1000000; 369 } 370 371 elapsed_time.tv_usec -= start_time->tv_usec; 372 elapsed_time.tv_sec -= start_time->tv_sec; 373 374 elapsed_usec = (elapsed_time.tv_sec * 1000000) + elapsed_time.tv_usec; 375 376 avg_time->msec = (elapsed_usec / iterations) / 1000; 377 avg_time->usec = (elapsed_usec / iterations) % 1000; 378} 379#else 380static void start_timing(start_time) 381struct msec_time *start_time; 382{ 383 GETTIMEOFDAY(&start_time->elapsed); 384 385 if (times(&start_time->ptime) == -1) 386 memset(&start_time->ptime, 0, sizeof(start_time->ptime)); 387} 388 389/* 390 * Take a starting time and an iteration count, and produce an average 391 * time per iteration based on the current time. 392 */ 393 394static void end_timing(start_time, iterations, avg_time) 395 396struct msec_time *start_time; 397unsigned long iterations; 398struct msec_time *avg_time; 399 400{ 401 struct tms ptime; 402 unsigned long elapsed_usec; 403 404 GETTIMEOFDAY(&avg_time->elapsed); 405 406 if (times(&ptime) != -1) 407 { 408 avg_time->ptime.tms_utime = ptime.tms_utime 409 - start_time->ptime.tms_utime; 410 avg_time->ptime.tms_stime = ptime.tms_stime 411 - start_time->ptime.tms_stime; 412 413 avg_time->u_msec = (avg_time->ptime.tms_utime / iterations) 414 * 1000 / clock_ticks; 415 avg_time->s_msec = (avg_time->ptime.tms_stime / iterations) 416 * 1000 / clock_ticks; 417 } 418 else 419 { 420 avg_time->u_msec = 0; 421 avg_time->s_msec = 0; 422 } 423 424 if (avg_time->elapsed.tv_usec < start_time->elapsed.tv_usec) 425 { 426 avg_time->elapsed.tv_sec--; 427 avg_time->elapsed.tv_usec += 1000000; 428 } 429 430 avg_time->elapsed.tv_usec -= start_time->elapsed.tv_usec; 431 avg_time->elapsed.tv_sec -= start_time->elapsed.tv_sec; 432 433 elapsed_usec = (avg_time->elapsed.tv_sec * 1000000) 434 + avg_time->elapsed.tv_usec; 435 436 avg_time->r_msec = (elapsed_usec / iterations) / 1000; 437 avg_time->r_usec = (elapsed_usec / iterations) % 1000; 438} 439#endif /* NO_TIMES */ 440 441/* 442 * Get an RPC handle for a name 443 */ 444 445static handle_t binding_from_string_binding (object, name) 446 447idl_uuid_t *object; 448char *name; 449 450{ 451 unsigned32 st; 452 handle_t h; 453 454 rpc_binding_from_string_binding 455 ((idl_char *) name, (rpc_binding_handle_t *) &h, &st); 456 457 if (st != rpc_s_ok) 458 { 459 fprintf (stderr, "*** Can't convert name \"%s\" to binding - %s\n", 460 name, error_text (st)); 461 exit(1); 462 } 463 464 rpc_binding_set_object (h, 465 object != NULL ? 466 object : 467 use_obj ? &NilTypeObj : NULL, 468 &st); 469 470 if (st != rpc_s_ok) 471 { 472 fprintf (stderr, "*** Can't set binding's object - %s\n", 473 error_text (st)); 474 exit(1); 475 } 476 477 if (timeout != -1) 478 { 479 rpc_mgmt_set_com_timeout (h, (unsigned32) timeout, &st); 480 481 if (st != rpc_s_ok) 482 { 483 fprintf (stderr, "*** Can't set timeout for binding - %s\n", 484 error_text (st)); 485 exit(1); 486 } 487 } 488 489 if (authenticate) 490 { 491 unsigned32 authn_level_local, authn_protocol_local, authz_protocol_local; 492 unsigned_char_p_t auth_principal_local; 493 494 /* 495 * If no server principal name was supplied, we must go get one from 496 * the server. 497 */ 498 if (auth_principal == NULL) 499 { 500 rpc_mgmt_inq_server_princ_name (h, authn_protocol, &auth_principal, &st); 501 if (st != rpc_s_ok) 502 { 503 fprintf (stderr, "*** Can't get server principal name - %s\n", 504 error_text (st)); 505 exit(1); 506 } 507 VRprintf(2, (" Server principal name found to be: \"%s\"\n", 508 auth_principal)); 509 } 510 511 /* 512 * Leave a backdoor for testing the unsupported "null server 513 * principal name" feature of rpc_binding_set_auth_info(). 514 */ 515 if (strcmp ((char *) auth_principal, "NULL") == 0) 516 { 517 auth_principal = NULL; 518 } 519 520 rpc_binding_set_auth_info 521 (h, auth_principal, authn_level, authn_protocol, NULL, authz_protocol, &st); 522 if (st != rpc_s_ok) 523 { 524 fprintf (stderr, "*** Can't set authentication for binding - %s\n", 525 error_text (st)); 526 exit(1); 527 } 528 rpc_binding_inq_auth_info 529 (h, &auth_principal_local, &authn_level_local, &authn_protocol_local, NULL, 530 &authz_protocol_local, &st); 531 if (st != rpc_s_ok) 532 { 533 fprintf (stderr, "*** Can't get authentication back from binding - %s\n", 534 error_text (st)); 535 exit(1); 536 } 537 VRprintf(2, (" Authentication info from binding:\n authn protocol: %s\n authz protocol: %s\n level: %s\n server princ: \"%s\"\n -----------------\n", 538 authn_names[authn_protocol_local], 539 authz_names[authz_protocol_local], 540 authn_level_names[authn_level_local], 541 auth_principal_local)); 542 if (auth_principal_local != NULL) 543 { 544 rpc_string_free (&auth_principal_local, &st); 545 } 546 } 547 548 return h; 549} 550 551/* 552 * Convert a binding to a string binding. 553 */ 554 555static void binding_to_string_binding (rh, name) 556 557handle_t rh; 558unsigned_char_p_t *name; 559 560{ 561 unsigned32 st; 562 563 rpc_binding_to_string_binding (rh, name, &st); 564 if (st != rpc_s_ok) 565 { 566 fprintf (stderr, "*** Can't convert binding to string binding - %s\n", 567 error_text (st)); 568 exit(1); 569 } 570} 571 572/* 573 * Reset a binding. 574 */ 575 576static void binding_reset (rh) 577 578handle_t rh; 579 580{ 581 unsigned32 st; 582 583 rpc_binding_reset((rpc_binding_handle_t) rh, &st); 584 if (st != rpc_s_ok) 585 { 586 fprintf(stderr, "*** Can't reset binding - %s\n", error_text(st)); 587 exit(1); 588 } 589} 590 591 592/* 593 * Broadcast test 594 */ 595 596static void brd_test (test, argc, argv) 597 598int test; 599int argc; 600char *argv[]; 601 602{ 603 handle_t rh; 604 unsigned32 st; 605 unsigned_char_p_t name, name2; 606 idl_char result[256]; 607 608 if (argc < 3) 609 { 610 usage (test); 611 } 612 613 rpc_string_binding_compose (NULL, (unsigned_char_p_t) argv[2], 614 NULL, NULL, NULL, &name, &st); 615 if (st != rpc_s_ok) 616 { 617 fprintf(stderr, "*** Can't form string binding from \"%s\"\n", argv[2]); 618 exit(1); 619 } 620 621 rh = binding_from_string_binding (NULL, name); 622 623 /* 624 * Broadcast/maybe test; just make the call and return. 625 */ 626 627 if (test == 5) 628 { 629 perf_brd_maybe(rh); 630 return; 631 } 632 633 /* 634 * Normal broadcast. 635 */ 636 637 printf (" Broadcast call that should succeed...\n"); 638 639 perf_brd(rh, result); 640 binding_to_string_binding (rh, &name2); 641 printf(" bound to \"%s\", result=\"%s\"\n", name2, result); 642 643 rpc_string_free (&name2, &st); 644 rpc_binding_free (&rh, &st); 645 646 /* 647 * Call a broadcast routine that raises an exception; should see comm failure, 648 * NOT exception. 649 */ 650 651 printf (" Broadcast call that should get communications failure (exception case)...\n"); 652 653 rh = binding_from_string_binding (NULL, name); 654 655 TRY 656 { 657 perf_brd_fault(rh); 658 binding_to_string_binding (rh, &name2); 659 fprintf (stderr, "*** Call succeeded (shouldn't have); bound to \"%s\", result=\"%s\"\n", name2, result); 660 rpc_string_free (&name2, &st); 661 exit(1); 662 } 663 CATCH (rpc_x_comm_failure) 664 { 665 printf (" call failed as expected\n"); 666 } 667 CATCH_ALL 668 { 669 exc_report(THIS_CATCH); 670 printf (" call failed, but with something other than \"communications failure\"\n"); 671 } 672 ENDTRY 673 674 rpc_binding_free (&rh, &st); 675 676 /* 677 * Call a broadcast routine that should not be registered; should see comm 678 * failure, NOT exception. 679 */ 680 681 printf (" Broadcast call that should get communications failure (unknown i/f case)...\n"); 682 683 rh = binding_from_string_binding (NULL, name); 684 685 TRY 686 { 687 perfb_brd(rh, result); 688 binding_to_string_binding (rh, &name2); 689 fprintf (stderr, "*** Call succeeded (shouldn't have); bound to \"%s\", result=\"%s\"\n", name2, result); 690 exit(1); 691 } 692 CATCH (rpc_x_comm_failure) 693 { 694 printf (" call failed as expected\n"); 695 } 696 CATCH_ALL 697 { 698 printf (" call failed, but with something other than \"communications failure\"\n"); 699 } 700 ENDTRY 701} 702 703/* 704 * Shutdown test 705 */ 706 707static void shutdown_test (test, argc, argv) 708 709int test; 710int argc; 711char *argv[]; 712 713{ 714 handle_t rh; 715 int mode; 716 unsigned32 secs; 717 unsigned32 st; 718 719 if (argc < 3) 720 { 721 usage(test); 722 } 723 724 rh = binding_from_string_binding(NULL, argv[2]); 725 726 mode = (argc < 4) ? SHUTMODE_MGR : atoi(argv[3]); 727 728 switch (mode) 729 { 730 case SHUTMODE_MGR: 731 printf(" Shutdown via manager thread calling shutdown\n"); 732 perf_shutdown(rh); 733 break; 734 735 case SHUTMODE_NO_MGR: 736 printf(" Shutdown via non-manager calling shutdown\n"); 737 secs = (argc < 5) ? 0 : atoi(argv[4]); 738 perf_shutdown2(rh, secs); 739 break; 740 741 case SHUTMODE_MGMT: 742 printf(" Shutdown via local call to management function\n"); 743 rpc_mgmt_stop_server_listening(rh, &st); 744 if (st != rpc_s_ok) 745 { 746 fprintf(stderr, "*** Error from management function - %s\n", 747 error_text (st)); 748 } 749 break; 750 } 751 752} 753 754/* 755 * Unregistered interface test. 756 */ 757 758static void unreg_test (test, argc, argv) 759 760int test; 761int argc; 762char *argv[]; 763 764{ 765 char name[256]; 766 handle_t rh; 767 unsigned32 st; 768 unsigned_char_t *endpoint; 769 770 rpc_if_rep_p_t if_rep = (rpc_if_rep_p_t)perfb_v1_0_c_ifspec; 771 idl_uuid_t if_uuid; 772 773 if (argc < 3) 774 { 775 usage(test); 776 } 777 778 memcpy(&if_uuid, &(if_rep->id), sizeof(idl_uuid_t)); 779 780 rh = binding_from_string_binding(NULL, argv[2]); 781 782 rpc_string_binding_parse((unsigned_char_t *)argv[2], NULL, NULL, NULL, 783 &endpoint, NULL, &st); 784 if (st != rpc_s_ok) 785 { 786 fprintf(stderr, "*** Can't parse string binding from \"%s\"\n", argv[2]); 787 exit(1); 788 } 789 790 if (endpoint == NULL) 791 { 792 /* 793 * Do a RPC to a supported interface so that we can get a complete 794 * binding to the server. 795 */ 796 perf_init(rh); 797 } 798 799 uuid_create(&(if_rep->id), &st); 800 if (st != rpc_s_ok) 801 { 802 fprintf(stderr, "*** Can't create uuid\n"); 803 exit(1); 804 } 805 806 /* 807 * Now try a RPC to an interface that the server doesn't 808 * have registered. 809 */ 810 TRY 811 { 812 perfb_init(rh, (idl_char *) name); 813 fprintf(stderr, "*** Call that should have failed succeeded!\n"); 814 } 815 CATCH (rpc_x_unknown_if) 816 { 817 printf(" \"Unknown interface\" exception correctly raised\n"); 818 } 819 ENDTRY 820 821#ifdef _POSIX_THREADS 822 if (! multithread) 823#endif 824 memcpy(&(if_rep->id), &if_uuid, sizeof(idl_uuid_t)); 825} 826 827/* 828 * Inquire Interface ids test 829 */ 830 831static void do_inq_if_ids (name) 832char *name; 833{ 834 handle_t rh; 835 rpc_if_id_vector_p_t if_ids; 836 unsigned32 st; 837 char *pstring; 838 unsigned_char_p_t uuid_string; 839 unsigned32 i; 840 unsigned32 temp_status; 841 842 if (name == NULL) 843 { 844 pstring = "local process"; 845 rh = NULL; 846 } 847 else 848 { 849 pstring = name; 850 rh = binding_from_string_binding(NULL, name); 851 } 852 853 rpc_mgmt_inq_if_ids (rh, &if_ids, &st); 854 if (st != rpc_s_ok) 855 { 856 fprintf(stderr, "*** Can't inquire interface ids for %s - %s\n", 857 pstring, error_text(st)); 858 exit(1); 859 } 860 861 printf ("%ld interface ids returned for %s.\n", if_ids->count, pstring); 862 for (i = 0; i < if_ids->count; i++) 863 { 864 uuid_to_string (&if_ids->if_id[i]->uuid, &uuid_string, &st); 865 printf ("%ld:\tuuid:\t%s\n\tvers_major:\t%d\tvers_minor\t%d\n", 866 (i+1), uuid_string, if_ids->if_id[i]->vers_major, 867 if_ids->if_id[i]->vers_minor ); 868 rpc_string_free (&uuid_string, &temp_status); 869 } 870 871 rpc_if_id_vector_free (&if_ids, &st); 872 if (st != rpc_s_ok) 873 { 874 fprintf(stderr, "*** Can't free interface ids - %s\n", error_text(st)); 875 exit(1); 876 } 877} 878 879static void inq_if_ids_test (test, argc, argv) 880 881int test; 882int argc; 883char *argv[]; 884 885{ 886 if (argc < 2) 887 { 888 usage(test); 889 } 890 891 do_inq_if_ids (argc == 2 ? NULL : argv[2]); 892} 893 894 895/* 896 * Statistics test 897 */ 898 899static void do_stats (name) 900char *name; 901{ 902 handle_t rh; 903 rpc_stats_vector_p_t stats; 904 unsigned32 st; 905 unsigned char *pstring; 906 907 if (name == NULL) 908 { 909 pstring = (unsigned char *)"local process"; 910 rh = NULL; 911 } 912 else 913 { 914 pstring = (unsigned char *)name; 915 rh = binding_from_string_binding(NULL, name); 916 } 917 918 rpc_mgmt_inq_stats (rh, &stats, &st); 919 if (st != rpc_s_ok) 920 { 921 fprintf(stderr, "*** Can't inquire statistics for %s - %s\n", 922 pstring, error_text(st)); 923 exit(1); 924 } 925 926 if (name != NULL) 927 { 928 binding_to_string_binding(rh, &pstring, &st); 929 } 930 931 printf(" Stats for %s\n", pstring); 932 933 if (name != NULL) 934 rpc_string_free(&pstring, &st); 935 936 printf(" Calls sent: %9lu\n", stats->stats[rpc_c_stats_calls_out]); 937 printf(" Calls rcvd: %9lu\n", stats->stats[rpc_c_stats_calls_in]); 938 printf(" Packets sent: %9lu\n", stats->stats[rpc_c_stats_pkts_out]); 939 printf(" Packets rcvd: %9lu\n", stats->stats[rpc_c_stats_pkts_in]); 940 941 rpc_mgmt_stats_vector_free (&stats, &st); 942 if (st != rpc_s_ok) 943 { 944 fprintf(stderr, "*** Can't free statistics - %s\n", error_text(st)); 945 exit(1); 946 } 947} 948 949static void stats_test (test, argc, argv) 950 951int test; 952int argc; 953char *argv[]; 954 955{ 956 if (argc < 2) 957 { 958 usage(test); 959 } 960 961 do_stats (argc == 2 ? NULL : argv[2]); 962} 963 964 965/* 966 * Auxiliary routine for forwarding test. 967 */ 968 969static void forwarding_mgmt_test (rh, obj, msg) 970 971handle_t rh; 972uuid_p_t obj; 973char *msg; 974 975{ 976 unsigned int i; 977 rpc_if_id_vector_p_t if_ids; 978 rpc_if_id_t perfb_if_id; 979 unsigned32 st; 980 981 /* 982 * Clear binding again and make a management call to test that 983 * management calls on partial bindings work. We do a 984 * mgmt_inq_if_ids and make sure that "perfb" is one of the i/f's 985 * we get back. 986 */ 987 binding_reset(rh); 988 989 rpc_binding_set_object(rh, obj, &st); 990 if (st != 0) 991 { 992 fprintf(stderr, "*** Can't set object in binding (%s) - %s\n", 993 msg, error_text(st)); 994 exit(1); 995 } 996 997 rpc_if_inq_id(perfb_v1_0_c_ifspec, &perfb_if_id, &st); 998 if (st != rpc_s_ok) 999 { 1000 fprintf(stderr, "*** Can't get interface id for perfb interface (%s) - %s\n", 1001 msg, error_text(st)); 1002 exit(1); 1003 } 1004 1005 rpc_mgmt_inq_if_ids (rh, &if_ids, &st); 1006 if (st != 0) 1007 { 1008 fprintf(stderr, "*** Can't get interface ids through partial binding (%s) - %s\n", 1009 msg, error_text(st)); 1010 exit(1); 1011 } 1012 1013 for (i = 0; i < if_ids->count; i++) 1014 { 1015 if (uuid_equal(&if_ids->if_id[i]->uuid, &perfb_if_id.uuid, &st)) 1016 break; 1017 } 1018 1019 if (i == if_ids->count) 1020 { 1021 fprintf(stderr, "*** Request for interface ids through partial binding completed OK,\n"); 1022 fprintf(stderr, "*** but perfb i/f not found; probably forwarded to wrong server (%s).\n", 1023 msg); 1024 exit(1); 1025 } 1026 1027 printf(" request for interface ids through partial binding completed OK (%s)\n", 1028 msg); 1029 1030 rpc_if_id_vector_free (&if_ids, &st); 1031 if (st != rpc_s_ok) 1032 { 1033 fprintf(stderr, "*** Can't free interface ids (%s) - %s\n", 1034 msg, error_text(st)); 1035 exit(1); 1036 } 1037} 1038 1039/* 1040 * Forwarding test. 1041 */ 1042 1043static void forwarding_test (test, argc, argv) 1044 1045int test; 1046int argc; 1047char *argv[]; 1048 1049{ 1050 handle_t rh; 1051 char name[256]; 1052 unsigned_char_p_t name2; 1053 unsigned32 st; 1054 idl_boolean global; 1055#define FSIZE 4000 1056 unsigned32 d[FSIZE]; 1057 int i; 1058 unsigned32 sum, rsum; 1059 idl_char result[256]; 1060 unsigned_char_p_t pstring; 1061 1062 DO_NOT_CLOBBER(rh); 1063 DO_NOT_CLOBBER(rsum); 1064 1065 if (argc < 4) 1066 { 1067 usage(test); 1068 } 1069 1070 global = argv[3][0] == 'y'; 1071 rh = binding_from_string_binding(NULL, argv[2]); 1072 1073 /* 1074 * Tell server to register the "perfb" interface. 1075 */ 1076 perf_register_b(rh, global, &st); 1077 1078 if (st != 0) 1079 { 1080 fprintf(stderr, "*** Can't register \"perfb\" interface - %s\n", 1081 error_text(st)); 1082 exit(1); 1083 } 1084 1085 TRY 1086 { 1087 if (! compat_mode) 1088 { 1089 /* 1090 * Clear the binding to the server and call resolve_binding. 1091 */ 1092 binding_reset(rh); 1093 1094 rpc_ep_resolve_binding(rh, perfb_v1_0_c_ifspec, &st); 1095 if (st != rpc_s_ok) 1096 { 1097 fprintf(stderr, "*** Can't resolve \"perfb\" interface - %s\n", 1098 error_text(st)); 1099 exit(1); 1100 } 1101 1102 binding_to_string_binding(rh, &pstring, &st); 1103 printf(" binding resolved to: %s\n", pstring); 1104 rpc_string_free(&pstring, &st); 1105 } 1106 1107 /* 1108 * Clear binding to server and make a simple call to the "perfb" interface. 1109 */ 1110 binding_reset(rh); 1111 1112 perfb_init(rh, (idl_char *) name); 1113 printf(" result of forwarded call = \"%s\"\n", name); 1114 1115 /* 1116 * Clear binding again and make a call that's too big to fit in a 1117 * single pkt to make sure multi-pkt forwarding works. Note that old 1118 * perf servers don't handle this call so catch that sort of error. 1119 */ 1120 binding_reset(rh); 1121 1122 for (i = 0, rsum = 0; i < FSIZE; i++) 1123 { 1124 d[i] = i; 1125 rsum += d[i]; 1126 } 1127 1128 TRY 1129 { 1130 perfb_in(rh, d, FSIZE, true, &sum); 1131 if (sum != rsum) 1132 { 1133 fprintf(stderr, "*** Sum mismatch in large forwarded call (%lu, %lu)\n", 1134 sum, rsum); 1135 } 1136 else 1137 { 1138 printf(" large forwarded call completed OK\n"); 1139 } 1140 } 1141 CATCH (rpc_x_op_rng_error) 1142 { 1143 printf (" warning: server doesn't implement \"perfb_in\" procedure "); 1144 printf ("(probably an old server)\n"); 1145 printf (" large forwarded call test skipped\n"); 1146 } 1147 ENDTRY 1148 1149 if (! compat_mode) 1150 { 1151 /* 1152 * Test forwarded mgmt calls. 1153 */ 1154 forwarding_mgmt_test (rh, &NilTypeObj, "nil type object"); 1155 forwarding_mgmt_test (rh, &FooObj1, "non-nil type object"); 1156 } 1157 1158 /* 1159 * Clear binding again and make a broadcast call. 1160 */ 1161 binding_reset(rh); 1162 1163 rpc_binding_set_object(rh, NULL, &st); 1164 if (st != 0) 1165 { 1166 fprintf(stderr, "*** Can't reset object in binding to nil - %s\n", 1167 error_text(st)); 1168 exit(1); 1169 } 1170 1171 TRY 1172 { 1173 perfb_brd(rh, result); 1174 binding_to_string_binding (rh, &name2); 1175 printf(" broadcast forwarded call completed OK\n"); 1176 printf(" bound to \"%s\", result=\"%s\"\n", name2, result); 1177 } 1178 CATCH (rpc_x_invalid_call_opt) 1179 { 1180 printf (" warning: can't do broadcast\n"); 1181 } 1182 CATCH (rpc_x_op_rng_error) 1183 { 1184 printf (" warning: server doesn't implement \"perfb_brd\" procedure "); 1185 printf ("(probably an old server)\n"); 1186 printf (" broadcast call test skipped\n"); 1187 } 1188 CATCH (rpc_x_comm_failure) 1189 { 1190 printf (" warning: communications failure (may be an old server)\n"); 1191 printf (" broadcast call test skipped\n"); 1192 } 1193 CATCH_ALL 1194 { 1195 exc_report(THIS_CATCH); 1196 fprintf (stderr, "*** Unknown exception raised in during broadcast forwarded call\n"); 1197 RERAISE; 1198 } 1199 ENDTRY 1200 } 1201 FINALLY 1202 { 1203 /* 1204 * Tell server to unregister the "perfb" interface. 1205 */ 1206 rh = binding_from_string_binding(NULL, argv[2]); 1207 1208 perf_unregister_b(rh, &st); 1209 if (st != 0) 1210 { 1211 fprintf(stderr, "*** Can't unregister \"perfb\" interface - %s\n", 1212 error_text(st)); 1213 exit(1); 1214 } 1215 } 1216 ENDTRY 1217} 1218 1219/* 1220 * Exception test. 1221 */ 1222 1223static void exception_test (test, argc, argv) 1224 1225int test; 1226int argc; 1227char *argv[]; 1228 1229{ 1230 handle_t rh; 1231 1232 if (argc < 3) 1233 { 1234 usage(test); 1235 } 1236 1237 rh = binding_from_string_binding(NULL, argv[2]); 1238 1239 TRY 1240 { 1241 perf_exception(rh); 1242 fprintf(stderr, "*** NO exception raised\n"); 1243 exit (1); 1244 } 1245#ifndef PD_BUILD 1246 CATCH (exc_intdiv_e) 1247#else 1248 CATCH (exc_e_intdiv) 1249#endif 1250 { 1251 printf(" Integer div-by-zero exception correctly raised\n"); 1252 } 1253#ifndef PD_BUILD 1254 CATCH (exc_fltdiv_e) 1255#else 1256 CATCH (exc_e_fltdiv) 1257#endif 1258 { 1259 printf(" Floating div-by-zero exception correctly raised\n"); 1260 } 1261 CATCH (exc_e_aritherr) 1262 { 1263 printf(" Arithmetic error exception correctly raised\n"); 1264 } 1265 CATCH_ALL 1266 { 1267 exc_report(THIS_CATCH); 1268 fprintf(stderr, "*** WRONG exception raised\n"); 1269 exit(1); 1270 } 1271 ENDTRY 1272} 1273 1274/* 1275 * Callback routines for callback test. 1276 */ 1277 1278static unsigned long callback_passes, callback_count; 1279 1280void perfc_init (h, p) 1281 1282handle_t h __attribute__(unused); 1283unsigned32 *p; 1284 1285{ 1286 callback_count = 0; 1287 *p = callback_passes; 1288} 1289 1290void perfc_cb (h, c) 1291 1292handle_t h __attribute__(unused); 1293unsigned32 *c; 1294 1295{ 1296 *c = ++callback_count; 1297 printf(" ...in callback %lu\n", *c); 1298} 1299 1300void perfc_cb_idem (h, c) 1301 1302handle_t h __attribute__(unused); 1303unsigned32 *c; 1304 1305{ 1306 *c = ++callback_count; 1307 printf(" ...in idempotent callback %lu\n", *c); 1308} 1309 1310perfc_v2_0_epv_t perfc_v2_mgr_epv = 1311{ 1312 perfc_init, 1313 perfc_cb, 1314 perfc_cb_idem 1315}; 1316 1317/* 1318 * Callback test 1319 */ 1320static void callback_test (test, argc, argv) 1321 1322int test; 1323int argc; 1324char *argv[]; 1325 1326{ 1327 handle_t rh; 1328 unsigned32 st; 1329 unsigned long idem; 1330 unsigned short passes, i; 1331 1332 if (argc < 6) 1333 { 1334 usage(test); 1335 } 1336 1337 passes = atoi(argv[3]); 1338 callback_passes = atoi(argv[4]); 1339 idem = argv[5][0] == 'y'; 1340 1341 rh = binding_from_string_binding(NULL, argv[2]); 1342 1343 rpc_server_register_if (perfc_v2_0_s_ifspec, NULL, 1344 (rpc_mgr_epv_t) &perfc_v2_mgr_epv, &st); 1345 if (st != rpc_s_ok) 1346 { 1347 fprintf(stderr, "*** Can't register interface - %s\n", error_text(st)); 1348 exit(1); 1349 } 1350 1351 for (i = 1; i <= passes; i++) 1352 { 1353 perf_call_callback(rh, idem); 1354 printf(" pass %2d...OK\n", i); 1355 } 1356 1357 rpc_server_unregister_if (perfc_v2_0_s_ifspec, NULL, &st); 1358 if (st != rpc_s_ok) 1359 { 1360 fprintf(stderr, "*** Can't unregister interface - %s\n", error_text(st)); 1361 exit(1); 1362 } 1363} 1364 1365/* 1366 * Returns T if two double floats are "pretty close" to each other. 1367 */ 1368 1369static idl_boolean approx_eq (d1, d2) 1370 1371double d1, d2; 1372 1373{ 1374 double ratio = d1 / d2; 1375 return (ratio > .9999 && ratio < 1.00001); 1376} 1377 1378/* 1379 * Generic interface test 1380 */ 1381 1382static void generic_test (test, argc, argv) 1383 1384int test; 1385int argc; 1386char *argv[]; 1387 1388{ 1389 handle_t rh; 1390 unsigned32 x; 1391 1392 if (argc < 3) 1393 { 1394 usage(test); 1395 } 1396 1397 rh = binding_from_string_binding((uuid_p_t) &FooObj1, argv[2]); 1398 perfg_op1(rh, 17l, &x); 1399 1400 if (x != 34) 1401 { 1402 fprintf(stderr, "*** op1 on Foo1 returned %lu instead of 34\n", x); 1403 } 1404 1405 rh = binding_from_string_binding((uuid_p_t) &BarObj2, argv[2]); 1406 perfg_op2(rh, 3l, &x); 1407 1408 if (x != 15) 1409 { 1410 fprintf(stderr, "*** op2 on Bar2 returned %lu instead of 15\n", x); 1411 } 1412 1413 rh = binding_from_string_binding((uuid_p_t) &FooObj2, argv[2]); 1414 perfg_op1(rh, 111l, &x); 1415 1416 if (x != 222) 1417 { 1418 fprintf(stderr, "*** op1 on Foo2 returned %lu instead of 222\n", x); 1419 } 1420 1421 rh = binding_from_string_binding((uuid_p_t) &BarObj1, argv[2]); 1422 perfg_op2(rh, 13l, &x); 1423 1424 if (x != 65) 1425 { 1426 fprintf(stderr, "*** op2 on Bar1 returned %lu instead of 65\n", x); 1427 } 1428 1429 TRY { 1430 idl_uuid_t random_uuid; 1431 unsigned32 st; 1432 1433 uuid_create(&random_uuid, &st); 1434 rh = binding_from_string_binding(&random_uuid, argv[2]); 1435 perfg_op1(rh, 17, &x); 1436 fprintf(stderr, 1437 "*** op1 on random uuid: \"Unsupported type\" exception expected\n"); 1438 exit(1); 1439 } 1440 CATCH (rpc_x_unsupported_type) 1441 { 1442 printf(" op1 on random uuid: \"Unsupported type\" exception correctly raised\n"); 1443 } 1444 CATCH (rpc_x_comm_failure) 1445 { 1446 fprintf(stderr, "*** op1 on random uuid: comm failure\n"); 1447 exit(1); 1448 } 1449 CATCH_ALL 1450 { 1451 exc_report(THIS_CATCH); 1452 fprintf(stderr, "*** op1 on random uuid: incorrect exception\n"); 1453 exit(1); 1454 } 1455 ENDTRY 1456 1457 TRY { 1458 rh = binding_from_string_binding(&ZotObj, argv[2]); 1459 perfg_op1(rh, 17, &x); 1460 fprintf(stderr, 1461 "*** op1 on unsupported type: \"Unsupported type\" exception expected\n"); 1462 exit(1); 1463 } 1464 CATCH (rpc_x_unsupported_type) 1465 { 1466 printf(" op1 on unsupported uuid: \"Unsupported type\" exception correctly raised\n"); 1467 } 1468 CATCH (rpc_x_comm_failure) 1469 { 1470 fprintf(stderr, "*** op1 on random uuid: comm failure\n"); 1471 exit(1); 1472 } 1473 CATCH_ALL 1474 { 1475 exc_report(THIS_CATCH); 1476 fprintf(stderr, "*** op1 on random uuid: incorrect exception\n"); 1477 exit(1); 1478 } 1479 ENDTRY 1480 1481 printf(" ...OK\n"); 1482} 1483 1484/* 1485 * Static Cancel test 1486 * 1487 * (static in the sense that a cancel is posted to the thread before 1488 * the RPC is performed and we perform limited tests). 1489 * 1490 * Note: since this test is using existing perf RPCs, there is the 1491 * possibility that things may appear to work on the client side 1492 * without the server side actually having performed correctly 1493 * (because we don't actually check that the server side did or 1494 * did not detect the cancel as expected_; you should be able to 1495 * follow the test printout and verify this visually. 1496 */ 1497 1498/* 1499 * Determine if a cancel is pending (and clear it). 1500 */ 1501 1502static boolean32 cancel_was_pending() 1503{ 1504 volatile boolean32 pending = false; 1505 1506 TRY 1507 { 1508 pthread_testcancel(); 1509 } 1510 CATCH (pthread_cancel_e) 1511 { 1512 printf("pending is set to TRUE\n"); fflush(stdout); 1513 pending = true; 1514 } 1515 CATCH_ALL 1516 { 1517 exc_report(THIS_CATCH); 1518 fprintf(stderr, "*** Unknown exception raised\n"); 1519 } 1520 ENDTRY 1521 1522 return pending; 1523} 1524 1525/* 1526 * static_cancel_test1 1527 * 1528 * Perform a RPC that doesn't call a cancellable operation 1529 * and verify that a cancel is pending upon completion. 1530 */ 1531void static_cancel_test1(rh, idem, slow_secs) 1532 1533rpc_binding_handle_t rh; 1534unsigned32 idem; 1535unsigned long slow_secs; 1536 1537{ 1538 1539 boolean32 pending; 1540 1541 printf(" Static Cancel Test 1 (server should NOT detect cancel):\n"); 1542 1543 /* make sure general cancellability is on */ 1544 pthread_setcancel(CANCEL_ON); 1545 1546 TRY 1547 { 1548 1549 /* 1550 * post a cancel to this thread and make a server RPC call 1551 */ 1552 1553 pthread_cancel(pthread_self()); 1554 if (idem) 1555 { 1556 perf_null_slow_idem(rh, 2 /* CPU LOOP */, slow_secs); 1557 } 1558 else 1559 { 1560 perf_null_slow(rh, 2 /* CPU LOOP */, slow_secs); 1561 } 1562 pending = cancel_was_pending(); 1563 1564 if (pending) 1565 printf(" Correct RPC cancel pending operation\n"); 1566 else 1567 fprintf(stderr, " *** lost cancel (not pending)!\n"); 1568 } 1569 CATCH (pthread_cancel_e) 1570 { 1571 fprintf(stderr, " *** unexpected cancel exception raised!\n"); 1572 if (cancel_was_pending()) 1573 fprintf(stderr, " *** and cancel still pending!\n"); 1574 } 1575 CATCH (rpc_x_cancel_timeout) 1576 { 1577 fprintf(stderr, " *** unexpected cancel timeout exception raised!\n"); 1578 if (! cancel_was_pending()) 1579 fprintf(stderr, " *** and lost cancel (not pending)!\n"); 1580 RERAISE; 1581 } 1582 CATCH_ALL 1583 { 1584 exc_report(THIS_CATCH); 1585 fprintf(stderr, " *** unexpected exception raised!\n"); 1586 fprintf(stderr, " *** cancel %s pending\n", 1587 cancel_was_pending() ? "still" : "not"); 1588 RERAISE; 1589 } 1590 ENDTRY 1591} 1592 1593/* 1594 * static_cancel_test2 1595 * 1596 * Perform a RPC that does call a cancellable operation 1597 * and verify that a cancel is detected. 1598 */ 1599void static_cancel_test2(rh, idem, slow_secs) 1600 1601rpc_binding_handle_t rh; 1602unsigned32 idem; 1603unsigned long slow_secs; 1604 1605{ 1606 int oc; 1607 boolean32 pending; 1608 1609 printf(" Static Cancel Test 2 (server SHOULD detect cancel):\n"); 1610 1611 TRY 1612 { 1613 pthread_cancel(pthread_self()); 1614 if (idem) 1615 { 1616 perf_null_slow_idem(rh, 0 /* SLEEP LOOP */, slow_secs); 1617 } 1618 else 1619 { 1620 perf_null_slow(rh, 0 /* SLEEP LOOP */, slow_secs); 1621 } 1622 fprintf(stderr, " *** cancel exception NOT raised!\n"); 1623 1624 pending = cancel_was_pending(); 1625 oc = pthread_setcancel(CANCEL_OFF); 1626 1627 if (pending) 1628 printf(" ... but cancel not lost (was pending)\n"); 1629 else 1630 fprintf(stderr, " *** and lost cancel (not pending)!\n"); 1631 } 1632 CATCH (pthread_cancel_e) 1633 { 1634 fprintf(stderr, " Correct cancel exception operation\n"); 1635 if (cancel_was_pending()) 1636 fprintf(stderr, " *** but ERROR: cancel still pending!\n"); 1637 } 1638 CATCH (rpc_x_cancel_timeout) 1639 { 1640 fprintf(stderr, " *** unexpected cancel timeout exception raised!\n"); 1641 if (! cancel_was_pending()) 1642 fprintf(stderr, " *** and lost cancel (not pending)!\n"); 1643 RERAISE; 1644 } 1645 CATCH_ALL 1646 { 1647 exc_report(THIS_CATCH); 1648 fprintf(stderr, " *** unexpected exception raised!\n"); 1649 fprintf(stderr, " *** cancel %s pending\n", 1650 cancel_was_pending() ? "still" : "not"); 1651 RERAISE; 1652 } 1653 ENDTRY 1654} 1655 1656/* 1657 * static_cancel_test3 1658 * 1659 * Perform a RPC that doesn't call a cancellable operation followed 1660 * by one that does and verify that a cancel is detected. 1661 */ 1662void static_cancel_test3(rh, idem, slow_secs) 1663 1664rpc_binding_handle_t rh; 1665unsigned32 idem; 1666unsigned long slow_secs; 1667 1668{ 1669 int oc; 1670 boolean32 pending; 1671 volatile idl_boolean first_done = false; 1672 1673 printf(" Static Cancel Test 3 (server SHOULD detect cancel on 2nd RPC):\n"); 1674 1675 TRY 1676 { 1677 pthread_cancel(pthread_self()); 1678 1679 if (idem) 1680 { 1681 perf_null_slow_idem(rh, 2 /* CPU LOOP */, slow_secs); 1682 first_done = true; 1683 perf_null_slow_idem(rh, 0 /* SLEEP LOOP */, slow_secs); 1684 } 1685 else 1686 { 1687 perf_null_slow(rh, 2 /* CPU LOOP */, slow_secs); 1688 first_done = true; 1689 perf_null_slow(rh, 0 /* SLEEP LOOP */, slow_secs); 1690 } 1691 1692 pending = cancel_was_pending(); 1693 oc = pthread_setcancel(CANCEL_OFF); 1694 1695 fprintf(stderr, " *** cancel exception NOT raised!\n"); 1696 if (pending) 1697 { 1698 printf(" ... but cancel not lost (was pending)\n"); 1699 } 1700 else 1701 { 1702 fprintf(stderr, " *** and lost cancel (not pending)!\n"); 1703 } 1704 } 1705 CATCH (pthread_cancel_e) 1706 { 1707 if (! first_done) 1708 { 1709 fprintf(stderr, " *** unexpected cancel raised (1st call)!\n"); 1710 fprintf(stderr, " *** cancel %s pending\n", 1711 cancel_was_pending() ? "still" : "not"); 1712 } 1713 else 1714 { 1715 fprintf(stderr, " Correct cancel exception operation\n"); 1716 if (cancel_was_pending()) 1717 fprintf(stderr, " *** but ERROR: cancel still pending!\n"); 1718 } 1719 } 1720 CATCH (rpc_x_cancel_timeout) 1721 { 1722 fprintf(stderr, " *** unexpected cancel timeout raised (%s call)!\n", 1723 first_done ? "2nd" : "1st"); 1724 if (! cancel_was_pending()) 1725 fprintf(stderr, " *** and lost cancel (not pending)!\n"); 1726 RERAISE; 1727 } 1728 CATCH_ALL 1729 { 1730 exc_report(THIS_CATCH); 1731 fprintf(stderr, " *** unexpected exception raised (%s call)!\n", 1732 first_done ? "2nd" : "1st"); 1733 fprintf(stderr, " *** cancel %s pending\n", 1734 cancel_was_pending() ? "still" : "not"); 1735 } 1736 ENDTRY 1737} 1738 1739/* 1740 * Static Cancel test 1741 */ 1742 1743static void static_cancel_test (test, argc, argv) 1744 1745int test; 1746int argc; 1747char *argv[]; 1748 1749{ 1750 handle_t rh; 1751 int idem; 1752 int has_ctmo = false; 1753 signed32 ctmo = 0; 1754 unsigned short i, passes; 1755 unsigned long slow_secs = 5; 1756 unsigned32 st; 1757 1758 if (argc < 5) 1759 { 1760 usage(test); 1761 } 1762 1763 rh = binding_from_string_binding(NULL, argv[2]); 1764 passes = atoi(argv[3]); 1765 idem = argv[4][0] == 'y'; 1766 1767 if (argc > 5) 1768 slow_secs = atoi(argv[5]); 1769 1770 if (argc > 6) 1771 { 1772 has_ctmo = true; 1773 ctmo = atoi(argv[6]); 1774 } 1775 1776 printf(" passes: %d; idem: %s; slow secs: %ld; cancel timeout secs: %s\n", 1777 passes, idem ? "yes" : "no", slow_secs, 1778 has_ctmo ? argv[6] : "<default>"); 1779 1780 if (has_ctmo) 1781 { 1782 rpc_mgmt_set_cancel_timeout(ctmo, &st); 1783 if (st != rpc_s_ok) 1784 { 1785 fprintf(stderr, "*** Error setting cancel timeout - '%s'\n", 1786 error_text(st)); 1787 exit(1); 1788 } 1789 } 1790 1791 for (i = 0; i < passes; i++) 1792 { 1793 static_cancel_test1(rh, idem, slow_secs); 1794 static_cancel_test2(rh, idem, slow_secs); 1795 static_cancel_test3(rh, idem, slow_secs); 1796 1797 printf(" pass %2d...OK\n", i); 1798 } 1799} 1800 1801 1802/* 1803 * Context test 1804 */ 1805 1806static void context_test (test, argc, argv) 1807 1808int test; 1809int argc; 1810char *argv[]; 1811 1812{ 1813 handle_t rh; 1814 unsigned32 data, rdata; 1815 int die; 1816 struct timespec delay; 1817 idl_void_p_t context; 1818 unsigned short i, passes; 1819 1820 if (argc < 6) 1821 { 1822 usage(test); 1823 } 1824 1825 rh = binding_from_string_binding(NULL, argv[2]); 1826 passes = atoi(argv[3]); 1827 die = argv[4][0] == 'y'; 1828 1829 delay.tv_sec = atoi(argv[5]); 1830 delay.tv_nsec = 0; 1831 1832 printf(" passes: %d; die: %s; sleep secs: %ld\n", 1833 passes, die ? "yes" : "no", delay.tv_sec); 1834 1835 for (i = 0; i < passes; i++) 1836 { 1837 data = time (NULL); 1838 1839 perf_get_context (rh, data, &context); 1840 1841 if (! perf_test_context (context, &rdata)) 1842 { 1843 fprintf (stderr, "*** perf_get_context returned false\n"); 1844 } 1845 1846 if (rdata != data) 1847 { 1848 fprintf (stderr, "*** data mismatch on data returned by perf_get_context; %lu != %lu\n", 1849 rdata, data); 1850 } 1851 1852 if (delay.tv_sec > 0) 1853 { 1854 printf (" Sleeping for %ld seconds...\n", delay.tv_sec); 1855 pthread_delay_np(&delay); 1856 printf (" ...awake\n"); 1857 } 1858 1859 if (! die) 1860 { 1861 if (! perf_free_context (&context, &rdata)) 1862 { 1863 fprintf (stderr, "*** perf_free_context returned false\n"); 1864 } 1865 1866 if (rdata != data) 1867 { 1868 fprintf (stderr, "*** data mismatch on data returned by perf_free_context; %lu != %lu\n", 1869 rdata, data); 1870 } 1871 } 1872 1873 printf(" pass %2d...OK\n", i); 1874 } 1875} 1876 1877 1878/* 1879 * Looping test 1880 */ 1881 1882static void looping_test (test, argc, argv) 1883 1884int test; 1885int argc; 1886char *argv[]; 1887 1888{ 1889#define MSIZE (1024 * 1024) 1890 unsigned32 i; 1891 unsigned short passes; 1892 handle_t rh; 1893 unsigned32 st; 1894#ifdef NO_TIMES 1895 struct timeval start_time; 1896#else 1897 struct msec_time start_time; 1898#endif /* NO_TIMES */ 1899 struct msec_time avg_time; 1900 unsigned short cpp; 1901 unsigned32 *d; 1902 unsigned32 len; 1903 unsigned32 sum=0, rsum=0; 1904 unsigned32 n_calls, n_brd, n_maybe, n_brd_maybe; 1905 idl_boolean idem; 1906 idl_boolean verify; 1907 unsigned short pass, calln; 1908 unsigned32 slow_secs=0; 1909 perf_slow_mode_t slow_mode=0; 1910 static char *slow_mode_names[4] = {"sleep", "I/O", "CPU", "Fork sleep"}; 1911#ifdef _POSIX_THREADS 1912 static handle_t first_handle = NULL; 1913#endif 1914 1915 d = (unsigned32 *)malloc(MSIZE); 1916 1917 switch (test) 1918 { 1919 case 4: 1920 if (argc < 5) 1921 usage(test); 1922 break; 1923 default: 1924 if (argc < 7) 1925 usage(test); 1926 break; 1927 } 1928 1929 passes = atoi(argv[3]); 1930 cpp = atoi(argv[4]); 1931 if (test == 4) 1932 { 1933 verify = false; 1934 idem = true; 1935 } 1936 else 1937 { 1938 verify = argv[5][0] == 'y'; 1939 idem = argv[6][0] == 'y'; 1940 } 1941 len = 0; 1942 1943 /* 1944 * Sanity check calls/pass. 1945 */ 1946 1947 if (cpp <= 0) 1948 { 1949 fprintf (stderr, "\nERROR: calls/pass must be > 0.\n\n"); 1950 exit (1); 1951 } 1952 1953#ifdef _POSIX_THREADS 1954 if (multithread) 1955 { 1956 pthread_mutex_lock(&global_mutex); 1957 if (first_handle == NULL) 1958 { 1959 rh = first_handle = binding_from_string_binding(NULL, argv[2]); 1960 } 1961 else 1962 { 1963 if (use_shared_handle) 1964 { 1965 rpc_binding_handle_copy(first_handle, &rh, &st); 1966 } 1967 else 1968 { 1969 rpc_binding_copy(first_handle, &rh, &st); 1970 } 1971 1972 if (st != rpc_s_ok) 1973 { 1974 fprintf(stderr, "*** Can't copy binding - %s\n", error_text(st)); 1975 exit(1); 1976 } 1977 } 1978 pthread_mutex_unlock(&global_mutex); 1979 } 1980 else 1981#endif 1982 { 1983 rh = binding_from_string_binding(NULL, argv[2]); 1984 } 1985 1986 printf(" passes: %d; calls/pass: %d; verification: %s; idempotent: %s", 1987 passes, cpp, verify ? "on" : "off", idem ? "yes" : "no"); 1988 1989 switch (test) 1990 { 1991 case 1: 1992 case 2: 1993 if (argc < 8) 1994 { 1995 printf("\n"); 1996 usage(test); 1997 } 1998 len = atoi(argv[7]) / 4; 1999 printf("; bytes/call: %ld", len * 4); 2000 break; 2001 case 10: 2002 if (argc < 8) 2003 { 2004 printf("\n"); 2005 usage(test); 2006 } 2007 slow_secs = atoi(argv[7]); 2008 if (argc < 9) 2009 { 2010 slow_mode = perf_slow_sleep; 2011 } 2012 else 2013 { 2014 slow_mode = atoi(argv[8]); 2015 if (slow_mode > 3) 2016 { 2017 printf("\n"); 2018 usage(test); 2019 } 2020 } 2021 printf("; sleep secs: %ld; mode: %s", 2022 slow_secs, slow_mode_names[slow_mode]); 2023 break; 2024 } 2025 2026 printf("\n"); 2027 2028 for (pass = 1; pass <= passes; pass++) 2029 { 2030 if (verify && ! idem) 2031 { 2032 perf_init(rh); 2033 } 2034 2035#ifdef NO_TIMES 2036 GETTIMEOFDAY(&start_time); 2037#else 2038 start_timing(&start_time); 2039#endif /* NO_TIMES */ 2040 2041 for (calln = 1; calln <= cpp; calln++) 2042 { 2043 if (verify) 2044 { 2045 for (i = 0, rsum = 0; i < len; i++) 2046 { 2047 d[i] = i * perf_magic * pass * calln; 2048 rsum += d[i]; 2049 } 2050 } 2051 2052 /* 2053 * for non-32 bit machines 2054 */ 2055 rsum &= (unsigned long) 0xffffffff; 2056 2057 switch (test) 2058 { 2059 case 0: 2060 if (idem) 2061 { 2062 perf_null_idem(rh); 2063 } 2064 else 2065 { 2066 perf_null(rh); 2067 } 2068 break; 2069 2070 case 4: 2071 perf_maybe(rh); 2072 break; 2073 2074 case 10: 2075 if (idem) 2076 { 2077 perf_null_slow_idem(rh, slow_mode, slow_secs); 2078 } 2079 else 2080 { 2081 perf_null_slow(rh, slow_mode, slow_secs); 2082 } 2083 break; 2084 2085 case 1: 2086 if (idem) 2087 { 2088 perf_in_idem(rh, d, len, verify, &sum); 2089 } 2090 else 2091 { 2092 perf_in(rh, d, len, verify, &sum); 2093 } 2094 if (verify) 2095 { 2096 if (sum != rsum) 2097 { 2098 fprintf(stderr, "*** Sum mismatch (%lu, %lu)\n", 2099 sum, rsum); 2100 } 2101 } 2102 break; 2103 2104 case 2: 2105 { 2106 unsigned32 tlen = len; 2107 2108 if (idem) 2109 { 2110 perf_out_idem (rh, d, &tlen, len, 2111 pass * calln, verify); 2112 } 2113 else 2114 { 2115 perf_out (rh, d, &tlen, len, 2116 pass * calln, verify); 2117 } 2118 if (len != tlen) 2119 { 2120 fprintf(stderr, 2121"*** Output length (%lu) is not equal to input length (%lu)\n", tlen, len); 2122 exit(1); 2123 } 2124 2125 if (verify) 2126 { 2127 for (i = 0, sum = 0; i < len; i++) 2128 { 2129 sum += d[i]; 2130 } 2131 2132 /* 2133 * for non-32 bit machines 2134 */ 2135 sum &= (unsigned long) 0xffffffff; 2136 if (sum != rsum) 2137 { 2138 fprintf(stderr, "*** Sum mismatch (%lu, %lu)\n", 2139 sum, rsum); 2140 } 2141 } 2142 break; 2143 } 2144 2145 case 6: 2146 { 2147 float f1 = (float) (rand()+1); 2148 float f2 = (calln & 1 ? 1.0 : -1.0) * (rand()+1); 2149 double d1 = 1.0 / (rand()+1); 2150 double d2; 2151 float o1, o1_l; 2152 double o2, o2_l; 2153 2154 d2 = sqrt(pow((double) (7 + (rand()+1) % 10), 2155 (double) ((rand()+1) % 40))); 2156 o1_l = (f1 / f2) * (d1 / d2); 2157 o2_l = (f2 / f1) * (d2 / d1); 2158 2159 MARSHALL_DOUBLE(d1); 2160 MARSHALL_DOUBLE(d2); 2161 2162 perf_fp_test(rh, &f1, &f2, d1, d2, &o1, &o2); 2163 2164 UNMARSHALL_DOUBLE(o2); 2165 2166 if (verify) 2167 { 2168 if (! approx_eq(o1, o1_l)) 2169 { 2170 fprintf(stderr, 2171 "*** Floating error #1 (%g != %g -- (%g / %g) * (%g / %g))\n", 2172 o1, o1_l, f1, f2, d1, d2); 2173 } 2174 2175 if (! approx_eq(o2, o2_l)) 2176 { 2177 fprintf(stderr, 2178 "*** Floating error #2 (%g != %g -- (%g / %g) * (%g / %g))\n", 2179 o2, o2_l, f2, f1, d2, d1); 2180 } 2181 } 2182 break; 2183 } 2184 } 2185#ifdef _POSIX_THREADS 2186 if (! multithread) 2187#endif 2188 { 2189 if (reset_binding_freq > 0 && calln % reset_binding_freq == 0) 2190 { 2191 binding_reset(rh); 2192 printf(" [binding has been reset]\n"); 2193 } 2194 if (recreate_binding_freq > 0 && calln % recreate_binding_freq == 0) 2195 { 2196 rpc_binding_free(&rh, &st); 2197 rh = binding_from_string_binding(NULL, argv[2]); 2198 printf(" [binding has been recreated]\n"); 2199 } 2200 } 2201 } 2202 2203 end_timing(&start_time, cpp, &avg_time); 2204 2205 if (verify && (! idem) 2206#ifdef _POSIX_THREADS 2207 && (! multithread) 2208#endif 2209 ) 2210 { 2211 perf_info(rh, &n_calls, &n_brd, &n_maybe, &n_brd_maybe); 2212 if (n_calls != cpp) 2213 { 2214 fprintf(stderr, "*** Call count mismatch (%lu, %d)\n", 2215 n_calls, cpp); 2216 } 2217 } 2218 2219#ifdef NO_TIMES 2220 printf(" pass %3d; ms/call: %lu.%03u", 2221 pass, avg_time.msec, avg_time.usec); 2222 2223 if (len > 0 && avg_time.msec > 0) 2224 { 2225 printf("; kbytes/sec: %3lu", (len * 4) / avg_time.msec); 2226 } 2227#else 2228 if (avg_time.u_msec == 0 || avg_time.s_msec == 0) 2229 printf(" pass %3d; ms/call: %lu.%03lu (ms/pass: %lu/%lu)", 2230 pass, avg_time.r_msec, avg_time.r_usec, 2231 avg_time.ptime.tms_utime*(1000/clock_ticks), 2232 avg_time.ptime.tms_stime*(1000/clock_ticks)); 2233 else 2234 printf(" pass %3d; ms/call: %lu.%03lu (%lu/%lu)", 2235 pass, avg_time.r_msec, avg_time.r_usec, 2236 avg_time.u_msec, avg_time.s_msec); 2237 2238 if (len > 0 && avg_time.r_msec > 0) 2239 { 2240 printf("; kbytes/sec: %3lu", (len * 4) / avg_time.r_msec); 2241 } 2242#endif /* NO_TIMES */ 2243 2244 printf("\n"); 2245 2246 } 2247} 2248 2249/* 2250 * One shot test 2251 */ 2252 2253static void one_shot_test (test, argc, argv) 2254 2255int test; 2256int argc; 2257char *argv[]; 2258 2259{ 2260 handle_t rh; 2261#ifdef NO_TIMES 2262 struct timeval start_time; 2263#else 2264 struct msec_time start_time; 2265#endif /* NO_TIMES */ 2266 struct msec_time avg_time; 2267 idl_boolean fwd; 2268 idl_boolean idem; 2269 2270 if (argc < 5) 2271 { 2272 usage(test); 2273 } 2274 2275 fwd = argv[3][0] == 'y'; 2276 idem = argv[4][0] == 'y'; 2277 2278 rh = binding_from_string_binding(NULL, argv[2]); 2279 2280 printf(" forward: %s; idempotent: %s\n", 2281 fwd ? "yes" : "no", idem ? "yes" : "no"); 2282 2283#ifdef NO_TIMES 2284 GETTIMEOFDAY(&start_time); 2285#else 2286 start_timing(&start_time); 2287#endif /* NO_TIMES */ 2288 2289 if (fwd) 2290 if (idem) 2291 perfb_null_idem(rh); 2292 else 2293 perfb_null(rh); 2294 else 2295 if (idem) 2296 perf_null_idem(rh); 2297 else 2298 perf_null(rh); 2299 2300 end_timing(&start_time, 1, &avg_time); 2301 2302#ifdef NO_TIMES 2303 printf(" ms: %lu.%03u\n", avg_time.msec, avg_time.usec); 2304#else 2305 printf(" ms: %lu.%03lu (%lu/%lu)\n", 2306 avg_time.r_msec, avg_time.r_usec, 2307 avg_time.u_msec, avg_time.s_msec); 2308#endif /* NO_TIMES */ 2309} 2310 2311/* 2312 * Start test. Catch and print any exceptions that are raised. 2313 */ 2314 2315void rpc__cn_set_sock_buffsize ( 2316 unsigned32 /* rsize */, 2317 unsigned32 /* ssize */, 2318 unsigned32 * /* st */); 2319void rpc__cn_inq_sock_buffsize ( 2320 unsigned32 * /* rsize */, 2321 unsigned32 * /* ssize */, 2322 unsigned32 * /* st */); 2323 2324static void start_test(test, argc, argv) 2325 2326int test; 2327int argc; 2328char *argv[]; 2329{ 2330 unsigned32 rsize, ssize; 2331 error_status_t status; 2332 2333 rpc__cn_set_sock_buffsize(socket_buf_size, socket_buf_size, &status); 2334 if (status != rpc_s_ok) 2335 { 2336 fprintf(stderr,"*** rpc__cn_set_sock_buffsize failed (0x%lx)\n", status); 2337 exit(1); 2338 } 2339 2340 rpc__cn_inq_sock_buffsize(&rsize, &ssize, &status); 2341 if (status != rpc_s_ok) 2342 { 2343 fprintf(stderr,"*** rpc__cn_inq_sock_buffsize failed (0x%lx)\n", status); 2344 exit(1); 2345 } 2346 if (socket_buf_size != rsize || socket_buf_size != ssize) 2347 { 2348 fprintf(stderr, "*** CN socket buffer sizes dont match:\n"); 2349 fprintf(stderr, "*** READ desired: %lu actual: %lu\n", socket_buf_size, rsize); 2350 fprintf(stderr, "*** WRITE desired: %lu actual: %lu\n", socket_buf_size, ssize); 2351 exit(1); 2352 } 2353 2354 TRY 2355 { 2356 (*tinfo[test].proc)(test, argc, argv); 2357 } 2358 CATCH (rpc_x_comm_failure) 2359 { 2360 fprintf(stderr, "*** \"Communications failure\" exception raised\n"); 2361 } 2362 CATCH (rpc_x_op_rng_error) 2363 { 2364 fprintf(stderr, "*** \"Operation out of range\" exception raised\n"); 2365 } 2366 CATCH (rpc_x_unknown_if) 2367 { 2368 fprintf(stderr, "*** \"Unknown interface\" exception raised\n"); 2369 } 2370 CATCH (rpc_x_unknown_error) 2371 { 2372 fprintf(stderr, "*** \"Unknown error\" exception raised\n"); 2373 } 2374 CATCH (rpc_x_unknown_remote_fault) 2375 { 2376 fprintf(stderr, "*** \"Unknown remote fault\" exception raised\n"); 2377 } 2378 CATCH_ALL 2379 { 2380 exc_report(THIS_CATCH); 2381 fprintf(stderr, "*** Unknown exception raised\n"); 2382 } 2383 FINALLY 2384 { 2385 check_wait_point(0); 2386 } 2387 ENDTRY 2388} 2389 2390 2391#ifdef _POSIX_THREADS 2392 2393struct task_info_t 2394{ 2395 int thread; 2396 int test; 2397 int argc; 2398 char **argv; 2399}; 2400 2401/* 2402 * Base procedure for multithreading test 2403 */ 2404 2405static void multi_task (info, len) 2406 2407struct task_info_t *info; 2408int len __attribute__(unused); 2409 2410{ 2411 unsigned32 st; 2412 2413 if (cancel_timeout != -1) 2414 { 2415 rpc_mgmt_set_cancel_timeout(cancel_timeout, &st); 2416 if (st != rpc_s_ok) 2417 { 2418 fprintf(stderr, 2419 "*** Error setting cancel timeout (thread %d) - '%s'\n", 2420 info->thread, error_text(st)); 2421 return; 2422 } 2423 } 2424 2425 TRY 2426 { 2427 start_test(info->test, info->argc, info->argv); 2428 } 2429 CATCH_ALL 2430 { 2431 exc_report(THIS_CATCH); 2432 fprintf(stderr, "*** Multi-thread base: exception raised (thread %d)\n", info->thread); 2433 RERAISE; 2434 } 2435 ENDTRY 2436} 2437 2438#endif 2439 2440 2441#ifdef _POSIX_THREADS 2442 2443/* 2444 * Start up multiple tasks, each running a test. 2445 */ 2446 2447#define TASK_STACK_SIZE (64 * 1024) 2448#define TASK_PRIORITY 3 2449 2450static void multi_test (test, argc, argv) 2451 2452int test; 2453int argc; 2454char *argv[]; 2455{ 2456 int i; 2457 volatile idl_boolean done; 2458 pthread_t tasks[MAX_TASKS]; 2459 2460 DO_NOT_CLOBBER(i); 2461 2462 if (n_tasks > MAX_TASKS) 2463 { 2464 fprintf(stderr, "%d is too many tasks (max is %d)\n", n_tasks, MAX_TASKS); 2465 exit(1); 2466 } 2467 2468 setbuf(stdout, NULL); /* Buffered output and tasking don't mix */ 2469 2470 printf(" Multithreading: # tasks = %d\n", n_tasks); 2471 2472 for (i = 0; i < n_tasks; i++) 2473 { 2474 struct task_info_t *info = (struct task_info_t *) malloc(sizeof(struct task_info_t)); 2475 2476 info->thread = i; 2477 info->test = test; 2478 info->argc = argc; 2479 info->argv = argv; 2480 2481 TRY { 2482 pthread_create(&tasks[i], pthread_attr_default, 2483 (pthread_startroutine_t) multi_task, (pthread_addr_t) info); 2484 } CATCH_ALL { 2485 exc_report(THIS_CATCH); 2486 printf("*** pthread_create failed\n"); 2487 exit(1); 2488 } ENDTRY 2489 } 2490 2491 done = false; 2492 while (!done) 2493 { 2494 TRY { 2495 for (i = 0; i < n_tasks; i++) 2496 { 2497 void *junk; 2498 pthread_join(tasks[i], &junk); 2499 } 2500 done = true; 2501 } CATCH_ALL { 2502 exc_report(THIS_CATCH); 2503 printf("*** Cancelling threads\n"); 2504 for (i = 0; i < n_tasks; i++) 2505 { 2506 pthread_cancel(tasks[i]); 2507 } 2508 } ENDTRY 2509 } 2510 2511 if (stats) 2512 { 2513 do_stats (NULL); 2514 } 2515} 2516 2517#endif 2518 2519 2520/* 2521 * Parse authentication (-p) option. 2522 */ 2523extern int lookup_name(char *table[], char *s); 2524 2525static void parse_auth_option() 2526{ 2527 extern char *optarg; 2528 char *s; 2529 2530 char *tmp; 2531 2532 if ((tmp = (char *)malloc(strlen(optarg)+1)) == NULL) 2533 { 2534 fprintf(stderr, "*** No more memery\n"); 2535 exit(1); 2536 } 2537 2538 strlcpy(tmp, optarg, strlen(optarg)+1)); 2539 2540 /* 2541 * We can't free tmp, so we will loose some memory after each fork. 2542 */ 2543 2544 if ((s = (char *) strtok(tmp, ",")) == NULL) 2545 usage(-1); 2546 authn_protocol = strcmp(s, "default") == 0 ? 2547 rpc_c_authn_default : lookup_name(authn_names, s); 2548 2549 if ((s = (char *) strtok(NULL, ",")) == NULL) 2550 usage(-1); 2551 authz_protocol = lookup_name(authz_names, s); 2552 2553 if ((s = (char *) strtok(NULL, ",")) == NULL) 2554 { 2555 authn_level = rpc_c_authn_level_default; 2556 } 2557 else 2558 { 2559 authn_level = lookup_name(authn_level_names, s); 2560 2561 if ((auth_principal = (idl_char *) strtok(NULL, " ")) == NULL) 2562 { 2563 auth_principal = NULL; 2564 } 2565 } 2566} 2567 2568 2569/* 2570 * Main program 2571 */ 2572extern void rpc__dbg_set_switches ( 2573 char * /*s*/, 2574 unsigned32 * /*st*/ 2575 ); 2576extern void dump_stg_info(void); 2577 2578int main (argc, argv) 2579 2580int argc; 2581char *argv[]; 2582 2583{ 2584 int test, save_argc=0; 2585 unsigned32 st; 2586 int c; 2587 idl_boolean stats = false; 2588 extern int optind; 2589 extern char *optarg; 2590 char *s, **save_argv=NULL; 2591 int do_fork = 0; 2592 int fork_count = 0; 2593 pid_t cpid = 0; 2594 pid_t opid = getpid(); 2595 2596 if ((clock_ticks = sysconf(_SC_CLK_TCK)) == -1) 2597 clock_ticks = 1; 2598 2599fork_test_replay: 2600 2601 while ((c = getopt(argc, argv, "oslDi1B:d:p:m:M:t:c:f:w:v:r:R:")) != EOF) 2602 { 2603 switch (c) 2604 { 2605 case 'd': 2606 case 'D': 2607 rpc__dbg_set_switches(c == 'd' ? optarg : DEBUG_LEVEL, &st); 2608 if (st != rpc_s_ok) 2609 { 2610 fprintf(stderr, "*** Error setting debug level - %s\n", 2611 error_text(st)); 2612 usage(-1); 2613 } 2614 2615 debug = true; 2616 break; 2617 2618 case 'p': 2619 parse_auth_option(); 2620 authenticate = true; 2621 break; 2622 2623 case 'i': 2624 stats = true; 2625 break; 2626 2627 case 't': 2628 timeout = atoi(optarg); 2629 break; 2630 2631 case 'v': 2632 verbose = atoi(optarg); 2633 break; 2634 2635 case 'c': 2636 cancel_timeout = atoi(optarg); 2637 if (cancel_timeout != -1) 2638 { 2639 rpc_mgmt_set_cancel_timeout(cancel_timeout, &st); 2640 if (st != rpc_s_ok) 2641 { 2642 fprintf(stderr, "*** Error setting cancel timeout - '%s'\n", 2643 error_text(st)); 2644 exit(1); 2645 } 2646 } 2647 break; 2648 2649 case 's': 2650 stats = true; 2651 break; 2652 2653 case 'f': 2654 /* 2655 * If we've already forked, don't do it again. 2656 */ 2657 if (do_fork == 0) 2658 { 2659 do_fork = atoi(optarg); 2660 save_argc = argc; 2661 save_argv = argv; 2662 } 2663 break; 2664 2665 case 'w': 2666 { 2667 char *tmp; 2668 2669 if ((tmp = (char *)malloc(strlen(optarg)+1)) == NULL) 2670 { 2671 fprintf(stderr, "*** No more memory\n"); 2672 exit(1); 2673 } 2674 2675 strlcpy(tmp, optarg, strlen(optarg)+1)); 2676 2677 /* 2678 * We can't free tmp, so we will loose some memory after each fork. 2679 */ 2680 2681 if ((s = (char *) strtok(tmp, ",")) == NULL) 2682 usage(-1); 2683 wait_point = atoi(s); 2684 2685 if ((s = (char *) strtok(NULL, " ")) == NULL) 2686 usage(-1); 2687 wait_time = atoi(s); 2688 } 2689 break; 2690 2691 case 'o': 2692 use_obj = true; 2693 break; 2694 2695 case '1': 2696 compat_mode = true; 2697 break; 2698 2699 case 'r': 2700 reset_binding_freq = atoi(optarg); 2701 break; 2702 2703 case 'R': 2704 recreate_binding_freq = atoi(optarg); 2705 break; 2706 2707#ifdef _POSIX_THREADS 2708 case 'm': 2709 case 'M': 2710 multithread = true; 2711 n_tasks = atoi(optarg); 2712 use_shared_handle = (c == 'M'); 2713 break; 2714#endif 2715 2716 case 'B': 2717 socket_buf_size = atoi(optarg); 2718 break; 2719 2720 default: 2721 usage(-1); 2722 } 2723 } 2724 2725 argc -= optind - 1; 2726 argv = &argv[optind - 1]; 2727 2728 if (argc < 2) 2729 { 2730 usage(-1); 2731 } 2732 2733 test = atoi(argv[1]); 2734 2735 if (test < 0 || test > N_TESTS - 1) 2736 { 2737 usage(-1); 2738 } 2739 2740 printf("%s test [%d]", tinfo[test].name, test); 2741 2742 if (debug) 2743 { 2744 printf(" (debug on)"); 2745 } 2746 2747 printf("\n"); 2748 2749 if (authenticate) 2750 { 2751 VRprintf(2, (" -----------------\n Authentication params:\n authn protocol: %s\n authz protocol: %s\n level: %s\n server princ: \"%s\"\n -----------------\n", 2752 authn_protocol == (unsigned32)rpc_c_authn_default ? 2753 "default" : authn_names[authn_protocol], 2754 authz_names[authz_protocol], 2755 authn_level_names[authn_level], 2756 (auth_principal == NULL) ? "<none given>" : (char *) auth_principal)); 2757 } 2758 2759 if (debug) 2760 { 2761 dump_stg_info(); 2762 } 2763 2764 check_wait_point(1); 2765 2766 if (fork_count != 0 || do_fork != 6) 2767 { 2768#ifdef _POSIX_THREADS 2769 pthread_mutex_init(&global_mutex, pthread_mutexattr_default); 2770 2771 if (multithread) 2772 { 2773 multi_test(test, argc, argv); 2774 exit(0); 2775 } 2776#endif 2777 2778 start_test(test, argc, argv); 2779 2780 if (stats) 2781 { 2782 do_stats (NULL); 2783 } 2784 } 2785 2786 switch (do_fork) 2787 { 2788 case 1: 2789 if (opid != getpid()) /* child */ 2790 break; 2791 if (fork_count != 0) /* original */ 2792 { 2793 waitpid(cpid, NULL, 0); 2794 break; 2795 } 2796 /* 2797 * Do the fork. Both parent and child need to jump back and 2798 * start over again. 2799 */ 2800 cpid = fork(); 2801 fork_count++; 2802 argc = save_argc; 2803 argv = save_argv; 2804 optind = 1; 2805 goto fork_test_replay; 2806 break; 2807 case 2: 2808 if (fork_count != 0) /* original */ 2809 { 2810 waitpid(cpid, NULL, 0); 2811 break; 2812 } 2813 /* 2814 * Do the fork. Only parent need to jump back and 2815 * start over again. 2816 */ 2817 cpid = fork(); 2818 fork_count++; 2819 2820 if (cpid == 0) /* child */ 2821 break; 2822 2823 argc = save_argc; 2824 argv = save_argv; 2825 optind = 1; 2826 goto fork_test_replay; 2827 break; 2828 case 3: 2829 if (opid != getpid()) /* child */ 2830 break; 2831 /* 2832 * Do the fork. Only child need to jump back and 2833 * start over again. 2834 */ 2835 cpid = fork(); 2836 fork_count++; 2837 2838 if (cpid != 0) /* original */ 2839 { 2840 waitpid(cpid, NULL, 0); 2841 break; 2842 } 2843 2844 argc = save_argc; 2845 argv = save_argv; 2846 optind = 1; 2847 goto fork_test_replay; 2848 break; 2849 case 4: 2850 if (fork_count == 1) /* child */ 2851 { 2852 waitpid(cpid, NULL, 0); 2853 break; 2854 } 2855 if (opid != getpid()) /* grandchild */ 2856 break; 2857 /* 2858 * Do the fork twice. Both child and grandchild need to jump back and 2859 * start over again. 2860 */ 2861 cpid = fork(); 2862 fork_count++; 2863 2864 if (cpid != 0) /* original */ 2865 { 2866 waitpid(cpid, NULL, 0); 2867 break; 2868 } 2869 2870 cpid = fork(); 2871 if (cpid == 0) /* grandchild */ 2872 fork_count++; 2873 2874 argc = save_argc; 2875 argv = save_argv; 2876 optind = 1; 2877 goto fork_test_replay; 2878 break; 2879 case 5: 2880 if (opid != getpid()) /* grandchild */ 2881 break; 2882 /* 2883 * Do the fork twice. Only grandchild need to jump back and 2884 * start over again. 2885 */ 2886 cpid = fork(); 2887 fork_count++; 2888 2889 if (cpid != 0) /* original */ 2890 { 2891 waitpid(cpid, NULL, 0); 2892 break; 2893 } 2894 2895 cpid = fork(); 2896 fork_count++; 2897 2898 if (cpid != 0) /* child */ 2899 { 2900 waitpid(cpid, NULL, 0); 2901 break; 2902 } 2903 2904 argc = save_argc; 2905 argv = save_argv; 2906 optind = 1; 2907 goto fork_test_replay; 2908 break; 2909 case 6: 2910 if (opid != getpid()) /* child */ 2911 break; 2912 /* 2913 * Do the fork. Only child need to jump back and 2914 * start over again. 2915 */ 2916 cpid = fork(); 2917 fork_count++; 2918 2919 if (cpid != 0) /* original */ 2920 { 2921 waitpid(cpid, NULL, 0); 2922 break; 2923 } 2924 2925 argc = save_argc; 2926 argv = save_argv; 2927 optind = 1; 2928 goto fork_test_replay; 2929 break; 2930 default: 2931 break; 2932 } 2933 2934 exit(0); 2935} 2936