Skip to content

Commit 85ccc29

Browse files
Merge pull request #35 from dreamer-coding/pr_scan_assertions
Pull Request Updating Assertions
2 parents 79be0ae + b7c404d commit 85ccc29

File tree

5 files changed

+211
-66
lines changed

5 files changed

+211
-66
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ To integrate Fossil Test into your project, follow these steps:
5252
# ======================
5353
[wrap-git]
5454
url = https://github.com/fossillogic/fossil-test.git
55-
revision = v1.1.3
55+
revision = v1.1.4
5656

5757
[provide]
5858
fossil-test = fossil_test_dep

code/logic/fossil/test/marking.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@
2424
extern "C" {
2525
#endif
2626

27+
/**
28+
* @brief Structure to hold the benchmark statistics.
29+
*
30+
* This structure contains various fields to manage the statistics for a benchmark,
31+
* including the name of the benchmark, the start and end times, the number of samples,
32+
* the total duration, the minimum and maximum durations, and a flag to indicate if the
33+
* benchmark is currently running.
34+
*/
2735
typedef struct {
2836
const char* name;
2937
clock_t start_time;

code/logic/fossil/test/testing.h

Lines changed: 161 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,35 @@
4848
extern "C" {
4949
#endif
5050

51-
// Define the structure to hold parsed options
51+
/**
52+
* @struct fossil_options
53+
* @brief Structure to hold the configuration options for the test environment.
54+
*
55+
* This structure contains various fields to manage the configuration options for
56+
* the test environment, including flags to show version and help information, as
57+
* well as options to reverse the order of tests, repeat tests, and shuffle tests.
58+
*
59+
* @var fossil_options::show_version
60+
* Flag to show version information.
61+
*
62+
* @var fossil_options::show_help
63+
* Flag to show help information.
64+
*
65+
* @var fossil_options::show_info
66+
* Flag to show additional information.
67+
*
68+
* @var fossil_options::reverse
69+
* Flag to reverse the order of tests.
70+
*
71+
* @var fossil_options::repeat_enabled
72+
* Flag to enable repeating tests.
73+
*
74+
* @var fossil_options::repeat_count
75+
* Number of times to repeat tests.
76+
*
77+
* @var fossil_options::shuffle_enabled
78+
* Flag to enable shuffling of tests.
79+
*/
5280
typedef struct {
5381
bool show_version;
5482
bool show_help;
@@ -59,6 +87,13 @@ typedef struct {
5987
bool shuffle_enabled;
6088
} fossil_options_t;
6189

90+
/**
91+
* @enum test_status
92+
* @brief Enumeration to represent the status of a test.
93+
*
94+
* This enumeration defines the possible status values for a test, including
95+
* pass, fail, skip, empty, and timeout.
96+
*/
6297
typedef enum {
6398
TEST_STATUS_PASS,
6499
TEST_STATUS_FAIL,
@@ -67,37 +102,128 @@ typedef enum {
67102
TEST_STATUS_TTIMEOUT
68103
} test_status_t;
69104

70-
// Stack frame structure for tracking function call details during failures
71-
typedef struct stack_frame {
72-
const char *func;
73-
const char *file;
74-
int line;
75-
struct stack_frame *next;
76-
} stack_frame_t;
77-
78-
// Test case structure
105+
/**
106+
* @struct test_case
107+
* @brief Structure to hold a test case.
108+
*
109+
* This structure contains fields to hold information about a test case, including
110+
* the name, test function, setup function, teardown function, status, failure message,
111+
* execution time, and a pointer to the next test case.
112+
*
113+
* @var test_case::name
114+
* Test case name
115+
*
116+
* @var test_case::test_func
117+
* Pointer to test function
118+
*
119+
* @var test_case::setup_func
120+
* Pointer to setup function (optional)
121+
*
122+
* @var test_case::teardown_func
123+
* Pointer to teardown function (optional)
124+
*
125+
* @var test_case::status
126+
* Test status (pass, fail, skip)
127+
*
128+
* @var test_case::failure_message
129+
* Failure message (if any)
130+
*
131+
* @var test_case::execution_time
132+
* Execution time of the test
133+
*
134+
* @var test_case::next
135+
* Pointer to next test case in the list
136+
*/
79137
typedef struct test_case {
80-
const char *name; // Test case name
81-
void (*test_func)(void); // Pointer to test function
82-
void (*setup_func)(void); // Pointer to setup function (optional)
83-
void (*teardown_func)(void); // Pointer to teardown function (optional)
84-
test_status_t status; // Test status (pass, fail, skip)
85-
const char *failure_message; // Failure message (if any)
86-
stack_frame_t *stack_trace; // Stack trace for failures
87-
double execution_time; // Execution time of the test
88-
struct test_case *next; // Pointer to next test case in the list
138+
const char *name;
139+
void (*test_func)(void);
140+
void (*setup_func)(void);
141+
void (*teardown_func)(void);
142+
test_status_t status;
143+
const char *failure_message;
144+
double execution_time;
145+
struct test_case *next;
89146
} test_case_t;
90147

91-
// Test suite structure
148+
/**
149+
* @struct test_suite
150+
* @brief Structure to hold a test suite.
151+
*
152+
* This structure contains fields to hold information about a test suite, including
153+
* the name, suite setup function, suite teardown function, total execution time,
154+
* list of test cases, and a pointer to the next test suite.
155+
*
156+
* @var test_suite::name
157+
* Suite name
158+
*
159+
* @var test_suite::suite_setup_func
160+
* Pointer to suite setup function (optional)
161+
*
162+
* @var test_suite::suite_teardown_func
163+
* Pointer to suite teardown function (optional)
164+
*
165+
* @var test_suite::total_execution_time
166+
* Total execution time of all test cases
167+
*
168+
* @var test_suite::tests
169+
* List of test cases
170+
*
171+
* @var test_suite::next
172+
* Pointer to next suite in the list
173+
*/
92174
typedef struct test_suite {
93-
const char *name; // Suite name
94-
void (*suite_setup_func)(void); // Suite setup function (optional)
95-
void (*suite_teardown_func)(void); // Suite teardown function (optional)
96-
double total_execution_time; // Total execution time of all test cases
97-
test_case_t *tests; // List of test cases
98-
struct test_suite *next; // Pointer to next suite in the list
175+
const char *name;
176+
void (*suite_setup_func)(void);
177+
void (*suite_teardown_func)(void);
178+
double total_execution_time;
179+
test_case_t *tests;
180+
struct test_suite *next;
99181
} test_suite_t;
100182

183+
/**
184+
* @struct fossil_test_env
185+
* @brief Structure to hold the environment for fossil tests.
186+
*
187+
* This structure contains various fields to manage and track the state of
188+
* test execution, including options, counts of different test outcomes,
189+
* execution times, and a list of test suites.
190+
*
191+
* @var fossil_test_env::options
192+
* Configuration options for the fossil test environment.
193+
*
194+
* @var fossil_test_env::env
195+
* Environment buffer for handling non-local jumps (e.g., setjmp/longjmp).
196+
*
197+
* @var fossil_test_env::total_tests
198+
* Total number of tests to be executed.
199+
*
200+
* @var fossil_test_env::pass_count
201+
* Count of tests that have passed.
202+
*
203+
* @var fossil_test_env::fail_count
204+
* Count of tests that have failed.
205+
*
206+
* @var fossil_test_env::skip_count
207+
* Count of tests that have been skipped.
208+
*
209+
* @var fossil_test_env::empty_count
210+
* Count of tests that are empty (i.e., no test cases).
211+
*
212+
* @var fossil_test_env::timeout_count
213+
* Count of tests that have timed out.
214+
*
215+
* @var fossil_test_env::unexpected_count
216+
* Count of tests that have encountered unexpected errors.
217+
*
218+
* @var fossil_test_env::start_execution_time
219+
* Timestamp marking the start of test execution.
220+
*
221+
* @var fossil_test_env::end_execution_time
222+
* Timestamp marking the end of test execution.
223+
*
224+
* @var fossil_test_env::test_suites
225+
* Pointer to the list of test suites to be executed.
226+
*/
101227
typedef struct fossil_test_env {
102228
fossil_options_t options;
103229
jmp_buf env;
@@ -180,13 +306,16 @@ void fossil_test_run_case(test_case_t *test_case, fossil_test_env_t *env);
180306
void fossil_test_run_suite(test_suite_t *suite, fossil_test_env_t *env);
181307

182308
/**
183-
* @brief Asserts a condition and prints a message if the assertion fails.
309+
* @brief Internal function to handle assertions with anomaly detection.
184310
*
185-
* @param condition The condition to assert.
186-
* @param message The message to print if the assertion fails.
187-
* @param file The file where the assertion failed.
188-
* @param line The line number where the assertion failed.
189-
* @param func The function where the assertion failed.
311+
* This function is used internally by the test framework to handle assertions
312+
* and detect duplicate assertions. It is not intended to be called directly.
313+
*
314+
* @param condition The condition to check.
315+
* @param message The message to display if the condition is false.
316+
* @param file The file name where the assertion occurred.
317+
* @param line The line number where the assertion occurred.
318+
* @param func The function name where the assertion occurred.
190319
*/
191320
void fossil_test_assert_internal(bool condition, const char *message, const char *file, int line, const char *func);
192321

@@ -211,13 +340,6 @@ void fossil_test_summary(fossil_test_env_t *env);
211340
*/
212341
void fossil_test_run_all(fossil_test_env_t *env);
213342

214-
/**
215-
* @brief Prints the stack trace.
216-
*
217-
* @param stack_trace The stack trace to print.
218-
*/
219-
void fossil_test_print_stack_trace(stack_frame_t *stack_trace);
220-
221343
// *****************************************************************************
222344
// Macro definitions
223345
// *****************************************************************************
@@ -262,7 +384,6 @@ void fossil_test_print_stack_trace(stack_frame_t *stack_trace);
262384
nullptr, \
263385
TEST_STATUS_PASS, \
264386
nullptr, \
265-
nullptr, \
266387
0.0, \
267388
nullptr \
268389
}; \
@@ -277,7 +398,6 @@ void fossil_test_print_stack_trace(stack_frame_t *stack_trace);
277398
.teardown_func = NULL, \
278399
.status = TEST_STATUS_PASS, \
279400
.failure_message = NULL, \
280-
.stack_trace = NULL, \
281401
.execution_time = 0.0, \
282402
.next = NULL \
283403
}; \

code/logic/testing.c

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -308,22 +308,24 @@ fossil_options_t init_options(void) {
308308
}
309309

310310
void usage_info(void) {
311-
printf("Usage: fossil [options] [command]\n");
312-
printf("Options:\n");
313-
printf(" --version\t\tDisplays the current version of Fossil Test\n");
314-
printf(" --help\t\tShows help message with usage\n");
315-
printf(" --info\t\tDisplays detailed information about the test run.\n");
316-
printf("Commands:\n");
317-
printf(" reverse [enable|disable]\tEnables or disables reverse order of test execution\n");
318-
printf(" repeat [count]\t\tRepeats the test suite a specified number of times\n");
319-
printf(" shuffle [enable|disable]\tEnables or disables shuffling of test execution order\n");
311+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_ITATIC "Usage: fossil [options] [command]\n" FOSSIL_TEST_COLOR_RESET);
312+
printf(FOSSIL_TEST_COLOR_BLUE FOSSIL_TEST_ATTR_BOLD "===================================================================\n" FOSSIL_TEST_COLOR_RESET);
313+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_BOLD "Options:\n" FOSSIL_TEST_COLOR_RESET);
314+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_ITATIC " --version\t\tDisplays the current version of Fossil Test\n" FOSSIL_TEST_COLOR_RESET);
315+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_ITATIC " --help\t\tShows help message with usage\n" FOSSIL_TEST_COLOR_RESET);
316+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_ITATIC " --info\t\tDisplays detailed information about the test run.\n" FOSSIL_TEST_COLOR_RESET);
317+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_BOLD "Commands:\n" FOSSIL_TEST_COLOR_RESET);
318+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_ITATIC " reverse [enable|disable]\tEnables or disables reverse order of test execution\n" FOSSIL_TEST_COLOR_RESET);
319+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_ITATIC " repeat [count]\t\tRepeats the test suite a specified number of times\n" FOSSIL_TEST_COLOR_RESET);
320+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_ITATIC " shuffle [enable|disable]\tEnables or disables shuffling of test execution order\n" FOSSIL_TEST_COLOR_RESET);
321+
printf(FOSSIL_TEST_COLOR_BLUE FOSSIL_TEST_ATTR_BOLD "===================================================================\n" FOSSIL_TEST_COLOR_RESET);
320322
}
321323

322324
void version_info(void) {
323-
printf("Fossil Logic Test Framework\n");
324-
printf("Version: 1.1.3\n");
325-
printf("Author: Michael Gene Brockus (Dreamer)\n");
326-
printf("License: Mozila Public License 2.0\n");
325+
printf(FOSSIL_TEST_COLOR_BLUE FOSSIL_TEST_ATTR_BOLD "Fossil Logic Test Framework\n");
326+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_ITATIC "Version: 1.1.4\n");
327+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_ITATIC "Author: Michael Gene Brockus (Dreamer)\n");
328+
printf(FOSSIL_TEST_COLOR_CYAN FOSSIL_TEST_ATTR_ITATIC "License: Mozila Public License 2.0\n");
327329
}
328330

329331
// Parse command-line arguments
@@ -543,12 +545,35 @@ void fossil_test_run_suite(test_suite_t *suite, fossil_test_env_t *env) {
543545
}
544546
}
545547

546-
// Internal function to handle assertions
548+
// Internal function to handle assertions with anomaly detection
547549
void fossil_test_assert_internal(bool condition, const char *message, const char *file, int line, const char *func) {
550+
static const char *last_message = NULL; // Store the last assertion message
551+
static const char *last_file = NULL; // Store the last file name
552+
static int last_line = 0; // Store the last line number
553+
static const char *last_func = NULL; // Store the last function name
554+
static int anomaly_count = 0; // Counter for anomaly detection
555+
548556
_ASSERT_COUNT++; // Increment the assertion count
549557

550558
if (!condition) {
551-
printf(FOSSIL_TEST_COLOR_RED "Assertion failed: %s (%s:%d in %s)\n" FOSSIL_TEST_COLOR_RESET, message, file, line, func);
559+
// Check if the current assertion is the same as the last one
560+
if (last_message && strcmp(last_message, message) == 0 &&
561+
last_file && strcmp(last_file, file) == 0 &&
562+
last_line == line &&
563+
last_func && strcmp(last_func, func) == 0) {
564+
anomaly_count++;
565+
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);
566+
} else {
567+
anomaly_count = 0; // Reset anomaly count for new assertion
568+
printf(FOSSIL_TEST_COLOR_RED "Assertion failed: %s (%s:%d in %s)\n" FOSSIL_TEST_COLOR_RESET, message, file, line, func);
569+
}
570+
571+
// Update the last assertion details
572+
last_message = message;
573+
last_file = file;
574+
last_line = line;
575+
last_func = func;
576+
552577
longjmp(test_jump_buffer, 1); // Jump back to test case failure handler
553578
}
554579
}
@@ -707,11 +732,3 @@ void fossil_test_summary(fossil_test_env_t *env) {
707732

708733
fossil_test_message(env);
709734
}
710-
711-
void fossil_test_print_stack_trace(stack_frame_t *stack_trace) {
712-
stack_frame_t *current_frame = stack_trace;
713-
while (current_frame) {
714-
printf(" at %s (%s:%d)\n", current_frame->func, current_frame->file, current_frame->line);
715-
current_frame = current_frame->next;
716-
}
717-
}

meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
project('Fossil Test', 'c', 'cpp',
22
meson_version: '>=1.3.0',
33
license: 'MPL-2.0',
4-
version: '1.1.3',
4+
version: '1.1.4',
55
default_options: ['c_std=c11,c18', 'cpp_std=c++20'])
66

77
subdir('code')

0 commit comments

Comments
 (0)