From dc1f3debd47bbfca80130901352facf01bcc05b9 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Thu, 25 Apr 2024 20:04:23 +0200 Subject: [PATCH 01/37] draft CI pipeline --- .github/workflows/build.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/build.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..9b4c696 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,19 @@ +--- +name: CI Pipeline + + +on: + push: + branches: [master] + pull_request: + branches: [master] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Execute tests + run: make From c4a0646690cc73f45d949b3d6cf488de3ba7cb07 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Thu, 25 Apr 2024 20:30:11 +0200 Subject: [PATCH 02/37] add testing on macos --- .github/workflows/build.yaml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 9b4c696..80f8bfc 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -10,10 +10,11 @@ on: workflow_dispatch: jobs: - build: - runs-on: ubuntu-latest + matrix: + strategy: + matrix: [ubuntu-latest, macos-latest] - steps: - - uses: actions/checkout@v2 - - name: Execute tests - run: make + steps: + - uses: actions/checkout@v4 + - name: Execute tests + run: make From 9fecb0255570f1af2c997fb8279c39f4f2b1d510 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Thu, 25 Apr 2024 20:32:10 +0200 Subject: [PATCH 03/37] fix typo --- .github/workflows/build.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 80f8bfc..c0ede0d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,6 +15,7 @@ jobs: matrix: [ubuntu-latest, macos-latest] steps: - - uses: actions/checkout@v4 - - name: Execute tests - run: make + - uses: actions/checkout@v4 + + - name: Execute tests + run: make From 4f1951c1f432c66374934adc6661ff506906549c Mon Sep 17 00:00:00 2001 From: pako-23 Date: Thu, 25 Apr 2024 20:35:54 +0200 Subject: [PATCH 04/37] fix typo --- .github/workflows/build.yaml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c0ede0d..b813926 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -10,12 +10,13 @@ on: workflow_dispatch: jobs: - matrix: + test: strategy: - matrix: [ubuntu-latest, macos-latest] + matrix: + os: [ubuntu-latest, macos-latest] - steps: + steps: - uses: actions/checkout@v4 - - name: Execute tests + - name: Run tests run: make From 69bf35de5d9813b826687e7760ed35e42096af25 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Thu, 25 Apr 2024 20:37:36 +0200 Subject: [PATCH 05/37] add runs-on property --- .github/workflows/build.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index b813926..3be1e77 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -11,6 +11,8 @@ on: jobs: test: + runs-on: ${{ matrix.os }} + strategy: matrix: os: [ubuntu-latest, macos-latest] From d835fc51605583a4c459a48d1a5fc713defda3fd Mon Sep 17 00:00:00 2001 From: pako-23 Date: Mon, 2 Sep 2024 10:39:37 +0200 Subject: [PATCH 06/37] draft all malloc instrumentations --- basic_testing.h | 173 ++++++++++++++++----- basic_testing.mk | 7 +- ex/memory_checks/tests/00_hash_map.c | 91 ++++++++--- ex/memory_checks/tests/00_hash_map_cpp.cc | 91 ++++++++--- ex/memory_checks/tests/08_lib_allocation.c | 15 ++ 5 files changed, 285 insertions(+), 92 deletions(-) create mode 100644 ex/memory_checks/tests/08_lib_allocation.c diff --git a/basic_testing.h b/basic_testing.h index ded9a7f..562506b 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -27,6 +27,7 @@ #include #include #include +#include #ifdef __cplusplus #include @@ -420,23 +421,32 @@ void bt_mem_reset_allocator (void) { } \ } while (0) -#ifdef __cplusplus -extern "C" { -#endif +// #ifdef __cplusplus +// extern "C" { +// #endif -extern void * __real_malloc (size_t); -extern void __real_free (void *); -extern void * __real_realloc (void *, size_t); -extern void * __real_calloc (size_t, size_t); -extern void * __real_reallocarray (void *, size_t, size_t); +// extern void * __real_malloc (size_t); +// extern void __real_free (void *); +// extern void * __real_realloc (void *, size_t); +// extern void * __real_calloc (size_t, size_t); +// extern void * __real_reallocarray (void *, size_t, size_t); -#ifdef __cplusplus -} -#endif +// #ifdef __cplusplus +// } +// #endif + + + +typedef enum { + BT_MALLOC, + BT_NEW, + BT_NEW_ARRAY +} bt_allocator_t; struct bt_mem_node { void * address; size_t size; + bt_allocator_t allocator; int deleted; }; @@ -447,10 +457,14 @@ static size_t bt_mem_table_capacity = 0; BT_POSSIBLY_UNUSED static void bt_mem_table_free (void) { - if (bt_mem_table) __real_free (bt_mem_table); + int checks_tmp = bt_mem_checks_disabled; + + bt_mem_checks_disabled = 1; + if (bt_mem_table) free (bt_mem_table); bt_mem_table = NULL; bt_mem_table_size = 0; bt_mem_table_capacity = 0; + bt_mem_checks_disabled = checks_tmp; } static size_t bt_ptr_hash (void * address) { @@ -495,9 +509,15 @@ static struct bt_mem_node * bt_mem_table_find_or_insert (void * address) { } static int bt_mem_rehash (size_t new_cap) { + int checks_tmp = bt_mem_checks_disabled; + + bt_mem_checks_disabled = 1; struct bt_mem_node * new_table = - (struct bt_mem_node *) __real_malloc(new_cap*sizeof(struct bt_mem_node)); - if (!new_table) return 0; + (struct bt_mem_node *) malloc(new_cap*sizeof(struct bt_mem_node)); + if (!new_table) { + bt_mem_checks_disabled = checks_tmp; + return 0; + } memset(new_table, 0, new_cap*sizeof(struct bt_mem_node)); struct bt_mem_node * tmp = bt_mem_table; @@ -513,32 +533,30 @@ static int bt_mem_rehash (size_t new_cap) { node->size = tmp[i].size; } } - if (tmp) __real_free(tmp); + if (tmp) free(tmp); + bt_mem_checks_disabled = checks_tmp; return 1; } BT_POSSIBLY_UNUSED -static int bt_mem_table_set (void *address, size_t size) { +static struct bt_mem_node * bt_mem_table_insert (void *address) { struct bt_mem_node * node = bt_mem_table_find_or_insert (address); - if (node && node->address != NULL) { - node->size = size; - return 1; - } + if (node && node->address != NULL) + return node; if (bt_mem_table_size*BT_MEM_TABLE_REHASH_HIGH_RATIO >= bt_mem_table_capacity) { size_t new_cap = bt_mem_table_capacity ? 2*bt_mem_table_capacity : BT_MEM_TABLE_MIN_SIZE; if (!bt_mem_rehash(new_cap)) - return 0; + return NULL; node = bt_mem_table_find_or_insert (address); } node->address = address; - node->size = size; node->deleted = 0; ++bt_mem_table_size; - return 1; + return node; } BT_POSSIBLY_UNUSED @@ -575,9 +593,14 @@ extern "C" { #endif BT_POSSIBLY_UNUSED -void *__wrap_malloc (size_t size) { +void * malloc (size_t size) { + static void *(*libc_malloc)(size_t) = NULL; + + if (!libc_malloc) + libc_malloc = (void *(*)(size_t)) dlsym(RTLD_NEXT, "malloc"); + if (bt_mem_checks_disabled) - return __real_malloc(size); + return libc_malloc(size); if (size == 0) { fputs("\nmalloc with size 0 is not portable\n", stderr); if (bt_fork_tests) exit(BT_FAILURE); @@ -603,7 +626,7 @@ void *__wrap_malloc (size_t size) { else if (bt_mem_bytes_budget_enabled && bt_mem_bytes_budget_curr < size) return NULL; - void * ret = __real_malloc(size); + void * ret = libc_malloc(size); if (!ret) return NULL; if (bt_mem_budget_enabled) @@ -611,18 +634,28 @@ void *__wrap_malloc (size_t size) { else if (bt_mem_bytes_budget_enabled) bt_mem_bytes_budget_curr -= size; - if (!bt_mem_table_set(ret, size)) { + struct bt_mem_node * node = bt_mem_table_insert (ret); + if (ret) { + node->allocator = BT_MALLOC; + node->size = size; + } else bt_mem_table_failed = 1; - } + return ret; } BT_POSSIBLY_UNUSED -void __wrap_free (void * ptr) { +void free (void * ptr) { + static void (*libc_free)(void *) = NULL; + + if (!libc_free) + libc_free = (void (*)(void *)) dlsym(RTLD_NEXT, "free"); + if (bt_mem_checks_disabled) { - __real_free(ptr); + libc_free(ptr); return; } + const struct bt_mem_node *p = bt_mem_table_find(ptr); if (!p) { fputs("\nmemory was not allocated via malloc, or possible double free\n", stderr); @@ -638,20 +671,25 @@ void __wrap_free (void * ptr) { bt_mem_bytes_budget_curr = bt_mem_bytes_budget; } bt_mem_table_remove(ptr); - __real_free(ptr); + libc_free(ptr); } BT_POSSIBLY_UNUSED -void *__wrap_realloc (void * ptr, size_t new_size) { +void * realloc (void * ptr, size_t new_size) { + static void *(*libc_realloc)(void *, size_t) = NULL; + + if (!libc_realloc) + libc_realloc = (void *(*)(void *, size_t)) dlsym(RTLD_NEXT, "realloc"); + if (bt_mem_checks_disabled) - return __real_realloc (ptr, new_size); + return libc_realloc (ptr, new_size); if (new_size == 0) { fputs("\nrealloc with size 0 is not portable\n", stderr); if (bt_fork_tests) exit(BT_FAILURE); else abort(); } - if (!ptr) return __wrap_malloc(new_size); + if (!ptr) return malloc (new_size); if (bt_mem_failure_count > 0) { if (--bt_mem_failure_count == 0) { @@ -677,10 +715,17 @@ void *__wrap_realloc (void * ptr, size_t new_size) { fputs("\nrealloc of not heap allocated memory\n", stderr); if (bt_fork_tests) exit(BT_FAILURE); else abort(); + } else if (node->allocator != BT_MALLOC) { + if (node->allocator == BT_NEW_ARRAY) + fputs("\nrealloc of memory allocated with 'new'\n", stderr); + else + fputs("\nrealloc of memory allocated with 'new[]'\n", stderr); + if (bt_fork_tests) exit(BT_FAILURE); + else abort(); } else if (bt_mem_bytes_budget_enabled && bt_mem_bytes_budget_curr + node->size < new_size) return NULL; - void * ret = __real_realloc(ptr, new_size); + void * ret = libc_realloc (ptr, new_size); if (!ret) return NULL; if (bt_mem_budget_enabled) @@ -690,9 +735,11 @@ void *__wrap_realloc (void * ptr, size_t new_size) { bt_mem_bytes_budget_curr -= new_size; } - if (!bt_mem_table_set(ret, new_size)) { + struct bt_mem_node * new_node = bt_mem_table_insert (ret); + if (new_node) + new_node->size = new_size; + else bt_mem_table_failed = 1; - } if (ret != ptr) bt_mem_table_remove(ptr); @@ -700,26 +747,36 @@ void *__wrap_realloc (void * ptr, size_t new_size) { return ret; } -void * __wrap_calloc (size_t nmemb, size_t size) { +void * calloc (size_t nmemb, size_t size) { + static void *(*libc_calloc)(size_t, size_t) = NULL; + + if (!libc_calloc) + libc_calloc = (void *(*)(size_t, size_t)) dlsym(RTLD_NEXT, "calloc"); + if (bt_mem_checks_disabled) - return __real_calloc(nmemb, size); + libc_calloc(nmemb, size); if (nmemb == 0 || size == 0 || SIZE_MAX / nmemb <= size) return NULL; size_t len = nmemb * size; - void * p = __wrap_malloc (len); + void * p = malloc (len); if (p) memset(p, 0, len); return p; } -void * __wrap_reallocarray (void * ptr, size_t nmemb, size_t size) { +void * reallocarray (void * ptr, size_t nmemb, size_t size) { + static void *(*libc_reallocarray)(void *, size_t, size_t) = NULL; + + if (!libc_reallocarray) + libc_reallocarray = (void *(*)(void *, size_t, size_t)) dlsym(RTLD_NEXT, "reallocarray"); + if (bt_mem_checks_disabled) - return __real_reallocarray(ptr, nmemb, size); + return libc_reallocarray(ptr, nmemb, size); if (nmemb == 0 || size == 0 || SIZE_MAX / nmemb <= size) return NULL; size_t len = nmemb * size; - return __wrap_realloc (ptr, len); + return realloc (ptr, len); } #ifdef __cplusplus @@ -727,6 +784,36 @@ void * __wrap_reallocarray (void * ptr, size_t nmemb, size_t size) { #endif +// #ifdef __cplusplus +// extern "C" { + +// void * __wrap__Znwm (size_t size) { +// void * p = __wrap_malloc(size); +// if (p) +// bt_mem_table_find (p)->allocator = BT_NEW; + +// return p; +// } + +// void * __wrap__Znam (size_t size) { +// void * p = __wrap_malloc(size); +// if (p) +// bt_mem_table_find (p)->allocator = BT_NEW_ARRAY; + +// return p; +// } + +// void __wrap__ZdlPvm (void * ptr, size_t) { +// __wrap_free(ptr); +// } + +// void __wrap__ZdaPv (void * ptr) { +// __wrap_free(ptr); +// } + +// } +// #endif + struct bt_test_descriptor { const char * name; int (*test_function)(); diff --git a/basic_testing.mk b/basic_testing.mk index 41829fd..1ad0a5d 100644 --- a/basic_testing.mk +++ b/basic_testing.mk @@ -184,13 +184,14 @@ check-io-sh: compile $(TESTS_IO) $(TESTS_SH) $(PROGRAMS_DRIVERS) done; \ test_summary 'Summary: PASS ' -BT_LDFLAGS := -Wl,--wrap=malloc,--wrap=free,--wrap=realloc,--wrap=calloc,--wrap=reallocarray +# BT_LDFLAGS := -Wl,--wrap=malloc,--wrap=free,--wrap=realloc,--wrap=calloc,--wrap=reallocarray +# BT_CXXLDFLAGS := -Wl,--wrap=_Znwm,--wrap=_Znam,--wrap=_ZdlPvm,--wrap=_ZdaPv $(TESTS_DIR)/%: $(TESTS_DIR)/%.c $(OBJECTS) - $(CC) $(CFLAGS) $(LDFLAGS) $(BT_LDFLAGS) $(TESTS_DIR)/$*.c $(OBJECTS) -o $@ + $(CC) $(CFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.c $(OBJECTS) -o $@ $(TESTS_DIR)/%: $(TESTS_DIR)/%.cc $(OBJECTS) - $(CXX) -std=c++11 $(CXXFLAGS) $(LDFLAGS) $(BT_LDFLAGS) $(TESTS_DIR)/$*.cc $(OBJECTS) -o $@ + $(CXX) -std=c++11 $(CXXFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.cc $(OBJECTS) -o $@ .PHONY: check-bin check-bin: $(TESTS_BIN) diff --git a/ex/memory_checks/tests/00_hash_map.c b/ex/memory_checks/tests/00_hash_map.c index ace9312..9310d76 100644 --- a/ex/memory_checks/tests/00_hash_map.c +++ b/ex/memory_checks/tests/00_hash_map.c @@ -26,7 +26,10 @@ TEST (map_find_empty) { TEST (map_insert) { int i = 0; - CHECK (bt_mem_table_set (&i, 12)); + struct bt_mem_node * ins_node = bt_mem_table_insert (&i); + CHECK (ins_node != NULL); + ins_node->size = 12; + ins_node->allocator = BT_MALLOC; struct bt_mem_node * node = bt_mem_table_find (&i); CHECK (node != NULL); @@ -45,7 +48,11 @@ TEST (map_insert) { TEST (map_update) { int i = 0; - CHECK (bt_mem_table_set (&i, 12)); + struct bt_mem_node * ins_node = bt_mem_table_insert (&i); + CHECK (ins_node != NULL); + ins_node->size = 12; + ins_node->allocator = BT_MALLOC; + struct bt_mem_node * node = bt_mem_table_find (&i); CHECK (node != NULL); CHECK_CMP (node->size,==,12); @@ -54,8 +61,9 @@ TEST (map_update) { size_t capacity = bt_mem_table_capacity; - CHECK (bt_mem_table_set (&i, 15)); - node = bt_mem_table_find (&i); + ins_node = bt_mem_table_insert (&i); + ins_node->allocator = BT_NEW; + ins_node->size = 15; CHECK (node != NULL); CHECK_CMP (node->size,==,15); CHECK (&i == node->address); @@ -77,13 +85,18 @@ TEST (map_insert_collisions) { for (size_t i = 0; i < len; ++i) items[i] = i; - for (size_t i = 0; i < len; ++i) - CHECK_CMP (bt_mem_table_set (items + i, items[i]),==,1); + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK(node != NULL); + node->allocator = BT_MALLOC; + node->size = items[i]; + } for (size_t i = 0; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); + CHECK_CMP (node->allocator,==,BT_MALLOC); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); @@ -104,13 +117,18 @@ TEST (map_update_collisions) { for (size_t i = 0; i < len; ++i) items[i] = i; - for (size_t i = 0; i < len; ++i) - CHECK_CMP (bt_mem_table_set (items + i, items[i]),==,1); + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK(node != NULL); + node->allocator = BT_MALLOC; + node->size = items[i]; + } for (size_t i = 0; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); + CHECK_CMP (node->allocator,==,BT_MALLOC); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); @@ -119,20 +137,24 @@ TEST (map_update_collisions) { for (size_t i = 0; i < len; ++i) items[i] = 2*i; - - for (size_t i = 0; i < len; ++i) - CHECK_CMP (bt_mem_table_set (items + i, items[i]),==,1); + + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK(node != NULL); + node->allocator = BT_NEW; + node->size = items[i]; + } for (size_t i = 0; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); + CHECK_CMP (node->allocator,==,BT_NEW); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); CHECK (bt_mem_table_capacity == cap); - bt_mem_table_free (); CHECK (bt_mem_table == NULL); CHECK_CMP (bt_mem_table_size,==,0); @@ -145,8 +167,12 @@ TEST (map_free) { const size_t len = 1024; int items[len]; - for (size_t i = 0; i < len; ++i) - CHECK (bt_mem_table_set (items + i, 10)); + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK (node != NULL); + node->size = 10; + node->allocator = BT_MALLOC; + } bt_mem_table_free (); @@ -160,7 +186,10 @@ TEST (map_free) { TEST (map_remove) { int x; - CHECK (bt_mem_table_set (&x, 10)); + struct bt_mem_node * node = bt_mem_table_insert (&x); + CHECK (node != NULL); + node->size = 10; + node->allocator = BT_MALLOC; CHECK (bt_mem_table_remove (&x)); CHECK (bt_mem_table_find (&x) == NULL); bt_mem_table_free (); @@ -182,8 +211,12 @@ TEST (map_remove_collisions) { const size_t len = 1024; int items[len]; - for (size_t i = 0; i < len; ++i) - CHECK (bt_mem_table_set (items + i, 10)); + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK (node != NULL); + node->size = 10; + node->allocator = BT_MALLOC; + } CHECK (bt_mem_table_size == len); CHECK (bt_mem_table_size <= bt_mem_table_capacity); @@ -207,8 +240,12 @@ TEST (map_remove_collisions_not_found) { int items[len]; int x; - for (size_t i = 0; i < len; ++i) - CHECK (bt_mem_table_set (items + i, 10)); + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK (node != NULL); + node->size = 10; + node->allocator = BT_MALLOC; + } CHECK (!bt_mem_table_remove (&x)); @@ -224,8 +261,12 @@ TEST (map_insert_remove_series) { for (size_t i = 0; i < len; ++i) items[i] = i; - for (size_t i = 0; i < len/2; ++i) - CHECK (bt_mem_table_set (items + i, items[i])); + for (size_t i = 0; i < len/2; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK (node != NULL); + node->size = items[i]; + node->allocator = BT_MALLOC; + } for (size_t i = 0; i < len/2; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); @@ -243,8 +284,12 @@ TEST (map_insert_remove_series) { CHECK (bt_mem_table_size*BT_MEM_TABLE_REHASH_HIGH_RATIO <= bt_mem_table_capacity); CHECK (bt_mem_table_size == len/4); - for (size_t i = len/2; i < len; ++i) - CHECK (bt_mem_table_set (items + i, items[i])); + for (size_t i = len/2; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK (node != NULL); + node->size = items[i]; + node->allocator = BT_MALLOC; + } for (size_t i = len/2; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); diff --git a/ex/memory_checks/tests/00_hash_map_cpp.cc b/ex/memory_checks/tests/00_hash_map_cpp.cc index ce49498..c066284 100644 --- a/ex/memory_checks/tests/00_hash_map_cpp.cc +++ b/ex/memory_checks/tests/00_hash_map_cpp.cc @@ -26,7 +26,10 @@ TEST (map_find_empty) { TEST (map_insert) { int i = 0; - CHECK (bt_mem_table_set (&i, 12)); + struct bt_mem_node * ins_node = bt_mem_table_insert (&i); + CHECK (ins_node != NULL); + ins_node->size = 12; + ins_node->allocator = BT_MALLOC; struct bt_mem_node * node = bt_mem_table_find (&i); CHECK (node != NULL); @@ -45,7 +48,11 @@ TEST (map_insert) { TEST (map_update) { int i = 0; - CHECK (bt_mem_table_set (&i, 12)); + struct bt_mem_node * ins_node = bt_mem_table_insert (&i); + CHECK (ins_node != NULL); + ins_node->size = 12; + ins_node->allocator = BT_MALLOC; + struct bt_mem_node * node = bt_mem_table_find (&i); CHECK (node != NULL); CHECK_CMP (node->size,==,12); @@ -54,8 +61,9 @@ TEST (map_update) { size_t capacity = bt_mem_table_capacity; - CHECK (bt_mem_table_set (&i, 15)); - node = bt_mem_table_find (&i); + ins_node = bt_mem_table_insert (&i); + ins_node->allocator = BT_NEW; + ins_node->size = 15; CHECK (node != NULL); CHECK_CMP (node->size,==,15); CHECK (&i == node->address); @@ -77,13 +85,18 @@ TEST (map_insert_collisions) { for (size_t i = 0; i < len; ++i) items[i] = i; - for (size_t i = 0; i < len; ++i) - CHECK_CMP (bt_mem_table_set (items + i, items[i]),==,1); + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK(node != NULL); + node->allocator = BT_MALLOC; + node->size = items[i]; + } for (size_t i = 0; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); + CHECK_CMP (node->allocator,==,BT_MALLOC); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); @@ -104,13 +117,18 @@ TEST (map_update_collisions) { for (size_t i = 0; i < len; ++i) items[i] = i; - for (size_t i = 0; i < len; ++i) - CHECK_CMP (bt_mem_table_set (items + i, items[i]),==,1); + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK(node != NULL); + node->allocator = BT_MALLOC; + node->size = items[i]; + } for (size_t i = 0; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); + CHECK_CMP (node->allocator,==,BT_MALLOC); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); @@ -119,20 +137,24 @@ TEST (map_update_collisions) { for (size_t i = 0; i < len; ++i) items[i] = 2*i; - - for (size_t i = 0; i < len; ++i) - CHECK_CMP (bt_mem_table_set (items + i, items[i]),==,1); + + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK(node != NULL); + node->allocator = BT_NEW; + node->size = items[i]; + } for (size_t i = 0; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); + CHECK_CMP (node->allocator,==,BT_NEW); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); CHECK (bt_mem_table_capacity == cap); - bt_mem_table_free (); CHECK (bt_mem_table == NULL); CHECK_CMP (bt_mem_table_size,==,0); @@ -145,8 +167,12 @@ TEST (map_free) { const size_t len = 1024; int items[len]; - for (size_t i = 0; i < len; ++i) - CHECK (bt_mem_table_set (items + i, 10)); + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK (node != NULL); + node->size = 10; + node->allocator = BT_MALLOC; + } bt_mem_table_free (); @@ -160,7 +186,10 @@ TEST (map_free) { TEST (map_remove) { int x; - CHECK (bt_mem_table_set (&x, 10)); + struct bt_mem_node * node = bt_mem_table_insert (&x); + CHECK (node != NULL); + node->size = 10; + node->allocator = BT_MALLOC; CHECK (bt_mem_table_remove (&x)); CHECK (bt_mem_table_find (&x) == NULL); bt_mem_table_free (); @@ -182,8 +211,12 @@ TEST (map_remove_collisions) { const size_t len = 1024; int items[len]; - for (size_t i = 0; i < len; ++i) - CHECK (bt_mem_table_set (items + i, 10)); + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK (node != NULL); + node->size = 10; + node->allocator = BT_MALLOC; + } CHECK (bt_mem_table_size == len); CHECK (bt_mem_table_size <= bt_mem_table_capacity); @@ -207,8 +240,12 @@ TEST (map_remove_collisions_not_found) { int items[len]; int x; - for (size_t i = 0; i < len; ++i) - CHECK (bt_mem_table_set (items + i, 10)); + for (size_t i = 0; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK (node != NULL); + node->size = 10; + node->allocator = BT_MALLOC; + } CHECK (!bt_mem_table_remove (&x)); @@ -224,8 +261,12 @@ TEST (map_insert_remove_series) { for (size_t i = 0; i < len; ++i) items[i] = i; - for (size_t i = 0; i < len/2; ++i) - CHECK (bt_mem_table_set (items + i, items[i])); + for (size_t i = 0; i < len/2; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK (node != NULL); + node->size = items[i]; + node->allocator = BT_MALLOC; + } for (size_t i = 0; i < len/2; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); @@ -243,8 +284,12 @@ TEST (map_insert_remove_series) { CHECK (bt_mem_table_size*BT_MEM_TABLE_REHASH_HIGH_RATIO <= bt_mem_table_capacity); CHECK (bt_mem_table_size == len/4); - for (size_t i = len/2; i < len; ++i) - CHECK (bt_mem_table_set (items + i, items[i])); + for (size_t i = len/2; i < len; ++i) { + struct bt_mem_node * node = bt_mem_table_insert (items + i); + CHECK (node != NULL); + node->size = items[i]; + node->allocator = BT_MALLOC; + } for (size_t i = len/2; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); diff --git a/ex/memory_checks/tests/08_lib_allocation.c b/ex/memory_checks/tests/08_lib_allocation.c new file mode 100644 index 0000000..87024a8 --- /dev/null +++ b/ex/memory_checks/tests/08_lib_allocation.c @@ -0,0 +1,15 @@ +#include "basic_testing.h" +#include + + + +TEST (memory_leak) { + char * str = "testing"; + char * str2 = strdup(str); + + CHECK_CMP(strcmp(str, str2),==,0); + + TEST_PASSED; +} + +MAIN_TEST_DRIVER (memory_leak); From 5f2855a015e91b5b527efb4e9e111a504fe457f0 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 4 Sep 2024 09:27:27 +0200 Subject: [PATCH 07/37] refactor memory checks instrumentations --- .gitignore | 2 + basic_testing.h | 211 ++++++++++++------ ex/memory_checks.expected | 18 +- ex/memory_checks/tests/00_hash_map.c | 24 +- .../tests/03_non_portable_realloc.c | 2 +- ex/memory_checks/tests/08_lib_allocation.c | 2 +- .../tests/08_lib_allocation_cpp.cc | 15 ++ 7 files changed, 190 insertions(+), 84 deletions(-) create mode 100644 ex/memory_checks/tests/08_lib_allocation_cpp.cc diff --git a/.gitignore b/.gitignore index b6dee88..5d17dc1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ ex/**/basic_testing.h ex ws/**/basic_testing.h +*.o +*.out diff --git a/basic_testing.h b/basic_testing.h index 562506b..54e5699 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -19,6 +19,7 @@ #ifndef BASIC_TESTING_H_INCLUDED #define BASIC_TESTING_H_INCLUDED +#include #include #include #include @@ -255,7 +256,11 @@ static unsigned int bt_timeout = 3; /* three seconds */ BT_POSSIBLY_UNUSED static int bt_verbose = 1; -static int bt_mem_checks_disabled = 0; +/* Disabling the memory checks by default, they will be enabled in the + main function. The reason is that we do not want to keep track of + allocations happening before the main function gets invoked. +*/ +static int bt_mem_checks_disabled = 1; BT_POSSIBLY_UNUSED static int MEM_CHECKS_DISABLED () { @@ -421,21 +426,6 @@ void bt_mem_reset_allocator (void) { } \ } while (0) -// #ifdef __cplusplus -// extern "C" { -// #endif - -// extern void * __real_malloc (size_t); -// extern void __real_free (void *); -// extern void * __real_realloc (void *, size_t); -// extern void * __real_calloc (size_t, size_t); -// extern void * __real_reallocarray (void *, size_t, size_t); - -// #ifdef __cplusplus -// } -// #endif - - typedef enum { BT_MALLOC, @@ -587,6 +577,25 @@ static size_t bt_leaked_bytes (void) { return size; } +BT_POSSIBLY_UNUSED +static void bt_exit_handler (void) { + if (bt_mem_table_failed) { + fputs("\nWARNING: Leakage test is disabled\n", stderr); + abort(); + } + + size_t leaked = bt_leaked_bytes (); + bt_mem_table_free (); + if (leaked != 0) { + fprintf(stderr, "\nleaked %zu bytes\n", leaked); + abort(); + } +} + +#ifdef __cplusplus +const int bt_exit_handler_registration = atexit(bt_exit_handler); +#endif + #ifdef __cplusplus extern "C" { @@ -747,6 +756,7 @@ void * realloc (void * ptr, size_t new_size) { return ret; } +BT_POSSIBLY_UNUSED void * calloc (size_t nmemb, size_t size) { static void *(*libc_calloc)(size_t, size_t) = NULL; @@ -764,6 +774,7 @@ void * calloc (size_t nmemb, size_t size) { return p; } +BT_POSSIBLY_UNUSED void * reallocarray (void * ptr, size_t nmemb, size_t size) { static void *(*libc_reallocarray)(void *, size_t, size_t) = NULL; @@ -779,40 +790,128 @@ void * reallocarray (void * ptr, size_t nmemb, size_t size) { return realloc (ptr, len); } -#ifdef __cplusplus +BT_POSSIBLY_UNUSED +int vfprintf (FILE * stream, const char * format, va_list ap) { + static int (*libc_vfprintf)(FILE *, const char *, va_list) = NULL; + + if (!libc_vfprintf) + libc_vfprintf = (int (*)(FILE *, const char *, va_list)) dlsym(RTLD_NEXT, "vfprintf"); + + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; + bt_mem_checks_disabled = 1; + int result = libc_vfprintf(stream, format, ap); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + + return result; } -#endif +BT_POSSIBLY_UNUSED +int vprintf (const char * format, va_list ap) { + return vfprintf(stdout, format, ap); +} + +BT_POSSIBLY_UNUSED +int printf (const char * format, ...) { + va_list ap; + + va_start(ap, format); + int result = vprintf(format, ap); + va_end(ap); + + return result; +} + +BT_POSSIBLY_UNUSED +int fprintf (FILE * stream, const char * format, ...) { + va_list ap; + + va_start(ap, format); + int result = vfprintf(stream, format, ap); + va_end(ap); + + return result; +} + +BT_POSSIBLY_UNUSED +int fputs (const char * s, FILE * stream) { + static int (*libc_fputs)(const char *, FILE *) = NULL; + + if (!libc_fputs) + libc_fputs = (int (*)(const char *, FILE *)) dlsym(RTLD_NEXT, "fputs"); -// #ifdef __cplusplus -// extern "C" { + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; + bt_mem_checks_disabled = 1; + int result = libc_fputs(s, stream); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; -// void * __wrap__Znwm (size_t size) { -// void * p = __wrap_malloc(size); -// if (p) -// bt_mem_table_find (p)->allocator = BT_NEW; + return result; +} -// return p; -// } +BT_POSSIBLY_UNUSED +int puts (const char * s) { + static int (*libc_puts)(const char *) = NULL; -// void * __wrap__Znam (size_t size) { -// void * p = __wrap_malloc(size); -// if (p) -// bt_mem_table_find (p)->allocator = BT_NEW_ARRAY; + if (!libc_puts) + libc_puts = (int (*)(const char *)) dlsym(RTLD_NEXT, "puts"); -// return p; -// } + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; + bt_mem_checks_disabled = 1; + int result = libc_puts(s); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; -// void __wrap__ZdlPvm (void * ptr, size_t) { -// __wrap_free(ptr); -// } + return result; +} -// void __wrap__ZdaPv (void * ptr) { -// __wrap_free(ptr); -// } +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +void * operator new (std::size_t count) { + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; + bt_mem_checks_disabled = 1; + void * ptr = malloc(count); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + return ptr; +} + +void * operator new[] (std::size_t count) { + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; + bt_mem_checks_disabled = 1; + void * ptr = malloc(count); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + return ptr; +} + +void operator delete (void * ptr) noexcept { + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; + bt_mem_checks_disabled = 1; + free(ptr); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; +} + +void operator delete (void * ptr, std::size_t size) noexcept { + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; + bt_mem_checks_disabled = 1; + free(ptr); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; +} + +void operator delete[] (void * ptr) noexcept { + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; + bt_mem_checks_disabled = 1; + free(ptr); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; +} + +void operator delete[] (void * ptr, std::size_t size) noexcept { + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; + bt_mem_checks_disabled = 1; + free(ptr); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; +} +#endif -// } -// #endif struct bt_test_descriptor { const char * name; @@ -858,20 +957,7 @@ BT_POSSIBLY_UNUSED static int bt_run_test(const struct bt_test_descriptor * t) { if (RUNNING_ON_VALGRIND || !bt_fork_tests) { int result = t->test_function(); - if (result == BT_FAILURE) return result; - - if (bt_mem_table_failed) { - printf("\nWARNING: Leakage test is disabled in %s\n", t->name); - result = BT_FAILURE; - } else { - size_t leak = bt_leaked_bytes(); - if (leak != 0) { - printf("\nLeaked %zu bytes in %s\n", leak, t->name); - result = BT_FAILURE; - } - } bt_mem_reset_allocator(); - bt_mem_table_free(); return result; } pid_t pid; @@ -893,19 +979,6 @@ static int bt_run_test(const struct bt_test_descriptor * t) { if (bt_timeout > 0) alarm(bt_timeout); int result = t->test_function(); - if (result == BT_FAILURE) exit(result); - - if (bt_mem_table_failed) { - printf("\nWARNING: Leakage test is disabled in %s\n", t->name); - result = BT_FAILURE; - } else { - size_t leak = bt_leaked_bytes(); - if (leak != 0) { - printf("\nLeaked %zu bytes in %s\n", leak, t->name); - result = BT_FAILURE; - } - } - bt_mem_table_free(); exit(result); } else { /* Parent: Wait until child terminates and analyze its exit code. */ @@ -1059,11 +1132,17 @@ int bt_test_driver(int argc, char * argv[]) { #ifdef __cplusplus #define MAIN_TEST_DRIVER(...) \ int main(int argc, char * argv[]) { \ + bt_mem_checks_disabled = 0; \ + if (bt_exit_handler_registration) \ + fputs("WARNING: failed to register memory checks handler\n", stderr); \ return bt_test_driver(argc, argv); \ } #else #define MAIN_TEST_DRIVER(...) \ int main(int argc, char * argv[]) { \ + bt_mem_checks_disabled = 0; \ + if (atexit(bt_exit_handler)) \ + fputs("WARNING: failed to register memory checks handler\n", stderr); \ struct bt_test_descriptor * suite [] = { __VA_ARGS__ }; \ const unsigned n = sizeof(suite)/sizeof(struct bt_test_descriptor *); \ for (unsigned i = 0; i < n; ++i) \ diff --git a/ex/memory_checks.expected b/ex/memory_checks.expected index c16b63a..542577c 100644 --- a/ex/memory_checks.expected +++ b/ex/memory_checks.expected @@ -17,19 +17,23 @@ FAIL run 'tests/03_double_free_cpp' to see what went wrong run 'tests/03_double_free_cpp -d' with a debugger Running test 03_memory_leaks... -Leaked 32 bytes in memory_leak +leaked 32 bytes FAIL run 'tests/03_memory_leaks' to see what went wrong run 'tests/03_memory_leaks -d' with a debugger Running test 03_memory_leaks_cpp... -Leaked 32 bytes in memory_leak +leaked 32 bytes FAIL run 'tests/03_memory_leaks_cpp' to see what went wrong run 'tests/03_memory_leaks_cpp -d' with a debugger -Running test 03_memory_leaks_debug... FAIL +Running test 03_memory_leaks_debug... +leaked 32 bytes +FAIL run 'tests/03_memory_leaks_debug' to see what went wrong run 'tests/03_memory_leaks_debug -d' with a debugger -Running test 03_memory_leaks_debug_cpp... FAIL +Running test 03_memory_leaks_debug_cpp... +leaked 32 bytes +FAIL run 'tests/03_memory_leaks_debug_cpp' to see what went wrong run 'tests/03_memory_leaks_debug_cpp -d' with a debugger Running test 03_non_portable_malloc... @@ -66,3 +70,9 @@ Running test 06_scheduled_failures_debug... PASS Running test 06_scheduled_failures_debug_cpp... PASS Running test 07_calloc_reallocarray_failures... PASS Running test 07_calloc_reallocarray_failures_cpp... PASS +Running test 08_lib_allocation... +leaked 8 bytes +FAIL +Running test 08_lib_allocation_cpp... +leaked 8 bytes +FAIL \ No newline at end of file diff --git a/ex/memory_checks/tests/00_hash_map.c b/ex/memory_checks/tests/00_hash_map.c index 9310d76..db4b54c 100644 --- a/ex/memory_checks/tests/00_hash_map.c +++ b/ex/memory_checks/tests/00_hash_map.c @@ -314,15 +314,15 @@ TEST (map_insert_remove_series) { MAIN_TEST_DRIVER (compile, - map_init, - map_find_empty, - map_insert, - map_update, - map_insert_collisions, - map_update_collisions, - map_free, - map_remove, - map_remove_not_found, - map_remove_collisions, - map_remove_collisions_not_found, - map_insert_remove_series); + map_init, + map_find_empty, + map_insert, + map_update, + map_insert_collisions, + map_update_collisions, + map_free, + map_remove, + map_remove_not_found, + map_remove_collisions, + map_remove_collisions_not_found, + map_insert_remove_series); diff --git a/ex/memory_checks/tests/03_non_portable_realloc.c b/ex/memory_checks/tests/03_non_portable_realloc.c index 0e00b20..1485b99 100644 --- a/ex/memory_checks/tests/03_non_portable_realloc.c +++ b/ex/memory_checks/tests/03_non_portable_realloc.c @@ -14,7 +14,7 @@ TEST (realloc_zero_size) { void * s = realloc (p, 0); CHECK (s != NULL); - + TEST_PASSED; } diff --git a/ex/memory_checks/tests/08_lib_allocation.c b/ex/memory_checks/tests/08_lib_allocation.c index 87024a8..8e4be6d 100644 --- a/ex/memory_checks/tests/08_lib_allocation.c +++ b/ex/memory_checks/tests/08_lib_allocation.c @@ -4,7 +4,7 @@ TEST (memory_leak) { - char * str = "testing"; + const char * str = "testing"; char * str2 = strdup(str); CHECK_CMP(strcmp(str, str2),==,0); diff --git a/ex/memory_checks/tests/08_lib_allocation_cpp.cc b/ex/memory_checks/tests/08_lib_allocation_cpp.cc new file mode 100644 index 0000000..682079e --- /dev/null +++ b/ex/memory_checks/tests/08_lib_allocation_cpp.cc @@ -0,0 +1,15 @@ +#include "basic_testing.h" +#include + + + +TEST (memory_leak) { + const char * str = "testing"; + char * str2 = strdup(str); + + CHECK_CMP(strcmp(str, str2),==,0); + + TEST_PASSED; +} + +MAIN_TEST_DRIVER (); From 984a51be0a93552d89b366d0d679435a0902a82e Mon Sep 17 00:00:00 2001 From: pako-23 Date: Thu, 5 Sep 2024 21:04:47 +0200 Subject: [PATCH 08/37] Improvements to the memory allocation features. - Add instrumentation for new/new[]/delete/delete[] in C++ - Add == range comparison for double - Change memory instrumentation strategy to use dlsym instead of wrapping the symbol at link time - Improvements in budget allocation, ie. better handling of changes of budget within a test - Introduce more tests for memory allocation features --- Makefile | 2 +- basic_testing.h | 244 ++++++++-- basic_testing.mk | 2 - ex ws/example3 ws/tests/test2.cc | 1 + ex/example3/tests/test2.cc | 1 + ex/memory_checks.expected | 109 +++-- ex/memory_checks/array.c | 42 +- ex/memory_checks/array.h | 5 + ex/memory_checks/tests/00_hash_map.c | 15 - ex/memory_checks/tests/03_double_free.c | 7 +- .../tests/03_memory_leak_calloc.c | 19 + .../tests/03_memory_leak_calloc_debug.c | 20 + .../tests/03_memory_leak_malloc.c | 19 + .../tests/03_memory_leak_malloc_debug.c | 20 + .../tests/03_memory_leak_realloc.c | 20 + .../tests/03_memory_leak_realloc_debug.c | 20 + .../tests/03_memory_leak_reallocarray.c | 20 + .../tests/03_memory_leak_reallocarray_debug.c | 20 + ex/memory_checks/tests/03_non_malloc_free.c | 17 + .../tests/03_non_portable_malloc.c | 8 +- .../tests/03_non_portable_realloc.c | 8 +- .../tests/04_budget_allocations.c | 45 +- .../tests/05_byte_budget_allocations.c | 50 ++- ex/memory_checks/tests/08_fopen_leak.c | 15 + ex/memory_checks/tests/08_stdlib_functions.c | 419 +++++++++++++++++ .../{08_lib_allocation.c => 08_strdup_leak.c} | 0 ex/memory_checks/tests/08_tmpfile_leak.c | 15 + ex/memory_checks/tests/08_tmpnum_leak.c | 12 + ex/memory_checks_cpp.expected | 189 ++++++++ ex/memory_checks_cpp/Makefile | 3 + ex/memory_checks_cpp/array.cc | 221 +++++++++ ex/memory_checks_cpp/array.h | 71 +++ .../tests/00_hash_map.cc} | 30 +- .../tests/01_fail_allocations.cc} | 92 +++- .../tests/01_fail_allocations_debug.cc} | 2 +- .../tests/02_allocations_recording.cc} | 125 +++++- .../tests/03_delete_array_malloc_object.cc | 18 + .../tests/03_delete_array_new_object.cc | 18 + .../tests/03_delete_malloc_object.cc | 18 + .../tests/03_delete_new_array_object.cc | 18 + .../tests/03_double_delete.cc} | 7 +- .../tests/03_double_delete_array.cc} | 9 +- ex/memory_checks_cpp/tests/03_double_free.cc | 17 + .../tests/03_free_new_array_object.cc | 18 + .../tests/03_free_new_object.cc | 18 + .../tests/03_memory_leak_calloc.cc | 19 + .../tests/03_memory_leak_calloc_debug.cc | 20 + .../tests/03_memory_leak_malloc.cc | 19 + .../tests/03_memory_leak_malloc_debug.cc | 20 + .../tests/03_memory_leak_new.cc | 19 + .../tests/03_memory_leak_new_array.cc | 20 + .../tests/03_memory_leak_new_array_debug.cc | 20 + .../tests/03_memory_leak_new_debug.cc | 20 + .../tests/03_memory_leak_realloc.cc | 20 + .../tests/03_memory_leak_realloc_debug.cc | 20 + .../tests/03_memory_leak_reallocarray.cc | 20 + .../03_memory_leak_reallocarray_debug.cc | 20 + .../tests/03_memory_leaks.cc} | 5 +- .../tests/03_memory_leaks_debug.cc} | 4 +- .../tests/03_non_malloc_free.cc | 17 + .../tests/03_non_new_array_delete.cc | 17 + .../tests/03_non_new_delete.cc | 17 + .../tests/03_non_portable_malloc.cc | 19 + .../tests/03_non_portable_realloc.cc} | 11 +- .../tests/03_static_object_leaked.cc | 19 + .../tests/03_static_object_non_leaked.cc | 33 ++ .../tests/04_budget_allocations.cc} | 299 ++++++++++++- .../tests/04_budget_allocations_debug.cc} | 2 +- .../tests/05_byte_budget_allocations.cc} | 325 +++++++++++++- .../05_byte_budget_allocations_debug.cc} | 2 +- .../tests/06_scheduled_failures.cc} | 127 +++++- .../tests/06_scheduled_failures_debug.cc} | 2 +- .../tests/07_calloc_reallocarray_failures.cc} | 0 ex/memory_checks_cpp/tests/08_fopen_leak.cc | 15 + .../tests/08_stdlib_functions.cc | 422 ++++++++++++++++++ .../tests/08_strdup_leak.cc} | 4 +- ex/memory_checks_cpp/tests/08_tmpfile_leak.cc | 15 + ex/memory_checks_cpp/tests/08_tmpnum_leak.cc | 12 + 78 files changed, 3430 insertions(+), 223 deletions(-) create mode 100644 ex/memory_checks/tests/03_memory_leak_calloc.c create mode 100644 ex/memory_checks/tests/03_memory_leak_calloc_debug.c create mode 100644 ex/memory_checks/tests/03_memory_leak_malloc.c create mode 100644 ex/memory_checks/tests/03_memory_leak_malloc_debug.c create mode 100644 ex/memory_checks/tests/03_memory_leak_realloc.c create mode 100644 ex/memory_checks/tests/03_memory_leak_realloc_debug.c create mode 100644 ex/memory_checks/tests/03_memory_leak_reallocarray.c create mode 100644 ex/memory_checks/tests/03_memory_leak_reallocarray_debug.c create mode 100644 ex/memory_checks/tests/03_non_malloc_free.c create mode 100644 ex/memory_checks/tests/08_fopen_leak.c create mode 100644 ex/memory_checks/tests/08_stdlib_functions.c rename ex/memory_checks/tests/{08_lib_allocation.c => 08_strdup_leak.c} (100%) create mode 100644 ex/memory_checks/tests/08_tmpfile_leak.c create mode 100644 ex/memory_checks/tests/08_tmpnum_leak.c create mode 100644 ex/memory_checks_cpp.expected create mode 100644 ex/memory_checks_cpp/Makefile create mode 100644 ex/memory_checks_cpp/array.cc create mode 100644 ex/memory_checks_cpp/array.h rename ex/{memory_checks/tests/00_hash_map_cpp.cc => memory_checks_cpp/tests/00_hash_map.cc} (91%) rename ex/{memory_checks/tests/01_fail_allocations_cpp.cc => memory_checks_cpp/tests/01_fail_allocations.cc} (83%) rename ex/{memory_checks/tests/03_memory_leaks_debug_cpp.cc => memory_checks_cpp/tests/01_fail_allocations_debug.cc} (74%) rename ex/{memory_checks/tests/02_allocations_recording_cpp.cc => memory_checks_cpp/tests/02_allocations_recording.cc} (53%) create mode 100644 ex/memory_checks_cpp/tests/03_delete_array_malloc_object.cc create mode 100644 ex/memory_checks_cpp/tests/03_delete_array_new_object.cc create mode 100644 ex/memory_checks_cpp/tests/03_delete_malloc_object.cc create mode 100644 ex/memory_checks_cpp/tests/03_delete_new_array_object.cc rename ex/{memory_checks/tests/03_non_portable_malloc_cpp.cc => memory_checks_cpp/tests/03_double_delete.cc} (62%) rename ex/{memory_checks/tests/03_double_free_cpp.cc => memory_checks_cpp/tests/03_double_delete_array.cc} (54%) create mode 100644 ex/memory_checks_cpp/tests/03_double_free.cc create mode 100644 ex/memory_checks_cpp/tests/03_free_new_array_object.cc create mode 100644 ex/memory_checks_cpp/tests/03_free_new_object.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_calloc.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_calloc_debug.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_malloc.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_malloc_debug.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_new.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_new_array.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_new_array_debug.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_new_debug.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_realloc.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_realloc_debug.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_reallocarray.cc create mode 100644 ex/memory_checks_cpp/tests/03_memory_leak_reallocarray_debug.cc rename ex/{memory_checks/tests/03_memory_leaks_cpp.cc => memory_checks_cpp/tests/03_memory_leaks.cc} (86%) rename ex/{memory_checks/tests/04_budget_allocations_debug_cpp.cc => memory_checks_cpp/tests/03_memory_leaks_debug.cc} (60%) create mode 100644 ex/memory_checks_cpp/tests/03_non_malloc_free.cc create mode 100644 ex/memory_checks_cpp/tests/03_non_new_array_delete.cc create mode 100644 ex/memory_checks_cpp/tests/03_non_new_delete.cc create mode 100644 ex/memory_checks_cpp/tests/03_non_portable_malloc.cc rename ex/{memory_checks/tests/03_non_portable_realloc_cpp.cc => memory_checks_cpp/tests/03_non_portable_realloc.cc} (54%) create mode 100644 ex/memory_checks_cpp/tests/03_static_object_leaked.cc create mode 100644 ex/memory_checks_cpp/tests/03_static_object_non_leaked.cc rename ex/{memory_checks/tests/04_budget_allocations_cpp.cc => memory_checks_cpp/tests/04_budget_allocations.cc} (51%) rename ex/{memory_checks/tests/01_fail_allocations_debug_cpp.cc => memory_checks_cpp/tests/04_budget_allocations_debug.cc} (70%) rename ex/{memory_checks/tests/05_byte_budget_allocations_cpp.cc => memory_checks_cpp/tests/05_byte_budget_allocations.cc} (50%) rename ex/{memory_checks/tests/05_byte_budget_allocations_debug_cpp.cc => memory_checks_cpp/tests/05_byte_budget_allocations_debug.cc} (68%) rename ex/{memory_checks/tests/06_scheduled_failures_cpp.cc => memory_checks_cpp/tests/06_scheduled_failures.cc} (67%) rename ex/{memory_checks/tests/06_scheduled_failures_debug_cpp.cc => memory_checks_cpp/tests/06_scheduled_failures_debug.cc} (70%) rename ex/{memory_checks/tests/07_calloc_reallocarray_failures_cpp.cc => memory_checks_cpp/tests/07_calloc_reallocarray_failures.cc} (100%) create mode 100644 ex/memory_checks_cpp/tests/08_fopen_leak.cc create mode 100644 ex/memory_checks_cpp/tests/08_stdlib_functions.cc rename ex/{memory_checks/tests/08_lib_allocation_cpp.cc => memory_checks_cpp/tests/08_strdup_leak.cc} (77%) create mode 100644 ex/memory_checks_cpp/tests/08_tmpfile_leak.cc create mode 100644 ex/memory_checks_cpp/tests/08_tmpnum_leak.cc diff --git a/Makefile b/Makefile index 8766da8..042c444 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ all: all-examples EXAMPLES = ex/example1 ex/example2 ex/example3 ex/example4 \ - ex/example5 ex/example6 ex/example7 ex/example8 ex/memory_checks \ + ex/example5 ex/example6 ex/example7 ex/example8 ex/memory_checks ex/memory_checks_cpp \ 'ex ws/example1 ws' 'ex ws/example2 ws' 'ex ws/example3 ws' 'ex ws/example4 ws' \ 'ex ws/example5 ws' 'ex ws/example6 ws' 'ex ws/example7 ws' 'ex ws/example8 ws' diff --git a/basic_testing.h b/basic_testing.h index 54e5699..8907f95 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -29,9 +29,13 @@ #include #include #include +#include +#include +#include #ifdef __cplusplus #include +#include #endif #include @@ -118,7 +122,10 @@ #define CHECK_CMP(X,OP,Y) do { \ auto x_ = (X); \ decltype (x_) y_ = (Y); \ - if (!(x_ OP y_)) { \ + if (!(x_ OP y_) \ + && !(typeid(x_) == typeid(double) \ + && strcmp(#OP, "==") == 0 \ + && fabs (x_ - y_) <= DBL_EPSILON)) { \ std::cout << std::endl <<__FILE__ << ":" << __LINE__ \ << ": Assertion '"#X" "#OP" "#Y"' failed: " \ << x_ << " "#OP" " << y_ << std::endl; \ @@ -194,7 +201,7 @@ static int check_cmp_double (double x, double y, const char * op, const char * filename, int line) { int res; switch (bt_operator(op)) { - case BT_EQ: res = (x == y); break; + case BT_EQ: res = (fabs (x - y) <= DBL_EPSILON); break; case BT_NE: res = (x != y); break; case BT_LE: res = (x <= y); break; case BT_GE: res = (x >= y); break; @@ -375,9 +382,19 @@ static void bt_mem_fail_all (void) { count as -1. */ void bt_mem_set_allocation_budget (size_t budget) { + if (!bt_mem_budget_enabled) + bt_mem_budget_curr = budget; + else if (bt_mem_budget == budget) + return; + else if (bt_mem_budget < budget) + bt_mem_budget_curr += budget-bt_mem_budget; + else if (bt_mem_budget - bt_mem_budget_curr >= budget) + bt_mem_budget_curr = 0; + else + bt_mem_budget_curr = budget - (bt_mem_budget - bt_mem_budget_curr); + bt_mem_budget_enabled = 1; bt_mem_budget = budget; - bt_mem_budget_curr = budget; } #define MEM_SET_ALLOCATION_BUDGET(B) do { \ @@ -394,9 +411,20 @@ void bt_mem_set_allocation_budget (size_t budget) { allocated with pointer `p'. */ void bt_mem_set_bytes_budget (size_t budget) { + if (!bt_mem_bytes_budget_enabled) + bt_mem_bytes_budget_curr = budget; + else if (bt_mem_bytes_budget == budget) + return; + else if (bt_mem_bytes_budget < budget) + bt_mem_bytes_budget_curr += budget-bt_mem_bytes_budget; + else if (bt_mem_bytes_budget - bt_mem_bytes_budget_curr >= budget) + bt_mem_bytes_budget_curr = 0; + else + bt_mem_bytes_budget_curr = budget - (bt_mem_bytes_budget - bt_mem_bytes_budget_curr); + + bt_mem_bytes_budget_enabled = 1; bt_mem_bytes_budget = budget; - bt_mem_bytes_budget_curr = budget; } #define MEM_SET_BYTES_BUDGET(B) do { \ @@ -427,16 +455,20 @@ void bt_mem_reset_allocator (void) { } while (0) -typedef enum { - BT_MALLOC, - BT_NEW, - BT_NEW_ARRAY -} bt_allocator_t; +#ifdef __cplusplus +enum bt_allocator { + MALLOC, + NEW, + NEW_ARRAY, +}; +#endif struct bt_mem_node { void * address; size_t size; - bt_allocator_t allocator; +#ifdef __cplusplus + enum bt_allocator allocator; +#endif int deleted; }; @@ -521,6 +553,9 @@ static int bt_mem_rehash (size_t new_cap) { struct bt_mem_node * node = bt_mem_table_find_or_insert(tmp[i].address); node->address = tmp[i].address; node->size = tmp[i].size; +#ifdef __cplusplus + node->allocator = tmp[i].allocator; +#endif } } if (tmp) free(tmp); @@ -621,7 +656,7 @@ void * malloc (size_t size) { return 0; } } - if (bt_mem_failure_size > 0) { + if (bt_mem_failure_size > 0) { if (size < bt_mem_failure_size) { bt_mem_failure_size -= size; } else { @@ -645,7 +680,9 @@ void * malloc (size_t size) { struct bt_mem_node * node = bt_mem_table_insert (ret); if (ret) { - node->allocator = BT_MALLOC; +#ifdef __cplusplus + node->allocator = bt_allocator::MALLOC; +#endif node->size = size; } else bt_mem_table_failed = 1; @@ -653,6 +690,54 @@ void * malloc (size_t size) { return ret; } + + + +#ifdef __cplusplus +BT_POSSIBLY_UNUSED +void bt_mem_deallocator (void * ptr, enum bt_allocator allocator) { + static void (*libc_free)(void *) = NULL; + + if (!libc_free) + libc_free = (void (*)(void *)) dlsym(RTLD_NEXT, "free"); + + if (bt_mem_checks_disabled) { + libc_free(ptr); + return; + } + + const struct bt_mem_node *p = bt_mem_table_find(ptr); + if (!p) { + fputs("\nmemory was not allocated via malloc/new/new[], or possible double free/delete/delete[]\n", stderr); + if (bt_fork_tests) exit(BT_FAILURE); + else abort(); + } else if (p->allocator != allocator) { + if (p->allocator == bt_allocator::MALLOC) + fputs("\nobjects allocated with malloc should be deallocated free\n", stderr); + else if (p->allocator == bt_allocator::NEW) + fputs("\nobjects allocated with new should be deallocated delete\n", stderr); + else if (p->allocator == bt_allocator::NEW_ARRAY) + fputs("\nobjects allocated with new[] should be deallocated delete[]\n", stderr); + + if (bt_fork_tests) exit(BT_FAILURE); + else abort(); + } + + if (bt_mem_budget_enabled && ++bt_mem_budget_curr > bt_mem_budget) + bt_mem_budget_curr = bt_mem_budget; + else if (bt_mem_bytes_budget_enabled) { + bt_mem_bytes_budget_curr += p->size; + if (bt_mem_bytes_budget_curr > bt_mem_bytes_budget) + bt_mem_bytes_budget_curr = bt_mem_bytes_budget; + } + bt_mem_table_remove(ptr); + libc_free(ptr); +} + +void free (void * ptr) { + bt_mem_deallocator (ptr, bt_allocator::MALLOC); +} +#else BT_POSSIBLY_UNUSED void free (void * ptr) { static void (*libc_free)(void *) = NULL; @@ -682,6 +767,7 @@ void free (void * ptr) { bt_mem_table_remove(ptr); libc_free(ptr); } +#endif BT_POSSIBLY_UNUSED void * realloc (void * ptr, size_t new_size) { @@ -724,16 +810,18 @@ void * realloc (void * ptr, size_t new_size) { fputs("\nrealloc of not heap allocated memory\n", stderr); if (bt_fork_tests) exit(BT_FAILURE); else abort(); - } else if (node->allocator != BT_MALLOC) { - if (node->allocator == BT_NEW_ARRAY) - fputs("\nrealloc of memory allocated with 'new'\n", stderr); - else - fputs("\nrealloc of memory allocated with 'new[]'\n", stderr); + } +#ifdef __cplusplus + if (node->allocator != bt_allocator::MALLOC) { + fputs("\nrealloc of memory not allocated via malloc\n", stderr); if (bt_fork_tests) exit(BT_FAILURE); else abort(); - } else if (bt_mem_bytes_budget_enabled && bt_mem_bytes_budget_curr + node->size < new_size) + } +#endif + if (bt_mem_bytes_budget_enabled && bt_mem_bytes_budget_curr + node->size < new_size) return NULL; + void * ret = libc_realloc (ptr, new_size); if (!ret) return NULL; @@ -861,54 +949,138 @@ int puts (const char * s) { return result; } + +BT_POSSIBLY_UNUSED +char * strerror (int errnum) { + static char *(*libc_strerror)(int) = NULL; -#ifdef __cplusplus -} -#endif + if (!libc_strerror) + libc_strerror = (char *(*)(int)) dlsym(RTLD_NEXT, "strerror"); -#ifdef __cplusplus -void * operator new (std::size_t count) { int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; bt_mem_checks_disabled = 1; - void * ptr = malloc(count); + char * result = libc_strerror (errnum); bt_mem_checks_disabled = prev_bt_mem_checks_disabled; - return ptr; + + return result; } -void * operator new[] (std::size_t count) { +BT_POSSIBLY_UNUSED +time_t mktime (struct tm * tp) { + static time_t (*libc_mktime)(struct tm *) = NULL; + + if (!libc_mktime) + libc_mktime = (time_t (*)(struct tm *)) dlsym(RTLD_NEXT, "mktime"); + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; bt_mem_checks_disabled = 1; - void * ptr = malloc(count); + time_t result = libc_mktime (tp); bt_mem_checks_disabled = prev_bt_mem_checks_disabled; - return ptr; + + return result; } -void operator delete (void * ptr) noexcept { +BT_POSSIBLY_UNUSED +struct tm * gmtime (const time_t * tp) { + static struct tm *(*libc_gmtime)(const time_t *) = NULL; + + if (!libc_gmtime) + libc_gmtime = (struct tm *(*)(const time_t *)) dlsym(RTLD_NEXT, "gmtime"); + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; bt_mem_checks_disabled = 1; - free(ptr); + struct tm * result = libc_gmtime (tp); bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + + return result; } -void operator delete (void * ptr, std::size_t size) noexcept { +BT_POSSIBLY_UNUSED +struct tm * localtime (const time_t * tp) { + static struct tm *(*libc_localtime)(const time_t *) = NULL; + + if (!libc_localtime) + libc_localtime = (struct tm *(*)(const time_t *)) dlsym(RTLD_NEXT, "localtime"); + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; bt_mem_checks_disabled = 1; - free(ptr); + struct tm * result = libc_localtime (tp); bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + + return result; } -void operator delete[] (void * ptr) noexcept { +BT_POSSIBLY_UNUSED +char * asctime (const struct tm * tp) { + static char *(*libc_asctime)(const struct tm *) = NULL; + + if (!libc_asctime) + libc_asctime = (char *(*)(const struct tm *)) dlsym(RTLD_NEXT, "asctime"); + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; bt_mem_checks_disabled = 1; - free(ptr); + char * result = libc_asctime (tp); bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + + return result; } -void operator delete[] (void * ptr, std::size_t size) noexcept { +BT_POSSIBLY_UNUSED +char * ctime (const time_t * tp) { + static char *(*libc_ctime)(const time_t *) = NULL; + + if (!libc_ctime) + libc_ctime = (char *(*)(const time_t *)) dlsym(RTLD_NEXT, "ctime"); + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; bt_mem_checks_disabled = 1; - free(ptr); + char * result = libc_ctime (tp); bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + + return result; +} + + + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +void * operator new (std::size_t count) { + void * ptr = malloc(count); + if (!ptr) throw std::bad_alloc {}; + else if (bt_mem_checks_disabled || bt_mem_table_failed) + return ptr; + struct bt_mem_node * node = bt_mem_table_find (ptr); + node->allocator = bt_allocator::NEW; + return ptr; +} + +void * operator new[] (std::size_t count) { + void * ptr = malloc(count); + if (!ptr) throw std::bad_alloc {}; + else if (bt_mem_checks_disabled || bt_mem_table_failed) + return ptr; + struct bt_mem_node * node = bt_mem_table_find (ptr); + node->allocator = bt_allocator::NEW_ARRAY; + return ptr; +} + +void operator delete (void * ptr) noexcept { + bt_mem_deallocator (ptr, bt_allocator::NEW); +} + +void operator delete (void * ptr, std::size_t size) noexcept { + bt_mem_deallocator (ptr, bt_allocator::NEW); +} + +void operator delete[] (void * ptr) noexcept { + bt_mem_deallocator (ptr, bt_allocator::NEW_ARRAY); +} + +void operator delete[] (void * ptr, std::size_t size) noexcept { + bt_mem_deallocator (ptr, bt_allocator::NEW_ARRAY); } #endif diff --git a/basic_testing.mk b/basic_testing.mk index 1ad0a5d..b0317db 100644 --- a/basic_testing.mk +++ b/basic_testing.mk @@ -184,8 +184,6 @@ check-io-sh: compile $(TESTS_IO) $(TESTS_SH) $(PROGRAMS_DRIVERS) done; \ test_summary 'Summary: PASS ' -# BT_LDFLAGS := -Wl,--wrap=malloc,--wrap=free,--wrap=realloc,--wrap=calloc,--wrap=reallocarray -# BT_CXXLDFLAGS := -Wl,--wrap=_Znwm,--wrap=_Znam,--wrap=_ZdlPvm,--wrap=_ZdaPv $(TESTS_DIR)/%: $(TESTS_DIR)/%.c $(OBJECTS) $(CC) $(CFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.c $(OBJECTS) -o $@ diff --git a/ex ws/example3 ws/tests/test2.cc b/ex ws/example3 ws/tests/test2.cc index 53bb995..7f27db1 100644 --- a/ex ws/example3 ws/tests/test2.cc +++ b/ex ws/example3 ws/tests/test2.cc @@ -99,6 +99,7 @@ TEST(large_trim) { CHECK_CMP(total_quantity(l), ==, 0); CHECK_CMP(total_quantity(l2), ==, 0); delete_log(l); + delete_log(l2); TEST_PASSED; } diff --git a/ex/example3/tests/test2.cc b/ex/example3/tests/test2.cc index 53bb995..7f27db1 100644 --- a/ex/example3/tests/test2.cc +++ b/ex/example3/tests/test2.cc @@ -99,6 +99,7 @@ TEST(large_trim) { CHECK_CMP(total_quantity(l), ==, 0); CHECK_CMP(total_quantity(l2), ==, 0); delete_log(l); + delete_log(l2); TEST_PASSED; } diff --git a/ex/memory_checks.expected b/ex/memory_checks.expected index 542577c..699a355 100644 --- a/ex/memory_checks.expected +++ b/ex/memory_checks.expected @@ -1,78 +1,101 @@ Running test 00_hash_map... PASS -Running test 00_hash_map_cpp... PASS Running test 01_fail_allocations... PASS -Running test 01_fail_allocations_cpp... PASS Running test 01_fail_allocations_debug... PASS -Running test 01_fail_allocations_debug_cpp... PASS Running test 02_allocations_recording... PASS -Running test 02_allocations_recording_cpp... PASS -Running test 03_double_free... +Running test 03_double_free... memory was not allocated via malloc, or possible double free FAIL run 'tests/03_double_free' to see what went wrong run 'tests/03_double_free -d' with a debugger -Running test 03_double_free_cpp... -memory was not allocated via malloc, or possible double free +Running test 03_memory_leak_calloc... +leaked 24 bytes +FAIL +run 'tests/03_memory_leak_calloc' to see what went wrong +run 'tests/03_memory_leak_calloc -d' with a debugger +Running test 03_memory_leak_calloc_debug... +leaked 24 bytes +FAIL +run 'tests/03_memory_leak_calloc_debug' to see what went wrong +run 'tests/03_memory_leak_calloc_debug -d' with a debugger +Running test 03_memory_leak_malloc... +leaked 24 bytes +FAIL +run 'tests/03_memory_leak_malloc' to see what went wrong +run 'tests/03_memory_leak_malloc -d' with a debugger +Running test 03_memory_leak_malloc_debug... +leaked 24 bytes +FAIL +run 'tests/03_memory_leak_malloc_debug' to see what went wrong +run 'tests/03_memory_leak_malloc_debug -d' with a debugger +Running test 03_memory_leak_realloc... +leaked 56 bytes FAIL -run 'tests/03_double_free_cpp' to see what went wrong -run 'tests/03_double_free_cpp -d' with a debugger -Running test 03_memory_leaks... +run 'tests/03_memory_leak_realloc' to see what went wrong +run 'tests/03_memory_leak_realloc -d' with a debugger +Running test 03_memory_leak_realloc_debug... +leaked 56 bytes +FAIL +run 'tests/03_memory_leak_realloc_debug' to see what went wrong +run 'tests/03_memory_leak_realloc_debug -d' with a debugger +Running test 03_memory_leak_reallocarray... +leaked 56 bytes +FAIL +run 'tests/03_memory_leak_reallocarray' to see what went wrong +run 'tests/03_memory_leak_reallocarray -d' with a debugger +Running test 03_memory_leak_reallocarray_debug... +leaked 56 bytes +FAIL +run 'tests/03_memory_leak_reallocarray_debug' to see what went wrong +run 'tests/03_memory_leak_reallocarray_debug -d' with a debugger +Running test 03_memory_leaks... leaked 32 bytes FAIL run 'tests/03_memory_leaks' to see what went wrong run 'tests/03_memory_leaks -d' with a debugger -Running test 03_memory_leaks_cpp... -leaked 32 bytes -FAIL -run 'tests/03_memory_leaks_cpp' to see what went wrong -run 'tests/03_memory_leaks_cpp -d' with a debugger -Running test 03_memory_leaks_debug... +Running test 03_memory_leaks_debug... leaked 32 bytes FAIL run 'tests/03_memory_leaks_debug' to see what went wrong run 'tests/03_memory_leaks_debug -d' with a debugger -Running test 03_memory_leaks_debug_cpp... -leaked 32 bytes +Running test 03_non_malloc_free... +memory was not allocated via malloc, or possible double free FAIL -run 'tests/03_memory_leaks_debug_cpp' to see what went wrong -run 'tests/03_memory_leaks_debug_cpp -d' with a debugger -Running test 03_non_portable_malloc... +run 'tests/03_non_malloc_free' to see what went wrong +run 'tests/03_non_malloc_free -d' with a debugger +Running test 03_non_portable_malloc... malloc with size 0 is not portable FAIL run 'tests/03_non_portable_malloc' to see what went wrong run 'tests/03_non_portable_malloc -d' with a debugger -Running test 03_non_portable_malloc_cpp... -malloc with size 0 is not portable -FAIL -run 'tests/03_non_portable_malloc_cpp' to see what went wrong -run 'tests/03_non_portable_malloc_cpp -d' with a debugger -Running test 03_non_portable_realloc... +Running test 03_non_portable_realloc... realloc with size 0 is not portable + +leaked 10 bytes FAIL run 'tests/03_non_portable_realloc' to see what went wrong run 'tests/03_non_portable_realloc -d' with a debugger -Running test 03_non_portable_realloc_cpp... -realloc with size 0 is not portable -FAIL -run 'tests/03_non_portable_realloc_cpp' to see what went wrong -run 'tests/03_non_portable_realloc_cpp -d' with a debugger Running test 04_budget_allocations... PASS -Running test 04_budget_allocations_cpp... PASS Running test 04_budget_allocations_debug... PASS -Running test 04_budget_allocations_debug_cpp... PASS Running test 05_byte_budget_allocations... PASS -Running test 05_byte_budget_allocations_cpp... PASS Running test 05_byte_budget_allocations_debug... PASS -Running test 05_byte_budget_allocations_debug_cpp... PASS Running test 06_scheduled_failures... PASS -Running test 06_scheduled_failures_cpp... PASS Running test 06_scheduled_failures_debug... PASS -Running test 06_scheduled_failures_debug_cpp... PASS Running test 07_calloc_reallocarray_failures... PASS -Running test 07_calloc_reallocarray_failures_cpp... PASS -Running test 08_lib_allocation... -leaked 8 bytes +Running test 08_fopen_leak... FAIL -Running test 08_lib_allocation_cpp... +run 'tests/08_fopen_leak' to see what went wrong +run 'tests/08_fopen_leak -d' with a debugger +Running test 08_stdlib_functions... PASS +Running test 08_strdup_leak... leaked 8 bytes -FAIL \ No newline at end of file +FAIL +run 'tests/08_strdup_leak' to see what went wrong +run 'tests/08_strdup_leak -d' with a debugger +Running test 08_tmpfile_leak... +FAIL +run 'tests/08_tmpfile_leak' to see what went wrong +run 'tests/08_tmpfile_leak -d' with a debugger +Running test 08_tmpnum_leak... +FAIL +run 'tests/08_tmpnum_leak' to see what went wrong +run 'tests/08_tmpnum_leak -d' with a debugger diff --git a/ex/memory_checks/array.c b/ex/memory_checks/array.c index 27172ba..d5ef9b9 100644 --- a/ex/memory_checks/array.c +++ b/ex/memory_checks/array.c @@ -6,7 +6,7 @@ static size_t initial_cap = 8; -struct array * array_new(void) { +struct array * array_new (void) { struct array * a = malloc(sizeof(struct array)); if (!a) return NULL; @@ -16,34 +16,32 @@ struct array * array_new(void) { return a; } -struct array * array_new_calloc(void) -{ +struct array * array_new_calloc (void) { return calloc(1, sizeof(struct array)); } -void array_free(struct array * array) { +void array_free (struct array * array) { if (array->cap) free(array->data); free(array); } -void array_free_leak(struct array * array) { +void array_free_leak (struct array * array) { free(array); } - -size_t array_length(struct array * array) { +size_t array_length (struct array * array) { return array->len; } -size_t array_capacity(struct array * array) { +size_t array_capacity (struct array * array) { return array->cap; } -int array_element(struct array * array, size_t index) { +int array_element (struct array * array, size_t index) { return array->data[index]; } -int array_append(struct array * array, int element) { +int array_append (struct array * array, int element) { if (array->len == array->cap) { size_t new_cap = array->cap ? 2*array->cap : initial_cap; @@ -58,7 +56,7 @@ int array_append(struct array * array, int element) { return 1; } -int array_append_reallocarray(struct array * array, int element) { +int array_append_reallocarray (struct array * array, int element) { if (array->len == array->cap) { size_t new_cap = array->cap ? 2*array->cap : initial_cap; @@ -72,3 +70,25 @@ int array_append_reallocarray(struct array * array, int element) { array->data[array->len++] = element; return 1; } + +void double_free (void) { + int a = 10; + void * p = malloc (10); + if (a < 20) free (p); + free (p); +} + +void non_malloc_free (void) { + int a = 10; + int * p; + if (a < 20) p = &a; + free (p); +} + +void * malloc_zero_size (void) { + return malloc (0); +} + +void * realloc_zero_size (void * ptr) { + return realloc (ptr, 0); +} diff --git a/ex/memory_checks/array.h b/ex/memory_checks/array.h index fad2c01..2e0b6c6 100644 --- a/ex/memory_checks/array.h +++ b/ex/memory_checks/array.h @@ -19,4 +19,9 @@ int array_element(struct array * array, size_t index); int array_append(struct array * array, int value); int array_append_reallocarray(struct array * array, int value); +void double_free (void); +void non_malloc_free (void); +void * malloc_zero_size (void); +void * realloc_zero_size (void * ptr); + #endif diff --git a/ex/memory_checks/tests/00_hash_map.c b/ex/memory_checks/tests/00_hash_map.c index db4b54c..59ee7d0 100644 --- a/ex/memory_checks/tests/00_hash_map.c +++ b/ex/memory_checks/tests/00_hash_map.c @@ -29,7 +29,6 @@ TEST (map_insert) { struct bt_mem_node * ins_node = bt_mem_table_insert (&i); CHECK (ins_node != NULL); ins_node->size = 12; - ins_node->allocator = BT_MALLOC; struct bt_mem_node * node = bt_mem_table_find (&i); CHECK (node != NULL); @@ -51,7 +50,6 @@ TEST (map_update) { struct bt_mem_node * ins_node = bt_mem_table_insert (&i); CHECK (ins_node != NULL); ins_node->size = 12; - ins_node->allocator = BT_MALLOC; struct bt_mem_node * node = bt_mem_table_find (&i); CHECK (node != NULL); @@ -62,7 +60,6 @@ TEST (map_update) { size_t capacity = bt_mem_table_capacity; ins_node = bt_mem_table_insert (&i); - ins_node->allocator = BT_NEW; ins_node->size = 15; CHECK (node != NULL); CHECK_CMP (node->size,==,15); @@ -88,7 +85,6 @@ TEST (map_insert_collisions) { for (size_t i = 0; i < len; ++i) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK(node != NULL); - node->allocator = BT_MALLOC; node->size = items[i]; } @@ -96,7 +92,6 @@ TEST (map_insert_collisions) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); - CHECK_CMP (node->allocator,==,BT_MALLOC); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); @@ -120,7 +115,6 @@ TEST (map_update_collisions) { for (size_t i = 0; i < len; ++i) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK(node != NULL); - node->allocator = BT_MALLOC; node->size = items[i]; } @@ -128,7 +122,6 @@ TEST (map_update_collisions) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); - CHECK_CMP (node->allocator,==,BT_MALLOC); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); @@ -141,7 +134,6 @@ TEST (map_update_collisions) { for (size_t i = 0; i < len; ++i) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK(node != NULL); - node->allocator = BT_NEW; node->size = items[i]; } @@ -149,7 +141,6 @@ TEST (map_update_collisions) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); - CHECK_CMP (node->allocator,==,BT_NEW); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); @@ -171,7 +162,6 @@ TEST (map_free) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK (node != NULL); node->size = 10; - node->allocator = BT_MALLOC; } bt_mem_table_free (); @@ -189,7 +179,6 @@ TEST (map_remove) { struct bt_mem_node * node = bt_mem_table_insert (&x); CHECK (node != NULL); node->size = 10; - node->allocator = BT_MALLOC; CHECK (bt_mem_table_remove (&x)); CHECK (bt_mem_table_find (&x) == NULL); bt_mem_table_free (); @@ -215,7 +204,6 @@ TEST (map_remove_collisions) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK (node != NULL); node->size = 10; - node->allocator = BT_MALLOC; } CHECK (bt_mem_table_size == len); @@ -244,7 +232,6 @@ TEST (map_remove_collisions_not_found) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK (node != NULL); node->size = 10; - node->allocator = BT_MALLOC; } CHECK (!bt_mem_table_remove (&x)); @@ -265,7 +252,6 @@ TEST (map_insert_remove_series) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK (node != NULL); node->size = items[i]; - node->allocator = BT_MALLOC; } for (size_t i = 0; i < len/2; ++i) { @@ -288,7 +274,6 @@ TEST (map_insert_remove_series) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK (node != NULL); node->size = items[i]; - node->allocator = BT_MALLOC; } for (size_t i = len/2; i < len; ++i) { diff --git a/ex/memory_checks/tests/03_double_free.c b/ex/memory_checks/tests/03_double_free.c index 5a99db8..cd1e39b 100644 --- a/ex/memory_checks/tests/03_double_free.c +++ b/ex/memory_checks/tests/03_double_free.c @@ -1,5 +1,5 @@ #include "basic_testing.h" -#include +#include "../array.h" @@ -9,10 +9,7 @@ TEST (compile) { TEST (invalid_free) { - int a = 10; - void * p = malloc (10); - if (a < 20) free (p); - free (p); + double_free (); TEST_PASSED; } diff --git a/ex/memory_checks/tests/03_memory_leak_calloc.c b/ex/memory_checks/tests/03_memory_leak_calloc.c new file mode 100644 index 0000000..c8749e4 --- /dev/null +++ b/ex/memory_checks/tests/03_memory_leak_calloc.c @@ -0,0 +1,19 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (memory_leak) { + struct array * array = array_new_calloc (); + CHECK (array != NULL); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, memory_leak); diff --git a/ex/memory_checks/tests/03_memory_leak_calloc_debug.c b/ex/memory_checks/tests/03_memory_leak_calloc_debug.c new file mode 100644 index 0000000..e678ce1 --- /dev/null +++ b/ex/memory_checks/tests/03_memory_leak_calloc_debug.c @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (debugger) { + int result = system ("./tests/03_memory_leak_calloc -d >/dev/null"); + + if (result != 0) TEST_FAILED; + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, debugger); diff --git a/ex/memory_checks/tests/03_memory_leak_malloc.c b/ex/memory_checks/tests/03_memory_leak_malloc.c new file mode 100644 index 0000000..c466939 --- /dev/null +++ b/ex/memory_checks/tests/03_memory_leak_malloc.c @@ -0,0 +1,19 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (memory_leak) { + struct array * array = array_new (); + CHECK (array != NULL); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, memory_leak); diff --git a/ex/memory_checks/tests/03_memory_leak_malloc_debug.c b/ex/memory_checks/tests/03_memory_leak_malloc_debug.c new file mode 100644 index 0000000..019b1a3 --- /dev/null +++ b/ex/memory_checks/tests/03_memory_leak_malloc_debug.c @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (debugger) { + int result = system ("./tests/03_memory_leak_malloc -d >/dev/null"); + + if (result != 0) TEST_FAILED; + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, debugger); diff --git a/ex/memory_checks/tests/03_memory_leak_realloc.c b/ex/memory_checks/tests/03_memory_leak_realloc.c new file mode 100644 index 0000000..dbd087b --- /dev/null +++ b/ex/memory_checks/tests/03_memory_leak_realloc.c @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (memory_leak) { + struct array * array = array_new (); + CHECK (array != NULL); + CHECK (array_append (array, 1)); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, memory_leak); diff --git a/ex/memory_checks/tests/03_memory_leak_realloc_debug.c b/ex/memory_checks/tests/03_memory_leak_realloc_debug.c new file mode 100644 index 0000000..a614a75 --- /dev/null +++ b/ex/memory_checks/tests/03_memory_leak_realloc_debug.c @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (debugger) { + int result = system ("./tests/03_memory_leak_realloc -d >/dev/null"); + + if (result != 0) TEST_FAILED; + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, debugger); diff --git a/ex/memory_checks/tests/03_memory_leak_reallocarray.c b/ex/memory_checks/tests/03_memory_leak_reallocarray.c new file mode 100644 index 0000000..2b830e0 --- /dev/null +++ b/ex/memory_checks/tests/03_memory_leak_reallocarray.c @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (memory_leak) { + struct array * array = array_new (); + CHECK (array != NULL); + CHECK (array_append_reallocarray (array, 1)); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, memory_leak); diff --git a/ex/memory_checks/tests/03_memory_leak_reallocarray_debug.c b/ex/memory_checks/tests/03_memory_leak_reallocarray_debug.c new file mode 100644 index 0000000..6f5e8e0 --- /dev/null +++ b/ex/memory_checks/tests/03_memory_leak_reallocarray_debug.c @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (debugger) { + int result = system ("./tests/03_memory_leak_reallocarray -d >/dev/null"); + + if (result != 0) TEST_FAILED; + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, debugger); diff --git a/ex/memory_checks/tests/03_non_malloc_free.c b/ex/memory_checks/tests/03_non_malloc_free.c new file mode 100644 index 0000000..f485eca --- /dev/null +++ b/ex/memory_checks/tests/03_non_malloc_free.c @@ -0,0 +1,17 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (invalid_free) { + non_malloc_free (); + TEST_PASSED; +} + + +MAIN_TEST_DRIVER (compile, invalid_free); diff --git a/ex/memory_checks/tests/03_non_portable_malloc.c b/ex/memory_checks/tests/03_non_portable_malloc.c index c3fad8b..0526e84 100644 --- a/ex/memory_checks/tests/03_non_portable_malloc.c +++ b/ex/memory_checks/tests/03_non_portable_malloc.c @@ -1,5 +1,5 @@ #include "basic_testing.h" -#include +#include "../array.h" @@ -8,12 +8,12 @@ TEST (compile) { } -TEST (malloc_zero_size) { - void * p = malloc (0); +TEST (non_portable_malloc) { + void * p = malloc_zero_size (); CHECK (p != NULL); TEST_PASSED; } -MAIN_TEST_DRIVER (compile, malloc_zero_size); +MAIN_TEST_DRIVER (compile, non_portable_malloc); diff --git a/ex/memory_checks/tests/03_non_portable_realloc.c b/ex/memory_checks/tests/03_non_portable_realloc.c index 1485b99..22b3b66 100644 --- a/ex/memory_checks/tests/03_non_portable_realloc.c +++ b/ex/memory_checks/tests/03_non_portable_realloc.c @@ -1,5 +1,5 @@ #include "basic_testing.h" -#include +#include "../array.h" @@ -8,15 +8,15 @@ TEST (compile) { } -TEST (realloc_zero_size) { +TEST (non_portable_realloc) { void * p = malloc (10); CHECK (p != NULL); - void * s = realloc (p, 0); + void * s = realloc_zero_size (p); CHECK (s != NULL); TEST_PASSED; } -MAIN_TEST_DRIVER (compile, realloc_zero_size); +MAIN_TEST_DRIVER (compile, non_portable_realloc); diff --git a/ex/memory_checks/tests/04_budget_allocations.c b/ex/memory_checks/tests/04_budget_allocations.c index 6ee0838..ca5952e 100644 --- a/ex/memory_checks/tests/04_budget_allocations.c +++ b/ex/memory_checks/tests/04_budget_allocations.c @@ -202,6 +202,20 @@ TEST (realloc_budget_reset) { } +TEST (set_same_budget) { + MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + MEM_SET_ALLOCATION_BUDGET (1); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + TEST (set_higher_budget) { MEM_SET_ALLOCATION_BUDGET (1); struct array * array = array_new (); @@ -209,31 +223,31 @@ TEST (set_higher_budget) { for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); MEM_SET_ALLOCATION_BUDGET (2); - for (int i = 8; i < 16; ++i) + for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); - for (int i = 32; i < 32; ++i) + for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); array_free (array); + MEM_SET_ALLOCATION_BUDGET (3); array = array_new (); CHECK (array != NULL); - for (int i = 0; i < 8; ++i) + for (int i = 0; i < 16; ++i) CHECK (array_append (array, i)); - for (int i = 8; i < 16; ++i) - CHECK (!array_append (array, i)); array_free (array); TEST_PASSED; } TEST (set_lower_budget) { - MEM_SET_ALLOCATION_BUDGET (2); + MEM_SET_ALLOCATION_BUDGET (4); struct array * array = array_new (); - CHECK (array != NULL); + MEM_SET_ALLOCATION_BUDGET (2); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); + CHECK (!array_append (array, 9)); + MEM_SET_ALLOCATION_BUDGET (1); for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); - MEM_SET_ALLOCATION_BUDGET (1); array_free (array); array = array_new (); CHECK (array != NULL); @@ -241,7 +255,18 @@ TEST (set_lower_budget) { CHECK (!array_append (array, i)); array_free (array); TEST_PASSED; +} + +TEST (set_lower_budget_after_allocations) { + MEM_SET_ALLOCATION_BUDGET (3); + struct array * array = array_new (); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + MEM_SET_ALLOCATION_BUDGET (2); + CHECK (!array_append (array, 17)); + array_free (array); + TEST_PASSED; } @@ -274,7 +299,7 @@ TEST (reallocarray_budget) { CHECK (!array_append_reallocarray (array, i)); CHECK_CMP (array_length (array),==,0); CHECK_CMP (array_capacity (array),==,0); - MEM_SET_ALLOCATION_BUDGET (1); + MEM_SET_ALLOCATION_BUDGET (2); for (int i = 0; i < 4; ++i) CHECK (array_append_reallocarray (array, i)); CHECK_CMP (array_length (array),==,4); @@ -299,8 +324,10 @@ MAIN_TEST_DRIVER (compile, malloc_budget_reset, realloc_null_budget_reset, realloc_budget_reset, + set_same_budget, set_higher_budget, set_lower_budget, + set_lower_budget_after_allocations, zero_budget_calloc, simple_budget_calloc, reallocarray_budget); diff --git a/ex/memory_checks/tests/05_byte_budget_allocations.c b/ex/memory_checks/tests/05_byte_budget_allocations.c index 05d3a17..7ac2370 100644 --- a/ex/memory_checks/tests/05_byte_budget_allocations.c +++ b/ex/memory_checks/tests/05_byte_budget_allocations.c @@ -205,38 +205,52 @@ TEST (realloc_budget_reset) { } -TEST (set_higher_budget) { - MEM_SET_BYTES_BUDGET (sizeof (struct array)); +TEST (set_same_budget) { + MEM_SET_BYTES_BUDGET (sizeof(struct array)); struct array * array = array_new (); CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); - MEM_SET_BYTES_BUDGET (16*sizeof (int)); - for (int i = 8; i < 16; ++i) - CHECK (array_append (array, i)); - for (int i = 32; i < 32; ++i) + MEM_SET_BYTES_BUDGET (sizeof(struct array)); + for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); array_free (array); - array = array_new (); + TEST_PASSED; +} + + +TEST (set_higher_budget) { + MEM_SET_BYTES_BUDGET (sizeof(struct array)); + struct array * array = array_new (); CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); array_free (array); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 16*sizeof(int)); + array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 16; ++i) + CHECK (array_append (array, i)); + array_free (array); TEST_PASSED; } TEST (set_lower_budget) { - MEM_SET_BYTES_BUDGET (sizeof (struct array) + 8*sizeof (int)); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 32*sizeof(int)); struct array * array = array_new (); - CHECK (array != NULL); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); + CHECK (!array_append (array, 9)); + MEM_SET_BYTES_BUDGET (sizeof(struct array)); for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); - MEM_SET_BYTES_BUDGET (sizeof (struct array)); array_free (array); array = array_new (); CHECK (array != NULL); @@ -247,6 +261,18 @@ TEST (set_lower_budget) { } +TEST (set_lower_budget_after_allocations) { + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 16*sizeof(int)); + struct array * array = array_new (); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); + CHECK (!array_append (array, 17)); + array_free (array); + TEST_PASSED; +} + + TEST (smaller_size_realloc) { MEM_SET_BYTES_BUDGET (8*sizeof (int)); int * p = malloc (8*sizeof (int)); @@ -292,7 +318,7 @@ TEST (reallocarray_budget) { CHECK (!array_append_reallocarray (array, i)); CHECK_CMP (array_length (array),==,0); CHECK_CMP (array_capacity (array),==,0); - MEM_SET_BYTES_BUDGET (sizeof (int)*8); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + sizeof (int)*8); for (int i = 0; i < 4; ++i) CHECK (array_append_reallocarray (array, i)); CHECK_CMP (array_length (array),==,4); @@ -316,8 +342,10 @@ MAIN_TEST_DRIVER (compile, malloc_budget_reset, realloc_null_budget_reset, realloc_budget_reset, + set_same_budget, set_higher_budget, set_lower_budget, + set_lower_budget_after_allocations, smaller_size_realloc, zero_budget_calloc, simple_budget_calloc, diff --git a/ex/memory_checks/tests/08_fopen_leak.c b/ex/memory_checks/tests/08_fopen_leak.c new file mode 100644 index 0000000..0bee302 --- /dev/null +++ b/ex/memory_checks/tests/08_fopen_leak.c @@ -0,0 +1,15 @@ +#include "basic_testing.h" +#include + + + + +TEST (memory_leak) { + FILE * fp = fopen("/tmp/leak_fopen", "w"); + fprintf (fp, "testing\n"); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (memory_leak); diff --git a/ex/memory_checks/tests/08_stdlib_functions.c b/ex/memory_checks/tests/08_stdlib_functions.c new file mode 100644 index 0000000..6290018 --- /dev/null +++ b/ex/memory_checks/tests/08_stdlib_functions.c @@ -0,0 +1,419 @@ +#include "basic_testing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +static int int_comparator (const void * a, const void * b) { + const int aval = (*(const int *)a); + const int bval = (*(const int *)b); + return aval - bval; +} + + +TEST (compile) { + TEST_PASSED; +} + + +// ctype.h functions +TEST (ctype_no_leaks) { + CHECK (isalnum ('a')); + CHECK (isalpha ('a')); + CHECK (iscntrl ('\n')); + CHECK (isdigit ('1')); + CHECK (isgraph ('a')); + CHECK (islower ('a')); + CHECK (isprint ('a')); + CHECK (ispunct ('.')); + CHECK (isspace (' ')); + CHECK (isupper ('A')); + CHECK (isxdigit ('A')); + CHECK_CMP (toupper ('a'),==,'A'); + CHECK_CMP (tolower ('A'),==,'a'); + TEST_PASSED; +} + + +// string.h functions +TEST (strcpy_no_leaks) { + char out[10]; + strcpy (out, "hello"); + CHECK_STRING_CMP (out,==,"hello"); + TEST_PASSED; +} + + +TEST (strncpy_no_leaks) { + char out[10]; + strncpy (out, "hello", 6); + CHECK_STRING_CMP (out,==,"hello"); + TEST_PASSED; +} + + +TEST (strcat_no_leaks) { + char out[10] = "hello"; + strcat (out, "he"); + CHECK_STRING_CMP (out,==,"hellohe"); + TEST_PASSED; +} + + +TEST (strncat_no_leaks) { + char out[10] = "hello"; + strncat (out, "he", 3); + CHECK_STRING_CMP (out,==,"hellohe"); + TEST_PASSED; +} + + +TEST (strcmp_no_leaks) { + CHECK_CMP (strcmp ("hello", "hello"),==,0); + TEST_PASSED; +} + + +TEST (strncmp_no_leaks) { + CHECK_CMP (strncmp ("hello", "hello2", 3),==,0); + TEST_PASSED; +} + + +TEST (strchr_no_leaks) { + const char *s = "hello"; + CHECK_STRING_CMP (strchr (s, 'l'),==,"llo"); + TEST_PASSED; +} + + +TEST (strrchr_no_leaks) { + const char *s = "hello"; + CHECK_STRING_CMP (strrchr (s, 'l'),==,"lo"); + TEST_PASSED; +} + + +TEST (strspn_no_leaks) { + const char *s = "hello"; + CHECK_CMP (strspn (s, "hel"),==,4); + TEST_PASSED; +} + + +TEST (strcspn_no_leaks) { + const char *s = "hello"; + CHECK_CMP (strcspn (s, "h"),==,0); + TEST_PASSED; +} + + +TEST (strpbrk_no_leaks) { + const char *s = "hello"; + CHECK_STRING_CMP (strpbrk (s, "l"),==,"llo"); + TEST_PASSED; +} + + +TEST (strstr_no_leaks) { + const char *s = "hello"; + CHECK_STRING_CMP (strstr (s, "lo"),==,"lo"); + TEST_PASSED; +} + + +TEST (strlen_no_leaks) { + const char *s = "hello"; + CHECK_CMP (strlen (s),==,5); + TEST_PASSED; +} + + +TEST (strerror_no_leaks) { + CHECK_STRING_CMP (strerror (EINVAL),==,"Invalid argument"); + TEST_PASSED; +} + + +TEST (strtok_no_leaks) { + char s[] = "hello,hello,hello"; + CHECK_STRING_CMP (strtok (s, ","),==,"hello"); + TEST_PASSED; +} + + +TEST (memcpy_no_leaks) { + char out[10]; + memcpy (out, "hello", 6); + CHECK_STRING_CMP (out,==,"hello"); + TEST_PASSED; +} + + +TEST (memmove_no_leaks) { + char out[10]; + memmove (out, "hello", 6); + CHECK_STRING_CMP (out,==,"hello"); + TEST_PASSED; +} + + +TEST (memcmp_no_leaks) { + CHECK_CMP (memcmp ("hello", "hello", 6),==,0); + TEST_PASSED; +} + + +TEST (memchr_no_leaks) { + const char * s = "hello"; + CHECK (memchr (s, 'l', 4) == s+2); + TEST_PASSED; +} + + +TEST (memset_no_leaks) { + char out[10]; + out[5] = '\0'; + CHECK_STRING_CMP (memset (out, 'a', 5),==,"aaaaa"); + TEST_PASSED; +} + + +// ctype.h functions +TEST (math_no_leaks) { + CHECK_CMP (sin (0),==,0); + CHECK_CMP (cos (0),==,1); + CHECK_CMP (tan (0),==,0); + CHECK_CMP (sinh (1),==,1); + CHECK_CMP (cosh (1),==,1); + CHECK_CMP (tanh (1),==,0); + CHECK_CMP (exp (0),==,1); + CHECK_CMP (log (1),==,0); + CHECK_CMP (log10 (1),==,0); + CHECK_CMP (pow (2, 1),==,2); + CHECK_CMP (sqrt (4),==,2); + CHECK_CMP (ceil (4.3),==,5); + CHECK_CMP (floor (4.3),==,4); + CHECK_CMP (fabs (-4.3),==,4.3); + CHECK_CMP (ldexp (4, 2),==,16); + int x; + CHECK_CMP (frexp (4.3, &x),==,0); + double ip; + CHECK_CMP (modf (4.3, &ip),==,0); + CHECK_CMP (fmod (4.3, 4),==,0.3); + CHECK_CMP (abs (-10),==, 10); + CHECK_CMP (labs (-10),==, 10); + div_t res = div (10, 2); + CHECK_CMP (res.quot,==,5); + CHECK_CMP (res.rem,==,0); + ldiv_t res_l = ldiv (10, 2); + CHECK_CMP (res_l.quot,==,5); + CHECK_CMP (res_l.rem,==,0); + TEST_PASSED; +} + + +// stdlib.h functions +TEST (stdlib_conversion_no_leaks) { + CHECK_CMP (atof ("2.23"),==,2.23); + CHECK_CMP (atoi ("2"),==,2); + CHECK_CMP (atol ("2"),==,2); + CHECK_CMP (strtod ("2.23", (char **) NULL),==,2.23); + CHECK_CMP (strtol ("2", (char **)NULL, 10),==,2); + CHECK_CMP (strtoul ("2", (char **)NULL, 10),==,2); + TEST_PASSED; +} + + +TEST (rand_no_leaks) { + srand (10); + CHECK_CMP (rand (),==,1215069295); + TEST_PASSED; +} + + +TEST (getenv_no_leaks) { + char * p = getenv ("PWD"); + CHECK (p != NULL); + TEST_PASSED; +} + + +TEST (qsort_no_leaks) { + int array[] = {32, 1, 41, 0, 31, 13}; + qsort (array, 6, sizeof(int), int_comparator); + for (int i = 1; i < 6; ++i) + CHECK_CMP (array[i],>=,array[i-1]); + TEST_PASSED; +} + + +TEST (bsearch_no_leaks) { + int array[] = {0, 1, 2, 3, 10, 32}; + int key = 10; + int * res = (int *) bsearch (&key, array, 6, sizeof(int), int_comparator); + CHECK_CMP (*res,==,key); + TEST_PASSED; +} + + +// time.h functions +TEST (time_no_leaks) { + CHECK_CMP (clock (),!=,-1); + CHECK_CMP (time (NULL),!=,-1); + CHECK_CMP (difftime (12, 10),==,2); + time_t t = time (NULL); + struct tm * tm_val = gmtime (&t); + CHECK (tm_val != NULL); + CHECK (mktime (tm_val) != -1); + CHECK (localtime (&t) != NULL); + CHECK_STRING_CMP (asctime(localtime(&t)),==, ctime (&t)); + char buf[100]; + size_t size = strftime (buf, 100, "%I:%M:%S", tm_val); + for (char * p = buf; p != buf + size; ++p) + CHECK (isprint (*p)); + TEST_PASSED; +} + + +// stdio.h functions +static void write_fp (FILE *fp, const char *format, ...) { + va_list ap; + + va_start (ap, format); + vfprintf (fp, format, ap); + va_end (ap); +} + + +static void read_fp (FILE *fp, const char *format, ...) { + va_list ap; + + va_start (ap, format); + vfscanf (fp, format, ap); + va_end (ap); +} + + +TEST (basic_file_operations_no_leak) { + char buf[100]; + FILE * fp = fopen ("/tmp/open_stlib_open", "w"); + CHECK (fp != NULL); + CHECK_CMP (setvbuf(fp, NULL, _IONBF, 0),==,0); + fputc('a', fp); + putc('b', fp); + fputs ("some line\n", fp); + const char * line = "some line 2\n"; + fwrite (line, sizeof(char), strlen (line), fp); + fprintf (fp, "testing %d\n", 10); + write_fp (fp, "testing vfprintf %d\n", 11); + + fflush (fp); + rewind (fp); + fpos_t pos; + CHECK_CMP (fgetpos (fp, &pos),==,0); + CHECK_CMP (ftell (fp),!=,-1); + rewind (fp); + CHECK_CMP (fsetpos (fp, &pos),==,0); + CHECK (fseek(fp, 0L, SEEK_SET) == 0); + fclose (fp); + fp = tmpfile (); + setbuf(fp, NULL); + CHECK_CMP (rename ("/tmp/open_stlib_open", "/tmp/open_stlib_open2"),==,0); + CHECK (fp != NULL); + + fp = freopen("/tmp/open_stlib_open2", "r", fp); + CHECK_CMP (fgetc (fp),==,'a'); + CHECK_CMP (getc (fp),==,'b'); + ungetc ('b', fp); + CHECK_CMP (getc (fp),==,'b'); + fgets (buf, 11, fp); + CHECK_STRING_CMP (buf,==,"some line\n"); + fread (buf, sizeof(char), strlen(line), fp); + buf[strlen(line)] = '\0'; + CHECK_STRING_CMP (buf,==,line); + int x; + fscanf (fp, "testing %d\n", &x); + CHECK_CMP (x,==,10); + read_fp (fp, "testing vfprintf %d\n", &x); + CHECK_CMP (x,==,11); + CHECK_CMP (feof (fp),!=, 0); + CHECK_CMP (ferror (fp),==, 0); + clearerr (fp); + fclose (fp); + CHECK_CMP (remove ("/tmp/open_stlib_open2"),==,0); + TEST_PASSED; +} + + +static void write_str (char *buf, const char *format, ...) { + va_list ap; + + va_start (ap, format); + vsprintf (buf, format, ap); + va_end (ap); +} + + +static void read_str (char *buf, const char *format, ...) { + va_list ap; + + va_start (ap, format); + vsscanf (buf, format, ap); + va_end (ap); +} + +TEST (stdio_string_no_leak) { + char buf[100]; + char * name = tempnam (NULL, "somefile"); + CHECK (name != NULL); + sprintf (buf, "testing %d", 10); + int x; + sscanf (buf, "testing %d", &x); + CHECK_CMP (x,==,10); + write_str (buf, "testing vsprintf %d", 11); + read_str (buf, "testing vsprintf %d", &x); + CHECK_CMP (x,==,11); + free (name); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (ctype_no_leaks, + strcpy_no_leaks, + strncpy_no_leaks, + strcat_no_leaks, + strncat_no_leaks, + strcmp_no_leaks, + strncmp_no_leaks, + strchr_no_leaks, + strrchr_no_leaks, + strspn_no_leaks, + strcspn_no_leaks, + strcspn_no_leaks, + strpbrk_no_leaks, + strstr_no_leaks, + strlen_no_leaks, + strerror_no_leaks, + strtok_no_leaks, + memcpy_no_leaks, + memmove_no_leaks, + memcmp_no_leaks, + memchr_no_leaks, + memset_no_leaks, + math_no_leaks, + stdlib_conversion_no_leaks, + rand_no_leaks, + qsort_no_leaks, + bsearch_no_leaks, + time_no_leaks, + basic_file_operations_no_leak, + stdio_string_no_leak); diff --git a/ex/memory_checks/tests/08_lib_allocation.c b/ex/memory_checks/tests/08_strdup_leak.c similarity index 100% rename from ex/memory_checks/tests/08_lib_allocation.c rename to ex/memory_checks/tests/08_strdup_leak.c diff --git a/ex/memory_checks/tests/08_tmpfile_leak.c b/ex/memory_checks/tests/08_tmpfile_leak.c new file mode 100644 index 0000000..c3c2e23 --- /dev/null +++ b/ex/memory_checks/tests/08_tmpfile_leak.c @@ -0,0 +1,15 @@ +#include "basic_testing.h" +#include + + + +TEST (memory_leak) { + FILE *fp = tmpfile (); + fprintf (fp, "testing\n"); + TEST_PASSED; +} + + + + +MAIN_TEST_DRIVER (memory_leak); diff --git a/ex/memory_checks/tests/08_tmpnum_leak.c b/ex/memory_checks/tests/08_tmpnum_leak.c new file mode 100644 index 0000000..04c455a --- /dev/null +++ b/ex/memory_checks/tests/08_tmpnum_leak.c @@ -0,0 +1,12 @@ +#include "basic_testing.h" +#include + + + +TEST (memory_leak) { + char * name = tempnam (NULL, "somefile"); + CHECK (name != NULL); + TEST_PASSED; +} + +MAIN_TEST_DRIVER (memory_leak); diff --git a/ex/memory_checks_cpp.expected b/ex/memory_checks_cpp.expected new file mode 100644 index 0000000..e2f680d --- /dev/null +++ b/ex/memory_checks_cpp.expected @@ -0,0 +1,189 @@ +Running test 00_hash_map... PASS +Running test 01_fail_allocations... PASS +Running test 01_fail_allocations_debug... PASS +Running test 02_allocations_recording... PASS +Running test 03_delete_array_malloc_object... +objects allocated with malloc should be deallocated free + +leaked 4 bytes +FAIL +run 'tests/03_delete_array_malloc_object' to see what went wrong +run 'tests/03_delete_array_malloc_object -d' with a debugger +Running test 03_delete_array_new_object... +objects allocated with new should be deallocated delete + +leaked 4 bytes +FAIL +run 'tests/03_delete_array_new_object' to see what went wrong +run 'tests/03_delete_array_new_object -d' with a debugger +Running test 03_delete_malloc_object... +objects allocated with malloc should be deallocated free + +leaked 4 bytes +FAIL +run 'tests/03_delete_malloc_object' to see what went wrong +run 'tests/03_delete_malloc_object -d' with a debugger +Running test 03_delete_new_array_object... +objects allocated with new[] should be deallocated delete[] + +leaked 40 bytes +FAIL +run 'tests/03_delete_new_array_object' to see what went wrong +run 'tests/03_delete_new_array_object -d' with a debugger +Running test 03_double_delete... +memory was not allocated via malloc/new/new[], or possible double free/delete/delete[] +FAIL +run 'tests/03_double_delete' to see what went wrong +run 'tests/03_double_delete -d' with a debugger +Running test 03_double_delete_array... +memory was not allocated via malloc/new/new[], or possible double free/delete/delete[] +FAIL +run 'tests/03_double_delete_array' to see what went wrong +run 'tests/03_double_delete_array -d' with a debugger +Running test 03_double_free... +memory was not allocated via malloc/new/new[], or possible double free/delete/delete[] +FAIL +run 'tests/03_double_free' to see what went wrong +run 'tests/03_double_free -d' with a debugger +Running test 03_free_new_array_object... +objects allocated with new[] should be deallocated delete[] + +leaked 40 bytes +FAIL +run 'tests/03_free_new_array_object' to see what went wrong +run 'tests/03_free_new_array_object -d' with a debugger +Running test 03_free_new_object... +objects allocated with new should be deallocated delete + +leaked 4 bytes +FAIL +run 'tests/03_free_new_object' to see what went wrong +run 'tests/03_free_new_object -d' with a debugger +Running test 03_memory_leak_calloc... +leaked 24 bytes +FAIL +run 'tests/03_memory_leak_calloc' to see what went wrong +run 'tests/03_memory_leak_calloc -d' with a debugger +Running test 03_memory_leak_calloc_debug... +leaked 24 bytes +FAIL +run 'tests/03_memory_leak_calloc_debug' to see what went wrong +run 'tests/03_memory_leak_calloc_debug -d' with a debugger +Running test 03_memory_leak_malloc... +leaked 24 bytes +FAIL +run 'tests/03_memory_leak_malloc' to see what went wrong +run 'tests/03_memory_leak_malloc -d' with a debugger +Running test 03_memory_leak_malloc_debug... +leaked 24 bytes +FAIL +run 'tests/03_memory_leak_malloc_debug' to see what went wrong +run 'tests/03_memory_leak_malloc_debug -d' with a debugger +Running test 03_memory_leak_new... +leaked 24 bytes +FAIL +run 'tests/03_memory_leak_new' to see what went wrong +run 'tests/03_memory_leak_new -d' with a debugger +Running test 03_memory_leak_new_array... +leaked 56 bytes +FAIL +run 'tests/03_memory_leak_new_array' to see what went wrong +run 'tests/03_memory_leak_new_array -d' with a debugger +Running test 03_memory_leak_new_array_debug... +leaked 56 bytes +FAIL +run 'tests/03_memory_leak_new_array_debug' to see what went wrong +run 'tests/03_memory_leak_new_array_debug -d' with a debugger +Running test 03_memory_leak_new_debug... +leaked 24 bytes +FAIL +run 'tests/03_memory_leak_new_debug' to see what went wrong +run 'tests/03_memory_leak_new_debug -d' with a debugger +Running test 03_memory_leak_realloc... +leaked 56 bytes +FAIL +run 'tests/03_memory_leak_realloc' to see what went wrong +run 'tests/03_memory_leak_realloc -d' with a debugger +Running test 03_memory_leak_realloc_debug... +leaked 56 bytes +FAIL +run 'tests/03_memory_leak_realloc_debug' to see what went wrong +run 'tests/03_memory_leak_realloc_debug -d' with a debugger +Running test 03_memory_leak_reallocarray... +leaked 56 bytes +FAIL +run 'tests/03_memory_leak_reallocarray' to see what went wrong +run 'tests/03_memory_leak_reallocarray -d' with a debugger +Running test 03_memory_leak_reallocarray_debug... +leaked 56 bytes +FAIL +run 'tests/03_memory_leak_reallocarray_debug' to see what went wrong +run 'tests/03_memory_leak_reallocarray_debug -d' with a debugger +Running test 03_memory_leaks... +leaked 32 bytes +FAIL +run 'tests/03_memory_leaks' to see what went wrong +run 'tests/03_memory_leaks -d' with a debugger +Running test 03_memory_leaks_debug... +leaked 32 bytes +FAIL +run 'tests/03_memory_leaks_debug' to see what went wrong +run 'tests/03_memory_leaks_debug -d' with a debugger +Running test 03_non_malloc_free... +memory was not allocated via malloc/new/new[], or possible double free/delete/delete[] +FAIL +run 'tests/03_non_malloc_free' to see what went wrong +run 'tests/03_non_malloc_free -d' with a debugger +Running test 03_non_new_array_delete... +memory was not allocated via malloc/new/new[], or possible double free/delete/delete[] +FAIL +run 'tests/03_non_new_array_delete' to see what went wrong +run 'tests/03_non_new_array_delete -d' with a debugger +Running test 03_non_new_delete... +memory was not allocated via malloc/new/new[], or possible double free/delete/delete[] +FAIL +run 'tests/03_non_new_delete' to see what went wrong +run 'tests/03_non_new_delete -d' with a debugger +Running test 03_non_portable_malloc... +malloc with size 0 is not portable +FAIL +run 'tests/03_non_portable_malloc' to see what went wrong +run 'tests/03_non_portable_malloc -d' with a debugger +Running test 03_non_portable_realloc... +realloc with size 0 is not portable + +leaked 10 bytes +FAIL +run 'tests/03_non_portable_realloc' to see what went wrong +run 'tests/03_non_portable_realloc -d' with a debugger +Running test 03_static_object_leaked... +leaked 4000 bytes +FAIL +run 'tests/03_static_object_leaked' to see what went wrong +run 'tests/03_static_object_leaked -d' with a debugger +Running test 03_static_object_non_leaked... PASS +Running test 04_budget_allocations... PASS +Running test 04_budget_allocations_debug... PASS +Running test 05_byte_budget_allocations... PASS +Running test 05_byte_budget_allocations_debug... PASS +Running test 06_scheduled_failures... PASS +Running test 06_scheduled_failures_debug... PASS +Running test 07_calloc_reallocarray_failures... PASS +Running test 08_fopen_leak... +FAIL +run 'tests/08_fopen_leak' to see what went wrong +run 'tests/08_fopen_leak -d' with a debugger +Running test 08_stdlib_functions... PASS +Running test 08_strdup_leak... +leaked 8 bytes +FAIL +run 'tests/08_strdup_leak' to see what went wrong +run 'tests/08_strdup_leak -d' with a debugger +Running test 08_tmpfile_leak... +FAIL +run 'tests/08_tmpfile_leak' to see what went wrong +run 'tests/08_tmpfile_leak -d' with a debugger +Running test 08_tmpnum_leak... +FAIL +run 'tests/08_tmpnum_leak' to see what went wrong +run 'tests/08_tmpnum_leak -d' with a debugger diff --git a/ex/memory_checks_cpp/Makefile b/ex/memory_checks_cpp/Makefile new file mode 100644 index 0000000..e462944 --- /dev/null +++ b/ex/memory_checks_cpp/Makefile @@ -0,0 +1,3 @@ +OBJECTS = array.o + +include ../../basic_testing.mk diff --git a/ex/memory_checks_cpp/array.cc b/ex/memory_checks_cpp/array.cc new file mode 100644 index 0000000..182a3cc --- /dev/null +++ b/ex/memory_checks_cpp/array.cc @@ -0,0 +1,221 @@ +#include "array.h" +#include +#include +#include +#include + +static size_t initial_cap = 8; + +static std::vector vec; +static std::vector vec_ptr; + +struct array * array_new (void) { + struct array * a = (struct array *) std::malloc(sizeof(struct array)); + if (!a) return NULL; + + a->data = NULL; + a->len = 0; + a->cap = 0; + return a; +} + +struct array * array_new_calloc (void) { + return (struct array *) std::calloc(1, sizeof(struct array)); +} + +void array_free (struct array * array) { + if (array->cap) std::free(array->data); + std::free(array); +} + +void array_free_leak (struct array * array) { + std::free(array); +} + +size_t array_length (struct array * array) { + return array->len; +} + +size_t array_capacity (struct array * array) { + return array->cap; +} + +int array_element (struct array * array, size_t index) { + return array->data[index]; +} + +int array_append (struct array * array, int element) { + if (array->len == array->cap) { + size_t new_cap = array->cap ? 2*array->cap : initial_cap; + + int * new_data = (int *) std::realloc(array->data, new_cap*sizeof(int)); + if (!new_data) return 0; + + array->data = new_data; + array->cap = new_cap; + } + + array->data[array->len++] = element; + return 1; +} + +int array_append_reallocarray (struct array * array, int element) { + if (array->len == array->cap) { + size_t new_cap = array->cap ? 2*array->cap : initial_cap; + + int * new_data = (int *) reallocarray(array->data, new_cap, sizeof(int)); + if (!new_data) return 0; + + array->data = new_data; + array->cap = new_cap; + } + + array->data[array->len++] = element; + return 1; +} + +array_cpp::array_cpp () : data{nullptr}, len{0}, cap{0} {} + +array_cpp::~array_cpp () { + if (data) delete[] data; +} + +void array_cpp::append (int value) { + if (len == cap) { + size_t new_cap = cap ? 2*cap : initial_cap; + int * new_data = new int[new_cap]; + std::copy_n (data, cap, new_data); + if (data) delete[] data; + data = new_data; + cap = new_cap; + } + + data[len++] = value; +} + +array_cpp * array_cpp_new (void) { + return new array_cpp {}; +} + +void array_cpp_delete (array_cpp *array) { + delete array; +} + +void double_free (void) { + int a = 10; + void * p = std::malloc (10); + if (a < 20) std::free (p); + std::free (p); +} + +void double_delete (void) { + int a = 10; + int * p = new int {10}; + if (a < 20) delete p; + delete p; +} + +void double_delete_array (void) { + int a = 10; + int * p = new int[10]; + if (a < 20) delete[] p; + delete[] p; +} + +void non_malloc_free (void) { + int a = 10; + int * p; + if (a < 20) p = &a; + std::free (p); +} + +void non_new_delete (void) { + int a = 10; + int * p; + if (a < 20) p = &a; + delete p; +} + +void non_new_array_delete (void) { + int a = 10; + int * p; + if (a < 20) p = &a; + delete[] p; + +} + +void * malloc_zero_size (void) { + return std::malloc (0); +} + +void * realloc_zero_size (void * ptr) { + return std::realloc (ptr, 0); +} + +void new_object_free (void) { + int a = 10; + int * p; + if (a < 20) + p = new int{10}; + std::free (p); +} + +void new_array_object_free (void) { + int a = 10; + int * p; + if (a < 20) + p = new int[10]; + std::free(p); +} + +void malloc_object_delete (void) { + int a = 10; + int * p; + if (a < 20) + p = (int *) std::malloc (sizeof(int)); + delete p; +} + +void new_array_object_delete (void) { + int a = 10; + int * p; + if (a < 20) + p = new int[10]; + delete p; +} + +void malloc_object_delete_array (void) { + int a = 10; + int * p; + if (a < 20) + p = (int *) std::malloc (sizeof(int)); + delete[] p; +} + +void new_object_delete_array (void) { + int a = 10; + int * p; + if (a < 20) + p = new int {10}; + delete[] p; +} + +void populate_static_vector (void) { + for (int i = 0; i < 1000; ++i) + vec.push_back (i); +} + +void clear_static_vector (void) { + vec.clear (); +} + +void populate_static_vector_ptr (void) { + for (int i = 0; i < 1000; ++i) + vec_ptr.push_back (new int {i}); +} + +void clear_static_vector_ptr (void) { + for (auto p : vec_ptr) + delete p; + vec_ptr.clear (); +} diff --git a/ex/memory_checks_cpp/array.h b/ex/memory_checks_cpp/array.h new file mode 100644 index 0000000..3afa446 --- /dev/null +++ b/ex/memory_checks_cpp/array.h @@ -0,0 +1,71 @@ +#ifndef ARRAY_H_INCLUDED +#define ARRAY_H_INCLUDED + +#include + +struct array { + int * data; + size_t len; + size_t cap; +}; + +struct array * array_new(void); +struct array * array_new_calloc(void); +void array_free(struct array * array); +void array_free_leak(struct array * array); +size_t array_length(struct array * array); +size_t array_capacity(struct array * array); +int array_element(struct array * array, size_t index); +int array_append(struct array * array, int value); +int array_append_reallocarray(struct array * array, int value); + +class array_cpp { +public: + array_cpp (); + ~array_cpp (); + void append (int value); + + const size_t length (void) const { return len; } + const size_t capacity (void) const { return cap; } + const int * get_data (void) const { return data; } + int operator [](int i) const { return data[i]; } + + const static size_t initial_cap = 8; +private: + int * data; + size_t len; + size_t cap; +}; + +array_cpp * array_cpp_new (void); +void array_cpp_delete (array_cpp *array); + +void double_free (void); +void double_delete (void); +void double_delete_array (void); + +void non_malloc_free (void); +void non_new_delete (void); +void non_new_array_delete (void); + +void * malloc_zero_size (void); +void * realloc_zero_size (void * ptr); + + +void new_object_free (void); +void new_array_object_free (void); + + +void malloc_object_delete (void); +void new_array_object_delete (void); + +void malloc_object_delete_array (void); +void new_object_delete_array (void); + + +void populate_static_vector (void); +void clear_static_vector (void); +void populate_static_vector_ptr (void); +void clear_static_vector_ptr (void); + +#endif diff --git a/ex/memory_checks/tests/00_hash_map_cpp.cc b/ex/memory_checks_cpp/tests/00_hash_map.cc similarity index 91% rename from ex/memory_checks/tests/00_hash_map_cpp.cc rename to ex/memory_checks_cpp/tests/00_hash_map.cc index c066284..72010ff 100644 --- a/ex/memory_checks/tests/00_hash_map_cpp.cc +++ b/ex/memory_checks_cpp/tests/00_hash_map.cc @@ -29,7 +29,7 @@ TEST (map_insert) { struct bt_mem_node * ins_node = bt_mem_table_insert (&i); CHECK (ins_node != NULL); ins_node->size = 12; - ins_node->allocator = BT_MALLOC; + ins_node->allocator = bt_allocator::MALLOC; struct bt_mem_node * node = bt_mem_table_find (&i); CHECK (node != NULL); @@ -51,7 +51,7 @@ TEST (map_update) { struct bt_mem_node * ins_node = bt_mem_table_insert (&i); CHECK (ins_node != NULL); ins_node->size = 12; - ins_node->allocator = BT_MALLOC; + ins_node->allocator = bt_allocator::MALLOC; struct bt_mem_node * node = bt_mem_table_find (&i); CHECK (node != NULL); @@ -62,7 +62,7 @@ TEST (map_update) { size_t capacity = bt_mem_table_capacity; ins_node = bt_mem_table_insert (&i); - ins_node->allocator = BT_NEW; + ins_node->allocator = bt_allocator::NEW; ins_node->size = 15; CHECK (node != NULL); CHECK_CMP (node->size,==,15); @@ -88,7 +88,7 @@ TEST (map_insert_collisions) { for (size_t i = 0; i < len; ++i) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK(node != NULL); - node->allocator = BT_MALLOC; + node->allocator = bt_allocator::MALLOC; node->size = items[i]; } @@ -96,7 +96,7 @@ TEST (map_insert_collisions) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); - CHECK_CMP (node->allocator,==,BT_MALLOC); + CHECK_CMP (node->allocator,==,bt_allocator::MALLOC); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); @@ -120,7 +120,7 @@ TEST (map_update_collisions) { for (size_t i = 0; i < len; ++i) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK(node != NULL); - node->allocator = BT_MALLOC; + node->allocator = bt_allocator::MALLOC; node->size = items[i]; } @@ -128,7 +128,7 @@ TEST (map_update_collisions) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); - CHECK_CMP (node->allocator,==,BT_MALLOC); + CHECK_CMP (node->allocator,==,bt_allocator::MALLOC); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); @@ -141,7 +141,7 @@ TEST (map_update_collisions) { for (size_t i = 0; i < len; ++i) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK(node != NULL); - node->allocator = BT_NEW; + node->allocator = bt_allocator::NEW; node->size = items[i]; } @@ -149,7 +149,7 @@ TEST (map_update_collisions) { const struct bt_mem_node * node = bt_mem_table_find (items + i); CHECK (node != NULL); CHECK_CMP (node->size,==,items[i]); - CHECK_CMP (node->allocator,==,BT_NEW); + CHECK_CMP (node->allocator,==,bt_allocator::NEW); CHECK (items + i == node->address); } CHECK (bt_mem_table_size == len); @@ -171,7 +171,7 @@ TEST (map_free) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK (node != NULL); node->size = 10; - node->allocator = BT_MALLOC; + node->allocator = bt_allocator::MALLOC; } bt_mem_table_free (); @@ -189,7 +189,7 @@ TEST (map_remove) { struct bt_mem_node * node = bt_mem_table_insert (&x); CHECK (node != NULL); node->size = 10; - node->allocator = BT_MALLOC; + node->allocator = bt_allocator::MALLOC; CHECK (bt_mem_table_remove (&x)); CHECK (bt_mem_table_find (&x) == NULL); bt_mem_table_free (); @@ -215,7 +215,7 @@ TEST (map_remove_collisions) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK (node != NULL); node->size = 10; - node->allocator = BT_MALLOC; + node->allocator = bt_allocator::MALLOC; } CHECK (bt_mem_table_size == len); @@ -244,7 +244,7 @@ TEST (map_remove_collisions_not_found) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK (node != NULL); node->size = 10; - node->allocator = BT_MALLOC; + node->allocator = bt_allocator::MALLOC; } CHECK (!bt_mem_table_remove (&x)); @@ -265,7 +265,7 @@ TEST (map_insert_remove_series) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK (node != NULL); node->size = items[i]; - node->allocator = BT_MALLOC; + node->allocator = bt_allocator::MALLOC; } for (size_t i = 0; i < len/2; ++i) { @@ -288,7 +288,7 @@ TEST (map_insert_remove_series) { struct bt_mem_node * node = bt_mem_table_insert (items + i); CHECK (node != NULL); node->size = items[i]; - node->allocator = BT_MALLOC; + node->allocator = bt_allocator::MALLOC; } for (size_t i = len/2; i < len; ++i) { diff --git a/ex/memory_checks/tests/01_fail_allocations_cpp.cc b/ex/memory_checks_cpp/tests/01_fail_allocations.cc similarity index 83% rename from ex/memory_checks/tests/01_fail_allocations_cpp.cc rename to ex/memory_checks_cpp/tests/01_fail_allocations.cc index 0014ffb..b002dce 100644 --- a/ex/memory_checks/tests/01_fail_allocations_cpp.cc +++ b/ex/memory_checks_cpp/tests/01_fail_allocations.cc @@ -1,7 +1,6 @@ #include "basic_testing.h" -extern "C" { #include "../array.h" -} +#include @@ -396,5 +395,94 @@ TEST (fail_reallocarray_reset) { } +TEST (array_new_init) { + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + CHECK_CMP (array->length (),==,0); + CHECK_CMP (array->capacity (),==,0); + array_cpp_delete (array); + TEST_PASSED; +} + + +TEST (fail_new) { + MEM_FAIL_ALL (); + try { + array_cpp * array = array_cpp_new (); + array_cpp_delete (array); + } catch (const std::bad_alloc& e) { + TEST_PASSED; + } + + TEST_FAILED; +} + + +TEST (reset_after_fail_new) { + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + CHECK_CMP (array->length (),==,0); + CHECK_CMP (array->capacity (),==,0); + array_cpp_delete (array); + TEST_PASSED; +} + + +TEST (array_new_array_init) { + array_cpp array; + + CHECK_CMP (array.length (),==,0); + CHECK_CMP (array.capacity (),==,0); + + for (int i = 0; i < 100; ++i) + array.append (i); + + CHECK_CMP (array.length (),==,100); + CHECK_CMP (array.capacity (),>=,100); + + for (int i = 0; i < 100; ++i) + CHECK_CMP (array[i],==,i); + + TEST_PASSED; +} + + +TEST (fail_new_array) { + MEM_FAIL_ALL (); + array_cpp array; + + try { + for (int i = 0; i < 100; ++i) + array.append (i); + } catch (const std::bad_alloc& e) { + CHECK_CMP (array.length (),==,0); + CHECK_CMP (array.capacity (),==,0); + TEST_PASSED; + } + + TEST_FAILED; +} + + +TEST (reset_after_fail_new_array) { + array_cpp array; + + CHECK_CMP (array.length (),==,0); + CHECK_CMP (array.capacity (),==,0); + + for (int i = 0; i < 100; ++i) + array.append (i); + + CHECK_CMP (array.length (),==,100); + CHECK_CMP (array.capacity (),>=,100); + + for (int i = 0; i < 100; ++i) + CHECK_CMP (array[i],==,i); + + TEST_PASSED; +} + + + MAIN_TEST_DRIVER (); diff --git a/ex/memory_checks/tests/03_memory_leaks_debug_cpp.cc b/ex/memory_checks_cpp/tests/01_fail_allocations_debug.cc similarity index 74% rename from ex/memory_checks/tests/03_memory_leaks_debug_cpp.cc rename to ex/memory_checks_cpp/tests/01_fail_allocations_debug.cc index ca89ae2..4bb3c24 100644 --- a/ex/memory_checks/tests/03_memory_leaks_debug_cpp.cc +++ b/ex/memory_checks_cpp/tests/01_fail_allocations_debug.cc @@ -9,7 +9,7 @@ TEST (compile) { TEST (debugger) { - int result = system ("./tests/03_memory_leaks_cpp -d >/dev/null"); + int result = system ("./tests/01_fail_allocations -d >/dev/null"); if (result != 0) TEST_FAILED; TEST_PASSED; diff --git a/ex/memory_checks/tests/02_allocations_recording_cpp.cc b/ex/memory_checks_cpp/tests/02_allocations_recording.cc similarity index 53% rename from ex/memory_checks/tests/02_allocations_recording_cpp.cc rename to ex/memory_checks_cpp/tests/02_allocations_recording.cc index 5d59dd8..c4f3615 100644 --- a/ex/memory_checks/tests/02_allocations_recording_cpp.cc +++ b/ex/memory_checks_cpp/tests/02_allocations_recording.cc @@ -1,8 +1,6 @@ #include "basic_testing.h" #include -extern "C" { #include "../array.h" -} @@ -18,7 +16,7 @@ TEST (malloc_add_memory_table) { const struct bt_mem_node *node = bt_mem_table_find (array); CHECK (node != NULL); CHECK (node->size == sizeof(struct array)); - + CHECK (node->allocator == bt_allocator::MALLOC); array_free (array); TEST_PASSED; } @@ -50,6 +48,7 @@ TEST (realloc_map_insert) { const struct bt_mem_node *node = bt_mem_table_find (array->data); CHECK (node != NULL); CHECK (node->size == sizeof(int) * array->cap); + CHECK (node->allocator == bt_allocator::MALLOC); array_free (array); TEST_PASSED; } @@ -63,14 +62,14 @@ TEST (realloc_map_update) { const struct bt_mem_node *node = bt_mem_table_find (array->data); CHECK (node != NULL); CHECK (node->size == sizeof(int) * array->cap); - + CHECK (node->allocator == bt_allocator::MALLOC); for (int i = 0; i < 100; ++i) CHECK (array_append(array, i)); node = bt_mem_table_find (array->data); CHECK (node != NULL); CHECK (node->size == sizeof(int) * array->cap); - + CHECK (node->allocator == bt_allocator::MALLOC); array_free (array); TEST_PASSED; } @@ -83,7 +82,7 @@ TEST (calloc_add_memory_table) { const struct bt_mem_node *node = bt_mem_table_find (array); CHECK (node != NULL); CHECK (node->size == sizeof(struct array)); - + CHECK (node->allocator == bt_allocator::MALLOC); array_free (array); TEST_PASSED; } @@ -107,7 +106,7 @@ TEST (reallocarray_map_insert) { const struct bt_mem_node *node = bt_mem_table_find (array->data); CHECK (node != NULL); CHECK (node->size == sizeof (int) * array->cap); - + CHECK (node->allocator == bt_allocator::MALLOC); array_free (array); TEST_PASSED; } @@ -121,17 +120,125 @@ TEST (reallocarray_map_update) { const struct bt_mem_node *node = bt_mem_table_find (array->data); CHECK (node != NULL); CHECK (node->size == sizeof (int) * array->cap); - + CHECK (node->allocator == bt_allocator::MALLOC); for (int i = 0; i < 100; ++i) CHECK (array_append_reallocarray (array, i)); node = bt_mem_table_find (array->data); CHECK (node != NULL); CHECK (node->size == sizeof (int) * array->cap); - + CHECK (node->allocator == bt_allocator::MALLOC); array_free (array); TEST_PASSED; } +TEST (new_add_memory_table) { + array_cpp * array = array_cpp_new(); + CHECK (array != nullptr); + const struct bt_mem_node *node = bt_mem_table_find (array); + CHECK (node != nullptr); + CHECK (node->size >= sizeof(struct array)); + CHECK (node->allocator == bt_allocator::NEW); + array_cpp_delete (array); + TEST_PASSED; +} + + +TEST (new_fail) { + MEM_FAIL_ALL (); + try { + array_cpp * array = array_cpp_new (); + array_cpp_delete (array); + } catch (const std::bad_alloc& e) { + CHECK (bt_mem_table_size == 0); + TEST_PASSED; + } + TEST_FAILED; +} + + +TEST (delete_table_remove) { + array_cpp * array = array_cpp_new(); + CHECK (array != nullptr); + array_cpp_delete (array); + CHECK (bt_mem_table_size == 0); + TEST_PASSED; +} + + +TEST (new_array_add_memory_table) { + array_cpp array; + array.append(10); + const struct bt_mem_node *node = bt_mem_table_find ((void *) array.get_data()); + CHECK (node != nullptr); + CHECK (node->size >= sizeof(struct array)); + CHECK (node->allocator == bt_allocator::NEW_ARRAY); + TEST_PASSED; +} + + +TEST (new_array_fail) { + MEM_FAIL_ALL (); + try { + array_cpp array; + array.append(10); + } catch (const std::bad_alloc& e) { + CHECK (bt_mem_table_size == 0); + TEST_PASSED; + } + TEST_FAILED; +} + + +TEST (delete_array_table_remove) { + { + array_cpp array; + for (int i = 0; i < 100; ++i) + array.append(i); + } + + CHECK (bt_mem_table_size == 0); + TEST_PASSED; +} + + + MAIN_TEST_DRIVER (); + + + + + + + + + + + + + + + + +// TEST (set_higher_budget_malloc) { +// MEM_SET_ALLOCATION_BUDGET (1); +// struct array * array = array_new (); +// CHECK (array != NULL); +// for (int i = 0; i < 8; ++i) +// CHECK (!array_append (array, i)); +// MEM_SET_ALLOCATION_BUDGET (2); +// for (int i = 8; i < 16; ++i) +// CHECK (array_append (array, i)); +// for (int i = 32; i < 32; ++i) +// CHECK (!array_append (array, i)); +// array_free (array); +// array = array_new (); +// CHECK (array != NULL); +// for (int i = 0; i < 8; ++i) +// CHECK (array_append (array, i)); +// for (int i = 8; i < 16; ++i) +// CHECK (!array_append (array, i)); +// array_free (array); +// TEST_PASSED; +// } diff --git a/ex/memory_checks_cpp/tests/03_delete_array_malloc_object.cc b/ex/memory_checks_cpp/tests/03_delete_array_malloc_object.cc new file mode 100644 index 0000000..b55351d --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_delete_array_malloc_object.cc @@ -0,0 +1,18 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (invalid_delete_array) { + malloc_object_delete_array (); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER(); diff --git a/ex/memory_checks_cpp/tests/03_delete_array_new_object.cc b/ex/memory_checks_cpp/tests/03_delete_array_new_object.cc new file mode 100644 index 0000000..fa04a2b --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_delete_array_new_object.cc @@ -0,0 +1,18 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (invalid_delete_array) { + new_object_delete_array (); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER(); diff --git a/ex/memory_checks_cpp/tests/03_delete_malloc_object.cc b/ex/memory_checks_cpp/tests/03_delete_malloc_object.cc new file mode 100644 index 0000000..54b9bd4 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_delete_malloc_object.cc @@ -0,0 +1,18 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (invalid_delete) { + malloc_object_delete (); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER(); diff --git a/ex/memory_checks_cpp/tests/03_delete_new_array_object.cc b/ex/memory_checks_cpp/tests/03_delete_new_array_object.cc new file mode 100644 index 0000000..fa8b4d1 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_delete_new_array_object.cc @@ -0,0 +1,18 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (invalid_delete) { + new_array_object_delete (); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER(); diff --git a/ex/memory_checks/tests/03_non_portable_malloc_cpp.cc b/ex/memory_checks_cpp/tests/03_double_delete.cc similarity index 62% rename from ex/memory_checks/tests/03_non_portable_malloc_cpp.cc rename to ex/memory_checks_cpp/tests/03_double_delete.cc index 89a3c1e..16f5023 100644 --- a/ex/memory_checks/tests/03_non_portable_malloc_cpp.cc +++ b/ex/memory_checks_cpp/tests/03_double_delete.cc @@ -1,6 +1,6 @@ #include "basic_testing.h" #include - +#include "../array.h" TEST (compile) { @@ -8,9 +8,8 @@ TEST (compile) { } -TEST (malloc_zero_size) { - void * p = malloc (0); - CHECK (p != NULL); +TEST (invalid_delete) { + double_delete (); TEST_PASSED; } diff --git a/ex/memory_checks/tests/03_double_free_cpp.cc b/ex/memory_checks_cpp/tests/03_double_delete_array.cc similarity index 54% rename from ex/memory_checks/tests/03_double_free_cpp.cc rename to ex/memory_checks_cpp/tests/03_double_delete_array.cc index 03d5736..c6fdb72 100644 --- a/ex/memory_checks/tests/03_double_free_cpp.cc +++ b/ex/memory_checks_cpp/tests/03_double_delete_array.cc @@ -1,6 +1,6 @@ #include "basic_testing.h" #include - +#include "../array.h" TEST (compile) { @@ -8,11 +8,8 @@ TEST (compile) { } -TEST (invalid_free) { - int a = 10; - void * p = malloc (10); - if (a < 20) free (p); - free (p); +TEST (invalid_delete) { + double_delete_array (); TEST_PASSED; } diff --git a/ex/memory_checks_cpp/tests/03_double_free.cc b/ex/memory_checks_cpp/tests/03_double_free.cc new file mode 100644 index 0000000..cd1e39b --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_double_free.cc @@ -0,0 +1,17 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (invalid_free) { + double_free (); + TEST_PASSED; +} + + +MAIN_TEST_DRIVER (compile, invalid_free); diff --git a/ex/memory_checks_cpp/tests/03_free_new_array_object.cc b/ex/memory_checks_cpp/tests/03_free_new_array_object.cc new file mode 100644 index 0000000..3021b8b --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_free_new_array_object.cc @@ -0,0 +1,18 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (invalid_free) { + new_array_object_free (); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER(); diff --git a/ex/memory_checks_cpp/tests/03_free_new_object.cc b/ex/memory_checks_cpp/tests/03_free_new_object.cc new file mode 100644 index 0000000..7ce458a --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_free_new_object.cc @@ -0,0 +1,18 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (invalid_free) { + new_object_free (); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER(); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_calloc.cc b/ex/memory_checks_cpp/tests/03_memory_leak_calloc.cc new file mode 100644 index 0000000..c8749e4 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_calloc.cc @@ -0,0 +1,19 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (memory_leak) { + struct array * array = array_new_calloc (); + CHECK (array != NULL); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, memory_leak); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_calloc_debug.cc b/ex/memory_checks_cpp/tests/03_memory_leak_calloc_debug.cc new file mode 100644 index 0000000..e678ce1 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_calloc_debug.cc @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (debugger) { + int result = system ("./tests/03_memory_leak_calloc -d >/dev/null"); + + if (result != 0) TEST_FAILED; + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, debugger); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_malloc.cc b/ex/memory_checks_cpp/tests/03_memory_leak_malloc.cc new file mode 100644 index 0000000..c466939 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_malloc.cc @@ -0,0 +1,19 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (memory_leak) { + struct array * array = array_new (); + CHECK (array != NULL); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, memory_leak); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_malloc_debug.cc b/ex/memory_checks_cpp/tests/03_memory_leak_malloc_debug.cc new file mode 100644 index 0000000..019b1a3 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_malloc_debug.cc @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (debugger) { + int result = system ("./tests/03_memory_leak_malloc -d >/dev/null"); + + if (result != 0) TEST_FAILED; + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, debugger); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_new.cc b/ex/memory_checks_cpp/tests/03_memory_leak_new.cc new file mode 100644 index 0000000..4baf947 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_new.cc @@ -0,0 +1,19 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (memory_leak) { + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, memory_leak); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_new_array.cc b/ex/memory_checks_cpp/tests/03_memory_leak_new_array.cc new file mode 100644 index 0000000..1712131 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_new_array.cc @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (memory_leak) { + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array->append (10); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, memory_leak); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_new_array_debug.cc b/ex/memory_checks_cpp/tests/03_memory_leak_new_array_debug.cc new file mode 100644 index 0000000..dc4ae1b --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_new_array_debug.cc @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (debugger) { + int result = system ("./tests/03_memory_leak_new_array -d >/dev/null"); + + if (result != 0) TEST_FAILED; + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, debugger); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_new_debug.cc b/ex/memory_checks_cpp/tests/03_memory_leak_new_debug.cc new file mode 100644 index 0000000..81a1476 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_new_debug.cc @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (debugger) { + int result = system ("./tests/03_memory_leak_new -d >/dev/null"); + + if (result != 0) TEST_FAILED; + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, debugger); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_realloc.cc b/ex/memory_checks_cpp/tests/03_memory_leak_realloc.cc new file mode 100644 index 0000000..dbd087b --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_realloc.cc @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (memory_leak) { + struct array * array = array_new (); + CHECK (array != NULL); + CHECK (array_append (array, 1)); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, memory_leak); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_realloc_debug.cc b/ex/memory_checks_cpp/tests/03_memory_leak_realloc_debug.cc new file mode 100644 index 0000000..a614a75 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_realloc_debug.cc @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (debugger) { + int result = system ("./tests/03_memory_leak_realloc -d >/dev/null"); + + if (result != 0) TEST_FAILED; + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, debugger); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_reallocarray.cc b/ex/memory_checks_cpp/tests/03_memory_leak_reallocarray.cc new file mode 100644 index 0000000..2b830e0 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_reallocarray.cc @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (memory_leak) { + struct array * array = array_new (); + CHECK (array != NULL); + CHECK (array_append_reallocarray (array, 1)); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, memory_leak); diff --git a/ex/memory_checks_cpp/tests/03_memory_leak_reallocarray_debug.cc b/ex/memory_checks_cpp/tests/03_memory_leak_reallocarray_debug.cc new file mode 100644 index 0000000..6f5e8e0 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_memory_leak_reallocarray_debug.cc @@ -0,0 +1,20 @@ +#include "basic_testing.h" +#include + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (debugger) { + int result = system ("./tests/03_memory_leak_reallocarray -d >/dev/null"); + + if (result != 0) TEST_FAILED; + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, debugger); diff --git a/ex/memory_checks/tests/03_memory_leaks_cpp.cc b/ex/memory_checks_cpp/tests/03_memory_leaks.cc similarity index 86% rename from ex/memory_checks/tests/03_memory_leaks_cpp.cc rename to ex/memory_checks_cpp/tests/03_memory_leaks.cc index 74477a6..13804cf 100644 --- a/ex/memory_checks/tests/03_memory_leaks_cpp.cc +++ b/ex/memory_checks_cpp/tests/03_memory_leaks.cc @@ -1,7 +1,5 @@ #include "basic_testing.h" -extern "C" { #include "../array.h" -} @@ -14,10 +12,11 @@ TEST (memory_leak) { struct array * array = array_new (); CHECK (array != NULL); CHECK (array_append (array, 1)); + array_free_leak (array); TEST_PASSED; } -MAIN_TEST_DRIVER (); +MAIN_TEST_DRIVER (compile, memory_leak); diff --git a/ex/memory_checks/tests/04_budget_allocations_debug_cpp.cc b/ex/memory_checks_cpp/tests/03_memory_leaks_debug.cc similarity index 60% rename from ex/memory_checks/tests/04_budget_allocations_debug_cpp.cc rename to ex/memory_checks_cpp/tests/03_memory_leaks_debug.cc index 96a6521..4ffefff 100644 --- a/ex/memory_checks/tests/04_budget_allocations_debug_cpp.cc +++ b/ex/memory_checks_cpp/tests/03_memory_leaks_debug.cc @@ -9,7 +9,7 @@ TEST (compile) { TEST (debugger) { - int result = system ("./tests/04_budget_allocations_cpp -d >/dev/null"); + int result = system ("./tests/03_memory_leaks -d >/dev/null"); if (result != 0) TEST_FAILED; TEST_PASSED; @@ -17,4 +17,4 @@ TEST (debugger) { -MAIN_TEST_DRIVER (); +MAIN_TEST_DRIVER (compile, debugger); diff --git a/ex/memory_checks_cpp/tests/03_non_malloc_free.cc b/ex/memory_checks_cpp/tests/03_non_malloc_free.cc new file mode 100644 index 0000000..f485eca --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_non_malloc_free.cc @@ -0,0 +1,17 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (invalid_free) { + non_malloc_free (); + TEST_PASSED; +} + + +MAIN_TEST_DRIVER (compile, invalid_free); diff --git a/ex/memory_checks_cpp/tests/03_non_new_array_delete.cc b/ex/memory_checks_cpp/tests/03_non_new_array_delete.cc new file mode 100644 index 0000000..96097ab --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_non_new_array_delete.cc @@ -0,0 +1,17 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (invalid_delete) { + non_new_array_delete (); + TEST_PASSED; +} + + +MAIN_TEST_DRIVER (compile, invalid_delete); diff --git a/ex/memory_checks_cpp/tests/03_non_new_delete.cc b/ex/memory_checks_cpp/tests/03_non_new_delete.cc new file mode 100644 index 0000000..b918d86 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_non_new_delete.cc @@ -0,0 +1,17 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (invalid_delete) { + non_new_delete (); + TEST_PASSED; +} + + +MAIN_TEST_DRIVER (compile, invalid_delete); diff --git a/ex/memory_checks_cpp/tests/03_non_portable_malloc.cc b/ex/memory_checks_cpp/tests/03_non_portable_malloc.cc new file mode 100644 index 0000000..0526e84 --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_non_portable_malloc.cc @@ -0,0 +1,19 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (non_portable_malloc) { + void * p = malloc_zero_size (); + CHECK (p != NULL); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (compile, non_portable_malloc); diff --git a/ex/memory_checks/tests/03_non_portable_realloc_cpp.cc b/ex/memory_checks_cpp/tests/03_non_portable_realloc.cc similarity index 54% rename from ex/memory_checks/tests/03_non_portable_realloc_cpp.cc rename to ex/memory_checks_cpp/tests/03_non_portable_realloc.cc index a2aa519..22b3b66 100644 --- a/ex/memory_checks/tests/03_non_portable_realloc_cpp.cc +++ b/ex/memory_checks_cpp/tests/03_non_portable_realloc.cc @@ -1,5 +1,5 @@ #include "basic_testing.h" -#include +#include "../array.h" @@ -8,16 +8,15 @@ TEST (compile) { } -TEST (realloc_zero_size) { +TEST (non_portable_realloc) { void * p = malloc (10); CHECK (p != NULL); - void * s = realloc (p, 0); + void * s = realloc_zero_size (p); CHECK (s != NULL); - + TEST_PASSED; } - -MAIN_TEST_DRIVER (); +MAIN_TEST_DRIVER (compile, non_portable_realloc); diff --git a/ex/memory_checks_cpp/tests/03_static_object_leaked.cc b/ex/memory_checks_cpp/tests/03_static_object_leaked.cc new file mode 100644 index 0000000..6f0fe8b --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_static_object_leaked.cc @@ -0,0 +1,19 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (static_object_ptr) { + populate_static_vector_ptr (); + TEST_PASSED; +} + + + + +MAIN_TEST_DRIVER (); diff --git a/ex/memory_checks_cpp/tests/03_static_object_non_leaked.cc b/ex/memory_checks_cpp/tests/03_static_object_non_leaked.cc new file mode 100644 index 0000000..3faf4ab --- /dev/null +++ b/ex/memory_checks_cpp/tests/03_static_object_non_leaked.cc @@ -0,0 +1,33 @@ +#include "basic_testing.h" +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (static_object) { + populate_static_vector (); + TEST_PASSED; +} + + +TEST (static_object_clear) { + populate_static_vector (); + clear_static_vector (); + TEST_PASSED; +} + + +TEST (static_object_ptr_clear) { + populate_static_vector_ptr (); + clear_static_vector_ptr (); + TEST_PASSED; +} + + + + +MAIN_TEST_DRIVER (); diff --git a/ex/memory_checks/tests/04_budget_allocations_cpp.cc b/ex/memory_checks_cpp/tests/04_budget_allocations.cc similarity index 51% rename from ex/memory_checks/tests/04_budget_allocations_cpp.cc rename to ex/memory_checks_cpp/tests/04_budget_allocations.cc index cf65ee1..29555d2 100644 --- a/ex/memory_checks/tests/04_budget_allocations_cpp.cc +++ b/ex/memory_checks_cpp/tests/04_budget_allocations.cc @@ -1,7 +1,6 @@ #include "basic_testing.h" -extern "C" { #include "../array.h" -} +#include @@ -204,38 +203,52 @@ TEST (realloc_budget_reset) { } -TEST (set_higher_budget) { +TEST (set_same_budget_malloc) { MEM_SET_ALLOCATION_BUDGET (1); struct array * array = array_new (); CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); - MEM_SET_ALLOCATION_BUDGET (2); - for (int i = 8; i < 16; ++i) - CHECK (array_append (array, i)); - for (int i = 32; i < 32; ++i) + MEM_SET_ALLOCATION_BUDGET (1); + for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); array_free (array); - array = array_new (); + TEST_PASSED; +} + + +TEST (set_higher_budget_malloc) { + MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new (); CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + MEM_SET_ALLOCATION_BUDGET (2); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); array_free (array); + MEM_SET_ALLOCATION_BUDGET (3); + array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 16; ++i) + CHECK (array_append (array, i)); + array_free (array); TEST_PASSED; } -TEST (set_lower_budget) { - MEM_SET_ALLOCATION_BUDGET (2); +TEST (set_lower_budget_malloc) { + MEM_SET_ALLOCATION_BUDGET (4); struct array * array = array_new (); - CHECK (array != NULL); + MEM_SET_ALLOCATION_BUDGET (2); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); + CHECK (!array_append (array, 9)); + MEM_SET_ALLOCATION_BUDGET (1); for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); - MEM_SET_ALLOCATION_BUDGET (1); array_free (array); array = array_new (); CHECK (array != NULL); @@ -243,7 +256,18 @@ TEST (set_lower_budget) { CHECK (!array_append (array, i)); array_free (array); TEST_PASSED; +} + +TEST (set_lower_budget_after_allocations_malloc) { + MEM_SET_ALLOCATION_BUDGET (3); + struct array * array = array_new (); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + MEM_SET_ALLOCATION_BUDGET (2); + CHECK (!array_append (array, 17)); + array_free (array); + TEST_PASSED; } @@ -276,16 +300,263 @@ TEST (reallocarray_budget) { CHECK (!array_append_reallocarray (array, i)); CHECK_CMP (array_length (array),==,0); CHECK_CMP (array_capacity (array),==,0); - MEM_SET_ALLOCATION_BUDGET (1); + MEM_SET_ALLOCATION_BUDGET (2); for (int i = 0; i < 4; ++i) CHECK (array_append_reallocarray (array, i)); CHECK_CMP (array_length (array),==,4); CHECK_CMP (array_capacity (array),==,8); - array_free (array); TEST_PASSED; } +TEST (zero_budget_new) { + MEM_SET_ALLOCATION_BUDGET (0); + try { + array_cpp * array = array_cpp_new (); + array_cpp_delete (array); + } catch (const std::bad_alloc& e) { + TEST_PASSED; + } + TEST_FAILED; +} + + +TEST (reset_after_budget_new) { + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array_cpp_delete (array); + TEST_PASSED; +} + + +TEST (simple_budget_new) { + MEM_SET_ALLOCATION_BUDGET (1); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + try { + array_cpp * array2 = array_cpp_new (); + array_cpp_delete (array2); + } catch (const std::bad_alloc& e) { + array_cpp_delete(array); + TEST_PASSED; + } + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (delete_increment_budget) { + MEM_SET_ALLOCATION_BUDGET (1); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array_cpp_delete (array); + array_cpp * array2 = array_cpp_new (); + CHECK (array2 != nullptr); + array_cpp_delete (array2); + TEST_PASSED; +} + + +TEST (new_budget_reset) { + MEM_SET_ALLOCATION_BUDGET (0); + + try { + array_cpp * array = array_cpp_new (); + array_cpp_delete(array); + } catch (const std::bad_alloc& e) { + MEM_RESET_ALLOCATOR (); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array_cpp_delete (array); + TEST_PASSED; + } + TEST_FAILED; +} + + +TEST (budget_new_array) { + array_cpp array; + MEM_SET_ALLOCATION_BUDGET (1); + + try { + for (int i = 0; i < 100; ++i) + array.append (i); + } catch (const std::bad_alloc& e) { + CHECK_CMP (array.length (),==,array_cpp::initial_cap); + CHECK_CMP (array.capacity (),==,array_cpp::initial_cap); + TEST_PASSED; + } + + TEST_FAILED; +} + + +TEST (reset_after_budget_new_array) { + array_cpp array; + + CHECK_CMP (array.length (),==,0); + CHECK_CMP (array.capacity (),==,0); + + for (int i = 0; i < 4; ++i) + array.append (i); + + CHECK_CMP (array.length (),==,4); + CHECK_CMP (array.capacity (),==,array_cpp::initial_cap); + TEST_PASSED; +} + + +TEST (reset_budget_new_array) { + MEM_SET_ALLOCATION_BUDGET (0); + array_cpp array; + + try { + for (int i = 0; i < 4; ++i) + array.append (i); + } catch (const std::bad_alloc& e) { + CHECK_CMP (array.length (),==,0); + CHECK_CMP (array.capacity (),==,0); + + MEM_RESET_ALLOCATOR (); + for (int i = 0; i < 4; ++i) + array.append (i); + + CHECK_CMP (array.length (),==,4); + CHECK_CMP (array.capacity (),==,array_cpp::initial_cap); + TEST_PASSED; + } + + TEST_FAILED; +} + + +TEST (set_same_budget_new) { + MEM_SET_ALLOCATION_BUDGET (1); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + try { + array_cpp * array2 = array_cpp_new (); + array_cpp_delete (array2); + } catch (const std::bad_alloc& e) { + MEM_SET_ALLOCATION_BUDGET (1); + try { + array_cpp * array2 = array_cpp_new (); + array_cpp_delete (array2); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + TEST_PASSED; + } + } + + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_same_budget_new_array) { + MEM_SET_ALLOCATION_BUDGET (1); + array_cpp array; + for (int i = 0; i < 8; ++i) + array.append (i); + try { + array.append (9); + } catch (const std::bad_alloc& e) { + MEM_SET_ALLOCATION_BUDGET (1); + try { + array.append (9); + } catch (const std::bad_alloc& e) { + TEST_PASSED; + } + } + + TEST_FAILED; +} + + +TEST (set_higher_budget_new) { + MEM_SET_ALLOCATION_BUDGET (1); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + try { + for (int i = 0; i < 8; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + MEM_SET_ALLOCATION_BUDGET (2); + for (int i = 0; i < 8; ++i) + array->append (i); + try { + for (int i = 8; i < 16; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + MEM_SET_ALLOCATION_BUDGET (3); + array = array_cpp_new (); + CHECK (array != nullptr); + for (int i = 0; i < 16; ++i) + array->append (i); + array_cpp_delete (array); + TEST_PASSED; + } + } + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_lower_budget_new) { + MEM_SET_ALLOCATION_BUDGET (4); + array_cpp * array = array_cpp_new (); + MEM_SET_ALLOCATION_BUDGET (2); + for (int i = 0; i < 8; ++i) + array->append (i); + try { + array->append (9); + } catch (const std::bad_alloc& e) { + MEM_SET_ALLOCATION_BUDGET (1); + + try { + for (int i = 8; i < 16; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + array = array_cpp_new (); + CHECK (array != nullptr); + + try { + for (int i = 0; i < 8; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + TEST_PASSED; + } + } + } + + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_lower_budget_after_allocations_new) { + MEM_SET_ALLOCATION_BUDGET (3); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + for (int i = 0; i < 8; ++i) + array->append (i); + MEM_SET_ALLOCATION_BUDGET (2); + + try { + array->append (17); + } catch(const std::bad_alloc& e) { + array_cpp_delete (array); + TEST_PASSED; + } + array_cpp_delete (array); + TEST_FAILED; +} + + + MAIN_TEST_DRIVER (); diff --git a/ex/memory_checks/tests/01_fail_allocations_debug_cpp.cc b/ex/memory_checks_cpp/tests/04_budget_allocations_debug.cc similarity index 70% rename from ex/memory_checks/tests/01_fail_allocations_debug_cpp.cc rename to ex/memory_checks_cpp/tests/04_budget_allocations_debug.cc index 4bd5516..d48cfb3 100644 --- a/ex/memory_checks/tests/01_fail_allocations_debug_cpp.cc +++ b/ex/memory_checks_cpp/tests/04_budget_allocations_debug.cc @@ -9,7 +9,7 @@ TEST (compile) { TEST (debugger) { - int result = system ("./tests/01_fail_allocations_cpp -d >/dev/null"); + int result = system ("./tests/04_budget_allocations -d >/dev/null"); if (result != 0) TEST_FAILED; TEST_PASSED; diff --git a/ex/memory_checks/tests/05_byte_budget_allocations_cpp.cc b/ex/memory_checks_cpp/tests/05_byte_budget_allocations.cc similarity index 50% rename from ex/memory_checks/tests/05_byte_budget_allocations_cpp.cc rename to ex/memory_checks_cpp/tests/05_byte_budget_allocations.cc index 44edfbb..a43321c 100644 --- a/ex/memory_checks/tests/05_byte_budget_allocations_cpp.cc +++ b/ex/memory_checks_cpp/tests/05_byte_budget_allocations.cc @@ -1,8 +1,6 @@ #include "basic_testing.h" #include -extern "C" { #include "../array.h" -} @@ -207,38 +205,52 @@ TEST (realloc_budget_reset) { } -TEST (set_higher_budget) { - MEM_SET_BYTES_BUDGET (sizeof (struct array)); +TEST (set_same_budget) { + MEM_SET_BYTES_BUDGET (sizeof(struct array)); struct array * array = array_new (); CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); - MEM_SET_BYTES_BUDGET (16*sizeof (int)); - for (int i = 8; i < 16; ++i) - CHECK (array_append (array, i)); - for (int i = 32; i < 32; ++i) + MEM_SET_BYTES_BUDGET (sizeof(struct array)); + for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); array_free (array); - array = array_new (); + TEST_PASSED; +} + + +TEST (set_higher_budget) { + MEM_SET_BYTES_BUDGET (sizeof(struct array)); + struct array * array = array_new (); CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); array_free (array); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 16*sizeof(int)); + array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 16; ++i) + CHECK (array_append (array, i)); + array_free (array); TEST_PASSED; } TEST (set_lower_budget) { - MEM_SET_BYTES_BUDGET (sizeof (struct array) + 8*sizeof (int)); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 32*sizeof(int)); struct array * array = array_new (); - CHECK (array != NULL); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); + CHECK (!array_append (array, 9)); + MEM_SET_BYTES_BUDGET (sizeof(struct array)); for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); - MEM_SET_BYTES_BUDGET (sizeof (struct array)); array_free (array); array = array_new (); CHECK (array != NULL); @@ -246,7 +258,18 @@ TEST (set_lower_budget) { CHECK (!array_append (array, i)); array_free (array); TEST_PASSED; +} + +TEST (set_lower_budget_after_allocations) { + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 16*sizeof(int)); + struct array * array = array_new (); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); + CHECK (!array_append (array, 17)); + array_free (array); + TEST_PASSED; } @@ -295,7 +318,7 @@ TEST (reallocarray_budget) { CHECK (!array_append_reallocarray (array, i)); CHECK_CMP (array_length (array),==,0); CHECK_CMP (array_capacity (array),==,0); - MEM_SET_BYTES_BUDGET (sizeof (int)*8); + MEM_SET_BYTES_BUDGET (sizeof(struct array) + sizeof (int)*8); for (int i = 0; i < 4; ++i) CHECK (array_append_reallocarray (array, i)); CHECK_CMP (array_length (array),==,4); @@ -306,4 +329,280 @@ TEST (reallocarray_budget) { + + + + + + + + + + + + + + + + + + + + + + + + + + + + +TEST (zero_budget_new) { + MEM_SET_BYTES_BUDGET (0); + try { + array_cpp * array = array_cpp_new (); + array_cpp_delete (array); + } catch (const std::bad_alloc& e) { + TEST_PASSED; + } + TEST_FAILED; +} + + +TEST (reset_after_budget_new) { + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array_cpp_delete (array); + TEST_PASSED; +} + + +TEST (simple_budget_new) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + try { + array_cpp * array2 = array_cpp_new (); + array_cpp_delete (array2); + } catch (const std::bad_alloc& e) { + array_cpp_delete(array); + TEST_PASSED; + } + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (delete_increment_budget) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array_cpp_delete (array); + array_cpp * array2 = array_cpp_new (); + CHECK (array2 != nullptr); + array_cpp_delete (array2); + TEST_PASSED; +} + + +TEST (new_budget_reset) { + MEM_SET_BYTES_BUDGET (0); + try { + array_cpp * array = array_cpp_new (); + array_cpp_delete(array); + } catch (const std::bad_alloc& e) { + MEM_RESET_ALLOCATOR (); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array_cpp_delete (array); + TEST_PASSED; + } + TEST_FAILED; +} + + +TEST (budget_new_array) { + array_cpp array; + MEM_SET_BYTES_BUDGET (array_cpp::initial_cap*sizeof(int)); + + try { + for (int i = 0; i < 100; ++i) + array.append (i); + } catch (const std::bad_alloc& e) { + CHECK_CMP (array.length (),==,array_cpp::initial_cap); + CHECK_CMP (array.capacity (),==,array_cpp::initial_cap); + TEST_PASSED; + } + + TEST_FAILED; +} + + +TEST (reset_after_budget_new_array) { + array_cpp array; + + CHECK_CMP (array.length (),==,0); + CHECK_CMP (array.capacity (),==,0); + + for (int i = 0; i < 4; ++i) + array.append (i); + + CHECK_CMP (array.length (),==,4); + CHECK_CMP (array.capacity (),==,array_cpp::initial_cap); + TEST_PASSED; +} + + +TEST (reset_budget_new_array) { + MEM_SET_BYTES_BUDGET (0); + array_cpp array; + + try { + for (int i = 0; i < 4; ++i) + array.append (i); + } catch (const std::bad_alloc& e) { + CHECK_CMP (array.length (),==,0); + CHECK_CMP (array.capacity (),==,0); + + MEM_RESET_ALLOCATOR (); + for (int i = 0; i < 4; ++i) + array.append (i); + + CHECK_CMP (array.length (),==,4); + CHECK_CMP (array.capacity (),==,array_cpp::initial_cap); + TEST_PASSED; + } + + TEST_FAILED; +} + + +TEST (set_same_budget_new) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + try { + array_cpp * array2 = array_cpp_new (); + array_cpp_delete (array2); + } catch (const std::bad_alloc& e) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); + try { + array_cpp * array2 = array_cpp_new (); + array_cpp_delete (array2); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + TEST_PASSED; + } + } + + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_same_budget_new_array) { + MEM_SET_BYTES_BUDGET (array_cpp::initial_cap*sizeof(int)); + array_cpp array; + for (int i = 0; i < 8; ++i) + array.append (i); + try { + array.append (9); + } catch (const std::bad_alloc& e) { + MEM_SET_BYTES_BUDGET (array_cpp::initial_cap*sizeof(int)); + try { + array.append (9); + } catch (const std::bad_alloc& e) { + TEST_PASSED; + } + } + + TEST_FAILED; +} + + +TEST (set_higher_budget_new) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + try { + for (int i = 0; i < 8; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + array_cpp::initial_cap*sizeof(int)); + for (int i = 0; i < 8; ++i) + array->append (i); + try { + for (int i = 8; i < 16; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + array_cpp::initial_cap*3*sizeof(int)); + array = array_cpp_new (); + CHECK (array != nullptr); + for (int i = 0; i < 16; ++i) + array->append (i); + array_cpp_delete (array); + TEST_PASSED; + } + } + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_lower_budget_new) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + 100*sizeof(int)); + array_cpp * array = array_cpp_new (); + MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + 8*sizeof(int)); + for (int i = 0; i < 8; ++i) + array->append (i); + + try { + array->append (9); + } catch (const std::bad_alloc& e) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); + + try { + for (int i = 8; i < 16; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + array = array_cpp_new (); + CHECK (array != nullptr); + + try { + for (int i = 0; i < 8; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + TEST_PASSED; + } + } + } + + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_lower_budget_after_allocations_new) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + 16*sizeof(int)); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + for (int i = 0; i < 8; ++i) + array->append (i); + MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + 8*sizeof(int)); + try { + array->append (17); + } catch(const std::bad_alloc& e) { + array_cpp_delete (array); + TEST_PASSED; + } + array_cpp_delete (array); + TEST_FAILED; +} + + + + MAIN_TEST_DRIVER (); diff --git a/ex/memory_checks/tests/05_byte_budget_allocations_debug_cpp.cc b/ex/memory_checks_cpp/tests/05_byte_budget_allocations_debug.cc similarity index 68% rename from ex/memory_checks/tests/05_byte_budget_allocations_debug_cpp.cc rename to ex/memory_checks_cpp/tests/05_byte_budget_allocations_debug.cc index b3a9db8..c96028c 100644 --- a/ex/memory_checks/tests/05_byte_budget_allocations_debug_cpp.cc +++ b/ex/memory_checks_cpp/tests/05_byte_budget_allocations_debug.cc @@ -7,7 +7,7 @@ TEST(compile) { TEST(debugger) { - int result = system("./tests/05_byte_budget_allocations_cpp -d >/dev/null"); + int result = system("./tests/05_byte_budget_allocations -d >/dev/null"); if (result != 0) TEST_FAILED; TEST_PASSED; diff --git a/ex/memory_checks/tests/06_scheduled_failures_cpp.cc b/ex/memory_checks_cpp/tests/06_scheduled_failures.cc similarity index 67% rename from ex/memory_checks/tests/06_scheduled_failures_cpp.cc rename to ex/memory_checks_cpp/tests/06_scheduled_failures.cc index d8bc5f4..64d1299 100644 --- a/ex/memory_checks/tests/06_scheduled_failures_cpp.cc +++ b/ex/memory_checks_cpp/tests/06_scheduled_failures.cc @@ -1,8 +1,7 @@ #include "basic_testing.h" #include -extern "C" { +#include #include "../array.h" -} @@ -216,5 +215,129 @@ TEST (reallocarray_failure_reset) { } +TEST (fail_next_count_new) { + MEM_SCHEDULE_FAILURE (1, 1000); + + try { + array_cpp * array = array_cpp_new (); + array_cpp_delete (array); + } catch (const std::bad_alloc& e) { + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array_cpp_delete (array); + TEST_PASSED; + } + TEST_FAILED; +} + + +TEST (fail_next_size_new) { + MEM_SCHEDULE_FAILURE (1000, sizeof(array_cpp)); + try { + array_cpp * array = array_cpp_new (); + array_cpp_delete (array); + } catch (const std::bad_alloc& e) { + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array_cpp_delete (array); + TEST_PASSED; + } + TEST_FAILED; +} + + +TEST (no_failure_new) { + MEM_SCHEDULE_FAILURE (0, 0); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array_cpp_delete (array); + TEST_PASSED; +} + + +TEST (failure_reset_new) { + MEM_SCHEDULE_FAILURE (1, sizeof(array_cpp)); + MEM_CANCEL_FAILURE (); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array_cpp_delete (array); + TEST_PASSED; +} + + +TEST (setting_failure_new) { + MEM_SCHEDULE_FAILURE (1, sizeof(array_cpp)); + TEST_PASSED; +} + + +TEST (reset_after_failure_new) { + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + array_cpp_delete (array); + TEST_PASSED; +} + + +TEST (fail_next_count_new_array) { + MEM_SCHEDULE_FAILURE (1, 1000); + array_cpp array; + + try { + array.append(1); + } catch (const std::bad_alloc& e) { + array.append(1); + TEST_PASSED; + } + TEST_FAILED; +} + + +TEST (fail_next_size_new_array) { + MEM_SCHEDULE_FAILURE (1000, array_cpp::initial_cap*sizeof(int)); + array_cpp array; + try { + array.append(1); + } catch (const std::bad_alloc& e) { + array.append(1); + TEST_PASSED; + } + TEST_FAILED; +} + + +TEST (no_failure_new_array) { + MEM_SCHEDULE_FAILURE (0, 0); + array_cpp array; + for (int i = 0; i < 100; ++i) + array.append (i); + TEST_PASSED; +} + + +TEST (failure_reset_new_array) { + MEM_SCHEDULE_FAILURE (1, sizeof (array_cpp)); + MEM_CANCEL_FAILURE (); + array_cpp array; + for (int i = 0; i < 100; ++i) + array.append (i); + TEST_PASSED; +} + + +TEST (setting_failure_new_array) { + MEM_SCHEDULE_FAILURE (1, sizeof (array_cpp)); + TEST_PASSED; +} + + +TEST (reset_after_failure_new_array) { + array_cpp array; + for (int i = 0; i < 100; ++i) + array.append (i); + TEST_PASSED; +} + + MAIN_TEST_DRIVER (); diff --git a/ex/memory_checks/tests/06_scheduled_failures_debug_cpp.cc b/ex/memory_checks_cpp/tests/06_scheduled_failures_debug.cc similarity index 70% rename from ex/memory_checks/tests/06_scheduled_failures_debug_cpp.cc rename to ex/memory_checks_cpp/tests/06_scheduled_failures_debug.cc index 0a043f4..1f5c636 100644 --- a/ex/memory_checks/tests/06_scheduled_failures_debug_cpp.cc +++ b/ex/memory_checks_cpp/tests/06_scheduled_failures_debug.cc @@ -9,7 +9,7 @@ TEST (compile) { TEST (debugger) { - int result = system ("./tests/06_scheduled_failures_cpp -d >/dev/null"); + int result = system ("./tests/06_scheduled_failures -d >/dev/null"); if (result != 0) TEST_FAILED; TEST_PASSED; diff --git a/ex/memory_checks/tests/07_calloc_reallocarray_failures_cpp.cc b/ex/memory_checks_cpp/tests/07_calloc_reallocarray_failures.cc similarity index 100% rename from ex/memory_checks/tests/07_calloc_reallocarray_failures_cpp.cc rename to ex/memory_checks_cpp/tests/07_calloc_reallocarray_failures.cc diff --git a/ex/memory_checks_cpp/tests/08_fopen_leak.cc b/ex/memory_checks_cpp/tests/08_fopen_leak.cc new file mode 100644 index 0000000..0bee302 --- /dev/null +++ b/ex/memory_checks_cpp/tests/08_fopen_leak.cc @@ -0,0 +1,15 @@ +#include "basic_testing.h" +#include + + + + +TEST (memory_leak) { + FILE * fp = fopen("/tmp/leak_fopen", "w"); + fprintf (fp, "testing\n"); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (memory_leak); diff --git a/ex/memory_checks_cpp/tests/08_stdlib_functions.cc b/ex/memory_checks_cpp/tests/08_stdlib_functions.cc new file mode 100644 index 0000000..cec41cf --- /dev/null +++ b/ex/memory_checks_cpp/tests/08_stdlib_functions.cc @@ -0,0 +1,422 @@ +#include "basic_testing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +static int int_comparator (const void * a, const void * b) { + const int aval = (*(const int *)a); + const int bval = (*(const int *)b); + return aval - bval; +} + + +TEST (compile) { + TEST_PASSED; +} + + +// ctype.h functions +TEST (ctype_no_leaks) { + CHECK (isalnum ('a')); + CHECK (isalpha ('a')); + CHECK (iscntrl ('\n')); + CHECK (isdigit ('1')); + CHECK (isgraph ('a')); + CHECK (islower ('a')); + CHECK (isprint ('a')); + CHECK (ispunct ('.')); + CHECK (isspace (' ')); + CHECK (isupper ('A')); + CHECK (isxdigit ('A')); + CHECK_CMP (toupper ('a'),==,'A'); + CHECK_CMP (tolower ('A'),==,'a'); + TEST_PASSED; +} + + +// string.h functions +TEST (strcpy_no_leaks) { + char out[10]; + strcpy (out, "hello"); + CHECK_STRING_CMP (out,==,"hello"); + TEST_PASSED; +} + + +TEST (strncpy_no_leaks) { + char out[10]; + strncpy (out, "hello", 6); + CHECK_STRING_CMP (out,==,"hello"); + TEST_PASSED; +} + + +TEST (strcat_no_leaks) { + char out[10] = "hello"; + strcat (out, "he"); + CHECK_STRING_CMP (out,==,"hellohe"); + TEST_PASSED; +} + + +TEST (strncat_no_leaks) { + char out[10] = "hello"; + strncat (out, "he", 3); + CHECK_STRING_CMP (out,==,"hellohe"); + TEST_PASSED; +} + + +TEST (strcmp_no_leaks) { + CHECK_CMP (strcmp ("hello", "hello"),==,0); + TEST_PASSED; +} + + +TEST (strncmp_no_leaks) { + CHECK_CMP (strncmp ("hello", "hello2", 3),==,0); + TEST_PASSED; +} + + +TEST (strchr_no_leaks) { + const char *s = "hello"; + CHECK_STRING_CMP (strchr (s, 'l'),==,"llo"); + TEST_PASSED; +} + + +TEST (strrchr_no_leaks) { + const char *s = "hello"; + CHECK_STRING_CMP (strrchr (s, 'l'),==,"lo"); + TEST_PASSED; +} + + +TEST (strspn_no_leaks) { + const char *s = "hello"; + CHECK_CMP (strspn (s, "hel"),==,4); + TEST_PASSED; +} + + +TEST (strcspn_no_leaks) { + const char *s = "hello"; + CHECK_CMP (strcspn (s, "h"),==,0); + TEST_PASSED; +} + + +TEST (strpbrk_no_leaks) { + const char *s = "hello"; + CHECK_STRING_CMP (strpbrk (s, "l"),==,"llo"); + TEST_PASSED; +} + + +TEST (strstr_no_leaks) { + const char *s = "hello"; + CHECK_STRING_CMP (strstr (s, "lo"),==,"lo"); + TEST_PASSED; +} + + +TEST (strlen_no_leaks) { + const char *s = "hello"; + CHECK_CMP (strlen (s),==,5); + TEST_PASSED; +} + + +TEST (strerror_no_leaks) { + CHECK_STRING_CMP (strerror (EINVAL),==,"Invalid argument"); + TEST_PASSED; +} + + +TEST (strtok_no_leaks) { + char s[] = "hello,hello,hello"; + CHECK_STRING_CMP (strtok (s, ","),==,"hello"); + TEST_PASSED; +} + + +TEST (memcpy_no_leaks) { + char out[10]; + memcpy (out, "hello", 6); + CHECK_STRING_CMP (out,==,"hello"); + TEST_PASSED; +} + + +TEST (memmove_no_leaks) { + char out[10]; + memmove (out, "hello", 6); + CHECK_STRING_CMP (out,==,"hello"); + TEST_PASSED; +} + + +TEST (memcmp_no_leaks) { + CHECK_CMP (memcmp ("hello", "hello", 6),==,0); + TEST_PASSED; +} + + +TEST (memchr_no_leaks) { + const char * s = "hello"; + CHECK (memchr (s, 'l', 4) == s+2); + TEST_PASSED; +} + + +TEST (memset_no_leaks) { + char out[10]; + out[5] = '\0'; + memset (out, 'a', 5); + CHECK_STRING_CMP (out,==,"aaaaa"); + TEST_PASSED; +} + + +// ctype.h functions +TEST (math_no_leaks) { + CHECK_CMP (sin (0),==,0); + CHECK_CMP (cos (0),==,1); + CHECK_CMP (tan (0),==,0); + CHECK_CMP (sinh (0),==,0); + CHECK_CMP (cosh (0),==,1); + CHECK_CMP (tanh (0),==,0); + CHECK_CMP (exp (0),==,1); + CHECK_CMP (log (1),==,0); + CHECK_CMP (log10 (1),==,0); + CHECK_CMP (pow (2, 1),==,2); + CHECK_CMP (sqrt (4),==,2); + CHECK_CMP (ceil (4.3),==,5); + CHECK_CMP (floor (4.3),==,4); + CHECK_CMP (fabs (-4.3),==,4.3); + CHECK_CMP (ldexp (4, 2),==,16); + int x; + CHECK_CMP (frexp (0.5, &x),==,0.5); + double ip; + CHECK_CMP (modf (4.3, &ip),==,0.3); + CHECK_CMP (fmod (4.3, 4),==,0.3); + CHECK_CMP (abs (-10),==, 10); + CHECK_CMP (labs (-10),==, 10); + div_t res = div (10, 2); + CHECK_CMP (res.quot,==,5); + CHECK_CMP (res.rem,==,0); + ldiv_t res_l = ldiv (10, 2); + CHECK_CMP (res_l.quot,==,5); + CHECK_CMP (res_l.rem,==,0); + TEST_PASSED; + +} + + +// stdlib.h functions +TEST (stdlib_conversion_no_leaks) { + CHECK_CMP (atof ("2.23"),==,2.23); + CHECK_CMP (atoi ("2"),==,2); + CHECK_CMP (atol ("2"),==,2); + CHECK_CMP (strtod ("2.23", (char **) NULL),==,2.23); + CHECK_CMP (strtol ("2", (char **)NULL, 10),==,2); + CHECK_CMP (strtoul ("2", (char **)NULL, 10),==,2); + TEST_PASSED; +} + + +TEST (rand_no_leaks) { + srand (10); + CHECK_CMP (rand (),==,1215069295); + TEST_PASSED; +} + + +TEST (getenv_no_leaks) { + char * p = getenv ("PWD"); + CHECK (p != NULL); + TEST_PASSED; +} + + +TEST (qsort_no_leaks) { + int array[] = {32, 1, 41, 0, 31, 13}; + qsort (array, 6, sizeof(int), int_comparator); + for (int i = 1; i < 6; ++i) + CHECK_CMP (array[i],>=,array[i-1]); + TEST_PASSED; +} + + +TEST (bsearch_no_leaks) { + int array[] = {0, 1, 2, 3, 10, 32}; + int key = 10; + int * res = (int *) bsearch (&key, array, 6, sizeof(int), int_comparator); + CHECK_CMP (*res,==,key); + TEST_PASSED; +} + + +// time.h functions +TEST (time_no_leaks) { + CHECK_CMP (clock (),!=,-1); + CHECK_CMP (time (NULL),!=,-1); + CHECK_CMP (difftime (12, 10),==,2); + time_t t = time (NULL); + struct tm * tm_val = gmtime (&t); + CHECK (tm_val != NULL); + CHECK (mktime (tm_val) != -1); + CHECK (localtime (&t) != NULL); + CHECK_STRING_CMP (asctime(localtime(&t)),==, ctime (&t)); + char buf[100]; + size_t size = strftime (buf, 100, "%I:%M:%S", tm_val); + for (char * p = buf; p != buf + size; ++p) + CHECK (isprint (*p)); + TEST_PASSED; +} + + +// stdio.h functions +static void write_fp (FILE *fp, const char *format, ...) { + va_list ap; + + va_start (ap, format); + vfprintf (fp, format, ap); + va_end (ap); +} + + +static void read_fp (FILE *fp, const char *format, ...) { + va_list ap; + + va_start (ap, format); + vfscanf (fp, format, ap); + va_end (ap); +} + + +TEST (basic_file_operations_no_leak) { + char buf[100]; + FILE * fp = fopen ("/tmp/open_stlib_open", "w"); + CHECK (fp != NULL); + CHECK_CMP (setvbuf(fp, NULL, _IONBF, 0),==,0); + fputc('a', fp); + putc('b', fp); + fputs ("some line\n", fp); + const char * line = "some line 2\n"; + fwrite (line, sizeof(char), strlen (line), fp); + fprintf (fp, "testing %d\n", 10); + write_fp (fp, "testing vfprintf %d\n", 11); + + fflush (fp); + rewind (fp); + fpos_t pos; + CHECK_CMP (fgetpos (fp, &pos),==,0); + CHECK_CMP (ftell (fp),!=,-1); + rewind (fp); + CHECK_CMP (fsetpos (fp, &pos),==,0); + CHECK (fseek(fp, 0L, SEEK_SET) == 0); + fclose (fp); + fp = tmpfile (); + setbuf(fp, NULL); + CHECK_CMP (rename ("/tmp/open_stlib_open", "/tmp/open_stlib_open2"),==,0); + CHECK (fp != NULL); + + fp = freopen("/tmp/open_stlib_open2", "r", fp); + CHECK_CMP (fgetc (fp),==,'a'); + CHECK_CMP (getc (fp),==,'b'); + ungetc ('b', fp); + CHECK_CMP (getc (fp),==,'b'); + fgets (buf, 11, fp); + CHECK_STRING_CMP (buf,==,"some line\n"); + fread (buf, sizeof(char), strlen(line), fp); + buf[strlen(line)] = '\0'; + CHECK_STRING_CMP (buf,==,line); + + int x; + fscanf (fp, "testing %d\n", &x); + CHECK_CMP (x,==,10); + read_fp (fp, "testing vfprintf %d\n", &x); + CHECK_CMP (x,==,11); + CHECK_CMP (feof (fp),!=, 0); + CHECK_CMP (ferror (fp),==, 0); + clearerr (fp); + fclose (fp); + CHECK_CMP (remove ("/tmp/open_stlib_open2"),==,0); + TEST_PASSED; +} + + +static void write_str (char *buf, const char *format, ...) { + va_list ap; + + va_start (ap, format); + vsprintf (buf, format, ap); + va_end (ap); +} + + +static void read_str (char *buf, const char *format, ...) { + va_list ap; + + va_start (ap, format); + vsscanf (buf, format, ap); + va_end (ap); +} + +TEST (stdio_string_no_leak) { + char buf[100]; + char * name = tempnam (NULL, "somefile"); + CHECK (name != NULL); + sprintf (buf, "testing %d", 10); + int x; + sscanf (buf, "testing %d", &x); + CHECK_CMP (x,==,10); + write_str (buf, "testing vsprintf %d", 11); + read_str (buf, "testing vsprintf %d", &x); + CHECK_CMP (x,==,11); + free (name); + TEST_PASSED; +} + + + +MAIN_TEST_DRIVER (ctype_no_leaks, + strcpy_no_leaks, + strncpy_no_leaks, + strcat_no_leaks, + strncat_no_leaks, + strcmp_no_leaks, + strncmp_no_leaks, + strchr_no_leaks, + strrchr_no_leaks, + strspn_no_leaks, + strcspn_no_leaks, + strcspn_no_leaks, + strpbrk_no_leaks, + strstr_no_leaks, + strlen_no_leaks, + strerror_no_leaks, + strtok_no_leaks, + memcpy_no_leaks, + memmove_no_leaks, + memcmp_no_leaks, + memchr_no_leaks, + memset_no_leaks, + math_no_leaks, + stdlib_conversion_no_leaks, + rand_no_leaks, + qsort_no_leaks, + bsearch_no_leaks, + time_no_leaks, + basic_file_operations_no_leak, + stdio_string_no_leak); diff --git a/ex/memory_checks/tests/08_lib_allocation_cpp.cc b/ex/memory_checks_cpp/tests/08_strdup_leak.cc similarity index 77% rename from ex/memory_checks/tests/08_lib_allocation_cpp.cc rename to ex/memory_checks_cpp/tests/08_strdup_leak.cc index 682079e..8e4be6d 100644 --- a/ex/memory_checks/tests/08_lib_allocation_cpp.cc +++ b/ex/memory_checks_cpp/tests/08_strdup_leak.cc @@ -1,5 +1,5 @@ #include "basic_testing.h" -#include +#include @@ -12,4 +12,4 @@ TEST (memory_leak) { TEST_PASSED; } -MAIN_TEST_DRIVER (); +MAIN_TEST_DRIVER (memory_leak); diff --git a/ex/memory_checks_cpp/tests/08_tmpfile_leak.cc b/ex/memory_checks_cpp/tests/08_tmpfile_leak.cc new file mode 100644 index 0000000..c3c2e23 --- /dev/null +++ b/ex/memory_checks_cpp/tests/08_tmpfile_leak.cc @@ -0,0 +1,15 @@ +#include "basic_testing.h" +#include + + + +TEST (memory_leak) { + FILE *fp = tmpfile (); + fprintf (fp, "testing\n"); + TEST_PASSED; +} + + + + +MAIN_TEST_DRIVER (memory_leak); diff --git a/ex/memory_checks_cpp/tests/08_tmpnum_leak.cc b/ex/memory_checks_cpp/tests/08_tmpnum_leak.cc new file mode 100644 index 0000000..04c455a --- /dev/null +++ b/ex/memory_checks_cpp/tests/08_tmpnum_leak.cc @@ -0,0 +1,12 @@ +#include "basic_testing.h" +#include + + + +TEST (memory_leak) { + char * name = tempnam (NULL, "somefile"); + CHECK (name != NULL); + TEST_PASSED; +} + +MAIN_TEST_DRIVER (memory_leak); From 9d46b6e66ba3d816d55b91b03286f31977cc6196 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Fri, 6 Sep 2024 13:38:18 +0200 Subject: [PATCH 09/37] Update pipeline to introduce tests on ubuntu 22.04/24.04 and macos-lates and on the gcc and clang compiler suites. Update the Makefile to support parallelism and fail fast. Update the example7 to trick the compiler warnings --- .github/workflows/build.yaml | 10 ++++++++-- Makefile | 9 +++++++-- ex ws/example7 ws/flipline.c | 2 +- ex/example7/flipline.c | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3be1e77..11f74c2 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,10 +15,16 @@ jobs: strategy: matrix: - os: [ubuntu-latest, macos-latest] + os: [ubuntu-24.04, ubuntu-22.04, macos-latest] + compiler_suite: [gcc, clang] steps: - uses: actions/checkout@v4 - name: Run tests - run: make + run: | + if [ "${{ matrix.compiler_suite }}" = 'gcc' ]; then + make CC=gcc CXX=g++ FAIL_FAST=yes PARALLELISM=4 + elif [ "${{ matrix.compiler_suite }}" = 'clang' ]; then + make CC=clang CXX=clang++ FAIL_FAST=yes PARALLELISM=4 + fi diff --git a/Makefile b/Makefile index 8766da8..f0e7581 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,12 @@ .PHONY: all all: all-examples +FAIL_FAST ?= no EXAMPLES = ex/example1 ex/example2 ex/example3 ex/example4 \ ex/example5 ex/example6 ex/example7 ex/example8 ex/memory_checks \ 'ex ws/example1 ws' 'ex ws/example2 ws' 'ex ws/example3 ws' 'ex ws/example4 ws' \ 'ex ws/example5 ws' 'ex ws/example6 ws' 'ex ws/example7 ws' 'ex ws/example8 ws' +PARALLELISM ?= 1 .PHONY: all-examples all-examples: @@ -12,10 +14,10 @@ all-examples: do test_result=PASS; \ cp -a basic_testing.h "$$ex"/tests ;\ $(MAKE) -C "$$ex" clean > /dev/null || test_result=FAIL; \ - $(MAKE) -C "$$ex" TEST_COLORS=no > "$$ex".out 2>&1 || test_result=FAIL ; \ + $(MAKE) -C "$$ex" -j $(PARALLELISM) TEST_COLORS=no > "$$ex".out || test_result=FAIL ; \ if test -r "$$ex".expected; \ then { IFS=''; while read l; \ - do if grep -Fq "$$l" "$$ex".out; \ + do if fgrep -q "$$l" "$$ex".out; \ then : ; \ else echo "'$$ex.out' must contain '$$l'"; \ test_result=FAIL; \ @@ -27,6 +29,9 @@ all-examples: rm -f "$$ex".out; \ else echo "$$ex FAIL" ; \ echo "check '$$ex.out' and '$$ex.expected' to see what went wrong"; \ + if [ "$(FAIL_FAST)" = "yes" ]; \ + then exit 1; \ + fi; \ fi; \ done diff --git a/ex ws/example7 ws/flipline.c b/ex ws/example7 ws/flipline.c index d358174..fcae46d 100644 --- a/ex ws/example7 ws/flipline.c +++ b/ex ws/example7 ws/flipline.c @@ -9,7 +9,7 @@ int main() { if (c == '\n') { if (i > 10) { i = 0; - while (line[i] != 255) { + while ((int) line[i] != 255) { line[i] = *p; --i; } diff --git a/ex/example7/flipline.c b/ex/example7/flipline.c index d358174..fcae46d 100644 --- a/ex/example7/flipline.c +++ b/ex/example7/flipline.c @@ -9,7 +9,7 @@ int main() { if (c == '\n') { if (i > 10) { i = 0; - while (line[i] != 255) { + while ((int) line[i] != 255) { line[i] = *p; --i; } From 0582859a5c794944e7301b505e71a5a1bb7e353b Mon Sep 17 00:00:00 2001 From: pako-23 Date: Fri, 6 Sep 2024 13:40:47 +0200 Subject: [PATCH 10/37] Fix tipy in Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f0e7581..31512bc 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ all-examples: $(MAKE) -C "$$ex" -j $(PARALLELISM) TEST_COLORS=no > "$$ex".out || test_result=FAIL ; \ if test -r "$$ex".expected; \ then { IFS=''; while read l; \ - do if fgrep -q "$$l" "$$ex".out; \ + do if grep -Fq "$$l" "$$ex".out; \ then : ; \ else echo "'$$ex.out' must contain '$$l'"; \ test_result=FAIL; \ From 84224a040a1a26ba21c1e8a8a7a8fa4801542af3 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Fri, 6 Sep 2024 14:04:43 +0200 Subject: [PATCH 11/37] fix macos version, sorting lists in pipeline --- .github/workflows/build.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 11f74c2..439c134 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,16 +15,16 @@ jobs: strategy: matrix: - os: [ubuntu-24.04, ubuntu-22.04, macos-latest] - compiler_suite: [gcc, clang] + os: [macos-14, ubuntu-22.04, ubuntu-24.04] + compiler_suite: [clang, gcc] steps: - uses: actions/checkout@v4 - name: Run tests run: | - if [ "${{ matrix.compiler_suite }}" = 'gcc' ]; then - make CC=gcc CXX=g++ FAIL_FAST=yes PARALLELISM=4 - elif [ "${{ matrix.compiler_suite }}" = 'clang' ]; then + if [ "${{ matrix.compiler_suite }}" = 'clang' ]; then make CC=clang CXX=clang++ FAIL_FAST=yes PARALLELISM=4 + elif [ "${{ matrix.compiler_suite }}" = 'gcc' ]; then + make CC=gcc CXX=g++ FAIL_FAST=yes PARALLELISM=4 fi From 6a1857a947679ee1e0d0352c924ad385b06e4cc1 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Tue, 10 Sep 2024 10:17:50 +0200 Subject: [PATCH 12/37] add _GNU_SOURCE --- basic_testing.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/basic_testing.h b/basic_testing.h index 8907f95..7101738 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -62,6 +62,10 @@ #define RUNNING_ON_VALGRIND 0 #endif +#ifndef _GNU_SOURCE +#define _GNU_GNU_SOURCE +#endif + /* SUCCESS/FAILURE macros */ #define BT_FAILURE 0 From a16b513d29c199da9c63ee43146370cfb6147402 Mon Sep 17 00:00:00 2001 From: Antonio Carzaniga Date: Tue, 10 Sep 2024 10:21:06 +0200 Subject: [PATCH 13/37] separate compile and link for tests, use CXX as linker --- basic_testing.mk | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/basic_testing.mk b/basic_testing.mk index 1ad0a5d..7bdc2aa 100644 --- a/basic_testing.mk +++ b/basic_testing.mk @@ -184,14 +184,14 @@ check-io-sh: compile $(TESTS_IO) $(TESTS_SH) $(PROGRAMS_DRIVERS) done; \ test_summary 'Summary: PASS ' -# BT_LDFLAGS := -Wl,--wrap=malloc,--wrap=free,--wrap=realloc,--wrap=calloc,--wrap=reallocarray -# BT_CXXLDFLAGS := -Wl,--wrap=_Znwm,--wrap=_Znam,--wrap=_ZdlPvm,--wrap=_ZdaPv - -$(TESTS_DIR)/%: $(TESTS_DIR)/%.c $(OBJECTS) - $(CC) $(CFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.c $(OBJECTS) -o $@ - -$(TESTS_DIR)/%: $(TESTS_DIR)/%.cc $(OBJECTS) - $(CXX) -std=c++11 $(CXXFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.cc $(OBJECTS) -o $@ +BT_WRAPPED_SYMBOLS := malloc free realloc calloc reallocarray \ + _Znwm _Znam _ZdlPvm _ZdaPv +BT_WRAP_FLAGS := $(foreach S,$(BT_WRAPPED_SYMBOLS),-Wl,--wrap=$(S)) + +# we must assume there are some C++ sources, so we must link with $(CXX) +# +$(TESTS_DIR)/%: $(TESTS_DIR)/%.o $(OBJECTS) + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(BT_WRAP_FLAGS) $(TESTS_DIR)/$*.o $(OBJECTS) -o $@ .PHONY: check-bin check-bin: $(TESTS_BIN) From 8413c79eab390e5cd245df8349556785e8a4cafb Mon Sep 17 00:00:00 2001 From: pako-23 Date: Tue, 10 Sep 2024 10:24:55 +0200 Subject: [PATCH 14/37] add -ldl to get dlsym --- basic_testing.h | 4 ---- basic_testing.mk | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/basic_testing.h b/basic_testing.h index 7101738..8907f95 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -62,10 +62,6 @@ #define RUNNING_ON_VALGRIND 0 #endif -#ifndef _GNU_SOURCE -#define _GNU_GNU_SOURCE -#endif - /* SUCCESS/FAILURE macros */ #define BT_FAILURE 0 diff --git a/basic_testing.mk b/basic_testing.mk index b0317db..fdc150a 100644 --- a/basic_testing.mk +++ b/basic_testing.mk @@ -184,6 +184,7 @@ check-io-sh: compile $(TESTS_IO) $(TESTS_SH) $(PROGRAMS_DRIVERS) done; \ test_summary 'Summary: PASS ' +LDFLAGS += -ldl $(TESTS_DIR)/%: $(TESTS_DIR)/%.c $(OBJECTS) $(CC) $(CFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.c $(OBJECTS) -o $@ From 5c7df90febe56fe0dcb11685497296dda28de9f5 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Tue, 10 Sep 2024 10:26:00 +0200 Subject: [PATCH 15/37] testing pipeline --- basic_testing.h | 1 + 1 file changed, 1 insertion(+) diff --git a/basic_testing.h b/basic_testing.h index 8907f95..6592024 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -28,6 +28,7 @@ #include #include #include +#define _GNU_SOURCE #include #include #include From 6147d24ec1186a89ff9b984cf7d2cef25d15ff05 Mon Sep 17 00:00:00 2001 From: Antonio Carzaniga Date: Tue, 10 Sep 2024 10:40:50 +0200 Subject: [PATCH 16/37] reverting to no wrap flags for the linker. --- basic_testing.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basic_testing.mk b/basic_testing.mk index 7bdc2aa..6304b2b 100644 --- a/basic_testing.mk +++ b/basic_testing.mk @@ -191,7 +191,7 @@ BT_WRAP_FLAGS := $(foreach S,$(BT_WRAPPED_SYMBOLS),-Wl,--wrap=$(S)) # we must assume there are some C++ sources, so we must link with $(CXX) # $(TESTS_DIR)/%: $(TESTS_DIR)/%.o $(OBJECTS) - $(CXX) $(CXXFLAGS) $(LDFLAGS) $(BT_WRAP_FLAGS) $(TESTS_DIR)/$*.o $(OBJECTS) -o $@ + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.o $(OBJECTS) -o $@ .PHONY: check-bin check-bin: $(TESTS_BIN) From 7c20842a31d27c25e8731a25e6a4c9efa5d92705 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Tue, 10 Sep 2024 10:42:34 +0200 Subject: [PATCH 17/37] testing pipeline --- basic_testing.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/basic_testing.h b/basic_testing.h index 6592024..b85f26a 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -19,6 +19,10 @@ #ifndef BASIC_TESTING_H_INCLUDED #define BASIC_TESTING_H_INCLUDED +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + #include #include #include @@ -28,7 +32,6 @@ #include #include #include -#define _GNU_SOURCE #include #include #include From e81c9e0b65126920443d0e1bbc37cd1affc20e92 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Tue, 10 Sep 2024 10:46:08 +0200 Subject: [PATCH 18/37] temporarly disable ubuntu-22 --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 439c134..0ff53c9 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,7 +15,7 @@ jobs: strategy: matrix: - os: [macos-14, ubuntu-22.04, ubuntu-24.04] + os: [macos-14, ubuntu-24.04] compiler_suite: [clang, gcc] steps: From 35b77530d7956a6f8ebaaf675e4d7e9c8095e591 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Tue, 10 Sep 2024 10:50:39 +0200 Subject: [PATCH 19/37] testing pipeline --- ex/memory_checks/array.c | 2 +- ex/memory_checks_cpp/array.cc | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ex/memory_checks/array.c b/ex/memory_checks/array.c index d5ef9b9..88b2d0c 100644 --- a/ex/memory_checks/array.c +++ b/ex/memory_checks/array.c @@ -80,7 +80,7 @@ void double_free (void) { void non_malloc_free (void) { int a = 10; - int * p; + int * p = NULL; if (a < 20) p = &a; free (p); } diff --git a/ex/memory_checks_cpp/array.cc b/ex/memory_checks_cpp/array.cc index 182a3cc..4c86fc2 100644 --- a/ex/memory_checks_cpp/array.cc +++ b/ex/memory_checks_cpp/array.cc @@ -154,7 +154,7 @@ void * realloc_zero_size (void * ptr) { void new_object_free (void) { int a = 10; - int * p; + int * p = nullptr; if (a < 20) p = new int{10}; std::free (p); @@ -162,7 +162,7 @@ void new_object_free (void) { void new_array_object_free (void) { int a = 10; - int * p; + int * p = nullptr; if (a < 20) p = new int[10]; std::free(p); @@ -170,7 +170,7 @@ void new_array_object_free (void) { void malloc_object_delete (void) { int a = 10; - int * p; + int * p = nullptr; if (a < 20) p = (int *) std::malloc (sizeof(int)); delete p; @@ -178,7 +178,7 @@ void malloc_object_delete (void) { void new_array_object_delete (void) { int a = 10; - int * p; + int * p = nullptr; if (a < 20) p = new int[10]; delete p; @@ -186,7 +186,7 @@ void new_array_object_delete (void) { void malloc_object_delete_array (void) { int a = 10; - int * p; + int * p = nullptr; if (a < 20) p = (int *) std::malloc (sizeof(int)); delete[] p; From d79560d80531a80318f54fd61b8f2fe37f2ca9d2 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Tue, 10 Sep 2024 10:53:00 +0200 Subject: [PATCH 20/37] testing pipeline --- .github/workflows/build.yaml | 2 +- ex/memory_checks_cpp/array.cc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 0ff53c9..897ce41 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,7 +15,7 @@ jobs: strategy: matrix: - os: [macos-14, ubuntu-24.04] + os: [ubuntu-24.04] compiler_suite: [clang, gcc] steps: diff --git a/ex/memory_checks_cpp/array.cc b/ex/memory_checks_cpp/array.cc index 4c86fc2..60ceb44 100644 --- a/ex/memory_checks_cpp/array.cc +++ b/ex/memory_checks_cpp/array.cc @@ -124,21 +124,21 @@ void double_delete_array (void) { void non_malloc_free (void) { int a = 10; - int * p; + int * p = nullptr; if (a < 20) p = &a; std::free (p); } void non_new_delete (void) { int a = 10; - int * p; + int * p = nullptr; if (a < 20) p = &a; delete p; } void non_new_array_delete (void) { int a = 10; - int * p; + int * p = nullptr; if (a < 20) p = &a; delete[] p; From 5850bf58f2b1b6785fb997d061ba3a9567cb3a13 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Tue, 10 Sep 2024 10:54:15 +0200 Subject: [PATCH 21/37] testing pipeline --- ex/memory_checks_cpp/array.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ex/memory_checks_cpp/array.cc b/ex/memory_checks_cpp/array.cc index 60ceb44..5e909ec 100644 --- a/ex/memory_checks_cpp/array.cc +++ b/ex/memory_checks_cpp/array.cc @@ -194,7 +194,7 @@ void malloc_object_delete_array (void) { void new_object_delete_array (void) { int a = 10; - int * p; + int * p = nullptr; if (a < 20) p = new int {10}; delete[] p; From f6e70908b4492f0b578cc7e4cdfa89d9443c2824 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Tue, 10 Sep 2024 10:56:42 +0200 Subject: [PATCH 22/37] add ubuntu 22.04 tests --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 897ce41..6c007b1 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,7 +15,7 @@ jobs: strategy: matrix: - os: [ubuntu-24.04] + os: [ubuntu-22.04, ubuntu-24.04] compiler_suite: [clang, gcc] steps: From 24cf999a711eea1801f857011761c5afdaf5c996 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Tue, 10 Sep 2024 15:14:04 +0200 Subject: [PATCH 23/37] testing pipeline --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 103b68b..50e19f0 100644 --- a/Makefile +++ b/Makefile @@ -10,11 +10,13 @@ PARALLELISM ?= 1 .PHONY: all-examples all-examples: + @$(CC) --version @for ex in $(EXAMPLES); \ do test_result=PASS; \ cp -a basic_testing.h "$$ex"/tests ;\ $(MAKE) -C "$$ex" clean > /dev/null || test_result=FAIL; \ $(MAKE) -C "$$ex" -j $(PARALLELISM) TEST_COLORS=no > "$$ex".out || test_result=FAIL ; \ + cat "$$ex".out ; \ if test -r "$$ex".expected; \ then { IFS=''; while read l; \ do if grep -Fq "$$l" "$$ex".out; \ From a5009ddc230f422607a286590a2431ebc9c7c4af Mon Sep 17 00:00:00 2001 From: pako-23 Date: Tue, 10 Sep 2024 15:19:02 +0200 Subject: [PATCH 24/37] testing pipeline --- basic_testing.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/basic_testing.mk b/basic_testing.mk index b7c2a78..937e268 100644 --- a/basic_testing.mk +++ b/basic_testing.mk @@ -5,6 +5,7 @@ CFLAGS=-Wall -Werror -g $(COVERAGE_FLAGS) CXXFLAGS=-Wall -Werror -g $(COVERAGE_FLAGS) +LDFLAGS += -ldl COVERAGE_FLAGS=$(if $(WITH_COVERAGE),--coverage,) SHELL=/bin/bash From ddeff0aded6cdb37ba2324e5796af19d99890e15 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 11:18:27 +0200 Subject: [PATCH 25/37] define _GNU_SOURCE to compile on ubuntu22.04 --- Makefile | 2 -- basic_testing.h | 19 +++++++++++++------ basic_testing.mk | 7 ++----- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 50e19f0..103b68b 100644 --- a/Makefile +++ b/Makefile @@ -10,13 +10,11 @@ PARALLELISM ?= 1 .PHONY: all-examples all-examples: - @$(CC) --version @for ex in $(EXAMPLES); \ do test_result=PASS; \ cp -a basic_testing.h "$$ex"/tests ;\ $(MAKE) -C "$$ex" clean > /dev/null || test_result=FAIL; \ $(MAKE) -C "$$ex" -j $(PARALLELISM) TEST_COLORS=no > "$$ex".out || test_result=FAIL ; \ - cat "$$ex".out ; \ if test -r "$$ex".expected; \ then { IFS=''; while read l; \ do if grep -Fq "$$l" "$$ex".out; \ diff --git a/basic_testing.h b/basic_testing.h index b85f26a..c40b2cd 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -19,10 +19,6 @@ #ifndef BASIC_TESTING_H_INCLUDED #define BASIC_TESTING_H_INCLUDED -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - #include #include #include @@ -882,6 +878,19 @@ void * reallocarray (void * ptr, size_t nmemb, size_t size) { return realloc (ptr, len); } +BT_POSSIBLY_UNUSED +void qsort (void * base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { + static void (*libc_qsort)(void * base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) = NULL; + + if (!libc_qsort) + libc_qsort = (void (*)(void *, size_t, size_t, int (*)(const void *, const void *))) dlsym(RTLD_NEXT, "qsort"); + + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; + bt_mem_checks_disabled = 1; + libc_qsort(base, nmemb, size, compar); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; +} + BT_POSSIBLY_UNUSED int vfprintf (FILE * stream, const char * format, va_list ap) { static int (*libc_vfprintf)(FILE *, const char *, va_list) = NULL; @@ -1044,8 +1053,6 @@ char * ctime (const time_t * tp) { return result; } - - #ifdef __cplusplus } #endif diff --git a/basic_testing.mk b/basic_testing.mk index 937e268..19b543c 100644 --- a/basic_testing.mk +++ b/basic_testing.mk @@ -3,9 +3,8 @@ # and/or # PROGRAMS= -CFLAGS=-Wall -Werror -g $(COVERAGE_FLAGS) -CXXFLAGS=-Wall -Werror -g $(COVERAGE_FLAGS) -LDFLAGS += -ldl +CFLAGS=-D_GNU_SOURCE -Wall -Werror -g $(COVERAGE_FLAGS) +CXXFLAGS=-D_GNU_SOURCE -Wall -Werror -g $(COVERAGE_FLAGS) COVERAGE_FLAGS=$(if $(WITH_COVERAGE),--coverage,) SHELL=/bin/bash @@ -185,8 +184,6 @@ check-io-sh: compile $(TESTS_IO) $(TESTS_SH) $(PROGRAMS_DRIVERS) done; \ test_summary 'Summary: PASS ' -LDFLAGS += -ldl - # we must assume there are some C++ sources, so we must link with $(CXX) # $(TESTS_DIR)/%: $(TESTS_DIR)/%.o $(OBJECTS) From faabd495fe38e7f4b2ec0225e3526c5075710fd5 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 11:21:14 +0200 Subject: [PATCH 26/37] change PR configuration --- .github/workflows/build.yaml | 1 - Makefile | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 6c007b1..e4f8d59 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,7 +6,6 @@ on: push: branches: [master] pull_request: - branches: [master] workflow_dispatch: jobs: diff --git a/Makefile b/Makefile index 103b68b..5d9a055 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ all-examples: do test_result=PASS; \ cp -a basic_testing.h "$$ex"/tests ;\ $(MAKE) -C "$$ex" clean > /dev/null || test_result=FAIL; \ - $(MAKE) -C "$$ex" -j $(PARALLELISM) TEST_COLORS=no > "$$ex".out || test_result=FAIL ; \ + $(MAKE) -C "$$ex" -j $(PARALLELISM) TEST_COLORS=no > "$$ex".out 2>&1 || test_result=FAIL ; \ if test -r "$$ex".expected; \ then { IFS=''; while read l; \ do if grep -Fq "$$l" "$$ex".out; \ From d1b8dc35b50b998daeb77e0562362a69599ef1d0 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 11:33:25 +0200 Subject: [PATCH 27/37] add macos-14 --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e4f8d59..5dd3347 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - os: [ubuntu-22.04, ubuntu-24.04] + os: [macos-14, ubuntu-22.04, ubuntu-24.04] compiler_suite: [clang, gcc] steps: From 969d4c7ba5d183e3de3c995620d8233611f3e6cd Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 11:35:13 +0200 Subject: [PATCH 28/37] debugging pipeline --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 5d9a055..31083cd 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ all-examples: cp -a basic_testing.h "$$ex"/tests ;\ $(MAKE) -C "$$ex" clean > /dev/null || test_result=FAIL; \ $(MAKE) -C "$$ex" -j $(PARALLELISM) TEST_COLORS=no > "$$ex".out 2>&1 || test_result=FAIL ; \ + cat "$$ex".out ; \ if test -r "$$ex".expected; \ then { IFS=''; while read l; \ do if grep -Fq "$$l" "$$ex".out; \ From cfafd1639fecbd8f72dfe2aa53fa3ad9576e5a63 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 11:38:06 +0200 Subject: [PATCH 29/37] add c++11 standard to compile on MacOS --- basic_testing.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basic_testing.mk b/basic_testing.mk index 19b543c..2a06b2d 100644 --- a/basic_testing.mk +++ b/basic_testing.mk @@ -4,7 +4,7 @@ # PROGRAMS= CFLAGS=-D_GNU_SOURCE -Wall -Werror -g $(COVERAGE_FLAGS) -CXXFLAGS=-D_GNU_SOURCE -Wall -Werror -g $(COVERAGE_FLAGS) +CXXFLAGS=-D_GNU_SOURCE -Wall -Werror -std=c++11 -g $(COVERAGE_FLAGS) COVERAGE_FLAGS=$(if $(WITH_COVERAGE),--coverage,) SHELL=/bin/bash From 209e8893290f73ce94748b3b39a51838a20fd08a Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 12:28:11 +0200 Subject: [PATCH 30/37] testing macos memory instrumentation --- basic_testing.h | 2 ++ ex/memory_checks/array.c | 6 +++++- ex/memory_checks_cpp/array.cc | 6 +++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/basic_testing.h b/basic_testing.h index c40b2cd..ab8d988 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -862,6 +862,7 @@ void * calloc (size_t nmemb, size_t size) { return p; } +#ifndef __APPLE__ BT_POSSIBLY_UNUSED void * reallocarray (void * ptr, size_t nmemb, size_t size) { static void *(*libc_reallocarray)(void *, size_t, size_t) = NULL; @@ -877,6 +878,7 @@ void * reallocarray (void * ptr, size_t nmemb, size_t size) { size_t len = nmemb * size; return realloc (ptr, len); } +#endif BT_POSSIBLY_UNUSED void qsort (void * base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { diff --git a/ex/memory_checks/array.c b/ex/memory_checks/array.c index 88b2d0c..dd6d445 100644 --- a/ex/memory_checks/array.c +++ b/ex/memory_checks/array.c @@ -60,7 +60,11 @@ int array_append_reallocarray (struct array * array, int element) { if (array->len == array->cap) { size_t new_cap = array->cap ? 2*array->cap : initial_cap; - int * new_data = reallocarray(array->data, new_cap, sizeof(int)); +#ifdef __APPLE__ + int * new_data = realloc (array->data, new_cap*sizeof(int)); +#else + int * new_data = reallocarray (array->data, new_cap, sizeof(int)); +#endif if (!new_data) return 0; array->data = new_data; diff --git a/ex/memory_checks_cpp/array.cc b/ex/memory_checks_cpp/array.cc index 5e909ec..fe1e238 100644 --- a/ex/memory_checks_cpp/array.cc +++ b/ex/memory_checks_cpp/array.cc @@ -63,7 +63,11 @@ int array_append_reallocarray (struct array * array, int element) { if (array->len == array->cap) { size_t new_cap = array->cap ? 2*array->cap : initial_cap; - int * new_data = (int *) reallocarray(array->data, new_cap, sizeof(int)); +#ifdef __APPLE__ + int * new_data = (int *) realloc (array->data, new_cap*sizeof(int)); +#else + int * new_data = (int *) reallocarray (array->data, new_cap, sizeof(int)); +#endif if (!new_data) return 0; array->data = new_data; From 970c88f0c27dd58e4b1bf443331e43cef643d1ac Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 13:14:20 +0200 Subject: [PATCH 31/37] testing builds on macos --- .github/workflows/build.yaml | 2 +- ex/memory_checks/array.c | 17 ++++++++++++----- ex/memory_checks/array.h | 1 + .../tests/07_calloc_reallocarray_failures.c | 8 ++++---- ex/memory_checks_cpp/array.cc | 17 ++++++++++++----- ex/memory_checks_cpp/array.h | 2 ++ .../tests/07_calloc_reallocarray_failures.cc | 8 ++++---- 7 files changed, 36 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5dd3347..71ff70f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - os: [macos-14, ubuntu-22.04, ubuntu-24.04] + os: [macos-13, macos-14, ubuntu-22.04, ubuntu-24.04] compiler_suite: [clang, gcc] steps: diff --git a/ex/memory_checks/array.c b/ex/memory_checks/array.c index dd6d445..62a8a74 100644 --- a/ex/memory_checks/array.c +++ b/ex/memory_checks/array.c @@ -60,11 +60,7 @@ int array_append_reallocarray (struct array * array, int element) { if (array->len == array->cap) { size_t new_cap = array->cap ? 2*array->cap : initial_cap; -#ifdef __APPLE__ - int * new_data = realloc (array->data, new_cap*sizeof(int)); -#else - int * new_data = reallocarray (array->data, new_cap, sizeof(int)); -#endif + int * new_data = wrapped_reallocarray (array->data, new_cap, sizeof(int)); if (!new_data) return 0; array->data = new_data; @@ -75,6 +71,17 @@ int array_append_reallocarray (struct array * array, int element) { return 1; } +void * wrapped_reallocarray (void * ptr, size_t nmemb, size_t size) { +#ifdef __APPLE__ + if (nmemb == 0 || size == 0 || SIZE_MAX / nmemb <= size) + return NULL; + + return realloc (ptr, nmemb*size); +#else + return reallocarray (ptr, nmemb, size); +#endif +} + void double_free (void) { int a = 10; void * p = malloc (10); diff --git a/ex/memory_checks/array.h b/ex/memory_checks/array.h index 2e0b6c6..f801aba 100644 --- a/ex/memory_checks/array.h +++ b/ex/memory_checks/array.h @@ -19,6 +19,7 @@ int array_element(struct array * array, size_t index); int array_append(struct array * array, int value); int array_append_reallocarray(struct array * array, int value); +void * wrapped_reallocarray (void * ptr, size_t nmemb, size_t size); void double_free (void); void non_malloc_free (void); void * malloc_zero_size (void); diff --git a/ex/memory_checks/tests/07_calloc_reallocarray_failures.c b/ex/memory_checks/tests/07_calloc_reallocarray_failures.c index 7d872a4..56b5509 100644 --- a/ex/memory_checks/tests/07_calloc_reallocarray_failures.c +++ b/ex/memory_checks/tests/07_calloc_reallocarray_failures.c @@ -1,6 +1,6 @@ #include "basic_testing.h" #include - +#include "../array.h" TEST (compile) { @@ -29,7 +29,7 @@ TEST (calloc_zero_size) { TEST (overflow_reallocarray) { int * p = malloc (sizeof (int)); CHECK (p != NULL); - CHECK (reallocarray (p, 1073741824, 1073741824) == NULL); + CHECK (wrapped_reallocarray (p, 1073741824, 1073741824) == NULL); free (p); TEST_PASSED; } @@ -38,7 +38,7 @@ TEST (overflow_reallocarray) { TEST (reallocarray_zero_nmemb) { int * p = malloc (sizeof (int)); CHECK (p != NULL); - CHECK (reallocarray (p, 0, 1073741824) == NULL); + CHECK (wrapped_reallocarray (p, 0, 1073741824) == NULL); free (p); TEST_PASSED; } @@ -47,7 +47,7 @@ TEST (reallocarray_zero_nmemb) { TEST (reallocarray_zero_size) { int * p = malloc (sizeof (int)); CHECK (p != NULL); - CHECK (reallocarray (p, 1073741824, 0) == NULL); + CHECK (wrapped_reallocarray (p, 1073741824, 0) == NULL); free (p); TEST_PASSED; } diff --git a/ex/memory_checks_cpp/array.cc b/ex/memory_checks_cpp/array.cc index fe1e238..4723075 100644 --- a/ex/memory_checks_cpp/array.cc +++ b/ex/memory_checks_cpp/array.cc @@ -63,11 +63,7 @@ int array_append_reallocarray (struct array * array, int element) { if (array->len == array->cap) { size_t new_cap = array->cap ? 2*array->cap : initial_cap; -#ifdef __APPLE__ - int * new_data = (int *) realloc (array->data, new_cap*sizeof(int)); -#else - int * new_data = (int *) reallocarray (array->data, new_cap, sizeof(int)); -#endif + int * new_data = (int *) wrapped_reallocarray (array->data, new_cap, sizeof(int)); if (!new_data) return 0; array->data = new_data; @@ -78,6 +74,17 @@ int array_append_reallocarray (struct array * array, int element) { return 1; } +void * wrapped_reallocarray (void * ptr, size_t nmemb, size_t size) { +#ifdef __APPLE__ + if (nmemb == 0 || size == 0 || SIZE_MAX / nmemb <= size) + return NULL; + + return realloc (ptr, nmemb*size); +#else + return reallocarray (ptr, nmemb, size); +#endif +} + array_cpp::array_cpp () : data{nullptr}, len{0}, cap{0} {} array_cpp::~array_cpp () { diff --git a/ex/memory_checks_cpp/array.h b/ex/memory_checks_cpp/array.h index 3afa446..a657f57 100644 --- a/ex/memory_checks_cpp/array.h +++ b/ex/memory_checks_cpp/array.h @@ -19,6 +19,8 @@ int array_element(struct array * array, size_t index); int array_append(struct array * array, int value); int array_append_reallocarray(struct array * array, int value); +void * wrapped_reallocarray (void * ptr, size_t nmemb, size_t size); + class array_cpp { public: array_cpp (); diff --git a/ex/memory_checks_cpp/tests/07_calloc_reallocarray_failures.cc b/ex/memory_checks_cpp/tests/07_calloc_reallocarray_failures.cc index 2efe6e4..21e7d4c 100644 --- a/ex/memory_checks_cpp/tests/07_calloc_reallocarray_failures.cc +++ b/ex/memory_checks_cpp/tests/07_calloc_reallocarray_failures.cc @@ -1,6 +1,6 @@ #include "basic_testing.h" #include - +#include "../array.h" TEST (compile) { @@ -29,7 +29,7 @@ TEST (calloc_zero_size) { TEST (overflow_reallocarray) { int * p = (int *) malloc (sizeof (int)); CHECK (p != NULL); - CHECK (reallocarray (p, 1073741824, 1073741824) == NULL); + CHECK (wrapped_reallocarray (p, 1073741824, 1073741824) == NULL); free (p); TEST_PASSED; } @@ -38,7 +38,7 @@ TEST (overflow_reallocarray) { TEST (reallocarray_zero_nmemb) { int * p = (int *) malloc (sizeof (int)); CHECK (p != NULL); - CHECK (reallocarray (p, 0, 1073741824) == NULL); + CHECK (wrapped_reallocarray (p, 0, 1073741824) == NULL); free (p); TEST_PASSED; } @@ -47,7 +47,7 @@ TEST (reallocarray_zero_nmemb) { TEST (reallocarray_zero_size) { int * p = (int *) malloc (sizeof (int)); CHECK (p != NULL); - CHECK (reallocarray (p, 1073741824, 0) == NULL); + CHECK (wrapped_reallocarray (p, 1073741824, 0) == NULL); free (p); TEST_PASSED; } From 464fe4a00f19362c0306916da4aa1f6a49090129 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 13:26:27 +0200 Subject: [PATCH 32/37] testing pipeline on macos --- .github/workflows/build.yaml | 2 + Makefile | 1 - ex/memory_checks.expected | 4 -- ex/memory_checks/tests/08_stdlib_functions.c | 7 +--- ex/memory_checks/tests/08_tmpnum_leak.c | 12 ------ ex/memory_checks_cpp.expected | 4 -- .../tests/08_stdlib_functions.cc | 37 ++----------------- ex/memory_checks_cpp/tests/08_tmpnum_leak.cc | 12 ------ 8 files changed, 7 insertions(+), 72 deletions(-) delete mode 100644 ex/memory_checks/tests/08_tmpnum_leak.c delete mode 100644 ex/memory_checks_cpp/tests/08_tmpnum_leak.cc diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 71ff70f..befd9f6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -27,3 +27,5 @@ jobs: elif [ "${{ matrix.compiler_suite }}" = 'gcc' ]; then make CC=gcc CXX=g++ FAIL_FAST=yes PARALLELISM=4 fi + env: + TERM: xterm diff --git a/Makefile b/Makefile index 31083cd..5d9a055 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,6 @@ all-examples: cp -a basic_testing.h "$$ex"/tests ;\ $(MAKE) -C "$$ex" clean > /dev/null || test_result=FAIL; \ $(MAKE) -C "$$ex" -j $(PARALLELISM) TEST_COLORS=no > "$$ex".out 2>&1 || test_result=FAIL ; \ - cat "$$ex".out ; \ if test -r "$$ex".expected; \ then { IFS=''; while read l; \ do if grep -Fq "$$l" "$$ex".out; \ diff --git a/ex/memory_checks.expected b/ex/memory_checks.expected index 699a355..d3bf71b 100644 --- a/ex/memory_checks.expected +++ b/ex/memory_checks.expected @@ -95,7 +95,3 @@ Running test 08_tmpfile_leak... FAIL run 'tests/08_tmpfile_leak' to see what went wrong run 'tests/08_tmpfile_leak -d' with a debugger -Running test 08_tmpnum_leak... -FAIL -run 'tests/08_tmpnum_leak' to see what went wrong -run 'tests/08_tmpnum_leak -d' with a debugger diff --git a/ex/memory_checks/tests/08_stdlib_functions.c b/ex/memory_checks/tests/08_stdlib_functions.c index 6290018..b717e7a 100644 --- a/ex/memory_checks/tests/08_stdlib_functions.c +++ b/ex/memory_checks/tests/08_stdlib_functions.c @@ -370,10 +370,8 @@ static void read_str (char *buf, const char *format, ...) { va_end (ap); } -TEST (stdio_string_no_leak) { +TEST (stdio_sprintf_scanf_no_leak) { char buf[100]; - char * name = tempnam (NULL, "somefile"); - CHECK (name != NULL); sprintf (buf, "testing %d", 10); int x; sscanf (buf, "testing %d", &x); @@ -381,7 +379,6 @@ TEST (stdio_string_no_leak) { write_str (buf, "testing vsprintf %d", 11); read_str (buf, "testing vsprintf %d", &x); CHECK_CMP (x,==,11); - free (name); TEST_PASSED; } @@ -416,4 +413,4 @@ MAIN_TEST_DRIVER (ctype_no_leaks, bsearch_no_leaks, time_no_leaks, basic_file_operations_no_leak, - stdio_string_no_leak); + stdio_sprintf_scanf_no_leak); diff --git a/ex/memory_checks/tests/08_tmpnum_leak.c b/ex/memory_checks/tests/08_tmpnum_leak.c deleted file mode 100644 index 04c455a..0000000 --- a/ex/memory_checks/tests/08_tmpnum_leak.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "basic_testing.h" -#include - - - -TEST (memory_leak) { - char * name = tempnam (NULL, "somefile"); - CHECK (name != NULL); - TEST_PASSED; -} - -MAIN_TEST_DRIVER (memory_leak); diff --git a/ex/memory_checks_cpp.expected b/ex/memory_checks_cpp.expected index e2f680d..7e163ee 100644 --- a/ex/memory_checks_cpp.expected +++ b/ex/memory_checks_cpp.expected @@ -183,7 +183,3 @@ Running test 08_tmpfile_leak... FAIL run 'tests/08_tmpfile_leak' to see what went wrong run 'tests/08_tmpfile_leak -d' with a debugger -Running test 08_tmpnum_leak... -FAIL -run 'tests/08_tmpnum_leak' to see what went wrong -run 'tests/08_tmpnum_leak -d' with a debugger diff --git a/ex/memory_checks_cpp/tests/08_stdlib_functions.cc b/ex/memory_checks_cpp/tests/08_stdlib_functions.cc index cec41cf..c86f53d 100644 --- a/ex/memory_checks_cpp/tests/08_stdlib_functions.cc +++ b/ex/memory_checks_cpp/tests/08_stdlib_functions.cc @@ -373,10 +373,8 @@ static void read_str (char *buf, const char *format, ...) { va_end (ap); } -TEST (stdio_string_no_leak) { +TEST (stdio_sprintf_scanf_no_leak) { char buf[100]; - char * name = tempnam (NULL, "somefile"); - CHECK (name != NULL); sprintf (buf, "testing %d", 10); int x; sscanf (buf, "testing %d", &x); @@ -384,39 +382,10 @@ TEST (stdio_string_no_leak) { write_str (buf, "testing vsprintf %d", 11); read_str (buf, "testing vsprintf %d", &x); CHECK_CMP (x,==,11); - free (name); TEST_PASSED; } -MAIN_TEST_DRIVER (ctype_no_leaks, - strcpy_no_leaks, - strncpy_no_leaks, - strcat_no_leaks, - strncat_no_leaks, - strcmp_no_leaks, - strncmp_no_leaks, - strchr_no_leaks, - strrchr_no_leaks, - strspn_no_leaks, - strcspn_no_leaks, - strcspn_no_leaks, - strpbrk_no_leaks, - strstr_no_leaks, - strlen_no_leaks, - strerror_no_leaks, - strtok_no_leaks, - memcpy_no_leaks, - memmove_no_leaks, - memcmp_no_leaks, - memchr_no_leaks, - memset_no_leaks, - math_no_leaks, - stdlib_conversion_no_leaks, - rand_no_leaks, - qsort_no_leaks, - bsearch_no_leaks, - time_no_leaks, - basic_file_operations_no_leak, - stdio_string_no_leak); + +MAIN_TEST_DRIVER (); diff --git a/ex/memory_checks_cpp/tests/08_tmpnum_leak.cc b/ex/memory_checks_cpp/tests/08_tmpnum_leak.cc deleted file mode 100644 index 04c455a..0000000 --- a/ex/memory_checks_cpp/tests/08_tmpnum_leak.cc +++ /dev/null @@ -1,12 +0,0 @@ -#include "basic_testing.h" -#include - - - -TEST (memory_leak) { - char * name = tempnam (NULL, "somefile"); - CHECK (name != NULL); - TEST_PASSED; -} - -MAIN_TEST_DRIVER (memory_leak); From 1d8525560b4a14c5fc108b815837b4e0f34a1419 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 13:30:07 +0200 Subject: [PATCH 33/37] testing pipeline --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 5d9a055..31083cd 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ all-examples: cp -a basic_testing.h "$$ex"/tests ;\ $(MAKE) -C "$$ex" clean > /dev/null || test_result=FAIL; \ $(MAKE) -C "$$ex" -j $(PARALLELISM) TEST_COLORS=no > "$$ex".out 2>&1 || test_result=FAIL ; \ + cat "$$ex".out ; \ if test -r "$$ex".expected; \ then { IFS=''; while read l; \ do if grep -Fq "$$l" "$$ex".out; \ From 47bcd6db9e13a0470e86f31f2c322260d5d07b77 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 13:34:19 +0200 Subject: [PATCH 34/37] improve test --- ex/memory_checks/tests/08_stdlib_functions.c | 3 ++- ex/memory_checks_cpp/tests/08_stdlib_functions.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ex/memory_checks/tests/08_stdlib_functions.c b/ex/memory_checks/tests/08_stdlib_functions.c index b717e7a..793c7c7 100644 --- a/ex/memory_checks/tests/08_stdlib_functions.c +++ b/ex/memory_checks/tests/08_stdlib_functions.c @@ -234,7 +234,8 @@ TEST (stdlib_conversion_no_leaks) { TEST (rand_no_leaks) { srand (10); - CHECK_CMP (rand (),==,1215069295); + int num = rand (); + CHECK_CMP (rand (),!=,num); TEST_PASSED; } diff --git a/ex/memory_checks_cpp/tests/08_stdlib_functions.cc b/ex/memory_checks_cpp/tests/08_stdlib_functions.cc index c86f53d..d5c8b43 100644 --- a/ex/memory_checks_cpp/tests/08_stdlib_functions.cc +++ b/ex/memory_checks_cpp/tests/08_stdlib_functions.cc @@ -236,7 +236,8 @@ TEST (stdlib_conversion_no_leaks) { TEST (rand_no_leaks) { srand (10); - CHECK_CMP (rand (),==,1215069295); + int num = rand (); + CHECK_CMP (rand (),!=,num); TEST_PASSED; } From 0c56383ffcdb0bc0a5fe59d11400692a849b98a3 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 14:01:02 +0200 Subject: [PATCH 35/37] extend memory allocation functions on macos --- Makefile | 1 - basic_testing.h | 34 +++++++++++++++++++ .../tests/08_stdlib_functions.cc | 3 +- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 31083cd..5d9a055 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,6 @@ all-examples: cp -a basic_testing.h "$$ex"/tests ;\ $(MAKE) -C "$$ex" clean > /dev/null || test_result=FAIL; \ $(MAKE) -C "$$ex" -j $(PARALLELISM) TEST_COLORS=no > "$$ex".out 2>&1 || test_result=FAIL ; \ - cat "$$ex".out ; \ if test -r "$$ex".expected; \ then { IFS=''; while read l; \ do if grep -Fq "$$l" "$$ex".out; \ diff --git a/basic_testing.h b/basic_testing.h index ab8d988..3d53019 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -862,6 +862,40 @@ void * calloc (size_t nmemb, size_t size) { return p; } +#ifdef __APPLE__ +BT_POSSIBLY_UNUSED +void * valloc (size_t size) { + static void *(*libc_valloc)(size_t) = NULL; + + if (!libc_valloc) + libc_valloc = (void *(*)(size_t)) dlsym(RTLD_NEXT, "valloc"); + + return malloc (size); +} + +BT_POSSIBLY_UNUSED +void * aligned_alloc (size_t aligned, size_t size) { + static void *(*libc_aligned_alloc)(size_t, size_t) = NULL; + + if (!libc_aligned_alloc) + libc_aligned_alloc = (void *(*)(size_t, size_t)) dlsym(RTLD_NEXT, "aligned_alloc"); + + return malloc (size); +} + +BT_POSSIBLY_UNUSED +void * reallocf (void * ptr, size_t size) { + static void *(*libc_reallocf)(void *, size_t) = NULL; + + if (!libc_reallocf) + libc_reallocf = (void *(*)(size_t, size_t)) dlsym(RTLD_NEXT, "reallocf"); + + void * ret = realloc (ptr, size); + if (!ret) free (ptr); + return ret; +} +#endif + #ifndef __APPLE__ BT_POSSIBLY_UNUSED void * reallocarray (void * ptr, size_t nmemb, size_t size) { diff --git a/ex/memory_checks_cpp/tests/08_stdlib_functions.cc b/ex/memory_checks_cpp/tests/08_stdlib_functions.cc index d5c8b43..d930d71 100644 --- a/ex/memory_checks_cpp/tests/08_stdlib_functions.cc +++ b/ex/memory_checks_cpp/tests/08_stdlib_functions.cc @@ -357,6 +357,7 @@ TEST (basic_file_operations_no_leak) { } +#ifndef __APPLE__ static void write_str (char *buf, const char *format, ...) { va_list ap; @@ -385,7 +386,7 @@ TEST (stdio_sprintf_scanf_no_leak) { CHECK_CMP (x,==,11); TEST_PASSED; } - +#endif From 1f8987c6fd8398d7f07da3e5c03604f02368a816 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Wed, 11 Sep 2024 14:19:56 +0200 Subject: [PATCH 36/37] wrap strdup in macos to detect leaks --- basic_testing.h | 10 +++++++++- ex/memory_checks.expected | 8 -------- ex/memory_checks/tests/08_fopen_leak.c | 15 --------------- ex/memory_checks/tests/08_tmpfile_leak.c | 15 --------------- ex/memory_checks_cpp.expected | 8 -------- ex/memory_checks_cpp/tests/08_fopen_leak.cc | 15 --------------- ex/memory_checks_cpp/tests/08_tmpfile_leak.cc | 15 --------------- 7 files changed, 9 insertions(+), 77 deletions(-) delete mode 100644 ex/memory_checks/tests/08_fopen_leak.c delete mode 100644 ex/memory_checks/tests/08_tmpfile_leak.c delete mode 100644 ex/memory_checks_cpp/tests/08_fopen_leak.cc delete mode 100644 ex/memory_checks_cpp/tests/08_tmpfile_leak.cc diff --git a/basic_testing.h b/basic_testing.h index 3d53019..d9b7707 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -888,12 +888,20 @@ void * reallocf (void * ptr, size_t size) { static void *(*libc_reallocf)(void *, size_t) = NULL; if (!libc_reallocf) - libc_reallocf = (void *(*)(size_t, size_t)) dlsym(RTLD_NEXT, "reallocf"); + libc_reallocf = (void *(*)(void *, size_t)) dlsym(RTLD_NEXT, "reallocf"); void * ret = realloc (ptr, size); if (!ret) free (ptr); return ret; } + +BT_POSSIBLY_UNUSED +char * strdup (const char * s) { + size_t len = strlen (s); + char * ret = (char *) malloc (len + 1); + if (ret) strcpy (ret, s); + return ret; +} #endif #ifndef __APPLE__ diff --git a/ex/memory_checks.expected b/ex/memory_checks.expected index d3bf71b..4100ed8 100644 --- a/ex/memory_checks.expected +++ b/ex/memory_checks.expected @@ -81,17 +81,9 @@ Running test 05_byte_budget_allocations_debug... PASS Running test 06_scheduled_failures... PASS Running test 06_scheduled_failures_debug... PASS Running test 07_calloc_reallocarray_failures... PASS -Running test 08_fopen_leak... -FAIL -run 'tests/08_fopen_leak' to see what went wrong -run 'tests/08_fopen_leak -d' with a debugger Running test 08_stdlib_functions... PASS Running test 08_strdup_leak... leaked 8 bytes FAIL run 'tests/08_strdup_leak' to see what went wrong run 'tests/08_strdup_leak -d' with a debugger -Running test 08_tmpfile_leak... -FAIL -run 'tests/08_tmpfile_leak' to see what went wrong -run 'tests/08_tmpfile_leak -d' with a debugger diff --git a/ex/memory_checks/tests/08_fopen_leak.c b/ex/memory_checks/tests/08_fopen_leak.c deleted file mode 100644 index 0bee302..0000000 --- a/ex/memory_checks/tests/08_fopen_leak.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "basic_testing.h" -#include - - - - -TEST (memory_leak) { - FILE * fp = fopen("/tmp/leak_fopen", "w"); - fprintf (fp, "testing\n"); - TEST_PASSED; -} - - - -MAIN_TEST_DRIVER (memory_leak); diff --git a/ex/memory_checks/tests/08_tmpfile_leak.c b/ex/memory_checks/tests/08_tmpfile_leak.c deleted file mode 100644 index c3c2e23..0000000 --- a/ex/memory_checks/tests/08_tmpfile_leak.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "basic_testing.h" -#include - - - -TEST (memory_leak) { - FILE *fp = tmpfile (); - fprintf (fp, "testing\n"); - TEST_PASSED; -} - - - - -MAIN_TEST_DRIVER (memory_leak); diff --git a/ex/memory_checks_cpp.expected b/ex/memory_checks_cpp.expected index 7e163ee..5b25ffa 100644 --- a/ex/memory_checks_cpp.expected +++ b/ex/memory_checks_cpp.expected @@ -169,17 +169,9 @@ Running test 05_byte_budget_allocations_debug... PASS Running test 06_scheduled_failures... PASS Running test 06_scheduled_failures_debug... PASS Running test 07_calloc_reallocarray_failures... PASS -Running test 08_fopen_leak... -FAIL -run 'tests/08_fopen_leak' to see what went wrong -run 'tests/08_fopen_leak -d' with a debugger Running test 08_stdlib_functions... PASS Running test 08_strdup_leak... leaked 8 bytes FAIL run 'tests/08_strdup_leak' to see what went wrong run 'tests/08_strdup_leak -d' with a debugger -Running test 08_tmpfile_leak... -FAIL -run 'tests/08_tmpfile_leak' to see what went wrong -run 'tests/08_tmpfile_leak -d' with a debugger diff --git a/ex/memory_checks_cpp/tests/08_fopen_leak.cc b/ex/memory_checks_cpp/tests/08_fopen_leak.cc deleted file mode 100644 index 0bee302..0000000 --- a/ex/memory_checks_cpp/tests/08_fopen_leak.cc +++ /dev/null @@ -1,15 +0,0 @@ -#include "basic_testing.h" -#include - - - - -TEST (memory_leak) { - FILE * fp = fopen("/tmp/leak_fopen", "w"); - fprintf (fp, "testing\n"); - TEST_PASSED; -} - - - -MAIN_TEST_DRIVER (memory_leak); diff --git a/ex/memory_checks_cpp/tests/08_tmpfile_leak.cc b/ex/memory_checks_cpp/tests/08_tmpfile_leak.cc deleted file mode 100644 index c3c2e23..0000000 --- a/ex/memory_checks_cpp/tests/08_tmpfile_leak.cc +++ /dev/null @@ -1,15 +0,0 @@ -#include "basic_testing.h" -#include - - - -TEST (memory_leak) { - FILE *fp = tmpfile (); - fprintf (fp, "testing\n"); - TEST_PASSED; -} - - - - -MAIN_TEST_DRIVER (memory_leak); From 4dd8361a280e8cade4c6ee415040cd4a9e221617 Mon Sep 17 00:00:00 2001 From: pako-23 Date: Sun, 15 Sep 2024 11:50:51 +0200 Subject: [PATCH 37/37] Add set and change functions for memory budgets --- basic_testing.h | 37 ++- .../tests/04_budget_allocations.c | 89 +++++- .../tests/05_byte_budget_allocations.c | 83 +++++- .../tests/04_budget_allocations.cc | 217 +++++++++++++-- .../tests/05_byte_budget_allocations.cc | 253 ++++++++++++++---- 5 files changed, 596 insertions(+), 83 deletions(-) diff --git a/basic_testing.h b/basic_testing.h index d9b7707..baf1aa6 100644 --- a/basic_testing.h +++ b/basic_testing.h @@ -381,7 +381,8 @@ static void bt_mem_fail_all (void) { exceeded, any allocation function will fail. A call to `free' will count as -1. */ -void bt_mem_set_allocation_budget (size_t budget) { +BT_POSSIBLY_UNUSED +static void bt_mem_change_allocation_budget (size_t budget) { if (!bt_mem_budget_enabled) bt_mem_budget_curr = budget; else if (bt_mem_budget == budget) @@ -397,6 +398,20 @@ void bt_mem_set_allocation_budget (size_t budget) { bt_mem_budget = budget; } +BT_POSSIBLY_UNUSED +static void bt_mem_set_allocation_budget (size_t budget) { + bt_mem_budget_enabled = 0; + bt_mem_change_allocation_budget (budget); +} + +#define MEM_CHANGE_ALLOCATION_BUDGET(B) do { \ + if (bt_mem_checks_disabled) { \ + TEST_SKIPPED; \ + } else { \ + bt_mem_change_allocation_budget (B); \ + } \ +} while (0) + #define MEM_SET_ALLOCATION_BUDGET(B) do { \ if (bt_mem_checks_disabled) { \ TEST_SKIPPED; \ @@ -410,7 +425,8 @@ void bt_mem_set_allocation_budget (size_t budget) { Calling `free(p)' will discount the amount of memory previously allocated with pointer `p'. */ -void bt_mem_set_bytes_budget (size_t budget) { +BT_POSSIBLY_UNUSED +static void bt_mem_change_bytes_budget (size_t budget) { if (!bt_mem_bytes_budget_enabled) bt_mem_bytes_budget_curr = budget; else if (bt_mem_bytes_budget == budget) @@ -427,6 +443,12 @@ void bt_mem_set_bytes_budget (size_t budget) { bt_mem_bytes_budget = budget; } +BT_POSSIBLY_UNUSED +static void bt_mem_set_bytes_budget (size_t budget) { + bt_mem_bytes_budget_enabled = 0; + bt_mem_change_bytes_budget (budget); +} + #define MEM_SET_BYTES_BUDGET(B) do { \ if (bt_mem_checks_disabled) { \ TEST_SKIPPED; \ @@ -435,11 +457,20 @@ void bt_mem_set_bytes_budget (size_t budget) { } \ } while (0) +#define MEM_CHANGE_BYTES_BUDGET(B) do { \ + if (bt_mem_checks_disabled) { \ + TEST_SKIPPED; \ + } else { \ + bt_mem_change_bytes_budget (B); \ + } \ +} while (0) + /* Completely reset the instrumentation of the memory allocation functions. Failures are reset, and invocations and bytes budgets are also canceled. */ -void bt_mem_reset_allocator (void) { +BT_POSSIBLY_UNUSED +static void bt_mem_reset_allocator (void) { bt_mem_table_failed = 0; bt_mem_bytes_budget_enabled = 0; bt_mem_budget_enabled = 0; diff --git a/ex/memory_checks/tests/04_budget_allocations.c b/ex/memory_checks/tests/04_budget_allocations.c index ca5952e..07ed9bf 100644 --- a/ex/memory_checks/tests/04_budget_allocations.c +++ b/ex/memory_checks/tests/04_budget_allocations.c @@ -202,13 +202,13 @@ TEST (realloc_budget_reset) { } -TEST (set_same_budget) { +TEST (change_same_budget) { MEM_SET_ALLOCATION_BUDGET (1); struct array * array = array_new (); CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); - MEM_SET_ALLOCATION_BUDGET (1); + MEM_CHANGE_ALLOCATION_BUDGET (1); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); array_free (array); @@ -216,19 +216,19 @@ TEST (set_same_budget) { } -TEST (set_higher_budget) { +TEST (change_higher_budget) { MEM_SET_ALLOCATION_BUDGET (1); struct array * array = array_new (); CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); - MEM_SET_ALLOCATION_BUDGET (2); + MEM_CHANGE_ALLOCATION_BUDGET (2); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); array_free (array); - MEM_SET_ALLOCATION_BUDGET (3); + MEM_CHANGE_ALLOCATION_BUDGET (3); array = array_new (); CHECK (array != NULL); for (int i = 0; i < 16; ++i) @@ -238,14 +238,14 @@ TEST (set_higher_budget) { } -TEST (set_lower_budget) { +TEST (change_lower_budget) { MEM_SET_ALLOCATION_BUDGET (4); struct array * array = array_new (); - MEM_SET_ALLOCATION_BUDGET (2); + MEM_CHANGE_ALLOCATION_BUDGET (2); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); CHECK (!array_append (array, 9)); - MEM_SET_ALLOCATION_BUDGET (1); + MEM_CHANGE_ALLOCATION_BUDGET (1); for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); array_free (array); @@ -258,18 +258,83 @@ TEST (set_lower_budget) { } -TEST (set_lower_budget_after_allocations) { +TEST (change_lower_budget_after_allocations) { MEM_SET_ALLOCATION_BUDGET (3); struct array * array = array_new (); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); - MEM_SET_ALLOCATION_BUDGET (2); + MEM_CHANGE_ALLOCATION_BUDGET (2); CHECK (!array_append (array, 17)); array_free (array); TEST_PASSED; } +TEST (set_same_budget) { + MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + MEM_SET_ALLOCATION_BUDGET (1); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (set_higher_budget) { + MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + MEM_SET_ALLOCATION_BUDGET (2); + for (int i = 0; i < 16; ++i) + CHECK (array_append (array, i)); + array_free (array); + MEM_SET_ALLOCATION_BUDGET (3); + array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 16; ++i) + CHECK (array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (set_lower_budget) { + MEM_SET_ALLOCATION_BUDGET (4); + struct array * array = array_new (); + MEM_SET_ALLOCATION_BUDGET (1); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + CHECK (!array_append (array, 9)); + array_free (array); + array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (set_lower_budget_after_allocations) { + MEM_SET_ALLOCATION_BUDGET (3); + struct array * array = array_new (); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + MEM_SET_ALLOCATION_BUDGET (1); + for (int i = 8; i < 16; ++i) + CHECK (array_append (array, i)); + CHECK (!array_append (array, 16)); + array_free (array); + TEST_PASSED; +} + + TEST (zero_budget_calloc) { MEM_SET_ALLOCATION_BUDGET (0); struct array * array = array_new_calloc (); @@ -328,6 +393,10 @@ MAIN_TEST_DRIVER (compile, set_higher_budget, set_lower_budget, set_lower_budget_after_allocations, + change_same_budget, + change_higher_budget, + change_lower_budget, + change_lower_budget_after_allocations, zero_budget_calloc, simple_budget_calloc, reallocarray_budget); diff --git a/ex/memory_checks/tests/05_byte_budget_allocations.c b/ex/memory_checks/tests/05_byte_budget_allocations.c index 7ac2370..c3d09bc 100644 --- a/ex/memory_checks/tests/05_byte_budget_allocations.c +++ b/ex/memory_checks/tests/05_byte_budget_allocations.c @@ -205,16 +205,84 @@ TEST (realloc_budget_reset) { } -TEST (set_same_budget) { +TEST (change_same_budget) { MEM_SET_BYTES_BUDGET (sizeof(struct array)); struct array * array = array_new (); CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array)); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (change_higher_budget) { MEM_SET_BYTES_BUDGET (sizeof(struct array)); + struct array * array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); array_free (array); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array) + 16*sizeof(int)); + array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 16; ++i) + CHECK (array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (change_lower_budget) { + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 32*sizeof(int)); + struct array * array = array_new (); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + CHECK (!array_append (array, 9)); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array)); + for (int i = 8; i < 16; ++i) + CHECK (!array_append (array, i)); + array_free (array); + array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (change_lower_budget_after_allocations) { + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 16*sizeof(int)); + struct array * array = array_new (); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); + CHECK (!array_append (array, 17)); + array_free (array); + TEST_PASSED; +} + + +TEST (set_same_budget) { + MEM_SET_BYTES_BUDGET (sizeof(struct array)); + struct array * array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + MEM_SET_BYTES_BUDGET (sizeof(int)*8); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + array_free (array); TEST_PASSED; } @@ -225,7 +293,7 @@ TEST (set_higher_budget) { CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); - MEM_SET_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); + MEM_SET_BYTES_BUDGET (8*sizeof(int)); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); for (int i = 8; i < 16; ++i) @@ -264,9 +332,14 @@ TEST (set_lower_budget) { TEST (set_lower_budget_after_allocations) { MEM_SET_BYTES_BUDGET (sizeof(struct array) + 16*sizeof(int)); struct array * array = array_new (); + CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); - MEM_SET_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); + MEM_SET_BYTES_BUDGET (sizeof(struct array)); + CHECK (!array_append (array, 17)); + array_free (array); + array = array_new (); + CHECK (array != NULL); CHECK (!array_append (array, 17)); array_free (array); TEST_PASSED; @@ -342,6 +415,10 @@ MAIN_TEST_DRIVER (compile, malloc_budget_reset, realloc_null_budget_reset, realloc_budget_reset, + change_same_budget, + change_higher_budget, + change_lower_budget, + change_lower_budget_after_allocations, set_same_budget, set_higher_budget, set_lower_budget, diff --git a/ex/memory_checks_cpp/tests/04_budget_allocations.cc b/ex/memory_checks_cpp/tests/04_budget_allocations.cc index 29555d2..51d8218 100644 --- a/ex/memory_checks_cpp/tests/04_budget_allocations.cc +++ b/ex/memory_checks_cpp/tests/04_budget_allocations.cc @@ -203,15 +203,83 @@ TEST (realloc_budget_reset) { } -TEST (set_same_budget_malloc) { +TEST (change_same_budget_malloc) { MEM_SET_ALLOCATION_BUDGET (1); struct array * array = array_new (); CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); + MEM_CHANGE_ALLOCATION_BUDGET (1); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (change_higher_budget_malloc) { + MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + MEM_CHANGE_ALLOCATION_BUDGET (2); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + for (int i = 8; i < 16; ++i) + CHECK (!array_append (array, i)); + array_free (array); + MEM_CHANGE_ALLOCATION_BUDGET (3); + array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 16; ++i) + CHECK (array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (change_lower_budget_malloc) { + MEM_SET_ALLOCATION_BUDGET (4); + struct array * array = array_new (); + MEM_CHANGE_ALLOCATION_BUDGET (2); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + CHECK (!array_append (array, 9)); + MEM_CHANGE_ALLOCATION_BUDGET (1); + for (int i = 8; i < 16; ++i) + CHECK (!array_append (array, i)); + array_free (array); + array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (change_lower_budget_after_allocations_malloc) { + MEM_SET_ALLOCATION_BUDGET (3); + struct array * array = array_new (); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + MEM_CHANGE_ALLOCATION_BUDGET (2); + CHECK (!array_append (array, 17)); + array_free (array); + TEST_PASSED; +} + + +TEST (set_same_budget) { MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new (); + CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); + MEM_SET_ALLOCATION_BUDGET (1); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); array_free (array); TEST_PASSED; } @@ -227,7 +295,7 @@ TEST (set_higher_budget_malloc) { for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); for (int i = 8; i < 16; ++i) - CHECK (!array_append (array, i)); + CHECK (array_append (array, i)); array_free (array); MEM_SET_ALLOCATION_BUDGET (3); array = array_new (); @@ -242,13 +310,10 @@ TEST (set_higher_budget_malloc) { TEST (set_lower_budget_malloc) { MEM_SET_ALLOCATION_BUDGET (4); struct array * array = array_new (); - MEM_SET_ALLOCATION_BUDGET (2); + MEM_SET_ALLOCATION_BUDGET (1); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); CHECK (!array_append (array, 9)); - MEM_SET_ALLOCATION_BUDGET (1); - for (int i = 8; i < 16; ++i) - CHECK (!array_append (array, i)); array_free (array); array = array_new (); CHECK (array != NULL); @@ -264,8 +329,10 @@ TEST (set_lower_budget_after_allocations_malloc) { struct array * array = array_new (); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); - MEM_SET_ALLOCATION_BUDGET (2); - CHECK (!array_append (array, 17)); + MEM_SET_ALLOCATION_BUDGET (1); + for (int i = 8; i < 16; ++i) + CHECK (array_append (array, i)); + CHECK (!array_append (array, 16)); array_free (array); TEST_PASSED; } @@ -431,7 +498,7 @@ TEST (reset_budget_new_array) { } -TEST (set_same_budget_new) { +TEST (change_same_budget_new) { MEM_SET_ALLOCATION_BUDGET (1); array_cpp * array = array_cpp_new (); CHECK (array != nullptr); @@ -439,7 +506,7 @@ TEST (set_same_budget_new) { array_cpp * array2 = array_cpp_new (); array_cpp_delete (array2); } catch (const std::bad_alloc& e) { - MEM_SET_ALLOCATION_BUDGET (1); + MEM_CHANGE_ALLOCATION_BUDGET (1); try { array_cpp * array2 = array_cpp_new (); array_cpp_delete (array2); @@ -454,7 +521,7 @@ TEST (set_same_budget_new) { } -TEST (set_same_budget_new_array) { +TEST (change_same_budget_new_array) { MEM_SET_ALLOCATION_BUDGET (1); array_cpp array; for (int i = 0; i < 8; ++i) @@ -462,7 +529,7 @@ TEST (set_same_budget_new_array) { try { array.append (9); } catch (const std::bad_alloc& e) { - MEM_SET_ALLOCATION_BUDGET (1); + MEM_CHANGE_ALLOCATION_BUDGET (1); try { array.append (9); } catch (const std::bad_alloc& e) { @@ -474,7 +541,7 @@ TEST (set_same_budget_new_array) { } -TEST (set_higher_budget_new) { +TEST (change_higher_budget_new) { MEM_SET_ALLOCATION_BUDGET (1); array_cpp * array = array_cpp_new (); CHECK (array != nullptr); @@ -482,7 +549,7 @@ TEST (set_higher_budget_new) { for (int i = 0; i < 8; ++i) array->append (i); } catch (const std::bad_alloc& e) { - MEM_SET_ALLOCATION_BUDGET (2); + MEM_CHANGE_ALLOCATION_BUDGET (2); for (int i = 0; i < 8; ++i) array->append (i); try { @@ -490,7 +557,7 @@ TEST (set_higher_budget_new) { array->append (i); } catch (const std::bad_alloc& e) { array_cpp_delete (array); - MEM_SET_ALLOCATION_BUDGET (3); + MEM_CHANGE_ALLOCATION_BUDGET (3); array = array_cpp_new (); CHECK (array != nullptr); for (int i = 0; i < 16; ++i) @@ -504,16 +571,16 @@ TEST (set_higher_budget_new) { } -TEST (set_lower_budget_new) { +TEST (change_lower_budget_new) { MEM_SET_ALLOCATION_BUDGET (4); array_cpp * array = array_cpp_new (); - MEM_SET_ALLOCATION_BUDGET (2); + MEM_CHANGE_ALLOCATION_BUDGET (2); for (int i = 0; i < 8; ++i) array->append (i); try { array->append (9); } catch (const std::bad_alloc& e) { - MEM_SET_ALLOCATION_BUDGET (1); + MEM_CHANGE_ALLOCATION_BUDGET (1); try { for (int i = 8; i < 16; ++i) @@ -538,13 +605,13 @@ TEST (set_lower_budget_new) { } -TEST (set_lower_budget_after_allocations_new) { +TEST (change_lower_budget_after_allocations_new) { MEM_SET_ALLOCATION_BUDGET (3); array_cpp * array = array_cpp_new (); CHECK (array != nullptr); for (int i = 0; i < 8; ++i) array->append (i); - MEM_SET_ALLOCATION_BUDGET (2); + MEM_CHANGE_ALLOCATION_BUDGET (2); try { array->append (17); @@ -557,6 +624,116 @@ TEST (set_lower_budget_after_allocations_new) { } +TEST (set_same_budget_new) { + MEM_SET_ALLOCATION_BUDGET (1); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + try { + array_cpp * array2 = array_cpp_new (); + array_cpp_delete (array2); + } catch (const std::bad_alloc& e) { + MEM_SET_ALLOCATION_BUDGET (1); + array_cpp * array2 = array_cpp_new (); + array_cpp_delete (array2); + array_cpp_delete (array); + TEST_PASSED; + } + + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_same_budget_new_array) { + MEM_SET_ALLOCATION_BUDGET (1); + array_cpp array; + for (int i = 0; i < 8; ++i) + array.append (i); + try { + array.append (9); + } catch (const std::bad_alloc& e) { + MEM_SET_ALLOCATION_BUDGET (1); + array.append (9); + TEST_PASSED; + } + + TEST_FAILED; +} + + +TEST (set_higher_budget_new) { + MEM_SET_ALLOCATION_BUDGET (1); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + try { + for (int i = 0; i < 8; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + MEM_SET_ALLOCATION_BUDGET (2); + for (int i = 0; i < 16; ++i) + array->append (i); + + array_cpp_delete (array); + MEM_SET_ALLOCATION_BUDGET (3); + array = array_cpp_new (); + CHECK (array != nullptr); + for (int i = 0; i < 16; ++i) + array->append (i); + array_cpp_delete (array); + TEST_PASSED; + } + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_lower_budget_new) { + MEM_SET_ALLOCATION_BUDGET (4); + array_cpp * array = array_cpp_new (); + MEM_SET_ALLOCATION_BUDGET (1); + for (int i = 0; i < 8; ++i) + array->append (i); + try { + array->append (9); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + array = array_cpp_new (); + CHECK (array != nullptr); + + try { + for (int i = 0; i < 8; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + TEST_PASSED; + } + } + + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_lower_budget_after_allocations_new) { + MEM_SET_ALLOCATION_BUDGET (2); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + for (int i = 0; i < 8; ++i) + array->append (i); + try { + array->append (16); + } catch(const std::bad_alloc& e) { + MEM_SET_ALLOCATION_BUDGET (1); + for (int i = 8; i < 16; ++i) + array->append (i); + array_cpp_delete (array); + TEST_PASSED; + } + array_cpp_delete (array); + TEST_FAILED; +} + + MAIN_TEST_DRIVER (); diff --git a/ex/memory_checks_cpp/tests/05_byte_budget_allocations.cc b/ex/memory_checks_cpp/tests/05_byte_budget_allocations.cc index a43321c..6803e63 100644 --- a/ex/memory_checks_cpp/tests/05_byte_budget_allocations.cc +++ b/ex/memory_checks_cpp/tests/05_byte_budget_allocations.cc @@ -205,27 +205,95 @@ TEST (realloc_budget_reset) { } -TEST (set_same_budget) { +TEST (change_same_budget_malloc) { MEM_SET_BYTES_BUDGET (sizeof(struct array)); struct array * array = array_new (); CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array)); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (change_higher_budget_malloc) { MEM_SET_BYTES_BUDGET (sizeof(struct array)); + struct array * array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + for (int i = 8; i < 16; ++i) CHECK (!array_append (array, i)); array_free (array); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array) + 16*sizeof(int)); + array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 16; ++i) + CHECK (array_append (array, i)); + array_free (array); TEST_PASSED; } -TEST (set_higher_budget) { +TEST (change_lower_budget_malloc) { + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 32*sizeof(int)); + struct array * array = array_new (); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + CHECK (!array_append (array, 9)); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array)); + for (int i = 8; i < 16; ++i) + CHECK (!array_append (array, i)); + array_free (array); + array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (change_lower_budget_after_allocations_malloc) { + MEM_SET_BYTES_BUDGET (sizeof(struct array) + 16*sizeof(int)); + struct array * array = array_new (); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + MEM_CHANGE_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); + CHECK (!array_append (array, 17)); + array_free (array); + TEST_PASSED; +} + + +TEST (set_same_budget_malloc) { MEM_SET_BYTES_BUDGET (sizeof(struct array)); struct array * array = array_new (); CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (!array_append (array, i)); - MEM_SET_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); + MEM_SET_BYTES_BUDGET (sizeof(int)*8); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + array_free (array); + TEST_PASSED; +} + + +TEST (set_higher_budget_malloc) { + MEM_SET_BYTES_BUDGET (sizeof(struct array)); + struct array * array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (!array_append (array, i)); + MEM_SET_BYTES_BUDGET (8*sizeof(int)); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); for (int i = 8; i < 16; ++i) @@ -241,7 +309,7 @@ TEST (set_higher_budget) { } -TEST (set_lower_budget) { +TEST (set_lower_budget_malloc) { MEM_SET_BYTES_BUDGET (sizeof(struct array) + 32*sizeof(int)); struct array * array = array_new (); MEM_SET_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); @@ -261,12 +329,17 @@ TEST (set_lower_budget) { } -TEST (set_lower_budget_after_allocations) { +TEST (set_lower_budget_after_allocations_malloc) { MEM_SET_BYTES_BUDGET (sizeof(struct array) + 16*sizeof(int)); struct array * array = array_new (); + CHECK (array != NULL); for (int i = 0; i < 8; ++i) CHECK (array_append (array, i)); - MEM_SET_BYTES_BUDGET (sizeof(struct array) + 8*sizeof(int)); + MEM_SET_BYTES_BUDGET (sizeof(struct array)); + CHECK (!array_append (array, 17)); + array_free (array); + array = array_new (); + CHECK (array != NULL); CHECK (!array_append (array, 17)); array_free (array); TEST_PASSED; @@ -328,35 +401,6 @@ TEST (reallocarray_budget) { } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST (zero_budget_new) { MEM_SET_BYTES_BUDGET (0); try { @@ -477,7 +521,7 @@ TEST (reset_budget_new_array) { } -TEST (set_same_budget_new) { +TEST (change_same_budget_new) { MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); array_cpp * array = array_cpp_new (); CHECK (array != nullptr); @@ -485,7 +529,7 @@ TEST (set_same_budget_new) { array_cpp * array2 = array_cpp_new (); array_cpp_delete (array2); } catch (const std::bad_alloc& e) { - MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); + MEM_CHANGE_BYTES_BUDGET (sizeof(array_cpp)); try { array_cpp * array2 = array_cpp_new (); array_cpp_delete (array2); @@ -500,7 +544,7 @@ TEST (set_same_budget_new) { } -TEST (set_same_budget_new_array) { +TEST (change_same_budget_new_array) { MEM_SET_BYTES_BUDGET (array_cpp::initial_cap*sizeof(int)); array_cpp array; for (int i = 0; i < 8; ++i) @@ -508,7 +552,7 @@ TEST (set_same_budget_new_array) { try { array.append (9); } catch (const std::bad_alloc& e) { - MEM_SET_BYTES_BUDGET (array_cpp::initial_cap*sizeof(int)); + MEM_CHANGE_BYTES_BUDGET (array_cpp::initial_cap*sizeof(int)); try { array.append (9); } catch (const std::bad_alloc& e) { @@ -520,7 +564,7 @@ TEST (set_same_budget_new_array) { } -TEST (set_higher_budget_new) { +TEST (change_higher_budget_new) { MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); array_cpp * array = array_cpp_new (); CHECK (array != nullptr); @@ -528,7 +572,7 @@ TEST (set_higher_budget_new) { for (int i = 0; i < 8; ++i) array->append (i); } catch (const std::bad_alloc& e) { - MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + array_cpp::initial_cap*sizeof(int)); + MEM_CHANGE_BYTES_BUDGET (sizeof(array_cpp) + array_cpp::initial_cap*sizeof(int)); for (int i = 0; i < 8; ++i) array->append (i); try { @@ -536,7 +580,7 @@ TEST (set_higher_budget_new) { array->append (i); } catch (const std::bad_alloc& e) { array_cpp_delete (array); - MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + array_cpp::initial_cap*3*sizeof(int)); + MEM_CHANGE_BYTES_BUDGET (sizeof(array_cpp) + array_cpp::initial_cap*3*sizeof(int)); array = array_cpp_new (); CHECK (array != nullptr); for (int i = 0; i < 16; ++i) @@ -550,17 +594,17 @@ TEST (set_higher_budget_new) { } -TEST (set_lower_budget_new) { +TEST (change_lower_budget_new) { MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + 100*sizeof(int)); array_cpp * array = array_cpp_new (); - MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + 8*sizeof(int)); + MEM_CHANGE_BYTES_BUDGET (sizeof(array_cpp) + 8*sizeof(int)); for (int i = 0; i < 8; ++i) array->append (i); try { array->append (9); } catch (const std::bad_alloc& e) { - MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); + MEM_CHANGE_BYTES_BUDGET (sizeof(array_cpp)); try { for (int i = 8; i < 16; ++i) @@ -585,13 +629,13 @@ TEST (set_lower_budget_new) { } -TEST (set_lower_budget_after_allocations_new) { +TEST (change_lower_budget_after_allocations_new) { MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + 16*sizeof(int)); array_cpp * array = array_cpp_new (); CHECK (array != nullptr); for (int i = 0; i < 8; ++i) array->append (i); - MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + 8*sizeof(int)); + MEM_CHANGE_BYTES_BUDGET (sizeof(array_cpp) + 8*sizeof(int)); try { array->append (17); } catch(const std::bad_alloc& e) { @@ -603,6 +647,121 @@ TEST (set_lower_budget_after_allocations_new) { } +TEST (set_same_budget_new) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + try { + array_cpp * array2 = array_cpp_new (); + array_cpp_delete (array2); + } catch (const std::bad_alloc& e) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); + array_cpp * array2 = array_cpp_new (); + array_cpp_delete (array2); + array_cpp_delete (array); + TEST_PASSED; + } + + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_same_budget_new_array) { + MEM_SET_BYTES_BUDGET (array_cpp::initial_cap*sizeof(int)); + array_cpp array; + for (int i = 0; i < 8; ++i) + array.append (i); + try { + array.append (9); + } catch (const std::bad_alloc& e) { + MEM_SET_BYTES_BUDGET (array_cpp::initial_cap*sizeof(int)); + array_cpp array2; + for (int i = 0; i < 8; ++i) + array2.append (i); + try { + array2.append (9); + } catch (const std::bad_alloc& e) { + TEST_PASSED; + } + } + + TEST_FAILED; +} + + +TEST (set_higher_budget_new) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp)); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + try { + for (int i = 0; i < 8; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + MEM_SET_BYTES_BUDGET (3*array_cpp::initial_cap*sizeof(int)); + for (int i = 0; i < 16; ++i) + array->append (i); + + array_cpp_delete (array); + MEM_SET_BYTES_BUDGET (3*array_cpp::initial_cap*sizeof(int)+sizeof(array_cpp)); + array = array_cpp_new (); + CHECK (array != nullptr); + for (int i = 0; i < 16; ++i) + array->append (i); + array_cpp_delete (array); + TEST_PASSED; + } + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_lower_budget_new) { + MEM_SET_BYTES_BUDGET (4*array_cpp::initial_cap*sizeof(int)+sizeof(array_cpp)); + array_cpp * array = array_cpp_new (); + MEM_SET_BYTES_BUDGET (array_cpp::initial_cap*sizeof(int)); + for (int i = 0; i < 8; ++i) + array->append (i); + try { + array->append (9); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + array = array_cpp_new (); + CHECK (array != nullptr); + + try { + for (int i = 0; i < 8; ++i) + array->append (i); + } catch (const std::bad_alloc& e) { + array_cpp_delete (array); + TEST_PASSED; + } + } + + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (set_lower_budget_after_allocations_new) { + MEM_SET_BYTES_BUDGET (array_cpp::initial_cap*sizeof(int)+sizeof(array_cpp)); + array_cpp * array = array_cpp_new (); + CHECK (array != nullptr); + for (int i = 0; i < 8; ++i) + array->append (i); + try { + array->append (16); + } catch(const std::bad_alloc& e) { + MEM_SET_BYTES_BUDGET (2*array_cpp::initial_cap*sizeof(int)); + for (int i = 8; i < 16; ++i) + array->append (i); + array_cpp_delete (array); + TEST_PASSED; + } + array_cpp_delete (array); + TEST_FAILED; +} + MAIN_TEST_DRIVER ();