mirror of
https://gitee.com/Lamdonn/varch.git
synced 2025-12-06 16:56:42 +08:00
306 lines
9.5 KiB
C
306 lines
9.5 KiB
C
/*********************************************************************************************************
|
|
* ------------------------------------------------------------------------------------------------------
|
|
* file description
|
|
* ------------------------------------------------------------------------------------------------------
|
|
* \file unitt.c
|
|
* \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.
|
|
********************************************************************************************************/
|
|
#include "unitt.h"
|
|
|
|
/**
|
|
* \brief Assert that a condition is true.
|
|
*
|
|
* This function checks if the given condition is true. If it is false,
|
|
* it outputs an assertion failure message and returns a failure code.
|
|
*
|
|
* \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)
|
|
{
|
|
if (!condition)
|
|
{
|
|
fprintf(stderr, "Assertion Failed: %s\n", message);
|
|
return UNITT_E_FAIL;
|
|
}
|
|
|
|
return UNITT_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Assert that a condition is false.
|
|
*
|
|
* This function checks if the given condition is false. If it is true,
|
|
* it outputs an assertion failure message and returns a failure code.
|
|
*
|
|
* \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)
|
|
{
|
|
if (condition)
|
|
{
|
|
fprintf(stderr, "Assertion Failed: %s\n", message);
|
|
return UNITT_E_FAIL;
|
|
}
|
|
|
|
return UNITT_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Assert that two integers are equal.
|
|
*
|
|
* This function checks whether the expected and actual values are equal.
|
|
* If they are not equal, it outputs an assertion failure message with
|
|
* both values and returns a failure code.
|
|
*
|
|
* \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)
|
|
{
|
|
if (expected != actual)
|
|
{
|
|
fprintf(stderr, "Assertion Failed: %s (Expected: %d, Actual: %d)\n", message, expected, actual);
|
|
return UNITT_E_FAIL;
|
|
}
|
|
|
|
return UNITT_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Assert that two integers are not equal.
|
|
*
|
|
* This function checks whether the expected and actual values are not equal.
|
|
* If they are equal, it outputs an assertion failure message and returns a failure code.
|
|
*
|
|
* \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)
|
|
{
|
|
if (expected == actual)
|
|
{
|
|
fprintf(stderr, "Assertion Failed: %s (Expected not equal to Actual)\n", message);
|
|
return UNITT_E_FAIL;
|
|
}
|
|
|
|
return UNITT_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Assert that a pointer is NULL.
|
|
*
|
|
* This function checks whether the given pointer is NULL. If it is not NULL,
|
|
* it outputs an assertion failure message with the pointer's value and returns a failure code.
|
|
*
|
|
* \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)
|
|
{
|
|
if (pointer != NULL)
|
|
{
|
|
fprintf(stderr, "Assertion Failed: %s (Expected NULL, Actual: %p)\n", message, pointer);
|
|
return UNITT_E_FAIL;
|
|
}
|
|
|
|
return UNITT_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Assert that a pointer is not NULL.
|
|
*
|
|
* This function checks whether the given pointer is not NULL. If it is NULL,
|
|
* it outputs an assertion failure message and returns a failure code.
|
|
*
|
|
* \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)
|
|
{
|
|
if (pointer == NULL)
|
|
{
|
|
fprintf(stderr, "Assertion Failed: %s (Expected non-NULL, Actual: NULL)\n", message);
|
|
return UNITT_E_FAIL;
|
|
}
|
|
|
|
return UNITT_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Assert that two floats are approximately equal.
|
|
*
|
|
* This function checks whether the expected and actual float values are approximately equal
|
|
* within a given epsilon range. If they are not, it outputs an assertion failure message
|
|
* with both values and returns a failure code.
|
|
*
|
|
* \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)
|
|
{
|
|
if (fabs(expected - actual) > epsilon)
|
|
{
|
|
fprintf(stderr, "Assertion Failed: %s (Expected: %.6f, Actual: %.6f)\n", message, expected, actual);
|
|
return UNITT_E_FAIL;
|
|
}
|
|
|
|
return UNITT_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Assert that two strings are equal.
|
|
*
|
|
* This function checks whether the expected and actual strings are equal.
|
|
* If they are not equal, it outputs an assertion failure message with both strings
|
|
* and returns a failure code.
|
|
*
|
|
* \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)
|
|
{
|
|
if (strcmp(expected, actual) != 0)
|
|
{
|
|
fprintf(stderr, "Assertion Failed: %s (Expected: '%s', Actual: '%s')\n", message, expected, actual);
|
|
return UNITT_E_FAIL;
|
|
}
|
|
|
|
return UNITT_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Handle a test failure.
|
|
*
|
|
* This function is called when a test fails. It outputs the name of the failed test.
|
|
*
|
|
* \param[in] name: The name of the failed test.
|
|
* \return Returns UNITT_E_OK.
|
|
*/
|
|
int unitt_fail_handle(const char* name)
|
|
{
|
|
printf("Failure in test: %s\n", name);
|
|
return UNITT_E_OK;
|
|
}
|
|
|
|
/**
|
|
* \brief Execute a test suite.
|
|
*
|
|
* This function runs all the test cases within the provided test suites.
|
|
* It measures the execution time for each test and outputs a summary report.
|
|
*
|
|
* \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)
|
|
{
|
|
UNITT* suite = NULL;
|
|
UNITT_TCASE* tcase = NULL;
|
|
uint64_t cstart = 0, cend = 0; // Record the start and end time of the test
|
|
|
|
FILE* output = stdout; // Default output to standard output
|
|
if (filename != NULL)
|
|
{
|
|
output = fopen(filename, "w");
|
|
if (output == NULL)
|
|
{
|
|
perror("Failed to open output file");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Iterate over each test suite
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
suite = &suites[i];
|
|
|
|
fprintf(output, "Running test suite: %s\n", suite->name);
|
|
|
|
// Iterate over each test case
|
|
for (int j = 0; j < suite->count; j++)
|
|
{
|
|
tcase = &suite->tests[j];
|
|
|
|
if (specific && strcmp(tcase->name, specific) != 0)
|
|
{
|
|
continue; // Skip non-matching tests
|
|
}
|
|
|
|
// Execute setup function before the test
|
|
if (tcase->setup) tcase->setup();
|
|
|
|
// Record start time
|
|
if (suite->clock) cstart = suite->clock();
|
|
|
|
// Execute test function
|
|
if (UNITT_E_OK == tcase->func())
|
|
{
|
|
tcase->passed++;
|
|
}
|
|
else
|
|
{
|
|
if (failcb) failcb(tcase->name);
|
|
}
|
|
|
|
// Record end time
|
|
if (suite->clock) cend = suite->clock();
|
|
|
|
// Accumulate the time taken for the test
|
|
if (suite->clock) tcase->time += (cend - cstart);
|
|
|
|
// Execute teardown function after the test
|
|
if (tcase->teardown) tcase->teardown();
|
|
|
|
tcase->tested++;
|
|
}
|
|
}
|
|
|
|
// Output summary of the tests
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
suite = &suites[i];
|
|
|
|
fprintf(output, "Test suite `%s` report: \r\n", suite->name);
|
|
|
|
// Iterate over each test case
|
|
for (int j = 0; j < suite->count; j++)
|
|
{
|
|
tcase = &suite->tests[j];
|
|
|
|
fprintf(output, "[%s] Summary: tested %u, passed %u, time %llu us.\r\n",
|
|
tcase->name,
|
|
tcase->tested,
|
|
tcase->passed,
|
|
tcase->time
|
|
);
|
|
}
|
|
}
|
|
|
|
if (filename != NULL)
|
|
{
|
|
fclose(output);
|
|
}
|
|
} |