1 /*
2  Tests for the capabilities-based memory allocator.
3 */
4 
5 #include <esp_types.h>
6 #include <stdio.h>
7 #include "unity.h"
8 #include "esp_attr.h"
9 #include "esp_heap_caps.h"
10 #include "esp_spi_flash.h"
11 #include <stdlib.h>
12 #include <sys/param.h>
13 #include <string.h>
14 #include <malloc.h>
15 
16 TEST_CASE("Capabilities aligned allocator test", "[heap]")
17 {
18     uint32_t alignments = 0;
19 
20     printf("[ALIGNED_ALLOC] Allocating from default CAP: \n");
21 
22     for(;alignments <= 1024; alignments++) {
23         uint8_t *buf = (uint8_t *)memalign(alignments, (alignments + 137));
24         if(((alignments & (alignments - 1)) != 0) || (!alignments)) {
25             TEST_ASSERT( buf == NULL );
26             //printf("[ALIGNED_ALLOC] alignment: %u is not a power of two, don't allow allocation \n", aligments);
27         } else {
28             TEST_ASSERT( buf != NULL );
29             printf("[ALIGNED_ALLOC] alignment required: %u \n", alignments);
30             printf("[ALIGNED_ALLOC] address of allocated memory: %p \n\n", (void *)buf);
31             //Address of obtained block must be aligned with selected value
32             TEST_ASSERT(((intptr_t)buf & (alignments - 1)) == 0);
33 
34             //Write some data, if it corrupts memory probably the heap
35             //canary verification will fail:
36             memset(buf, 0xA5, (alignments + 137));
37 
38             free(buf);
39         }
40     }
41 
42     //Alloc from a non permitted area:
43     uint32_t *not_permitted_buf = (uint32_t *)heap_caps_aligned_alloc(alignments, (alignments + 137), MALLOC_CAP_EXEC | MALLOC_CAP_32BIT);
44     TEST_ASSERT( not_permitted_buf == NULL );
45 
46 #if CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_ESP32S2_SPIRAM_SUPPORT
47     alignments = 0;
48     printf("[ALIGNED_ALLOC] Allocating from external memory: \n");
49 
50     for(;alignments <= 1024 * 1024; alignments++) {
51         //Now try to take aligned memory from IRAM:
52         uint8_t *buf = (uint8_t *)heap_caps_aligned_alloc(alignments, 10*1024, MALLOC_CAP_SPIRAM);
53         if(((alignments & (alignments - 1)) != 0) || (!alignments)) {
54             TEST_ASSERT( buf == NULL );
55             //printf("[ALIGNED_ALLOC] alignment: %u is not a power of two, don't allow allocation \n", aligments);
56         } else {
57             TEST_ASSERT( buf != NULL );
58             printf("[ALIGNED_ALLOC] alignment required: %u \n", alignments);
59             printf("[ALIGNED_ALLOC] address of allocated memory: %p \n\n", (void *)buf);
60             //Address of obtained block must be aligned with selected value
61             TEST_ASSERT(((intptr_t)buf & (alignments - 1)) == 0);
62 
63             //Write some data, if it corrupts memory probably the heap
64             //canary verification will fail:
65             memset(buf, 0xA5, (10*1024));
66             heap_caps_free(buf);
67         }
68     }
69 #endif
70 
71 }
72 
73 TEST_CASE("Capabilities aligned calloc test", "[heap]")
74 {
75     uint32_t alignments = 0;
76 
77     printf("[ALIGNED_ALLOC] Allocating from default CAP: \n");
78 
79     for(;alignments <= 1024; alignments++) {
80         uint8_t *buf = (uint8_t *)heap_caps_aligned_calloc(alignments, 1, (alignments + 137), MALLOC_CAP_DEFAULT);
81         if(((alignments & (alignments - 1)) != 0) || (!alignments)) {
82             TEST_ASSERT( buf == NULL );
83             //printf("[ALIGNED_ALLOC] alignment: %u is not a power of two, don't allow allocation \n", aligments);
84         } else {
85             TEST_ASSERT( buf != NULL );
86             printf("[ALIGNED_ALLOC] alignment required: %u \n", alignments);
87             printf("[ALIGNED_ALLOC] address of allocated memory: %p \n\n", (void *)buf);
88             //Address of obtained block must be aligned with selected value
89             TEST_ASSERT(((intptr_t)buf & (alignments - 1)) == 0);
90 
91             //Write some data, if it corrupts memory probably the heap
92             //canary verification will fail:
93             memset(buf, 0xA5, (alignments + 137));
94 
95             heap_caps_free(buf);
96         }
97     }
98 
99     //Check if memory is initialized with zero:
100     uint8_t byte_array[1024];
101     memset(&byte_array, 0, sizeof(byte_array));
102     uint8_t *buf = (uint8_t *)heap_caps_aligned_calloc(1024, 1, 1024, MALLOC_CAP_DEFAULT);
103     TEST_ASSERT(memcmp(byte_array, buf, sizeof(byte_array)) == 0);
104     heap_caps_free(buf);
105 
106     //Same size, but different chunk:
107     buf = (uint8_t *)heap_caps_aligned_calloc(1024, 1024, 1, MALLOC_CAP_DEFAULT);
108     TEST_ASSERT(memcmp(byte_array, buf, sizeof(byte_array)) == 0);
109     heap_caps_free(buf);
110 
111     //Alloc from a non permitted area:
112     uint32_t *not_permitted_buf = (uint32_t *)heap_caps_aligned_calloc(alignments, 1, (alignments + 137), MALLOC_CAP_32BIT);
113     TEST_ASSERT( not_permitted_buf == NULL );
114 
115 #if CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_ESP32S2_SPIRAM_SUPPORT
116     alignments = 0;
117     printf("[ALIGNED_ALLOC] Allocating from external memory: \n");
118 
119     for(;alignments <= 1024 * 1024; alignments++) {
120         //Now try to take aligned memory from IRAM:
121         uint8_t *buf = (uint8_t *)(uint8_t *)heap_caps_aligned_calloc(alignments, 1, 10*1024, MALLOC_CAP_SPIRAM);
122         if(((alignments & (alignments - 1)) != 0) || (!alignments)) {
123             TEST_ASSERT( buf == NULL );
124             //printf("[ALIGNED_ALLOC] alignment: %u is not a power of two, don't allow allocation \n", aligments);
125         } else {
126             TEST_ASSERT( buf != NULL );
127             printf("[ALIGNED_ALLOC] alignment required: %u \n", alignments);
128             printf("[ALIGNED_ALLOC] address of allocated memory: %p \n\n", (void *)buf);
129             //Address of obtained block must be aligned with selected value
130             TEST_ASSERT(((intptr_t)buf & (alignments - 1)) == 0);
131 
132             //Write some data, if it corrupts memory probably the heap
133             //canary verification will fail:
134             memset(buf, 0xA5, (10*1024));
135             heap_caps_free(buf);
136         }
137     }
138 #endif
139 
140 }
141 
142 TEST_CASE("aligned_alloc(0) should return a NULL pointer", "[heap]")
143 {
144     void *p;
145     p = heap_caps_aligned_alloc(32, 0, MALLOC_CAP_DEFAULT);
146     TEST_ASSERT(p == NULL);
147 }
148