Fixed small errors in pipes and pipes factory.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12307 110e8d01-0319-4d1e-a829-52ad28d1bb01
This commit is contained in:
Giovanni Di Sirio 2018-09-30 05:38:03 +00:00
parent f562ee4948
commit 8fa2bcdad9
13 changed files with 559 additions and 1037 deletions

View File

@ -5,7 +5,7 @@
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).

View File

@ -33,9 +33,9 @@
<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
<stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;contentList/&gt;"/>
<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;globalVariableList/&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;memoryBlockExpressionList/&gt;&#13;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&lt;contentList&gt;&lt;content id=&quot;r0-(format)&quot; val=&quot;4&quot;/&gt;&lt;/contentList&gt;"/>
<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;globalVariableList/&gt;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;memoryBlockExpressionList/&gt;&#10;"/>
<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="./build/ch.elf"/>
<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="RT-STM32L476-DISCOVERY"/>
<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/>

View File

@ -70,7 +70,7 @@ int main(void) {
*/
while (true) {
if (palReadLine(LINE_JOY_CENTER)) {
test_execute((BaseSequentialStream *)&SD2, &rt_test_suite);
// test_execute((BaseSequentialStream *)&SD2, &rt_test_suite);
test_execute((BaseSequentialStream *)&SD2, &oslib_test_suite);
}
chThdSleepMilliseconds(500);

View File

@ -271,6 +271,9 @@ void _factory_init(void) {
#if CH_CFG_FACTORY_OBJ_FIFOS == TRUE
dyn_list_init(&ch_factory.fifo_list);
#endif
#if CH_CFG_FACTORY_PIPES == TRUE
dyn_list_init(&ch_factory.pipe_list);
#endif
}
#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXIGEN__)
@ -775,7 +778,7 @@ dyn_pipe_t *chFactoryFindPipe(const char *name) {
F_LOCK();
dpp = (dyn_pipe_t *)dyn_find_object(name, &ch_factory.fifo_list);
dpp = (dyn_pipe_t *)dyn_find_object(name, &ch_factory.pipe_list);
F_UNLOCK();

View File

@ -138,8 +138,8 @@ static size_t pipe_read(pipe_t *pp, uint8_t *bp, size_t n) {
size_t s1, s2;
/* Number of bytes that can be read in a single atomic operation.*/
if (n > chPipeGetFreeCount(pp)) {
n = chPipeGetFreeCount(pp);
if (n > chPipeGetUsedCount(pp)) {
n = chPipeGetUsedCount(pp);
}
/* Number of bytes before buffer limit.*/

View File

@ -53,7 +53,7 @@
<value>Mailboxes.</value>
</brief>
<description>
<value>This sequence tests the ChibiOS libraryfunctionalities related to mailboxes.</value>
<value>This sequence tests the ChibiOS library functionalities related to mailboxes.</value>
</description>
<condition>
<value>CH_CFG_USE_MAILBOXES</value>
@ -430,6 +430,140 @@ test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");]]></value>
</case>
</cases>
</sequence>
<sequence>
<type index="0">
<value>Internal Tests</value>
</type>
<brief>
<value>Pipes</value>
</brief>
<description>
<value>This sequence tests the ChibiOS library functionalities related to pipes.</value>
</description>
<condition>
<value>CH_CFG_USE_PIPES</value>
</condition>
<shared_code>
<value><![CDATA[#define PIPE_SIZE 16
static uint8_t buffer[PIPE_SIZE];
static PIPE_DECL(pipe1, buffer, PIPE_SIZE);
static const uint8_t pipe_pattern[] = "0123456789ABCDEF";]]></value>
</shared_code>
<cases>
<case>
<brief>
<value>Filling and emptying a pipe, non blocking.</value>
</brief>
<description>
<value>The pipe functionality is tested by loading and emptying it, all conditions are tested.</value>
</description>
<condition>
<value>
</value>
</condition>
<various_code>
<setup_code>
<value><![CDATA[chPipeObjectInit(&pipe1, buffer, PIPE_SIZE);]]></value>
</setup_code>
<teardown_code>
<value/>
</teardown_code>
<local_variables>
<value><![CDATA[unsigned i;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Filling whole pipe.</value>
</description>
<tags>
<value></value>
</tags>
<code>
<value><![CDATA[msg_t msg;
msg = chPipeWriteTimeout(&pipe1, pipe_pattern, PIPE_SIZE, TIME_IMMEDIATE);
test_assert(msg == PIPE_SIZE, "wrong size");
test_assert((pipe1.rdptr == pipe1.buffer) &&
(pipe1.wrptr == pipe1.buffer) &&
(pipe1.cnt == PIPE_SIZE),
"invalid pipe state");]]></value>
</code>
</step>
<step>
<description>
<value>Emptying pipe.</value>
</description>
<tags>
<value></value>
</tags>
<code>
<value><![CDATA[msg_t msg;
uint8_t buf[PIPE_SIZE];
msg = chPipeReadTimeout(&pipe1, buf, PIPE_SIZE, TIME_IMMEDIATE);
test_assert(msg == PIPE_SIZE, "wrong size");
test_assert((pipe1.rdptr == pipe1.buffer) &&
(pipe1.wrptr == pipe1.buffer) &&
(pipe1.cnt == PIPE_SIZE),
"invalid pipe state");]]></value>
</code>
</step>
<step>
<description>
<value>
</value>
</description>
<tags>
<value></value>
</tags>
<code>
<value><![CDATA[]]></value>
</code>
</step>
<step>
<description>
<value>
</value>
</description>
<tags>
<value></value>
</tags>
<code>
<value><![CDATA[]]></value>
</code>
</step>
<step>
<description>
<value>
</value>
</description>
<tags>
<value></value>
</tags>
<code>
<value><![CDATA[]]></value>
</code>
</step>
<step>
<description>
<value>
</value>
</description>
<tags>
<value></value>
</tags>
<code>
<value><![CDATA[]]></value>
</code>
</step>
</steps>
</case>
</cases>
</sequence>
<sequence>
<type index="0">
<value>Internal Tests</value>
@ -438,7 +572,7 @@ test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message");]]></value>
<value>Memory Pools.</value>
</brief>
<description>
<value>This sequence tests the ChibiOS library functionalities related to memory pools.</value>
<value>This sequence tests the ChibiOS library functionalities related to memory pools.</value>
</description>
<condition>
<value>CH_CFG_USE_MEMPOOLS</value>
@ -1681,6 +1815,7 @@ test_assert(dpp == NULL, "found");]]></value>
</case>
</cases>
</sequence>
</sequences>
</instance>
</instances>

View File

@ -3,7 +3,8 @@ TESTSRC += ${CHIBIOS}/test/oslib/source/test/oslib_test_root.c \
${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_001.c \
${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_002.c \
${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_003.c \
${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_004.c
${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_004.c \
${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_005.c
# Required include directories
TESTINC += ${CHIBIOS}/test/oslib/source/test

View File

@ -25,6 +25,7 @@
* - @subpage oslib_test_sequence_002
* - @subpage oslib_test_sequence_003
* - @subpage oslib_test_sequence_004
* - @subpage oslib_test_sequence_005
* .
*/
@ -49,14 +50,17 @@ const testsequence_t * const oslib_test_suite_array[] = {
#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__)
&oslib_test_sequence_001,
#endif
#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
#if (CH_CFG_USE_PIPES) || defined(__DOXYGEN__)
&oslib_test_sequence_002,
#endif
#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
&oslib_test_sequence_003,
#endif
#if ((CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE)) || defined(__DOXYGEN__)
#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
&oslib_test_sequence_004,
#endif
#if ((CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE)) || defined(__DOXYGEN__)
&oslib_test_sequence_005,
#endif
NULL
};

View File

@ -28,6 +28,7 @@
#include "oslib_test_sequence_002.h"
#include "oslib_test_sequence_003.h"
#include "oslib_test_sequence_004.h"
#include "oslib_test_sequence_005.h"
#if !defined(__DOXYGEN__)

View File

@ -26,7 +26,7 @@
* File: @ref oslib_test_sequence_001.c
*
* <h2>Description</h2>
* This sequence tests the ChibiOS libraryfunctionalities related to
* This sequence tests the ChibiOS library functionalities related to
* mailboxes.
*
* <h2>Conditions</h2>

View File

@ -21,259 +21,121 @@
* @file oslib_test_sequence_002.c
* @brief Test Sequence 002 code.
*
* @page oslib_test_sequence_002 [2] Memory Pools
* @page oslib_test_sequence_002 [2] Pipes
*
* File: @ref oslib_test_sequence_002.c
*
* <h2>Description</h2>
* This sequence tests the ChibiOS library functionalities related to
* memory pools.
* pipes.
*
* <h2>Conditions</h2>
* This sequence is only executed if the following preprocessor condition
* evaluates to true:
* - CH_CFG_USE_MEMPOOLS
* - CH_CFG_USE_PIPES
* .
*
* <h2>Test Cases</h2>
* - @subpage oslib_test_002_001
* - @subpage oslib_test_002_002
* - @subpage oslib_test_002_003
* .
*/
#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
#if (CH_CFG_USE_PIPES) || defined(__DOXYGEN__)
/****************************************************************************
* Shared code.
****************************************************************************/
#define MEMORY_POOL_SIZE 4
#define PIPE_SIZE 16
static uint32_t objects[MEMORY_POOL_SIZE];
static MEMORYPOOL_DECL(mp1, sizeof (uint32_t), PORT_NATURAL_ALIGN, NULL);
static uint8_t buffer[PIPE_SIZE];
static PIPE_DECL(pipe1, buffer, PIPE_SIZE);
#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 const uint8_t pipe_pattern[] = "0123456789ABCDEF";
/****************************************************************************
* Test cases.
****************************************************************************/
/**
* @page oslib_test_002_001 [2.1] Loading and emptying a memory pool
* @page oslib_test_002_001 [2.1] Loading and emptying a pipe, non blocking
*
* <h2>Description</h2>
* The memory pool functionality is tested by loading and emptying it,
* all conditions are tested.
* The pipe functionality is tested by loading and emptying it, all
* conditions are tested.
*
* <h2>Test Steps</h2>
* - [2.1.1] Adding the objects to the pool using chPoolLoadArray().
* - [2.1.2] Emptying the pool using chPoolAlloc().
* - [2.1.3] Now must be empty.
* - [2.1.4] Adding the objects to the pool using chPoolFree().
* - [2.1.5] Emptying the pool using chPoolAlloc() again.
* - [2.1.6] Now must be empty again.
* - [2.1.7] Covering the case where a provider is unable to return
* more memory.
* - [2.1.1] Filling whole pipe.
* - [2.1.2] Emptying pipe.
* - [2.1.3].
* - [2.1.4].
* - [2.1.5].
* - [2.1.6].
* .
*/
static void oslib_test_002_001_setup(void) {
chPoolObjectInit(&mp1, sizeof (uint32_t), NULL);
chPipeObjectInit(&pipe1, buffer, PIPE_SIZE);
}
static void oslib_test_002_001_execute(void) {
unsigned i;
/* [2.1.1] Adding the objects to the pool using chPoolLoadArray().*/
/* [2.1.1] Filling whole pipe.*/
test_set_step(1);
{
chPoolLoadArray(&mp1, objects, MEMORY_POOL_SIZE);
msg_t msg;
msg = chPipeWriteTimeout(&pipe1, pipe_pattern, PIPE_SIZE, TIME_IMMEDIATE);
test_assert(msg == PIPE_SIZE, "wrong size");
test_assert((pipe1.rdptr == pipe1.buffer) &&
(pipe1.wrptr == pipe1.buffer) &&
(pipe1.cnt == PIPE_SIZE),
"invalid pipe state");
}
/* [2.1.2] Emptying the pool using chPoolAlloc().*/
/* [2.1.2] Emptying pipe.*/
test_set_step(2);
{
for (i = 0; i < MEMORY_POOL_SIZE; i++)
test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
msg_t msg;
uint8_t buf[PIPE_SIZE];
msg = chPipeReadTimeout(&pipe1, buf, PIPE_SIZE, TIME_IMMEDIATE);
test_assert(msg == PIPE_SIZE, "wrong size");
test_assert((pipe1.rdptr == pipe1.buffer) &&
(pipe1.wrptr == pipe1.buffer) &&
(pipe1.cnt == 0),
"invalid pipe state");
}
/* [2.1.3] Now must be empty.*/
/* [2.1.3].*/
test_set_step(3);
{
test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
}
/* [2.1.4] Adding the objects to the pool using chPoolFree().*/
/* [2.1.4].*/
test_set_step(4);
{
for (i = 0; i < MEMORY_POOL_SIZE; i++)
chPoolFree(&mp1, &objects[i]);
}
/* [2.1.5] Emptying the pool using chPoolAlloc() again.*/
/* [2.1.5].*/
test_set_step(5);
{
for (i = 0; i < MEMORY_POOL_SIZE; i++)
test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
}
/* [2.1.6] Now must be empty again.*/
/* [2.1.6].*/
test_set_step(6);
{
test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
}
/* [2.1.7] Covering the case where a provider is unable to return
more memory.*/
test_set_step(7);
{
chPoolObjectInit(&mp1, sizeof (uint32_t), null_provider);
test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");
}
}
static const testcase_t oslib_test_002_001 = {
"Loading and emptying a memory pool",
"Loading and emptying a pipe, non blocking",
oslib_test_002_001_setup,
NULL,
oslib_test_002_001_execute
};
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
/**
* @page oslib_test_002_002 [2.2] Loading and emptying a guarded memory pool without waiting
*
* <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
* .
*
* <h2>Test Steps</h2>
* - [2.2.1] Adding the objects to the pool using
* chGuardedPoolLoadArray().
* - [2.2.2] Emptying the pool using chGuardedPoolAllocTimeout().
* - [2.2.3] Now must be empty.
* - [2.2.4] Adding the objects to the pool using chGuardedPoolFree().
* - [2.2.5] Emptying the pool using chGuardedPoolAllocTimeout() again.
* - [2.2.6] Now must be empty again.
* .
*/
static void oslib_test_002_002_setup(void) {
chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
}
static void oslib_test_002_002_execute(void) {
unsigned i;
/* [2.2.1] Adding the objects to the pool using
chGuardedPoolLoadArray().*/
test_set_step(1);
{
chGuardedPoolLoadArray(&gmp1, objects, MEMORY_POOL_SIZE);
}
/* [2.2.2] Emptying the pool using chGuardedPoolAllocTimeout().*/
test_set_step(2);
{
for (i = 0; i < MEMORY_POOL_SIZE; i++)
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty");
}
/* [2.2.3] Now must be empty.*/
test_set_step(3);
{
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty");
}
/* [2.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]);
}
/* [2.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");
}
/* [2.2.6] Now must be empty again.*/
test_set_step(6);
{
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty");
}
}
static const testcase_t oslib_test_002_002 = {
"Loading and emptying a guarded memory pool without waiting",
oslib_test_002_002_setup,
NULL,
oslib_test_002_002_execute
};
#endif /* CH_CFG_USE_SEMAPHORES */
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
/**
* @page oslib_test_002_003 [2.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>
* - [2.3.1] Trying to allocate with 100mS timeout, must fail because
* the pool is empty.
* .
*/
static void oslib_test_002_003_setup(void) {
chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
}
static void oslib_test_002_003_execute(void) {
/* [2.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_002_003 = {
"Guarded Memory Pools timeout",
oslib_test_002_003_setup,
NULL,
oslib_test_002_003_execute
};
#endif /* CH_CFG_USE_SEMAPHORES */
/****************************************************************************
* Exported data.
****************************************************************************/
@ -283,21 +145,15 @@ static const testcase_t oslib_test_002_003 = {
*/
const testcase_t * const oslib_test_sequence_002_array[] = {
&oslib_test_002_001,
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
&oslib_test_002_002,
#endif
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
&oslib_test_002_003,
#endif
NULL
};
/**
* @brief Memory Pools.
* @brief Pipes.
*/
const testsequence_t oslib_test_sequence_002 = {
"Memory Pools",
"Pipes",
oslib_test_sequence_002_array
};
#endif /* CH_CFG_USE_MEMPOOLS */
#endif /* CH_CFG_USE_PIPES */

View File

@ -21,240 +21,258 @@
* @file oslib_test_sequence_003.c
* @brief Test Sequence 003 code.
*
* @page oslib_test_sequence_003 [3] Memory Heaps
* @page oslib_test_sequence_003 [3] Memory Pools
*
* File: @ref oslib_test_sequence_003.c
*
* <h2>Description</h2>
* This sequence tests the ChibiOS library functionalities related to
* memory heaps.
* memory pools.
*
* <h2>Conditions</h2>
* This sequence is only executed if the following preprocessor condition
* evaluates to true:
* - CH_CFG_USE_HEAP
* - CH_CFG_USE_MEMPOOLS
* .
*
* <h2>Test Cases</h2>
* - @subpage oslib_test_003_001
* - @subpage oslib_test_003_002
* - @subpage oslib_test_003_003
* .
*/
#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
/****************************************************************************
* Shared code.
****************************************************************************/
#define ALLOC_SIZE 16
#define HEAP_SIZE (ALLOC_SIZE * 8)
#define MEMORY_POOL_SIZE 4
static memory_heap_t test_heap;
static uint8_t test_heap_buffer[HEAP_SIZE];
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;
}
/****************************************************************************
* Test cases.
****************************************************************************/
/**
* @page oslib_test_003_001 [3.1] Allocation and fragmentation
* @page oslib_test_003_001 [3.1] Loading and emptying a memory pool
*
* <h2>Description</h2>
* 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.
* The memory pool functionality is tested by loading and emptying it,
* all conditions are tested.
*
* <h2>Test Steps</h2>
* - [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.
* - [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.
* .
*/
static void oslib_test_003_001_setup(void) {
chHeapObjectInit(&test_heap, test_heap_buffer, sizeof(test_heap_buffer));
chPoolObjectInit(&mp1, sizeof (uint32_t), NULL);
}
static void oslib_test_003_001_execute(void) {
void *p1, *p2, *p3;
size_t n, sz;
unsigned i;
/* [3.1.1] Testing initial conditions, the heap must not be
fragmented and one free block present.*/
/* [3.1.1] Adding the objects to the pool using chPoolLoadArray().*/
test_set_step(1);
{
test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented");
chPoolLoadArray(&mp1, objects, MEMORY_POOL_SIZE);
}
/* [3.1.2] Trying to allocate an block bigger than available space,
an error is expected.*/
/* [3.1.2] Emptying the pool using chPoolAlloc().*/
test_set_step(2);
{
p1 = chHeapAlloc(&test_heap, sizeof test_heap_buffer * 2);
test_assert(p1 == NULL, "allocation not failed");
for (i = 0; i < MEMORY_POOL_SIZE; i++)
test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
}
/* [3.1.3] Single block allocation using chHeapAlloc() then the block
is freed using chHeapFree(), must not fail.*/
/* [3.1.3] Now must be empty.*/
test_set_step(3);
{
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
test_assert(p1 != NULL, "allocation failed");
chHeapFree(p1);
test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
}
/* [3.1.4] Using chHeapStatus() to assess the heap state. There must
be at least one free block of sufficient size.*/
/* [3.1.4] Adding the objects to the pool using chPoolFree().*/
test_set_step(4);
{
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");
for (i = 0; i < MEMORY_POOL_SIZE; i++)
chPoolFree(&mp1, &objects[i]);
}
/* [3.1.5] Allocating then freeing in the same order.*/
/* [3.1.5] Emptying the pool using chPoolAlloc() again.*/
test_set_step(5);
{
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");
for (i = 0; i < MEMORY_POOL_SIZE; i++)
test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
}
/* [3.1.6] Allocating then freeing in reverse order.*/
/* [3.1.6] Now must be empty again.*/
test_set_step(6);
{
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");
test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
}
/* [3.1.7] Small fragments handling. Checking the behavior when
allocating blocks with size not multiple of alignment unit.*/
/* [3.1.7] Covering the case where a provider is unable to return
more memory.*/
test_set_step(7);
{
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");
chPoolObjectInit(&mp1, sizeof (uint32_t), null_provider);
test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");
}
}
static const testcase_t oslib_test_003_001 = {
"Allocation and fragmentation",
"Loading and emptying a memory pool",
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] Default Heap
* @page oslib_test_003_002 [3.2] Loading and emptying a guarded memory pool without waiting
*
* <h2>Description</h2>
* The default heap is pre-allocated in the system. We test base
* functionality.
* 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
* .
*
* <h2>Test Steps</h2>
* - [3.2.1] Single block allocation using chHeapAlloc() then the block
* is freed using chHeapFree(), must not fail.
* - [3.2.2] Testing allocation failure.
* - [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.
* .
*/
static void oslib_test_003_002_execute(void) {
void *p1;
size_t total_size, largest_size;
static void oslib_test_003_002_setup(void) {
chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
}
/* [3.2.1] Single block allocation using chHeapAlloc() then the block
is freed using chHeapFree(), must not fail.*/
static void oslib_test_003_002_execute(void) {
unsigned i;
/* [3.2.1] Adding the objects to the pool using
chGuardedPoolLoadArray().*/
test_set_step(1);
{
(void)chHeapStatus(NULL, &total_size, &largest_size);
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
test_assert(p1 != NULL, "allocation failed");
chHeapFree(p1);
chGuardedPoolLoadArray(&gmp1, objects, MEMORY_POOL_SIZE);
}
/* [3.2.2] Testing allocation failure.*/
/* [3.2.2] Emptying the pool using chGuardedPoolAllocTimeout().*/
test_set_step(2);
{
p1 = chHeapAlloc(NULL, (size_t)-256);
test_assert(p1 == NULL, "allocation not failed");
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");
}
}
static const testcase_t oslib_test_003_002 = {
"Default Heap",
NULL,
"Loading and emptying a guarded memory pool without waiting",
oslib_test_003_002_setup,
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
};
#endif /* CH_CFG_USE_SEMAPHORES */
/****************************************************************************
* Exported data.
@ -265,16 +283,21 @@ static const testcase_t oslib_test_003_002 = {
*/
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 Heaps.
* @brief Memory Pools.
*/
const testsequence_t oslib_test_sequence_003 = {
"Memory Heaps",
"Memory Pools",
oslib_test_sequence_003_array
};
#endif /* CH_CFG_USE_HEAP */
#endif /* CH_CFG_USE_MEMPOOLS */

View File

@ -21,725 +21,240 @@
* @file oslib_test_sequence_004.c
* @brief Test Sequence 004 code.
*
* @page oslib_test_sequence_004 [4] Objects Factory
* @page oslib_test_sequence_004 [4] Memory Heaps
*
* File: @ref oslib_test_sequence_004.c
*
* <h2>Description</h2>
* This sequence tests the ChibiOS library functionalities related to
* the object factory.
* memory heaps.
*
* <h2>Conditions</h2>
* This sequence is only executed if the following preprocessor condition
* evaluates to true:
* - (CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE)
* - CH_CFG_USE_HEAP
* .
*
* <h2>Test Cases</h2>
* - @subpage oslib_test_004_001
* - @subpage oslib_test_004_002
* - @subpage oslib_test_004_003
* - @subpage oslib_test_004_004
* - @subpage oslib_test_004_005
* - @subpage oslib_test_004_006
* .
*/
#if ((CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE)) || defined(__DOXYGEN__)
#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
/****************************************************************************
* Shared code.
****************************************************************************/
#define ALLOC_SIZE 16
#define HEAP_SIZE (ALLOC_SIZE * 8)
static memory_heap_t test_heap;
static uint8_t test_heap_buffer[HEAP_SIZE];
/****************************************************************************
* Test cases.
****************************************************************************/
#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__)
/**
* @page oslib_test_004_001 [4.1] Objects Registry
* @page oslib_test_004_001 [4.1] Allocation and fragmentation
*
* <h2>Description</h2>
* This test case verifies the static objects registry.
*
* <h2>Conditions</h2>
* This test is only executed if the following preprocessor condition
* evaluates to true:
* - CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE
* .
* 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>
* - [4.1.1] Retrieving a registered object by name, must not exist.
* - [4.1.2] Registering an object, it must not exists, must succeed.
* - [4.1.3] Registering an object with the same name, must fail.
* - [4.1.4] Retrieving the registered object by name, must exist, then
* increasing the reference counter, finally releasing both
* references.
* - [4.1.5] Releasing the first reference to the object, must not
* trigger an assertion.
* - [4.1.6] Retrieving the registered object by name again, must not
* exist.
* - [4.1.1] Testing initial conditions, the heap must not be
* fragmented and one free block present.
* - [4.1.2] Trying to allocate an block bigger than available space,
* an error is expected.
* - [4.1.3] Single block allocation using chHeapAlloc() then the block
* is freed using chHeapFree(), must not fail.
* - [4.1.4] Using chHeapStatus() to assess the heap state. There must
* be at least one free block of sufficient size.
* - [4.1.5] Allocating then freeing in the same order.
* - [4.1.6] Allocating then freeing in reverse order.
* - [4.1.7] Small fragments handling. Checking the behavior when
* allocating blocks with size not multiple of alignment unit.
* - [4.1.8] Skipping a fragment, the first fragment in the list is too
* small so the allocator must pick the second one.
* - [4.1.9] Allocating the whole available space.
* - [4.1.10] Testing final conditions. The heap geometry must be the
* same than the one registered at beginning.
* .
*/
static void oslib_test_004_001_teardown(void) {
registered_object_t *rop;
rop = chFactoryFindObject("myobj");
if (rop != NULL) {
while (rop->element.refs > 0U) {
chFactoryReleaseObject(rop);
}
}
static void oslib_test_004_001_setup(void) {
chHeapObjectInit(&test_heap, test_heap_buffer, sizeof(test_heap_buffer));
}
static void oslib_test_004_001_execute(void) {
registered_object_t *rop;
void *p1, *p2, *p3;
size_t n, sz;
/* [4.1.1] Retrieving a registered object by name, must not exist.*/
/* [4.1.1] Testing initial conditions, the heap must not be
fragmented and one free block present.*/
test_set_step(1);
{
rop = chFactoryFindObject("myobj");
test_assert(rop == NULL, "found");
test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented");
}
/* [4.1.2] Registering an object, it must not exists, must succeed.*/
/* [4.1.2] Trying to allocate an block bigger than available space,
an error is expected.*/
test_set_step(2);
{
static uint32_t myobj = 0x55aa;
rop = chFactoryRegisterObject("myobj", (void *)&myobj);
test_assert(rop != NULL, "cannot register");
p1 = chHeapAlloc(&test_heap, sizeof test_heap_buffer * 2);
test_assert(p1 == NULL, "allocation not failed");
}
/* [4.1.3] Registering an object with the same name, must fail.*/
/* [4.1.3] Single block allocation using chHeapAlloc() then the block
is freed using chHeapFree(), must not fail.*/
test_set_step(3);
{
registered_object_t *rop1;
static uint32_t myobj = 0x55aa;
rop1 = chFactoryRegisterObject("myobj", (void *)&myobj);
test_assert(rop1 == NULL, "can register");
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
test_assert(p1 != NULL, "allocation failed");
chHeapFree(p1);
}
/* [4.1.4] Retrieving the registered object by name, must exist, then
increasing the reference counter, finally releasing both
references.*/
/* [4.1.4] Using chHeapStatus() to assess the heap state. There must
be at least one free block of sufficient size.*/
test_set_step(4);
{
registered_object_t *rop1, *rop2;
size_t total_size, largest_size;
rop1 = chFactoryFindObject("myobj");
test_assert(rop1 != NULL, "not found");
test_assert(*(uint32_t *)(rop1->objp) == 0x55aa, "object mismatch");
test_assert(rop == rop1, "object reference mismatch");
test_assert(rop1->element.refs == 2, "object reference mismatch");
rop2 = (registered_object_t *)chFactoryDuplicateReference(&rop1->element);
test_assert(rop1 == rop2, "object reference mismatch");
test_assert(*(uint32_t *)(rop2->objp) == 0x55aa, "object mismatch");
test_assert(rop2->element.refs == 3, "object reference mismatch");
chFactoryReleaseObject(rop2);
test_assert(rop1->element.refs == 2, "references mismatch");
chFactoryReleaseObject(rop1);
test_assert(rop->element.refs == 1, "references mismatch");
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");
}
/* [4.1.5] Releasing the first reference to the object, must not
trigger an assertion.*/
/* [4.1.5] Allocating then freeing in the same order.*/
test_set_step(5);
{
chFactoryReleaseObject(rop);
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");
}
/* [4.1.6] Retrieving the registered object by name again, must not
exist.*/
/* [4.1.6] Allocating then freeing in reverse order.*/
test_set_step(6);
{
rop = chFactoryFindObject("myobj");
test_assert(rop == NULL, "found");
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");
}
/* [4.1.7] Small fragments handling. Checking the behavior when
allocating blocks with size not multiple of alignment unit.*/
test_set_step(7);
{
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");
}
/* [4.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");
}
/* [4.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);
}
/* [4.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_004_001 = {
"Objects Registry",
"Allocation and fragmentation",
oslib_test_004_001_setup,
NULL,
oslib_test_004_001_teardown,
oslib_test_004_001_execute
};
#endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */
#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__)
/**
* @page oslib_test_004_002 [4.2] Dynamic Buffers Factory
* @page oslib_test_004_002 [4.2] Default Heap
*
* <h2>Description</h2>
* This test case verifies the dynamic buffers factory.
*
* <h2>Conditions</h2>
* This test is only executed if the following preprocessor condition
* evaluates to true:
* - CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE
* .
* The default heap is pre-allocated in the system. We test base
* functionality.
*
* <h2>Test Steps</h2>
* - [4.2.1] Retrieving a dynamic buffer by name, must not exist.
* - [4.2.2] Creating a dynamic buffer it must not exists, must
* succeed.
* - [4.2.3] Creating a dynamic buffer with the same name, must fail.
* - [4.2.4] Retrieving the dynamic buffer by name, must exist, then
* increasing the reference counter, finally releasing both
* references.
* - [4.2.5] Releasing the first reference to the dynamic buffer, must
* not trigger an assertion.
* - [4.2.6] Retrieving the dynamic buffer by name again, must not
* exist.
* - [4.2.1] Single block allocation using chHeapAlloc() then the block
* is freed using chHeapFree(), must not fail.
* - [4.2.2] Testing allocation failure.
* .
*/
static void oslib_test_004_002_teardown(void) {
dyn_buffer_t *dbp;
dbp = chFactoryFindBuffer("mybuf");
if (dbp != NULL) {
while (dbp->element.refs > 0U) {
chFactoryReleaseBuffer(dbp);
}
}
}
static void oslib_test_004_002_execute(void) {
dyn_buffer_t *dbp;
void *p1;
size_t total_size, largest_size;
/* [4.2.1] Retrieving a dynamic buffer by name, must not exist.*/
/* [4.2.1] Single block allocation using chHeapAlloc() then the block
is freed using chHeapFree(), must not fail.*/
test_set_step(1);
{
dbp = chFactoryFindBuffer("mybuf");
test_assert(dbp == NULL, "found");
(void)chHeapStatus(NULL, &total_size, &largest_size);
p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
test_assert(p1 != NULL, "allocation failed");
chHeapFree(p1);
}
/* [4.2.2] Creating a dynamic buffer it must not exists, must
succeed.*/
/* [4.2.2] Testing allocation failure.*/
test_set_step(2);
{
dbp = chFactoryCreateBuffer("mybuf", 128U);
test_assert(dbp != NULL, "cannot create");
}
/* [4.2.3] Creating a dynamic buffer with the same name, must fail.*/
test_set_step(3);
{
dyn_buffer_t *dbp1;
dbp1 = chFactoryCreateBuffer("mybuf", 128U);
test_assert(dbp1 == NULL, "can create");
}
/* [4.2.4] Retrieving the dynamic buffer by name, must exist, then
increasing the reference counter, finally releasing both
references.*/
test_set_step(4);
{
dyn_buffer_t *dbp1, *dbp2;
dbp1 = chFactoryFindBuffer("mybuf");
test_assert(dbp1 != NULL, "not found");
test_assert(dbp == dbp1, "object reference mismatch");
test_assert(dbp1->element.refs == 2, "object reference mismatch");
dbp2 = (dyn_buffer_t *)chFactoryDuplicateReference(&dbp1->element);
test_assert(dbp1 == dbp2, "object reference mismatch");
test_assert(dbp2->element.refs == 3, "object reference mismatch");
chFactoryReleaseBuffer(dbp2);
test_assert(dbp1->element.refs == 2, "references mismatch");
chFactoryReleaseBuffer(dbp1);
test_assert(dbp->element.refs == 1, "references mismatch");
}
/* [4.2.5] Releasing the first reference to the dynamic buffer, must
not trigger an assertion.*/
test_set_step(5);
{
chFactoryReleaseBuffer(dbp);
}
/* [4.2.6] Retrieving the dynamic buffer by name again, must not
exist.*/
test_set_step(6);
{
dbp = chFactoryFindBuffer("mybuf");
test_assert(dbp == NULL, "found");
p1 = chHeapAlloc(NULL, (size_t)-256);
test_assert(p1 == NULL, "allocation not failed");
}
}
static const testcase_t oslib_test_004_002 = {
"Dynamic Buffers Factory",
"Default Heap",
NULL,
NULL,
oslib_test_004_002_teardown,
oslib_test_004_002_execute
};
#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE */
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
/**
* @page oslib_test_004_003 [4.3] Dynamic Semaphores Factory
*
* <h2>Description</h2>
* This test case verifies the dynamic semaphores factory.
*
* <h2>Conditions</h2>
* This test is only executed if the following preprocessor condition
* evaluates to true:
* - CH_CFG_FACTORY_SEMAPHORES == TRUE
* .
*
* <h2>Test Steps</h2>
* - [4.3.1] Retrieving a dynamic semaphore by name, must not exist.
* - [4.3.2] Creating a dynamic semaphore it must not exists, must
* succeed.
* - [4.3.3] Creating a dynamic semaphore with the same name, must
* fail.
* - [4.3.4] Retrieving the dynamic semaphore by name, must exist, then
* increasing the reference counter, finally releasing both
* references.
* - [4.3.5] Releasing the first reference to the dynamic semaphore
* must not trigger an assertion.
* - [4.3.6] Retrieving the dynamic semaphore by name again, must not
* exist.
* .
*/
static void oslib_test_004_003_teardown(void) {
dyn_semaphore_t *dsp;
dsp = chFactoryFindSemaphore("mysem");
if (dsp != NULL) {
while (dsp->element.refs > 0U) {
chFactoryReleaseSemaphore(dsp);
}
}
}
static void oslib_test_004_003_execute(void) {
dyn_semaphore_t *dsp;
/* [4.3.1] Retrieving a dynamic semaphore by name, must not exist.*/
test_set_step(1);
{
dsp = chFactoryFindSemaphore("mysem");
test_assert(dsp == NULL, "found");
}
/* [4.3.2] Creating a dynamic semaphore it must not exists, must
succeed.*/
test_set_step(2);
{
dsp = chFactoryCreateSemaphore("mysem", 0);
test_assert(dsp != NULL, "cannot create");
}
/* [4.3.3] Creating a dynamic semaphore with the same name, must
fail.*/
test_set_step(3);
{
dyn_semaphore_t *dsp1;
dsp1 = chFactoryCreateSemaphore("mysem", 0);
test_assert(dsp1 == NULL, "can create");
}
/* [4.3.4] Retrieving the dynamic semaphore by name, must exist, then
increasing the reference counter, finally releasing both
references.*/
test_set_step(4);
{
dyn_semaphore_t *dsp1, *dsp2;
dsp1 = chFactoryFindSemaphore("mysem");
test_assert(dsp1 != NULL, "not found");
test_assert(dsp == dsp1, "object reference mismatch");
test_assert(dsp1->element.refs == 2, "object reference mismatch");
dsp2 = (dyn_semaphore_t *)chFactoryDuplicateReference(&dsp1->element);
test_assert(dsp1 == dsp2, "object reference mismatch");
test_assert(dsp2->element.refs == 3, "object reference mismatch");
chFactoryReleaseSemaphore(dsp2);
test_assert(dsp1->element.refs == 2, "references mismatch");
chFactoryReleaseSemaphore(dsp1);
test_assert(dsp->element.refs == 1, "references mismatch");
}
/* [4.3.5] Releasing the first reference to the dynamic semaphore
must not trigger an assertion.*/
test_set_step(5);
{
chFactoryReleaseSemaphore(dsp);
}
/* [4.3.6] Retrieving the dynamic semaphore by name again, must not
exist.*/
test_set_step(6);
{
dsp = chFactoryFindSemaphore("mysem");
test_assert(dsp == NULL, "found");
}
}
static const testcase_t oslib_test_004_003 = {
"Dynamic Semaphores Factory",
NULL,
oslib_test_004_003_teardown,
oslib_test_004_003_execute
};
#endif /* CH_CFG_FACTORY_SEMAPHORES == TRUE */
#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__)
/**
* @page oslib_test_004_004 [4.4] Dynamic Mailboxes Factory
*
* <h2>Description</h2>
* This test case verifies the dynamic mailboxes factory.
*
* <h2>Conditions</h2>
* This test is only executed if the following preprocessor condition
* evaluates to true:
* - CH_CFG_FACTORY_MAILBOXES == TRUE
* .
*
* <h2>Test Steps</h2>
* - [4.4.1] Retrieving a dynamic mailbox by name, must not exist.
* - [4.4.2] Creating a dynamic mailbox it must not exists, must
* succeed.
* - [4.4.3] Creating a dynamic mailbox with the same name, must fail.
* - [4.4.4] Retrieving the dynamic mailbox by name, must exist, then
* increasing the reference counter, finally releasing both
* references.
* - [4.4.5] Releasing the first reference to the dynamic mailbox must
* not trigger an assertion.
* - [4.4.6] Retrieving the dynamic mailbox by name again, must not
* exist.
* .
*/
static void oslib_test_004_004_teardown(void) {
dyn_mailbox_t *dmp;
dmp = chFactoryFindMailbox("mymbx");
if (dmp != NULL) {
while (dmp->element.refs > 0U) {
chFactoryReleaseMailbox(dmp);
}
}
}
static void oslib_test_004_004_execute(void) {
dyn_mailbox_t *dmp;
/* [4.4.1] Retrieving a dynamic mailbox by name, must not exist.*/
test_set_step(1);
{
dmp = chFactoryFindMailbox("mymbx");
test_assert(dmp == NULL, "found");
}
/* [4.4.2] Creating a dynamic mailbox it must not exists, must
succeed.*/
test_set_step(2);
{
dmp = chFactoryCreateMailbox("mymbx", 16U);
test_assert(dmp != NULL, "cannot create");
}
/* [4.4.3] Creating a dynamic mailbox with the same name, must
fail.*/
test_set_step(3);
{
dyn_mailbox_t *dmp1;
dmp1 = chFactoryCreateMailbox("mymbx", 16U);
test_assert(dmp1 == NULL, "can create");
}
/* [4.4.4] Retrieving the dynamic mailbox by name, must exist, then
increasing the reference counter, finally releasing both
references.*/
test_set_step(4);
{
dyn_mailbox_t *dmp1, *dmp2;
dmp1 = chFactoryFindMailbox("mymbx");
test_assert(dmp1 != NULL, "not found");
test_assert(dmp == dmp1, "object reference mismatch");
test_assert(dmp1->element.refs == 2, "object reference mismatch");
dmp2 = (dyn_mailbox_t *)chFactoryDuplicateReference(&dmp1->element);
test_assert(dmp1 == dmp2, "object reference mismatch");
test_assert(dmp2->element.refs == 3, "object reference mismatch");
chFactoryReleaseMailbox(dmp2);
test_assert(dmp1->element.refs == 2, "references mismatch");
chFactoryReleaseMailbox(dmp1);
test_assert(dmp->element.refs == 1, "references mismatch");
}
/* [4.4.5] Releasing the first reference to the dynamic mailbox must
not trigger an assertion.*/
test_set_step(5);
{
chFactoryReleaseMailbox(dmp);
}
/* [4.4.6] Retrieving the dynamic mailbox by name again, must not
exist.*/
test_set_step(6);
{
dmp = chFactoryFindMailbox("mymbx");
test_assert(dmp == NULL, "found");
}
}
static const testcase_t oslib_test_004_004 = {
"Dynamic Mailboxes Factory",
NULL,
oslib_test_004_004_teardown,
oslib_test_004_004_execute
};
#endif /* CH_CFG_FACTORY_MAILBOXES == TRUE */
#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
/**
* @page oslib_test_004_005 [4.5] Dynamic Objects FIFOs Factory
*
* <h2>Description</h2>
* This test case verifies the dynamic objects FIFOs factory.
*
* <h2>Conditions</h2>
* This test is only executed if the following preprocessor condition
* evaluates to true:
* - CH_CFG_FACTORY_OBJ_FIFOS == TRUE
* .
*
* <h2>Test Steps</h2>
* - [4.5.1] Retrieving a dynamic objects FIFO by name, must not exist.
* - [4.5.2] Creating a dynamic objects FIFO it must not exists, must
* succeed.
* - [4.5.3] Creating a dynamic objects FIFO with the same name, must
* fail.
* - [4.5.4] Retrieving the dynamic objects FIFO by name, must exist,
* then increasing the reference counter, finally releasing both
* references.
* - [4.5.5] Releasing the first reference to the dynamic objects FIFO
* must not trigger an assertion.
* - [4.5.6] Retrieving the dynamic objects FIFO by name again, must
* not exist.
* .
*/
static void oslib_test_004_005_teardown(void) {
dyn_objects_fifo_t *dofp;
dofp = chFactoryFindObjectsFIFO("myfifo");
if (dofp != NULL) {
while (dofp->element.refs > 0U) {
chFactoryReleaseObjectsFIFO(dofp);
}
}
}
static void oslib_test_004_005_execute(void) {
dyn_objects_fifo_t *dofp;
/* [4.5.1] Retrieving a dynamic objects FIFO by name, must not
exist.*/
test_set_step(1);
{
dofp = chFactoryFindObjectsFIFO("myfifo");
test_assert(dofp == NULL, "found");
}
/* [4.5.2] Creating a dynamic objects FIFO it must not exists, must
succeed.*/
test_set_step(2);
{
dofp = chFactoryCreateObjectsFIFO("myfifo", 16U, 16U, PORT_NATURAL_ALIGN);
test_assert(dofp != NULL, "cannot create");
}
/* [4.5.3] Creating a dynamic objects FIFO with the same name, must
fail.*/
test_set_step(3);
{
dyn_objects_fifo_t *dofp1;
dofp1 = chFactoryCreateObjectsFIFO("myfifo", 16U, 16U, PORT_NATURAL_ALIGN);
test_assert(dofp1 == NULL, "can create");
}
/* [4.5.4] Retrieving the dynamic objects FIFO by name, must exist,
then increasing the reference counter, finally releasing both
references.*/
test_set_step(4);
{
dyn_objects_fifo_t *dofp1, *dofp2;
dofp1 = chFactoryFindObjectsFIFO("myfifo");
test_assert(dofp1 != NULL, "not found");
test_assert(dofp == dofp1, "object reference mismatch");
test_assert(dofp1->element.refs == 2, "object reference mismatch");
dofp2 = (dyn_objects_fifo_t *)chFactoryDuplicateReference(&dofp1->element);
test_assert(dofp1 == dofp2, "object reference mismatch");
test_assert(dofp2->element.refs == 3, "object reference mismatch");
chFactoryReleaseObjectsFIFO(dofp2);
test_assert(dofp1->element.refs == 2, "references mismatch");
chFactoryReleaseObjectsFIFO(dofp1);
test_assert(dofp->element.refs == 1, "references mismatch");
}
/* [4.5.5] Releasing the first reference to the dynamic objects FIFO
must not trigger an assertion.*/
test_set_step(5);
{
chFactoryReleaseObjectsFIFO(dofp);
}
/* [4.5.6] Retrieving the dynamic objects FIFO by name again, must
not exist.*/
test_set_step(6);
{
dofp = chFactoryFindObjectsFIFO("myfifo");
test_assert(dofp == NULL, "found");
}
}
static const testcase_t oslib_test_004_005 = {
"Dynamic Objects FIFOs Factory",
NULL,
oslib_test_004_005_teardown,
oslib_test_004_005_execute
};
#endif /* CH_CFG_FACTORY_OBJ_FIFOS == TRUE */
#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__)
/**
* @page oslib_test_004_006 [4.6] Dynamic Pipes Factory
*
* <h2>Description</h2>
* This test case verifies the dynamic pipes factory.
*
* <h2>Conditions</h2>
* This test is only executed if the following preprocessor condition
* evaluates to true:
* - CH_CFG_FACTORY_PIPES == TRUE
* .
*
* <h2>Test Steps</h2>
* - [4.6.1] Retrieving a dynamic pipe by name, must not exist.
* - [4.6.2] Creating a dynamic pipe it must not exists, must succeed.
* - [4.6.3] Creating a dynamic pipe with the same name, must fail.
* - [4.6.4] Retrieving the dynamic pipe by name, must exist, then
* increasing the reference counter, finally releasing both
* references.
* - [4.6.5] Releasing the first reference to the dynamic pipe must not
* trigger an assertion.
* - [4.6.6] Retrieving the dynamic pipe by name again, must not exist.
* .
*/
static void oslib_test_004_006_teardown(void) {
dyn_pipe_t *dpp;
dpp = chFactoryFindPipe("mypipe");
if (dpp != NULL) {
while (dpp->element.refs > 0U) {
chFactoryReleasePipe(dpp);
}
}
}
static void oslib_test_004_006_execute(void) {
dyn_pipe_t *dpp;
/* [4.6.1] Retrieving a dynamic pipe by name, must not exist.*/
test_set_step(1);
{
dpp = chFactoryFindPipe("mypipe");
test_assert(dpp == NULL, "found");
}
/* [4.6.2] Creating a dynamic pipe it must not exists, must
succeed.*/
test_set_step(2);
{
dpp = chFactoryCreatePipe("mypipe", 16U);
test_assert(dpp != NULL, "cannot create");
}
/* [4.6.3] Creating a dynamic pipe with the same name, must fail.*/
test_set_step(3);
{
dyn_pipe_t *dpp1;
dpp1 = chFactoryCreatePipe("mypipe", 16U);
test_assert(dpp1 == NULL, "can create");
}
/* [4.6.4] Retrieving the dynamic pipe by name, must exist, then
increasing the reference counter, finally releasing both
references.*/
test_set_step(4);
{
dyn_pipe_t *dpp1, *dpp2;
dpp1 = chFactoryFindPipe("mypipe");
test_assert(dpp1 != NULL, "not found");
test_assert(dpp == dpp1, "object reference mismatch");
test_assert(dpp1->element.refs == 2, "object reference mismatch");
dpp2 = (dyn_pipe_t *)chFactoryDuplicateReference(&dpp1->element);
test_assert(dpp1 == dpp2, "object reference mismatch");
test_assert(dpp2->element.refs == 3, "object reference mismatch");
chFactoryReleasePipe(dpp2);
test_assert(dpp1->element.refs == 2, "references mismatch");
chFactoryReleasePipe(dpp1);
test_assert(dpp->element.refs == 1, "references mismatch");
}
/* [4.6.5] Releasing the first reference to the dynamic pipe must not
trigger an assertion.*/
test_set_step(5);
{
chFactoryReleasePipe(dpp);
}
/* [4.6.6] Retrieving the dynamic pipe by name again, must not
exist.*/
test_set_step(6);
{
dpp = chFactoryFindPipe("mypipe");
test_assert(dpp == NULL, "found");
}
}
static const testcase_t oslib_test_004_006 = {
"Dynamic Pipes Factory",
NULL,
oslib_test_004_006_teardown,
oslib_test_004_006_execute
};
#endif /* CH_CFG_FACTORY_PIPES == TRUE */
/****************************************************************************
* Exported data.
@ -749,33 +264,17 @@ static const testcase_t oslib_test_004_006 = {
* @brief Array of test cases.
*/
const testcase_t * const oslib_test_sequence_004_array[] = {
#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__)
&oslib_test_004_001,
#endif
#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__)
&oslib_test_004_002,
#endif
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
&oslib_test_004_003,
#endif
#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__)
&oslib_test_004_004,
#endif
#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__)
&oslib_test_004_005,
#endif
#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__)
&oslib_test_004_006,
#endif
NULL
};
/**
* @brief Objects Factory.
* @brief Memory Heaps.
*/
const testsequence_t oslib_test_sequence_004 = {
"Objects Factory",
"Memory Heaps",
oslib_test_sequence_004_array
};
#endif /* (CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE) */
#endif /* CH_CFG_USE_HEAP */