diff --git a/components/utilities/utest/utest.c b/components/utilities/utest/utest.c index 18d2c88d0a..5ba36ff397 100644 --- a/components/utilities/utest/utest.c +++ b/components/utilities/utest/utest.c @@ -125,28 +125,45 @@ static void utest_run(const char *utest_name) continue; } + LOG_I("[----------] [ testcase ] (%s) started", tc_table[i].name); if (tc_table[i].init != RT_NULL) { - tc_table[i].init(); + if (tc_table[i].init() != RT_EOK) + { + LOG_I("[ FAILED ] [ result ] testcase (%s)", tc_table[i].name); + goto __tc_continue; + } } - LOG_I("[----------] [ testcase ] (%s) started", tc_table[i].name); - tc_table[i].tc(); - if (local_utest.failed_num == 0) + if (tc_table[i].tc != RT_NULL) { - LOG_I("[ PASSED ] [ result ] testcase (%s)", tc_table[i].name); + tc_table[i].tc(); + if (local_utest.failed_num == 0) + { + LOG_I("[ PASSED ] [ result ] testcase (%s)", tc_table[i].name); + } + else + { + LOG_I("[ FAILED ] [ result ] testcase (%s)", tc_table[i].name); + } } else { LOG_I("[ FAILED ] [ result ] testcase (%s)", tc_table[i].name); } - LOG_I("[----------] [ testcase ] (%s) finished", tc_table[i].name); if (tc_table[i].cleanup != RT_NULL) { - tc_table[i].cleanup(); + if (tc_table[i].cleanup() != RT_EOK) + { + LOG_I("[ FAILED ] [ result ] testcase (%s)", tc_table[i].name); + goto __tc_continue; + } } +__tc_continue: + LOG_I("[----------] [ testcase ] (%s) finished", tc_table[i].name); + i++; } LOG_I("[==========] [ utest ] finished"); @@ -184,7 +201,11 @@ void utest_unit_run(test_unit_func func, const char *unit_func_name) local_utest.error = UTEST_PASSED; local_utest.passed_num = 0; local_utest.failed_num = 0; - func(); + + if (func != RT_NULL) + { + func(); + } } void utest_assert(int value, const char *file, int line, const char *func, const char *msg) diff --git a/components/utilities/utest/utest.h b/components/utilities/utest/utest.h index 9532b115e6..9a5e58fc57 100644 --- a/components/utilities/utest/utest.h +++ b/components/utilities/utest/utest.h @@ -16,6 +16,16 @@ #define UTEST_SW_VERSION "0.0.1" +/** + * utest_error + * + * @brief Test result. + * + * @member UTEST_PASSED Test success. + * @member UTEST_FAILED Test failed. + * @member UTEST_PASSED Test skipped. + * +*/ enum utest_error { UTEST_PASSED = 0, @@ -24,6 +34,16 @@ enum utest_error }; typedef enum utest_error utest_err_e; +/** + * utest + * + * @brief utest data structure. + * + * @member error Error number from enum `utest_error`. + * @member passed_num Total number of tests passed. + * @member failed_num Total number of tests failed. + * +*/ struct utest { utest_err_e error; @@ -32,6 +52,19 @@ struct utest }; typedef struct utest *utest_t; +/** + * utest_tc_export + * + * @brief utest testcase data structure. + * Will export the data to `UtestTcTab` section in flash. + * + * @member name Testcase name. + * @member run_timeout Testcase maximum test time. + * @member init Necessary initialization before executing the test case function. + * @member tc Total number of tests failed. + * @member cleanup Total number of tests failed. + * +*/ struct utest_tc_export { const char *name; uint32_t run_timeout; @@ -41,18 +74,80 @@ struct utest_tc_export { }; typedef struct utest_tc_export *utest_tc_export_t; +/** + * test_unit_func + * + * @brief Unit test handler function pointer. + * +*/ typedef void (*test_unit_func)(void); +/** + * TC_LOG_x + * + * @brief Log output interface used in test cases. + * + * @type TC_LOG_I Output info level log. + * @type TC_LOG_D Output debug level log. + * @type TC_LOG_E Output error level log. + * @type TC_LOG_W Output warning level log. + * +*/ #define TC_LOG_I(...) LOG_I(__VA_ARGS__) #define TC_LOG_D(...) LOG_D(__VA_ARGS__) #define TC_LOG_E(...) LOG_E(__VA_ARGS__) #define TC_LOG_W(...) LOG_W(__VA_ARGS__) +/** + * utest_unit_run + * + * @brief Unit test function executor. + * No need for the user to call this function directly + * + * @param func Unit test function. + * @param unit_func_name Unit test function name. + * + * @return void + * +*/ void utest_unit_run(test_unit_func func, const char *unit_func_name); + +/** + * utest_handle_get + * + * @brief Get the utest data structure handle. + * No need for the user to call this function directly + * + * @param void + * + * @return utest_t type. (struct utest *) + * +*/ utest_t utest_handle_get(void); +/** + * UTEST_NAME_MAX_LEN + * + * @brief Testcase name maximum length. + * +*/ #define UTEST_NAME_MAX_LEN (128u) +/** + * UTEST_TC_EXPORT + * + * @brief Export testcase function to `UtestTcTab` section in flash. + * Used in application layer. + * + * @param testcase The testcase function. + * @param name The testcase name. + * @param init The initialization function of the test case. + * @param cleanup The cleanup function of the test case. + * @param timeout Testcase maximum test time. + * + * @return None + * +*/ #define UTEST_TC_EXPORT(testcase, name, init, cleanup, timeout) \ RT_USED static const struct utest_tc_export _utest_testcase \ SECTION("UtestTcTab") = \ @@ -64,8 +159,19 @@ utest_t utest_handle_get(void); cleanup \ } +/** + * UTEST_UNIT_RUN + * + * @brief Unit test function executor. + * Used in `testcase` function in application. + * + * @param test_unit_func Unit test function + * + * @return None + * +*/ #define UTEST_UNIT_RUN(test_unit_func) \ utest_unit_run(test_unit_func, #test_unit_func); \ if(utest_handle_get()->failed_num != 0) return; -#endif +#endif /* __UTEST_H__ */ diff --git a/components/utilities/utest/utest_assert.h b/components/utilities/utest/utest_assert.h index 57346b701f..e36fdc8af4 100644 --- a/components/utilities/utest/utest_assert.h +++ b/components/utilities/utest/utest_assert.h @@ -14,11 +14,33 @@ #include "utest.h" #include +/* No need for the user to use this function directly */ void utest_assert(int value, const char *file, int line, const char *func, const char *msg); + +/* No need for the user to use this function directly */ void utest_assert_string(const char *a, const char *b, rt_bool_t equal, const char *file, int line, const char *func, const char *msg); +/* No need for the user to use this macro directly */ #define __utest_assert(value, msg) utest_assert(value, __FILE__, __LINE__, __func__, msg) +/** + * uassert_x macros + * + * @brief Get the utest data structure handle. + * No need for the user to call this function directly. + * + * @macro uassert_true if @value is true, not assert, means passing. + * @macro uassert_false if @value is false, not assert, means passing. + * @macro uassert_null if @value is null, not assert, means passing. + * @macro uassert_not_null if @value is not null, not assert, means passing. + * @macro uassert_int_equal if @a equal to @b, not assert, means passing. Integer type test. + * @macro uassert_int_not_equal if @a not equal to @b, not assert, means passing. Integer type test. + * @macro uassert_str_equal if @a equal to @b, not assert, means passing. String type test. + * @macro uassert_str_not_equal if @a not equal to @b, not assert, means passing. String type test. + * @macro uassert_in_range if @value is in range of min and max, not assert, means passing. + * @macro uassert_not_in_range if @value is not in range of min and max, not assert, means passing. + * +*/ #define uassert_true(value) __utest_assert(value, "(" #value ") is false") #define uassert_false(value) __utest_assert(!(value), "(" #value ") is true") #define uassert_null(value) __utest_assert((value) == NULL, "(" #value ") is not null")