regex/mlx5: fix leak after probing failure
[dpdk.git] / app / test / test.c
index afabfe4..173d202 100644 (file)
@@ -36,6 +36,18 @@ extern cmdline_parse_ctx_t main_ctx[];
 
 #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
 
+#define FOR_EACH_SUITE_TESTCASE(iter, suite, case)                     \
+       for (iter = 0, case = suite->unit_test_cases[0];                \
+               suite->unit_test_cases[iter].testcase ||                \
+               suite->unit_test_cases[iter].testcase_with_data;        \
+               iter++, case = suite->unit_test_cases[iter])
+
+#define FOR_EACH_SUITE_TESTSUITE(iter, suite, sub_ts)                  \
+       for (iter = 0, sub_ts = suite->unit_test_suites ?               \
+               suite->unit_test_suites[0]:NULL; sub_ts &&              \
+               suite->unit_test_suites[iter]->suite_name != NULL;      \
+               iter++, sub_ts = suite->unit_test_suites[iter])
+
 const char *prgname; /* to be set to argv[0] */
 
 static const char *recursive_call; /* used in linux for MP and other tests */
@@ -58,10 +70,10 @@ do_recursive_call(void)
 #endif
 #endif
                        { "test_missing_c_flag", no_action },
-                       { "test_master_lcore_flag", no_action },
+                       { "test_main_lcore_flag", no_action },
                        { "test_invalid_n_flag", no_action },
                        { "test_no_hpet_flag", no_action },
-                       { "test_whitelist_flag", no_action },
+                       { "test_allow_flag", no_action },
                        { "test_invalid_b_flag", no_action },
                        { "test_invalid_vdev_flag", no_action },
                        { "test_invalid_r_flag", no_action },
@@ -93,6 +105,9 @@ main(int argc, char **argv)
 {
 #ifdef RTE_LIB_CMDLINE
        struct cmdline *cl;
+       char *tests[argc]; /* store an array of tests to run */
+       int test_count = 0;
+       int i;
 #endif
        char *extra_args;
        int ret;
@@ -134,8 +149,14 @@ main(int argc, char **argv)
                goto out;
        }
 
+       argv += ret;
+       argc -= ret;
+
+       prgname = argv[0];
+
 #ifdef RTE_LIB_TIMER
-       if (rte_timer_subsystem_init() < 0) {
+       ret = rte_timer_subsystem_init();
+       if (ret < 0 && ret != -EALREADY) {
                ret = -1;
                goto out;
        }
@@ -146,10 +167,6 @@ main(int argc, char **argv)
                goto out;
        }
 
-       argv += ret;
-
-       prgname = argv[0];
-
        recursive_call = getenv(RECURSIVE_ENV_VAR);
        if (recursive_call != NULL) {
                ret = do_recursive_call();
@@ -164,29 +181,60 @@ main(int argc, char **argv)
 
 
 #ifdef RTE_LIB_CMDLINE
-       cl = cmdline_stdin_new(main_ctx, "RTE>>");
-       if (cl == NULL) {
-               ret = -1;
-               goto out;
+       char *dpdk_test = getenv("DPDK_TEST");
+
+       if (dpdk_test && strlen(dpdk_test) == 0)
+               dpdk_test = NULL;
+
+       if (dpdk_test && !command_valid(dpdk_test)) {
+               RTE_LOG(WARNING, APP, "Invalid DPDK_TEST value '%s'\n", dpdk_test);
+               dpdk_test = NULL;
        }
 
-       char *dpdk_test = getenv("DPDK_TEST");
-       if (dpdk_test && strlen(dpdk_test)) {
+       if (dpdk_test)
+               tests[test_count++] = dpdk_test;
+       for (i = 1; i < argc; i++) {
+               if (!command_valid(argv[i]))
+                       RTE_LOG(WARNING, APP, "Invalid test requested: '%s'\n", argv[i]);
+               else
+                       tests[test_count++] = argv[i];
+       }
+
+       if (test_count > 0) {
                char buf[1024];
-               snprintf(buf, sizeof(buf), "%s\n", dpdk_test);
-               if (cmdline_in(cl, buf, strlen(buf)) < 0) {
-                       printf("error on cmdline input\n");
+
+               cl = cmdline_new(main_ctx, "RTE>>", 0, 1);
+               if (cl == NULL) {
                        ret = -1;
                        goto out;
                }
 
-               cmdline_stdin_exit(cl);
-               ret = last_test_result;
+               for (i = 0; i < test_count; i++) {
+                       snprintf(buf, sizeof(buf), "%s\n", tests[i]);
+                       if (cmdline_in(cl, buf, strlen(buf)) < 0) {
+                               printf("error on cmdline input\n");
+
+                               ret = -1;
+                       } else
+                               ret = last_test_result;
+
+                       if (ret != 0)
+                               break;
+               }
+               cmdline_free(cl);
                goto out;
+       } else {
+               /* if no DPDK_TEST env variable, go interactive */
+               cl = cmdline_stdin_new(main_ctx, "RTE>>");
+               if (cl == NULL) {
+                       ret = -1;
+                       goto out;
+               }
+
+               cmdline_interact(cl);
+               cmdline_stdin_exit(cl);
+               cmdline_free(cl);
        }
-       /* if no DPDK_TEST env variable, go interactive */
-       cmdline_interact(cl);
-       cmdline_stdin_exit(cl);
 #endif
        ret = 0;
 
@@ -198,14 +246,64 @@ out:
        return ret;
 }
 
+static void
+unit_test_suite_count_tcs_on_setup_fail(struct unit_test_suite *suite,
+               int test_success, unsigned int *sub_ts_failed,
+               unsigned int *sub_ts_skipped, unsigned int *sub_ts_total)
+{
+       struct unit_test_case tc;
+       struct unit_test_suite *ts;
+       int i;
+
+       FOR_EACH_SUITE_TESTSUITE(i, suite, ts) {
+               unit_test_suite_count_tcs_on_setup_fail(
+                       ts, test_success, sub_ts_failed,
+                       sub_ts_skipped, sub_ts_total);
+               suite->total += ts->total;
+               suite->failed += ts->failed;
+               suite->skipped += ts->skipped;
+               if (ts->failed)
+                       (*sub_ts_failed)++;
+               else
+                       (*sub_ts_skipped)++;
+               (*sub_ts_total)++;
+       }
+       FOR_EACH_SUITE_TESTCASE(i, suite, tc) {
+               suite->total++;
+               if (!tc.enabled || test_success == TEST_SKIPPED)
+                       suite->skipped++;
+               else
+                       suite->failed++;
+       }
+}
+
+static void
+unit_test_suite_reset_counts(struct unit_test_suite *suite)
+{
+       struct unit_test_suite *ts;
+       int i;
+
+       FOR_EACH_SUITE_TESTSUITE(i, suite, ts)
+               unit_test_suite_reset_counts(ts);
+       suite->total = 0;
+       suite->executed = 0;
+       suite->succeeded = 0;
+       suite->skipped = 0;
+       suite->failed = 0;
+       suite->unsupported = 0;
+}
 
 int
 unit_test_suite_runner(struct unit_test_suite *suite)
 {
-       int test_success;
-       unsigned int total = 0, executed = 0, skipped = 0;
-       unsigned int succeeded = 0, failed = 0, unsupported = 0;
+       int test_success, i, ret;
        const char *status;
+       struct unit_test_case tc;
+       struct unit_test_suite *ts;
+       unsigned int sub_ts_succeeded = 0, sub_ts_failed = 0;
+       unsigned int sub_ts_skipped = 0, sub_ts_total = 0;
+
+       unit_test_suite_reset_counts(suite);
 
        if (suite->suite_name) {
                printf(" + ------------------------------------------------------- +\n");
@@ -219,55 +317,55 @@ unit_test_suite_runner(struct unit_test_suite *suite)
                         * setup did not pass, so count all enabled tests and
                         * mark them as failed/skipped
                         */
-                       while (suite->unit_test_cases[total].testcase) {
-                               if (!suite->unit_test_cases[total].enabled ||
-                                   test_success == TEST_SKIPPED)
-                                       skipped++;
-                               else
-                                       failed++;
-                               total++;
-                       }
+                       unit_test_suite_count_tcs_on_setup_fail(suite,
+                                       test_success, &sub_ts_failed,
+                                       &sub_ts_skipped, &sub_ts_total);
                        goto suite_summary;
                }
        }
 
        printf(" + ------------------------------------------------------- +\n");
 
-       while (suite->unit_test_cases[total].testcase) {
-               if (!suite->unit_test_cases[total].enabled) {
-                       skipped++;
-                       total++;
+       FOR_EACH_SUITE_TESTCASE(suite->total, suite, tc) {
+               if (!tc.enabled) {
+                       suite->skipped++;
                        continue;
                } else {
-                       executed++;
+                       suite->executed++;
                }
 
                /* run test case setup */
-               if (suite->unit_test_cases[total].setup)
-                       test_success = suite->unit_test_cases[total].setup();
+               if (tc.setup)
+                       test_success = tc.setup();
                else
                        test_success = TEST_SUCCESS;
 
                if (test_success == TEST_SUCCESS) {
                        /* run the test case */
-                       test_success = suite->unit_test_cases[total].testcase();
+                       if (tc.testcase)
+                               test_success = tc.testcase();
+                       else if (tc.testcase_with_data)
+                               test_success = tc.testcase_with_data(tc.data);
+                       else
+                               test_success = -ENOTSUP;
+
                        if (test_success == TEST_SUCCESS)
-                               succeeded++;
+                               suite->succeeded++;
                        else if (test_success == TEST_SKIPPED)
-                               skipped++;
+                               suite->skipped++;
                        else if (test_success == -ENOTSUP)
-                               unsupported++;
+                               suite->unsupported++;
                        else
-                               failed++;
+                               suite->failed++;
                } else if (test_success == -ENOTSUP) {
-                       unsupported++;
+                       suite->unsupported++;
                } else {
-                       failed++;
+                       suite->failed++;
                }
 
                /* run the test case teardown */
-               if (suite->unit_test_cases[total].teardown)
-                       suite->unit_test_cases[total].teardown();
+               if (tc.teardown)
+                       tc.teardown();
 
                if (test_success == TEST_SUCCESS)
                        status = "succeeded";
@@ -278,10 +376,25 @@ unit_test_suite_runner(struct unit_test_suite *suite)
                else
                        status = "failed";
 
-               printf(" + TestCase [%2d] : %s %s\n", total,
-                               suite->unit_test_cases[total].name, status);
-
-               total++;
+               printf(" + TestCase [%2d] : %s %s\n", suite->total,
+                               tc.name, status);
+       }
+       FOR_EACH_SUITE_TESTSUITE(i, suite, ts) {
+               ret = unit_test_suite_runner(ts);
+               if (ret == TEST_SUCCESS)
+                       sub_ts_succeeded++;
+               else if (ret == TEST_SKIPPED)
+                       sub_ts_skipped++;
+               else
+                       sub_ts_failed++;
+               sub_ts_total++;
+
+               suite->total += ts->total;
+               suite->succeeded += ts->succeeded;
+               suite->failed += ts->failed;
+               suite->skipped += ts->skipped;
+               suite->unsupported += ts->unsupported;
+               suite->executed += ts->executed;
        }
 
        /* Run test suite teardown */
@@ -292,20 +405,37 @@ unit_test_suite_runner(struct unit_test_suite *suite)
 
 suite_summary:
        printf(" + ------------------------------------------------------- +\n");
-       printf(" + Test Suite Summary \n");
-       printf(" + Tests Total :       %2d\n", total);
-       printf(" + Tests Skipped :     %2d\n", skipped);
-       printf(" + Tests Executed :    %2d\n", executed);
-       printf(" + Tests Unsupported:  %2d\n", unsupported);
-       printf(" + Tests Passed :      %2d\n", succeeded);
-       printf(" + Tests Failed :      %2d\n", failed);
+       printf(" + Test Suite Summary : %s\n", suite->suite_name);
+       printf(" + ------------------------------------------------------- +\n");
+
+       FOR_EACH_SUITE_TESTSUITE(i, suite, ts)
+               printf(" + %s : %d/%d passed, %d/%d skipped, "
+                       "%d/%d failed, %d/%d unsupported\n", ts->suite_name,
+                       ts->succeeded, ts->total, ts->skipped, ts->total,
+                       ts->failed, ts->total, ts->unsupported, ts->total);
+
+       if (suite->unit_test_suites) {
+               printf(" + ------------------------------------------------------- +\n");
+               printf(" + Sub Testsuites Total :     %2d\n", sub_ts_total);
+               printf(" + Sub Testsuites Skipped :   %2d\n", sub_ts_skipped);
+               printf(" + Sub Testsuites Passed :    %2d\n", sub_ts_succeeded);
+               printf(" + Sub Testsuites Failed :    %2d\n", sub_ts_failed);
+               printf(" + ------------------------------------------------------- +\n");
+       }
+
+       printf(" + Tests Total :       %2d\n", suite->total);
+       printf(" + Tests Skipped :     %2d\n", suite->skipped);
+       printf(" + Tests Executed :    %2d\n", suite->executed);
+       printf(" + Tests Unsupported:  %2d\n", suite->unsupported);
+       printf(" + Tests Passed :      %2d\n", suite->succeeded);
+       printf(" + Tests Failed :      %2d\n", suite->failed);
        printf(" + ------------------------------------------------------- +\n");
 
-       last_test_result = failed;
+       last_test_result = suite->failed;
 
-       if (failed)
+       if (suite->failed)
                return TEST_FAILED;
-       if (total == skipped)
+       if (suite->total == suite->skipped)
                return TEST_SKIPPED;
        return TEST_SUCCESS;
 }