git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9192 35acf78f-673a-0410-8e92-d51de3d6d3f4

master
Giovanni Di Sirio 2016-04-01 05:08:20 +00:00
parent e47e9096bd
commit f2fdc06c4d
7 changed files with 562 additions and 2 deletions

View File

@ -36,8 +36,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="components"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="source"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="components"/>
</sourceEntries>
</configuration>
</storageModule>

View File

@ -76,6 +76,7 @@ union test_buffers {
uint8_t buffer[WA_SIZE * 5];
};
extern union test_buffers test;
extern thread_t *threads[MAX_THREADS];
extern void * ROMCONST wa[5];
@ -3800,6 +3801,262 @@ test_assert(p1 == NULL, "allocation not failed");]]></value>
</case>
</cases>
</sequence>
<sequence>
<type index="0">
<value>Internal Tests</value>
</type>
<brief>
<value>Dynamic threads.</value>
</brief>
<description>
<value>This module implements the test sequence for the dynamic thread creation APIs.</value>
</description>
<condition>
<value>CH_CFG_USE_DYNAMIC</value>
</condition>
<shared_code>
<value><![CDATA[#if CH_CFG_USE_HEAP
static memory_heap_t heap1;
#endif
#if CH_CFG_USE_MEMPOOLS
static memory_pool_t mp1;
#endif
static THD_FUNCTION(dyn_thread1, p) {
test_emit_token(*(char *)p);
}]]></value>
</shared_code>
<cases>
<case>
<brief>
<value>Threads creation from Memory Heap.</value>
</brief>
<description>
<value>Two threads are started by allocating the memory from the Memory Heap then the remaining heap space is arbitrarily allocated and a third tread startup is attempted.&lt;br&gt;&#xD;
The test expects the first two threads to successfully start and the last one to fail.</value>
</description>
<condition>
<value>CH_CFG_USE_HEAP</value>
</condition>
<various_code>
<setup_code>
<value><![CDATA[chHeapObjectInit(&heap1, test.buffer, sizeof(union test_buffers));]]></value>
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[size_t n1, total1, largest1;
size_t n2, total2, largest2;
tprio_t prio;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Getting base priority for threads.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[prio = chThdGetPriorityX();]]></value>
</code>
</step>
<step>
<description>
<value>Getting heap info before the test.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[n1 = chHeapStatus(&heap1, &total1, &largest1);
test_assert(n1 == 1, "heap fragmented");]]></value>
</code>
</step>
<step>
<description>
<value>Creating 1, it is expected to succeed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[threads[0] = chThdCreateFromHeap(&heap1,
THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE),
"dyn1",
prio-1, dyn_thread1, "A");
test_assert(threads[0] != NULL, "thread creation failed");]]></value>
</code>
</step>
<step>
<description>
<value>Creating thread 2, it is expected to succeed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[threads[1] = chThdCreateFromHeap(&heap1,
THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE),
"dyn2",
prio-2, dyn_thread1, "B");
test_assert(threads[1] != NULL, "thread creation failed");]]></value>
</code>
</step>
<step>
<description>
<value>Creating thread 3, it is expected to fail</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[threads[2] = chThdCreateFromHeap(&heap1,
THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE * 16),
"dyn3",
prio-3, dyn_thread1, "C");
test_assert(threads[2] == NULL, "thread creation not failed");]]></value>
</code>
</step>
<step>
<description>
<value>Letting threads execute then checking the start order and freeing memory.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_wait_threads();
test_assert_sequence("AB", "invalid sequence");]]></value>
</code>
</step>
<step>
<description>
<value>Getting heap info again for verification.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[n2 = chHeapStatus(&heap1, &total2, &largest2);
test_assert(n1 == n2, "fragmentation changed");
test_assert(total1 == total2, "total free space changed");
test_assert(largest1 == largest2, "largest fragment size changed");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
<value>Threads creation from Memory Pool.</value>
</brief>
<description>
<value>Five thread creation are attempted from a pool containing only four elements.&lt;br&gt;&#xD;
The test expects the first four threads to successfully start and the last one to fail.</value>
</description>
<condition>
<value>CH_CFG_USE_MEMPOOLS</value>
</condition>
<various_code>
<setup_code>
<value><![CDATA[chPoolObjectInit(&mp1, THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), NULL);]]></value>
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
<value><![CDATA[unsigned i;
tprio_t prio;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
<value>Adding four working areas to the pool.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[for (i = 0; i < 4; i++)
chPoolFree(&mp1, wa[i]);]]></value>
</code>
</step>
<step>
<description>
<value>Getting base priority for threads.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[prio = chThdGetPriorityX();]]></value>
</code>
</step>
<step>
<description>
<value>Creating the five threads.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[threads[0] = chThdCreateFromMemoryPool(&mp1, "dyn1", prio-1, dyn_thread1, "A");
threads[1] = chThdCreateFromMemoryPool(&mp1, "dyn2", prio-2, dyn_thread1, "B");
threads[2] = chThdCreateFromMemoryPool(&mp1, "dyn3", prio-3, dyn_thread1, "C");
threads[3] = chThdCreateFromMemoryPool(&mp1, "dyn4", prio-4, dyn_thread1, "D");
threads[4] = chThdCreateFromMemoryPool(&mp1, "dyn5", prio-5, dyn_thread1, "E");]]></value>
</code>
</step>
<step>
<description>
<value>Testing that only the fifth thread creation failed.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_assert((threads[0] != NULL) &&
(threads[1] != NULL) &&
(threads[2] != NULL) &&
(threads[3] != NULL),
"thread creation failed");
test_assert(threads[4] == NULL,
"thread creation not failed");]]></value>
</code>
</step>
<step>
<description>
<value>Letting them run, free the memory then checking the execution sequence.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[test_wait_threads();
test_assert_sequence("ABCD", "invalid sequence");]]></value>
</code>
</step>
<step>
<description>
<value>Testing that the pool contains four elements again.</value>
</description>
<tags>
<value />
</tags>
<code>
<value><![CDATA[for (i = 0; i < 4; i++)
test_assert(chPoolAlloc(&mp1) != NULL, "pool list empty");
test_assert(chPoolAlloc(&mp1) == NULL, "pool list not empty");]]></value>
</code>
</step>
</steps>
</case>
</cases>
</sequence>
</sequences>
</instance>
</instances>

View File

@ -31,6 +31,7 @@
* - @subpage test_sequence_008
* - @subpage test_sequence_009
* - @subpage test_sequence_010
* - @subpage test_sequence_011
* .
*/
@ -63,6 +64,7 @@ const testcase_t * const *test_suite[] = {
test_sequence_008,
test_sequence_009,
test_sequence_010,
test_sequence_011,
NULL
};

View File

@ -32,6 +32,7 @@
#include "test_sequence_008.h"
#include "test_sequence_009.h"
#include "test_sequence_010.h"
#include "test_sequence_011.h"
#if !defined(__DOXYGEN__)
@ -96,6 +97,7 @@ union test_buffers {
uint8_t buffer[WA_SIZE * 5];
};
extern union test_buffers test;
extern thread_t *threads[MAX_THREADS];
extern void * ROMCONST wa[5];

View File

@ -0,0 +1,281 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "hal.h"
#include "ch_test.h"
#include "test_root.h"
/**
* @page test_sequence_011 [11] Dynamic threads
*
* File: @ref test_sequence_011.c
*
* <h2>Description</h2>
* This module implements the test sequence for the dynamic thread
* creation APIs.
*
* <h2>Conditions</h2>
* This sequence is only executed if the following preprocessor condition
* evaluates to true:
* - CH_CFG_USE_DYNAMIC
* .
*
* <h2>Test Cases</h2>
* - @subpage test_011_001
* - @subpage test_011_002
* .
*/
#if (CH_CFG_USE_DYNAMIC) || defined(__DOXYGEN__)
/****************************************************************************
* Shared code.
****************************************************************************/
#if CH_CFG_USE_HEAP
static memory_heap_t heap1;
#endif
#if CH_CFG_USE_MEMPOOLS
static memory_pool_t mp1;
#endif
static THD_FUNCTION(dyn_thread1, p) {
test_emit_token(*(char *)p);
}
/****************************************************************************
* Test cases.
****************************************************************************/
#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
/**
* @page test_011_001 [11.1] Threads creation from Memory Heap
*
* <h2>Description</h2>
* Two threads are started by allocating the memory from the Memory
* Heap then the remaining heap space is arbitrarily allocated and a
* third tread startup is attempted.<br> The test expects the first two
* threads to successfully start and the last one to fail.
*
* <h2>Conditions</h2>
* This test is only executed if the following preprocessor condition
* evaluates to true:
* - CH_CFG_USE_HEAP
* .
*
* <h2>Test Steps</h2>
* - [11.1.1] Getting base priority for threads.
* - [11.1.2] Getting heap info before the test.
* - [11.1.3] Creating 1, it is expected to succeed.
* - [11.1.4] Creating thread 2, it is expected to succeed.
* - [11.1.5] Creating thread 3, it is expected to fail.
* - [11.1.6] Letting threads execute then checking the start order and
* freeing memory.
* - [11.1.7] Getting heap info again for verification.
* .
*/
static void test_011_001_setup(void) {
chHeapObjectInit(&heap1, test.buffer, sizeof(union test_buffers));
}
static void test_011_001_execute(void) {
size_t n1, total1, largest1;
size_t n2, total2, largest2;
tprio_t prio;
/* [11.1.1] Getting base priority for threads.*/
test_set_step(1);
{
prio = chThdGetPriorityX();
}
/* [11.1.2] Getting heap info before the test.*/
test_set_step(2);
{
n1 = chHeapStatus(&heap1, &total1, &largest1);
test_assert(n1 == 1, "heap fragmented");
}
/* [11.1.3] Creating 1, it is expected to succeed.*/
test_set_step(3);
{
threads[0] = chThdCreateFromHeap(&heap1,
THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE),
"dyn1",
prio-1, dyn_thread1, "A");
test_assert(threads[0] != NULL, "thread creation failed");
}
/* [11.1.4] Creating thread 2, it is expected to succeed.*/
test_set_step(4);
{
threads[1] = chThdCreateFromHeap(&heap1,
THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE),
"dyn2",
prio-2, dyn_thread1, "B");
test_assert(threads[1] != NULL, "thread creation failed");
}
/* [11.1.5] Creating thread 3, it is expected to fail.*/
test_set_step(5);
{
threads[2] = chThdCreateFromHeap(&heap1,
THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE * 16),
"dyn3",
prio-3, dyn_thread1, "C");
test_assert(threads[2] == NULL, "thread creation not failed");
}
/* [11.1.6] Letting threads execute then checking the start order and
freeing memory.*/
test_set_step(6);
{
test_wait_threads();
test_assert_sequence("AB", "invalid sequence");
}
/* [11.1.7] Getting heap info again for verification.*/
test_set_step(7);
{
n2 = chHeapStatus(&heap1, &total2, &largest2);
test_assert(n1 == n2, "fragmentation changed");
test_assert(total1 == total2, "total free space changed");
test_assert(largest1 == largest2, "largest fragment size changed");
}
}
static const testcase_t test_011_001 = {
"Threads creation from Memory Heap",
test_011_001_setup,
NULL,
test_011_001_execute
};
#endif /* CH_CFG_USE_HEAP */
#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
/**
* @page test_011_002 [11.2] Threads creation from Memory Pool
*
* <h2>Description</h2>
* Five thread creation are attempted from a pool containing only four
* elements.<br> The test expects the first four threads to
* successfully start and the last one to fail.
*
* <h2>Conditions</h2>
* This test is only executed if the following preprocessor condition
* evaluates to true:
* - CH_CFG_USE_MEMPOOLS
* .
*
* <h2>Test Steps</h2>
* - [11.2.1] Adding four working areas to the pool.
* - [11.2.2] Getting base priority for threads.
* - [11.2.3] Creating the five threads.
* - [11.2.4] Testing that only the fifth thread creation failed.
* - [11.2.5] Letting them run, free the memory then checking the
* execution sequence.
* - [11.2.6] Testing that the pool contains four elements again.
* .
*/
static void test_011_002_setup(void) {
chPoolObjectInit(&mp1, THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), NULL);
}
static void test_011_002_execute(void) {
unsigned i;
tprio_t prio;
/* [11.2.1] Adding four working areas to the pool.*/
test_set_step(1);
{
for (i = 0; i < 4; i++)
chPoolFree(&mp1, wa[i]);
}
/* [11.2.2] Getting base priority for threads.*/
test_set_step(2);
{
prio = chThdGetPriorityX();
}
/* [11.2.3] Creating the five threads.*/
test_set_step(3);
{
threads[0] = chThdCreateFromMemoryPool(&mp1, "dyn1", prio-1, dyn_thread1, "A");
threads[1] = chThdCreateFromMemoryPool(&mp1, "dyn2", prio-2, dyn_thread1, "B");
threads[2] = chThdCreateFromMemoryPool(&mp1, "dyn3", prio-3, dyn_thread1, "C");
threads[3] = chThdCreateFromMemoryPool(&mp1, "dyn4", prio-4, dyn_thread1, "D");
threads[4] = chThdCreateFromMemoryPool(&mp1, "dyn5", prio-5, dyn_thread1, "E");
}
/* [11.2.4] Testing that only the fifth thread creation failed.*/
test_set_step(4);
{
test_assert((threads[0] != NULL) &&
(threads[1] != NULL) &&
(threads[2] != NULL) &&
(threads[3] != NULL),
"thread creation failed");
test_assert(threads[4] == NULL,
"thread creation not failed");
}
/* [11.2.5] Letting them run, free the memory then checking the
execution sequence.*/
test_set_step(5);
{
test_wait_threads();
test_assert_sequence("ABCD", "invalid sequence");
}
/* [11.2.6] Testing that the pool contains four elements again.*/
test_set_step(6);
{
for (i = 0; i < 4; i++)
test_assert(chPoolAlloc(&mp1) != NULL, "pool list empty");
test_assert(chPoolAlloc(&mp1) == NULL, "pool list not empty");
}
}
static const testcase_t test_011_002 = {
"Threads creation from Memory Pool",
test_011_002_setup,
NULL,
test_011_002_execute
};
#endif /* CH_CFG_USE_MEMPOOLS */
/****************************************************************************
* Exported data.
****************************************************************************/
/**
* @brief Dynamic threads.
*/
const testcase_t * const test_sequence_011[] = {
#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
&test_011_001,
#endif
#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
&test_011_002,
#endif
NULL
};
#endif /* CH_CFG_USE_DYNAMIC */

View File

@ -0,0 +1,17 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
extern const testcase_t * const test_sequence_011[];

View File

@ -10,7 +10,8 @@ TESTSRC = ${CHIBIOS}/test/lib/ch_test.c \
${CHIBIOS}/test/rt/source/test/test_sequence_007.c \
${CHIBIOS}/test/rt/source/test/test_sequence_008.c \
${CHIBIOS}/test/rt/source/test/test_sequence_009.c \
${CHIBIOS}/test/rt/source/test/test_sequence_010.c
${CHIBIOS}/test/rt/source/test/test_sequence_010.c \
${CHIBIOS}/test/rt/source/test/test_sequence_011.c
# Required include directories
TESTINC = ${CHIBIOS}/test/lib \