Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dynmemtest.cpp Source File

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 <string.h>
00021 #include "error_callback.h"
00022 
00023 // hardcoded amount of regions, keep in sync with nsdynmemlib "REGION_COUNT"
00024 #define NS_MEM_REGION_CNT  (3)
00025 // size of nsdynmemlib book keeping data ns_mem_book_t
00026 #define NS_MEM_BOOK_SIZE (64 + (NS_MEM_REGION_CNT-1)*2*sizeof(ns_mem_heap_size_t))
00027 #define NS_MEM_BOOK_SIZE_WITH_HOLE (NS_MEM_BOOK_SIZE + 2*sizeof(ns_mem_heap_size_t))
00028 
00029 int ret_val;
00030 
00031 TEST_GROUP(dynmem)
00032 {
00033     void setup() {
00034         reset_heap_error();
00035     }
00036 
00037     void teardown() {
00038     }
00039 };
00040 
00041 TEST(dynmem, init)
00042 {
00043     uint16_t size = 1000;
00044     uint8_t *heap = (uint8_t *)malloc(size);
00045     CHECK(NULL != heap);
00046     mem_stat_t info;
00047     reset_heap_error();
00048     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00049     CHECK(info.heap_sector_size == (size - NS_MEM_BOOK_SIZE));
00050     CHECK(!heap_have_failed());
00051     CHECK(ns_dyn_mem_get_mem_stat() == &info);
00052     free(heap);
00053 }
00054 
00055 TEST(dynmem, different_sizes)
00056 {
00057     reset_heap_error();
00058     for (uint16_t size = 1000; size < 32768; size++) {
00059         mem_stat_t info;
00060         uint8_t *heap = (uint8_t *)malloc(size);
00061         ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00062         CHECK(info.heap_sector_size >= (size - NS_MEM_BOOK_SIZE_WITH_HOLE));
00063         CHECK(!heap_have_failed());
00064         CHECK(ns_dyn_mem_alloc(10));
00065         free(heap);
00066     }
00067 }
00068 
00069 TEST(dynmem, diff_alignment)
00070 {
00071     uint16_t size = 1000;
00072     mem_stat_t info;
00073     uint8_t *heap = (uint8_t *)malloc(size);
00074     uint8_t *ptr = heap;
00075     CHECK(NULL != heap);
00076     reset_heap_error();
00077     for (int i = 0; i < 16; i++) {
00078         ptr++;
00079         size--;
00080         ns_dyn_mem_init(ptr, size, &heap_fail_callback, &info);
00081         CHECK(info.heap_sector_size >= (size - NS_MEM_BOOK_SIZE_WITH_HOLE));
00082         CHECK(!heap_have_failed());
00083     }
00084     free(heap);
00085 }
00086 
00087 TEST(dynmem, heap_add_region_api)
00088 {
00089 #if (NS_MEM_REGION_CNT  > 1)
00090     uint16_t size = 1000;
00091     uint8_t *heap = (uint8_t *)malloc(size);
00092     uint8_t *heap2add = (uint8_t *)malloc(size);
00093     uint8_t *heap2add2 = (uint8_t *)malloc(size);
00094 
00095     mem_stat_t info;
00096 
00097     reset_heap_error();
00098     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00099     CHECK(info.heap_sector_size == (size - NS_MEM_BOOK_SIZE))
00100 
00101     // param error, return <0
00102     ret_val = ns_dyn_mem_region_add(NULL, size);
00103     CHECK(0 != ret_val);
00104 
00105     // param error, return <0
00106     ret_val = ns_dyn_mem_region_add(heap2add, 0);
00107     CHECK(0 != ret_val);
00108 
00109     // param error, return <0
00110     ret_val = ns_dyn_mem_region_add(heap2add, 8);
00111     CHECK(0 != ret_val);
00112 
00113     // All OK - success, 1 reserved for bookkeeping
00114     ret_val = ns_dyn_mem_region_add(heap2add, size);
00115     CHECK(0 == ret_val);
00116 
00117     CHECK(!heap_have_failed());
00118     CHECK(ns_dyn_mem_get_mem_stat() == &info);
00119     CHECK(info.heap_sector_size == (2 * size - NS_MEM_BOOK_SIZE))
00120 
00121     // All OK - add more memory again success
00122     ret_val = ns_dyn_mem_region_add(heap2add2, size);
00123     CHECK(0 == ret_val);
00124     CHECK(info.heap_sector_size == (3 * size - NS_MEM_BOOK_SIZE))
00125 
00126     free(heap);
00127     free(heap2add);
00128     free(heap2add2);
00129 #endif
00130 }
00131 
00132 TEST(dynmem, heap_add_region)
00133 {
00134 #if (NS_MEM_REGION_CNT  > 1 && NS_MEM_REGION_CNT < 4)
00135     uint16_t size = 200;
00136     uint8_t *heap = (uint8_t *)malloc(size);
00137     uint8_t *heap_add1 = (uint8_t *)malloc(size);
00138     uint8_t *heap_add2 = (uint8_t *)malloc(size);
00139     uint8_t *heap_add3 = (uint8_t *)malloc(size);
00140     void *p[size * 4];
00141 
00142     mem_stat_t info;
00143 
00144     reset_heap_error();
00145     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00146     CHECK(info.heap_sector_size == (size - NS_MEM_BOOK_SIZE))
00147 
00148     ret_val = ns_dyn_mem_region_add(heap_add1, size);
00149     CHECK(0 == ret_val);
00150 
00151     // region already added, therefore fails
00152     ret_val = ns_dyn_mem_region_add(heap_add1, size);
00153     CHECK(0 != ret_val);
00154 
00155     ret_val = ns_dyn_mem_region_add(heap_add3, size);
00156     CHECK(0 == ret_val);
00157 
00158     // There is room for 2 additional regions , therfore fails
00159     ret_val = ns_dyn_mem_region_add(heap_add2, size);
00160     CHECK(0 != ret_val);
00161 
00162     CHECK(info.heap_sector_size == (3 * size - NS_MEM_BOOK_SIZE))
00163 
00164     CHECK(!heap_have_failed());
00165     int block_size = 10;
00166 
00167     int i;
00168     for (i = 0; i < size * 3; i++) {
00169         p[i] = ns_dyn_mem_alloc(block_size);
00170         if (p[i]) {
00171             memset(p[i], 0xb0, block_size);
00172         } else {
00173             break;
00174         }
00175     }
00176     CHECK(!heap_have_failed());
00177     CHECK(info.heap_alloc_fail_cnt == 1);
00178     CHECK(info.heap_sector_alloc_cnt == i);
00179     CHECK(info.heap_sector_allocated_bytes == info.heap_sector_allocated_bytes_max);
00180 
00181     for (; i >= 0; i--) {
00182         ns_dyn_mem_free(p[i]);
00183     }
00184     CHECK(!heap_have_failed());
00185     CHECK(info.heap_sector_alloc_cnt == 0);
00186 
00187     free(heap);
00188     free(heap_add1);
00189     free(heap_add2);
00190     free(heap_add3);
00191 #endif
00192 }
00193 
00194 TEST(dynmem, heap_add_region_randomized)
00195 {
00196     /**
00197      * Test:
00198      *  - multiple regions
00199      *  - regions are not from continous
00200      *  - all memory allocated from heap
00201      *  - blocks are deallocated in random order
00202      */
00203 #if (NS_MEM_REGION_CNT  > 1)
00204     uint32_t size = 200000;
00205     uint8_t *heap_ptr[NS_MEM_REGION_CNT];  // heap memory regions
00206     void *ptrs[size * NS_MEM_REGION_CNT / 4] = {0}; // allocated memory pointers
00207     mem_stat_t info;
00208     uint8_t *gap_between_regions = NULL;
00209 
00210     for (int cnt = 0; cnt < NS_MEM_REGION_CNT; cnt++) {
00211         heap_ptr[cnt] = (uint8_t *)malloc(size);
00212         if (gap_between_regions) {
00213             free(gap_between_regions);
00214         }
00215         gap_between_regions = (uint8_t *)malloc(size / 3);
00216     }
00217     free(gap_between_regions);
00218 
00219     reset_heap_error();
00220     ns_dyn_mem_init(heap_ptr[0], size, &heap_fail_callback, &info);
00221     CHECK(info.heap_sector_size == (size - NS_MEM_BOOK_SIZE))
00222 
00223     for (int cnt = NS_MEM_REGION_CNT - 1; cnt > 0; cnt--) {
00224         ret_val = ns_dyn_mem_region_add(heap_ptr[cnt], size);
00225         CHECK(0 == ret_val);
00226     }
00227 
00228     CHECK(info.heap_sector_size == (NS_MEM_REGION_CNT * size - NS_MEM_BOOK_SIZE))
00229 
00230     CHECK(!heap_have_failed());
00231 
00232     srand(time(NULL));
00233     int block_size;
00234     int i;
00235     for (i = 0; i < size * NS_MEM_REGION_CNT; i++) {
00236         // allocate huge amount of small blocks until allocation fails
00237         block_size = (rand() % 4) + 1;
00238         ptrs[i] = ns_dyn_mem_alloc(block_size);
00239         if (ptrs[i]) {
00240             memset(ptrs[i], 0xb0, block_size);
00241         } else {
00242             break;
00243         }
00244     }
00245     CHECK(!heap_have_failed());
00246     CHECK(info.heap_alloc_fail_cnt == 1);
00247     CHECK(info.heap_sector_alloc_cnt == i);
00248     CHECK(info.heap_sector_allocated_bytes == info.heap_sector_allocated_bytes_max);
00249 
00250     // free allocated memmory blocks in random order
00251     int block_id;
00252     do {
00253         block_id = (rand() % i);
00254         if (ptrs[block_id] != NULL) {
00255             ns_dyn_mem_free(ptrs[block_id]);
00256             ptrs[block_id] = NULL;
00257         }
00258     } while (info.heap_sector_alloc_cnt != 0);
00259 
00260 
00261     CHECK(!heap_have_failed());
00262     CHECK(info.heap_sector_alloc_cnt == 0);
00263     CHECK(info.heap_sector_allocated_bytes == 0);
00264 
00265     for (int cnt = 0; cnt < NS_MEM_REGION_CNT; cnt++) {
00266         free(heap_ptr[cnt]);
00267     }
00268 #endif
00269 }
00270 
00271 TEST(dynmem, ns_dyn_mem_alloc)
00272 {
00273     uint16_t size = 1000;
00274     mem_stat_t info;
00275     void *p[size];
00276     uint8_t *heap = (uint8_t *)malloc(size);
00277     CHECK(NULL != heap);
00278     reset_heap_error();
00279     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00280     CHECK(!heap_have_failed());
00281     int block = 1;
00282 
00283     int i;
00284     for (i = 0; i < size; i++) {
00285         p[i] = ns_dyn_mem_alloc(block);
00286 
00287         if (p[i]) {
00288             memset(p[i], 0xb0, block);
00289         } else {
00290             break;
00291         }
00292     }
00293     CHECK(!heap_have_failed());
00294     CHECK(info.heap_alloc_fail_cnt == 1);
00295     CHECK(info.heap_sector_alloc_cnt == i);
00296     CHECK(info.heap_sector_allocated_bytes == info.heap_sector_allocated_bytes_max);
00297 
00298     for (; i >= 0; i--) {
00299         ns_dyn_mem_free(p[i]);
00300     }
00301     CHECK(!heap_have_failed());
00302     CHECK(info.heap_sector_alloc_cnt == 0);
00303     free(heap);
00304 }
00305 
00306 TEST(dynmem, ns_dyn_mem_temporary_alloc)
00307 {
00308     uint16_t size = 1000;
00309     mem_stat_t info;
00310     void *p[size];
00311     uint8_t *heap = (uint8_t *)malloc(size);
00312     CHECK(NULL != heap);
00313     reset_heap_error();
00314     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00315     CHECK(!heap_have_failed());
00316     int block = 1;
00317 
00318     int i;
00319     for (i = 0; i < size; i++) {
00320         p[i] = ns_dyn_mem_temporary_alloc(block);
00321         if (!p[i]) {
00322             break;
00323         }
00324     }
00325     CHECK(!heap_have_failed());
00326     CHECK(info.heap_alloc_fail_cnt == 1);
00327     CHECK(info.heap_sector_alloc_cnt == i);
00328     CHECK(info.heap_sector_allocated_bytes == info.heap_sector_allocated_bytes_max);
00329 
00330     for (; i >= 0; i--) {
00331         ns_dyn_mem_free(p[i]);
00332     }
00333     CHECK(!heap_have_failed());
00334     CHECK(info.heap_sector_alloc_cnt == 0);
00335     free(heap);
00336 }
00337 
00338 TEST(dynmem, ns_dyn_mem_temporary_alloc_with_heap_threshold)
00339 {
00340     uint16_t size = 1000;
00341     mem_stat_t info;
00342     void *p1, *p2;
00343     int ret_val;
00344     uint8_t *heap = (uint8_t *)malloc(size);
00345     CHECK(NULL != heap);
00346     reset_heap_error();
00347     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00348     CHECK(!heap_have_failed());
00349 
00350     // test1: temporary alloc will fail if there is less than 5% heap free
00351     p1 = ns_dyn_mem_temporary_alloc((size - NS_MEM_BOOK_SIZE_WITH_HOLE) * 0.96);
00352     CHECK(!heap_have_failed());
00353     CHECK(p1);
00354     p2 = ns_dyn_mem_temporary_alloc((size - NS_MEM_BOOK_SIZE_WITH_HOLE) * 0.02);
00355     CHECK(p2 == NULL);
00356     CHECK(!heap_have_failed());
00357     CHECK(info.heap_alloc_fail_cnt == 1);
00358 
00359     // Test2, disable threshold feature and try p2 allocation again
00360     ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, 0);
00361     p2 = ns_dyn_mem_temporary_alloc((size - NS_MEM_BOOK_SIZE_WITH_HOLE) * 0.02);
00362     CHECK(!heap_have_failed());
00363     CHECK(p2);
00364     ns_dyn_mem_free(p1);
00365     ns_dyn_mem_free(p2);
00366     CHECK(info.heap_alloc_fail_cnt == 1);
00367     CHECK(info.heap_sector_alloc_cnt == 0);
00368 
00369     // Test3, enable feature by free heap percentage
00370     ns_dyn_mem_set_temporary_alloc_free_heap_threshold(40, 0);
00371     p1 = ns_dyn_mem_temporary_alloc((size - NS_MEM_BOOK_SIZE_WITH_HOLE) * 0.65);
00372     CHECK(p1);
00373     p2 = ns_dyn_mem_temporary_alloc((size - NS_MEM_BOOK_SIZE_WITH_HOLE) * 0.10);
00374     CHECK(p2 == NULL);
00375     ns_dyn_mem_free(p1);
00376     CHECK(!heap_have_failed());
00377     CHECK(info.heap_alloc_fail_cnt == 2);
00378     CHECK(info.heap_sector_alloc_cnt == 0);
00379 
00380     // Test4, enable feature by free heap amount
00381     ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, 200);
00382     p1 = ns_dyn_mem_temporary_alloc(size - NS_MEM_BOOK_SIZE_WITH_HOLE - 100);
00383     CHECK(p1);
00384     p2 = ns_dyn_mem_temporary_alloc(1);
00385     CHECK(p2 == NULL);
00386     ns_dyn_mem_free(p1);
00387 
00388     // Test5, illegal API parameters
00389     ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, size / 2);
00390     CHECK(ret_val == -2);
00391     ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, size * 2);
00392     CHECK(ret_val == -2);
00393     ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(51, 0);
00394     CHECK(ret_val == -2);
00395     ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(255, 0);
00396     CHECK(ret_val == -2);
00397 
00398     CHECK(!heap_have_failed());
00399     CHECK(info.heap_alloc_fail_cnt == 3);
00400     CHECK(info.heap_sector_alloc_cnt == 0);
00401     free(heap);
00402 
00403     // Test6, feature is disabled if info is not set
00404     heap = (uint8_t *)malloc(size);
00405     CHECK(NULL != heap);
00406     ns_dyn_mem_init(heap, size, &heap_fail_callback, NULL);
00407     ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, 0);
00408     CHECK(ret_val == -1);
00409     CHECK(!heap_have_failed());
00410     free(heap);
00411 }
00412 
00413 TEST(dynmem, test_both_allocs_with_hole_usage)
00414 {
00415     uint16_t size = NS_MEM_BOOK_SIZE_WITH_HOLE + 15 + 5;
00416     mem_stat_t info;
00417     void *p[size];
00418     uint8_t *heap = (uint8_t *)malloc(size);
00419     CHECK(NULL != heap);
00420     reset_heap_error();
00421     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00422     CHECK(!heap_have_failed());
00423 
00424     void *ptr = ns_dyn_mem_alloc(15);
00425     void *ptr2 = ns_dyn_mem_alloc(4);
00426 
00427     ns_dyn_mem_free(ptr);
00428     ns_dyn_mem_free(ptr2);
00429     CHECK(info.heap_sector_allocated_bytes == 0);
00430 
00431     void *ptr3 = ns_dyn_mem_temporary_alloc(15);
00432     void *ptr4 = ns_dyn_mem_temporary_alloc(5);
00433 
00434     ns_dyn_mem_free(ptr3);
00435     ns_dyn_mem_free(ptr4);
00436 
00437 
00438     CHECK(info.heap_sector_allocated_bytes == 0);
00439 
00440     free(heap);
00441 }
00442 
00443 TEST(dynmem, test_temp_alloc_with_skipping_hole)
00444 {
00445     uint16_t size = 1000;
00446     mem_stat_t info;
00447     void *p[size];
00448     uint8_t *heap = (uint8_t *)malloc(size);
00449     CHECK(NULL != heap);
00450     reset_heap_error();
00451     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00452     CHECK(!heap_have_failed());
00453 
00454     void *ptr1 = ns_dyn_mem_temporary_alloc(15);
00455     void *ptr2 = ns_dyn_mem_temporary_alloc(5);
00456 
00457     ns_dyn_mem_free(ptr1);
00458     void *ptr3 = ns_dyn_mem_temporary_alloc(35);
00459     ns_dyn_mem_free(ptr2);
00460     ns_dyn_mem_free(ptr3);
00461 
00462 
00463     CHECK(info.heap_sector_allocated_bytes == 0);
00464 
00465     free(heap);
00466 }
00467 
00468 TEST(dynmem, zero_allocate)
00469 {
00470     uint16_t size = 1000;
00471     mem_stat_t info;
00472     uint8_t *heap = (uint8_t *)malloc(size);
00473     uint8_t *ptr = heap;
00474     CHECK(NULL != heap);
00475     reset_heap_error();
00476     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00477     CHECK(!heap_have_failed());
00478     ns_dyn_mem_alloc(0);
00479     CHECK(heap_have_failed());
00480     CHECK(NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID == current_heap_error);
00481     free(heap);
00482 }
00483 
00484 TEST(dynmem, too_big)
00485 {
00486     uint16_t size = 1000;
00487     mem_stat_t info;
00488     uint8_t *heap = (uint8_t *)malloc(size);
00489     uint8_t *ptr = heap;
00490     CHECK(NULL != heap);
00491     reset_heap_error();
00492     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00493     CHECK(!heap_have_failed());
00494     ns_dyn_mem_alloc(size);
00495     CHECK(heap_have_failed());
00496     CHECK(NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID == current_heap_error);
00497     free(heap);
00498 }
00499 
00500 TEST(dynmem, corrupted_memory)
00501 {
00502     uint16_t size = 1000;
00503     mem_stat_t info;
00504     uint8_t *heap = (uint8_t *)malloc(size);
00505     uint8_t *ptr = heap;
00506     CHECK(NULL != heap);
00507     reset_heap_error();
00508     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00509     CHECK(!heap_have_failed());
00510     int *pt = (int *)ns_dyn_mem_alloc(8);
00511     CHECK(!heap_have_failed());
00512     pt -= 2;
00513     *pt = 0;
00514     ns_dyn_mem_alloc(8);
00515     CHECK(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED == current_heap_error);
00516     free(heap);
00517 }
00518 
00519 TEST(dynmem, no_big_enough_sector)
00520 {
00521     uint16_t size = NS_MEM_BOOK_SIZE_WITH_HOLE + (5 * 8);
00522     mem_stat_t info;
00523     uint8_t *heap = (uint8_t *)malloc(size);
00524     uint8_t *ptr = heap;
00525     CHECK(NULL != heap);
00526     reset_heap_error();
00527     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00528     CHECK(!heap_have_failed());
00529     int *pt = (int *)ns_dyn_mem_alloc(8);
00530     pt = (int *)ns_dyn_mem_alloc(8);
00531     ns_dyn_mem_alloc(8);
00532     ns_dyn_mem_temporary_alloc(8);
00533     ns_dyn_mem_temporary_alloc(8);
00534 
00535     ns_dyn_mem_free(pt);
00536 
00537     pt = (int *)ns_dyn_mem_temporary_alloc(32);
00538     CHECK(NULL == pt);
00539     free(heap);
00540 }
00541 
00542 TEST(dynmem, diff_sizes)
00543 {
00544     uint16_t size = 1000;
00545     mem_stat_t info;
00546     void *p;
00547     uint8_t *heap = (uint8_t *)malloc(size);
00548     CHECK(NULL != heap);
00549     reset_heap_error();
00550     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00551     CHECK(!heap_have_failed());
00552     int i;
00553     for (i = 1; i < (size - NS_MEM_BOOK_SIZE_WITH_HOLE); i++) {
00554         p = ns_dyn_mem_temporary_alloc(i);
00555         CHECK(p);
00556         ns_dyn_mem_free(p);
00557         CHECK(!heap_have_failed());
00558     }
00559     CHECK(!heap_have_failed());
00560     CHECK(info.heap_sector_alloc_cnt == 0);
00561     free(heap);
00562 }
00563 
00564 TEST(dynmem, double_free)
00565 {
00566     uint16_t size = 1000;
00567     mem_stat_t info;
00568     uint8_t *heap = (uint8_t *)malloc(size);
00569     void *p;
00570     CHECK(NULL != heap);
00571     reset_heap_error();
00572     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00573     CHECK(!heap_have_failed());
00574     p = ns_dyn_mem_alloc(100);
00575     CHECK(p);
00576     ns_dyn_mem_free(p);
00577     CHECK(!heap_have_failed());
00578     ns_dyn_mem_free(p);
00579     CHECK(heap_have_failed());
00580     CHECK(NS_DYN_MEM_DOUBLE_FREE == current_heap_error);
00581     free(heap);
00582 }
00583 
00584 TEST(dynmem, middle_free)
00585 {
00586     uint16_t size = 1000;
00587     mem_stat_t info;
00588     uint8_t *heap = (uint8_t *)malloc(size);
00589     void *p[3];
00590     CHECK(NULL != heap);
00591     reset_heap_error();
00592     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00593     CHECK(!heap_have_failed());
00594     for (int i = 0; i < 3; i++) {
00595         p[i] = ns_dyn_mem_temporary_alloc(100);
00596         CHECK(p);
00597     }
00598     ns_dyn_mem_free(p[1]);
00599     CHECK(!heap_have_failed());
00600     ns_dyn_mem_free(p[0]);
00601     CHECK(!heap_have_failed());
00602     ns_dyn_mem_free(p[2]);
00603     CHECK(!heap_have_failed());
00604     free(heap);
00605 }
00606 
00607 TEST(dynmem, over_by_one)
00608 {
00609     uint16_t size = 1000;
00610     mem_stat_t info;
00611     uint8_t *heap = (uint8_t *)malloc(size);
00612     uint8_t *p;
00613     CHECK(NULL != heap);
00614     reset_heap_error();
00615     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00616     CHECK(!heap_have_failed());
00617     p = (uint8_t *)ns_dyn_mem_alloc(100);
00618     CHECK(p);
00619     p[100] = 0xff;
00620     ns_dyn_mem_free(p);
00621     CHECK(heap_have_failed());
00622     CHECK(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED == current_heap_error);
00623     free(heap);
00624 }
00625 
00626 TEST(dynmem, not_from_this_heap)
00627 {
00628     uint16_t size = 1000;
00629     mem_stat_t info;
00630     uint8_t *heap = (uint8_t *)malloc(size);
00631     uint8_t *p;
00632     CHECK(NULL != heap);
00633     reset_heap_error();
00634     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00635     CHECK(!heap_have_failed());
00636     p = (uint8_t *)ns_dyn_mem_alloc(100);
00637     CHECK(p);
00638     ns_dyn_mem_free(&heap[-1]);
00639     CHECK(heap_have_failed());
00640     CHECK(NS_DYN_MEM_POINTER_NOT_VALID == current_heap_error);
00641     reset_heap_error();
00642     ns_dyn_mem_free(&heap[1001]);
00643     CHECK(heap_have_failed());
00644     CHECK(NS_DYN_MEM_POINTER_NOT_VALID == current_heap_error);
00645     free(heap);
00646 }
00647 
00648 TEST(dynmem, free_on_empty_heap)
00649 {
00650     uint16_t size = 1000;
00651     mem_stat_t info;
00652     uint8_t *heap = (uint8_t *)malloc(size);
00653     uint8_t *p;
00654     CHECK(NULL != heap);
00655     reset_heap_error();
00656     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00657     CHECK(!heap_have_failed());
00658     ns_dyn_mem_free(&heap[1]);
00659     CHECK(heap_have_failed());
00660     CHECK(NS_DYN_MEM_POINTER_NOT_VALID == current_heap_error);
00661     free(heap);
00662 }
00663 
00664 TEST(dynmem, not_negative_stats)
00665 {
00666     uint16_t size = 1000;
00667     mem_stat_t info;
00668     uint8_t *heap = (uint8_t *)malloc(size);
00669     void *p;
00670     CHECK(NULL != heap);
00671     reset_heap_error();
00672     ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
00673     CHECK(!heap_have_failed());
00674     CHECK(info.heap_sector_allocated_bytes == 0);
00675     ns_dyn_mem_alloc(8);
00676     p = ns_dyn_mem_alloc(8);
00677     ns_dyn_mem_alloc(8);
00678     CHECK(info.heap_sector_allocated_bytes >= 24);
00679     int16_t last_value = info.heap_sector_allocated_bytes;
00680     ns_dyn_mem_free(p);
00681     CHECK(info.heap_sector_allocated_bytes >= 16);
00682     CHECK(info.heap_sector_allocated_bytes < last_value);
00683     last_value = info.heap_sector_allocated_bytes;
00684     for (int i = 0; i < 10; i++) {
00685         p = ns_dyn_mem_alloc(1);
00686         ns_dyn_mem_free(p);
00687     }
00688     CHECK(info.heap_sector_allocated_bytes == last_value);
00689     free(heap);
00690 }
00691 
00692 TEST(dynmem, test_invalid_pointer_freed)
00693 {
00694     uint16_t size = 1000;
00695     uint8_t *heap = (uint8_t *)malloc(size);
00696     CHECK(NULL != heap);
00697     reset_heap_error();
00698     ns_dyn_mem_init(heap, size, &heap_fail_callback, NULL);
00699     int *ptr = (int *)ns_dyn_mem_alloc(4);
00700     ptr--;
00701     *ptr = 16;
00702     ptr++;
00703     ns_dyn_mem_free(ptr);
00704     CHECK(NS_DYN_MEM_POINTER_NOT_VALID == current_heap_error);
00705 
00706     free(heap);
00707 }
00708 
00709 TEST(dynmem, test_merge_corrupted_previous_block)
00710 {
00711     uint16_t size = 1000;
00712     uint8_t *heap = (uint8_t *)malloc(size);
00713     uint8_t *p;
00714     CHECK(NULL != heap);
00715     reset_heap_error();
00716     ns_dyn_mem_init(heap, size, &heap_fail_callback, NULL);
00717     CHECK(!heap_have_failed());
00718 
00719     int *ptr = (int *)ns_dyn_mem_alloc(4);
00720     int *ptr2 = (int *)ns_dyn_mem_alloc(4);
00721     ns_dyn_mem_free(ptr);
00722     ptr = ptr2 - 2;
00723     *ptr = -2;
00724     ns_dyn_mem_free(ptr2);
00725 
00726     CHECK(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED == current_heap_error);
00727 
00728     free(heap);
00729 }
00730 
00731 TEST(dynmem, test_free_corrupted_next_block)
00732 {
00733     uint16_t size = 1000;
00734     uint8_t *heap = (uint8_t *)malloc(size);
00735     uint8_t *p;
00736     CHECK(NULL != heap);
00737     reset_heap_error();
00738     ns_dyn_mem_init(heap, size, &heap_fail_callback, NULL);
00739     CHECK(!heap_have_failed());
00740 
00741     int *ptr = (int *)ns_dyn_mem_temporary_alloc(4);
00742     int *ptr2 = (int *)ns_dyn_mem_temporary_alloc(4);
00743     ns_dyn_mem_free(ptr);
00744     ptr = ptr2 + 2;
00745     *ptr = -2;
00746     ns_dyn_mem_free(ptr2);
00747 
00748     CHECK(NS_DYN_MEM_HEAP_SECTOR_CORRUPTED == current_heap_error);
00749 
00750     free(heap);
00751 }
00752 
00753 //NOTE! This test must be last!
00754 TEST(dynmem, uninitialized_test)
00755 {
00756     void *p = ns_dyn_mem_alloc(4);
00757     ns_dyn_mem_free(p);
00758     CHECK(p == NULL);
00759 }