2024-11-16 13:36:54 +08:00

185 lines
6.9 KiB
C

/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* 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 <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdint.h>
/* 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