LCOV - code coverage report
Current view: top level - lib/ut - ut.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 37 131 28.2 %
Date: 2024-12-13 10:52:24 Functions: 3 5 60.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2023 Intel Corporation. All rights reserved.
       3             :  */
       4             : 
       5             : #include "spdk/stdinc.h"
       6             : #include "spdk/util.h"
       7             : #include "spdk_internal/cunit.h"
       8             : 
       9             : enum ut_action {
      10             :         UT_ACTION_RUN_TESTS,
      11             :         UT_ACTION_PRINT_HELP,
      12             :         UT_ACTION_LIST_TESTS,
      13             : };
      14             : 
      15             : struct ut_config {
      16             :         const char                      *app;
      17             :         const char                      *test;
      18             :         const char                      *suite;
      19             :         enum ut_action                  action;
      20             :         const struct spdk_ut_opts       *opts;
      21             : };
      22             : 
      23             : #define OPTION_STRING "hls:t:"
      24             : 
      25             : static const struct option g_ut_options[] = {
      26             : #define OPTION_TEST_CASE 't'
      27             :         {"test", required_argument, NULL, OPTION_TEST_CASE},
      28             : #define OPTION_TEST_SUITE 's'
      29             :         {"suite", required_argument, NULL, OPTION_TEST_SUITE},
      30             : #define OPTION_LIST 'l'
      31             :         {"list", no_argument, NULL, OPTION_LIST},
      32             : #define OPTION_HELP 'h'
      33             :         {"help", no_argument, NULL, OPTION_HELP},
      34             :         {},
      35             : };
      36             : 
      37             : static void
      38           0 : usage(struct ut_config *config)
      39             : {
      40           0 :         const struct spdk_ut_opts *opts = config->opts;
      41             : 
      42           0 :         printf("Usage: %s [OPTIONS]\n", config->app);
      43           0 :         printf("  -t, --test                       run single test case\n");
      44           0 :         printf("  -s, --suite                      run all tests in a given suite\n");
      45           0 :         printf("  -l, --list                       list registered test suites and test cases\n");
      46           0 :         printf("  -h, --help                       print this help\n");
      47             : 
      48           0 :         if (opts != NULL && opts->usage_cb_fn != NULL) {
      49           0 :                 opts->usage_cb_fn(opts->cb_arg);
      50           0 :         }
      51           0 : }
      52             : 
      53             : static int
      54         109 : parse_args(int argc, char **argv, struct ut_config *config)
      55             : {
      56         109 :         const struct spdk_ut_opts *opts = config->opts;
      57             : #define MAX_OPTSTRING_LEN 4096
      58         109 :         char optstring[MAX_OPTSTRING_LEN] = {};
      59             : #define MAX_OPT_COUNT 128
      60         109 :         struct option options[MAX_OPT_COUNT] = {};
      61         109 :         size_t optlen;
      62         109 :         int op, rc;
      63             : 
      64             :         /* Run the tests by default */
      65         109 :         config->action = UT_ACTION_RUN_TESTS;
      66         109 :         config->app = argv[0];
      67             : 
      68         109 :         if (opts != NULL && opts->opts != NULL) {
      69           0 :                 optlen = SPDK_COUNTOF(g_ut_options) + opts->optlen;
      70           0 :                 if (optlen > MAX_OPT_COUNT) {
      71           0 :                         fprintf(stderr, "%s: unsupported number of options: %zu\n",
      72           0 :                                 config->app, optlen);
      73           0 :                         return -EINVAL;
      74             :                 }
      75             : 
      76           0 :                 memcpy(&options[0], opts->opts, sizeof(*opts->opts) * opts->optlen);
      77           0 :                 memcpy(&options[opts->optlen], g_ut_options, sizeof(g_ut_options));
      78             : 
      79           0 :                 rc = snprintf(optstring, MAX_OPTSTRING_LEN, "%s%s", OPTION_STRING,
      80           0 :                               opts->optstring);
      81           0 :                 if (rc < 0 || rc >= MAX_OPTSTRING_LEN) {
      82           0 :                         fprintf(stderr, "%s: bad optstring\n", config->app);
      83           0 :                         return -EINVAL;
      84             :                 }
      85           0 :         } else {
      86         109 :                 snprintf(optstring, sizeof(optstring), "%s", OPTION_STRING);
      87         109 :                 memcpy(options, g_ut_options, sizeof(g_ut_options));
      88             :         }
      89             : 
      90         109 :         while ((op = getopt_long(argc, argv, optstring, options, NULL)) != -1) {
      91           0 :                 switch (op) {
      92             :                 case OPTION_TEST_CASE:
      93           0 :                         config->test = optarg;
      94           0 :                         break;
      95             :                 case OPTION_TEST_SUITE:
      96           0 :                         config->suite = optarg;
      97           0 :                         break;
      98             :                 case OPTION_HELP:
      99           0 :                         config->action = UT_ACTION_PRINT_HELP;
     100           0 :                         break;
     101             :                 case OPTION_LIST:
     102           0 :                         config->action = UT_ACTION_LIST_TESTS;
     103           0 :                         break;
     104             :                 case '?':
     105           0 :                         return -EINVAL;
     106             :                 default:
     107           0 :                         if (opts != NULL && opts->option_cb_fn != NULL) {
     108           0 :                                 rc = opts->option_cb_fn(op, optarg, opts->cb_arg);
     109           0 :                                 if (rc != 0) {
     110           0 :                                         return rc;
     111             :                                 }
     112           0 :                         } else {
     113           0 :                                 return -EINVAL;
     114             :                         }
     115           0 :                 }
     116             :         }
     117             : 
     118         109 :         return 0;
     119         109 : }
     120             : 
     121             : static int
     122         109 : run_tests(const struct ut_config *config)
     123             : {
     124         109 :         CU_pSuite suite = NULL;
     125         109 :         CU_pTest test = NULL;
     126             : 
     127         109 :         if (config->suite != NULL) {
     128           0 :                 suite = CU_get_suite(config->suite);
     129           0 :                 if (suite == NULL) {
     130           0 :                         fprintf(stderr, "%s: invalid test suite: '%s'\n",
     131           0 :                                 config->app, config->suite);
     132           0 :                         return 1;
     133             :                 }
     134           0 :         }
     135             : 
     136         109 :         if (config->test != NULL) {
     137           0 :                 if (suite == NULL) {
     138             :                         /* Allow users to skip test suite if there's only a single test suite
     139             :                          * registered (CUnit starts indexing from 1). */
     140           0 :                         if (CU_get_suite_at_pos(2) != NULL) {
     141           0 :                                 fprintf(stderr, "%s: there are multiple test suites registered, "
     142           0 :                                         "select one using the -s option\n", config->app);
     143           0 :                                 return 1;
     144             :                         }
     145             : 
     146           0 :                         suite = CU_get_suite_at_pos(1);
     147           0 :                         if (suite == NULL) {
     148           0 :                                 fprintf(stderr, "%s: there are no tests registered\n", config->app);
     149           0 :                                 return 1;
     150             :                         }
     151           0 :                 }
     152             : 
     153           0 :                 test = CU_get_test(suite, config->test);
     154           0 :                 if (test == NULL) {
     155           0 :                         fprintf(stderr, "%s: invalid test case: '%s'\n", config->app, config->test);
     156           0 :                         return 1;
     157             :                 }
     158           0 :         }
     159             : 
     160         109 :         CU_set_error_action(CUEA_ABORT);
     161         109 :         CU_basic_set_mode(CU_BRM_VERBOSE);
     162             : 
     163             :         /* Either run a single test, all tests in a given test suite, or all registered tests */
     164         109 :         if (test != NULL) {
     165           0 :                 CU_basic_run_test(suite, test);
     166         109 :         } else if (suite != NULL) {
     167           0 :                 CU_basic_run_suite(suite);
     168           0 :         } else {
     169         109 :                 CU_basic_run_tests();
     170             :         }
     171             : 
     172         109 :         return CU_get_number_of_failures();
     173         109 : }
     174             : 
     175             : static void
     176           0 : list_tests(void)
     177             : {
     178           0 :         CU_pSuite suite;
     179           0 :         CU_pTest test;
     180           0 :         int sid, tid;
     181             : 
     182           0 :         for (sid = 1;; ++sid) {
     183           0 :                 suite = CU_get_suite_at_pos(sid);
     184           0 :                 if (suite == NULL) {
     185           0 :                         break;
     186             :                 }
     187             : 
     188           0 :                 printf("%s:\n", suite->pName);
     189           0 :                 for (tid = 1;; ++tid) {
     190           0 :                         test = CU_get_test_at_pos(suite, tid);
     191           0 :                         if (test == NULL) {
     192           0 :                                 break;
     193             :                         }
     194             : 
     195           0 :                         printf("  %s\n", test->pName);
     196           0 :                 }
     197           0 :         }
     198           0 : }
     199             : 
     200             : int
     201         109 : spdk_ut_run_tests(int argc, char **argv, const struct spdk_ut_opts *opts)
     202             : {
     203         109 :         struct ut_config config = {.opts = opts};
     204         109 :         int rc;
     205             : 
     206         109 :         rc = parse_args(argc, argv, &config);
     207         109 :         if (rc != 0) {
     208           0 :                 usage(&config);
     209           0 :                 return 1;
     210             :         }
     211             : 
     212         109 :         switch (config.action) {
     213             :         case UT_ACTION_PRINT_HELP:
     214           0 :                 usage(&config);
     215           0 :                 break;
     216             :         case UT_ACTION_RUN_TESTS:
     217         109 :                 if (opts != NULL && opts->init_cb_fn != NULL) {
     218           0 :                         rc = opts->init_cb_fn(opts->cb_arg);
     219           0 :                         if (rc != 0) {
     220           0 :                                 usage(&config);
     221           0 :                                 return 1;
     222             :                         }
     223           0 :                 }
     224             : 
     225         109 :                 rc = run_tests(&config);
     226         109 :                 break;
     227             :         case UT_ACTION_LIST_TESTS:
     228           0 :                 list_tests();
     229           0 :                 break;
     230             :         default:
     231           0 :                 assert(0);
     232             :         }
     233             : 
     234         109 :         return rc;
     235         109 : }

Generated by: LCOV version 1.15