aboutsummaryrefslogtreecommitdiffstats
path: root/test/oslib/source/test/oslib_test_sequence_003.c
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2017-10-17 07:46:38 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2017-10-17 07:46:38 +0000
commitba2ff06045c441a2be4ecd923d38e614db48f964 (patch)
treeccbb16452507ef332c8aeabd2785bb2498853b8c /test/oslib/source/test/oslib_test_sequence_003.c
parenta202724feaf68aaf44986e2bc336de0008bb2c64 (diff)
downloadChibiOS-ba2ff06045c441a2be4ecd923d38e614db48f964.tar.gz
ChibiOS-ba2ff06045c441a2be4ecd923d38e614db48f964.tar.bz2
ChibiOS-ba2ff06045c441a2be4ecd923d38e614db48f964.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10841 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'test/oslib/source/test/oslib_test_sequence_003.c')
-rw-r--r--test/oslib/source/test/oslib_test_sequence_003.c297
1 files changed, 137 insertions, 160 deletions
diff --git a/test/oslib/source/test/oslib_test_sequence_003.c b/test/oslib/source/test/oslib_test_sequence_003.c
index c103873ac..806cd2706 100644
--- a/test/oslib/source/test/oslib_test_sequence_003.c
+++ b/test/oslib/source/test/oslib_test_sequence_003.c
@@ -21,258 +21,240 @@
* @file oslib_test_sequence_003.c
* @brief Test Sequence 003 code.
*
- * @page oslib_test_sequence_003 [3] Memory Pools
+ * @page oslib_test_sequence_003 [3] Memory Heaps
*
* File: @ref oslib_test_sequence_003.c
*
* <h2>Description</h2>
* This sequence tests the ChibiOS library functionalities related to
- * memory pools.
+ * memory heaps.
*
* <h2>Conditions</h2>
* This sequence is only executed if the following preprocessor condition
* evaluates to true:
- * - CH_CFG_USE_MEMPOOLS
+ * - CH_CFG_USE_HEAP
* .
*
* <h2>Test Cases</h2>
* - @subpage oslib_test_003_001
* - @subpage oslib_test_003_002
- * - @subpage oslib_test_003_003
* .
*/
-#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
+#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
/****************************************************************************
* Shared code.
****************************************************************************/
-#define MEMORY_POOL_SIZE 4
+#define ALLOC_SIZE 16
+#define HEAP_SIZE (ALLOC_SIZE * 8)
-static uint32_t objects[MEMORY_POOL_SIZE];
-static MEMORYPOOL_DECL(mp1, sizeof (uint32_t), PORT_NATURAL_ALIGN, NULL);
-
-#if CH_CFG_USE_SEMAPHORES
-static GUARDEDMEMORYPOOL_DECL(gmp1, sizeof (uint32_t), PORT_NATURAL_ALIGN);
-#endif
-
-static void *null_provider(size_t size, unsigned align) {
-
- (void)size;
- (void)align;
-
- return NULL;
-}
+static memory_heap_t test_heap;
+static uint8_t test_heap_buffer[HEAP_SIZE];
/****************************************************************************
* Test cases.
****************************************************************************/
/**
- * @page oslib_test_003_001 [3.1] Loading and emptying a memory pool
+ * @page oslib_test_003_001 [3.1] Allocation and fragmentation
*
* <h2>Description</h2>
- * The memory pool functionality is tested by loading and emptying it,
- * all conditions are tested.
+ * Series of allocations/deallocations are performed in carefully
+ * designed sequences in order to stimulate all the possible code paths
+ * inside the allocator. The test expects to find the heap back to the
+ * initial status after each sequence.
*
* <h2>Test Steps</h2>
- * - [3.1.1] Adding the objects to the pool using chPoolLoadArray().
- * - [3.1.2] Emptying the pool using chPoolAlloc().
- * - [3.1.3] Now must be empty.
- * - [3.1.4] Adding the objects to the pool using chPoolFree().
- * - [3.1.5] Emptying the pool using chPoolAlloc() again.
- * - [3.1.6] Now must be empty again.
- * - [3.1.7] Covering the case where a provider is unable to return
- * more memory.
+ * - [3.1.1] Testing initial conditions, the heap must not be
+ * fragmented and one free block present.
+ * - [3.1.2] Trying to allocate an block bigger than available space,
+ * an error is expected.
+ * - [3.1.3] Single block allocation using chHeapAlloc() then the block
+ * is freed using chHeapFree(), must not fail.
+ * - [3.1.4] Using chHeapStatus() to assess the heap state. There must
+ * be at least one free block of sufficient size.
+ * - [3.1.5] Allocating then freeing in the same order.
+ * - [3.1.6] Allocating then freeing in reverse order.
+ * - [3.1.7] Small fragments handling. Checking the behavior when
+ * allocating blocks with size not multiple of alignment unit.
+ * - [3.1.8] Skipping a fragment, the first fragment in the list is too
+ * small so the allocator must pick the second one.
+ * - [3.1.9] Allocating the whole available space.
+ * - [3.1.10] Testing final conditions. The heap geometry must be the
+ * same than the one registered at beginning.
* .
*/
static void oslib_test_003_001_setup(void) {
- chPoolObjectInit(&mp1, sizeof (uint32_t), NULL);
+ chHeapObjectInit(&test_heap, test_heap_buffer, sizeof(test_heap_buffer));
}
static void oslib_test_003_001_execute(void) {
- unsigned i;
+ void *p1, *p2, *p3;
+ size_t n, sz;
- /* [3.1.1] Adding the objects to the pool using chPoolLoadArray().*/
+ /* [3.1.1] Testing initial conditions, the heap must not be
+ fragmented and one free block present.*/
test_set_step(1);
{
- chPoolLoadArray(&mp1, objects, MEMORY_POOL_SIZE);
+ test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented");
}
- /* [3.1.2] Emptying the pool using chPoolAlloc().*/
+ /* [3.1.2] Trying to allocate an block bigger than available space,
+ an error is expected.*/
test_set_step(2);
{
- for (i = 0; i < MEMORY_POOL_SIZE; i++)
- test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
+ p1 = chHeapAlloc(&test_heap, sizeof test_heap_buffer * 2);
+ test_assert(p1 == NULL, "allocation not failed");
}
- /* [3.1.3] Now must be empty.*/
+ /* [3.1.3] Single block allocation using chHeapAlloc() then the block
+ is freed using chHeapFree(), must not fail.*/
test_set_step(3);
{
- test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ test_assert(p1 != NULL, "allocation failed");
+ chHeapFree(p1);
}
- /* [3.1.4] Adding the objects to the pool using chPoolFree().*/
+ /* [3.1.4] Using chHeapStatus() to assess the heap state. There must
+ be at least one free block of sufficient size.*/
test_set_step(4);
{
- for (i = 0; i < MEMORY_POOL_SIZE; i++)
- chPoolFree(&mp1, &objects[i]);
+ size_t total_size, largest_size;
+
+ n = chHeapStatus(&test_heap, &total_size, &largest_size);
+ test_assert(n == 1, "missing free block");
+ test_assert(total_size >= ALLOC_SIZE, "unexpected heap state");
+ test_assert(total_size == largest_size, "unexpected heap state");
}
- /* [3.1.5] Emptying the pool using chPoolAlloc() again.*/
+ /* [3.1.5] Allocating then freeing in the same order.*/
test_set_step(5);
{
- for (i = 0; i < MEMORY_POOL_SIZE; i++)
- test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ p3 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ chHeapFree(p1); /* Does not merge.*/
+ chHeapFree(p2); /* Merges backward.*/
+ chHeapFree(p3); /* Merges both sides.*/
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
}
- /* [3.1.6] Now must be empty again.*/
+ /* [3.1.6] Allocating then freeing in reverse order.*/
test_set_step(6);
{
- test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ p3 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ chHeapFree(p3); /* Merges forward.*/
+ chHeapFree(p2); /* Merges forward.*/
+ chHeapFree(p1); /* Merges forward.*/
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
}
- /* [3.1.7] Covering the case where a provider is unable to return
- more memory.*/
+ /* [3.1.7] Small fragments handling. Checking the behavior when
+ allocating blocks with size not multiple of alignment unit.*/
test_set_step(7);
{
- chPoolObjectInit(&mp1, sizeof (uint32_t), null_provider);
- test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE + 1);
+ p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ chHeapFree(p1);
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state");
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ /* Note, the first situation happens when the alignment size is smaller
+ than the header size, the second in the other cases.*/
+ test_assert((chHeapStatus(&test_heap, &n, NULL) == 1) ||
+ (chHeapStatus(&test_heap, &n, NULL) == 2), "heap fragmented");
+ chHeapFree(p2);
+ chHeapFree(p1);
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
+ }
+
+ /* [3.1.8] Skipping a fragment, the first fragment in the list is too
+ small so the allocator must pick the second one.*/
+ test_set_step(8);
+ {
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ chHeapFree(p1);
+ test_assert( chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state");
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE * 2); /* Skips first fragment.*/
+ chHeapFree(p1);
+ chHeapFree(p2);
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
+ }
+
+ /* [3.1.9] Allocating the whole available space.*/
+ test_set_step(9);
+ {
+ (void)chHeapStatus(&test_heap, &n, NULL);
+ p1 = chHeapAlloc(&test_heap, n);
+ test_assert(p1 != NULL, "allocation failed");
+ test_assert(chHeapStatus(&test_heap, NULL, NULL) == 0, "not empty");
+ chHeapFree(p1);
+ }
+
+ /* [3.1.10] Testing final conditions. The heap geometry must be the
+ same than the one registered at beginning.*/
+ test_set_step(10);
+ {
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
+ test_assert(n == sz, "size changed");
}
}
static const testcase_t oslib_test_003_001 = {
- "Loading and emptying a memory pool",
+ "Allocation and fragmentation",
oslib_test_003_001_setup,
NULL,
oslib_test_003_001_execute
};
-#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
/**
- * @page oslib_test_003_002 [3.2] Loading and emptying a guarded memory pool without waiting
+ * @page oslib_test_003_002 [3.2] Default Heap
*
* <h2>Description</h2>
- * The memory pool functionality is tested by loading and emptying it,
- * all conditions are tested.
- *
- * <h2>Conditions</h2>
- * This test is only executed if the following preprocessor condition
- * evaluates to true:
- * - CH_CFG_USE_SEMAPHORES
- * .
+ * The default heap is pre-allocated in the system. We test base
+ * functionality.
*
* <h2>Test Steps</h2>
- * - [3.2.1] Adding the objects to the pool using
- * chGuardedPoolLoadArray().
- * - [3.2.2] Emptying the pool using chGuardedPoolAllocTimeout().
- * - [3.2.3] Now must be empty.
- * - [3.2.4] Adding the objects to the pool using chGuardedPoolFree().
- * - [3.2.5] Emptying the pool using chGuardedPoolAllocTimeout() again.
- * - [3.2.6] Now must be empty again.
+ * - [3.2.1] Single block allocation using chHeapAlloc() then the block
+ * is freed using chHeapFree(), must not fail.
+ * - [3.2.2] Testing allocation failure.
* .
*/
-static void oslib_test_003_002_setup(void) {
- chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
-}
-
static void oslib_test_003_002_execute(void) {
- unsigned i;
+ void *p1;
+ size_t total_size, largest_size;
- /* [3.2.1] Adding the objects to the pool using
- chGuardedPoolLoadArray().*/
+ /* [3.2.1] Single block allocation using chHeapAlloc() then the block
+ is freed using chHeapFree(), must not fail.*/
test_set_step(1);
{
- chGuardedPoolLoadArray(&gmp1, objects, MEMORY_POOL_SIZE);
+ (void)chHeapStatus(NULL, &total_size, &largest_size);
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ test_assert(p1 != NULL, "allocation failed");
+ chHeapFree(p1);
}
- /* [3.2.2] Emptying the pool using chGuardedPoolAllocTimeout().*/
+ /* [3.2.2] Testing allocation failure.*/
test_set_step(2);
{
- for (i = 0; i < MEMORY_POOL_SIZE; i++)
- test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty");
- }
-
- /* [3.2.3] Now must be empty.*/
- test_set_step(3);
- {
- test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty");
- }
-
- /* [3.2.4] Adding the objects to the pool using
- chGuardedPoolFree().*/
- test_set_step(4);
- {
- for (i = 0; i < MEMORY_POOL_SIZE; i++)
- chGuardedPoolFree(&gmp1, &objects[i]);
- }
-
- /* [3.2.5] Emptying the pool using chGuardedPoolAllocTimeout()
- again.*/
- test_set_step(5);
- {
- for (i = 0; i < MEMORY_POOL_SIZE; i++)
- test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty");
- }
-
- /* [3.2.6] Now must be empty again.*/
- test_set_step(6);
- {
- test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty");
+ p1 = chHeapAlloc(NULL, (size_t)-256);
+ test_assert(p1 == NULL, "allocation not failed");
}
}
static const testcase_t oslib_test_003_002 = {
- "Loading and emptying a guarded memory pool without waiting",
- oslib_test_003_002_setup,
+ "Default Heap",
NULL,
- oslib_test_003_002_execute
-};
-#endif /* CH_CFG_USE_SEMAPHORES */
-
-#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
-/**
- * @page oslib_test_003_003 [3.3] Guarded Memory Pools timeout
- *
- * <h2>Description</h2>
- * The timeout features for the Guarded Memory Pools is tested.
- *
- * <h2>Conditions</h2>
- * This test is only executed if the following preprocessor condition
- * evaluates to true:
- * - CH_CFG_USE_SEMAPHORES
- * .
- *
- * <h2>Test Steps</h2>
- * - [3.3.1] Trying to allocate with 100mS timeout, must fail because
- * the pool is empty.
- * .
- */
-
-static void oslib_test_003_003_setup(void) {
- chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
-}
-
-static void oslib_test_003_003_execute(void) {
-
- /* [3.3.1] Trying to allocate with 100mS timeout, must fail because
- the pool is empty.*/
- test_set_step(1);
- {
- test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_MS2I(100)) == NULL, "list not empty");
- }
-}
-
-static const testcase_t oslib_test_003_003 = {
- "Guarded Memory Pools timeout",
- oslib_test_003_003_setup,
NULL,
- oslib_test_003_003_execute
+ oslib_test_003_002_execute
};
-#endif /* CH_CFG_USE_SEMAPHORES */
/****************************************************************************
* Exported data.
@@ -283,21 +265,16 @@ static const testcase_t oslib_test_003_003 = {
*/
const testcase_t * const oslib_test_sequence_003_array[] = {
&oslib_test_003_001,
-#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
&oslib_test_003_002,
-#endif
-#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
- &oslib_test_003_003,
-#endif
NULL
};
/**
- * @brief Memory Pools.
+ * @brief Memory Heaps.
*/
const testsequence_t oslib_test_sequence_003 = {
NULL,
oslib_test_sequence_003_array
};
-#endif /* CH_CFG_USE_MEMPOOLS */
+#endif /* CH_CFG_USE_HEAP */