diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..befd9f6 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,31 @@ +--- +name: CI Pipeline + + +on: + push: + branches: [master] + pull_request: + workflow_dispatch: + +jobs: + test: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [macos-13, 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 }}" = '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 + env: + TERM: xterm 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/AUTHORS b/AUTHORS new file mode 100644 index 0000000..4c29da9 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Antonio Carzaniga +Pasquale Polverino diff --git a/Makefile b/Makefile index 8766da8..5d9a055 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/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' +PARALLELISM ?= 1 .PHONY: all-examples all-examples: @@ -12,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" TEST_COLORS=no > "$$ex".out 2>&1 || 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; \ @@ -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/basic_testing.h b/basic_testing.h index ded9a7f..baf1aa6 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 @@ -27,9 +28,14 @@ #include #include #include +#include +#include +#include +#include #ifdef __cplusplus #include +#include #endif #include @@ -116,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; \ @@ -192,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; @@ -254,7 +263,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 () { @@ -368,12 +381,37 @@ 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) + 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; } +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; \ @@ -387,10 +425,28 @@ 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) + 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; +} + +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 { \ @@ -401,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; @@ -420,23 +485,21 @@ 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 -} +enum bt_allocator { + MALLOC, + NEW, + NEW_ARRAY, +}; #endif struct bt_mem_node { void * address; size_t size; +#ifdef __cplusplus + enum bt_allocator allocator; +#endif int deleted; }; @@ -447,10 +510,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 +562,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; @@ -511,34 +584,35 @@ 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) __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 @@ -569,15 +643,39 @@ 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" { #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); @@ -589,7 +687,7 @@ void *__wrap_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 { @@ -603,7 +701,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 +709,78 @@ 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) { +#ifdef __cplusplus + node->allocator = bt_allocator::MALLOC; +#endif + node->size = size; + } else bt_mem_table_failed = 1; - } + return ret; } + + + +#ifdef __cplusplus BT_POSSIBLY_UNUSED -void __wrap_free (void * ptr) { +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) { - __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/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; + + 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, or possible double free\n", stderr); @@ -638,20 +796,26 @@ 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); } +#endif 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 +841,19 @@ 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 (bt_mem_bytes_budget_enabled && bt_mem_bytes_budget_curr + node->size < new_size) + } +#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(); + } +#endif + 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 +863,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,29 +875,298 @@ void *__wrap_realloc (void * ptr, size_t new_size) { return ret; } -void * __wrap_calloc (size_t nmemb, size_t size) { +BT_POSSIBLY_UNUSED +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) { +#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 *(*)(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__ +BT_POSSIBLY_UNUSED +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); +} +#endif + +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; + + 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; +} + +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"); + + 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; + + return result; +} + +BT_POSSIBLY_UNUSED +int puts (const char * s) { + static int (*libc_puts)(const char *) = NULL; + + if (!libc_puts) + libc_puts = (int (*)(const char *)) dlsym(RTLD_NEXT, "puts"); + + 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; + + return result; +} + +BT_POSSIBLY_UNUSED +char * strerror (int errnum) { + static char *(*libc_strerror)(int) = NULL; + + if (!libc_strerror) + libc_strerror = (char *(*)(int)) dlsym(RTLD_NEXT, "strerror"); + + int prev_bt_mem_checks_disabled = bt_mem_checks_disabled; + bt_mem_checks_disabled = 1; + char * result = libc_strerror (errnum); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + + return result; +} + +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; + time_t result = libc_mktime (tp); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + + return result; +} + +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; + struct tm * result = libc_gmtime (tp); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + + return result; +} + +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; + struct tm * result = libc_localtime (tp); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + + return result; +} + +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; + char * result = libc_asctime (tp); + bt_mem_checks_disabled = prev_bt_mem_checks_disabled; + + return result; } +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; + 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 @@ -771,20 +1215,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; @@ -806,19 +1237,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. */ @@ -972,11 +1390,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/basic_testing.mk b/basic_testing.mk index 41829fd..2a06b2d 100644 --- a/basic_testing.mk +++ b/basic_testing.mk @@ -3,8 +3,8 @@ # and/or # PROGRAMS= -CFLAGS=-Wall -Werror -g $(COVERAGE_FLAGS) -CXXFLAGS=-Wall -Werror -g $(COVERAGE_FLAGS) +CFLAGS=-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 @@ -184,13 +184,10 @@ 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 - -$(TESTS_DIR)/%: $(TESTS_DIR)/%.c $(OBJECTS) - $(CC) $(CFLAGS) $(LDFLAGS) $(BT_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 $@ +# we must assume there are some C++ sources, so we must link with $(CXX) +# +$(TESTS_DIR)/%: $(TESTS_DIR)/%.o $(OBJECTS) + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.o $(OBJECTS) -o $@ .PHONY: check-bin check-bin: $(TESTS_BIN) 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 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/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/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; } diff --git a/ex/memory_checks.expected b/ex/memory_checks.expected index c16b63a..4100ed8 100644 --- a/ex/memory_checks.expected +++ b/ex/memory_checks.expected @@ -1,68 +1,89 @@ 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_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_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 +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 in memory_leak +Running test 03_memory_leaks_debug... +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 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 -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... +Running test 03_non_malloc_free... +memory was not allocated via malloc, or possible double free +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_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_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 diff --git a/ex/memory_checks/array.c b/ex/memory_checks/array.c index 27172ba..62a8a74 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,11 +56,11 @@ 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; - int * new_data = reallocarray(array->data, new_cap, sizeof(int)); + int * new_data = wrapped_reallocarray (array->data, new_cap, sizeof(int)); if (!new_data) return 0; array->data = new_data; @@ -72,3 +70,36 @@ int array_append_reallocarray(struct array * array, int element) { array->data[array->len++] = 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); + if (a < 20) free (p); + free (p); +} + +void non_malloc_free (void) { + int a = 10; + int * p = NULL; + 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..f801aba 100644 --- a/ex/memory_checks/array.h +++ b/ex/memory_checks/array.h @@ -19,4 +19,10 @@ 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); +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 ace9312..59ee7d0 100644 --- a/ex/memory_checks/tests/00_hash_map.c +++ b/ex/memory_checks/tests/00_hash_map.c @@ -26,7 +26,9 @@ 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; struct bt_mem_node * node = bt_mem_table_find (&i); CHECK (node != NULL); @@ -45,7 +47,10 @@ 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; + struct bt_mem_node * node = bt_mem_table_find (&i); CHECK (node != NULL); CHECK_CMP (node->size,==,12); @@ -54,8 +59,8 @@ 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->size = 15; CHECK (node != NULL); CHECK_CMP (node->size,==,15); CHECK (&i == node->address); @@ -77,8 +82,11 @@ 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->size = items[i]; + } for (size_t i = 0; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); @@ -104,8 +112,11 @@ 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->size = items[i]; + } for (size_t i = 0; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); @@ -119,9 +130,12 @@ 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->size = items[i]; + } for (size_t i = 0; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); @@ -132,7 +146,6 @@ TEST (map_update_collisions) { 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 +158,11 @@ 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; + } bt_mem_table_free (); @@ -160,7 +176,9 @@ 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; CHECK (bt_mem_table_remove (&x)); CHECK (bt_mem_table_find (&x) == NULL); bt_mem_table_free (); @@ -182,8 +200,11 @@ 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; + } CHECK (bt_mem_table_size == len); CHECK (bt_mem_table_size <= bt_mem_table_capacity); @@ -207,8 +228,11 @@ 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; + } CHECK (!bt_mem_table_remove (&x)); @@ -224,8 +248,11 @@ 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]; + } for (size_t i = 0; i < len/2; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); @@ -243,8 +270,11 @@ 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]; + } for (size_t i = len/2; i < len; ++i) { const struct bt_mem_node * node = bt_mem_table_find (items + i); @@ -269,15 +299,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_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 0e00b20..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..07ed9bf 100644 --- a/ex/memory_checks/tests/04_budget_allocations.c +++ b/ex/memory_checks/tests/04_budget_allocations.c @@ -202,38 +202,115 @@ TEST (realloc_budget_reset) { } -TEST (set_higher_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 (2); - for (int i = 8; i < 16; ++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) { + 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 = 32; i < 32; ++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) { + 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 (set_lower_budget) { - MEM_SET_ALLOCATION_BUDGET (2); +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_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)); - for (int i = 8; i < 16; ++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); @@ -241,7 +318,20 @@ 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 (1); + for (int i = 8; i < 16; ++i) + CHECK (array_append (array, i)); + CHECK (!array_append (array, 16)); + array_free (array); + TEST_PASSED; } @@ -274,7 +364,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 +389,14 @@ 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, + 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/04_budget_allocations_cpp.cc b/ex/memory_checks/tests/04_budget_allocations_cpp.cc deleted file mode 100644 index cf65ee1..0000000 --- a/ex/memory_checks/tests/04_budget_allocations_cpp.cc +++ /dev/null @@ -1,291 +0,0 @@ -#include "basic_testing.h" -extern "C" { -#include "../array.h" -} - - - -TEST (compile) { - TEST_PASSED; -} - - -TEST (no_budget_set) { - struct array * array = array_new (); - CHECK (array != NULL); - - CHECK_CMP (array_length (array),==,0); - CHECK_CMP (array_capacity (array),==,0); - - for (int i = 0; i < 100; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,100); - CHECK_CMP (array_capacity (array),>=,100); - - for (int i = 0; i < 100; ++i) - CHECK_CMP (array_element (array, i),==,i); - - array_free (array); - TEST_PASSED; -} - - -TEST (zero_budget) { - MEM_SET_ALLOCATION_BUDGET (0); - struct array * array = array_new (); - CHECK (array == NULL); - TEST_PASSED; -} - - -TEST (reset_after_budget) { - struct array * array = array_new (); - CHECK (array != NULL); - array_free (array); - TEST_PASSED; -} - - -TEST (simple_budget) { - MEM_SET_ALLOCATION_BUDGET (1); - struct array * array = array_new (); - CHECK (array != NULL); - struct array * array2 = array_new (); - CHECK (array2 == NULL); - array_free (array); - TEST_PASSED; -} - - -TEST (free_increment_budget) { - MEM_SET_ALLOCATION_BUDGET (1); - struct array * array = array_new (); - CHECK (array != NULL); - array_free (array); - struct array * array2 = array_new (); - CHECK (array2 != NULL); - array_free (array2); - TEST_PASSED; -} - - -TEST (budget_realloc_null) { - MEM_SET_ALLOCATION_BUDGET (1); - struct array * array = array_new (); - CHECK (array != NULL); - - for (int i = 0; i < 4; ++i) - CHECK (!array_append (array, i)); - - CHECK_CMP (array_length (array),==,0); - CHECK_CMP (array_capacity (array),==,0); - - array_free (array); - TEST_PASSED; -} - - -TEST (reset_after_budget_realloc_null) { - struct array * array = array_new (); - CHECK (array != NULL); - - for (int i = 0; i < 4; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,4); - CHECK_CMP (array_capacity (array),==,8); - - array_free (array); - TEST_PASSED; -} - - -TEST (budget_realloc) { - MEM_SET_ALLOCATION_BUDGET (2); - struct array * array = array_new (); - CHECK (array != NULL); - - for (int i = 0; i < 8; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,8); - CHECK_CMP (array_capacity (array),==,8); - - for (int i = 4; i < 16; ++i) - CHECK (!array_append (array, i)); - - CHECK_CMP (array_length (array),==,8); - CHECK_CMP (array_capacity (array),==,8); - - array_free (array); - TEST_PASSED; -} - - -TEST (reset_after_budget_realloc) { - struct array * array = array_new (); - CHECK (array != NULL); - - for (int i = 0; i < 8; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,8); - CHECK_CMP (array_capacity (array),==,8); - - for (int i = 4; i < 16; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,20); - CHECK_CMP (array_capacity (array),==,32); - - array_free (array); - TEST_PASSED; -} - - -TEST (malloc_budget_reset) { - MEM_SET_ALLOCATION_BUDGET (0); - struct array * array = array_new (); - CHECK (array == NULL); - MEM_RESET_ALLOCATOR (); - array = array_new (); - CHECK (array != NULL); - array_free (array); - TEST_PASSED; -} - - -TEST (realloc_null_budget_reset) { - MEM_SET_ALLOCATION_BUDGET (1); - struct array * array = array_new (); - CHECK (array != NULL); - - for (int i = 0; i < 4; ++i) - CHECK (!array_append (array, i)); - - CHECK_CMP (array_length (array),==,0); - CHECK_CMP (array_capacity (array),==,0); - MEM_RESET_ALLOCATOR (); - for (int i = 0; i < 4; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,4); - CHECK_CMP (array_capacity (array),==,8); - - array_free (array); - TEST_PASSED; -} - - -TEST (realloc_budget_reset) { - MEM_SET_ALLOCATION_BUDGET (2); - struct array * array = array_new (); - CHECK (array != NULL); - for (int i = 0; i < 8; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,8); - CHECK_CMP (array_capacity (array),==,8); - - for (int i = 4; i < 16; ++i) - CHECK (!array_append (array, i)); - - CHECK_CMP (array_length (array),==,8); - CHECK_CMP (array_capacity (array),==,8); - MEM_RESET_ALLOCATOR (); - for (int i = 4; i < 16; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,20); - CHECK_CMP (array_capacity (array),==,32); - 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 = 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; -} - - -TEST (set_lower_budget) { - MEM_SET_ALLOCATION_BUDGET (2); - struct 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)); - MEM_SET_ALLOCATION_BUDGET (1); - 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 (zero_budget_calloc) { - MEM_SET_ALLOCATION_BUDGET (0); - struct array * array = array_new_calloc (); - CHECK (array == NULL); - TEST_PASSED; -} - - -TEST (simple_budget_calloc) { - MEM_SET_ALLOCATION_BUDGET (1); - struct array * array = array_new_calloc (); - CHECK (array != NULL); - struct array * array2 = array_new_calloc (); - CHECK (array2 == NULL); - array2 = array_new (); - CHECK (array2 == NULL); - array_free (array); - TEST_PASSED; -} - - -TEST (reallocarray_budget) { - MEM_SET_ALLOCATION_BUDGET (1); - struct array * array = array_new_calloc (); - CHECK (array != NULL); - for (int i = 0; i < 4; ++i) - CHECK (!array_append_reallocarray (array, i)); - CHECK_CMP (array_length (array),==,0); - CHECK_CMP (array_capacity (array),==,0); - MEM_SET_ALLOCATION_BUDGET (1); - 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; -} - - - -MAIN_TEST_DRIVER (); diff --git a/ex/memory_checks/tests/05_byte_budget_allocations.c b/ex/memory_checks/tests/05_byte_budget_allocations.c index 05d3a17..c3d09bc 100644 --- a/ex/memory_checks/tests/05_byte_budget_allocations.c +++ b/ex/memory_checks/tests/05_byte_budget_allocations.c @@ -205,38 +205,120 @@ TEST (realloc_budget_reset) { } -TEST (set_higher_budget) { - MEM_SET_BYTES_BUDGET (sizeof (struct array)); +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_SET_BYTES_BUDGET (16*sizeof (int)); + 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)); - for (int i = 32; i < 32; ++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; +} + + +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 (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 +329,23 @@ 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)); + CHECK (!array_append (array, 17)); + array_free (array); + array = array_new (); + CHECK (array != NULL); + 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 +391,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 +415,14 @@ 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, + set_lower_budget_after_allocations, smaller_size_realloc, zero_budget_calloc, simple_budget_calloc, diff --git a/ex/memory_checks/tests/05_byte_budget_allocations_cpp.cc b/ex/memory_checks/tests/05_byte_budget_allocations_cpp.cc deleted file mode 100644 index 44edfbb..0000000 --- a/ex/memory_checks/tests/05_byte_budget_allocations_cpp.cc +++ /dev/null @@ -1,309 +0,0 @@ -#include "basic_testing.h" -#include -extern "C" { -#include "../array.h" -} - - - -TEST (compile) { - TEST_PASSED; -} - - -TEST (no_budget_set) { - struct array * array = array_new (); - CHECK (array != NULL); - - CHECK_CMP (array_length (array),==,0); - CHECK_CMP (array_capacity (array),==,0); - - for (int i = 0; i < 100; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,100); - CHECK_CMP (array_capacity (array),>=,100); - - for (int i = 0; i < 100; ++i) - CHECK_CMP (array_element (array, i),==,i); - - array_free (array); - TEST_PASSED; -} - - -TEST (zero_budget) { - MEM_SET_BYTES_BUDGET (0); - struct array * array = array_new (); - CHECK (array == NULL); - TEST_PASSED; -} - - -TEST (reset_after_budget) { - struct array * array = array_new (); - CHECK (array != NULL); - array_free (array); - TEST_PASSED; -} - - -TEST (simple_budget) { - MEM_SET_BYTES_BUDGET (sizeof (struct array)); - struct array * array = array_new (); - CHECK (array != NULL); - struct array * array2 = array_new (); - CHECK (array2 == NULL); - array_free (array); - TEST_PASSED; -} - - -TEST (free_increment_budget) { - MEM_SET_BYTES_BUDGET (sizeof (struct array)); - struct array * array = array_new (); - CHECK (array != NULL); - array_free (array); - struct array * array2 = array_new (); - CHECK (array2 != NULL); - array_free (array2); - TEST_PASSED; -} - - -TEST (budget_realloc_null) { - MEM_SET_BYTES_BUDGET (sizeof (struct array)); - struct array * array = array_new (); - CHECK (array != NULL); - - for (int i = 0; i < 4; ++i) - CHECK (!array_append (array, i)); - - CHECK_CMP (array_length (array),==,0); - CHECK_CMP (array_capacity (array),==,0); - - array_free (array); - TEST_PASSED; -} - - -TEST (reset_after_budget_realloc_null) { - struct array * array = array_new (); - CHECK (array != NULL); - - for (int i = 0; i < 4; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,4); - CHECK_CMP (array_capacity (array),==,8); - - array_free (array); - TEST_PASSED; -} - - -TEST (budget_realloc) { - MEM_SET_BYTES_BUDGET (sizeof (struct array) + 8*sizeof (int)); - struct array * array = array_new (); - CHECK (array != NULL); - - for (int i = 0; i < 8; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,8); - CHECK_CMP (array_capacity (array),==,8); - - for (int i = 4; i < 16; ++i) - CHECK (!array_append (array, i)); - - CHECK_CMP (array_length (array),==,8); - CHECK_CMP (array_capacity (array),==,8); - - array_free (array); - TEST_PASSED; -} - - -TEST (reset_after_budget_realloc) { - struct array * array = array_new (); - CHECK (array != NULL); - - for (int i = 0; i < 8; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,8); - CHECK_CMP (array_capacity (array),==,8); - - for (int i = 4; i < 16; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,20); - CHECK_CMP (array_capacity (array),==,32); - - array_free (array); - TEST_PASSED; -} - - -TEST (malloc_budget_reset) { - MEM_SET_BYTES_BUDGET (0); - struct array * array = array_new (); - CHECK (array == NULL); - MEM_RESET_ALLOCATOR (); - array = array_new (); - CHECK (array != NULL); - array_free (array); - TEST_PASSED; -} - - -TEST (realloc_null_budget_reset) { - MEM_SET_BYTES_BUDGET (sizeof (struct array)); - struct array * array = array_new (); - CHECK (array != NULL); - - for (int i = 0; i < 4; ++i) - CHECK (!array_append (array, i)); - - CHECK_CMP (array_length (array),==,0); - CHECK_CMP (array_capacity (array),==,0); - - MEM_RESET_ALLOCATOR (); - - for (int i = 0; i < 4; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,4); - CHECK_CMP (array_capacity (array),==,8); - - array_free (array); - TEST_PASSED; -} - - -TEST (realloc_budget_reset) { - MEM_SET_BYTES_BUDGET (sizeof (struct array) + 8*sizeof (int)); - struct array * array = array_new (); - CHECK (array != NULL); - for (int i = 0; i < 8; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,8); - CHECK_CMP (array_capacity (array),==,8); - - for (int i = 4; i < 16; ++i) - CHECK (!array_append (array, i)); - - CHECK_CMP (array_length (array),==,8); - CHECK_CMP (array_capacity (array),==,8); - MEM_RESET_ALLOCATOR (); - for (int i = 4; i < 16; ++i) - CHECK (array_append (array, i)); - - CHECK_CMP (array_length (array),==,20); - CHECK_CMP (array_capacity (array),==,32); - array_free (array); - 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 (16*sizeof (int)); - 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; -} - - -TEST (set_lower_budget) { - MEM_SET_BYTES_BUDGET (sizeof (struct array) + 8*sizeof (int)); - struct 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)); - MEM_SET_BYTES_BUDGET (sizeof (struct array)); - 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 (smaller_size_realloc) { - MEM_SET_BYTES_BUDGET (8*sizeof (int)); - int * p = (int *) malloc (8*sizeof (int)); - CHECK (p != NULL); - int * i = (int *) malloc (sizeof (int)); - CHECK (i == NULL); - p = (int *) realloc (p, 4*sizeof (int)); - CHECK (p != NULL); - i = (int *) malloc (sizeof (int)); - CHECK (i != NULL); - free (p); - free (i); - TEST_PASSED; -} - - -TEST (zero_budget_calloc) { - MEM_SET_BYTES_BUDGET (0); - struct array * array = array_new_calloc (); - CHECK (array == NULL); - TEST_PASSED; -} - - -TEST (simple_budget_calloc) { - MEM_SET_BYTES_BUDGET (sizeof (struct array)); - struct array * array = array_new_calloc (); - CHECK (array != NULL); - struct array * array2 = array_new_calloc (); - CHECK (array2 == NULL); - array2 = array_new (); - CHECK (array2 == NULL); - array_free (array); - TEST_PASSED; -} - - -TEST (reallocarray_budget) { - MEM_SET_BYTES_BUDGET (sizeof (struct array)); - struct array * array = array_new_calloc (); - CHECK (array != NULL); - for (int i = 0; i < 4; ++i) - 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); - 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; -} - - - -MAIN_TEST_DRIVER (); 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/tests/08_stdlib_functions.c b/ex/memory_checks/tests/08_stdlib_functions.c new file mode 100644 index 0000000..793c7c7 --- /dev/null +++ b/ex/memory_checks/tests/08_stdlib_functions.c @@ -0,0 +1,417 @@ +#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); + int num = rand (); + CHECK_CMP (rand (),!=,num); + 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_sprintf_scanf_no_leak) { + char buf[100]; + 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); + 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_sprintf_scanf_no_leak); diff --git a/ex/memory_checks/tests/08_strdup_leak.c b/ex/memory_checks/tests/08_strdup_leak.c new file mode 100644 index 0000000..8e4be6d --- /dev/null +++ b/ex/memory_checks/tests/08_strdup_leak.c @@ -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 (memory_leak); diff --git a/ex/memory_checks_cpp.expected b/ex/memory_checks_cpp.expected new file mode 100644 index 0000000..5b25ffa --- /dev/null +++ b/ex/memory_checks_cpp.expected @@ -0,0 +1,177 @@ +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_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 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..4723075 --- /dev/null +++ b/ex/memory_checks_cpp/array.cc @@ -0,0 +1,232 @@ +#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 *) wrapped_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; +} + +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 () { + 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 = nullptr; + if (a < 20) p = &a; + std::free (p); +} + +void non_new_delete (void) { + int a = 10; + int * p = nullptr; + if (a < 20) p = &a; + delete p; +} + +void non_new_array_delete (void) { + int a = 10; + int * p = nullptr; + 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 = nullptr; + if (a < 20) + p = new int{10}; + std::free (p); +} + +void new_array_object_free (void) { + int a = 10; + int * p = nullptr; + if (a < 20) + p = new int[10]; + std::free(p); +} + +void malloc_object_delete (void) { + int a = 10; + int * p = nullptr; + if (a < 20) + p = (int *) std::malloc (sizeof(int)); + delete p; +} + +void new_array_object_delete (void) { + int a = 10; + int * p = nullptr; + if (a < 20) + p = new int[10]; + delete p; +} + +void malloc_object_delete_array (void) { + int a = 10; + int * p = nullptr; + if (a < 20) + p = (int *) std::malloc (sizeof(int)); + delete[] p; +} + +void new_object_delete_array (void) { + int a = 10; + int * p = nullptr; + 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..a657f57 --- /dev/null +++ b/ex/memory_checks_cpp/array.h @@ -0,0 +1,73 @@ +#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); + +void * wrapped_reallocarray (void * ptr, size_t nmemb, size_t size); + +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 71% rename from ex/memory_checks/tests/00_hash_map_cpp.cc rename to ex/memory_checks_cpp/tests/00_hash_map.cc index ce49498..72010ff 100644 --- a/ex/memory_checks/tests/00_hash_map_cpp.cc +++ b/ex/memory_checks_cpp/tests/00_hash_map.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_allocator::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_allocator::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_allocator::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_allocator::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_allocator::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_allocator::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_allocator::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_allocator::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_allocator::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_allocator::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_allocator::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_allocator::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_allocator::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_allocator::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_allocator::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/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_cpp/tests/04_budget_allocations.cc b/ex/memory_checks_cpp/tests/04_budget_allocations.cc new file mode 100644 index 0000000..51d8218 --- /dev/null +++ b/ex/memory_checks_cpp/tests/04_budget_allocations.cc @@ -0,0 +1,739 @@ +#include "basic_testing.h" +#include "../array.h" +#include + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (no_budget_set) { + struct array * array = array_new (); + CHECK (array != NULL); + + CHECK_CMP (array_length (array),==,0); + CHECK_CMP (array_capacity (array),==,0); + + for (int i = 0; i < 100; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,100); + CHECK_CMP (array_capacity (array),>=,100); + + for (int i = 0; i < 100; ++i) + CHECK_CMP (array_element (array, i),==,i); + + array_free (array); + TEST_PASSED; +} + + +TEST (zero_budget) { + MEM_SET_ALLOCATION_BUDGET (0); + struct array * array = array_new (); + CHECK (array == NULL); + TEST_PASSED; +} + + +TEST (reset_after_budget) { + struct array * array = array_new (); + CHECK (array != NULL); + array_free (array); + TEST_PASSED; +} + + +TEST (simple_budget) { + MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new (); + CHECK (array != NULL); + struct array * array2 = array_new (); + CHECK (array2 == NULL); + array_free (array); + TEST_PASSED; +} + + +TEST (free_increment_budget) { + MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new (); + CHECK (array != NULL); + array_free (array); + struct array * array2 = array_new (); + CHECK (array2 != NULL); + array_free (array2); + TEST_PASSED; +} + + +TEST (budget_realloc_null) { + MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new (); + CHECK (array != NULL); + + for (int i = 0; i < 4; ++i) + CHECK (!array_append (array, i)); + + CHECK_CMP (array_length (array),==,0); + CHECK_CMP (array_capacity (array),==,0); + + array_free (array); + TEST_PASSED; +} + + +TEST (reset_after_budget_realloc_null) { + struct array * array = array_new (); + CHECK (array != NULL); + + for (int i = 0; i < 4; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,4); + CHECK_CMP (array_capacity (array),==,8); + + array_free (array); + TEST_PASSED; +} + + +TEST (budget_realloc) { + MEM_SET_ALLOCATION_BUDGET (2); + struct array * array = array_new (); + CHECK (array != NULL); + + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,8); + CHECK_CMP (array_capacity (array),==,8); + + for (int i = 4; i < 16; ++i) + CHECK (!array_append (array, i)); + + CHECK_CMP (array_length (array),==,8); + CHECK_CMP (array_capacity (array),==,8); + + array_free (array); + TEST_PASSED; +} + + +TEST (reset_after_budget_realloc) { + struct array * array = array_new (); + CHECK (array != NULL); + + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,8); + CHECK_CMP (array_capacity (array),==,8); + + for (int i = 4; i < 16; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,20); + CHECK_CMP (array_capacity (array),==,32); + + array_free (array); + TEST_PASSED; +} + + +TEST (malloc_budget_reset) { + MEM_SET_ALLOCATION_BUDGET (0); + struct array * array = array_new (); + CHECK (array == NULL); + MEM_RESET_ALLOCATOR (); + array = array_new (); + CHECK (array != NULL); + array_free (array); + TEST_PASSED; +} + + +TEST (realloc_null_budget_reset) { + MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new (); + CHECK (array != NULL); + + for (int i = 0; i < 4; ++i) + CHECK (!array_append (array, i)); + + CHECK_CMP (array_length (array),==,0); + CHECK_CMP (array_capacity (array),==,0); + MEM_RESET_ALLOCATOR (); + for (int i = 0; i < 4; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,4); + CHECK_CMP (array_capacity (array),==,8); + + array_free (array); + TEST_PASSED; +} + + +TEST (realloc_budget_reset) { + MEM_SET_ALLOCATION_BUDGET (2); + struct array * array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,8); + CHECK_CMP (array_capacity (array),==,8); + + for (int i = 4; i < 16; ++i) + CHECK (!array_append (array, i)); + + CHECK_CMP (array_length (array),==,8); + CHECK_CMP (array_capacity (array),==,8); + MEM_RESET_ALLOCATOR (); + for (int i = 4; i < 16; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,20); + CHECK_CMP (array_capacity (array),==,32); + array_free (array); + TEST_PASSED; +} + + +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; +} + + +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_malloc) { + 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_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 (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 (); + CHECK (array == NULL); + TEST_PASSED; +} + + +TEST (simple_budget_calloc) { + MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new_calloc (); + CHECK (array != NULL); + struct array * array2 = array_new_calloc (); + CHECK (array2 == NULL); + array2 = array_new (); + CHECK (array2 == NULL); + array_free (array); + TEST_PASSED; +} + + +TEST (reallocarray_budget) { + MEM_SET_ALLOCATION_BUDGET (1); + struct array * array = array_new_calloc (); + CHECK (array != NULL); + for (int i = 0; i < 4; ++i) + CHECK (!array_append_reallocarray (array, i)); + CHECK_CMP (array_length (array),==,0); + CHECK_CMP (array_capacity (array),==,0); + 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 (change_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_CHANGE_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 (change_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_CHANGE_ALLOCATION_BUDGET (1); + try { + array.append (9); + } catch (const std::bad_alloc& e) { + TEST_PASSED; + } + } + + TEST_FAILED; +} + + +TEST (change_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_CHANGE_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_CHANGE_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 (change_lower_budget_new) { + MEM_SET_ALLOCATION_BUDGET (4); + array_cpp * array = array_cpp_new (); + 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_CHANGE_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 (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_CHANGE_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; +} + + +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/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_cpp/tests/05_byte_budget_allocations.cc b/ex/memory_checks_cpp/tests/05_byte_budget_allocations.cc new file mode 100644 index 0000000..6803e63 --- /dev/null +++ b/ex/memory_checks_cpp/tests/05_byte_budget_allocations.cc @@ -0,0 +1,767 @@ +#include "basic_testing.h" +#include +#include "../array.h" + + + +TEST (compile) { + TEST_PASSED; +} + + +TEST (no_budget_set) { + struct array * array = array_new (); + CHECK (array != NULL); + + CHECK_CMP (array_length (array),==,0); + CHECK_CMP (array_capacity (array),==,0); + + for (int i = 0; i < 100; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,100); + CHECK_CMP (array_capacity (array),>=,100); + + for (int i = 0; i < 100; ++i) + CHECK_CMP (array_element (array, i),==,i); + + array_free (array); + TEST_PASSED; +} + + +TEST (zero_budget) { + MEM_SET_BYTES_BUDGET (0); + struct array * array = array_new (); + CHECK (array == NULL); + TEST_PASSED; +} + + +TEST (reset_after_budget) { + struct array * array = array_new (); + CHECK (array != NULL); + array_free (array); + TEST_PASSED; +} + + +TEST (simple_budget) { + MEM_SET_BYTES_BUDGET (sizeof (struct array)); + struct array * array = array_new (); + CHECK (array != NULL); + struct array * array2 = array_new (); + CHECK (array2 == NULL); + array_free (array); + TEST_PASSED; +} + + +TEST (free_increment_budget) { + MEM_SET_BYTES_BUDGET (sizeof (struct array)); + struct array * array = array_new (); + CHECK (array != NULL); + array_free (array); + struct array * array2 = array_new (); + CHECK (array2 != NULL); + array_free (array2); + TEST_PASSED; +} + + +TEST (budget_realloc_null) { + MEM_SET_BYTES_BUDGET (sizeof (struct array)); + struct array * array = array_new (); + CHECK (array != NULL); + + for (int i = 0; i < 4; ++i) + CHECK (!array_append (array, i)); + + CHECK_CMP (array_length (array),==,0); + CHECK_CMP (array_capacity (array),==,0); + + array_free (array); + TEST_PASSED; +} + + +TEST (reset_after_budget_realloc_null) { + struct array * array = array_new (); + CHECK (array != NULL); + + for (int i = 0; i < 4; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,4); + CHECK_CMP (array_capacity (array),==,8); + + array_free (array); + TEST_PASSED; +} + + +TEST (budget_realloc) { + MEM_SET_BYTES_BUDGET (sizeof (struct array) + 8*sizeof (int)); + struct array * array = array_new (); + CHECK (array != NULL); + + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,8); + CHECK_CMP (array_capacity (array),==,8); + + for (int i = 4; i < 16; ++i) + CHECK (!array_append (array, i)); + + CHECK_CMP (array_length (array),==,8); + CHECK_CMP (array_capacity (array),==,8); + + array_free (array); + TEST_PASSED; +} + + +TEST (reset_after_budget_realloc) { + struct array * array = array_new (); + CHECK (array != NULL); + + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,8); + CHECK_CMP (array_capacity (array),==,8); + + for (int i = 4; i < 16; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,20); + CHECK_CMP (array_capacity (array),==,32); + + array_free (array); + TEST_PASSED; +} + + +TEST (malloc_budget_reset) { + MEM_SET_BYTES_BUDGET (0); + struct array * array = array_new (); + CHECK (array == NULL); + MEM_RESET_ALLOCATOR (); + array = array_new (); + CHECK (array != NULL); + array_free (array); + TEST_PASSED; +} + + +TEST (realloc_null_budget_reset) { + MEM_SET_BYTES_BUDGET (sizeof (struct array)); + struct array * array = array_new (); + CHECK (array != NULL); + + for (int i = 0; i < 4; ++i) + CHECK (!array_append (array, i)); + + CHECK_CMP (array_length (array),==,0); + CHECK_CMP (array_capacity (array),==,0); + + MEM_RESET_ALLOCATOR (); + + for (int i = 0; i < 4; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,4); + CHECK_CMP (array_capacity (array),==,8); + + array_free (array); + TEST_PASSED; +} + + +TEST (realloc_budget_reset) { + MEM_SET_BYTES_BUDGET (sizeof (struct array) + 8*sizeof (int)); + struct array * array = array_new (); + CHECK (array != NULL); + for (int i = 0; i < 8; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,8); + CHECK_CMP (array_capacity (array),==,8); + + for (int i = 4; i < 16; ++i) + CHECK (!array_append (array, i)); + + CHECK_CMP (array_length (array),==,8); + CHECK_CMP (array_capacity (array),==,8); + MEM_RESET_ALLOCATOR (); + for (int i = 4; i < 16; ++i) + CHECK (array_append (array, i)); + + CHECK_CMP (array_length (array),==,20); + CHECK_CMP (array_capacity (array),==,32); + array_free (array); + TEST_PASSED; +} + + +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 (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(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) + 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_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)); + 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)); + 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_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)); + CHECK (!array_append (array, 17)); + array_free (array); + array = array_new (); + CHECK (array != NULL); + CHECK (!array_append (array, 17)); + array_free (array); + TEST_PASSED; +} + + +TEST (smaller_size_realloc) { + MEM_SET_BYTES_BUDGET (8*sizeof (int)); + int * p = (int *) malloc (8*sizeof (int)); + CHECK (p != NULL); + int * i = (int *) malloc (sizeof (int)); + CHECK (i == NULL); + p = (int *) realloc (p, 4*sizeof (int)); + CHECK (p != NULL); + i = (int *) malloc (sizeof (int)); + CHECK (i != NULL); + free (p); + free (i); + TEST_PASSED; +} + + +TEST (zero_budget_calloc) { + MEM_SET_BYTES_BUDGET (0); + struct array * array = array_new_calloc (); + CHECK (array == NULL); + TEST_PASSED; +} + + +TEST (simple_budget_calloc) { + MEM_SET_BYTES_BUDGET (sizeof (struct array)); + struct array * array = array_new_calloc (); + CHECK (array != NULL); + struct array * array2 = array_new_calloc (); + CHECK (array2 == NULL); + array2 = array_new (); + CHECK (array2 == NULL); + array_free (array); + TEST_PASSED; +} + + +TEST (reallocarray_budget) { + MEM_SET_BYTES_BUDGET (sizeof (struct array)); + struct array * array = array_new_calloc (); + CHECK (array != NULL); + for (int i = 0; i < 4; ++i) + CHECK (!array_append_reallocarray (array, i)); + CHECK_CMP (array_length (array),==,0); + CHECK_CMP (array_capacity (array),==,0); + 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); + CHECK_CMP (array_capacity (array),==,8); + array_free (array); + TEST_PASSED; +} + + +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 (change_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_CHANGE_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 (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) + array.append (i); + try { + array.append (9); + } catch (const std::bad_alloc& e) { + MEM_CHANGE_BYTES_BUDGET (array_cpp::initial_cap*sizeof(int)); + try { + array.append (9); + } catch (const std::bad_alloc& e) { + TEST_PASSED; + } + } + + TEST_FAILED; +} + + +TEST (change_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_CHANGE_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_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) + array->append (i); + array_cpp_delete (array); + TEST_PASSED; + } + } + array_cpp_delete (array); + TEST_FAILED; +} + + +TEST (change_lower_budget_new) { + MEM_SET_BYTES_BUDGET (sizeof(array_cpp) + 100*sizeof(int)); + array_cpp * array = array_cpp_new (); + 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_CHANGE_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 (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_CHANGE_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; +} + + +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 (); 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 78% rename from ex/memory_checks/tests/07_calloc_reallocarray_failures_cpp.cc rename to ex/memory_checks_cpp/tests/07_calloc_reallocarray_failures.cc index 2efe6e4..21e7d4c 100644 --- a/ex/memory_checks/tests/07_calloc_reallocarray_failures_cpp.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; } 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..d930d71 --- /dev/null +++ b/ex/memory_checks_cpp/tests/08_stdlib_functions.cc @@ -0,0 +1,393 @@ +#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); + int num = rand (); + CHECK_CMP (rand (),!=,num); + 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; +} + + +#ifndef __APPLE__ +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_sprintf_scanf_no_leak) { + char buf[100]; + 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); + TEST_PASSED; +} +#endif + + + +MAIN_TEST_DRIVER (); diff --git a/ex/memory_checks_cpp/tests/08_strdup_leak.cc b/ex/memory_checks_cpp/tests/08_strdup_leak.cc new file mode 100644 index 0000000..8e4be6d --- /dev/null +++ b/ex/memory_checks_cpp/tests/08_strdup_leak.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 (memory_leak);