summaryrefslogtreecommitdiff
path: root/test/unit/core/test_mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/unit/core/test_mem.c')
-rw-r--r--test/unit/core/test_mem.c221
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);
+}