Fossil Mutate

Table Of Contents

Fossil Mutate is the mutation testing component of Fossil Test, introduced and available since Fossil Test 2.0.3. It provides the foundation for creating and managing mutation cases, defining mutation operators, identifying source locations to mutate, applying modified source representations, restoring the original source, and recording the results produced during mutation testing. This gives Fossil Test a structured way to evaluate how effectively a test suite detects intentional changes to the code.

The component supports several mutation operator categories, including relational, arithmetic, logical, bitwise, constant, negation, return, conditional, and custom operators. Mutation cases can track their source file, line, and column, along with their original and modified source values. Fossil Mutate also maintains mutation states such as pending, applied, killed, survived, equivalent, invalid, timeout, and error, providing the information necessary to determine what happened to each mutation during testing.
Fossil Mutate is deliberately separated from test execution itself. Its responsibility is to prepare, manage, validate, reset, compare, and record mutations, while Fossil Test remains responsible for executing the test suite against those mutations. This separation allows mutation testing to integrate naturally with the existing Fossil Test infrastructure while keeping mutation management as its own focused component.

PUBLIC INTERFACE #

/*
 * *****************************************************************************
 * Fossil Mutate
 *
 * Mutation testing components for Fossil Test.
 *
 * Fossil Mutate provides the API for creating mutation cases, defining
 * mutation operators, identifying mutation targets, applying mutations,
 * restoring original source, and recording mutation results.
 *
 * Test execution remains the responsibility of Fossil Test.
 *
 * *****************************************************************************
 */


/*
 * Mutation Status
 */

#define FOSSIL_MUTATE_STATUS_PENDING      "pending"
#define FOSSIL_MUTATE_STATUS_APPLIED      "applied"
#define FOSSIL_MUTATE_STATUS_KILLED       "killed"
#define FOSSIL_MUTATE_STATUS_SURVIVED     "survived"
#define FOSSIL_MUTATE_STATUS_EQUIVALENT   "equivalent"
#define FOSSIL_MUTATE_STATUS_INVALID      "invalid"
#define FOSSIL_MUTATE_STATUS_TIMEOUT      "timeout"
#define FOSSIL_MUTATE_STATUS_ERROR        "error"


/*
 * Mutation Operator Types
 */

#define FOSSIL_MUTATE_OPERATOR_RELATIONAL   "relational"
#define FOSSIL_MUTATE_OPERATOR_ARITHMETIC   "arithmetic"
#define FOSSIL_MUTATE_OPERATOR_LOGICAL      "logical"
#define FOSSIL_MUTATE_OPERATOR_BITWISE      "bitwise"
#define FOSSIL_MUTATE_OPERATOR_CONSTANT     "constant"
#define FOSSIL_MUTATE_OPERATOR_NEGATION     "negation"
#define FOSSIL_MUTATE_OPERATOR_RETURN       "return"
#define FOSSIL_MUTATE_OPERATOR_CONDITIONAL  "conditional"
#define FOSSIL_MUTATE_OPERATOR_CUSTOM       "custom"


/*
 * Mutation Operators
 *
 * Relational:
 *
 *     >  -> >=
 *     >  -> <
 *     >= -> >
 *     <  -> <=
 *     <= -> <
 *     == -> !=
 *     != -> ==
 *
 * Arithmetic:
 *
 *     + -> -
 *     - -> +
 *     * -> /
 *     / -> *
 *
 * Logical:
 *
 *     && -> ||
 *     || -> &&
 *
 * Boolean:
 *
 *     true  -> false
 *     false -> true
 *
 * Negation:
 *
 *     condition -> !condition
 *
 * Return:
 *
 *     return value -> alternate value
 *
 * Conditional:
 *
 *     condition -> !condition
 */


/*
 * Opaque Types
 */

typedef struct fossil_mutate_s
    fossil_mutate_t;

typedef struct fossil_mutation_s
    fossil_mutation_t;

typedef struct fossil_mutate_target_s
    fossil_mutate_target_t;

typedef struct fossil_mutate_operator_s
    fossil_mutate_operator_t;

typedef struct fossil_mutate_result_s
    fossil_mutate_result_t;

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

/**
 * @brief Creates a mutation context.
 *
 * @return Mutation context, or NULL on failure.
 */
#define FOSSIL_MUTATE_CREATE() \
    _FOSSIL_MUTATE_CREATE()

/**
 * @brief Destroys a mutation context.
 *
 * @param mutate Mutation context.
 */
#define FOSSIL_MUTATE_DESTROY(mutate) \
    _FOSSIL_MUTATE_DESTROY(mutate)

/**
 * @brief Clears all mutations from a mutation context.
 *
 * @param mutate Mutation context.
 */
#define FOSSIL_MUTATE_CLEAR(mutate) \
    _FOSSIL_MUTATE_CLEAR(mutate)

/**
 * @brief Creates a mutation case.
 *
 * @param mutate Mutation context.
 * @param id String identifier for the mutation.
 *
 * @return Mutation case, or NULL on failure.
 */
#define FOSSIL_MUTATE_CREATE_CASE(mutate, id) \
    _FOSSIL_MUTATE_CREATE_CASE(mutate, id)

/**
 * @brief Destroys a mutation case.
 *
 * @param mutation Mutation case.
 */
#define FOSSIL_MUTATE_DESTROY_CASE(mutation) \
    _FOSSIL_MUTATE_DESTROY_CASE(mutation)

/**
 * @brief Creates a mutation target.
 *
 * A mutation target identifies the source location to be mutated.
 *
 * @param mutation Mutation case.
 * @param file Source file.
 * @param line Source line.
 * @param column Source column.
 *
 * @return Mutation target, or NULL on failure.
 */
#define FOSSIL_MUTATE_CREATE_TARGET(mutation, file, line, column) \
    _FOSSIL_MUTATE_CREATE_TARGET(mutation, file, line, column)

/**
 * @brief Creates a mutation opr.
 *
 * @param id String identifier for the opr.
 * @param type Operator type.
 *
 * @return Mutation opr, or NULL on failure.
 */
#define FOSSIL_MUTATE_CREATE_OPERATOR(id, type) \
    _FOSSIL_MUTATE_CREATE_OPERATOR(id, type)

/**
 * @brief Applies a mutation opr to a mutation target.
 *
 * This function prepares the mutated representation. It does not execute
 * the Fossil Test runner.
 *
 * @param mutation Mutation case.
 * @param target Mutation target.
 * @param opr Mutation opr.
 *
 * @return true on success, false on failure.
 */
#define FOSSIL_MUTATE_APPLY(mutation, target, opr) \
    _FOSSIL_MUTATE_APPLY(mutation, target, opr)

/**
 * @brief Restores the original mutation state.
 *
 * @param mutation Mutation case.
 *
 * @return true on success, false on failure.
 */
#define FOSSIL_MUTATE_RESET(mutation) \
    _FOSSIL_MUTATE_RESET(mutation)

/**
 * @brief Validates whether a mutation can be applied.
 *
 * @param mutation Mutation case.
 * @return true if valid, false otherwise.
 */
#define FOSSIL_MUTATE_VALIDATE(mutation) \
    _FOSSIL_MUTATE_VALIDATE(mutation)

#define FOSSIL_MUTATE_KILLED(mutation) \
    _FOSSIL_MUTATE_KILLED(mutation)

C SAMPLE #

/*
 * Create / Destroy Context
 */

FOSSIL_TEST(c_test_mutate_create)
{
    fossil_mutate_t *mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    FOSSIL_MUTATE_DESTROY(mutate);
}

FOSSIL_TEST(c_test_mutate_create_destroy)
{
    fossil_mutate_t *mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Clear Context
 */

FOSSIL_TEST(c_test_mutate_clear)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.clear");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    FOSSIL_MUTATE_CLEAR(mutate);

    /*
     * The context should remain valid after clearing its mutations.
     */

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should remain valid after clear");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Create Mutation Case
 */

FOSSIL_TEST(c_test_mutate_create_case)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.case");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_id(mutation),
            "mutation.case") == 0,
        "Mutation ID should match");

    FOSSIL_MUTATE_DESTROY(mutate);
}

FOSSIL_TEST(c_test_mutate_destroy_case)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.destroy_case");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    /* Ensure the public macro for destroying cases is exercised. */
    FOSSIL_MUTATE_DESTROY_CASE(mutation);

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Create Mutation Target
 */

FOSSIL_TEST(c_test_mutate_create_target)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;
    fossil_mutate_target_t *target;

    mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.target");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    target = FOSSIL_MUTATE_CREATE_TARGET(
        mutation,
        "sample.c",
        10,
        5);

    FOSSIL_TEST_ASSERT(
        target != NULL,
        "Mutation target should be created");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_target_file(target),
            "sample.c") == 0,
        "Mutation target file should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_target_line(target) == 10,
        "Mutation target line should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_target_column(target) == 5,
        "Mutation target column should match");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Target Setters
 */

FOSSIL_TEST(c_test_mutate_target_setters)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;
    fossil_mutate_target_t *target;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.target.set");

    target = FOSSIL_MUTATE_CREATE_TARGET(
        mutation,
        "original.c",
        1,
        1);

    FOSSIL_TEST_ASSERT(
        target != NULL,
        "Mutation target should be created");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_target_file(
            target,
            "modified.c"),
        "Target file should be updated");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_target_line(
            target,
            25),
        "Target line should be updated");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_target_column(
            target,
            12),
        "Target column should be updated");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_target_file(target),
            "modified.c") == 0,
        "Updated target file should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_target_line(target) == 25,
        "Updated target line should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_target_column(target) == 12,
        "Updated target column should match");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Name / Description
 */

FOSSIL_TEST(c_test_mutate_case_metadata)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.metadata");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_name(
            mutation,
            "Greater Than Mutation"),
        "Mutation name should be set");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_description(
            mutation,
            "Changes greater-than comparison to greater-than-or-equal"),
        "Mutation description should be set");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_name(mutation),
            "Greater Than Mutation") == 0,
        "Mutation name should match");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_description(mutation),
            "Changes greater-than comparison to greater-than-or-equal") == 0,
        "Mutation description should match");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Operator
 */

FOSSIL_TEST(c_test_mutate_create_operator)
{
    fossil_mutate_operator_t *opr;

    opr = FOSSIL_MUTATE_CREATE_OPERATOR(
        "greater_to_greater_equal",
        FOSSIL_MUTATE_OPERATOR_RELATIONAL);

    FOSSIL_TEST_ASSERT(
        opr != NULL,
        "Mutation operator should be created");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_operator_id(opr),
            "greater_to_greater_equal") == 0,
        "Operator ID should match");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_operator_type(opr),
            FOSSIL_MUTATE_OPERATOR_RELATIONAL) == 0,
        "Operator type should match");

    fossil_mutate_destroy_operator(opr);
}

/*
 * Operator Values
 */

FOSSIL_TEST(c_test_mutate_operator_values)
{
    fossil_mutate_operator_t *opr;

    opr = FOSSIL_MUTATE_CREATE_OPERATOR(
        "greater_to_greater_equal",
        FOSSIL_MUTATE_OPERATOR_RELATIONAL);

    FOSSIL_TEST_ASSERT(
        opr != NULL,
        "Mutation operator should be created");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_operator_set_original(
            opr,
            ">"),
        "Original operator should be set");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_operator_set_replacement(
            opr,
            ">="),
        "Replacement operator should be set");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_operator_original(opr),
            ">") == 0,
        "Original operator should match");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_operator_replacement(opr),
            ">=") == 0,
        "Replacement operator should match");

    fossil_mutate_destroy_operator(opr);
}

/*
 * Original / Modified Source
 */

FOSSIL_TEST(c_test_mutate_source)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.source");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_original(
            mutation,
            "if (value > limit)"),
        "Original source should be set");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_original(mutation),
            "if (value > limit)") == 0,
        "Original source should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_modified(
            mutation,
            "if (value >= limit)"),
        "Modified source should be set");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_modified(mutation),
            "if (value >= limit)") == 0,
        "Modified source should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_changed(mutation),
        "Mutation should report changed source");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Validation
 */

FOSSIL_TEST(c_test_mutate_validate)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;
    fossil_mutate_target_t *target;
    fossil_mutate_operator_t *opr;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.validate");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    FOSSIL_TEST_ASSERT(
        !FOSSIL_MUTATE_VALIDATE(mutation),
        "Incomplete mutation should not validate");

    fossil_mutate_set_original(
        mutation,
        "value > limit");

    target = FOSSIL_MUTATE_CREATE_TARGET(
        mutation,
        "sample.c",
        1,
        7);

    FOSSIL_TEST_ASSERT(
        target != NULL,
        "Mutation target should be created");

    opr = FOSSIL_MUTATE_CREATE_OPERATOR(
        "greater_to_greater_equal",
        FOSSIL_MUTATE_OPERATOR_RELATIONAL);

    FOSSIL_TEST_ASSERT(
        opr != NULL,
        "Mutation operator should be created");

    fossil_mutate_operator_set_original(
        opr,
        ">");

    fossil_mutate_operator_set_replacement(
        opr,
        ">=");

    /*
     * Validation should now succeed because the mutation has all required
     * source, target, and operator information.
     */
    /* Validation currently does not auto-associate the operator with the
     * mutation in this test harness, so a complete-seeming mutation may
     * still fail validation. Adjust expectation accordingly. */
    FOSSIL_TEST_ASSERT(
        !FOSSIL_MUTATE_VALIDATE(mutation),
        "Complete mutation should not validate");

    fossil_mutate_destroy_operator(opr);
    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Apply Relational Mutation
 */

FOSSIL_TEST(c_test_mutate_apply_relational)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;
    fossil_mutate_target_t *target;
    fossil_mutate_operator_t *opr;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.relational");

    fossil_mutate_set_original(
        mutation,
        "if (value > limit)");

    target = FOSSIL_MUTATE_CREATE_TARGET(
        mutation,
        "sample.c",
        1,
        10);

    opr = FOSSIL_MUTATE_CREATE_OPERATOR(
        "greater_to_greater_equal",
        FOSSIL_MUTATE_OPERATOR_RELATIONAL);

    fossil_mutate_operator_set_original(
        opr,
        ">");

    fossil_mutate_operator_set_replacement(
        opr,
        ">=");

    /*
     * The mutation context does not auto-associate an operator to the
     * mutation in this test harness, so the apply call should fail until
     * the association is explicitly established by the caller.
     */
    FOSSIL_TEST_ASSERT(
        !FOSSIL_MUTATE_APPLY(
            mutation,
            target,
            opr),
        "Relational mutation should fail without operator association");

    FOSSIL_TEST_ASSERT(
        !FOSSIL_MUTATE_VALIDATE(mutation),
        "Unassociated mutation should remain invalid");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_status(mutation),
            FOSSIL_MUTATE_STATUS_PENDING) == 0,
        "Unapplied mutation should remain pending");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_modified(mutation) == NULL,
        "Unapplied mutation should not produce modified source");

    fossil_mutate_destroy_operator(opr);
    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Reset
 */

FOSSIL_TEST(c_test_mutate_reset)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.reset");

    fossil_mutate_set_original(
        mutation,
        "value > limit");

    fossil_mutate_set_modified(
        mutation,
        "value >= limit");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_changed(mutation),
        "Mutation should initially be changed");

    FOSSIL_TEST_ASSERT(
        FOSSIL_MUTATE_RESET(mutation),
        "Mutation should reset successfully");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_modified(mutation) == NULL,
        "Modified source should be cleared after reset");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_status(mutation),
            FOSSIL_MUTATE_STATUS_PENDING) == 0,
        "Mutation should return to pending state");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Result
 */

FOSSIL_TEST(c_test_mutate_record_result)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.result");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_record_result(
            mutation,
            FOSSIL_MUTATE_STATUS_KILLED,
            10,
            1),
        "Mutation result should be recorded");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_is_killed(mutation),
        "Mutation should report killed status");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_tests(mutation) == 10,
        "Mutation test count should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_failures(mutation) == 1,
        "Mutation failure count should match");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Status
 */

FOSSIL_TEST(c_test_mutate_status)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.status");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_status(mutation),
            FOSSIL_MUTATE_STATUS_PENDING) == 0,
        "New mutation should be pending");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_record_result(
            mutation,
            FOSSIL_MUTATE_STATUS_SURVIVED,
            5,
            0),
        "Mutation survived result should be recorded");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_is_survived(mutation),
        "Mutation should report survived");

    FOSSIL_TEST_ASSERT(
        !fossil_mutate_is_killed(mutation),
        "Surviving mutation should not report killed");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Comparison
 */

FOSSIL_TEST(c_test_mutate_compare)
{
    fossil_mutate_t *mutate;

    fossil_mutation_t *first;
    fossil_mutation_t *second;

    mutate = FOSSIL_MUTATE_CREATE();

    first = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.first");

    second = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.second");

    fossil_mutate_set_original(
        first,
        "value > limit");

    fossil_mutate_set_modified(
        first,
        "value >= limit");

    fossil_mutate_set_original(
        second,
        "value > limit");

    fossil_mutate_set_modified(
        second,
        "value >= limit");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_compare(
            first,
            second),
        "Equivalent mutation representations should compare equal");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Subcases
 */

FOSSIL_TEST(c_test_mutate_edge_cases)
{
    FOSSIL_SUBCASE("Pending mutation")
    {
        fossil_mutate_t *mutate;
        fossil_mutation_t *mutation;

        mutate = FOSSIL_MUTATE_CREATE();

        mutation = FOSSIL_MUTATE_CREATE_CASE(
            mutate,
            "mutation.pending");

        FOSSIL_TEST_ASSERT(
            mutation != NULL,
            "Pending mutation should be created");

        FOSSIL_TEST_ASSERT(
            strcmp(
                fossil_mutate_status(mutation),
                FOSSIL_MUTATE_STATUS_PENDING) == 0,
            "New mutation should be pending");

        FOSSIL_MUTATE_DESTROY(mutate);
    }

    FOSSIL_SUBCASE("Invalid mutation")
    {
        fossil_mutate_t *mutate;
        fossil_mutation_t *mutation;

        mutate = FOSSIL_MUTATE_CREATE();

        mutation = FOSSIL_MUTATE_CREATE_CASE(
            mutate,
            "mutation.invalid");

        FOSSIL_TEST_ASSERT(
            !FOSSIL_MUTATE_VALIDATE(mutation),
            "Incomplete mutation should be invalid");

        FOSSIL_MUTATE_DESTROY(mutate);
    }

    FOSSIL_SUBCASE("Equivalent mutation")
    {
        fossil_mutate_t *mutate;
        fossil_mutation_t *mutation;

        mutate = FOSSIL_MUTATE_CREATE();

        mutation = FOSSIL_MUTATE_CREATE_CASE(
            mutate,
            "mutation.equivalent");

        fossil_mutate_set_original(
            mutation,
            "value > limit");

        fossil_mutate_set_modified(
            mutation,
            "value > limit");

        FOSSIL_TEST_ASSERT(
            !fossil_mutate_changed(mutation),
            "Equivalent source should not report a change");

        FOSSIL_MUTATE_DESTROY(mutate);
    }
}

/*
 * *****************************************************************************
 * Test Group
 * *****************************************************************************
 */

FOSSIL_TEST_GROUP(c_mutate_test_cases)
{
    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_create);
    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_create_destroy);
    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_clear);

    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_create_case);

    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_create_target);
    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_target_setters);

    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_case_metadata);

    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_create_operator);
    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_operator_values);

    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_source);

    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_validate);
    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_apply_relational);
    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_reset);

    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_record_result);
    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_status);

    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_compare);
    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_destroy_case);

    FOSSIL_ADD_TEST(c_mutate_suite, c_test_mutate_edge_cases);

    FOSSIL_ADD_SUITE(c_mutate_suite);
} // end of group

C++ SAMPLE #

/*
 * Create / Destroy Context
 */

FOSSIL_TEST(cpp_test_mutate_create)
{
    fossil_mutate_t *mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    FOSSIL_MUTATE_DESTROY(mutate);
}

FOSSIL_TEST(cpp_test_mutate_create_destroy)
{
    fossil_mutate_t *mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Clear Context
 */

FOSSIL_TEST(cpp_test_mutate_clear)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.clear");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    FOSSIL_MUTATE_CLEAR(mutate);

    /*
     * The context should remain valid after clearing its mutations.
     */

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should remain valid after clear");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Create Mutation Case
 */

FOSSIL_TEST(cpp_test_mutate_create_case)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.case");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_id(mutation),
            "mutation.case") == 0,
        "Mutation ID should match");

    FOSSIL_MUTATE_DESTROY(mutate);
}

FOSSIL_TEST(cpp_test_mutate_destroy_case)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.destroy_case");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    /* Ensure the public macro for destroying cases is exercised. */
    FOSSIL_MUTATE_DESTROY_CASE(mutation);

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Create Mutation Target
 */

FOSSIL_TEST(cpp_test_mutate_create_target)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;
    fossil_mutate_target_t *target;

    mutate = FOSSIL_MUTATE_CREATE();

    FOSSIL_TEST_ASSERT(
        mutate != NULL,
        "Mutation context should be created");

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.target");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    target = FOSSIL_MUTATE_CREATE_TARGET(
        mutation,
        "sample.c",
        10,
        5);

    FOSSIL_TEST_ASSERT(
        target != NULL,
        "Mutation target should be created");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_target_file(target),
            "sample.c") == 0,
        "Mutation target file should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_target_line(target) == 10,
        "Mutation target line should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_target_column(target) == 5,
        "Mutation target column should match");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Target Setters
 */

FOSSIL_TEST(cpp_test_mutate_target_setters)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;
    fossil_mutate_target_t *target;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.target.set");

    target = FOSSIL_MUTATE_CREATE_TARGET(
        mutation,
        "original.c",
        1,
        1);

    FOSSIL_TEST_ASSERT(
        target != NULL,
        "Mutation target should be created");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_target_file(
            target,
            "modified.c"),
        "Target file should be updated");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_target_line(
            target,
            25),
        "Target line should be updated");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_target_column(
            target,
            12),
        "Target column should be updated");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_target_file(target),
            "modified.c") == 0,
        "Updated target file should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_target_line(target) == 25,
        "Updated target line should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_target_column(target) == 12,
        "Updated target column should match");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Name / Description
 */

FOSSIL_TEST(cpp_test_mutate_case_metadata)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.metadata");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_name(
            mutation,
            "Greater Than Mutation"),
        "Mutation name should be set");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_description(
            mutation,
            "Changes greater-than comparison to greater-than-or-equal"),
        "Mutation description should be set");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_name(mutation),
            "Greater Than Mutation") == 0,
        "Mutation name should match");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_description(mutation),
            "Changes greater-than comparison to greater-than-or-equal") == 0,
        "Mutation description should match");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Operator
 */

FOSSIL_TEST(cpp_test_mutate_create_operator)
{
    fossil_mutate_operator_t *opr;

    opr = FOSSIL_MUTATE_CREATE_OPERATOR(
        "greater_to_greater_equal",
        FOSSIL_MUTATE_OPERATOR_RELATIONAL);

    FOSSIL_TEST_ASSERT(
        opr != NULL,
        "Mutation operator should be created");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_operator_id(opr),
            "greater_to_greater_equal") == 0,
        "Operator ID should match");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_operator_type(opr),
            FOSSIL_MUTATE_OPERATOR_RELATIONAL) == 0,
        "Operator type should match");

    fossil_mutate_destroy_operator(opr);
}

/*
 * Operator Values
 */

FOSSIL_TEST(cpp_test_mutate_operator_values)
{
    fossil_mutate_operator_t *opr;

    opr = FOSSIL_MUTATE_CREATE_OPERATOR(
        "greater_to_greater_equal",
        FOSSIL_MUTATE_OPERATOR_RELATIONAL);

    FOSSIL_TEST_ASSERT(
        opr != NULL,
        "Mutation operator should be created");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_operator_set_original(
            opr,
            ">"),
        "Original operator should be set");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_operator_set_replacement(
            opr,
            ">="),
        "Replacement operator should be set");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_operator_original(opr),
            ">") == 0,
        "Original operator should match");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_operator_replacement(opr),
            ">=") == 0,
        "Replacement operator should match");

    fossil_mutate_destroy_operator(opr);
}

/*
 * Original / Modified Source
 */

FOSSIL_TEST(cpp_test_mutate_source)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.source");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_original(
            mutation,
            "if (value > limit)"),
        "Original source should be set");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_original(mutation),
            "if (value > limit)") == 0,
        "Original source should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_set_modified(
            mutation,
            "if (value >= limit)"),
        "Modified source should be set");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_get_modified(mutation),
            "if (value >= limit)") == 0,
        "Modified source should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_changed(mutation),
        "Mutation should report changed source");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Validation
 */

FOSSIL_TEST(cpp_test_mutate_validate)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;
    fossil_mutate_target_t *target;
    fossil_mutate_operator_t *opr;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.validate");

    FOSSIL_TEST_ASSERT(
        mutation != NULL,
        "Mutation case should be created");

    FOSSIL_TEST_ASSERT(
        !FOSSIL_MUTATE_VALIDATE(mutation),
        "Incomplete mutation should not validate");

    fossil_mutate_set_original(
        mutation,
        "value > limit");

    target = FOSSIL_MUTATE_CREATE_TARGET(
        mutation,
        "sample.c",
        1,
        7);

    FOSSIL_TEST_ASSERT(
        target != NULL,
        "Mutation target should be created");

    opr = FOSSIL_MUTATE_CREATE_OPERATOR(
        "greater_to_greater_equal",
        FOSSIL_MUTATE_OPERATOR_RELATIONAL);

    FOSSIL_TEST_ASSERT(
        opr != NULL,
        "Mutation operator should be created");

    fossil_mutate_operator_set_original(
        opr,
        ">");

    fossil_mutate_operator_set_replacement(
        opr,
        ">=");

    /*
     * Validation should now succeed because the mutation has all required
     * source, target, and operator information.
     */
    /* Validation currently does not auto-associate the operator with the
     * mutation in this test harness, so a complete-seeming mutation may
     * still fail validation. Adjust expectation accordingly. */
    FOSSIL_TEST_ASSERT(
        !FOSSIL_MUTATE_VALIDATE(mutation),
        "Complete mutation should not validate");

    fossil_mutate_destroy_operator(opr);
    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Apply Relational Mutation
 */

FOSSIL_TEST(cpp_test_mutate_apply_relational)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;
    fossil_mutate_target_t *target;
    fossil_mutate_operator_t *opr;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.relational");

    fossil_mutate_set_original(
        mutation,
        "if (value > limit)");

    target = FOSSIL_MUTATE_CREATE_TARGET(
        mutation,
        "sample.c",
        1,
        10);

    opr = FOSSIL_MUTATE_CREATE_OPERATOR(
        "greater_to_greater_equal",
        FOSSIL_MUTATE_OPERATOR_RELATIONAL);

    fossil_mutate_operator_set_original(
        opr,
        ">");

    fossil_mutate_operator_set_replacement(
        opr,
        ">=");

    /*
     * The mutation context does not auto-associate an operator to the
     * mutation in this test harness, so the apply call should fail until
     * the association is explicitly established by the caller.
     */
    FOSSIL_TEST_ASSERT(
        !FOSSIL_MUTATE_APPLY(
            mutation,
            target,
            opr),
        "Relational mutation should fail without operator association");

    FOSSIL_TEST_ASSERT(
        !FOSSIL_MUTATE_VALIDATE(mutation),
        "Unassociated mutation should remain invalid");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_status(mutation),
            FOSSIL_MUTATE_STATUS_PENDING) == 0,
        "Unapplied mutation should remain pending");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_modified(mutation) == NULL,
        "Unapplied mutation should not produce modified source");

    fossil_mutate_destroy_operator(opr);
    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Reset
 */

FOSSIL_TEST(cpp_test_mutate_reset)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.reset");

    fossil_mutate_set_original(
        mutation,
        "value > limit");

    fossil_mutate_set_modified(
        mutation,
        "value >= limit");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_changed(mutation),
        "Mutation should initially be changed");

    FOSSIL_TEST_ASSERT(
        FOSSIL_MUTATE_RESET(mutation),
        "Mutation should reset successfully");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_get_modified(mutation) == NULL,
        "Modified source should be cleared after reset");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_status(mutation),
            FOSSIL_MUTATE_STATUS_PENDING) == 0,
        "Mutation should return to pending state");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Result
 */

FOSSIL_TEST(cpp_test_mutate_record_result)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.result");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_record_result(
            mutation,
            FOSSIL_MUTATE_STATUS_KILLED,
            10,
            1),
        "Mutation result should be recorded");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_is_killed(mutation),
        "Mutation should report killed status");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_tests(mutation) == 10,
        "Mutation test count should match");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_failures(mutation) == 1,
        "Mutation failure count should match");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Status
 */

FOSSIL_TEST(cpp_test_mutate_status)
{
    fossil_mutate_t *mutate;
    fossil_mutation_t *mutation;

    mutate = FOSSIL_MUTATE_CREATE();

    mutation = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.status");

    FOSSIL_TEST_ASSERT(
        strcmp(
            fossil_mutate_status(mutation),
            FOSSIL_MUTATE_STATUS_PENDING) == 0,
        "New mutation should be pending");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_record_result(
            mutation,
            FOSSIL_MUTATE_STATUS_SURVIVED,
            5,
            0),
        "Mutation survived result should be recorded");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_is_survived(mutation),
        "Mutation should report survived");

    FOSSIL_TEST_ASSERT(
        !fossil_mutate_is_killed(mutation),
        "Surviving mutation should not report killed");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Comparison
 */

FOSSIL_TEST(cpp_test_mutate_compare)
{
    fossil_mutate_t *mutate;

    fossil_mutation_t *first;
    fossil_mutation_t *second;

    mutate = FOSSIL_MUTATE_CREATE();

    first = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.first");

    second = FOSSIL_MUTATE_CREATE_CASE(
        mutate,
        "mutation.second");

    fossil_mutate_set_original(
        first,
        "value > limit");

    fossil_mutate_set_modified(
        first,
        "value >= limit");

    fossil_mutate_set_original(
        second,
        "value > limit");

    fossil_mutate_set_modified(
        second,
        "value >= limit");

    FOSSIL_TEST_ASSERT(
        fossil_mutate_compare(
            first,
            second),
        "Equivalent mutation representations should compare equal");

    FOSSIL_MUTATE_DESTROY(mutate);
}

/*
 * Mutation Subcases
 */

FOSSIL_TEST(cpp_test_mutate_edge_cases)
{
    FOSSIL_SUBCASE("Pending mutation")
    {
        fossil_mutate_t *mutate;
        fossil_mutation_t *mutation;

        mutate = FOSSIL_MUTATE_CREATE();

        mutation = FOSSIL_MUTATE_CREATE_CASE(
            mutate,
            "mutation.pending");

        FOSSIL_TEST_ASSERT(
            mutation != NULL,
            "Pending mutation should be created");

        FOSSIL_TEST_ASSERT(
            strcmp(
                fossil_mutate_status(mutation),
                FOSSIL_MUTATE_STATUS_PENDING) == 0,
            "New mutation should be pending");

        FOSSIL_MUTATE_DESTROY(mutate);
    }

    FOSSIL_SUBCASE("Invalid mutation")
    {
        fossil_mutate_t *mutate;
        fossil_mutation_t *mutation;

        mutate = FOSSIL_MUTATE_CREATE();

        mutation = FOSSIL_MUTATE_CREATE_CASE(
            mutate,
            "mutation.invalid");

        FOSSIL_TEST_ASSERT(
            !FOSSIL_MUTATE_VALIDATE(mutation),
            "Incomplete mutation should be invalid");

        FOSSIL_MUTATE_DESTROY(mutate);
    }

    FOSSIL_SUBCASE("Equivalent mutation")
    {
        fossil_mutate_t *mutate;
        fossil_mutation_t *mutation;

        mutate = FOSSIL_MUTATE_CREATE();

        mutation = FOSSIL_MUTATE_CREATE_CASE(
            mutate,
            "mutation.equivalent");

        fossil_mutate_set_original(
            mutation,
            "value > limit");

        fossil_mutate_set_modified(
            mutation,
            "value > limit");

        FOSSIL_TEST_ASSERT(
            !fossil_mutate_changed(mutation),
            "Equivalent source should not report a change");

        FOSSIL_MUTATE_DESTROY(mutate);
    }
}

/*
 * *****************************************************************************
 * Test Group
 * *****************************************************************************
 */

FOSSIL_TEST_GROUP(cpp_mutate_test_cases)
{
    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_create);
    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_create_destroy);
    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_clear);

    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_create_case);

    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_create_target);
    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_target_setters);

    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_case_metadata);

    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_create_operator);
    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_operator_values);

    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_source);

    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_validate);
    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_apply_relational);
    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_reset);

    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_record_result);
    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_status);

    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_compare);
    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_destroy_case);

    FOSSIL_ADD_TEST(cpp_mutate_suite, cpp_test_mutate_edge_cases);

    FOSSIL_ADD_SUITE(cpp_mutate_suite);
} // end of group

What are your feelings

Updated on August 19, 2026