takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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 "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 }