openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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;