From 42e42f3d5325a309622c9110991b81e758863385 Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Mon, 31 Aug 2020 04:38:47 +0100 Subject: [PATCH 1/5] enable memory allocation validation for compiler greater than C99 --- include/exotic/cester.h | 24 ++++++++++++------------ test/test_assert_double_float.c | 6 +++++- test/test_expect_actual.c | 4 ++++ test/test_junitxml_output.c | 4 ++++ test/test_junitxml_output_no_time.c | 4 ++++ test/test_tap_output.c | 4 ++++ test/test_tap_output_no_time.c | 4 ++++ test/test_tap_v13_output.c | 4 ++++ test/test_tap_v13_output_no_time.c | 4 ++++ test/test_test_instance_arg.c | 4 ++++ 10 files changed, 49 insertions(+), 13 deletions(-) diff --git a/include/exotic/cester.h b/include/exotic/cester.h index b8a0ca1..cabcea7 100644 --- a/include/exotic/cester.h +++ b/include/exotic/cester.h @@ -3456,6 +3456,7 @@ static __CESTER_INLINE__ unsigned cester_run_test_no_isolation(TestInstance *tes ((cester_before_after_each)((TestCase*)test_case)->test_ba_function)(test_instance, a_test_case->name, index); } }) + superTestInstance.current_cester_function_type = CESTER_NORMAL_TEST; superTestInstance.current_test_case = a_test_case; ((cester_test)a_test_case->test_function)(test_instance); check_memory_allocated_for_functions(a_test_case->name, NULL); @@ -3875,22 +3876,21 @@ static __CESTER_INLINE__ void* cester_malloc(unsigned size, const char *file, un if (superTestInstance.current_test_case != NULL) { actual_function_name = superTestInstance.current_test_case->name; } else { - if (superTestInstance.current_cester_function_type == CESTER_BEFORE_ALL_TEST) { - actual_function_name = "CESTER_BEFORE_ALL"; - - } else if (superTestInstance.current_cester_function_type == CESTER_OPTIONS_FUNCTION) { - actual_function_name = "CESTER_OPTIONS"; - - } else if (superTestInstance.current_cester_function_type == CESTER_BEFORE_EACH_TEST) { - actual_function_name = "CESTER_BEFORE_EACH"; - - } else { - actual_function_name = func; - } + actual_function_name = func; } #else actual_function_name = func; #endif + if (superTestInstance.current_cester_function_type == CESTER_BEFORE_ALL_TEST) { + actual_function_name = "CESTER_BEFORE_ALL"; + + } else if (superTestInstance.current_cester_function_type == CESTER_OPTIONS_FUNCTION) { + actual_function_name = "CESTER_OPTIONS"; + + } else if (superTestInstance.current_cester_function_type == CESTER_BEFORE_EACH_TEST) { + actual_function_name = "CESTER_BEFORE_EACH"; + + } if (superTestInstance.mem_test_active == 1) { if (superTestInstance.mem_alloc_manager == NULL) { if (cester_array_init(&superTestInstance.mem_alloc_manager) == 0) { diff --git a/test/test_assert_double_float.c b/test/test_assert_double_float.c index 2bff706..7dbae22 100644 --- a/test/test_assert_double_float.c +++ b/test/test_assert_double_float.c @@ -1,4 +1,4 @@ -/*!gcc -ansi -pedantic-errors {0} -I. -I../include/ -o out; ./out --cester-verbose */ +/*!gcc {0} -I. -I../include/ -o out; ./out --cester-verbose */ #include @@ -78,6 +78,10 @@ CESTER_TEST(test_long_double_assertion_literal, test_instance, cester_assert_ldouble_le(number, number); ) +CESTER_AFTER_ALL(test_instance, + free(test_instance->arg); +) + CESTER_OPTIONS( CESTER_NO_ISOLATION(); ) diff --git a/test/test_expect_actual.c b/test/test_expect_actual.c index e4b2543..c6e960f 100644 --- a/test/test_expect_actual.c +++ b/test/test_expect_actual.c @@ -40,6 +40,10 @@ CESTER_TEST(test_direct_variables, test_instance, cester_assert_equal(((AStruct*)test_instance->arg)->value, "Unknown"); ) +CESTER_AFTER_ALL(inst, + free(inst->arg); +) + CESTER_OPTIONS( CESTER_NO_ISOLATION(); ) diff --git a/test/test_junitxml_output.c b/test/test_junitxml_output.c index 27f086b..d83faa9 100644 --- a/test/test_junitxml_output.c +++ b/test/test_junitxml_output.c @@ -39,6 +39,10 @@ CESTER_OPTIONS( CESTER_NO_ISOLATION(); ) +CESTER_AFTER_ALL(test_instance, + free(test_instance->arg); +) + #ifndef __BASE_FILE__ CESTER_BODY( int main(int argc, char** argv) { diff --git a/test/test_junitxml_output_no_time.c b/test/test_junitxml_output_no_time.c index f90d732..e728183 100644 --- a/test/test_junitxml_output_no_time.c +++ b/test/test_junitxml_output_no_time.c @@ -41,6 +41,10 @@ CESTER_OPTIONS( CESTER_NO_ISOLATION(); ) +CESTER_AFTER_ALL(inst, + free(inst->arg); +) + #ifndef __BASE_FILE__ CESTER_BODY( int main(int argc, char** argv) { diff --git a/test/test_tap_output.c b/test/test_tap_output.c index 8f33dc8..c3d98a3 100644 --- a/test/test_tap_output.c +++ b/test/test_tap_output.c @@ -46,6 +46,10 @@ CESTER_SKIP_TEST(skip_this_test_it_breaks, test_instance, cester_assert_true('a' == 'b'); ) +CESTER_AFTER_ALL(test_instance, + free(test_instance->arg); +) + CESTER_OPTIONS( CESTER_OUTPUT_TAP(); CESTER_VERBOSE(); diff --git a/test/test_tap_output_no_time.c b/test/test_tap_output_no_time.c index 78b09bb..b663eb7 100644 --- a/test/test_tap_output_no_time.c +++ b/test/test_tap_output_no_time.c @@ -48,6 +48,10 @@ CESTER_SKIP_TEST(skip_this_test_it_breaks, test_instance, cester_assert_true('a' == 'b'); ) +CESTER_AFTER_ALL(test_instance, + free(test_instance->arg); +) + CESTER_OPTIONS( CESTER_OUTPUT_TAP(); CESTER_VERBOSE(); diff --git a/test/test_tap_v13_output.c b/test/test_tap_v13_output.c index 0fc06d1..36bc8a6 100644 --- a/test/test_tap_v13_output.c +++ b/test/test_tap_v13_output.c @@ -46,6 +46,10 @@ CESTER_SKIP_TEST(skip_this_test_it_breaks, test_instance, cester_assert_true('a' == 'b'); ) +CESTER_AFTER_ALL(test_instance, + free(test_instance->arg); +) + CESTER_OPTIONS( CESTER_OUTPUT_TAPV13(); CESTER_VERBOSE(); diff --git a/test/test_tap_v13_output_no_time.c b/test/test_tap_v13_output_no_time.c index 37d6f3e..cf8ff48 100644 --- a/test/test_tap_v13_output_no_time.c +++ b/test/test_tap_v13_output_no_time.c @@ -48,6 +48,10 @@ CESTER_SKIP_TEST(skip_this_test_it_breaks, test_instance, cester_assert_true('a' == 'b'); ) +CESTER_AFTER_ALL(test_instance, + free(test_instance->arg); +) + CESTER_OPTIONS( CESTER_OUTPUT_TAPV13(); CESTER_VERBOSE(); diff --git a/test/test_test_instance_arg.c b/test/test_test_instance_arg.c index 7cdccd7..bab4cef 100644 --- a/test/test_test_instance_arg.c +++ b/test/test_test_instance_arg.c @@ -24,6 +24,10 @@ CESTER_TEST(test_int_assertion_literal, test_instance, cester_assert_int_le(number, number); ) +CESTER_AFTER_ALL(test_instance, + free(test_instance->arg); +) + CESTER_TEST(test_unsigned_int_assertion_literal, test_instance, unsigned int number = ((Arg*)(test_instance->arg))->number; cester_assert_uint_eq(21, number); From e2b813dcdbf58d777dd4e335a18181057af3e94c Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Thu, 3 Sep 2020 23:55:05 +0100 Subject: [PATCH 2/5] update cester to print error and failure for memleak for junix and tap format --- include/exotic/cester.h | 137 ++++++++++++++------- test/test_before_after_memtest_fail_safe.c | 66 ++++++++++ 2 files changed, 158 insertions(+), 45 deletions(-) create mode 100644 test/test_before_after_memtest_fail_safe.c diff --git a/include/exotic/cester.h b/include/exotic/cester.h index cabcea7..fd65ac6 100644 --- a/include/exotic/cester.h +++ b/include/exotic/cester.h @@ -252,19 +252,19 @@ typedef void (*cester_before_after_each)(TestInstance*, char * const, unsigned); typedef void (*cester_void)(); typedef struct test_case { - unsigned execution_status; /**< the test execution result status. For internal use only. */ - unsigned line_num; /**< the line number where the test case is created. For internal use only. */ - enum cester_test_status expected_result; /**< The expected result for the test case. For internal use only. */ + unsigned execution_status; /**< the test execution result status. For internal use only. */ + unsigned line_num; /**< the line number where the test case is created. For internal use only. */ + enum cester_test_status expected_result; /**< The expected result for the test case. For internal use only. */ #ifndef CESTER_NO_TIME - double start_tic; /**< the time taken for the test case to complete. For internal use only. */ - double execution_time; /**< the time taken for the test case to complete. For internal use only. */ -#endif - char* execution_output; /**< the test execution output in string. For internal use only. */ - char *name; /**< the test function name. For internal use only. */ - cester_test test_function; /**< the function that enclosed the tests. For internal use only. */ - cester_before_after_each test_ba_function; /**< the function that enclosed the tests. For internal use only. */ - cester_void test_void_function; /**< the function that enclosed the tests. For internal use only. */ - TestType test_type; /**< the type of the test function. For internal use only. */ + double start_tic; /**< the time taken for the test case to complete. For internal use only. */ + double execution_time; /**< the time taken for the test case to complete. For internal use only. */ +#endif + char* execution_output; /**< the test execution output in string. For internal use only. */ + char *name; /**< the test function name. For internal use only. */ + cester_test test_function; /**< the function that enclosed the tests. For internal use only. */ + cester_before_after_each test_ba_function; /**< the function that enclosed the tests. For internal use only. */ + cester_void test_void_function; /**< the function that enclosed the tests. For internal use only. */ + TestType test_type; /**< the type of the test function. For internal use only. */ } TestCase; #ifndef CESTER_NO_MEM_TEST @@ -315,6 +315,7 @@ typedef struct super_test_instance { unsigned total_tests_ran; /**< the total number of tests that was run e.t.c. To use in your code call CESTER_TOTAL_TESTS_RAN */ unsigned total_failed_tests_count; /**< the total number of tests that failed. To use in your code call CESTER_TOTAL_FAILED_TESTS_COUNT */ unsigned total_passed_tests_count; /**< the total number of tests that passed. To use in your code call CESTER_TOTAL_FAILED_TESTS_COUNT */ + unsigned total_test_errors_count; /**< the total number of errors that occurs. To use in your code call CESTER_TOTAL_TEST_ERRORS_COUNT */ unsigned verbose; /**< prints as much info as possible into the output stream */ unsigned minimal; /**< prints minimal output into the output stream */ unsigned print_version; /**< prints cester version before running tests */ @@ -331,13 +332,14 @@ typedef struct super_test_instance { #ifndef CESTER_NO_TIME double start_tic; /**< The unix time when the tests starts. For internal use only. */ #endif - char* flattened_cmd_argv; /**< Flattened command line argument for sub process. For internal use only. */ - char* test_file_path; /**< The main test file full path. For internal use only. */ - char* output_format; /**< The output format to print the test result in. For internal use only. */ + char *main_execution_output; /**< The main test execution output in string. For internal use only. . */ + char *flattened_cmd_argv; /**< Flattened command line argument for sub process. For internal use only. */ + char *test_file_path; /**< The main test file full path. For internal use only. */ + char *output_format; /**< The output format to print the test result in. For internal use only. */ TestInstance *test_instance ; /**< The test instance for sharing datas. For internal use only. */ - FILE* output_stream; /**< Output stream to write message to, stdout by default. For internal use only. */ - char** selected_test_cases_names; /**< selected test cases from command line. For internal use only. e.g. --cester-test=Test2,Test1 */ - TestCase* current_test_case; /**< The currently running test case. For internal use only. */ + FILE *output_stream; /**< Output stream to write message to, stdout by default. For internal use only. */ + char **selected_test_cases_names; /**< selected test cases from command line. For internal use only. e.g. --cester-test=Test2,Test1 */ + TestCase *current_test_case; /**< The currently running test case. For internal use only. */ CesterArray *registered_test_cases; /**< all the manually registered test cases in the instance. For internal use only. */ #ifndef CESTER_NO_MEM_TEST CesterArray* mem_alloc_manager; /**< the array of allocated memory. For testing and detecting memory leaks. For internal use only. */ @@ -365,6 +367,7 @@ SuperTestInstance superTestInstance = { 0, 0, 0, + 0, 1, CESTER_RESULT_SUCCESS, 1, @@ -376,6 +379,7 @@ SuperTestInstance superTestInstance = { 0.0, #endif (char*)"", + (char*)"", #ifdef __BASE_FILE__ (char*)__BASE_FILE__, #else @@ -538,6 +542,18 @@ SuperTestInstance superTestInstance = { */ #define CESTER_TOTAL_FAILED_TESTS_COUNT (superTestInstance.total_failed_tests_count) +/** + The total number of errors that occur during the test. + + The errors is not tied to the test cases, the error + is tied to cester fixtures, environment error and error + that occur outside a test case. + + Error that occur within a test case is reported for + that test case +*/ +#define CESTER_TOTAL_TEST_ERRORS_COUNT (superTestInstance.total_test_errors_count) + /** The number of test that was skipped. @@ -553,7 +569,11 @@ SuperTestInstance superTestInstance = { #define CESTER_TOTAL_PASSED_TESTS_COUNT (superTestInstance.total_passed_tests_count) /** - The total number of tests that passed. CESTER_TOTAL_TESTS_COUNT - CESTER_TOTAL_FAILED_TESTS_COUNT + The number of test that was marked as todo and skipped. + + If the selected test_cases_size is 0 then no test was skipped else the + number of executed selected test cases minus the total number of test cases + is the number of test that was skipped. */ #define CESTER_TOTAL_TODO_TESTS (superTestInstance.todo_tests_count) @@ -933,6 +953,10 @@ static __CESTER_INLINE__ void print_test_result() { CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_GREEN), CESTER_TOTAL_PASSED_TESTS_COUNT); CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_WHITE), " | Failing: "); CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_RED), CESTER_TOTAL_FAILED_TESTS_COUNT); + if (CESTER_TOTAL_TEST_ERRORS_COUNT > 0) { + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_WHITE), " | Errors: "); + CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_RED), CESTER_TOTAL_TEST_ERRORS_COUNT); + } if (CESTER_TOTAL_TESTS_SKIPPED > 0) { CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_WHITE), " | Skipped: "); CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_YELLOW), CESTER_TOTAL_TESTS_SKIPPED); @@ -1127,7 +1151,7 @@ static __CESTER_INLINE__ void write_testcase_tap_v13(TestCase *a_test_case, char CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), " outputs:\n"); CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), a_test_case->execution_output); CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), " message: "); - CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), (superTestInstance.format_test_name == 1 ? cester_str_replace(a_test_case->name, '_', ' ') : a_test_case->name )); + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), a_test_case->name); switch (a_test_case->execution_status) { case CESTER_RESULT_SUCCESS: CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), " passed"); @@ -1213,7 +1237,7 @@ static __CESTER_INLINE__ void write_testcase_junitxml(TestCase *a_test_case, cha } -static __CESTER_INLINE__ void check_memory_allocated_for_functions(char *funcname1, char *funcname2) { +static __CESTER_INLINE__ unsigned check_memory_allocated_for_functions(char *funcname1, char *funcname2, char *prefix, char **write_string) { #ifndef CESTER_NO_MEM_TEST unsigned mem_index; unsigned leaked_bytes = 0; @@ -1224,34 +1248,31 @@ static __CESTER_INLINE__ void check_memory_allocated_for_functions(char *funcnam leaked_bytes += ((AllocatedMemory*)alloc_mem)->allocated_bytes; if (superTestInstance.current_test_case != NULL) { - if (cester_string_equals(superTestInstance.output_format, (char*) "tap") == 1) { - cester_concat_str(&(superTestInstance.current_test_case)->execution_output, "# "); - } - cester_concat_str(&(superTestInstance.current_test_case)->execution_output, "MemoryLeakError "); - cester_concat_str(&(superTestInstance.current_test_case)->execution_output, (superTestInstance.minimal == 0 ? superTestInstance.test_file_path : cester_extract_name(superTestInstance.test_file_path) )); - cester_concat_str(&(superTestInstance.current_test_case)->execution_output, ":"); - cester_concat_int(&(superTestInstance.current_test_case)->execution_output, ((AllocatedMemory*)alloc_mem)->line_num); - cester_concat_str(&(superTestInstance.current_test_case)->execution_output, ": "); - cester_concat_str(&(superTestInstance.current_test_case)->execution_output, "in '"); - cester_concat_str(&(superTestInstance.current_test_case)->execution_output, (char*)((AllocatedMemory*)alloc_mem)->function_name); - cester_concat_str(&(superTestInstance.current_test_case)->execution_output, "' => Memory allocated in line '"); - cester_concat_int(&(superTestInstance.current_test_case)->execution_output, ((AllocatedMemory*)alloc_mem)->line_num); - cester_concat_str(&(superTestInstance.current_test_case)->execution_output, "' not freed. Leaking '"); - cester_concat_int(&(superTestInstance.current_test_case)->execution_output, ((AllocatedMemory*)alloc_mem)->allocated_bytes); - cester_concat_str(&(superTestInstance.current_test_case)->execution_output, "' Bytes \n"); + cester_concat_str(write_string, prefix); + cester_concat_str(write_string, "MemoryLeakError "); + cester_concat_str(write_string, (superTestInstance.minimal == 0 ? superTestInstance.test_file_path : cester_extract_name(superTestInstance.test_file_path) )); + cester_concat_str(write_string, ":"); + cester_concat_int(write_string, ((AllocatedMemory*)alloc_mem)->line_num); + cester_concat_str(write_string, ": "); + cester_concat_str(write_string, "in '"); + cester_concat_str(write_string, (char*)((AllocatedMemory*)alloc_mem)->function_name); + cester_concat_str(write_string, "' => Memory allocated in line '"); + cester_concat_int(write_string, ((AllocatedMemory*)alloc_mem)->line_num); + cester_concat_str(write_string, "' not freed. Leaking '"); + cester_concat_int(write_string, ((AllocatedMemory*)alloc_mem)->allocated_bytes); + cester_concat_str(write_string, "' Bytes \n"); } } }) - if (leaked_bytes > 0) { - superTestInstance.current_execution_status = CESTER_RESULT_MEMORY_LEAK; - } } #endif + return leaked_bytes; } static __CESTER_INLINE__ int cester_print_result(TestCase cester_test_cases[], TestInstance* test_instance) { unsigned index_sub; unsigned i, index4, index5, index6, index7; + char *prefix = ""; #ifndef CESTER_NO_TIME clock_t tok; @@ -1274,7 +1295,14 @@ static __CESTER_INLINE__ int cester_print_result(TestCase cester_test_cases[], T ((cester_test)((TestCase*)test_case)->test_function)(test_instance); } }) - check_memory_allocated_for_functions((char *)"CESTER_BEFORE_ALL", (char *)"CESTER_OPTIONS"); + if (cester_string_equals(superTestInstance.output_format, (char*) "tap") == 1 || + cester_string_equals(superTestInstance.output_format, (char*) "tapV13") == 1) { + prefix = "# "; + } + if (check_memory_allocated_for_functions((char *)"CESTER_BEFORE_ALL", (char *)"CESTER_OPTIONS", prefix, &superTestInstance.main_execution_output) > 0) { + superTestInstance.current_execution_status = CESTER_RESULT_MEMORY_LEAK; + ++superTestInstance.total_test_errors_count; + } if (superTestInstance.single_output_only == 0) { if (cester_string_equals(superTestInstance.output_format, (char*) "junitxml") == 1) { CESTER_DELEGATE_FPRINT_STR((default_color), "\n"); @@ -1284,7 +1312,9 @@ static __CESTER_INLINE__ int cester_print_result(TestCase cester_test_cases[], T CESTER_DELEGATE_FPRINT_INT((default_color), superTestInstance.total_failed_tests_count); CESTER_DELEGATE_FPRINT_STR((default_color), "\" name=\""); CESTER_DELEGATE_FPRINT_STR((default_color), cester_extract_name_only(superTestInstance.test_file_path)); - CESTER_DELEGATE_FPRINT_STR((default_color), "\" errors=\"0\" skipped=\""); + CESTER_DELEGATE_FPRINT_STR((default_color), "\" errors=\""); + CESTER_DELEGATE_FPRINT_INT((default_color), CESTER_TOTAL_TEST_ERRORS_COUNT); + CESTER_DELEGATE_FPRINT_STR((default_color), "\" skipped=\""); CESTER_DELEGATE_FPRINT_INT((default_color), CESTER_TOTAL_TESTS_SKIPPED + CESTER_TOTAL_TODO_TESTS); #ifndef CESTER_NO_TIME CESTER_DELEGATE_FPRINT_STR((default_color), "\" time=\""); @@ -1335,6 +1365,7 @@ static __CESTER_INLINE__ int cester_print_result(TestCase cester_test_cases[], T ++index_sub; } }) + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), superTestInstance.main_execution_output); if (superTestInstance.verbose == 1) { CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), "# Failed "); CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_GRAY), CESTER_TOTAL_FAILED_TESTS_COUNT); @@ -1381,6 +1412,7 @@ static __CESTER_INLINE__ int cester_print_result(TestCase cester_test_cases[], T ++index_sub; } }) + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), superTestInstance.main_execution_output); if (superTestInstance.verbose == 1) { CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), "# Failed "); CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_GRAY), CESTER_TOTAL_FAILED_TESTS_COUNT); @@ -1438,6 +1470,7 @@ static __CESTER_INLINE__ int cester_print_result(TestCase cester_test_cases[], T } }) + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_WHITE), superTestInstance.main_execution_output); #ifndef CESTER_NO_TIME print_test_result(time_spent); #else @@ -3441,6 +3474,7 @@ static __CESTER_INLINE__ void cester_run_test(TestInstance *test_instance, TestC static __CESTER_INLINE__ unsigned cester_run_test_no_isolation(TestInstance *test_instance, TestCase *a_test_case, unsigned index) { unsigned i, index1, index2, mem_index, cached_current_execution_status; + char *prefix = ""; superTestInstance.current_execution_status = CESTER_RESULT_SUCCESS; if (superTestInstance.registered_test_cases->size == 0) { for (i=0;cester_test_cases[i].test_type != CESTER_TESTS_TERMINATOR;++i) { @@ -3459,7 +3493,16 @@ static __CESTER_INLINE__ unsigned cester_run_test_no_isolation(TestInstance *tes superTestInstance.current_cester_function_type = CESTER_NORMAL_TEST; superTestInstance.current_test_case = a_test_case; ((cester_test)a_test_case->test_function)(test_instance); - check_memory_allocated_for_functions(a_test_case->name, NULL); + if (cester_string_equals(superTestInstance.output_format, (char*) "tap") == 1) { + prefix = "# "; + + } else if (cester_string_equals(superTestInstance.output_format, (char*) "tapV13") == 1) { + prefix = " - "; + + } + if (check_memory_allocated_for_functions(a_test_case->name, NULL, prefix, &(superTestInstance.current_test_case)->execution_output) > 0) { + superTestInstance.current_execution_status = CESTER_RESULT_MEMORY_LEAK; + } if (superTestInstance.registered_test_cases->size == 0) { for (i=0;cester_test_cases[i].test_type != CESTER_TESTS_TERMINATOR;++i) { if (cester_test_cases[i].test_type == CESTER_AFTER_EACH_TEST) { @@ -3474,9 +3517,13 @@ static __CESTER_INLINE__ unsigned cester_run_test_no_isolation(TestInstance *tes ((cester_before_after_each)((TestCase*)test_case)->test_ba_function)(test_instance, a_test_case->name, index); } }) - cached_current_execution_status = superTestInstance.current_execution_status; - check_memory_allocated_for_functions((char *)"CESTER_BEFORE_EACH", NULL); - superTestInstance.current_execution_status = cached_current_execution_status; + if (cester_string_equals(superTestInstance.output_format, (char*) "tap") == 1 || + cester_string_equals(superTestInstance.output_format, (char*) "tapV13") == 1) { + prefix = "# "; + } + if (check_memory_allocated_for_functions((char *)"CESTER_BEFORE_EACH", NULL, prefix, &superTestInstance.main_execution_output) > 0) { + ++superTestInstance.total_test_errors_count; + } ++superTestInstance.total_tests_ran; if (superTestInstance.single_output_only == 1) { CESTER_DELEGATE_FPRINT_STR((default_color), a_test_case->execution_output); diff --git a/test/test_before_after_memtest_fail_safe.c b/test/test_before_after_memtest_fail_safe.c new file mode 100644 index 0000000..e69f4ee --- /dev/null +++ b/test/test_before_after_memtest_fail_safe.c @@ -0,0 +1,66 @@ +/*!gcc -ansi -pedantic-errors {0} -I. -I../include/ -o out; ./out --cester-verbose */ + +#include + +CESTER_BODY( +typedef struct argumets { + void *arg1; + void *arg2; +} Args; +) + +CESTER_BEFORE_ALL(inst, + char *ba_str1 = (char *) malloc(1); + char *ba_str2 = (char *) malloc(1); + Args *args = (Args *) malloc(sizeof(Args)); + args->arg1 = ba_str2; + inst->arg = args; + + free(ba_str1); +) + +CESTER_BEFORE_EACH(inst, index, test_name, + char *be_str1 = (char *) malloc(4); + char *be_str2 = (char *) malloc(4); + Args *args = (Args *) inst->arg; + args->arg2 = be_str2; + + free(be_str1); +) + +CESTER_TEST(test_assert_false, test_instance, + char *str1 = (char *) malloc(2); + char *str2 = (char *) malloc(2); + free(str1); + free(str2); +) + +CESTER_TEST(test_assert_false1, test_instance, + char *str1 = (char *) malloc(2); + char *str2 = (char *) malloc(2); + free(str1); + free(str2); +) + +CESTER_TEST(test_number_2, test_instance, + char *str1 = (char *) malloc(6); + cester_assert_true(1); + /* free(str1); */ +) + +CESTER_AFTER_EACH(inst, index, test_name, + Args *args = (Args *) inst->arg; + free(args->arg2); +) + +CESTER_AFTER_ALL(inst, + Args *args = (Args *) inst->arg; + /* free(args->arg1); + free(args); */ +) + +CESTER_OPTIONS( + char *co_str = (char *) malloc(3); + /* free(co_str); */ + CESTER_OUTPUT_TEXT(); +) From 099d7447da8538033d253f582db91f3cc5905cbe Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Fri, 4 Sep 2020 01:41:27 +0100 Subject: [PATCH 3/5] add the CESTER_REPORT_FAILURE_REGARDLESS and CESTER_REPORT_SUCCESS_REGARDLESS to indicate the test final status report --- docs/docs/macros.rst | 36 ++++++++ docs/docs/test_for_failure.rst | 99 ++++++++++++++++++++-- include/exotic/cester.h | 79 ++++++++++++++--- test/skips_test_always_fail.c | 18 ++++ test/test_always_success.c | 22 +++++ test/test_before_after_memtest_fail_safe.c | 66 --------------- 6 files changed, 237 insertions(+), 83 deletions(-) create mode 100644 test/skips_test_always_fail.c create mode 100644 test/test_always_success.c delete mode 100644 test/test_before_after_memtest_fail_safe.c diff --git a/docs/docs/macros.rst b/docs/docs/macros.rst index c2c051d..f1c161a 100644 --- a/docs/docs/macros.rst +++ b/docs/docs/macros.rst @@ -224,6 +224,28 @@ It should not begin or end in quote, escape characters is expanded when printed before any test cases is executed. ) +CESTER_REPORT_SUCCESS_REGARDLESS +--------------------------------- + +Always mark the test as success even if the test cases failed or an error occur while running the test. + +.. code:: c + + CESTER_OPTIONS( + CESTER_REPORT_SUCCESS_REGARDLESS(); + ) + +CESTER_REPORT_FAILURE_REGARDLESS +--------------------------------- + +Always mark the test as failure even if the test cases passes and no error occur. + +.. code:: c + + CESTER_OPTIONS( + CESTER_REPORT_FAILURE_REGARDLESS(); + ) + CESTER_REGISTER_TEST ---------------------- @@ -836,6 +858,20 @@ CESTER_TOTAL_TESTS_COUNT The total number of test that is registered at the time. +CESTER_TOTAL_TEST_ERRORS_COUNT +------------------------------- + +.. code:: text + + printf("Total Test Error %d", CESTER_TOTAL_TEST_ERRORS_COUNT); + +The total number of errors that occur during the test. The errors is not tied to the test +cases, the error is tied to cester fixtures, environment error and error that occur +outside a test case. + +Error that occur within a test case is reported for that test case + + CESTER_TOTAL_TESTS_RAN ------------------------- diff --git a/docs/docs/test_for_failure.rst b/docs/docs/test_for_failure.rst index 7d39b76..fbe2ad0 100644 --- a/docs/docs/test_for_failure.rst +++ b/docs/docs/test_for_failure.rst @@ -14,6 +14,8 @@ to set a test case result: - `CESTER_TEST_SHOULD_FAIL <./macros.html#cester-test-should-fail>`_ - `CESTER_TEST_SHOULD_BE_TERMINATED <./macros.html#cester-test-should-be-terminated>`_ - `CESTER_TEST_SHOULD_LEAK_MEMORY <./macros.html#cester-test-should-leak-memory>`_ +- `CESTER_REPORT_SUCCESS_REGARDLESS <./macros.html#cester-report-success-regardless>`_ +- `CESTER_REPORT_FAILURE_REGARDLESS <./macros.html#cester-report-failure-regardless>`_ The macro CESTER_TEST_SHOULD accepts the test case name as the first parameter and the expected result as the second parameter. By default the expected result for the test cases is @@ -53,7 +55,7 @@ the expected result of the test case. gcc test.c -I. -o test ./test --cester-minimal - + (0.01s) definitely crahses + + (0.01s) definitely crahses Passed crash_test.c:5: in 'definitely_crahses' => Segfault as expected @@ -107,11 +109,11 @@ are expected to fail. gcc test.c -I. -o test ./test --cester-minimal - + (0.00s) this should segfault - + (0.00s) this should fail - + (0.00s) this should pass - + (0.00s) this should segfault also fail - + (0.01s) this should leak memory + + (0.00s) this should segfault + + (0.00s) this should fail + + (0.00s) this should pass + + (0.00s) this should segfault also fail + + (0.01s) this should leak memory Passed crash_test.c:5: in 'this_should_segfault' => Segfault as expected AssertionError crash_test.c:10: in 'this_should_fail' => not expecting 'NULL', received '((void*)0)' @@ -121,4 +123,87 @@ are expected to fail. Passed crash_test.c:21: in 'this_should_leak_memory' => Leaked memory as expected Ran 5 test(s) in 0.02 Seconds - Synthesis: SUCCESS Tests: 5 | Passing: 5 | Failing: 0 \ No newline at end of file + Synthesis: SUCCESS Tests: 5 | Passing: 5 | Failing: 0 + + +Example 3 +'''''''''' + +The test case in the example below will fail and memory error will be reported. But the test +will still be reported as success since the option CESTER_REPORT_SUCCESS_REGARDLESS() is specified. + +.. code:: c + + //test.c + #include + + CESTER_BEFORE_ALL(test_instance, + char *str = (char *) malloc(20); + ) + + CESTER_TEST(test_assert_true, test_instance, + cester_assert_false(2 > 1); + cester_assert_false(test_instance != NULL); + cester_assert_false(test_instance->argc > 0); + ) + + CESTER_OPTIONS( + CESTER_REPORT_SUCCESS_REGARDLESS(); + ) + + +.. code:: bash + + gcc test.c -I. -o test + ./test --cester-minimal + + - (0.00s) test assert true + + EvaluationError test_always_success.c:10: in 'test_assert_true' expr => '(2 > 1)' + EvaluationError test_always_success.c:11: in 'test_assert_true' expr => '(test_instance != NULL)' + EvaluationError test_always_success.c:12: in 'test_assert_true' expr => '(test_instance->argc > 0)' + MemoryLeakError test_always_success.c:6: in 'CESTER_BEFORE_ALL' => Memory allocated in line '6' not freed. Leaking '20' Bytes + + Ran 1 test(s) in 0.00 Seconds + Synthesis: SUCCESS Tests: 1 | Passing: 0 | Failing: 1 | Errors: 1 + + echo $? + 0 + + +Example 4 +'''''''''' + +The test case in the example below will pass with no error . But the test be reported as failure +since the option CESTER_REPORT_FAILURE_REGARDLESS() is specified. + +.. code:: c + + //test.c + #include + + CESTER_TEST(test_assert_true, test_instance, + cester_assert_true(2 > 1); + cester_assert_true(test_instance != NULL); + cester_assert_true(test_instance->argc > 0); + ) + + CESTER_OPTIONS( + CESTER_REPORT_FAILURE_REGARDLESS(); + ) + + +.. code:: bash + + gcc test.c -I. -o test + ./test --cester-minimal + + + (0.00s) test assert true + + + Ran 1 test(s) in 0.00 Seconds + Synthesis: FAILURE Tests: 1 | Passing: 1 | Failing: 0 + + echo $? + 1 + diff --git a/include/exotic/cester.h b/include/exotic/cester.h index fd65ac6..6bf2781 100644 --- a/include/exotic/cester.h +++ b/include/exotic/cester.h @@ -328,6 +328,8 @@ typedef struct super_test_instance { unsigned skipped_test_count; /**< The number of test cases to be skipped. For internal use only. */ unsigned todo_tests_count; /**< The number of test cases that would be implemented in future. For internal use only. */ unsigned format_test_name; /**< Format the test name for fine output e.g. 'test_file_exit' becomes 'test file exist'. For internal use only. */ + unsigned report_success_regardless; /**< If the value is set to 1 the test will be mark as success even if it fails. For internal use only. */ + unsigned report_failure_regardless; /**< If the value is set to 1 the test will be mark as failure even if it passes. For internal use only. */ TestType current_cester_function_type; /**< The current cester funtion type, this enable cester to properly track memory allocation in non test case functions. For internal use only. */ #ifndef CESTER_NO_TIME double start_tic; /**< The unix time when the tests starts. For internal use only. */ @@ -374,6 +376,8 @@ SuperTestInstance superTestInstance = { 0, 0, 1, + 0, + 0, CESTER_TESTS_TERMINATOR, #ifndef CESTER_NO_TIME 0.0, @@ -586,6 +590,18 @@ SuperTestInstance superTestInstance = { */ #define CESTER_RUN_ALL_TESTS(x,y) cester_run_all_test(x,y) +/** + Always mark the test as success even if the test cases + failed or an error occur while running the test. +*/ +#define CESTER_REPORT_SUCCESS_REGARDLESS() (superTestInstance.report_failure_regardless = 0); (superTestInstance.report_success_regardless = 1) + +/** + Always mark the test as failure even if the test cases + passes and no error occur. +*/ +#define CESTER_REPORT_FAILURE_REGARDLESS() (superTestInstance.report_success_regardless = 0); (superTestInstance.report_failure_regardless = 1) + #ifdef _WIN32 int default_color = CESTER_RESET_TERMINAL; HANDLE hConsole; @@ -945,7 +961,13 @@ static __CESTER_INLINE__ void print_test_result() { superTestInstance.total_failed_tests_count = superTestInstance.current_execution_status == CESTER_RESULT_SUCCESS && superTestInstance.total_failed_tests_count == 0 ? 0 : 1; CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_WHITE), "Synthesis: "); - CESTER_DELEGATE_FPRINT_STR(CESTER_GET_RESULT_AGGR_COLOR, CESTER_GET_RESULT_AGGR); + if (superTestInstance.report_success_regardless == 1) { + CESTER_DELEGATE_FPRINT_STR(CESTER_FOREGROUND_GREEN, "SUCCESS"); + } else if (superTestInstance.report_failure_regardless == 1) { + CESTER_DELEGATE_FPRINT_STR(CESTER_FOREGROUND_RED, "FAILURE"); + } else { + CESTER_DELEGATE_FPRINT_STR(CESTER_GET_RESULT_AGGR_COLOR, CESTER_GET_RESULT_AGGR); + } superTestInstance.total_failed_tests_count = cached_total_failed_tests_count; CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_WHITE), " Tests: "); CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_YELLOW), CESTER_TOTAL_TESTS_COUNT); @@ -1240,13 +1262,13 @@ static __CESTER_INLINE__ void write_testcase_junitxml(TestCase *a_test_case, cha static __CESTER_INLINE__ unsigned check_memory_allocated_for_functions(char *funcname1, char *funcname2, char *prefix, char **write_string) { #ifndef CESTER_NO_MEM_TEST unsigned mem_index; - unsigned leaked_bytes = 0; + unsigned leaked_memory_count = 0; if (superTestInstance.mem_test_active == 1) { CESTER_ARRAY_FOREACH(superTestInstance.mem_alloc_manager, mem_index, alloc_mem, { if ((funcname1 != NULL && cester_string_equals((char*)((AllocatedMemory*)alloc_mem)->function_name, funcname1)) || (funcname2 != NULL && cester_string_equals((char*)((AllocatedMemory*)alloc_mem)->function_name, funcname2))) { - leaked_bytes += ((AllocatedMemory*)alloc_mem)->allocated_bytes; + leaked_memory_count += 1; if (superTestInstance.current_test_case != NULL) { cester_concat_str(write_string, prefix); cester_concat_str(write_string, "MemoryLeakError "); @@ -1266,11 +1288,11 @@ static __CESTER_INLINE__ unsigned check_memory_allocated_for_functions(char *fun }) } #endif - return leaked_bytes; + return leaked_memory_count; } static __CESTER_INLINE__ int cester_print_result(TestCase cester_test_cases[], TestInstance* test_instance) { - unsigned index_sub; + unsigned index_sub, ret_val; unsigned i, index4, index5, index6, index7; char *prefix = ""; @@ -1299,9 +1321,10 @@ static __CESTER_INLINE__ int cester_print_result(TestCase cester_test_cases[], T cester_string_equals(superTestInstance.output_format, (char*) "tapV13") == 1) { prefix = "# "; } - if (check_memory_allocated_for_functions((char *)"CESTER_BEFORE_ALL", (char *)"CESTER_OPTIONS", prefix, &superTestInstance.main_execution_output) > 0) { + ret_val = check_memory_allocated_for_functions((char *)"CESTER_BEFORE_ALL", (char *)"CESTER_OPTIONS", prefix, &superTestInstance.main_execution_output); + if (ret_val > 0) { superTestInstance.current_execution_status = CESTER_RESULT_MEMORY_LEAK; - ++superTestInstance.total_test_errors_count; + superTestInstance.total_test_errors_count += ret_val; } if (superTestInstance.single_output_only == 0) { if (cester_string_equals(superTestInstance.output_format, (char*) "junitxml") == 1) { @@ -1367,6 +1390,21 @@ static __CESTER_INLINE__ int cester_print_result(TestCase cester_test_cases[], T }) CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), superTestInstance.main_execution_output); if (superTestInstance.verbose == 1) { + if (CESTER_TOTAL_TEST_ERRORS_COUNT > 0) { + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), "# "); + CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_GRAY), CESTER_TOTAL_TEST_ERRORS_COUNT); + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), " total error(s) occured\n"); + } + if (CESTER_TOTAL_TODO_TESTS > 0) { + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), "# "); + CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_GRAY), CESTER_TOTAL_TODO_TESTS); + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), " todo test case(s) skipped\n"); + } + if (CESTER_TOTAL_TESTS_SKIPPED > 0) { + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), "# "); + CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_GRAY), CESTER_TOTAL_TESTS_SKIPPED); + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), " test case(s) skipped\n"); + } CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), "# Failed "); CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_GRAY), CESTER_TOTAL_FAILED_TESTS_COUNT); CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), " of "); @@ -1414,6 +1452,21 @@ static __CESTER_INLINE__ int cester_print_result(TestCase cester_test_cases[], T }) CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), superTestInstance.main_execution_output); if (superTestInstance.verbose == 1) { + if (CESTER_TOTAL_TEST_ERRORS_COUNT > 0) { + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), "# "); + CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_GRAY), CESTER_TOTAL_TEST_ERRORS_COUNT); + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), " total error(s) occured\n"); + } + if (CESTER_TOTAL_TODO_TESTS > 0) { + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), "# "); + CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_GRAY), CESTER_TOTAL_TODO_TESTS); + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), " todo test case(s) skipped\n"); + } + if (CESTER_TOTAL_TESTS_SKIPPED > 0) { + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), "# "); + CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_GRAY), CESTER_TOTAL_TESTS_SKIPPED); + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), " test case(s) skipped\n"); + } CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), "# Failed "); CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_GRAY), CESTER_TOTAL_FAILED_TESTS_COUNT); CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_GRAY), " of "); @@ -1483,6 +1536,11 @@ static __CESTER_INLINE__ int cester_print_result(TestCase cester_test_cases[], T if (CESTER_TOTAL_FAILED_TESTS_COUNT != 0 && superTestInstance.current_execution_status == CESTER_RESULT_SUCCESS) { return CESTER_RESULT_FAILURE; } + if (superTestInstance.report_success_regardless == 1) { + return CESTER_RESULT_SUCCESS; + } else if (superTestInstance.report_failure_regardless == 1) { + return CESTER_RESULT_FAILURE; + } return superTestInstance.current_execution_status; } @@ -3473,7 +3531,7 @@ static __CESTER_INLINE__ void cester_run_test(TestInstance *test_instance, TestC } static __CESTER_INLINE__ unsigned cester_run_test_no_isolation(TestInstance *test_instance, TestCase *a_test_case, unsigned index) { - unsigned i, index1, index2, mem_index, cached_current_execution_status; + unsigned i, index1, index2, mem_index, ret_val; char *prefix = ""; superTestInstance.current_execution_status = CESTER_RESULT_SUCCESS; if (superTestInstance.registered_test_cases->size == 0) { @@ -3521,8 +3579,9 @@ static __CESTER_INLINE__ unsigned cester_run_test_no_isolation(TestInstance *tes cester_string_equals(superTestInstance.output_format, (char*) "tapV13") == 1) { prefix = "# "; } - if (check_memory_allocated_for_functions((char *)"CESTER_BEFORE_EACH", NULL, prefix, &superTestInstance.main_execution_output) > 0) { - ++superTestInstance.total_test_errors_count; + ret_val = check_memory_allocated_for_functions((char *)"CESTER_BEFORE_EACH", NULL, prefix, &superTestInstance.main_execution_output); + if (ret_val > 0) { + superTestInstance.total_test_errors_count += ret_val; } ++superTestInstance.total_tests_ran; if (superTestInstance.single_output_only == 1) { diff --git a/test/skips_test_always_fail.c b/test/skips_test_always_fail.c new file mode 100644 index 0000000..47a0af4 --- /dev/null +++ b/test/skips_test_always_fail.c @@ -0,0 +1,18 @@ +/*!gcc -ansi -pedantic-errors {0} -I. -I../include/ -o out; ./out --cester-verbose; $LastExitCode */ + +#include + +CESTER_TEST(test_assert_true, test_instance, + cester_assert_true(2 > 1); + cester_assert_true(test_instance != NULL); + cester_assert_true(test_instance->argc > 0); +) + +CESTER_TEST(test_assert_false, test_instance, + cester_assert_false(2 < 1); + cester_assert_false(test_instance == NULL); +) + +CESTER_OPTIONS( + CESTER_REPORT_FAILURE_REGARDLESS(); +) diff --git a/test/test_always_success.c b/test/test_always_success.c new file mode 100644 index 0000000..719c78a --- /dev/null +++ b/test/test_always_success.c @@ -0,0 +1,22 @@ +/*!gcc -ansi -pedantic-errors {0} -I. -I../include/ -o out; ./out --cester-verbose; $LastExitCode */ + +#include + +CESTER_BEFORE_ALL(test_instance, + char *str = (char *) malloc(20); +) + +CESTER_TEST(test_assert_true, test_instance, + cester_assert_false(2 > 1); + cester_assert_false(test_instance != NULL); + cester_assert_false(test_instance->argc > 0); +) + +CESTER_TEST(test_assert_false, test_instance, + cester_assert_true(2 < 1); + cester_assert_true(test_instance == NULL); +) + +CESTER_OPTIONS( + CESTER_REPORT_SUCCESS_REGARDLESS(); +) diff --git a/test/test_before_after_memtest_fail_safe.c b/test/test_before_after_memtest_fail_safe.c deleted file mode 100644 index e69f4ee..0000000 --- a/test/test_before_after_memtest_fail_safe.c +++ /dev/null @@ -1,66 +0,0 @@ -/*!gcc -ansi -pedantic-errors {0} -I. -I../include/ -o out; ./out --cester-verbose */ - -#include - -CESTER_BODY( -typedef struct argumets { - void *arg1; - void *arg2; -} Args; -) - -CESTER_BEFORE_ALL(inst, - char *ba_str1 = (char *) malloc(1); - char *ba_str2 = (char *) malloc(1); - Args *args = (Args *) malloc(sizeof(Args)); - args->arg1 = ba_str2; - inst->arg = args; - - free(ba_str1); -) - -CESTER_BEFORE_EACH(inst, index, test_name, - char *be_str1 = (char *) malloc(4); - char *be_str2 = (char *) malloc(4); - Args *args = (Args *) inst->arg; - args->arg2 = be_str2; - - free(be_str1); -) - -CESTER_TEST(test_assert_false, test_instance, - char *str1 = (char *) malloc(2); - char *str2 = (char *) malloc(2); - free(str1); - free(str2); -) - -CESTER_TEST(test_assert_false1, test_instance, - char *str1 = (char *) malloc(2); - char *str2 = (char *) malloc(2); - free(str1); - free(str2); -) - -CESTER_TEST(test_number_2, test_instance, - char *str1 = (char *) malloc(6); - cester_assert_true(1); - /* free(str1); */ -) - -CESTER_AFTER_EACH(inst, index, test_name, - Args *args = (Args *) inst->arg; - free(args->arg2); -) - -CESTER_AFTER_ALL(inst, - Args *args = (Args *) inst->arg; - /* free(args->arg1); - free(args); */ -) - -CESTER_OPTIONS( - char *co_str = (char *) malloc(3); - /* free(co_str); */ - CESTER_OUTPUT_TEXT(); -) From b834d188d559f695da1d28e6deefec0b285585a6 Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Fri, 4 Sep 2020 01:51:29 +0100 Subject: [PATCH 4/5] add the CESTER_REPORT_FAILURE_REGARDLESS and CESTER_REPORT_SUCCESS_REGARDLESS to indicate the test final status report --- include/exotic/cester.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/exotic/cester.h b/include/exotic/cester.h index 6bf2781..59f4ee4 100644 --- a/include/exotic/cester.h +++ b/include/exotic/cester.h @@ -987,7 +987,10 @@ static __CESTER_INLINE__ void print_test_result() { CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_WHITE), " | Todo: "); CESTER_DELEGATE_FPRINT_INT((CESTER_FOREGROUND_YELLOW), CESTER_TOTAL_TODO_TESTS); } - CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_WHITE), "\n"); + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_WHITE), "\n"); + if (superTestInstance.report_failure_regardless == 1 || superTestInstance.report_success_regardless == 1) { + CESTER_DELEGATE_FPRINT_STR((CESTER_FOREGROUND_YELLOW), "Avoid using the CESTER_REPORT_*_REGARDLESS macros, they hides the actual result of the test\n"); + } } static __CESTER_INLINE__ void print_test_case_result(TestCase* test_case) { From 0bd5ceccc218f278718c84dd86137bc4fad87a2a Mon Sep 17 00:00:00 2001 From: Adewale Azeez Date: Sun, 6 Sep 2020 08:49:15 +0100 Subject: [PATCH 5/5] add metadata to the documentation conf.py and enable travis test for PR --- .travis.yml | 4 ---- docs/_static/css/libcester.css | 9 --------- docs/conf.py | 21 ++++++++++++++++++++- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9b6186b..a79cbef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,5 @@ language: sh -branches: - only: - - main - os: - linux diff --git a/docs/_static/css/libcester.css b/docs/_static/css/libcester.css index 8a9530c..04ed6f9 100644 --- a/docs/_static/css/libcester.css +++ b/docs/_static/css/libcester.css @@ -131,7 +131,6 @@ code { } .two-sided pre { - max-height: 20pc; overflow-y: scroll; } @@ -139,14 +138,6 @@ code { font-weight: bold; } -.note { - background: rgb(24,26,27) !important; -} - -.warning { - background: rgb(24,26,27) !important; -} - .bodywrapper { min-height: 100vh; } diff --git a/docs/conf.py b/docs/conf.py index 706ba8e..617c7c3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -35,5 +35,24 @@ 'index' ], "source_root": "https://github.com/exoticlibraries/libcester/edit/main/docs", - "document_font_size": "17px" + "document_font_size": "17px", + "metadata": { + "enable": True, + "url": "https://exoticlibraries.github.io/libcester/", + "type": "website", + "title": "A robust header only unit testing framework for C programming language.", + "description": "libcester is a header only automated testing framework for the C programming language, it requires no dependency and can be downloaded and used in a project immediately.", + "image": "https://raw.githubusercontent.com/exoticlibraries/libcester/main/docs/libcester.png", + "keywords": "thecarisma, c, cpp, c++, unit testing, framework, exoticlibraries, exotic, libraries, regression, test", + "author": "Adewale Azeez" + }, + "twitter_metadata": { + "enable": True, + "card": "summary", + "site": "@iamthecarisma", + "creator": "@iamthecarisma", + "title": "A robust header only unit testing framework for C programming language.", + "description": "libcester is a header only automated testing framework for the C programming language, it requires no dependency and can be downloaded and used in a project immediately.", + "image": "https://raw.githubusercontent.com/exoticlibraries/libcester/main/docs/libcester.png", + } } \ No newline at end of file