test.c (40671B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: test.c 8 * Purpose: entry point for all tr related routines 9 */ 10 11 #ifdef INCLUDE_TEST 12 13 #include <shared/bsl.h> 14 15 #include <sal/types.h> 16 #include <sal/core/libc.h> 17 #include <shared/bsl.h> 18 #include <soc/debug.h> 19 #include <soc/drv.h> 20 21 #include <appl/diag/system.h> 22 #include <appl/diag/test.h> 23 #include <appl/diag/progress.h> 24 25 #ifndef NO_CTRL_C 26 #include <setjmp.h> 27 #endif 28 29 #ifdef __KERNEL__ 30 #define atoi _shr_ctoi 31 #endif 32 33 /* 34 * Variable: test_XXX_usage 35 * Purpose: usage strings for various tests. 36 */ 37 38 #define TEST_ID_USAGE \ 39 "\"Test ID\" is a test #, test name, or \"*\"\n" 40 41 char test_list_usage[] = 42 "Parameters: [Test ID] ...\n\t" 43 "Display the tests specified by [Test ID] in table format,\n\t" 44 "A=active, S=selected, # Runs = number times test dispatched, \n\t" 45 "# Pass = number times test completed successfully, \n\t" 46 "# Fail = number times test completed with a failure\n\t" 47 TEST_ID_USAGE; 48 49 static test_t *test_active = NULL; /* Pointer to active test */ 50 static sal_thread_t test_thread = NULL; /* Pointer to test thread */ 51 52 /* 53 * variables: test_active_jmp 54 * Purpose: Long jump buffer used to return from a running 55 * test such as "test_exit" call. 56 */ 57 #ifndef NO_CTRL_C 58 static jmp_buf test_active_jmp; /* test_exit Long jump */ 59 #endif 60 /* 61 * Defines: TEST_XXX 62 * Purpose: Return values from longjmp indicating action to 63 * take (also return value from some of the "run" 64 * routines. 65 * 66 * TEST_RUNNING - (0), normal return from longjmp 67 * TEST_ABORT - (1), abort current test, continue running 68 * test sequence. 69 * TEST_STOP - (2), abort current test, AND test sequence. 70 * TEST_CONTINUE- (3), continue running test and sequence 71 * TEST_INTR - (4), test aborted by CTRL-C 72 */ 73 #define TEST_RUNNING 0 74 #define TEST_ABORT 1 75 #define TEST_STOP 2 76 #define TEST_CONTINUE 3 77 #define TEST_INTR 4 78 79 #define TEST_O_SOE 0x01 /* Stop on Error */ 80 #define TEST_O_AOE 0x02 /* Abort on Error */ 81 #define TEST_O_BATCH 0x04 /* Batch Mode */ 82 #define TEST_O_RANDOM 0x08 /* Random Mode */ 83 #define TEST_O_PROGRESS 0x10 /* Print test progress */ 84 #define TEST_O_SILENT 0x20 /* Don't print test error msgs */ 85 #define TEST_O_RUN 0x40 /* Print msg when test run */ 86 #define TEST_O_OVERRIDE 0x80 /* Override Chips */ 87 #define TEST_O_QUIET 0x100 /* Don't print messages */ 88 #define TEST_O_NO_REINIT 0x200 /* No reinit */ 89 90 static uint32 test_options = 0; /* Run options */ 91 static int last_test_status[SOC_MAX_NUM_DEVICES] = {0}; /* Store the last test runs status */ 92 93 /* 94 * Approach changed from 1 global testlist to dynamic list assignment for whatever reason one chose 95 * It may be SOC_IS based as in case of Jericho2/Ramon, or any other one 96 * So this routine allows caller to assigns test_list and test_cnt local values instead of global ones 97 */ 98 static test_t *get_test_list(int unit, int *test_cnt_p) 99 { 100 #if defined(BCM_SAND_SUPPORT) 101 /* For now only Jericho 2 and Ramon will utilize sand_test_list, but we may consider to moving all the dune 102 * chip families due to lack of bits in common_test_list 103 */ 104 if(SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) 105 { 106 *test_cnt_p = sand_test_cnt; 107 return sand_test_list; 108 } 109 else 110 #endif 111 { 112 *test_cnt_p = common_test_cnt; 113 return common_test_list; 114 } 115 } 116 117 int 118 test_is_no_reinit_mode(int unit) 119 { 120 return ((test_options & TEST_O_NO_REINIT) > 0); 121 } 122 123 int 124 test_get_last_test_status(int unit) 125 { 126 assert((unit < SOC_MAX_NUM_DEVICES) && (unit >= 0)); 127 return last_test_status[unit]; 128 } 129 130 STATIC uint32 131 _test_chip(int unit) 132 /* 133 * Function: _test_chip 134 * Purpose: Return current T56xx mask based on unit #. 135 * Parameters: Unit - Strata Swtich unit #. 136 * Returns: Mask. 137 */ 138 { 139 if (!soc_attached(unit)) { 140 return(0); 141 } 142 switch (SOC_CHIP_GROUP(unit)) { 143 #if defined (BCM_SAND_SUPPORT) 144 case SOC_CHIP_BCM88650: return(T88650); 145 case SOC_CHIP_BCM88660: return(T88650); 146 case SOC_CHIP_BCM88675: return(T88675); 147 case SOC_CHIP_BCM88375: return(T88675); 148 case SOC_CHIP_BCM88680: return(T88675); 149 case SOC_CHIP_BCM88470: return(T88675); 150 case SOC_CHIP_BCM83208: return(T88675); 151 case SOC_CHIP_BCM88202: return(T88650); 152 case SOC_CHIP_BCM88750: return(T88750); 153 case SOC_CHIP_BCM88270: return(T88675); 154 case SOC_CHIP_BCM88950: return(T88750); 155 case SOC_CHIP_BCM88952: return(T88750); 156 case SOC_CHIP_BCM88752: return(T88750); 157 /* Starting from Jericho 2 and Ramon there is another test_list with new bitmap TSxxxxx instead of Txxxxx */ 158 case SOC_CHIP_BCM8869X: return(TS88690); 159 case SOC_CHIP_BCM8879X: return(TS88790); 160 #endif 161 #if defined(BCM_ESW_SUPPORT) 162 case SOC_CHIP_BCM5675: return(T5675); 163 case SOC_CHIP_BCM56102: return(T56504); 164 case SOC_CHIP_BCM56304: return(T56504); 165 case SOC_CHIP_BCM56112: return(T56504); 166 case SOC_CHIP_BCM56314: return(T56504); 167 case SOC_CHIP_BCM56504: return(T56504); 168 case SOC_CHIP_BCM56514: return(T56504); 169 case SOC_CHIP_BCM56800: 170 if (SOC_IS_HUMV(unit)) { 171 return(T56700); 172 } else { 173 return(T56504); 174 } 175 case SOC_CHIP_BCM56820: return(T56820); 176 case SOC_CHIP_BCM56725: return(T56700); 177 case SOC_CHIP_BCM56624: return(T56624); 178 case SOC_CHIP_BCM56680: return(T56624); 179 case SOC_CHIP_BCM56218: return(T56218); 180 case SOC_CHIP_BCM56224: return(T56224); 181 case SOC_CHIP_BCM53314: return(T53314); 182 case SOC_CHIP_BCM56634: return(T56634); 183 case SOC_CHIP_BCM56524: return(T56634); 184 case SOC_CHIP_BCM56685: return(T56634); 185 case SOC_CHIP_BCM56334: return(T56334); 186 case SOC_CHIP_BCM56142: return(T56142); 187 case SOC_CHIP_BCM56150: return(T56150); 188 case SOC_CHIP_BCM56160: return(T56160); 189 case SOC_CHIP_BCM53540: return(T56160); 190 case SOC_CHIP_BCM53400: return(T53400); 191 case SOC_CHIP_BCM88732: return(T88732); 192 case SOC_CHIP_BCM56840: return(T56840); 193 case SOC_CHIP_BCM56640: return(T56640); 194 case SOC_CHIP_BCM56340: return(T56340); 195 case SOC_CHIP_BCM56440: return(T56440); 196 case SOC_CHIP_BCM56450: return(T56450); 197 case SOC_CHIP_BCM56260: return(T56260); 198 case SOC_CHIP_BCM56270: return(T56270); 199 case SOC_CHIP_BCM56850: return(T56850); 200 case SOC_CHIP_BCM56860: return(T56860); 201 case SOC_CHIP_BCM56960: return(T56960); 202 case SOC_CHIP_BCM56965: return(T56960); 203 case SOC_CHIP_BCM56980: return(T56980); 204 case SOC_CHIP_BCM56560: return(T56560); 205 case SOC_CHIP_BCM56870: return(T56870); 206 case SOC_CHIP_BCM53570: return(T53570); 207 case SOC_CHIP_BCM56970: return(T56970); 208 case SOC_CHIP_BCM56770: return(T56770); 209 case SOC_CHIP_BCM56370: return(T56370); 210 case SOC_CHIP_BCM56670: return(T56670); 211 #endif 212 default: return(0); 213 } 214 } 215 216 static test_t * 217 test_find(char *key, test_t *test_list, int test_cnt) 218 /* 219 * Function: test_find 220 * Purpose: Location a matching entry in the TEST test list. 221 * Parameters: key - key to lookup name on 222 * Returns: Pointer to entry if found, NULL if no match 223 * Notes: If key is all digits (0-9), it is assumed top be a test 224 * number otherwise it is a test name. 225 */ 226 { 227 test_t *test = NULL; 228 int ki, kl; /* Key integer/length */ 229 int i; 230 231 if (isint(key)) { /* Locate on test number */ 232 ki = atoi(key); 233 for (i = 0; !test && (i < test_cnt); i++) { 234 if (test_list[i].t_test == ki) { 235 test = &test_list[i]; 236 } 237 } 238 } else { /* Locate Based on name */ 239 kl = strlen(key); 240 for (i = 0; !test && (i < test_cnt); i++) { 241 if (!sal_strncasecmp(key, test_list[i].t_name, kl)) { 242 test = &test_list[i]; 243 } 244 } 245 } 246 return(test); 247 } 248 249 void 250 test_done(int u, test_t *test, int status) 251 /* 252 * Function: test_done 253 * Purpose: Process the completion of a test 254 * Parameters: u - unit number. 255 * test - pointer to test completed. 256 * status - exit status of test. 257 * Returns: Nothing. 258 */ 259 { 260 if (status || (test->t_flags & T_F_ERROR)) { 261 last_test_status[u] = -1; 262 test->t_fail++; 263 LOG_INFO(BSL_LS_APPL_TESTS, 264 (BSL_META_U(u, 265 "Test %d (%s) Completed with error (%d)\n"), 266 test->t_test, test->t_name, status)); 267 /* 268 * If Stop-on-error not processed yet, give user a chance 269 * now. 270 */ 271 if ((status == TEST_ABORT) || (status == TEST_STOP)) { 272 cli_out("Test %d (%s) Aborted\n", test->t_test, test->t_name); 273 } else if ((test_options & TEST_O_SOE) && 274 !(test->t_flags & T_F_STOP)) { 275 test_error(u, 276 "Stop-on-error: Test %d (%s) completed with error\n", 277 test->t_test, test->t_name); 278 } 279 } else { 280 last_test_status[u] = 0; 281 test->t_success++; 282 LOG_INFO(BSL_LS_APPL_TESTS, 283 (BSL_META_U(u, 284 "Test %d (%s) Completed successfully\n"), 285 test->t_test, test->t_name)); 286 } 287 } 288 289 void 290 test_exit(int u, int status) 291 /* 292 * Function: test_exit 293 * Purpose: To exit the currently running test. 294 * Parameters: status - the exit status, 0 for success, -1 for failure. 295 * Returns: Does not return 296 */ 297 { 298 test_done(u, test_active, status); 299 #ifndef NO_CTRL_C 300 longjmp(test_active_jmp, 1); 301 #endif 302 } 303 304 int 305 test_test_init(int u, test_t *test, args_t *a, void **fp) 306 /* 307 * Function: test_test_init 308 * Purpose: Run initialization scripts and routines for a specified test. 309 * Parameters: u - unit # 310 * test - pointer to test description. 311 * a - pointer to arguments. 312 * fp - cookie passed back to test routine. 313 * Returns: 0 - success 314 * -1 - failed. 315 */ 316 { 317 int rv = 0; 318 319 *fp = NULL; 320 if (sh_set_rctest && (test->t_flags & T_F_RC)) { 321 var_set_integer("testinit", test->t_test, 0, 0); 322 #if defined(BCM_ESW_SUPPORT) 323 #ifndef NO_SAL_APPL 324 if (SOC_IS_XGS(u)) { 325 if (diag_rc_load(u) != CMD_OK) { 326 cli_out("Test: ERROR: RC init script for test %d (%s) failed\n", 327 test->t_test, test->t_name); 328 rv = -1; 329 } 330 } 331 #endif 332 #endif 333 var_unset("testinit", 0, 1, 0); 334 if (rv) { 335 return(rv); 336 } 337 } 338 if (test->t_init_f) { /* Call init function */ 339 rv = test->t_init_f(u, a, fp); 340 /* check if return value is != BCM_E_UNAVAIL because the memory test on the internal 341 * memories will return BCM_E_UNAVAIL if External TCAM is present. Those memories shouldn't 342 * be tested instead should be skipped. */ 343 if (rv && (rv != BCM_E_UNAVAIL)) { 344 cli_out("Test: ERROR: Init function for test %d (%s) failed\n", 345 test->t_test, test->t_name); 346 rv = -1; 347 } 348 } 349 return(rv); 350 } 351 352 /* 353 * Function: test_test_done 354 * Purpose: Run done scripts and routines for a specified test. 355 * Parameters: u - unit # 356 * test - pointer to test description. 357 * fp - value returned from init function. 358 * Returns: 0 - success 359 * -1 - failed. 360 */ 361 int 362 test_test_done(int u, test_t *test, void *fp) 363 { 364 int rv = 0; 365 366 if (test->t_done_f) { /* Call done function */ 367 if (test->t_done_f(u, fp)) { 368 cli_out("Test: ERROR: Done function for test %d (%s) failed\n", 369 test->t_test, test->t_name); 370 rv = -1; 371 } 372 } 373 test->t_flags &= ~(T_F_ACTIVE|T_F_STOP|T_F_ERROR); 374 test_active = NULL; 375 test_thread = NULL; 376 if (test_options & TEST_O_RUN) { 377 cli_out("Test %d (%s) Completed\n", test->t_test, test->t_name); 378 } 379 380 return(rv); 381 } 382 383 int 384 test_dispatch(int u, test_t *test, int loops, args_t *a) 385 /* 386 * Function: test_dispatch 387 * Purpose: Run a selected test. 388 * Parameters: test - Pointer to test entry to run. 389 * loops - # of iterations, if -1 count taken from test default. 390 * a - arguments to pass to test. 391 * Returns: TEST_XXX 392 */ 393 { 394 jmp_buf jmp; /* ^C out of tests must be trapped */ 395 int i; /* Loop counter */ 396 int error; /* No error */ 397 int arg_saved; 398 volatile int vloops = loops; /* "loops"/setjmp clobber war */ 399 args_t * volatile av = a; 400 args_t * volatile args = 0; 401 void * volatile fp; /* Test function pointer parameter */ 402 volatile int cleanup = FALSE; 403 int rv; 404 /* Check if test supported */ 405 406 if (!(test->t_flags & _test_chip(u))) { 407 if (test_options & TEST_O_OVERRIDE) { 408 cli_out("Warning: Running test %d (%s) not supported on %s\n", 409 test->t_test, test->t_name, SOC_UNIT_GROUP(u)); 410 } 411 } 412 413 if (test_options & TEST_O_RUN) { 414 cli_out("Test %d (%s) Started\n", test->t_test, test->t_name); 415 } 416 417 COMPILER_REFERENCE(cleanup); 418 error = TEST_RUNNING; 419 420 #ifndef NO_CTRL_C 421 if (TEST_RUNNING != (error = setjmp(jmp))) { /* Control C handler */ 422 if (test_active) { 423 if (cleanup) { 424 cli_out("Warning: Cleanup aborted - " 425 "continue at your own risk\n"); 426 } else { 427 cleanup = TRUE; 428 cli_out("Warning: cleaning up active test: %s\n", 429 test_active->t_name); 430 test->t_flags |= T_F_STOP; /* Say processed stop */ 431 test_done(u, test_active, error); 432 test_test_done(u, test_active, fp); 433 if (args) { 434 sal_free(args); 435 } 436 } 437 sh_pop_ctrl_c(); 438 test_thread = NULL; 439 test_active = NULL; 440 return(TEST_INTR); 441 } 442 } 443 #endif 444 445 sh_push_ctrl_c(&jmp); 446 test_thread = sal_thread_self(); 447 448 /* If no arguments passed in, use default args */ 449 450 error = TEST_ABORT; 451 if (!av) { 452 if ((av = args = sal_alloc(sizeof(args_t), "test_args")) == NULL) { 453 goto return_no_free; 454 } 455 456 if (diag_parse_args(test->t_override_string ? 457 test->t_override_string : test->t_default_string, 458 NULL, 459 av)) { 460 test->t_fail++; 461 last_test_status[u] = -1; 462 goto return_with_free; 463 } 464 } 465 fp = NULL; 466 467 if (-1 == vloops) { /* Assign AFTER setjmp */ 468 vloops = test->t_loops; /* Use default */ 469 } 470 471 test_active = test; 472 test->t_flags |= T_F_ACTIVE; 473 arg_saved = av->a_arg; /* Some may be consumed */ 474 475 rv = test_test_init(u, test, av, (void **)&fp); 476 /* check if return value is != BCM_E_UNAVAIL because the memory test on the internal 477 * memories will return BCM_E_UNAVAIL if External TCAM is present. Those memories shouldn't 478 * be tested instead should be skipped. */ 479 if ((rv != BCM_E_UNAVAIL) && (rv)){ 480 test->t_runs++; /* Increment RUN/FAIL count */ 481 test->t_fail++; 482 last_test_status[u] = -1; 483 test->t_flags &= ~T_F_ACTIVE; 484 test_active = NULL; 485 test_thread = NULL; 486 goto return_with_free; 487 } 488 489 #ifndef NO_CTRL_C 490 if (TEST_RUNNING != (error = setjmp(test_active_jmp))) { 491 if (cleanup) { 492 cli_out("Warning: Cleanup aborted - " 493 "continue at your own risk\n"); 494 } else { 495 cleanup = TRUE; 496 test_done(u, test, error); 497 } 498 } else { 499 #endif 500 /* If progress reporting requested, set it up ... */ 501 if (test_options & TEST_O_PROGRESS) { 502 progress_init(vloops, 0, FALSE); 503 progress_status(test->t_name); 504 } 505 for (i = 0; i < vloops; i++) { 506 if (vloops > 1) { 507 LOG_VERBOSE(BSL_LS_APPL_TESTS, 508 (BSL_META_U(u, 509 "Test %d: %s. Starting interation %d.\n"), 510 test->t_test, test->t_name, i+1)); 511 } 512 test->t_runs++; /* Let-em know we ran */ 513 av->a_arg = arg_saved; /* Reset ARG pointer */ 514 test->t_flags &= ~(T_F_STOP|T_F_ERROR); 515 /* Skip if rv is BCM_E_UNAVAIL as we mentioned above */ 516 if (rv != BCM_E_UNAVAIL) { 517 error = test->t_test_f(u, av, fp);/* Run Test */ 518 } else { 519 error = 0; 520 } 521 if (error == 0 && test->t_flags & T_F_ERROR) { 522 /* Some tests call test_error but fail to return error */ 523 error = -1; 524 } 525 test_done(u, test, error); 526 if (test_options & TEST_O_PROGRESS) { 527 progress_report(1); 528 } 529 } 530 if (test_options & TEST_O_PROGRESS) { 531 progress_done(); 532 } 533 #ifndef NO_CTRL_C 534 } 535 #endif 536 537 /* Skip if rv is BCM_E_UNAVAIL as we mentioned above */ 538 if (rv != BCM_E_UNAVAIL) { 539 (void)test_test_done(u, test, fp); /* Run done routines/scripts */ 540 } else { 541 /* If Return Value is BCM_E_UNAVAIL it is assumed that the internal 542 * memories are being tested for External TCAm devices and the test has 543 * not supported these memories. Even though the test is not executed 544 * increasing the test success count in order to show up in the final test 545 * results as not failed. 546 */ 547 test_active = NULL; 548 test_thread = NULL; 549 test->t_success++; 550 } 551 return_with_free: 552 if (args != NULL) { 553 sh_block_ctrl_c(TRUE); 554 sal_free(args); 555 args = 0; 556 sh_block_ctrl_c(FALSE); 557 } 558 559 return_no_free: 560 sh_pop_ctrl_c(); 561 562 if (test_options & TEST_O_RUN) { 563 cli_out("Completed test (%d) %s\n", test->t_test, test->t_name); 564 } 565 566 if (a != NULL) 567 ARG_DISCARD(a); 568 569 return(error); 570 } 571 572 void 573 test_msg(const char *fmt, ...) 574 /* 575 * Function: test_msg 576 * Purpose: Print an informational message from a test. 577 * Parameters: Printf style string. 578 * Returns: Nothing 579 */ 580 { 581 va_list varg; 582 583 va_start(varg, fmt); 584 585 if (!(test_options & TEST_O_QUIET)) { 586 (void)bsl_vprintf(fmt, varg); 587 } 588 589 va_end(varg); 590 } 591 592 void 593 test_error(int u, const char *fmt, ...) 594 /* 595 * Function: test_error 596 * Purpose: Print an Error Message for test failure, stopping if 597 * Stop-on-Error is requested. 598 * Parameters: Printf style string. 599 * Returns: Nothing 600 */ 601 { 602 char pfx[64]; 603 va_list varg; 604 int o_spl; 605 606 va_start(varg, fmt); 607 608 if (sal_thread_self() != test_thread) { 609 /* 610 * If this is not the test thread itself, then longjump 611 * will not work - so only option is to continue. 612 */ 613 cli_out("\n" 614 "****************************************\n" 615 "TEST ERROR: Warning: Not in test thread, " 616 "continuing ...\n"); 617 (void)bsl_vprintf(fmt, varg); 618 cli_out("****************************************\n"); 619 va_end(varg); 620 621 return; 622 } 623 624 o_spl = sal_splhi(); 625 test_active->t_flags |= T_F_ERROR; /* Indicate error seen */ 626 sal_spl(o_spl); 627 628 if (!(test_options & TEST_O_SILENT)) { 629 cli_out("\n" 630 "****************************************\n" 631 "TEST ERROR %s:\n", test_active->t_name); 632 (void)bsl_vprintf(fmt, varg); 633 cli_out("****************************************\n"); 634 } 635 636 if (test_options & TEST_O_SOE) { /* Stop on error? */ 637 o_spl = sal_splhi(); 638 test_active->t_flags |= T_F_STOP; /* Indicate stopped once */ 639 sal_spl(o_spl); 640 while (1) { 641 char *c, b[64]; 642 int bl; 643 cli_out("\n\n *** Stop-on-Error *** \n" 644 "\t\"bcm\" to enter recursive BCM shell\n" 645 "\t\"continue\" to continue running current test\n\n" 646 "\t\"stop\" to stop all tests\n" 647 "\t\"abort\" to abort current test and start next test\n"); 648 c = sal_readline("Stop-on-Error action? ", b, sizeof(b), "bcm"); 649 if (c) { 650 b[sizeof(b) - 1] = '\0'; /* Be sure null terminated */ 651 bl = strlen(c); 652 if (!sal_strncasecmp("bcm", b, bl)) { 653 cli_out("\nType \"exit\" to return from sh\n\n"); 654 sal_sprintf(pfx, "FAILED(%s)", test_active->t_name); 655 (void)sh_process(u, pfx, TRUE); 656 } else if (!sal_strncasecmp("stop", b, bl)) { 657 #ifndef NO_CTRL_C 658 longjmp(test_active_jmp, TEST_STOP); 659 #endif 660 } else if (!sal_strncasecmp("abort", b, bl)) { 661 #ifndef NO_CTRL_C 662 longjmp(test_active_jmp, TEST_ABORT); 663 #endif 664 } else if (!sal_strncasecmp("continue", b, bl)) { 665 va_end(varg); 666 return; 667 } 668 } 669 } 670 } else if (test_options & TEST_O_AOE) { /* Abort on error */ 671 cli_out("\nAborting test\n"); 672 #ifndef NO_CTRL_C 673 longjmp(test_active_jmp, TEST_ABORT); 674 #endif 675 } 676 677 va_end(varg); 678 return; /* Continue */ 679 } 680 681 void 682 test_print_header(int status_report) 683 /* 684 * Function: test_print_header 685 * Purpose: Print header string for output. 686 * Parameters: None. 687 * Returns: Nothing 688 */ 689 { 690 if (status_report) { 691 cli_out("-----+----+--- TEST STATUS REPORT ----+" 692 "-----+-----+-----+-----+-----------\n"); 693 } 694 695 cli_out("U/A/S|Test| Test |Loop | Run |Pass |Fail |" 696 " Arguments\n"); 697 cli_out(" | # | Name |Count|Count|Count|Count|" 698 "\n"); 699 } 700 701 void 702 test_print_separator(void) 703 /* 704 * Function: test_print_header 705 * Purpose: Print header string for output. 706 * Parameters: None. 707 * Returns: Nothing 708 */ 709 { 710 cli_out("-----+----+---------------------------+-----+-----+-----+-----+" 711 "-----------\n"); 712 } 713 714 void 715 test_print_summary(int loops, int runs, int successes, int failures) 716 /* 717 * Function: test_print_summary 718 * Purpose: Print summary values 719 * Parameters: Summary values 720 * Returns: Nothing 721 */ 722 { 723 cli_out(" | | %-26s|%5d|%5d|%5d|%5d|\n", 724 "TOTAL", loops, runs, successes, failures); 725 } 726 727 void 728 test_print_entry(int unit, test_t *test) 729 /* 730 * Function: test_print_entry 731 * Purpose: Print a single test entry in a pretty formatted way. 732 * Parameters: unit - Strata Switch unit # 733 * test - pointer to test list entry to print 734 * Returns: Nothing 735 */ 736 { 737 int selected; 738 uint32 chip = _test_chip(unit); 739 740 selected = (test->t_flags & T_F_SEL_ALL) || 741 ((test->t_flags & T_F_SEL_CHIP) && (test->t_flags & chip)); 742 cli_out(" %c%c%c |%4d| %-26s|%5d|%5d|%5d|%5d| %s\n", 743 test->t_flags & _test_chip(unit) ? ' ' : 'U', 744 test->t_flags & T_F_ACTIVE ? 'A' : ' ', 745 selected ? 'S' : ' ', 746 test->t_test, test->t_name, test->t_loops, test->t_runs, 747 test->t_success, test->t_fail, 748 test->t_override_string ? 749 test->t_override_string : 750 test->t_default_string ? test->t_default_string : "(none)"); 751 } 752 753 cmd_result_t 754 test_print_list(int u, args_t *a) 755 /* 756 * Function: test_print_list 757 * Purpose: Print some/all of the tests and status. 758 * Parameters: u - unit # 759 * "*" for all tests 760 * List of tests 761 * Nothing for all (same as *) 762 * Returns: CMD_OK - success 763 * CMD_FAIL - failed to find test or if a test failed. 764 */ 765 { 766 test_t *test; 767 char *s; 768 int header = FALSE; 769 int i, supported, all, fail; 770 cmd_result_t result = CMD_OK; 771 uint32 chip = _test_chip(u); 772 int num_fail = 0; 773 774 test_t *test_list; 775 int test_cnt; 776 test_list = get_test_list(u, &test_cnt); 777 778 COMPILER_REFERENCE(u); 779 780 /* Check for print all */ 781 782 if (ARG_CNT(a) > 0) { 783 supported = (0 == strcmp(_ARG_CUR(a), "*")); 784 all = (0 == sal_strcasecmp(_ARG_CUR(a), "all")); 785 fail = (0 == sal_strcasecmp(_ARG_CUR(a), "fail")); 786 if (supported || all || fail) { /* Consume Argument */ 787 ARG_NEXT(a); 788 } 789 } else if (ARG_CNT(a) == 0) { 790 supported = TRUE; 791 all = FALSE; 792 fail = FALSE; 793 } else { 794 supported = FALSE; 795 all = FALSE; 796 fail = FALSE; 797 } 798 799 /* If "all" or supported, consume argument and list tests */ 800 801 if (fail) { 802 for (i = 0; i < test_cnt; i++) { 803 if (test_list[i].t_fail) { 804 cli_out("%d ", test_list[i].t_test); 805 num_fail++; 806 } 807 } 808 if (num_fail == 0) { 809 cli_out("All tests passed"); 810 } 811 cli_out("\n"); 812 return(result); 813 } 814 815 if (all || supported) { 816 int t_loops = 0, t_runs = 0, t_success = 0, t_fail = 0; 817 if (chip == 0) { /* No chip - print all */ 818 all = TRUE; 819 } 820 test_print_header(TRUE); 821 test_print_separator(); 822 for (i = 0; i < test_cnt; i++) { 823 if (all || 824 (supported && (chip & test_list[i].t_flags)) 825 || (test_list[i].t_flags & T_F_SEL_ALL)) { 826 test_print_entry(u, &test_list[i]); 827 t_loops += test_list[i].t_loops; 828 t_runs += test_list[i].t_runs; 829 t_success += test_list[i].t_success; 830 t_fail += test_list[i].t_fail; 831 } 832 } 833 test_print_summary(t_loops, t_runs, t_success, t_fail); 834 test_print_separator(); 835 836 /* 837 In order for the automated tests to automatically diagnose 838 that a test failed, we need this function to return 839 something when an individual test fails. 840 */ 841 if (t_runs == 0) { 842 /* 843 * We want return CMD_FAIL if no tests were run 844 */ 845 result = CMD_FAIL; 846 } else if (t_fail > 0) { 847 /* 848 * We also want to return CMD_FAIL if any tests failed. 849 */ 850 result = CMD_FAIL; 851 } 852 return(result); 853 } 854 855 while ((s = ARG_GET(a)) != NULL) { 856 test = test_find(s, test_list, test_cnt); 857 if (!test) { 858 cli_out("%s: Unable to locate test: %s\n", ARG_CMD(a), s); 859 result = CMD_FAIL; 860 continue; 861 } 862 if (!header) { 863 test_print_header(FALSE); 864 test_print_separator(); 865 header = TRUE; 866 } 867 test_print_entry(u, test); 868 } 869 return(result); 870 } 871 872 /* 873 * Function: test_run_selected 874 * Purpose: Run selected tests. 875 * Parameters: u - unit number to run tests on. 876 * Returns: Nothing. 877 */ 878 static int 879 test_run_selected(int u, test_t *test_list, int test_cnt) 880 { 881 int i; 882 883 if (test_options & TEST_O_RANDOM) { 884 cli_out("Test: Random mode not supported yet\n"); 885 return(TEST_STOP); 886 } 887 888 for (i = 0; i < test_cnt; i++) { 889 if ((test_list[i].t_flags & T_F_SEL_ALL) || 890 ((test_list[i].t_flags & T_F_SEL_CHIP) && 891 (test_list[i].t_flags & _test_chip(u)))) 892 { 893 int rv; 894 switch((rv = test_dispatch(u, &test_list[i], -1, NULL))) { 895 case TEST_STOP: 896 case TEST_INTR: 897 return(rv); 898 } 899 } 900 } 901 return(TEST_RUNNING); 902 } 903 904 char test_run_usage[] = 905 "Parameters: [Test ID] [arguments]\n\t" 906 " With no parameters runs all selected tests with the set\n\t" 907 " loop counts and set parameters. Otherwise, runs a specific\n\t" 908 " test with the specified loop count and arguments. You may\n\t" 909 " want to use \"set RCTest=true\" so that some tests (like\n\t" 910 " loopback) will properly initialize using rc.soc).\n"; 911 912 cmd_result_t 913 test_run(int u, args_t *a) 914 /* 915 * Function: test_run 916 * Purpose: Perform "run" command for test. 917 * Parameters: none - Run all selected tests with loaded parameters. 918 * "test [options]" 919 * Returns: Test result. 920 */ 921 { 922 test_t *test; 923 int rv; 924 int loops = -1; 925 926 test_t *test_list; 927 int test_cnt; 928 test_list = get_test_list(u, &test_cnt); 929 930 if (test_active && !SOC_IS_SAND(u)) { 931 cli_out("%s: Already running: %s\n", ARG_CMD(a), test_active->t_name); 932 return(CMD_FAIL); 933 } else if (!sh_check_attached(ARG_CMD(a), u)) { 934 return(CMD_FAIL); 935 } 936 937 if (!ARG_CNT(a)) { 938 rv = test_run_selected(u, test_list, test_cnt); 939 } else { 940 if (NULL == (test = test_find(ARG_CUR(a), test_list, test_cnt))) { 941 cli_out("%s: Unknown test: %s\n", ARG_CMD(a), ARG_CUR(a)); 942 return(CMD_FAIL); 943 } 944 945 if (!(test->t_flags & _test_chip(u)) && 946 !(test_options & TEST_O_OVERRIDE)) { 947 cli_out("Error: Test %d (%s) not supported on %s\n" 948 "Error: use \"testmode +override\" to override and run\n", 949 test->t_test, test->t_name, SOC_UNIT_GROUP(u)); 950 return(CMD_FAIL); 951 } 952 ARG_NEXT(a); /* Move arg pointer */ 953 /* If there is an argument which is an integer, it's a loop count */ 954 if (ARG_CUR(a) && isint(ARG_CUR(a))) { 955 loops = strtoul(_ARG_GET(a), NULL, 10); 956 } 957 rv = test_dispatch(u, test, loops, ARG_CNT(a) ? a : NULL); 958 } 959 return(rv == TEST_INTR ? CMD_INTR : rv); 960 } 961 962 STATIC int 963 _test_select(int u, test_t *t, int only_if_available) 964 { 965 uint32 chip = _test_chip(u); 966 967 if (only_if_available) { /* Only select available tests */ 968 if (t->t_flags & chip) { 969 t->t_flags |= T_F_SEL_CHIP; 970 } 971 } else { 972 if (!(t->t_flags & chip)) { 973 if (test_options & TEST_O_OVERRIDE) { 974 cli_out("Warning: Selecting test %d (%s) " 975 "not supported on %s\n", 976 t->t_test, t->t_name, SOC_UNIT_GROUP(u)); 977 } else { 978 cli_out("Error: Test %d (%s) not supported on %s\n" 979 "use \"testmode +override\" to override and run\n", 980 t->t_test, t->t_name, SOC_UNIT_GROUP(u)); 981 return(CMD_FAIL); 982 } 983 } 984 t->t_flags |= T_F_SEL_ALL; 985 } 986 return(CMD_OK); 987 } 988 989 STATIC void 990 _test_unselect(int u, test_t *t) 991 { 992 uint32 chip = _test_chip(u); 993 994 t->t_flags &= ~T_F_SEL_ALL; 995 if (t->t_flags & chip) { 996 t->t_flags &= ~T_F_SEL_CHIP; 997 } 998 } 999 1000 STATIC int 1001 _test_select_check(int u, test_t *t) 1002 { 1003 uint32 chip = _test_chip(u); 1004 1005 return((t->t_flags & T_F_SEL_ALL) || 1006 ((t->t_flags & T_F_SEL_CHIP) && (t->t_flags & chip))); 1007 } 1008 1009 char test_select_usage[] = 1010 "Parameters: [+|-][Test ID] ... - Select specified tests\n\t" 1011 " If + specified before a test it is added to the\n\t" 1012 " run list. If - is specified it is removed from\n\t" 1013 " the run list. If neither + or - is specified then\n\t" 1014 " the current select status for a test is inverted\n\t" 1015 TEST_ID_USAGE; 1016 1017 cmd_result_t 1018 test_select(int u, args_t *a) 1019 /* 1020 * Function: test_select 1021 * Purpose: Select a set of tests, prefix with + to add, - to remove. 1022 * Parameters: u - unit # 1023 * a - list of tests to select, deselect (* means all) 1024 * Returns: 0 - success, -1 failed. 1025 */ 1026 { 1027 enum {ADD, DEL, XOR} option; 1028 int silent; 1029 cmd_result_t error = CMD_OK; 1030 char *s; 1031 test_t *ts, *te; /* Test start/end pointers */ 1032 1033 test_t *test_list; 1034 int test_cnt; 1035 test_list = get_test_list(u, &test_cnt); 1036 1037 COMPILER_REFERENCE(u); 1038 1039 while ((s = ARG_GET(a)) != NULL) { 1040 if ('+' == *s) { 1041 option = ADD; 1042 s++; 1043 } else if ('-' == *s) { 1044 option = DEL; 1045 s++; 1046 } else { 1047 option = XOR; 1048 } 1049 1050 if (!strcmp("*", s)) { /* Do it to all of the tests */ 1051 ts = &test_list[0]; 1052 te = &test_list[test_cnt-1]; 1053 silent = TRUE; 1054 } else { 1055 silent = FALSE; 1056 ts = te = test_find(s, test_list, test_cnt); 1057 if (!ts) { 1058 cli_out("%s: Unable to locate test: %s\n", ARG_CMD(a), s); 1059 return(CMD_FAIL); 1060 } 1061 1062 } 1063 while (ts <= te) { 1064 switch(option) { 1065 case ADD: 1066 error = _test_select(u, ts, silent); 1067 break; 1068 case DEL: 1069 _test_unselect(u, ts); 1070 break; 1071 case XOR: 1072 if (_test_select_check(u, ts)) { 1073 _test_unselect(u, ts); 1074 } else { 1075 error = _test_select(u, ts, silent); 1076 } 1077 break; 1078 } 1079 ts++; 1080 } 1081 } 1082 return(error); 1083 } 1084 1085 char test_mode_usage[] = 1086 "Parameters: [+/-][StopOnError|Random|Progress|SIlent|Run|Override] ... \n" 1087 #ifndef COMPILER_STRING_CONST_LIMIT 1088 "\t - StopOnError requests a diagnostic shell be invoked when\n\t" 1089 " a test fails. This allows the user to inspect SOC state\n\t" 1090 " using the diagshell.\n\t" 1091 " - Abortonerror requests a test be aborted on failure, and \n\t" 1092 " execution continues with next test.\n\t" 1093 " - Random requests tests be run in pseudo random order\n\t" 1094 " - Progress requests a simple progress report be displayed\n\t" 1095 " as tests are run\n\t" 1096 " - Silent requests test error messages not be printed, but\n\t" 1097 " errors are counted\n\t" 1098 " - Run requests a message is printed when a test is dispatched\n\t" 1099 " Prefixing the flag with + turns on the option, - turns\n\t" 1100 " off the option, no +/- toggles the current option\n\t" 1101 " - Override allows tests not supported on the specified chip to\n\t" 1102 " be selected and run. WARNING: these is a high probablility the\n\t" 1103 " system will crash when running unsupported chips\n" 1104 #endif 1105 ; 1106 1107 cmd_result_t 1108 test_mode(int u, args_t *a) 1109 /* 1110 * Function: test_mode 1111 * Purpose: Set test test mode 1112 * Parameters: [+/-] "soe" or "stoponerror" 1113 * Returns: 0 - success, 1114 * -1 - failed. 1115 */ 1116 { 1117 static parse_pm_t options[] = { 1118 {"@SOE", TEST_O_SOE}, 1119 {"@AOE", TEST_O_AOE}, 1120 {"Stoponerror", TEST_O_SOE}, 1121 {"Abortonerror",TEST_O_AOE}, 1122 {"Quiet", TEST_O_QUIET}, 1123 {"Progress", TEST_O_PROGRESS}, 1124 {"RANDom", TEST_O_RANDOM}, 1125 {"SIlent", TEST_O_SILENT}, 1126 {"Run", TEST_O_RUN}, 1127 {"Override", TEST_O_OVERRIDE}, 1128 {"NoReinit", TEST_O_NO_REINIT}, 1129 {NULL, 0} 1130 }; 1131 char *c; 1132 1133 COMPILER_REFERENCE(u); 1134 1135 if (0 == ARG_CNT(a)) { 1136 cli_out("Test: Options: "); 1137 parse_mask_format(80, options, test_options); 1138 cli_out("\n"); 1139 return(CMD_OK); 1140 } 1141 1142 while ((c = ARG_GET(a)) != NULL) { 1143 if (parse_mask(c, options, &test_options)) { 1144 cli_out("%s: Error: invalid option ignored: %s\n", ARG_CMD(a), c); 1145 } 1146 } 1147 return(CMD_OK); 1148 } 1149 1150 char test_parameters_usage[] = 1151 "Parameters: [Test Name | Test #] [\"Parameter String\"] ...\n\t" 1152 " Override the default parameters for the test specified\n\t" 1153 " by [Test ID]. Multiple tests may be listed and the parameter\n\t" 1154 " string must be quoted if more that 1 argument is specified (\").\n\t" 1155 " To clear a previously set parameter list, pass a NULL string\n\t" 1156 " as an argument (\"\").\n"; 1157 1158 cmd_result_t 1159 test_parameters(int u, args_t *a) 1160 /* 1161 * Function: test_parameters 1162 * Purpose: Set the parameters for the specified tests. 1163 * Parameters: u - unit number 1164 * a - arguments, expects tuples of the form: 1165 * [Test name/#] Arguments. 1166 * if arguments is null string ("") then previously 1167 * set arguments are discarded and defaults used. 1168 * Returns: cmd_result_t. 1169 */ 1170 { 1171 char *tid, *p; /* Testid, parameters */ 1172 test_t *t; /* Test pointer */ 1173 1174 test_t *test_list; 1175 int test_cnt; 1176 test_list = get_test_list(u, &test_cnt); 1177 1178 COMPILER_REFERENCE(u); 1179 1180 if (0 == ARG_CNT(a)) { 1181 return(CMD_USAGE); 1182 } 1183 1184 while (NULL != (tid = ARG_GET(a))) { 1185 p = ARG_GET(a); /* Parameter */ 1186 t = test_find(tid, test_list, test_cnt); 1187 if (NULL == t) { 1188 cli_out("%s: Error: Unable to find test: %s\n", ARG_CMD(a), tid); 1189 return(CMD_FAIL); 1190 } 1191 if (!p || !*p) { /* Clear parameter */ 1192 if (!t->t_override_string) { 1193 cli_out("%s: Warning: No arguments to clear for test: %s\n", 1194 ARG_CMD(a), t->t_name); 1195 continue; 1196 } 1197 sal_free(t->t_override_string); 1198 t->t_override_string = NULL; 1199 } else { /* Set Arguments */ 1200 if (t->t_override_string) { 1201 sal_free(t->t_override_string); 1202 } 1203 if (!(t->t_override_string = 1204 (char *)sal_alloc(strlen(p) + 1, "test_parm"))) { 1205 cli_out("%s: Error: Out of memory\n", ARG_CMD(a)); 1206 return(CMD_FAIL); 1207 } 1208 sal_strncpy(t->t_override_string, p, sal_strlen(p) + 1); 1209 cli_out("%s: Parameter set: %s(\"%s\")\n", ARG_CMD(a), t->t_name, 1210 t->t_override_string); 1211 } 1212 } 1213 return(CMD_OK); 1214 } 1215 1216 char test_clear_usage[] = 1217 "Parameters: [Test Name | Test #]\n\t" 1218 "Clear the run, success, and failure statistics for the test\n\t" 1219 "specified by [Test ID]. Multiple tests may be listed, and \"*\"\n\t" 1220 "may be used to represent all tests.\n"; 1221 1222 cmd_result_t 1223 test_clear(int u, args_t *a) 1224 /* 1225 * Function: test_clear 1226 * Purpose: Clear previous test results for a test. 1227 * Parameters: u - unit number 1228 * a - arguments, expects testname/#. 1229 * Returns: cmd_result_t 1230 */ 1231 { 1232 char *tid; 1233 test_t *t; 1234 1235 test_t *test_list; 1236 int test_cnt; 1237 test_list = get_test_list(u, &test_cnt); 1238 1239 COMPILER_REFERENCE(u); 1240 1241 if (0 == ARG_CNT(a)) { 1242 return(CMD_USAGE); 1243 } 1244 1245 while (NULL != (tid = ARG_GET(a))) { 1246 if (!strcmp(tid, "*")) { /* Clear all tests */ 1247 for (t = test_list; t < &test_list[test_cnt]; t++) { 1248 t->t_runs = 0; 1249 t->t_success = 0; 1250 t->t_fail = 0; 1251 } 1252 } else { /* Clear specific test */ 1253 t = test_find(tid, test_list, test_cnt); 1254 if (NULL == t) { 1255 cli_out("%s: Error: Unable to find test: %s\n", 1256 ARG_CMD(a), tid); 1257 return(CMD_FAIL); 1258 } 1259 t->t_runs = 0; 1260 t->t_success = 0; 1261 t->t_fail = 0; 1262 } 1263 } 1264 return(CMD_OK); 1265 } 1266 1267 #endif /* INCLUDE_TEST */ 1268 1269 int _diag_test_not_empty;