diff options
Diffstat (limited to 'test/unit/core/test_mem.c')
-rw-r--r-- | test/unit/core/test_mem.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/test/unit/core/test_mem.c b/test/unit/core/test_mem.c new file mode 100644 index 00000000000..601bfc7d485 --- /dev/null +++ b/test/unit/core/test_mem.c @@ -0,0 +1,221 @@ +#include "test_mem.h" + +#include "lwip/mem.h" +#include "lwip/stats.h" + +#if !LWIP_STATS || !MEM_STATS +#error "This tests needs MEM-statistics enabled" +#endif + +/* Setups/teardown functions */ + +static void +mem_setup(void) +{ + lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); +} + +static void +mem_teardown(void) +{ + lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT)); +} + + +/* Test functions */ + +/** Call mem_malloc, mem_free and mem_trim and check stats */ +START_TEST(test_mem_one) +{ +#define SIZE1 16 +#define SIZE1_2 12 +#define SIZE2 16 + void *p1, *p2; + mem_size_t s1, s2; + LWIP_UNUSED_ARG(_i); + + fail_unless(lwip_stats.mem.used == 0); + + p1 = mem_malloc(SIZE1); + fail_unless(p1 != NULL); + fail_unless(lwip_stats.mem.used >= SIZE1); + s1 = lwip_stats.mem.used; + + p2 = mem_malloc(SIZE2); + fail_unless(p2 != NULL); + fail_unless(lwip_stats.mem.used >= SIZE2 + s1); + s2 = lwip_stats.mem.used; + + mem_trim(p1, SIZE1_2); + + mem_free(p2); + fail_unless(lwip_stats.mem.used <= s2 - SIZE2); + + mem_free(p1); + fail_unless(lwip_stats.mem.used == 0); +} +END_TEST + +static void malloc_keep_x(int x, int num, int size, int freestep) +{ + int i; + void* p[16]; + LWIP_ASSERT("invalid size", size >= 0 && size < (mem_size_t)-1); + memset(p, 0, sizeof(p)); + for(i = 0; i < num && i < 16; i++) { + p[i] = mem_malloc((mem_size_t)size); + fail_unless(p[i] != NULL); + } + for(i = 0; i < num && i < 16; i += freestep) { + if (i == x) { + continue; + } + mem_free(p[i]); + p[i] = NULL; + } + for(i = 0; i < num && i < 16; i++) { + if (i == x) { + continue; + } + if (p[i] != NULL) { + mem_free(p[i]); + p[i] = NULL; + } + } + fail_unless(p[x] != NULL); + mem_free(p[x]); +} + +START_TEST(test_mem_random) +{ + const int num = 16; + int x; + int size; + int freestep; + LWIP_UNUSED_ARG(_i); + + fail_unless(lwip_stats.mem.used == 0); + + for (x = 0; x < num; x++) { + for (size = 1; size < 32; size++) { + for (freestep = 1; freestep <= 3; freestep++) { + fail_unless(lwip_stats.mem.used == 0); + malloc_keep_x(x, num, size, freestep); + fail_unless(lwip_stats.mem.used == 0); + } + } + } +} +END_TEST + +START_TEST(test_mem_invalid_free) +{ + u8_t *ptr, *ptr_low, *ptr_high; + LWIP_UNUSED_ARG(_i); + + fail_unless(lwip_stats.mem.used == 0); + fail_unless(lwip_stats.mem.illegal == 0); + + ptr = (u8_t *)mem_malloc(1); + fail_unless(ptr != NULL); + fail_unless(lwip_stats.mem.used != 0); + + ptr_low = ptr - 0x10; + mem_free(ptr_low); + fail_unless(lwip_stats.mem.illegal == 1); + lwip_stats.mem.illegal = 0; + + ptr_high = ptr + (MEM_SIZE * 2); + mem_free(ptr_high); + fail_unless(lwip_stats.mem.illegal == 1); + lwip_stats.mem.illegal = 0; + + mem_free(ptr); + fail_unless(lwip_stats.mem.illegal == 0); + fail_unless(lwip_stats.mem.used == 0); +} +END_TEST + +START_TEST(test_mem_double_free) +{ + u8_t *ptr1b, *ptr1, *ptr2, *ptr3; + LWIP_UNUSED_ARG(_i); + + fail_unless(lwip_stats.mem.used == 0); + fail_unless(lwip_stats.mem.illegal == 0); + + ptr1 = (u8_t *)mem_malloc(1); + fail_unless(ptr1 != NULL); + fail_unless(lwip_stats.mem.used != 0); + + ptr2 = (u8_t *)mem_malloc(1); + fail_unless(ptr2 != NULL); + fail_unless(lwip_stats.mem.used != 0); + + ptr3 = (u8_t *)mem_malloc(1); + fail_unless(ptr3 != NULL); + fail_unless(lwip_stats.mem.used != 0); + + /* free the middle mem */ + mem_free(ptr2); + fail_unless(lwip_stats.mem.illegal == 0); + + /* double-free of middle mem: should fail */ + mem_free(ptr2); + fail_unless(lwip_stats.mem.illegal == 1); + lwip_stats.mem.illegal = 0; + + /* free upper memory and try again */ + mem_free(ptr3); + fail_unless(lwip_stats.mem.illegal == 0); + + mem_free(ptr2); + fail_unless(lwip_stats.mem.illegal == 1); + lwip_stats.mem.illegal = 0; + + /* free lower memory and try again */ + mem_free(ptr1); + fail_unless(lwip_stats.mem.illegal == 0); + fail_unless(lwip_stats.mem.used == 0); + + mem_free(ptr2); + fail_unless(lwip_stats.mem.illegal == 1); + fail_unless(lwip_stats.mem.used == 0); + lwip_stats.mem.illegal = 0; + + /* reallocate lowest memory, now overlapping already freed ptr2 */ +#ifndef MIN_SIZE +#define MIN_SIZE 12 +#endif + ptr1b = (u8_t *)mem_malloc(MIN_SIZE * 2); + fail_unless(ptr1b != NULL); + fail_unless(lwip_stats.mem.used != 0); + + mem_free(ptr2); + fail_unless(lwip_stats.mem.illegal == 1); + lwip_stats.mem.illegal = 0; + + memset(ptr1b, 1, MIN_SIZE * 2); + + mem_free(ptr2); + fail_unless(lwip_stats.mem.illegal == 1); + lwip_stats.mem.illegal = 0; + + mem_free(ptr1b); + fail_unless(lwip_stats.mem.illegal == 0); + fail_unless(lwip_stats.mem.used == 0); +} +END_TEST + +/** Create the suite including all tests for this module */ +Suite * +mem_suite(void) +{ + testfunc tests[] = { + TESTFUNC(test_mem_one), + TESTFUNC(test_mem_random), + TESTFUNC(test_mem_invalid_free), + TESTFUNC(test_mem_double_free) + }; + return create_suite("MEM", tests, sizeof(tests)/sizeof(testfunc), mem_setup, mem_teardown); +} |