From 71c2a4d0815f71e077dfe057e2949e9d0a696e2d Mon Sep 17 00:00:00 2001 From: seleznevae Date: Wed, 4 Apr 2018 22:13:37 +0300 Subject: [PATCH] [A] Added memory test and fixed err. treatment errors --- CMakeLists.txt | 1 + include/fort.h | 1 + src/fort.c | 10 ++-- src/fort_impl.c | 56 ++++++++++++++++++++ src/fort_impl.h | 16 ++++-- src/options.c | 2 +- tests/test.c | 1 + tests/test_memory_errors.c | 106 +++++++++++++++++++++++++++++++++++++ tests/tests.h | 1 + 9 files changed, 186 insertions(+), 8 deletions(-) create mode 100644 tests/test_memory_errors.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8509ea9..9c94a87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,6 +91,7 @@ set(TEST_SOURCES tests/test_table_basic.c tests/test_table_border_style.c tests/test_table_options.c + tests/test_memory_errors.c tests/test_utility.c) add_executable(${PROJECT_NAME}_test ${FORT_SOURCES} diff --git a/include/fort.h b/include/fort.h index 02c593a..0bc589f 100644 --- a/include/fort.h +++ b/include/fort.h @@ -468,6 +468,7 @@ FT_EXTERN int ft_set_default_tbl_option(uint32_t option, int value); FT_EXTERN int ft_set_tbl_option(FTABLE *table, uint32_t option, int value); +FT_EXTERN void ft_set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free)(void *ptr)); /* diff --git a/src/fort.c b/src/fort.c index 9750344..1a262ea 100644 --- a/src/fort.c +++ b/src/fort.c @@ -515,13 +515,12 @@ const char *ft_to_string(const FTABLE *table) size_t *col_width_arr = NULL; size_t *row_height_arr = NULL; status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows); + if (IS_ERROR(status)) + return NULL; if (rows == 0) return cur_F_STRDUP(empty_string); - if (IS_ERROR(status)) - return NULL; - int written = 0; int tmp = 0; size_t i = 0; @@ -871,3 +870,8 @@ FT_EXTERN int ft_set_tbl_option(FTABLE *table, uint32_t option, int value) } return set_entire_table_option(table->options, option, value); } + +FT_EXTERN void ft_set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free)(void *ptr)) +{ + set_memory_funcs(f_malloc, f_free); +} diff --git a/src/fort_impl.c b/src/fort_impl.c index 7cb17c8..0c09603 100644 --- a/src/fort_impl.c +++ b/src/fort_impl.c @@ -6,6 +6,62 @@ /***************************************************************************** * LIBFORT helpers *****************************************************************************/ + +void *(*fort_malloc)(size_t size) = &malloc; +void (*fort_free)(void *ptr) = &free; +void *(*fort_calloc)(size_t nmemb, size_t size) = &calloc; +void *(*fort_realloc)(void *ptr, size_t size) = &realloc; + + +static void *custom_fort_calloc(size_t nmemb, size_t size) +{ + size_t total_size = nmemb * size; + void *result = F_MALLOC(total_size); + if (result != NULL) + memset(result, 0, total_size); + return result; +} + +static void *custom_fort_realloc(void *ptr, size_t size) +{ + if (ptr == NULL) + return F_MALLOC(size); + if (size == 0) { + F_FREE(ptr); + return NULL; + } + + void *new_chunk = F_MALLOC(size); + if (new_chunk == NULL) + return NULL; + + /* + * In theory we should copy MIN(size, size allocated for ptr) bytes, + * but this is rather dummy implementation so we don't care about it + */ + memcpy(new_chunk, ptr, size); + F_FREE(ptr); + return new_chunk; +} + +void set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free)(void *ptr)) +{ + assert((f_malloc == NULL && f_free == NULL) /* Use std functions */ + || (f_malloc != NULL && f_free != NULL) /* Use custom functions */); + fort_malloc = f_malloc; + fort_free = f_free; + + if (fort_malloc == NULL) { + fort_calloc = &calloc; + fort_realloc = &realloc; + } else { + fort_calloc = &custom_fort_calloc; + fort_realloc = &custom_fort_realloc; + } + +} + + char *fort_strdup(const char *str) { if (str == NULL) diff --git a/src/fort_impl.h b/src/fort_impl.h index 1bb08b4..aa122e3 100644 --- a/src/fort_impl.h +++ b/src/fort_impl.h @@ -12,10 +12,10 @@ #define FORT_UNUSED __attribute__((unused)) -#define F_CALLOC calloc -#define F_MALLOC malloc -#define F_REALLOC realloc -#define F_FREE free +#define F_MALLOC fort_malloc +#define F_FREE fort_free +#define F_CALLOC fort_calloc +#define F_REALLOC fort_realloc #define F_STRDUP fort_strdup #define F_WCSDUP fort_wcsdup @@ -109,6 +109,14 @@ typedef struct separator separator_t; /***************************************************************************** * LIBFORT helpers *****************************************************************************/ + +extern void *(*fort_malloc)(size_t size); +extern void (*fort_free)(void *ptr); +extern void *(*fort_calloc)(size_t nmemb, size_t size); +extern void *(*fort_realloc)(void *ptr, size_t size); +void set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free)(void *ptr)); + + char *fort_strdup(const char* str); wchar_t *fort_wcsdup(const wchar_t* str); size_t number_of_columns_in_format_string(const char *fmt); diff --git a/src/options.c b/src/options.c index a2065cd..3a05ad7 100644 --- a/src/options.c +++ b/src/options.c @@ -374,7 +374,7 @@ fort_table_options_t *create_table_options() options->cell_options = create_cell_opt_container(); if (options->cell_options == NULL) { destroy_table_options(options); - options = NULL; + return NULL; } memcpy(&options->entire_table_options, &g_entire_table_options, sizeof(fort_entire_table_options_t)); return options; diff --git a/tests/test.c b/tests/test.c index 891f1a1..871c884 100644 --- a/tests/test.c +++ b/tests/test.c @@ -12,6 +12,7 @@ struct test_case test_suit [] = { {"test_table_border_style", test_table_border_style}, {"test_table_cell_options", test_table_cell_options}, {"test_table_tbl_options", test_table_tbl_options}, + {"test_memory_errors", test_memory_errors}, }; int main(void) diff --git a/tests/test_memory_errors.c b/tests/test_memory_errors.c new file mode 100644 index 0000000..d50f52a --- /dev/null +++ b/tests/test_memory_errors.c @@ -0,0 +1,106 @@ +#include "tests.h" + +static int aloc_num = 0; +static int aloc_lim = 9999; + +void *test_malloc(size_t size) +{ + if (aloc_num < aloc_lim) { + void *result = malloc(size); + if (result) + aloc_num++; + return result; + } else { + return NULL; + } +} + +void test_free(void *ptr) +{ + if (ptr != 0) { + aloc_num--; + free(ptr); + } +} + +static int create_simple_table_and_show() +{ + FTABLE *table = NULL; + int result = 0; + + table = ft_create_table(); + if (table == NULL) { + result = 1; + goto exit; + } +// if (set_test_options_for_table(table) != FT_SUCCESS) +// return 2; + + if (ft_set_cell_option(table, 0, FT_ANY_COLUMN, FT_COPT_ROW_TYPE, FT_ROW_HEADER) != FT_SUCCESS) { + result = 3; + goto exit; + } + if (FT_NWRITE_LN(table, "3", "c", "234", "3.140000") != FT_SUCCESS) { + result = 4; + goto exit; + } + if (FT_NWRITE_LN(table, "3", "c", "234", "3.140000") != FT_SUCCESS) { + result = 5; + goto exit; + } + if (FT_NWRITE_LN(table, "3", "c", "234", "3.140000") != FT_SUCCESS) { + result = 6; + goto exit; + } + + const char *table_str = ft_to_string(table); + if (table_str == NULL) { + result = 7; + goto exit; + } + const char *table_str_etalon = + "+---+---+-----+----------+\n" + "| | | | |\n" + "| 3 | c | 234 | 3.140000 |\n" + "| | | | |\n" + "+---+---+-----+----------+\n" + "| | | | |\n" + "| 3 | c | 234 | 3.140000 |\n" + "| | | | |\n" + "+---+---+-----+----------+\n" + "| | | | |\n" + "| 3 | c | 234 | 3.140000 |\n" + "| | | | |\n" + "+---+---+-----+----------+\n"; +// assert_str_equal(table_str, table_str_etalon); + if (strcmp(table_str, table_str_etalon) != 0) { + result = 8; + goto exit; + } + + +exit: + ft_destroy_table(table); + return result; +} + +void test_memory_errors(void) +{ + ft_set_memory_funcs(&test_malloc, &test_free); + + const int ITER_MAX = 150; + int i; + for (i = 0; i < ITER_MAX; ++i) { + aloc_lim = i; + int result = create_simple_table_and_show(); + if (result == 0) + break; + if (aloc_num != 0) { + assert_true(0); + break; + } + } + + assert_true(i != ITER_MAX); + ft_set_memory_funcs(NULL, NULL); +} diff --git a/tests/tests.h b/tests/tests.h index becf2fe..bac3c5d 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -24,6 +24,7 @@ void test_table_write(void); void test_table_border_style(void); void test_table_cell_options(void); void test_table_tbl_options(void); +void test_memory_errors(void); struct test_case {