Fossil Mock

Table Of Contents

The Fossil Mock subsystem provides a flexible and extensible foundation for capturing, inspecting, and validating function behavior within the Fossil Testing Framework. Built around the Pizza-type metadata system, the mock layer allows developers to represent arguments, attributes, and values using structured, strongly typed components. This gives the framework a uniform language for introspection, enabling richer reporting, enhanced debugging capabilities, and compatibility with higher-level features such as Truthful Intelligent Mocking (TIM), planned for future releases.

At the heart of the subsystem is a lightweight mock-call recording engine that stores all invocations in a chainable call list. Each entry captures the function name, a Pizza-typed argument array, and invocation metadata. This design makes it possible to observe how code paths behave at runtime, verify expected interactions, and easily print or analyze recorded calls. Supporting utilities such as captured-output comparison further expand the mock framework’s testing capabilities, enabling tests to validate both behavioral side effects and emitted console output without intrusive instrumentation.

The framework also provides a suite of ergonomic public macros—ranging from function and struct mock generators to wrappers for initialization, recording, printing, and validation. These macros standardize mock creation and ensure portability across platforms, hiding implementation complexity behind a clean and predictable API. As the subsystem evolves toward TIM integration, these abstractions will become the bridge for intelligent behavior modeling, automated inference of expected values, and more expressive test diagnostics in Fossil Test.

PUBLIC INTERFACE #

#ifndef FOSSIL_MOCK_H
#define FOSSIL_MOCK_H

#include "common.h"

#ifdef __cplusplus
extern "C" {
#endif

// TODO: Upgrade to have Truthful Intelligent Mocking (TIM) capabilities

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

// --- Pizza Data Types ---
typedef enum {
    FOSSIL_MOCK_PIZZA_TYPE_I8,
    FOSSIL_MOCK_PIZZA_TYPE_I16,
    FOSSIL_MOCK_PIZZA_TYPE_I32,
    FOSSIL_MOCK_PIZZA_TYPE_I64,
    FOSSIL_MOCK_PIZZA_TYPE_U8,
    FOSSIL_MOCK_PIZZA_TYPE_U16,
    FOSSIL_MOCK_PIZZA_TYPE_U32,
    FOSSIL_MOCK_PIZZA_TYPE_U64,
    FOSSIL_MOCK_PIZZA_TYPE_HEX,
    FOSSIL_MOCK_PIZZA_TYPE_OCTAL,
    FOSSIL_MOCK_PIZZA_TYPE_FLOAT,
    FOSSIL_MOCK_PIZZA_TYPE_DOUBLE,
    FOSSIL_MOCK_PIZZA_TYPE_WSTR,
    FOSSIL_MOCK_PIZZA_TYPE_CSTR,
    FOSSIL_MOCK_PIZZA_TYPE_CCHAR,
    FOSSIL_MOCK_PIZZA_TYPE_WCHAR,
    FOSSIL_MOCK_PIZZA_TYPE_BOOL,
    FOSSIL_MOCK_PIZZA_TYPE_SIZE,
    FOSSIL_MOCK_PIZZA_TYPE_ANY
} fossil_mock_pizza_type_t;

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

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

typedef struct {
    fossil_mock_pizza_type_t type;
    fossil_mock_pizza_value_t value;
    fossil_mock_pizza_attribute_t attribute;
} fossil_mock_pizza_t;

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

typedef struct fossil_mock_call_t {
    char *function_name;
    fossil_mock_pizza_t *arguments; // Use pizza type for arguments
    int num_args;
    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_calllist_t;

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

/**
 * Initializes a fossil_mock_calllist_t.
 * 
 * @param list The fossil_mock_calllist_t to initialize.
 */
FOSSIL_PIZZA_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_PIZZA_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_PIZZA_API void fossil_mock_add_call(fossil_mock_calllist_t *list, const char *function_name, fossil_mock_pizza_t *arguments, int num_args);

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

/**
 * 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_PIZZA_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_PIZZA_API bool fossil_mock_compare_output(const char *captured, const char *expected);

#ifdef __cplusplus
}
#endif

/**
 * @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) fossil_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) fossil_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) fossil_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) fossil_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.
 */
#ifdef _WIN32
#define _FOSSIL_MOCK_FUNC(return_type, name, ...) \
    __declspec(dllexport) return_type fossil_mockup_##name(__VA_ARGS__)
#else
#define _FOSSIL_MOCK_FUNC(return_type, name, ...) \
    return_type fossil_mockup_##name(__VA_ARGS__)
#endif

/**
 * @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) \
    typedef existing_type new_type; \
    new_type fossil_mockup_##new_type(void)

/**
 * @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.
 */
#ifdef __cplusplus
#define _FOSSIL_MOCK_STRUCT(name) \
    struct name
#else
#define _FOSSIL_MOCK_STRUCT(name) \
    typedef struct name
#endif

/**
 * @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_CAPTURE_OUTPUT(buffer, size, function) \
    fossil_mock_capture_output(buffer, size, function)

/**
 * @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_COMPARE_OUTPUT(captured, expected) \
    fossil_mock_compare_output(captured, expected)

// *****************************************************************************
// 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)

/**
 * @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)

#endif // FOSSIL_MOCK_FRAMEWORK_H

C SAMPLE #

// * * * * * * * * * * * * * * * * * * * * * * * *
// * 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) {
    pizza_io_printf("Hello, Fossil Logic!");
}

FOSSIL_MOCK_FUNC(void, mock_function_redirection, void) {
    pizza_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
    fossil_mock_calllist_t list;
    fossil_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
    fossil_mock_calllist_t list;
    fossil_mock_init(&list);

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

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

    fossil_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
    fossil_mock_calllist_t list;
    fossil_mock_init(&list);

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

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

    fossil_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");

    fossil_mock_destroy(&list);
} // end case

FOSSIL_TEST(c_mock_function_creation) {
    // Test cases
    FOSSIL_TEST_ASSUME(fossil_mockup_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
    fossil_mock_calllist_t list;
    fossil_mock_init(&list);

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

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

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

    // Add a mock call with the arguments
    fossil_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_PIZZA_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_PIZZA_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_PIZZA_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
    fossil_mock_destroy(&list);
} // end case

FOSSIL_TEST(c_mock_call_list_edge_cases) {
    // Initialize the mock call list
    fossil_mock_calllist_t list;
    fossil_mock_init(&list);

    // Add a call with no arguments
    fossil_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
    fossil_mock_destroy(&list);
} // end case

FOSSIL_TEST(c_mock_call_list_large_arguments) {
    // Initialize the mock call list
    fossil_mock_calllist_t list;
    fossil_mock_init(&list);

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

    // Add a mock call with the large number of arguments
    fossil_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
    fossil_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_pizza_t args[2];
    args[0].type = FOSSIL_MOCK_PIZZA_TYPE_CSTR;
    args[0].value.data = pizza_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = pizza_io_cstr_dup("arg1_name");
    args[0].attribute.description = pizza_io_cstr_dup("First argument");
    args[0].attribute.id = pizza_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_PIZZA_TYPE_CSTR;
    args[1].value.data = pizza_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = pizza_io_cstr_dup("arg2_name");
    args[1].attribute.description = pizza_io_cstr_dup("Second argument");
    args[1].attribute.id = pizza_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_pizza_t args[2];
    args[0].type = FOSSIL_MOCK_PIZZA_TYPE_CSTR;
    args[0].value.data = pizza_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = pizza_io_cstr_dup("arg1_name");
    args[0].attribute.description = pizza_io_cstr_dup("First argument");
    args[0].attribute.id = pizza_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_PIZZA_TYPE_CSTR;
    args[1].value.data = pizza_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = pizza_io_cstr_dup("arg2_name");
    args[1].attribute.description = pizza_io_cstr_dup("Second argument");
    args[1].attribute.id = pizza_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), fossil_mockup_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_TEST_ADD(c_mock_suite, c_mock_call_list_initialization);
    FOSSIL_TEST_ADD(c_mock_suite, c_mock_call_list_addition);
    FOSSIL_TEST_ADD(c_mock_suite, c_mock_call_list_destruction);
    FOSSIL_TEST_ADD(c_mock_suite, c_mock_function_creation);
    FOSSIL_TEST_ADD(c_mock_suite, c_mock_alias_creation);
    FOSSIL_TEST_ADD(c_mock_suite, c_mock_struct_creation);
    FOSSIL_TEST_ADD(c_mock_suite, c_mock_call_list_type_handling);
    FOSSIL_TEST_ADD(c_mock_suite, c_mock_call_list_edge_cases);
    FOSSIL_TEST_ADD(c_mock_suite, c_mock_call_list_large_arguments);

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

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

    FOSSIL_TEST_REGISTER(c_mock_suite);
} // end of group

C++ SAMPLE #

// * * * * * * * * * * * * * * * * * * * * * * * *
// * 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) {
    pizza_io_printf("Hello, Fossil Logic!");
}

FOSSIL_MOCK_FUNC(void, mock_function_redirection, void) {
    pizza_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;
    fossil_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;
    fossil_mock_init(&list);

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

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

    fossil_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;
    fossil_mock_init(&list);

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

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

    fossil_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");

    fossil_mock_destroy(&list);
} // end case

FOSSIL_TEST(cpp_mock_function_creation) {
    // Test cases
    FOSSIL_TEST_ASSUME(fossil_mockup_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;
    fossil_mock_init(&list);

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

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

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

    // Add a mock call with the arguments
    fossil_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_PIZZA_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_PIZZA_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_PIZZA_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
    fossil_mock_destroy(&list);
} // end case

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

    // Add a call with no arguments
    fossil_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
    fossil_mock_destroy(&list);
} // end case

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

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

    // Add a mock call with the large number of arguments
    fossil_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
    fossil_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_pizza_t args[2];
    args[0].type = FOSSIL_MOCK_PIZZA_TYPE_CSTR;
    args[0].value.data = pizza_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = pizza_io_cstr_dup("arg1_name");
    args[0].attribute.description = pizza_io_cstr_dup("First argument");
    args[0].attribute.id = pizza_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_PIZZA_TYPE_CSTR;
    args[1].value.data = pizza_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = pizza_io_cstr_dup("arg2_name");
    args[1].attribute.description = pizza_io_cstr_dup("Second argument");
    args[1].attribute.id = pizza_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_pizza_t args[2];
    args[0].type = FOSSIL_MOCK_PIZZA_TYPE_CSTR;
    args[0].value.data = pizza_io_cstr_dup("arg1");
    args[0].value.mutable_flag = false;
    args[0].attribute.name = pizza_io_cstr_dup("arg1_name");
    args[0].attribute.description = pizza_io_cstr_dup("First argument");
    args[0].attribute.id = pizza_io_cstr_dup("1");

    args[1].type = FOSSIL_MOCK_PIZZA_TYPE_CSTR;
    args[1].value.data = pizza_io_cstr_dup("arg2");
    args[1].value.mutable_flag = false;
    args[1].attribute.name = pizza_io_cstr_dup("arg2_name");
    args[1].attribute.description = pizza_io_cstr_dup("Second argument");
    args[1].attribute.id = pizza_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), fossil_mockup_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), 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(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_TEST_ADD(cpp_mock_suite, cpp_mock_call_list_initialization);
    FOSSIL_TEST_ADD(cpp_mock_suite, cpp_mock_call_list_addition);
    FOSSIL_TEST_ADD(cpp_mock_suite, cpp_mock_call_list_destruction);
    FOSSIL_TEST_ADD(cpp_mock_suite, cpp_mock_function_creation);
    FOSSIL_TEST_ADD(cpp_mock_suite, cpp_mock_alias_creation);
    FOSSIL_TEST_ADD(cpp_mock_suite, cpp_mock_struct_creation);
    FOSSIL_TEST_ADD(cpp_mock_suite, cpp_mock_call_list_type_handling);
    FOSSIL_TEST_ADD(cpp_mock_suite, cpp_mock_call_list_edge_cases);
    FOSSIL_TEST_ADD(cpp_mock_suite, cpp_mock_call_list_large_arguments);

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

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

    FOSSIL_TEST_REGISTER(cpp_mock_suite);
} // end of group

What are your feelings

Updated on December 12, 2025