Fossil Mock

Table Of Contents

Fossil Mock has been part of Fossil Test since version 0.2.1, providing mocking capabilities for building more controlled and predictable test environments. It allows test suites to create mock functions, record function calls and their arguments, manage mock call lists, and inspect captured calls during testing. The API also provides support for a range of data types and mock values, giving developers a flexible foundation for representing the inputs used by mocked functions.

Fossil Mock provides a collection of macros that simplify the creation and use of mocks, including FOSSIL_MOCK_FUNC for defining mock functions, FOSSIL_MOCK_ALIAS for creating type aliases, and FOSSIL_MOCK_STRUCT for defining mock structures. Mock calls can be initialized, added to a call list, printed, and destroyed, making it possible to track how code under test interacts with its dependencies without requiring those dependencies to perform their normal operations.


Fossil Mock also includes functionality for capturing and validating program output, allowing test cases to redirect function output into a buffer and compare the captured result against an expected value. In addition, the current API includes optional AI context associated with mock calls, supporting contextual information such as expected behavior, confidence scores, and notes for suggestions or verification. Together, these capabilities make Fossil Mock a long-standing part of Fossil Test for isolating behavior, observing function interactions, and validating outputs as part of automated testing.

PUBLIC INTERFACE #

// *****************************************************************************
// Type declarations
// *****************************************************************************

// --- Maip Data Types ---
typedef enum {
    FOSSIL_MOCK_MAIP_TYPE_I8,
    FOSSIL_MOCK_MAIP_TYPE_I16,
    FOSSIL_MOCK_MAIP_TYPE_I32,
    FOSSIL_MOCK_MAIP_TYPE_I64,
    FOSSIL_MOCK_MAIP_TYPE_U8,
    FOSSIL_MOCK_MAIP_TYPE_U16,
    FOSSIL_MOCK_MAIP_TYPE_U32,
    FOSSIL_MOCK_MAIP_TYPE_U64,
    FOSSIL_MOCK_MAIP_TYPE_HEX,
    FOSSIL_MOCK_MAIP_TYPE_OCTAL,
    FOSSIL_MOCK_MAIP_TYPE_FLOAT,
    FOSSIL_MOCK_MAIP_TYPE_DOUBLE,
    FOSSIL_MOCK_MAIP_TYPE_WSTR,
    FOSSIL_MOCK_MAIP_TYPE_CSTR,
    FOSSIL_MOCK_MAIP_TYPE_CCHAR,
    FOSSIL_MOCK_MAIP_TYPE_WCHAR,
    FOSSIL_MOCK_MAIP_TYPE_BOOL,
    FOSSIL_MOCK_MAIP_TYPE_SIZE,
    FOSSIL_MOCK_MAIP_TYPE_ANY
} fossil_mock_maip_type_t;

typedef struct {
    char *data;
    bool mutable_flag;
} fossil_mock_maip_value_t;

typedef struct {
    char* name;
    char* description;
    char* id;
} fossil_mock_maip_attribute_t;

typedef struct {
    fossil_mock_maip_type_t type;
    fossil_mock_maip_value_t value;
    fossil_mock_maip_attribute_t attribute;
} fossil_mock_maip_t;

// ******************************************************************************
// Mock call structure
// *****************************************************************************

typedef struct fossil_mock_ai_context_t {
    char *context_info;      // Additional context for AI reasoning (e.g., scenario, test intent)
    char *expected_behavior; // Description of expected behavior for the call
    double confidence;       // Confidence score for AI-generated suggestions or verifications
    char *ai_notes;          // AI-generated notes, explanations, or recommendations
} fossil_mock_ai_context_t;

typedef struct fossil_mock_call_t {
    char *function_name;
    fossil_mock_maip_t *arguments; // Use maip type for arguments
    int num_args;
    fossil_mock_ai_context_t *ai_context; // Pointer to AI context for this call
    struct fossil_mock_call_t *next;
} fossil_mock_call_t;

typedef struct {
    fossil_mock_call_t *head;
    fossil_mock_call_t *tail;
    int size;
    fossil_mock_ai_context_t *global_ai_context; // Optional: global AI context for the call list
} fossil_mock_calllist_t;

// *****************************************************************************
// Function declarations
// *****************************************************************************

/**
 * Initializes a fossil_mock_calllist_t.
 * 
 * @param list The fossil_mock_calllist_t to initialize.
 */
FOSSIL_MAIP_API void fossil_mock_init(fossil_mock_calllist_t *list);

/**
 * Destroys a fossil_mock_calllist_t and frees all associated memory.
 * 
 * @param list The fossil_mock_calllist_t to destroy.
 */
FOSSIL_MAIP_API void fossil_mock_destroy(fossil_mock_calllist_t *list);

/**
 * Adds a fossil_mock_call_t to the fossil_mock_calllist_t.
 * 
 * @param list The fossil_mock_calllist_t to add the fossil_mock_call_t to.
 * @param function_name The name of the function being called.
 * @param arguments The arguments passed to the function.
 * @param num_args The number of arguments.
 */
FOSSIL_MAIP_API void fossil_mock_add_call(fossil_mock_calllist_t *list, const char *function_name, fossil_mock_maip_t *arguments, int num_args);

/**
 * Prints the contents of a fossil_mock_calllist_t.
 * 
 * @param list The fossil_mock_calllist_t to print.
 */
FOSSIL_MAIP_API void fossil_mock_print(fossil_mock_calllist_t *list);

/**
 * Sets the AI context for a specific mock call.
 *
 * @param call The mock call to set the AI context for.
 * @param ai_context The AI context to associate with the call.
 */
FOSSIL_MAIP_API void fossil_mock_set_ai_context(fossil_mock_call_t *call, fossil_mock_ai_context_t *ai_context);

/**
 * Creates a new AI context for mocking.
 *
 * @param context_info Additional context information.
 * @param expected_behavior Description of expected behavior.
 * @param confidence Confidence score for AI suggestions.
 * @param ai_notes AI-generated notes or recommendations.
 * @return Pointer to the newly created AI context.
 */
FOSSIL_MAIP_API fossil_mock_ai_context_t *fossil_mock_create_ai_context(const char *context_info, const char *expected_behavior, double confidence, const char *ai_notes);

/**
 * Destroys an AI context and frees associated memory.
 *
 * @param ai_context The AI context to destroy.
 */
FOSSIL_MAIP_API void fossil_mock_destroy_ai_context(fossil_mock_ai_context_t *ai_context);

/**
 * Prints the AI context information for a mock call.
 *
 * @param ai_context The AI context to print.
 */
FOSSIL_MAIP_API void fossil_mock_print_ai_context(const fossil_mock_ai_context_t *ai_context);

/**
 * Captures the output of a function to a buffer for testing purposes.
 *
 * @param buffer The buffer to store the captured output.
 * @param size The size of the buffer.
 * @param function The function whose output is to be captured.
 * @return The number of characters captured.
 */
FOSSIL_MAIP_API int fossil_mock_capture_output(char *buffer, size_t size, void (*function)(void));

/**
 * Compares the captured output with the expected output.
 *
 * @param captured The captured output.
 * @param expected The expected output.
 * @return True if the captured output matches the expected output, false otherwise.
 */
FOSSIL_MAIP_API bool fossil_mock_compare_output(const char *captured, const char *expected);

#ifdef __cplusplus
}
#endif

// *****************************************************************************
// Public API Macros
// *****************************************************************************

/**
 * @brief Macro for initializing the mock list.
 *
 * This macro initializes the mock list by calling the fossil_mock_init function.
 *
 * @param list The mock list to initialize.
 */
#define MOCK_INIT(list) \
    _MOCK_INIT(list)

/**
 * @brief Macro for destroying the mock list.
 *
 * This macro destroys the mock list by calling the fossil_mock_destroy function.
 *
 * @param list The mock list to destroy.
 */
#define MOCK_DESTROY(list) \
    _MOCK_DESTROY(list)

/**
 * @brief Macro for adding a mock function call to the mock list.
 *
 * This macro adds a mock function call to the mock list by calling the fossil_mock_add_call function.
 *
 * @param list     The mock list to add the call to.
 * @param func     The mock function to add the call for.
 * @param args     The arguments of the mock function call.
 * @param num_args The number of arguments in the mock function call.
 */
#define MOCK_ADD_CALL(list, func, args, num_args) \
    _MOCK_ADD_CALL(list, func, args, num_args)

/**
 * @brief Macro for printing the mock list.
 *
 * This macro prints the mock list by calling the fossil_mock_print function.
 *
 * @param list The mock list to print.
 */
#define MOCK_PRINT(list) \
    _MOCK_PRINT(list)

/**
 * @def FOSSIL_MOCK_FUNC
 * @brief Macro for creating a mock function with the specified return type, name, and parameters.
 *
 * This macro simplifies the creation of mock functions by defining a function with the given return
 * type, name, and parameters. The function name will be prefixed with "fossil_mockup_" to clearly indicate
 * that it is a mock function.
 *
 * @param return_type   The return type of the mock function.
 * @param name          The name of the mock function.
 * @param ...           The parameters of the mock function in the format: (type1 param1, type2 param2, ...).
 * @return The return type specified for the mock function.
 */
#define FOSSIL_MOCK_FUNC(return_type, name, ...) \
    _FOSSIL_MOCK_FUNC(return_type, name, __VA_ARGS__)

/**
 * @def FOSSIL_MOCK_ALIAS
 * @brief Macro for creating a type alias based on an existing type.
 *
 * This macro creates a type alias for a given existing type.
 *
 * @param new_type       The name of the new type alias.
 * @param existing_type  The existing type to create an alias for.
 */
#define FOSSIL_MOCK_ALIAS(new_type, existing_type) \
    _FOSSIL_MOCK_ALIAS(new_type, existing_type)

/**
 * @def FOSSIL_MOCK_STRUCT
 * 
 * @brief Macro for creating a mock struct with the specified name and members.
 * 
 * This macro simplifies the creation of mock structs by defining a struct with the given name
 * and members. The struct name will be prefixed with "fossil_mockup_" to clearly indicate that it is a mock struct.
 * 
 * @param name     The name of the mock struct.
 */
#define FOSSIL_MOCK_STRUCT(name) \
    _FOSSIL_MOCK_STRUCT(name)

/**
 * @brief Macro for setting the AI context for a specific mock call (public version).
 *
 * This macro sets the AI context for a given mock call by calling the
 * fossil_mock_set_ai_context function.
 *
 * @param call The mock call to set the AI context for.
 * @param ai_context The AI context to associate with the call.
 */
#define MOCK_SET_AI_CONTEXT(call, ai_context) \
    _MOCK_SET_AI_CONTEXT(call, ai_context)

/**
 * @brief Macro for creating a new AI context for mocking (public version).
 *
 * This macro creates a new AI context by calling the
 * fossil_mock_create_ai_context function.
 *
 * @param context_info Additional context information.
 * @param expected_behavior Description of expected behavior.
 * @param confidence Confidence score for AI suggestions.
 * @param ai_notes AI-generated notes or recommendations.
 * @return Pointer to the newly created AI context.
 */
#define MOCK_CREATE_AI_CONTEXT(context_info, expected_behavior, confidence, ai_notes) \
    _MOCK_CREATE_AI_CONTEXT(context_info, expected_behavior, confidence, ai_notes)

/**
 * @brief Macro for destroying an AI context and freeing associated memory (public version).
 *
 * This macro destroys an AI context by calling the
 * fossil_mock_destroy_ai_context function.
 *
 * @param ai_context The AI context to destroy.
 */
#define MOCK_DESTROY_AI_CONTEXT(ai_context) \
    _MOCK_DESTROY_AI_CONTEXT(ai_context)

/**
 * @brief Macro for printing the AI context information for a mock call (public version).
 *
 * This macro prints the AI context by calling the
 * fossil_mock_print_ai_context function.
 *
 * @param ai_context The AI context to print.
 */
#define MOCK_PRINT_AI_CONTEXT(ai_context) \
    _MOCK_PRINT_AI_CONTEXT(ai_context)

/**
 * @def FOSSIL_MOCK_REDIRECT_STDOUT
 * @brief Macro for redirecting stdout to a buffer.
 *
 * This macro redirects stdout to a buffer for capturing output.
 *
 * @param buffer The buffer to capture the output.
 * @param size   The size of the buffer.
 */
#define FOSSIL_MOCK_REDIRECT_STDOUT(buffer, size, function) \
    _FOSSIL_MOCK_CAPTURE_OUTPUT(buffer, size, function)

/**
 * @def FOSSIL_MOCK_COMPARE_OUTPUT
 * @brief Macro for comparing captured output with expected output.
 *
 * This macro compares the captured output with the expected output.
 *
 * @param captured The captured output.
 * @param expected The expected output.
 * @return True if the captured output matches the expected output, false otherwise.
 */
#define FOSSIL_MOCK_COMPARE_OUTPUT(captured, expected) \
    _FOSSIL_MOCK_COMPARE_OUTPUT(captured, expected)

/**
 * @def MOCK_FUNC_CALL
 * @brief Macro for brigging macro function calls to the fossil_mockup_ prefixed functions.
 * This macro simplifies the creation of mock function calls by defining a function call
 * with the given name. The function name will be prefixed with "fossil_mockup_" to clearly indicate that it is a mock function call.
 * 
 * @param name The name of the mock function call.
 */
#define MOCK_FUNC_CALL(name) \
    _MOCK_FUNC_CALL(name)

C SAMPLE #

#include <fossil/maip/framework.h>
#include <string.h>


// * * * * * * * * * * * * * * * * * * * * * * * *
// * Fossil Logic Test Utilites
// * * * * * * * * * * * * * * * * * * * * * * * *
// Setup steps for things like test fixtures and
// mock objects are set here.
// * * * * * * * * * * * * * * * * * * * * * * * *

// Define the test suite and add test cases
FOSSIL_SUITE(c_mock_suite);

// Setup function for the test suite
FOSSIL_SETUP(c_mock_suite) {
    // Setup code here
}

// Teardown function for the test suite
FOSSIL_TEARDOWN(c_mock_suite) {
    // Teardown code here
}

FOSSIL_MOCK_ALIAS(MockInt, int);

// Example of creating a mock struct using the macro
FOSSIL_MOCK_STRUCT(MockStruct) {
    int a;
    char b;
} MockStruct;

// Example of creating a mock function using the macro
FOSSIL_MOCK_FUNC(int, c_mock_function, int a, int b) {
    return a + b;
}

FOSSIL_MOCK_FUNC(void, c_mock_function_with_output, void) {
    maip_io_printf("Hello, Fossil Logic!");
}

FOSSIL_MOCK_FUNC(void, mock_function_redirection, void) {
    maip_io_printf("Testing macro redirection!");
}

// * * * * * * * * * * * * * * * * * * * * * * * *
// * Fossil Logic Test Cases
// * * * * * * * * * * * * * * * * * * * * * * * *
// The test cases below are provided as samples, showcasing
// Domain-Driven Design (DDD) usage in the Fossil Logic project.
// * * * * * * * * * * * * * * * * * * * * * * * *

FOSSIL_TEST(c_mock_call_list_initialization) {
    // Example of initializing a fossil_mock_calllist_t using macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Test cases
    FOSSIL_TEST_ASSUME(list.head == NULL, "fossil_mock_calllist_t head should be NULL after initialization");
    FOSSIL_TEST_ASSUME(list.tail == NULL, "fossil_mock_calllist_t tail should be NULL after initialization");
    FOSSIL_TEST_ASSUME(list.size == 0, "fossil_mock_calllist_t size should be 0 after initialization");
} // end case

FOSSIL_TEST(c_mock_call_list_addition) {
    // Example of adding a fossil_mock_call_t to a fossil_mock_calllist_t using macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create mock arguments
    fossil_mock_maip_t args[2];
    args[0].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[0].value.data = maip_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = maip_io_cstr_dup("arg1_name");
    args[0].attribute.description = maip_io_cstr_dup("First argument");
    args[0].attribute.id = maip_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[1].value.data = maip_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = maip_io_cstr_dup("arg2_name");
    args[1].attribute.description = maip_io_cstr_dup("Second argument");
    args[1].attribute.id = maip_io_cstr_dup("2");

    MOCK_ADD_CALL(list, "test_function", args, 2);

    // Test cases
    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call");
    FOSSIL_TEST_ASSUME(strcmp(list.head->function_name, "test_function") == 0, "Function name should be 'test_function'");
    FOSSIL_TEST_ASSUME(list.head->num_args == 2, "Number of arguments should be 2");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[0].value.data, "arg1") == 0, "First argument should be 'arg1'");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[1].value.data, "arg2") == 0, "Second argument should be 'arg2'");
} // end case

FOSSIL_TEST(c_mock_call_list_destruction) {
    // Example of destroying a fossil_mock_calllist_t using macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create mock arguments
    fossil_mock_maip_t args[2];
    args[0].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[0].value.data = maip_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = maip_io_cstr_dup("arg1_name");
    args[0].attribute.description = maip_io_cstr_dup("First argument");
    args[0].attribute.id = maip_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[1].value.data = maip_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = maip_io_cstr_dup("arg2_name");
    args[1].attribute.description = maip_io_cstr_dup("Second argument");
    args[1].attribute.id = maip_io_cstr_dup("2");

    MOCK_ADD_CALL(list, "test_function", args, 2);

    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call");
    FOSSIL_TEST_ASSUME(strcmp(list.head->function_name, "test_function") == 0, "Function name should be 'test_function'");
    FOSSIL_TEST_ASSUME(list.head->num_args == 2, "Number of arguments should be 2");

    MOCK_DESTROY(list);
    FOSSIL_TEST_ASSUME(list.head == NULL, "fossil_mock_calllist_t head should be NULL after destruction");
    FOSSIL_TEST_ASSUME(list.tail == NULL, "fossil_mock_calllist_t tail should be NULL after destruction");
    FOSSIL_TEST_ASSUME(list.size == 0, "fossil_mock_calllist_t size should be 0 after destruction");
} // end case

FOSSIL_TEST(c_mock_function_creation) {
    // Test cases
    FOSSIL_TEST_ASSUME(MOCK_FUNC_CALL(c_mock_function(2, 3)) == 5, "Mock function should return the sum of its arguments");
} // end case

FOSSIL_TEST(c_mock_alias_creation) {
    // Example of creating a type alias using the macro

    // Test cases
    MockInt x = 10;
    FOSSIL_TEST_ASSUME(x == 10, "Mock alias should behave like the original type");
} // end case

FOSSIL_TEST(c_mock_struct_creation) {
    // Test cases
    MockStruct instance;
    instance.a = 5;
    instance.b = 'c';
    FOSSIL_TEST_ASSUME(instance.a == 5, "Mock struct member 'a' should be 5");
    FOSSIL_TEST_ASSUME(instance.b == 'c', "Mock struct member 'b' should be 'c'");
} // end case

FOSSIL_TEST(c_mock_call_list_type_handling) {
    // Initialize the mock call list using macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create mock arguments with various types
    fossil_mock_maip_t args[3];
    args[0].type = FOSSIL_MOCK_MAIP_TYPE_I32;
    args[0].value.data = maip_io_cstr_dup("42");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = maip_io_cstr_dup("arg1");
    args[0].attribute.description = maip_io_cstr_dup("Integer argument");
    args[0].attribute.id = maip_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[1].value.data = maip_io_cstr_dup("Hello");
    args[1].value.mutable_flag = true;
    args[1].attribute.name = maip_io_cstr_dup("arg2");
    args[1].attribute.description = maip_io_cstr_dup("String argument");
    args[1].attribute.id = maip_io_cstr_dup("2");

    args[2].type = FOSSIL_MOCK_MAIP_TYPE_BOOL;
    args[2].value.data = maip_io_cstr_dup("true");
    args[2].value.mutable_flag = false;
    args[2].attribute.name = maip_io_cstr_dup("arg3");
    args[2].attribute.description = maip_io_cstr_dup("Boolean argument");
    args[2].attribute.id = maip_io_cstr_dup("3");

    // Add a mock call with the arguments using macro
    MOCK_ADD_CALL(list, "test_function", args, 3);

    // Test cases
    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call");
    FOSSIL_TEST_ASSUME(strcmp(list.head->function_name, "test_function") == 0, "Function name should be 'test_function'");
    FOSSIL_TEST_ASSUME(list.head->num_args == 3, "Number of arguments should be 3");

    FOSSIL_TEST_ASSUME(list.head->arguments[0].type == FOSSIL_MOCK_MAIP_TYPE_I32, "First argument type should be I32");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[0].value.data, "42") == 0, "First argument value should be '42'");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[0].attribute.name, "arg1") == 0, "First argument name should be 'arg1'");

    FOSSIL_TEST_ASSUME(list.head->arguments[1].type == FOSSIL_MOCK_MAIP_TYPE_CSTR, "Second argument type should be CSTR");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[1].value.data, "Hello") == 0, "Second argument value should be 'Hello'");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[1].attribute.name, "arg2") == 0, "Second argument name should be 'arg2'");

    FOSSIL_TEST_ASSUME(list.head->arguments[2].type == FOSSIL_MOCK_MAIP_TYPE_BOOL, "Third argument type should be BOOL");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[2].value.data, "true") == 0, "Third argument value should be 'true'");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[2].attribute.name, "arg3") == 0, "Third argument name should be 'arg3'");

    // Clean up
    MOCK_DESTROY(list);
} // end case

FOSSIL_TEST(c_mock_call_list_edge_cases) {
    // Initialize the mock call list using macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Add a call with no arguments using macro
    MOCK_ADD_CALL(list, "no_args_function", NULL, 0);

    // Test cases
    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call with no arguments");
    FOSSIL_TEST_ASSUME(strcmp(list.head->function_name, "no_args_function") == 0, "Function name should be 'no_args_function'");
    FOSSIL_TEST_ASSUME(list.head->num_args == 0, "Number of arguments should be 0");

    // Clean up
    MOCK_DESTROY(list);
} // end case

FOSSIL_TEST(c_mock_call_list_large_arguments) {
    // Initialize the mock call list using macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create a large number of mock arguments
    const int num_args = 100;
    fossil_mock_maip_t args[num_args];
    for (int i = 0; i < num_args; ++i) {
        args[i].type = FOSSIL_MOCK_MAIP_TYPE_I32;
        args[i].value.data = maip_io_cstr_dup("42");
        args[i].value.mutable_flag = false;
        args[i].attribute.name = maip_io_cstr_dup("arg");
        args[i].attribute.description = maip_io_cstr_dup("Large argument test");
        args[i].attribute.id = maip_io_cstr_dup("id");
    }

    // Add a mock call with the large number of arguments using macro
    MOCK_ADD_CALL(list, "large_args_function", args, num_args);

    // Test cases
    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call with large arguments");
    FOSSIL_TEST_ASSUME(list.head->num_args == num_args, "Number of arguments should match the large number");

    // Clean up
    MOCK_DESTROY(list);
} // end case

FOSSIL_TEST(c_mock_macro_initialization) {
    // Initialize the mock call list using the macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Test cases
    FOSSIL_TEST_ASSUME(list.head == NULL, "fossil_mock_calllist_t head should be NULL after initialization using macro");
    FOSSIL_TEST_ASSUME(list.tail == NULL, "fossil_mock_calllist_t tail should be NULL after initialization using macro");
    FOSSIL_TEST_ASSUME(list.size == 0, "fossil_mock_calllist_t size should be 0 after initialization using macro");
} // end case

FOSSIL_TEST(c_mock_macro_addition) {
    // Initialize the mock call list using the macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create mock arguments
    fossil_mock_maip_t args[2];
    args[0].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[0].value.data = maip_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = maip_io_cstr_dup("arg1_name");
    args[0].attribute.description = maip_io_cstr_dup("First argument");
    args[0].attribute.id = maip_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[1].value.data = maip_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = maip_io_cstr_dup("arg2_name");
    args[1].attribute.description = maip_io_cstr_dup("Second argument");
    args[1].attribute.id = maip_io_cstr_dup("2");

    // Add a mock call using the macro
    MOCK_ADD_CALL(list, "test_function", args, 2);

    // Test cases
    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call using macro");
    FOSSIL_TEST_ASSUME(strcmp(list.head->function_name, "test_function") == 0, "Function name should be 'test_function'");
    FOSSIL_TEST_ASSUME(list.head->num_args == 2, "Number of arguments should be 2");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[0].value.data, "arg1") == 0, "First argument should be 'arg1'");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[1].value.data, "arg2") == 0, "Second argument should be 'arg2'");
} // end case

FOSSIL_TEST(c_mock_macro_destruction) {
    // Initialize the mock call list using the macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create mock arguments
    fossil_mock_maip_t args[2];
    args[0].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[0].value.data = maip_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = maip_io_cstr_dup("arg1_name");
    args[0].attribute.description = maip_io_cstr_dup("First argument");
    args[0].attribute.id = maip_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[1].value.data = maip_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = maip_io_cstr_dup("arg2_name");
    args[1].attribute.description = maip_io_cstr_dup("Second argument");
    args[1].attribute.id = maip_io_cstr_dup("2");

    // Add a mock call using the macro
    MOCK_ADD_CALL(list, "test_function", args, 2);

    // Destroy the mock call list using the macro
    MOCK_DESTROY(list);

    // Test cases
    FOSSIL_TEST_ASSUME(list.head == NULL, "fossil_mock_calllist_t head should be NULL after destruction using macro");
    FOSSIL_TEST_ASSUME(list.tail == NULL, "fossil_mock_calllist_t tail should be NULL after destruction using macro");
    FOSSIL_TEST_ASSUME(list.size == 0, "fossil_mock_calllist_t size should be 0 after destruction using macro");
} // end case

FOSSIL_TEST(c_mock_io_capture_output) {
    // Buffer to capture output
    char buffer[256];

    // Capture the output of the mock function
    int captured_size = fossil_mock_capture_output(buffer, sizeof(buffer), MOCK_FUNC_CALL(c_mock_function_with_output));

    // Test cases
    FOSSIL_TEST_ASSUME(captured_size > 0, "Captured size should be greater than 0");
    FOSSIL_TEST_ASSUME(strcmp(buffer, "Hello, Fossil Logic!") == 0, "Captured output should match expected output");
} // end case

FOSSIL_TEST(c_mock_io_compare_output) {
    // Captured and expected outputs
    const char *captured = "Hello, Fossil Logic!";
    const char *expected = "Hello, Fossil Logic!";

    // Compare the outputs
    bool result = fossil_mock_compare_output(captured, expected);

    // Test cases
    FOSSIL_TEST_ASSUME(result == true, "Captured output should match expected output");
} // end case

FOSSIL_TEST(c_mock_io_redirect_stdout_macro) {
    // Buffer to capture output
    char buffer[256];

    // Use the macro to redirect stdout and capture output
    FOSSIL_MOCK_REDIRECT_STDOUT(buffer, sizeof(buffer), fossil_mockup_mock_function_redirection);

    // Test cases
    FOSSIL_TEST_ASSUME(strcmp(buffer, "Testing macro redirection!") == 0, "Captured output should match expected output");
} // end case

FOSSIL_TEST(c_mock_io_compare_output_macro) {
    // Captured and expected outputs
    const char *captured = "Macro comparison test!";
    const char *expected = "Macro comparison test!";

    // Use the macro to compare outputs
    bool result = FOSSIL_MOCK_COMPARE_OUTPUT(captured, expected);

    // Test cases
    FOSSIL_TEST_ASSUME(result == true, "Captured output should match expected output using macro");
} // end case

// * * * * * * * * * * * * * * * * * * * * * * * *
// * Fossil Logic Test Pool
// * * * * * * * * * * * * * * * * * * * * * * * *
FOSSIL_TEST_GROUP(c_mock_test_cases) {
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_call_list_initialization);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_call_list_addition);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_call_list_destruction);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_function_creation);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_alias_creation);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_struct_creation);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_call_list_type_handling);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_call_list_edge_cases);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_call_list_large_arguments);

    FOSSIL_ADD_TEST(c_mock_suite, c_mock_macro_initialization);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_macro_addition);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_macro_destruction);

    FOSSIL_ADD_TEST(c_mock_suite, c_mock_io_capture_output);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_io_compare_output);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_io_redirect_stdout_macro);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_io_compare_output_macro);
    FOSSIL_ADD_TEST(c_mock_suite, c_mock_io_compare_output);

    FOSSIL_ADD_SUITE(c_mock_suite);
} // end of group

C++ SAMPLE #

#include <fossil/maip/framework.h>
#include <string.h>


// * * * * * * * * * * * * * * * * * * * * * * * *
// * Fossil Logic Test Utilites
// * * * * * * * * * * * * * * * * * * * * * * * *
// Setup steps for things like test fixtures and
// mock objects are set here.
// * * * * * * * * * * * * * * * * * * * * * * * *

// Define the test suite and add test cases
FOSSIL_SUITE(cpp_mock_suite);

// Setup function for the test suite
FOSSIL_SETUP(cpp_mock_suite) {
    // Setup code here
}

// Teardown function for the test suite
FOSSIL_TEARDOWN(cpp_mock_suite) {
    // Teardown code here
}

FOSSIL_MOCK_ALIAS(MockInt, int);

// Example of creating a mock struct using the macro
FOSSIL_MOCK_STRUCT(MockStruct) {
    int a;
    char b;
};

// Example of creating a mock function using the macro
FOSSIL_MOCK_FUNC(int, cpp_mock_function, int a, int b) {
    return a + b;
}

FOSSIL_MOCK_FUNC(void, cpp_mock_function_with_output, void) {
    maip_io_printf("Hello, Fossil Logic!");
}

FOSSIL_MOCK_FUNC(void, mock_function_redirection, void) {
    maip_io_printf("Testing macro redirection!");
}

// * * * * * * * * * * * * * * * * * * * * * * * *
// * Fossil Logic Test Cases
// * * * * * * * * * * * * * * * * * * * * * * * *
// The test cases below are provided as samples, showcasing
// Domain-Driven Design (DDD) usage in the Fossil Logic project.
// * * * * * * * * * * * * * * * * * * * * * * * *

FOSSIL_TEST(cpp_mock_call_list_initialization) {
    // Example of initializing a fossil_mock_calllist_t
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Test cases
    FOSSIL_TEST_ASSUME(list.head == NULL, "fossil_mock_calllist_t head should be NULL after initialization");
    FOSSIL_TEST_ASSUME(list.tail == NULL, "fossil_mock_calllist_t tail should be NULL after initialization");
    FOSSIL_TEST_ASSUME(list.size == 0, "fossil_mock_calllist_t size should be 0 after initialization");
} // end case

FOSSIL_TEST(cpp_mock_call_list_addition) {
    // Example of adding a fossil_mock_call_t to a fossil_mock_calllist_t
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create mock arguments
    fossil_mock_maip_t args[2];
    args[0].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[0].value.data = maip_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = maip_io_cstr_dup("arg1_name");
    args[0].attribute.description = maip_io_cstr_dup("First argument");
    args[0].attribute.id = maip_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[1].value.data = maip_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = maip_io_cstr_dup("arg2_name");
    args[1].attribute.description = maip_io_cstr_dup("Second argument");
    args[1].attribute.id = maip_io_cstr_dup("2");

    MOCK_ADD_CALL(list, "test_function", args, 2);

    // Test cases
    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call");
    FOSSIL_TEST_ASSUME(strcmp(list.head->function_name, "test_function") == 0, "Function name should be 'test_function'");
    FOSSIL_TEST_ASSUME(list.head->num_args == 2, "Number of arguments should be 2");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[0].value.data, "arg1") == 0, "First argument should be 'arg1'");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[1].value.data, "arg2") == 0, "Second argument should be 'arg2'");
} // end case

FOSSIL_TEST(cpp_mock_call_list_destruction) {
    // Example of destroying a fossil_mock_calllist_t
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create mock arguments
    fossil_mock_maip_t args[2];
    args[0].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[0].value.data = maip_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = maip_io_cstr_dup("arg1_name");
    args[0].attribute.description = maip_io_cstr_dup("First argument");
    args[0].attribute.id = maip_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[1].value.data = maip_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = maip_io_cstr_dup("arg2_name");
    args[1].attribute.description = maip_io_cstr_dup("Second argument");
    args[1].attribute.id = maip_io_cstr_dup("2");

    MOCK_ADD_CALL(list, "test_function", args, 2);

    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call");
    FOSSIL_TEST_ASSUME(strcmp(list.head->function_name, "test_function") == 0, "Function name should be 'test_function'");
    FOSSIL_TEST_ASSUME(list.head->num_args == 2, "Number of arguments should be 2");

    MOCK_DESTROY(list);
} // end case

FOSSIL_TEST(cpp_mock_function_creation) {
    // Test cases
    FOSSIL_TEST_ASSUME(MOCK_FUNC_CALL(cpp_mock_function(2, 3)) == 5, "Mock function should return the sum of its arguments");
} // end case

FOSSIL_TEST(cpp_mock_alias_creation) {
    // Example of creating a type alias using the macro

    // Test cases
    MockInt x = 10;
    FOSSIL_TEST_ASSUME(x == 10, "Mock alias should behave like the original type");
} // end case

FOSSIL_TEST(cpp_mock_struct_creation) {
    // Test cases
    MockStruct instance;
    instance.a = 5;
    instance.b = 'c';
    FOSSIL_TEST_ASSUME(instance.a == 5, "Mock struct member 'a' should be 5");
    FOSSIL_TEST_ASSUME(instance.b == 'c', "Mock struct member 'b' should be 'c'");
} // end case

FOSSIL_TEST(cpp_mock_call_list_type_handling) {
    // Initialize the mock call list
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create mock arguments with various types
    fossil_mock_maip_t args[3];
    args[0].type = FOSSIL_MOCK_MAIP_TYPE_I32;
    args[0].value.data = maip_io_cstr_dup("42");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = maip_io_cstr_dup("arg1");
    args[0].attribute.description = maip_io_cstr_dup("Integer argument");
    args[0].attribute.id = maip_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[1].value.data = maip_io_cstr_dup("Hello");
    args[1].value.mutable_flag = true;
    args[1].attribute.name = maip_io_cstr_dup("arg2");
    args[1].attribute.description = maip_io_cstr_dup("String argument");
    args[1].attribute.id = maip_io_cstr_dup("2");

    args[2].type = FOSSIL_MOCK_MAIP_TYPE_BOOL;
    args[2].value.data = maip_io_cstr_dup("true");
    args[2].value.mutable_flag = false;
    args[2].attribute.name = maip_io_cstr_dup("arg3");
    args[2].attribute.description = maip_io_cstr_dup("Boolean argument");
    args[2].attribute.id = maip_io_cstr_dup("3");

    // Add a mock call with the arguments
    MOCK_ADD_CALL(list, "test_function", args, 3);

    // Test cases
    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call");
    FOSSIL_TEST_ASSUME(strcmp(list.head->function_name, "test_function") == 0, "Function name should be 'test_function'");
    FOSSIL_TEST_ASSUME(list.head->num_args == 3, "Number of arguments should be 3");

    FOSSIL_TEST_ASSUME(list.head->arguments[0].type == FOSSIL_MOCK_MAIP_TYPE_I32, "First argument type should be I32");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[0].value.data, "42") == 0, "First argument value should be '42'");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[0].attribute.name, "arg1") == 0, "First argument name should be 'arg1'");

    FOSSIL_TEST_ASSUME(list.head->arguments[1].type == FOSSIL_MOCK_MAIP_TYPE_CSTR, "Second argument type should be CSTR");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[1].value.data, "Hello") == 0, "Second argument value should be 'Hello'");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[1].attribute.name, "arg2") == 0, "Second argument name should be 'arg2'");

    FOSSIL_TEST_ASSUME(list.head->arguments[2].type == FOSSIL_MOCK_MAIP_TYPE_BOOL, "Third argument type should be BOOL");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[2].value.data, "true") == 0, "Third argument value should be 'true'");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[2].attribute.name, "arg3") == 0, "Third argument name should be 'arg3'");

    // Clean up
    MOCK_DESTROY(list);
} // end case

FOSSIL_TEST(cpp_mock_call_list_edge_cases) {
    // Initialize the mock call list
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Add a call with no arguments
    MOCK_ADD_CALL(list, "no_args_function", NULL, 0);

    // Test cases
    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call with no arguments");
    FOSSIL_TEST_ASSUME(strcmp(list.head->function_name, "no_args_function") == 0, "Function name should be 'no_args_function'");
    FOSSIL_TEST_ASSUME(list.head->num_args == 0, "Number of arguments should be 0");

    // Clean up
    MOCK_DESTROY(list);
} // end case

FOSSIL_TEST(cpp_mock_call_list_large_arguments) {
    // Initialize the mock call list
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create a large number of mock arguments
    const int num_args = 100;
    fossil_mock_maip_t args[num_args];
    for (int i = 0; i < num_args; ++i) {
        args[i].type = FOSSIL_MOCK_MAIP_TYPE_I32;
        args[i].value.data = maip_io_cstr_dup("42");
        args[i].value.mutable_flag = false;
        args[i].attribute.name = maip_io_cstr_dup("arg");
        args[i].attribute.description = maip_io_cstr_dup("Large argument test");
        args[i].attribute.id = maip_io_cstr_dup("id");
    }

    // Add a mock call with the large number of arguments
    MOCK_ADD_CALL(list, "large_args_function", args, num_args);

    // Test cases
    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call with large arguments");
    FOSSIL_TEST_ASSUME(list.head->num_args == num_args, "Number of arguments should match the large number");

    // Clean up
    MOCK_DESTROY(list);
} // end case

FOSSIL_TEST(cpp_mock_macro_initialization) {
    // Initialize the mock call list using the macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Test cases
    FOSSIL_TEST_ASSUME(list.head == NULL, "fossil_mock_calllist_t head should be NULL after initialization using macro");
    FOSSIL_TEST_ASSUME(list.tail == NULL, "fossil_mock_calllist_t tail should be NULL after initialization using macro");
    FOSSIL_TEST_ASSUME(list.size == 0, "fossil_mock_calllist_t size should be 0 after initialization using macro");
} // end case

FOSSIL_TEST(cpp_mock_macro_addition) {
    // Initialize the mock call list using the macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create mock arguments
    fossil_mock_maip_t args[2];
    args[0].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[0].value.data = maip_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = maip_io_cstr_dup("arg1_name");
    args[0].attribute.description = maip_io_cstr_dup("First argument");
    args[0].attribute.id = maip_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[1].value.data = maip_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = maip_io_cstr_dup("arg2_name");
    args[1].attribute.description = maip_io_cstr_dup("Second argument");
    args[1].attribute.id = maip_io_cstr_dup("2");

    // Add a mock call using the macro
    MOCK_ADD_CALL(list, "test_function", args, 2);

    // Test cases
    FOSSIL_TEST_ASSUME(list.size == 1, "fossil_mock_calllist_t size should be 1 after adding a call using macro");
    FOSSIL_TEST_ASSUME(strcmp(list.head->function_name, "test_function") == 0, "Function name should be 'test_function'");
    FOSSIL_TEST_ASSUME(list.head->num_args == 2, "Number of arguments should be 2");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[0].value.data, "arg1") == 0, "First argument should be 'arg1'");
    FOSSIL_TEST_ASSUME(strcmp(list.head->arguments[1].value.data, "arg2") == 0, "Second argument should be 'arg2'");
} // end case

FOSSIL_TEST(cpp_mock_macro_destruction) {
    // Initialize the mock call list using the macro
    fossil_mock_calllist_t list;
    MOCK_INIT(list);

    // Create mock arguments
    fossil_mock_maip_t args[2];
    args[0].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[0].value.data = maip_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = maip_io_cstr_dup("arg1_name");
    args[0].attribute.description = maip_io_cstr_dup("First argument");
    args[0].attribute.id = maip_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_MAIP_TYPE_CSTR;
    args[1].value.data = maip_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = maip_io_cstr_dup("arg2_name");
    args[1].attribute.description = maip_io_cstr_dup("Second argument");
    args[1].attribute.id = maip_io_cstr_dup("2");

    // Add a mock call using the macro
    MOCK_ADD_CALL(list, "test_function", args, 2);

    // Destroy the mock call list using the macro
    MOCK_DESTROY(list);

    // Test cases
    FOSSIL_TEST_ASSUME(list.head == NULL, "fossil_mock_calllist_t head should be NULL after destruction using macro");
    FOSSIL_TEST_ASSUME(list.tail == NULL, "fossil_mock_calllist_t tail should be NULL after destruction using macro");
    FOSSIL_TEST_ASSUME(list.size == 0, "fossil_mock_calllist_t size should be 0 after destruction using macro");
} // end case

FOSSIL_TEST(cpp_mock_io_capture_output) {
    // Buffer to capture output
    char buffer[256];

    // Capture the output of the mock function
    int captured_size = fossil_mock_capture_output(buffer, sizeof(buffer), MOCK_FUNC_CALL(cpp_mock_function_with_output));

    // Test cases
    FOSSIL_TEST_ASSUME(captured_size > 0, "Captured size should be greater than 0");
    FOSSIL_TEST_ASSUME(strcmp(buffer, "Hello, Fossil Logic!") == 0, "Captured output should match expected output");
} // end case

FOSSIL_TEST(cpp_mock_io_compare_output) {
    // Captured and expected outputs
    const char *captured = "Hello, Fossil Logic!";
    const char *expected = "Hello, Fossil Logic!";

    // Compare the outputs
    bool result = fossil_mock_compare_output(captured, expected);

    // Test cases
    FOSSIL_TEST_ASSUME(result == true, "Captured output should match expected output");
} // end case

FOSSIL_TEST(cpp_mock_io_redirect_stdout_macro) {
    // Buffer to capture output
    char buffer[256];

    // Use the macro to redirect stdout and capture output
    FOSSIL_MOCK_REDIRECT_STDOUT(buffer, sizeof(buffer), MOCK_FUNC_CALL(mock_function_redirection));

    // Test cases
    FOSSIL_TEST_ASSUME(strcmp(buffer, "Testing macro redirection!") == 0, "Captured output should match expected output");
} // end case

FOSSIL_TEST(cpp_mock_io_compare_output_macro) {
    // Captured and expected outputs
    const char *captured = "Macro comparison test!";
    const char *expected = "Macro comparison test!";

    // Use the macro to compare outputs
    bool result = FOSSIL_MOCK_COMPARE_OUTPUT(captured, expected);

    // Test cases
    FOSSIL_TEST_ASSUME(result == true, "Captured output should match expected output using macro");
} // end case

// * * * * * * * * * * * * * * * * * * * * * * * *
// * Fossil Logic Test Pool
// * * * * * * * * * * * * * * * * * * * * * * * *
FOSSIL_TEST_GROUP(cpp_mock_test_cases) {
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_call_list_initialization);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_call_list_addition);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_call_list_destruction);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_function_creation);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_alias_creation);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_struct_creation);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_call_list_type_handling);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_call_list_edge_cases);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_call_list_large_arguments);

    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_macro_initialization);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_macro_addition);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_macro_destruction);

    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_io_capture_output);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_io_compare_output);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_io_redirect_stdout_macro);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_io_compare_output_macro);
    FOSSIL_ADD_TEST(cpp_mock_suite, cpp_mock_io_compare_output);

    FOSSIL_ADD_SUITE(cpp_mock_suite);
} // end of group

What are your feelings

Updated on August 19, 2026