blob: 9cabe4367334f8e29ea0826cfd509497f2c70b54 [file] [log] [blame]
Praful Swarnakar3a82aef2018-08-02 08:36:59 +05301/*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7/*
8 * @file test dynamic memory allocation using C libraries
9 *
10 * This module verifies that the various dynamic memory allocation functions
11 * works fine with minimal C library and newlib C library.
12 *
13 * IMPORTANT: The module only ensures that each supported library is present,
14 * and that a bare minimum of its functionality is operating correctly. It does
15 * NOT guarantee that ALL standards-defined functionality is present, nor does
16 * it guarantee that ALL functionality provided is working correctly.
17 */
18
Keith Packard623a6d92022-04-12 17:16:01 -070019#define _BSD_SOURCE
Gerard Marull-Paretas79e6b0e2022-08-25 09:58:46 +020020#include <zephyr/kernel.h>
Fabio Baltieridef23012022-07-19 14:16:24 +000021#include <zephyr/ztest.h>
Tom Hughes11d70c62025-01-15 16:32:52 -080022#include <zephyr/test_toolchain.h>
Praful Swarnakar3a82aef2018-08-02 08:36:59 +053023#include <stdlib.h>
24#include <errno.h>
Martin Åberg80b90802021-01-14 15:24:16 +010025#include <time.h>
Keith Packard0643f002022-06-20 21:44:20 -070026#include <stdint.h>
27
Tom Hughes11d70c62025-01-15 16:32:52 -080028/*
29 * Don't complain about ridiculous alloc size requests
30 */
Tom Hughes15411742025-01-17 09:32:42 -080031TOOLCHAIN_DISABLE_GCC_WARNING(TOOLCHAIN_WARNING_ALLOC_SIZE_LARGER_THAN)
Tom Hughes11d70c62025-01-15 16:32:52 -080032
Keith Packard0643f002022-06-20 21:44:20 -070033#define TOO_BIG PTRDIFF_MAX
Praful Swarnakar3a82aef2018-08-02 08:36:59 +053034
shixiongx zhang84d23fd2021-03-04 14:31:06 +080035/**
36 *
37 * @brief Test implementation-defined constants library
38 * @defgroup libc_api
39 * @ingroup all_tests
40 * @{
41 *
42 */
43
Praful Swarnakar3a82aef2018-08-02 08:36:59 +053044#define BUF_LEN 10
45
Martin Åberg80b90802021-01-14 15:24:16 +010046
47/* The access test allocates objects of this type and dereferences members. */
48union aligntest {
49 long long thelonglong;
50 double thedouble;
51 uintmax_t theuintmax_t;
52 void (*thepfunc)(void);
53 time_t thetime_t;
54};
55
Anas Nashif3e4c5472023-02-22 15:56:59 +000056
Keith Packard5e0a25f2023-05-09 12:14:52 -070057#if defined(CONFIG_COMMON_LIBC_MALLOC) && \
58 (CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE == 0)
Anas Nashif3e4c5472023-02-22 15:56:59 +000059__no_optimization void _test_no_mem_malloc(void)
60{
61 int *iptr = NULL;
62
63 iptr = malloc(BUF_LEN);
64 zassert_is_null((iptr), "malloc failed, errno: %d", errno);
65 free(iptr);
66 iptr = NULL;
67}
68
69ZTEST(c_lib_dynamic_memalloc, test_no_mem_malloc)
70{
71 _test_no_mem_malloc();
72}
73
74__no_optimization void _test_no_mem_realloc(void)
75{
76 char *ptr = NULL;
77 char *reloc_ptr = NULL;
78
79 reloc_ptr = realloc(ptr, BUF_LEN);
80 zassert_is_null(reloc_ptr, "realloc failed, errno: %d", errno);
81 free(reloc_ptr);
82 reloc_ptr = NULL;
83}
84
85ZTEST(c_lib_dynamic_memalloc, test_no_mem_realloc)
86{
87 _test_no_mem_realloc();
88}
89#else
Martin Åberg80b90802021-01-14 15:24:16 +010090/* Make sure we can access some built-in types. */
91static void do_the_access(volatile union aligntest *aptr)
92{
93 aptr->thelonglong = 2;
94 aptr->thelonglong;
95
96 if (IS_ENABLED(CONFIG_FPU)) {
97 aptr->thedouble = 3.0;
98 aptr->thedouble;
99 }
100
101 aptr->theuintmax_t = 4;
102 aptr->theuintmax_t;
103
104 aptr->thepfunc = test_main;
105 aptr->thepfunc;
106
107 aptr->thetime_t = 3;
108 aptr->thetime_t;
109}
110
111#define PRINT_TYPE_INFO(_t) \
112 TC_PRINT(" %-14s %4zu %5zu\n", #_t, sizeof(_t), __alignof__(_t))
113
Anas Nashif3e4c5472023-02-22 15:56:59 +0000114ZTEST(c_lib_dynamic_memalloc, test_malloc_align)
Martin Åberg80b90802021-01-14 15:24:16 +0100115{
116 char *ptr[64] = { NULL };
117
118 TC_PRINT(" Compiler type info for " CONFIG_ARCH " " CONFIG_BOARD "\n");
119 TC_PRINT(" TYPE SIZE ALIGN\n");
120 PRINT_TYPE_INFO(int);
121 PRINT_TYPE_INFO(long);
122 PRINT_TYPE_INFO(long long);
123 PRINT_TYPE_INFO(double);
124 PRINT_TYPE_INFO(size_t);
125 PRINT_TYPE_INFO(void *);
126 PRINT_TYPE_INFO(void (*)(void));
127 PRINT_TYPE_INFO(time_t);
128
129 /* Tries to use the malloc() implementation when in different states. */
130 for (size_t i = 0; i < ARRAY_SIZE(ptr); i++) {
131 union aligntest *aptr = NULL;
132
133 ptr[i] = malloc(sizeof *(ptr[i]));
134 aptr = malloc(sizeof(*aptr));
135 if (aptr) {
136 do_the_access(aptr);
137 }
138 free(aptr);
139 }
140 for (size_t i = 0; i < ARRAY_SIZE(ptr); i++) {
141 free(ptr[i]);
142 ptr[i] = NULL;
143 }
144
145 for (size_t n = 0; n < ARRAY_SIZE(ptr); n++) {
146 union aligntest *aptr = NULL;
147
148 for (size_t i = 0; i < n; i++) {
149 ptr[i] = malloc(sizeof *(ptr[i]));
150 }
151 aptr = malloc(sizeof(*aptr));
152 if (aptr) {
153 do_the_access(aptr);
154 }
155 free(aptr);
156 for (size_t i = 0; i < n; i++) {
157 free(ptr[i]);
158 ptr[i] = NULL;
159 }
160 }
161
162 for (size_t n = 0; n < ARRAY_SIZE(ptr); n++) {
163 union aligntest *aptr = NULL;
164
165 ptr[n] = malloc(n);
166 aptr = malloc(sizeof(*aptr));
167 if (aptr) {
168 do_the_access(aptr);
169 }
170 free(aptr);
171 free(ptr[n]);
172 ptr[n] = NULL;
173 }
174}
175
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530176/**
177 * @brief Test dynamic memory allocation using malloc
178 *
179 * @see malloc(), free()
180 */
Anas Nashif3e4c5472023-02-22 15:56:59 +0000181ZTEST(c_lib_dynamic_memalloc, test_malloc)
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530182{
183 /* Initialize error number to avoid garbage value, in case of SUCCESS */
184 int *iptr = NULL;
185
186 iptr = malloc(BUF_LEN * sizeof(int));
187 zassert_not_null((iptr), "malloc failed, errno: %d", errno);
Andrew Boie4b4f7732019-02-01 12:18:31 -0800188 memset(iptr, 'p', BUF_LEN * sizeof(int));
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530189 free(iptr);
190 iptr = NULL;
191}
192
193/**
194 * @brief Test dynamic memory allocation free function
195 *
196 * @see free()
197 */
Anas Nashif3e4c5472023-02-22 15:56:59 +0000198ZTEST(c_lib_dynamic_memalloc, test_free)
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530199{
200/*
201 * In free, if ptr is passed as NULL, no operation is performed
202 * Just make sure, no exception occurs and test pass
203 */
204 free(NULL);
205}
206
207/**
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530208 * @brief Test dynamic memory allocation using realloc
209 *
210 * @see malloc(), realloc(), free()
211 */
Andrew Boie4b4f7732019-02-01 12:18:31 -0800212ZTEST_BMEM unsigned char filled_buf[BUF_LEN];
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530213
Anas Nashif3e4c5472023-02-22 15:56:59 +0000214ZTEST(c_lib_dynamic_memalloc, test_realloc)
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530215{
216 char orig_size = BUF_LEN;
217 char new_size = BUF_LEN + BUF_LEN;
218 char *ptr = NULL;
219 char *reloc_ptr = NULL;
220
221 ptr = malloc(orig_size);
222
223 zassert_not_null((ptr), "malloc failed, errno: %d", errno);
Flavio Ceolinda49f2e2018-09-11 19:09:03 -0700224 (void)memset(ptr, 'p', orig_size);
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530225
226 reloc_ptr = realloc(ptr, new_size);
227
228 zassert_not_null(reloc_ptr, "realloc failed, errno: %d", errno);
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530229 ptr = reloc_ptr;
230
Flavio Ceolinda49f2e2018-09-11 19:09:03 -0700231 (void)memset(filled_buf, 'p', BUF_LEN);
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530232 zassert_true(((memcmp(ptr, filled_buf, BUF_LEN)) == 0),
233 "realloc failed to copy malloc data, errno: %d", errno);
234
235 free(ptr);
236 ptr = NULL;
237}
238
239/**
240 * @brief Test dynamic memory allocation using reallocarray
241 *
242 * @see malloc(), reallocarray(), free()
243 */
Kumar Galad4ed0d72023-03-16 14:58:04 +0000244#if defined(CONFIG_NEWLIB_LIBC) || defined(CONFIG_ARMCLANG_STD_LIBC)
Anas Nashif3e4c5472023-02-22 15:56:59 +0000245ZTEST(c_lib_dynamic_memalloc, test_reallocarray)
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530246{
Kumar Galad4ed0d72023-03-16 14:58:04 +0000247 /* reallocarray not implemented for newlib or arm libc */
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530248 ztest_test_skip();
249}
Anas Nashif3e4c5472023-02-22 15:56:59 +0000250ZTEST(c_lib_dynamic_memalloc, test_calloc)
shixiongx zhang84d23fd2021-03-04 14:31:06 +0800251{
252 ztest_test_skip();
253}
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530254#else
shixiongx zhang84d23fd2021-03-04 14:31:06 +0800255/**
256 * @brief Test dynamic memory allocation using calloc
257 *
258 * @see calloc(), free()
259 */
260#define CALLOC_BUFLEN (200)
261static ZTEST_BMEM unsigned char zerobuf[CALLOC_BUFLEN];
262
Anas Nashif3e4c5472023-02-22 15:56:59 +0000263__no_optimization void _test_calloc(void)
shixiongx zhang84d23fd2021-03-04 14:31:06 +0800264{
265 char *cptr = NULL;
266
Keith Packard0643f002022-06-20 21:44:20 -0700267 cptr = calloc(TOO_BIG, sizeof(int));
shixiongx zhang84d23fd2021-03-04 14:31:06 +0800268 zassert_is_null((cptr), "calloc failed, errno: %d", errno);
Enjia Maid1116372021-03-31 01:10:53 +0800269 free(cptr);
shixiongx zhang84d23fd2021-03-04 14:31:06 +0800270
Keith Packard0643f002022-06-20 21:44:20 -0700271 cptr = calloc(TOO_BIG, sizeof(char));
shixiongx zhang84d23fd2021-03-04 14:31:06 +0800272 zassert_is_null((cptr), "calloc failed, errno: %d", errno);
Enjia Maid1116372021-03-31 01:10:53 +0800273 free(cptr);
shixiongx zhang84d23fd2021-03-04 14:31:06 +0800274
275 cptr = calloc(CALLOC_BUFLEN, sizeof(char));
276 zassert_not_null((cptr), "calloc failed, errno: %d", errno);
277 zassert_true(((memcmp(cptr, zerobuf, CALLOC_BUFLEN)) == 0),
278 "calloc failed to set zero value, errno: %d", errno);
279 memset(cptr, 'p', CALLOC_BUFLEN);
280 free(cptr);
281 cptr = NULL;
282}
Anas Nashif3e4c5472023-02-22 15:56:59 +0000283ZTEST(c_lib_dynamic_memalloc, test_calloc)
284{
285 _test_calloc();
286}
shixiongx zhang84d23fd2021-03-04 14:31:06 +0800287
Anas Nashif3e4c5472023-02-22 15:56:59 +0000288ZTEST(c_lib_dynamic_memalloc, test_reallocarray)
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530289{
290 char orig_size = BUF_LEN;
291 char *ptr = NULL;
shixiongx zhang84d23fd2021-03-04 14:31:06 +0800292 char *cptr = NULL;
293
Keith Packard0643f002022-06-20 21:44:20 -0700294 cptr = reallocarray(ptr, TOO_BIG, sizeof(int));
shixiongx zhang84d23fd2021-03-04 14:31:06 +0800295 zassert_is_null((ptr), "reallocarray failed, errno: %d", errno);
296 zassert_is_null((cptr), "reallocarray failed, errno: %d");
297 free(cptr);
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530298
299 ptr = malloc(orig_size);
300
301 zassert_not_null((ptr), "malloc failed, errno: %d", errno);
Flavio Ceolinda49f2e2018-09-11 19:09:03 -0700302 (void)memset(ptr, 'p', orig_size);
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530303
304 char *reloc_ptr = reallocarray(ptr, 2, orig_size);
305
306 zassert_not_null(reloc_ptr, "reallocarray failed");
307 zassert_not_null((ptr), "malloc/reallocarray failed, errno: %d", errno);
308 ptr = reloc_ptr;
309
Flavio Ceolinda49f2e2018-09-11 19:09:03 -0700310 (void)memset(filled_buf, 'p', BUF_LEN);
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530311 zassert_true(((memcmp(ptr, filled_buf, BUF_LEN)) == 0),
312 "realloc failed to copy malloc data, errno: %d", errno);
313
314 free(ptr);
315 ptr = NULL;
316}
317#endif
318
319
320#define MAX_LEN (10 * BUF_LEN)
321
322/**
323 * @brief Test dynamic memory allocation functions
324 *
325 * @see malloc(), calloc(), realloc(), free()
326 */
Anas Nashif3e4c5472023-02-22 15:56:59 +0000327ZTEST(c_lib_dynamic_memalloc, test_memalloc_all)
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530328{
329 char *mlc_ptr = NULL;
330 char *clc_ptr = NULL;
331 char *reloc_ptr = NULL;
332 int orig_size = BUF_LEN;
333 int new_size = MAX_LEN;
334
335 mlc_ptr = malloc(orig_size);
336 zassert_not_null((mlc_ptr), "malloc failed, errno: %d", errno);
337
338 clc_ptr = calloc(100, sizeof(char));
339 zassert_not_null((clc_ptr), "calloc failed, errno: %d", errno);
340
341 reloc_ptr = realloc(mlc_ptr, new_size);
342 zassert_not_null(reloc_ptr, "realloc failed, errno: %d", errno);
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530343 mlc_ptr = reloc_ptr;
344
345 free(mlc_ptr);
346 free(clc_ptr);
347 mlc_ptr = NULL;
348 clc_ptr = NULL;
349 reloc_ptr = NULL;
350}
351
352/**
shixiongx zhang84d23fd2021-03-04 14:31:06 +0800353 * @}
354 */
355
356/**
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530357 *
358 * @brief Test dynamic memory allocation upto maximum size
359 * Negative test case
360 *
361 */
Anas Nashif3e4c5472023-02-22 15:56:59 +0000362__no_optimization void _test_memalloc_max(void)
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530363{
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530364 char *ptr = NULL;
365
Keith Packard0643f002022-06-20 21:44:20 -0700366 ptr = malloc(TOO_BIG);
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530367 zassert_is_null(ptr, "malloc passed unexpectedly");
368 free(ptr);
369 ptr = NULL;
370}
371
Anas Nashif3e4c5472023-02-22 15:56:59 +0000372ZTEST(c_lib_dynamic_memalloc, test_memalloc_max)
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530373{
Anas Nashif3e4c5472023-02-22 15:56:59 +0000374 _test_memalloc_max();
Praful Swarnakar3a82aef2018-08-02 08:36:59 +0530375}
Anas Nashif3e4c5472023-02-22 15:56:59 +0000376#endif
377
378ZTEST_SUITE(c_lib_dynamic_memalloc, NULL, NULL, NULL, NULL, NULL);