/********************************************************************************************************* * ------------------------------------------------------------------------------------------------------ * file description * ------------------------------------------------------------------------------------------------------ * \file unitt.h * \unit unitt * \brief This is a simple unit test module for C language * \author Lamdonn * \version v1.0.0 * \license GPL-2.0 * \copyright Copyright (C) 2023 Lamdonn. ********************************************************************************************************/ #ifndef __unitt_H #define __unitt_H #include #include #include #include #include #include /* Version infomation */ #define UNITT_V_MAJOR 0 #define UNITT_V_MINOR 1 #define UNITT_V_PATCH 0 // Type definition for a clock function typedef uint64_t (*unitt_clock_t)(); // Type definition for a test function typedef int (*unitt_func_t)(); // Type definition for a setup function before the test typedef int (*unitt_setup_t)(); // Type definition for a teardown function after the test typedef int (*unitt_teardown_t)(); // Type definition for a failure callback function typedef int (*unitt_failcb_t)(const char* name); // Type definition for a random input generation function typedef int (*unitt_randin_t)(); /** * \brief Structure representing a test case */ typedef struct { const char* name; ///< Name of the test unitt_func_t func; ///< Pointer to the test function unitt_setup_t setup; ///< Pointer to the setup function unitt_teardown_t teardown; ///< Pointer to the teardown function unitt_randin_t random_input; ///< Pointer to the random input generation function uint32_t tested; ///< Count of tests executed uint32_t passed; ///< Count of tests passed uint64_t time; ///< Total time taken for the test } UNITT_TCASE; /** * \brief Structure representing a test suite */ typedef struct { const char* name; ///< Name of the test suite UNITT_TCASE* tests; ///< Array of test cases uint32_t count; ///< Number of test cases unitt_clock_t clock; ///< Pointer to the clock function for measuring time } UNITT; #define UNITT_E_OK (0) // Success return code #define UNITT_E_FAIL (-1) // Failure return code /** * \brief Assert that a condition is true * \param[in] condition: The condition to evaluate * \param[in] message: The message to display if the assertion fails * \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL */ int unitt_det_true(int condition, const char* message); /** * \brief Assert that a condition is false * \param[in] condition: The condition to evaluate * \param[in] message: The message to display if the assertion fails * \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL */ int unitt_det_false(int condition, const char* message); /** * \brief Assert that two integers are equal * \param[in] expected: The expected value * \param[in] actual: The actual value * \param[in] message: The message to display if the assertion fails * \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL */ int unitt_det_equal(int expected, int actual, const char* message); /** * \brief Assert that two integers are not equal * \param[in] expected: The expected value * \param[in] actual: The actual value * \param[in] message: The message to display if the assertion fails * \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL */ int unitt_det_nequal(int expected, int actual, const char* message); /** * \brief Assert that a pointer is NULL * \param[in] pointer: The pointer to evaluate * \param[in] message: The message to display if the assertion fails * \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL */ int unitt_det_null(void* pointer, const char* message); /** * \brief Assert that a pointer is not NULL * \param[in] pointer: The pointer to evaluate * \param[in] message: The message to display if the assertion fails * \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL */ int unitt_det_nnull(void* pointer, const char* message); /** * \brief Assert that two floats are approximately equal * \param[in] expected: The expected float value * \param[in] actual: The actual float value * \param[in] epsilon: The acceptable difference between the two values * \param[in] message: The message to display if the assertion fails * \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL */ int unitt_det_float(float expected, float actual, float epsilon, const char* message); /** * \brief Assert that two strings are equal * \param[in] expected: The expected string * \param[in] actual: The actual string * \param[in] message: The message to display if the assertion fails * \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL */ int unitt_det_string(const char* expected, const char* actual, const char* message); /** * \brief Handle a test failure * \param[in] name: The name of the failed test * \return Returns UNITT_E_OK */ int unitt_fail_handle(const char* name); /** * \brief Execute a test suite * \param[in] suites: Array of test suites to execute * \param[in] count: Number of test suites in the array * \param[in] failcb: Callback function to handle test failures * \param[in] specific: Specific test name to execute (NULL for all) * \param[in] filename: Output filename for results (NULL for stdout) * \return none */ void unitt_execute(UNITT* suites, uint32_t count, unitt_failcb_t failcb, const char* specific, const char* filename); /** * \brief Macro to define a test case * \param name: Name of the test case */ #define UNITT_TCASE(name) { #name, name, NULL, NULL, NULL, 0, 0, 0 } /** * \brief Macro to execute a set of test cases * \param suites: Array of test cases to execute */ #define UNITT_EXE(suites) unitt_execute((suites), sizeof(suites) / sizeof(suites[0]), unitt_fail_handle, 0, 0) /** * \brief Macro to execute a set of test cases with additional parameters * \param suites: Array of test cases to execute * \param count: Number of test cases * \param mode: Execution mode * \param specific: Specific test name to execute * \param output: Output filename for results */ #define UNITT_EXE2(suites, count, mode, specific, output) unitt_execute(suites, count, unitt_fail_handle, specific, output) #endif // __unit_H