--- a/src/cmocka.c 2023-08-15 15:54:57.439010743 +0800 +++ cmocka/src/cmocka.c 2023-08-15 15:53:54.240452568 +0800 @@ -45,6 +45,9 @@ #include #include #include +#include +#include +#include /* * This allows to add a platform specific header file. Some embedded platforms @@ -269,6 +272,7 @@ const char *global_last_failed_assert = NULL; static int global_skip_test; static int global_stop_test; +static int global_list_test; /* Keeps a map of the values that functions will have to return to provide */ /* mocked interfaces. */ @@ -474,62 +478,18 @@ return 0; } -static int c_strmatch(const char *str, const char *pattern) -{ - int ok; +static int c_regexmatch(const char *str, const char *pattern){ + regex_t re; + int ret; - if (str == NULL || pattern == NULL) { + ret = regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB); + if (ret != 0){ return 0; } + ret = regexec(&re, str, 0, NULL, 0); + regfree(&re); - for (;;) { - /* Check if pattern is done */ - if (*pattern == '\0') { - /* If string is at the end, we're good */ - if (*str == '\0') { - return 1; - } - - return 0; - } - - if (*pattern == '*') { - /* Move on */ - pattern++; - - /* If we are at the end, everything is fine */ - if (*pattern == '\0') { - return 1; - } - - /* Try to match each position */ - for (; *str != '\0'; str++) { - ok = c_strmatch(str, pattern); - if (ok) { - return 1; - } - } - - /* No match */ - return 0; - } - - /* If we are at the end, leave */ - if (*str == '\0') { - return 0; - } - - /* Check if we have a single wildcard or matching char */ - if (*pattern != '?' && *str != *pattern) { - return 0; - } - - /* Move string and pattern */ - str++; - pattern++; - } - - return 0; + return (ret == 0)? 1 : 0; } /* Create function results and expected parameter lists. */ @@ -1850,7 +1810,7 @@ { if (result < 0) { if (error > 0) { - cmocka_print_error("%s < 0, errno(%d): %s\n", + cmocka_print_error("%s < 0, errno(%"PRIi32"): %s\n", expression, error, strerror(error)); @@ -2667,21 +2627,21 @@ print_message("[==========] %s: %zu test(s) run.\n", group_name, total_executed); - print_error("[ PASSED ] %u test(s).\n", + print_message("[ PASSED ] %u test(s).\n", (unsigned)(total_passed)); if (total_skipped) { - print_error("[ SKIPPED ] %s: %zu test(s), listed below:\n", + print_message("[ SKIPPED ] %s: %zu test(s), listed below:\n", group_name, total_skipped); for (i = 0; i < total_executed; i++) { struct CMUnitTestState *cmtest = &cm_tests[i]; if (cmtest->status == CM_TEST_SKIPPED) { - print_error("[ SKIPPED ] %s\n", cmtest->test->name); + print_message("[ SKIPPED ] %s\n", cmtest->test->name); } } - print_error("\n %zu SKIPPED TEST(S)\n", total_skipped); + print_message("\n %zu SKIPPED TEST(S)\n", total_skipped); } if (total_failed) { @@ -2918,6 +2878,11 @@ global_skip_filter_pattern = pattern; } +void cmocka_set_list_test(int list_test) +{ + global_list_test = list_test; +} + /**************************************************************************** * TIME CALCULATIONS ****************************************************************************/ @@ -3194,10 +3159,26 @@ double total_runtime = 0; size_t i; int rc; + mqd_t mq_id; /* Make sure uintmax_t is at least the size of a pointer. */ assert_true(sizeof(uintmax_t) >= sizeof(void*)); + /* Display name of testcase/testsuite but not run */ + if (global_list_test) { + print_message("%s\n", group_name); + for (i = 0; i < num_tests; i++) { + if (tests[i].name != NULL && + (tests[i].test_func != NULL + || tests[i].setup_func != NULL + || tests[i].teardown_func != NULL)) { + print_message("%4s%s\n", "", tests[i].name); + }; + } + + return 0; + } + cm_tests = libc_calloc(1, sizeof(struct CMUnitTestState) * num_tests); if (cm_tests == NULL) { return -1; @@ -3209,10 +3190,15 @@ (tests[i].test_func != NULL || tests[i].setup_func != NULL || tests[i].teardown_func != NULL)) { + cm_tests[total_tests] = (struct CMUnitTestState) { + .test = &tests[i], + .status = CM_TEST_NOT_STARTED, + .state = NULL, + }; if (global_test_filter_pattern != NULL) { int match; - match = c_strmatch(tests[i].name, global_test_filter_pattern); + match = c_regexmatch(tests[i].name, global_test_filter_pattern); if (!match) { continue; } @@ -3220,16 +3206,11 @@ if (global_skip_filter_pattern != NULL) { int match; - match = c_strmatch(tests[i].name, global_skip_filter_pattern); + match = c_regexmatch(tests[i].name, global_skip_filter_pattern); if (match) { - continue; + cm_tests[i].status = CM_TEST_SKIPPED; } } - cm_tests[total_tests] = (struct CMUnitTestState) { - .test = &tests[i], - .status = CM_TEST_NOT_STARTED, - .state = NULL, - }; total_tests++; } } @@ -3261,9 +3242,11 @@ cmtest->state = cmtest->test->initial_state; } - rc = cmocka_run_one_tests(cmtest); + if (cmtest->status != CM_TEST_SKIPPED) { + rc = cmocka_run_one_tests(cmtest); + total_runtime += cmtest->runtime; + } total_executed++; - total_runtime += cmtest->runtime; if (rc == 0) { switch (cmtest->status) { case CM_TEST_PASSED: @@ -3296,7 +3279,7 @@ break; } } else { - char err_msg[2048] = {0}; + char err_msg[256] = {0}; snprintf(err_msg, sizeof(err_msg), "Could not run test: %s", @@ -3347,6 +3330,24 @@ total_runtime, cm_tests); + mq_id = mq_open(CMOCKA_QUEUE_NAME, O_WRONLY); + if (mq_id != (mqd_t)-1) { + struct cm_summary_counter summary_send = {total_tests, + total_failed, + total_passed, + total_executed, + total_errors, + total_skipped}; + if (mq_send(mq_id, + (const char *)&summary_send, + sizeof(summary_send), + 0) < 0) { + perror("mq_send"); + } + + mq_close(mq_id); + } + for (i = 0; i < total_tests; i++) { vcm_free_error(discard_const_p(char, cm_tests[i].error_message)); } --- a/include/cmocka.h 2022-09-06 02:12:20.000000000 +0800 +++ cmocka/include/cmocka.h 2023-08-15 15:53:54.240452568 +0800 @@ -2279,6 +2279,20 @@ uintmax_t check_value_data; } CheckParameterEvent; +/* Mutiple suite run summary counter. */ +#define CMOCKA_QUEUE_NAME "/tmp/cmocka" +#define CMOCKA_MAX_MSG_SIZE 128 +#define CMOCKA_MAX_MSG_NUM 15 + +typedef struct cm_summary_counter { + int tests; + int failed; + int passed; + int executed; + int errors; + int skipped; +} cm_summary_counter; + /* Used by expect_assert_failure() and mock_assert(). */ extern int global_expecting_assert; extern jmp_buf global_expect_assert_env; @@ -2517,6 +2531,15 @@ */ void cmocka_set_skip_filter(const char *pattern); +/** + * @brief Set a flag to list testcase name only. + * + * This set global list_tests flag to indicate whether to list only, + * if list_tests is 1, list only. + * + * @param list_tests 0 or 1. + */ +void cmocka_set_list_test(int list_test); /** @} */ #endif /* CMOCKA_H_ */