Skip to content
Merged
4 changes: 2 additions & 2 deletions code/logic/fossil/test/mocking.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@
* @param existing_type The existing type to create an alias for.
*/
#define _FOSSIL_MOCK_ALIAS(new_type, existing_type) \
typedef existing_type fossil_mockup_##new_type##_type; \
fossil_mockup_##new_type##_type fossil_mockup_##new_type(void)
typedef existing_type new_type; \
new_type fossil_mockup_##new_type(void)

/**
* @def _FOSSIL_MOCK_STRUCT
Expand Down
2 changes: 1 addition & 1 deletion code/logic/fossil/test/testing.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ void fossil_test_run_all(fossil_test_env_t *env);
#define _FOSSIL_TEST_SKIP(test_name, message) \
test_name##_test_case.status = TEST_STATUS_SKIP; \
test_name##_test_case.failure_message = message; \
printf(FOSSIL_TEST_COLOR_YELLOW "SKIP: %s - %s\n" FOSSIL_TEST_COLOR_RESET, #test_name, message); \
printf(FOSSIL_TEST_COLOR_YELLOW "SKIPPED: %s - %s\n" FOSSIL_TEST_COLOR_RESET, #test_name, message); \

/**
* @brief Macro to define a test case.
Expand Down
64 changes: 64 additions & 0 deletions code/logic/marking.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ void assume_duration(double expected, double actual, double unit) {

// Marks a test case as timeout with a specified time and prints it to stderr.
void fossil_test_benchmark(char* duration_type, double expected, double actual) {
if (duration_type == NULL) {
printf("Error: duration_type is NULL\n");
return;
}

if (strcmp(duration_type, "minutes") == 0) {
assume_duration(expected, actual, 60.0);
} else if (strcmp(duration_type, "seconds") == 0) {
Expand All @@ -119,6 +124,16 @@ void fossil_test_benchmark(char* duration_type, double expected, double actual)
} // end of func

void fossil_benchmark_init(fossil_benchmark_t* benchmark, const char* name) {
if (benchmark == NULL) {
printf("Error: benchmark is NULL\n");
return;
}

if (name == NULL) {
printf("Error: name is NULL\n");
return;
}

benchmark->name = name;
benchmark->num_samples = 0;
benchmark->total_duration = 0.0;
Expand All @@ -128,13 +143,23 @@ void fossil_benchmark_init(fossil_benchmark_t* benchmark, const char* name) {
}

void fossil_benchmark_start(fossil_benchmark_t* benchmark) {
if (benchmark == NULL) {
printf("Error: benchmark is NULL\n");
return;
}

if (!benchmark->running) {
benchmark->start_time = clock();
benchmark->running = 1;
}
}

void fossil_benchmark_stop(fossil_benchmark_t* benchmark) {
if (benchmark == NULL) {
printf("Error: benchmark is NULL\n");
return;
}

if (benchmark->running) {
benchmark->end_time = clock();
double elapsed = ((double)(benchmark->end_time - benchmark->start_time)) / CLOCKS_PER_SEC;
Expand All @@ -151,29 +176,53 @@ void fossil_benchmark_stop(fossil_benchmark_t* benchmark) {
}

double fossil_benchmark_elapsed_seconds(const fossil_benchmark_t* benchmark) {
if (benchmark == NULL) {
printf("Error: benchmark is NULL\n");
return 0.0;
}
return benchmark->total_duration;
}

double fossil_benchmark_min_time(const fossil_benchmark_t* benchmark) {
if (benchmark == NULL) {
printf("Error: benchmark is NULL\n");
return 0.0;
}
return benchmark->min_duration;
}

double fossil_benchmark_max_time(const fossil_benchmark_t* benchmark) {
if (benchmark == NULL) {
printf("Error: benchmark is NULL\n");
return 0.0;
}
return benchmark->max_duration;
}

double fossil_benchmark_avg_time(const fossil_benchmark_t* benchmark) {
if (benchmark == NULL) {
printf("Error: benchmark is NULL\n");
return 0.0;
}
return benchmark->num_samples > 0 ? benchmark->total_duration / benchmark->num_samples : 0.0;
}

void fossil_benchmark_reset(fossil_benchmark_t* benchmark) {
if (benchmark == NULL) {
printf("Error: benchmark is NULL\n");
return;
}
benchmark->num_samples = 0;
benchmark->total_duration = 0.0;
benchmark->min_duration = DBL_MAX;
benchmark->max_duration = 0.0;
}

void fossil_benchmark_report(const fossil_benchmark_t* benchmark) {
if (benchmark == NULL) {
printf("Error: benchmark is NULL\n");
return;
}
printf("\033[1;36mBenchmark : %s\n", benchmark->name);
printf("\033[1;32mTotal Time: %.6f seconds\n", fossil_benchmark_elapsed_seconds(benchmark));
printf("\033[1;32mMin Time : %.6f seconds\n", fossil_benchmark_min_time(benchmark));
Expand All @@ -182,10 +231,25 @@ void fossil_benchmark_report(const fossil_benchmark_t* benchmark) {
}

void fossil_scoped_benchmark_init(scoped_benchmark_t* scoped_benchmark, fossil_benchmark_t* benchmark) {
if (scoped_benchmark == NULL) {
printf("Error: scoped_benchmark is NULL\n");
return;
}

if (benchmark == NULL) {
printf("Error: benchmark is NULL\n");
return;
}

scoped_benchmark->benchmark = benchmark;
fossil_benchmark_start(scoped_benchmark->benchmark);
}

void fossil_scoped_benchmark_destroy(scoped_benchmark_t* scoped_benchmark) {
if (scoped_benchmark == NULL) {
printf("Error: scoped_benchmark is NULL\n");
return;
}

fossil_benchmark_stop(scoped_benchmark->benchmark);
}
43 changes: 43 additions & 0 deletions code/logic/mocking.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,19 @@
extern char *_custom_fossil_test_strdup(const char *str);

void fossil_mock_init(MockCallList *list) {
if (!list) {
return;
}
list->head = NULL;
list->tail = NULL;
list->size = 0;
}

void fossil_mock_destroy(MockCallList *list) {
if (!list) {
return;
}

MockCall *current = list->head;
while (current) {
MockCall *next = current->next;
Expand All @@ -36,15 +43,47 @@ void fossil_mock_destroy(MockCallList *list) {
free(current);
current = next;
}
list->head = NULL;
list->tail = NULL;
list->size = 0;
}

void fossil_mock_add_call(MockCallList *list, const char *function_name, char **arguments, int num_args) {
if (!list || !function_name || !arguments) {
return;
}

MockCall *call = (MockCall *)malloc(sizeof(MockCall));
if (!call) {
return;
}

call->function_name = _custom_fossil_test_strdup(function_name);
if (!call->function_name) {
free(call);
return;
}

call->arguments = (char **)malloc(num_args * sizeof(char *));
if (!call->arguments) {
free(call->function_name);
free(call);
return;
}

for (int i = 0; i < num_args; ++i) {
call->arguments[i] = _custom_fossil_test_strdup(arguments[i]);
if (!call->arguments[i]) {
for (int j = 0; j < i; ++j) {
free(call->arguments[j]);
}
free(call->arguments);
free(call->function_name);
free(call);
return;
}
}

call->num_args = num_args;
call->next = NULL;

Expand All @@ -58,6 +97,10 @@ void fossil_mock_add_call(MockCallList *list, const char *function_name, char **
}

void fossil_mock_print(MockCallList *list) {
if (!list) {
return;
}

MockCall *current = list->head;
while (current) {
printf("Function: %s\n", current->function_name);
Expand Down
12 changes: 6 additions & 6 deletions code/logic/testing.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,13 +586,13 @@ void fossil_test_assert_internal(bool condition, const char *message, const char
_ASSERT_COUNT++; // Increment the assertion count

if (!condition) {
// Check if the current assertion is the same as the last one
if (last_message && strcmp(last_message, message) == 0 &&
// Check if the current assertion is the same or similar to the last one
if (last_message && strstr(message, last_message) != NULL &&
last_file && strcmp(last_file, file) == 0 &&
last_line == line &&
last_func && strcmp(last_func, func) == 0) {
anomaly_count++;
printf(FOSSIL_TEST_COLOR_YELLOW "Duplicate assertion detected: %s (%s:%d in %s) [Anomaly Count: %d]\n" FOSSIL_TEST_COLOR_RESET, message, file, line, func, anomaly_count);
printf(FOSSIL_TEST_COLOR_YELLOW "Duplicate or similar assertion detected: %s (%s:%d in %s) [Anomaly Count: %d]\n" FOSSIL_TEST_COLOR_RESET, message, file, line, func, anomaly_count);
} else {
anomaly_count = 0; // Reset anomaly count for new assertion
printf(FOSSIL_TEST_COLOR_RED "Assertion failed: %s (%s:%d in %s)\n" FOSSIL_TEST_COLOR_RESET, message, file, line, func);
Expand Down Expand Up @@ -635,14 +635,14 @@ void fossil_test_run_case(test_case_t *test_case, fossil_test_env_t *env) {
}
} else {
test_case->status = TEST_STATUS_FAIL;
printf(FOSSIL_TEST_COLOR_RED "FAIL: " FOSSIL_TEST_COLOR_BLUE " %s\n", test_case->name);
printf(FOSSIL_TEST_COLOR_RED "FAILED: " FOSSIL_TEST_COLOR_BLUE " %s\n", test_case->name);
printf("Failure Message: %s\n" FOSSIL_TEST_COLOR_RESET, test_case->failure_message);
}
test_case->execution_time = (double)(clock() - test_start_time) / CLOCKS_PER_SEC;

// Check if the test case is empty
if (_ASSERT_COUNT == 0) {
printf(FOSSIL_TEST_COLOR_YELLOW "WARNING: " FOSSIL_TEST_COLOR_BLUE " %s contains no assertions\n" FOSSIL_TEST_COLOR_RESET, test_case->name);
printf(FOSSIL_TEST_COLOR_YELLOW "WARNING: %s contains no assertions\n" FOSSIL_TEST_COLOR_RESET, test_case->name);
}

// Run teardown
Expand All @@ -651,7 +651,7 @@ void fossil_test_run_case(test_case_t *test_case, fossil_test_env_t *env) {
// Log result
if (test_case->status == TEST_STATUS_PASS) {
if (env->options.show_info) {
printf(FOSSIL_TEST_COLOR_GREEN "PASS: " FOSSIL_TEST_COLOR_BLUE " %s (%.3f seconds)\n" FOSSIL_TEST_COLOR_RESET, test_case->name, test_case->execution_time);
printf(FOSSIL_TEST_COLOR_GREEN "PASSED: " FOSSIL_TEST_COLOR_BLUE " %s (%.3f seconds)\n" FOSSIL_TEST_COLOR_RESET, test_case->name, test_case->execution_time);
}
} else if (test_case->status == TEST_STATUS_FAIL) {
env->fail_count++;
Expand Down
60 changes: 60 additions & 0 deletions code/tests/cases/test_bdd.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,63 @@ FOSSIL_TEST_CASE(xbdd_invalid_login) {
}
} // end of case

FOSSIL_TEST_CASE(xbdd_insufficient_balance) {
GIVEN("a user's account with insufficient balance") {
// Set up the context
float accountBalance = 100.0;
float withdrawalAmount = 200.0;

WHEN("the user requests a withdrawal of $200") {
// Perform the withdrawal action
bool withdrawalSuccess = false;
if (accountBalance >= withdrawalAmount) {
accountBalance -= withdrawalAmount;
withdrawalSuccess = true;
}

THEN("the withdrawal should fail and balance should remain unchanged") {
// Check the expected outcome
FOSSIL_TEST_ASSUME(!withdrawalSuccess, "Withdrawal should not succeed");
FOSSIL_TEST_ASSUME(accountBalance == 100.0, "Account balance should remain unchanged");
}
}
}
} // end of case

FOSSIL_TEST_CASE(xbdd_add_multiple_items_to_cart) {
GIVEN("a user with an empty shopping cart") {
// Set up the context
int cartItemCount = 0;

WHEN("the user adds three products to the cart") {
// Perform the action of adding products
cartItemCount += 3;

THEN("the cart item count should increase by 3") {
// Check the expected outcome
FOSSIL_TEST_ASSUME(cartItemCount == 3, "Cart item count should have increased by 3");
}
}
}
} // end of case

FOSSIL_TEST_CASE(xbdd_remove_item_from_cart) {
GIVEN("a user with a shopping cart containing 2 items") {
// Set up the context
int cartItemCount = 2;

WHEN("the user removes one product from the cart") {
// Perform the action of removing a product
cartItemCount--;

THEN("the cart item count should decrease by 1") {
// Check the expected outcome
FOSSIL_TEST_ASSUME(cartItemCount == 1, "Cart item count should have decreased by 1");
}
}
}
} // end of case

// * * * * * * * * * * * * * * * * * * * * * * * *
// * Fossil Logic Test Pool
// * * * * * * * * * * * * * * * * * * * * * * * *
Expand All @@ -167,6 +224,9 @@ FOSSIL_TEST_GROUP(c_bdd_test_cases) {
FOSSIL_TEST_ADD(bdd_suite, xbdd_empty_cart);
FOSSIL_TEST_ADD(bdd_suite, xbdd_valid_login);
FOSSIL_TEST_ADD(bdd_suite, xbdd_invalid_login);
FOSSIL_TEST_ADD(bdd_suite, xbdd_insufficient_balance);
FOSSIL_TEST_ADD(bdd_suite, xbdd_add_multiple_items_to_cart);
FOSSIL_TEST_ADD(bdd_suite, xbdd_remove_item_from_cart);

FOSSIL_TEST_REGISTER(bdd_suite);
} // end of group
Loading
Loading