Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
dynmemtest.cpp
00001 /* 00002 * Copyright (c) 2015-2018 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "CppUTest/TestHarness.h" 00017 #include "nsdynmemLIB.h" 00018 #include <stdlib.h> 00019 #include <stdio.h> 00020 #include "error_callback.h" 00021 00022 TEST_GROUP(dynmem) 00023 { 00024 void setup() { 00025 reset_heap_error(); 00026 } 00027 00028 void teardown() { 00029 } 00030 }; 00031 00032 TEST(dynmem, init) 00033 { 00034 uint16_t size = 1000; 00035 uint8_t *heap = (uint8_t*)malloc(size); 00036 CHECK(NULL != heap); 00037 mem_stat_t info; 00038 reset_heap_error(); 00039 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00040 CHECK(info.heap_sector_size >= (size-72)); 00041 CHECK(!heap_have_failed()); 00042 CHECK(ns_dyn_mem_get_mem_stat() == &info); 00043 free(heap); 00044 } 00045 00046 TEST(dynmem, different_sizes) 00047 { 00048 reset_heap_error(); 00049 for (uint16_t size = 1000; size<32768; size++) { 00050 mem_stat_t info; 00051 uint8_t *heap = (uint8_t*)malloc(size); 00052 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00053 CHECK(info.heap_sector_size >= (size-72)); 00054 CHECK(!heap_have_failed()); 00055 CHECK(ns_dyn_mem_alloc(10)); 00056 free(heap); 00057 } 00058 } 00059 00060 TEST(dynmem, diff_alignment) 00061 { 00062 uint16_t size = 1000; 00063 mem_stat_t info; 00064 uint8_t *heap = (uint8_t*)malloc(size); 00065 uint8_t *ptr = heap; 00066 CHECK(NULL != heap); 00067 reset_heap_error(); 00068 for (int i=0; i<16; i++) { 00069 ptr++; size--; 00070 ns_dyn_mem_init(ptr, size, &heap_fail_callback, &info); 00071 CHECK(info.heap_sector_size >= (size-72)); 00072 CHECK(!heap_have_failed()); 00073 } 00074 free(heap); 00075 } 00076 00077 TEST(dynmem, ns_dyn_mem_alloc) 00078 { 00079 uint16_t size = 1000; 00080 mem_stat_t info; 00081 void *p[size]; 00082 uint8_t *heap = (uint8_t*)malloc(size); 00083 CHECK(NULL != heap); 00084 reset_heap_error(); 00085 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00086 CHECK(!heap_have_failed()); 00087 int block = 1; 00088 00089 int i; 00090 for (i=0; i<size; i++) { 00091 p[i] = ns_dyn_mem_alloc(block); 00092 if (!p[i]) 00093 break; 00094 } 00095 CHECK(!heap_have_failed()); 00096 CHECK(info.heap_alloc_fail_cnt == 1); 00097 CHECK(info.heap_sector_alloc_cnt == i); 00098 CHECK(info.heap_sector_allocated_bytes == info.heap_sector_allocated_bytes_max); 00099 00100 for (; i>=0; i--) { 00101 ns_dyn_mem_free(p[i]); 00102 } 00103 CHECK(!heap_have_failed()); 00104 CHECK(info.heap_sector_alloc_cnt == 0); 00105 free(heap); 00106 } 00107 00108 TEST(dynmem, ns_dyn_mem_temporary_alloc) 00109 { 00110 uint16_t size = 1000; 00111 mem_stat_t info; 00112 void *p[size]; 00113 uint8_t *heap = (uint8_t*)malloc(size); 00114 CHECK(NULL != heap); 00115 reset_heap_error(); 00116 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00117 CHECK(!heap_have_failed()); 00118 int block = 1; 00119 00120 int i; 00121 for (i=0; i<size; i++) { 00122 p[i] = ns_dyn_mem_temporary_alloc(block); 00123 if (!p[i]) 00124 break; 00125 } 00126 CHECK(!heap_have_failed()); 00127 CHECK(info.heap_alloc_fail_cnt == 1); 00128 CHECK(info.heap_sector_alloc_cnt == i); 00129 CHECK(info.heap_sector_allocated_bytes == info.heap_sector_allocated_bytes_max); 00130 00131 for (; i>=0; i--) { 00132 ns_dyn_mem_free(p[i]); 00133 } 00134 CHECK(!heap_have_failed()); 00135 CHECK(info.heap_sector_alloc_cnt == 0); 00136 free(heap); 00137 } 00138 00139 TEST(dynmem, ns_dyn_mem_temporary_alloc_with_heap_threshold) 00140 { 00141 uint16_t size = 1000; 00142 mem_stat_t info; 00143 void *p1, *p2; 00144 int ret_val; 00145 uint8_t *heap = (uint8_t*)malloc(size); 00146 CHECK(NULL != heap); 00147 reset_heap_error(); 00148 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00149 CHECK(!heap_have_failed()); 00150 00151 // test1: temporary alloc will fail if there is less than 5% heap free 00152 p1 = ns_dyn_mem_temporary_alloc((size-72)*0.96); 00153 CHECK(!heap_have_failed()); 00154 CHECK(p1); 00155 p2 = ns_dyn_mem_temporary_alloc((size-72)*0.02); 00156 CHECK(p2 == NULL); 00157 CHECK(!heap_have_failed()); 00158 CHECK(info.heap_alloc_fail_cnt == 1); 00159 00160 // Test2, disable threshold feature and try p2 allocation again 00161 ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, 0); 00162 p2 = ns_dyn_mem_temporary_alloc((size-72)*0.02); 00163 CHECK(!heap_have_failed()); 00164 CHECK(p2); 00165 ns_dyn_mem_free(p1); 00166 ns_dyn_mem_free(p2); 00167 CHECK(info.heap_alloc_fail_cnt == 1); 00168 CHECK(info.heap_sector_alloc_cnt == 0); 00169 00170 // Test3, enable feature by free heap percentage 00171 ns_dyn_mem_set_temporary_alloc_free_heap_threshold(40, 0); 00172 p1 = ns_dyn_mem_temporary_alloc((size-72)*0.65); 00173 CHECK(p1); 00174 p2 = ns_dyn_mem_temporary_alloc((size-72)*0.10); 00175 CHECK(p2==NULL); 00176 ns_dyn_mem_free(p1); 00177 CHECK(!heap_have_failed()); 00178 CHECK(info.heap_alloc_fail_cnt == 2); 00179 CHECK(info.heap_sector_alloc_cnt == 0); 00180 00181 // Test4, enable feature by free heap amount 00182 ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, 200); 00183 p1 = ns_dyn_mem_temporary_alloc(size-72-100 /*828 bytes */); 00184 CHECK(p1); 00185 p2 = ns_dyn_mem_temporary_alloc(1); 00186 CHECK(p2==NULL); 00187 ns_dyn_mem_free(p1); 00188 00189 // Test5, illegal API parameters 00190 ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, size/2); 00191 CHECK(ret_val==-2); 00192 ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, size*2); 00193 CHECK(ret_val==-2); 00194 ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(51, 0); 00195 CHECK(ret_val==-2); 00196 ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(255, 0); 00197 CHECK(ret_val==-2); 00198 00199 CHECK(!heap_have_failed()); 00200 CHECK(info.heap_alloc_fail_cnt == 3); 00201 CHECK(info.heap_sector_alloc_cnt == 0); 00202 free(heap); 00203 00204 // Test6, feature is disabled if info is not set 00205 heap = (uint8_t*)malloc(size); 00206 CHECK(NULL != heap); 00207 ns_dyn_mem_init(heap, size, &heap_fail_callback, NULL); 00208 ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, 0); 00209 CHECK(ret_val==-1); 00210 CHECK(!heap_have_failed()); 00211 free(heap); 00212 } 00213 00214 TEST(dynmem, test_both_allocs_with_hole_usage) { 00215 uint16_t size = 112; 00216 mem_stat_t info; 00217 void *p[size]; 00218 uint8_t *heap = (uint8_t*)malloc(size); 00219 CHECK(NULL != heap); 00220 reset_heap_error(); 00221 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00222 CHECK(!heap_have_failed()); 00223 00224 void *ptr = ns_dyn_mem_alloc(15); 00225 void *ptr2 = ns_dyn_mem_alloc(4); 00226 00227 ns_dyn_mem_free(ptr); 00228 ns_dyn_mem_free(ptr2); 00229 CHECK(info.heap_sector_allocated_bytes == 0); 00230 00231 void *ptr3 = ns_dyn_mem_temporary_alloc(15); 00232 void *ptr4 = ns_dyn_mem_temporary_alloc(5); 00233 00234 ns_dyn_mem_free(ptr3); 00235 ns_dyn_mem_free(ptr4); 00236 00237 00238 CHECK(info.heap_sector_allocated_bytes == 0); 00239 00240 free(heap); 00241 } 00242 00243 TEST(dynmem, test_temp_alloc_with_skipping_hole) { 00244 uint16_t size = 1000; 00245 mem_stat_t info; 00246 void *p[size]; 00247 uint8_t *heap = (uint8_t*)malloc(size); 00248 CHECK(NULL != heap); 00249 reset_heap_error(); 00250 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00251 CHECK(!heap_have_failed()); 00252 00253 void *ptr1 = ns_dyn_mem_temporary_alloc(15); 00254 void *ptr2 = ns_dyn_mem_temporary_alloc(5); 00255 00256 ns_dyn_mem_free(ptr1); 00257 void *ptr3 = ns_dyn_mem_temporary_alloc(35); 00258 ns_dyn_mem_free(ptr2); 00259 ns_dyn_mem_free(ptr3); 00260 00261 00262 CHECK(info.heap_sector_allocated_bytes == 0); 00263 00264 free(heap); 00265 } 00266 00267 TEST(dynmem, zero_allocate) 00268 { 00269 uint16_t size = 1000; 00270 mem_stat_t info; 00271 uint8_t *heap = (uint8_t*)malloc(size); 00272 uint8_t *ptr = heap; 00273 CHECK(NULL != heap); 00274 reset_heap_error(); 00275 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00276 CHECK(!heap_have_failed()); 00277 ns_dyn_mem_alloc(0); 00278 CHECK(heap_have_failed()); 00279 CHECK(NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID == current_heap_error); 00280 free(heap); 00281 } 00282 00283 TEST(dynmem, too_big) 00284 { 00285 uint16_t size = 1000; 00286 mem_stat_t info; 00287 uint8_t *heap = (uint8_t*)malloc(size); 00288 uint8_t *ptr = heap; 00289 CHECK(NULL != heap); 00290 reset_heap_error(); 00291 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00292 CHECK(!heap_have_failed()); 00293 ns_dyn_mem_alloc(size); 00294 CHECK(heap_have_failed()); 00295 CHECK(NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID == current_heap_error); 00296 free(heap); 00297 } 00298 00299 TEST(dynmem, corrupted_memory) 00300 { 00301 uint16_t size = 1000; 00302 mem_stat_t info; 00303 uint8_t *heap = (uint8_t*)malloc(size); 00304 uint8_t *ptr = heap; 00305 CHECK(NULL != heap); 00306 reset_heap_error(); 00307 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00308 CHECK(!heap_have_failed()); 00309 int *pt = (int *)ns_dyn_mem_alloc(8); 00310 CHECK(!heap_have_failed()); 00311 pt -= 2; 00312 *pt = 0; 00313 ns_dyn_mem_alloc(8); 00314 CHECK(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED == current_heap_error); 00315 free(heap); 00316 } 00317 00318 TEST(dynmem, no_big_enough_sector) { 00319 uint16_t size = 112; 00320 mem_stat_t info; 00321 uint8_t *heap = (uint8_t*)malloc(size); 00322 uint8_t *ptr = heap; 00323 CHECK(NULL != heap); 00324 reset_heap_error(); 00325 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00326 CHECK(!heap_have_failed()); 00327 int *pt = (int *)ns_dyn_mem_alloc(8); 00328 pt = (int *)ns_dyn_mem_alloc(8); 00329 ns_dyn_mem_alloc(8); 00330 ns_dyn_mem_temporary_alloc(8); 00331 ns_dyn_mem_temporary_alloc(8); 00332 00333 ns_dyn_mem_free(pt); 00334 00335 pt = (int *)ns_dyn_mem_temporary_alloc(32); 00336 CHECK(NULL == pt); 00337 free(heap); 00338 } 00339 00340 TEST(dynmem, diff_sizes) 00341 { 00342 uint16_t size = 1000; 00343 mem_stat_t info; 00344 void *p; 00345 uint8_t *heap = (uint8_t*)malloc(size); 00346 CHECK(NULL != heap); 00347 reset_heap_error(); 00348 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00349 CHECK(!heap_have_failed()); 00350 int i; 00351 for (i=1; i<(size-72); i++) { 00352 p = ns_dyn_mem_temporary_alloc(i); 00353 CHECK(p); 00354 ns_dyn_mem_free(p); 00355 CHECK(!heap_have_failed()); 00356 } 00357 CHECK(!heap_have_failed()); 00358 CHECK(info.heap_sector_alloc_cnt == 0); 00359 free(heap); 00360 } 00361 00362 TEST(dynmem, double_free) 00363 { 00364 uint16_t size = 1000; 00365 mem_stat_t info; 00366 uint8_t *heap = (uint8_t*)malloc(size); 00367 void *p; 00368 CHECK(NULL != heap); 00369 reset_heap_error(); 00370 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00371 CHECK(!heap_have_failed()); 00372 p = ns_dyn_mem_alloc(100); 00373 CHECK(p); 00374 ns_dyn_mem_free(p); 00375 CHECK(!heap_have_failed()); 00376 ns_dyn_mem_free(p); 00377 CHECK(heap_have_failed()); 00378 CHECK(NS_DYN_MEM_DOUBLE_FREE == current_heap_error); 00379 free(heap); 00380 } 00381 00382 TEST(dynmem, middle_free) 00383 { 00384 uint16_t size = 1000; 00385 mem_stat_t info; 00386 uint8_t *heap = (uint8_t*)malloc(size); 00387 void *p[3]; 00388 CHECK(NULL != heap); 00389 reset_heap_error(); 00390 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00391 CHECK(!heap_have_failed()); 00392 for (int i=0; i<3; i++) { 00393 p[i] = ns_dyn_mem_temporary_alloc(100); 00394 CHECK(p); 00395 } 00396 ns_dyn_mem_free(p[1]); 00397 CHECK(!heap_have_failed()); 00398 ns_dyn_mem_free(p[0]); 00399 CHECK(!heap_have_failed()); 00400 ns_dyn_mem_free(p[2]); 00401 CHECK(!heap_have_failed()); 00402 free(heap); 00403 } 00404 00405 TEST(dynmem, over_by_one) 00406 { 00407 uint16_t size = 1000; 00408 mem_stat_t info; 00409 uint8_t *heap = (uint8_t*)malloc(size); 00410 uint8_t *p; 00411 CHECK(NULL != heap); 00412 reset_heap_error(); 00413 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00414 CHECK(!heap_have_failed()); 00415 p = (uint8_t *)ns_dyn_mem_alloc(100); 00416 CHECK(p); 00417 p[100] = 0xff; 00418 ns_dyn_mem_free(p); 00419 CHECK(heap_have_failed()); 00420 CHECK(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED == current_heap_error); 00421 free(heap); 00422 } 00423 00424 TEST(dynmem, not_from_this_heap) 00425 { 00426 uint16_t size = 1000; 00427 mem_stat_t info; 00428 uint8_t *heap = (uint8_t*)malloc(size); 00429 uint8_t *p; 00430 CHECK(NULL != heap); 00431 reset_heap_error(); 00432 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00433 CHECK(!heap_have_failed()); 00434 p = (uint8_t *)ns_dyn_mem_alloc(100); 00435 CHECK(p); 00436 ns_dyn_mem_free(&heap[-1]); 00437 CHECK(heap_have_failed()); 00438 CHECK(NS_DYN_MEM_POINTER_NOT_VALID == current_heap_error); 00439 reset_heap_error(); 00440 ns_dyn_mem_free(&heap[1001]); 00441 CHECK(heap_have_failed()); 00442 CHECK(NS_DYN_MEM_POINTER_NOT_VALID == current_heap_error); 00443 free(heap); 00444 } 00445 00446 TEST(dynmem, free_on_empty_heap) 00447 { 00448 uint16_t size = 1000; 00449 mem_stat_t info; 00450 uint8_t *heap = (uint8_t*)malloc(size); 00451 uint8_t *p; 00452 CHECK(NULL != heap); 00453 reset_heap_error(); 00454 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00455 CHECK(!heap_have_failed()); 00456 ns_dyn_mem_free(&heap[1]); 00457 CHECK(heap_have_failed()); 00458 CHECK(NS_DYN_MEM_POINTER_NOT_VALID == current_heap_error); 00459 free(heap); 00460 } 00461 00462 TEST(dynmem, not_negative_stats) 00463 { 00464 uint16_t size = 1000; 00465 mem_stat_t info; 00466 uint8_t *heap = (uint8_t*)malloc(size); 00467 void *p; 00468 CHECK(NULL != heap); 00469 reset_heap_error(); 00470 ns_dyn_mem_init(heap, size, &heap_fail_callback, &info); 00471 CHECK(!heap_have_failed()); 00472 CHECK(info.heap_sector_allocated_bytes == 0); 00473 ns_dyn_mem_alloc(8); 00474 p = ns_dyn_mem_alloc(8); 00475 ns_dyn_mem_alloc(8); 00476 CHECK(info.heap_sector_allocated_bytes >= 24); 00477 int16_t last_value = info.heap_sector_allocated_bytes; 00478 ns_dyn_mem_free(p); 00479 CHECK(info.heap_sector_allocated_bytes >= 16); 00480 CHECK(info.heap_sector_allocated_bytes < last_value); 00481 last_value = info.heap_sector_allocated_bytes; 00482 for (int i=0; i<10; i++) { 00483 p = ns_dyn_mem_alloc(1); 00484 ns_dyn_mem_free(p); 00485 } 00486 CHECK(info.heap_sector_allocated_bytes == last_value); 00487 free(heap); 00488 } 00489 00490 TEST(dynmem, test_invalid_pointer_freed) { 00491 uint16_t size = 92; 00492 uint8_t *heap = (uint8_t*)malloc(size); 00493 CHECK(NULL != heap); 00494 reset_heap_error(); 00495 ns_dyn_mem_init(heap, size, &heap_fail_callback, NULL); 00496 int *ptr = (int *)ns_dyn_mem_alloc(4); 00497 ptr--; 00498 *ptr = 16; 00499 ptr++; 00500 ns_dyn_mem_free(ptr); 00501 CHECK(NS_DYN_MEM_POINTER_NOT_VALID == current_heap_error); 00502 00503 free(heap); 00504 } 00505 00506 TEST(dynmem, test_merge_corrupted_previous_block) { 00507 uint16_t size = 1000; 00508 uint8_t *heap = (uint8_t*)malloc(size); 00509 uint8_t *p; 00510 CHECK(NULL != heap); 00511 reset_heap_error(); 00512 ns_dyn_mem_init(heap, size, &heap_fail_callback, NULL); 00513 CHECK(!heap_have_failed()); 00514 00515 int *ptr = (int *)ns_dyn_mem_alloc(4); 00516 int *ptr2 = (int *)ns_dyn_mem_alloc(4); 00517 ns_dyn_mem_free(ptr); 00518 ptr = ptr2 - 2; 00519 *ptr = -2; 00520 ns_dyn_mem_free(ptr2); 00521 00522 CHECK(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED == current_heap_error); 00523 00524 free(heap); 00525 } 00526 00527 TEST(dynmem, test_free_corrupted_next_block) { 00528 uint16_t size = 1000; 00529 uint8_t *heap = (uint8_t*)malloc(size); 00530 uint8_t *p; 00531 CHECK(NULL != heap); 00532 reset_heap_error(); 00533 ns_dyn_mem_init(heap, size, &heap_fail_callback, NULL); 00534 CHECK(!heap_have_failed()); 00535 00536 int *ptr = (int *)ns_dyn_mem_temporary_alloc(4); 00537 int *ptr2 = (int *)ns_dyn_mem_temporary_alloc(4); 00538 ns_dyn_mem_free(ptr); 00539 ptr = ptr2 + 2; 00540 *ptr = -2; 00541 ns_dyn_mem_free(ptr2); 00542 00543 CHECK(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED == current_heap_error); 00544 00545 free(heap); 00546 } 00547 00548 //NOTE! This test must be last! 00549 TEST(dynmem, uninitialized_test){ 00550 void *p = ns_dyn_mem_alloc(4); 00551 ns_dyn_mem_free(p); 00552 CHECK(p == NULL); 00553 }
Generated on Tue Aug 9 2022 00:37:05 by
1.7.2