ChibiOS/RT Architecture - Reference Manual - Guides |
00001 /* 00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. 00003 00004 This file is part of ChibiOS/RT. 00005 00006 ChibiOS/RT is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 ChibiOS/RT is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 00019 --- 00020 00021 A special exception to the GPL can be applied should you wish to distribute 00022 a combined work that includes ChibiOS/RT, without being obliged to provide 00023 the source code for any proprietary components. See the file exception.txt 00024 for full details of how and when the exception can be applied. 00025 */ 00026 00027 #include "ch.h" 00028 #include "test.h" 00029 00030 /** 00031 * @page test_heap Memory Heap test 00032 * 00033 * File: @ref testheap.c 00034 * 00035 * <h2>Description</h2> 00036 * This module implements the test sequence for the @ref heaps subsystem. 00037 * 00038 * <h2>Objective</h2> 00039 * Objective of the test module is to cover 100% of the @ref heaps subsystem. 00040 * 00041 * <h2>Preconditions</h2> 00042 * The module requires the following kernel options: 00043 * - @p CH_USE_HEAP 00044 * . 00045 * In case some of the required options are not enabled then some or all tests 00046 * may be skipped. 00047 * 00048 * <h2>Test Cases</h2> 00049 * - @subpage test_heap_001 00050 * . 00051 * @file testheap.c 00052 * @brief Heap test source file 00053 * @file testheap.h 00054 * @brief Heap header file 00055 */ 00056 00057 #if CH_USE_HEAP 00058 00059 #define SIZE 16 00060 00061 static MemoryHeap test_heap; 00062 00063 /** 00064 * @page test_heap_001 Allocation and fragmentation test 00065 * 00066 * <h2>Description</h2> 00067 * Series of allocations/deallocations are performed in carefully designed 00068 * sequences in order to stimulate all the possible code paths inside the 00069 * allocator.<br> 00070 * The test expects to find the heap back to the initial status after each 00071 * sequence. 00072 */ 00073 00074 static char *heap1_gettest(void) { 00075 00076 return "Heap, allocation and fragmentation test"; 00077 } 00078 00079 static void heap1_setup(void) { 00080 00081 chHeapInit(&test_heap, test.buffer, sizeof(union test_buffers)); 00082 } 00083 00084 static void heap1_execute(void) { 00085 void *p1, *p2, *p3; 00086 size_t n, sz; 00087 00088 /* Unrelated, for coverage only.*/ 00089 (void)chCoreStatus(); 00090 00091 /* 00092 * Test on the default heap in order to cover the core allocator at 00093 * least one time. 00094 */ 00095 (void)chHeapStatus(NULL, &sz); 00096 p1 = chHeapAlloc(NULL, SIZE); 00097 test_assert(1, p1 != NULL, "allocation failed"); 00098 chHeapFree(p1); 00099 p1 = chHeapAlloc(NULL, (size_t)-256); 00100 test_assert(2, p1 == NULL, "allocation not failed"); 00101 00102 /* Initial local heap state.*/ 00103 (void)chHeapStatus(&test_heap, &sz); 00104 00105 /* Same order.*/ 00106 p1 = chHeapAlloc(&test_heap, SIZE); 00107 p2 = chHeapAlloc(&test_heap, SIZE); 00108 p3 = chHeapAlloc(&test_heap, SIZE); 00109 chHeapFree(p1); /* Does not merge.*/ 00110 chHeapFree(p2); /* Merges backward.*/ 00111 chHeapFree(p3); /* Merges both sides.*/ 00112 test_assert(3, chHeapStatus(&test_heap, &n) == 1, "heap fragmented"); 00113 00114 /* Reverse order.*/ 00115 p1 = chHeapAlloc(&test_heap, SIZE); 00116 p2 = chHeapAlloc(&test_heap, SIZE); 00117 p3 = chHeapAlloc(&test_heap, SIZE); 00118 chHeapFree(p3); /* Merges forward.*/ 00119 chHeapFree(p2); /* Merges forward.*/ 00120 chHeapFree(p1); /* Merges forward.*/ 00121 test_assert(4, chHeapStatus(&test_heap, &n) == 1, "heap fragmented"); 00122 00123 /* Small fragments handling.*/ 00124 p1 = chHeapAlloc(&test_heap, SIZE + 1); 00125 p2 = chHeapAlloc(&test_heap, SIZE); 00126 chHeapFree(p1); 00127 test_assert(5, chHeapStatus(&test_heap, &n) == 2, "invalid state"); 00128 p1 = chHeapAlloc(&test_heap, SIZE); 00129 /* Note, the first situation happens when the alignment size is smaller 00130 than the header size, the second in the other cases.*/ 00131 test_assert(6, (chHeapStatus(&test_heap, &n) == 1) || 00132 (chHeapStatus(&test_heap, &n) == 2), "heap fragmented"); 00133 chHeapFree(p2); 00134 chHeapFree(p1); 00135 test_assert(7, chHeapStatus(&test_heap, &n) == 1, "heap fragmented"); 00136 00137 /* Skip fragment handling.*/ 00138 p1 = chHeapAlloc(&test_heap, SIZE); 00139 p2 = chHeapAlloc(&test_heap, SIZE); 00140 chHeapFree(p1); 00141 test_assert(8, chHeapStatus(&test_heap, &n) == 2, "invalid state"); 00142 p1 = chHeapAlloc(&test_heap, SIZE * 2); /* Skips first fragment.*/ 00143 chHeapFree(p1); 00144 chHeapFree(p2); 00145 test_assert(9, chHeapStatus(&test_heap, &n) == 1, "heap fragmented"); 00146 00147 /* Allocate all handling.*/ 00148 (void)chHeapStatus(&test_heap, &n); 00149 p1 = chHeapAlloc(&test_heap, n); 00150 test_assert(10, chHeapStatus(&test_heap, &n) == 0, "not empty"); 00151 chHeapFree(p1); 00152 00153 test_assert(11, chHeapStatus(&test_heap, &n) == 1, "heap fragmented"); 00154 test_assert(12, n == sz, "size changed"); 00155 } 00156 00157 const struct testcase testheap1 = { 00158 heap1_gettest, 00159 heap1_setup, 00160 NULL, 00161 heap1_execute 00162 }; 00163 00164 #endif /* CH_USE_HEAP.*/ 00165 00166 /** 00167 * @brief Test sequence for heap. 00168 */ 00169 const struct testcase * const patternheap[] = { 00170 #if CH_USE_HEAP 00171 &testheap1, 00172 #endif 00173 NULL 00174 };