diff --git a/test/rt/.cproject b/test/rt/.cproject index e92ac3785..e849ada7d 100644 --- a/test/rt/.cproject +++ b/test/rt/.cproject @@ -36,8 +36,8 @@ - + diff --git a/test/rt/configuration.xml b/test/rt/configuration.xml index cfeff88f4..326e7359d 100644 --- a/test/rt/configuration.xml +++ b/test/rt/configuration.xml @@ -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");]]> + + + Internal Tests + + + Dynamic threads. + + + This module implements the test sequence for the dynamic thread creation APIs. + + + CH_CFG_USE_DYNAMIC + + + + + + + + Threads creation from Memory Heap. + + + 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. + + + CH_CFG_USE_HEAP + + + + + + + + + + + + + + + + Getting base priority for threads. + + + + + + + + + + + Getting heap info before the test. + + + + + + + + + + + Creating 1, it is expected to succeed. + + + + + + + + + + + Creating thread 2, it is expected to succeed. + + + + + + + + + + + Creating thread 3, it is expected to fail + + + + + + + + + + + Letting threads execute then checking the start order and freeing memory. + + + + + + + + + + + Getting heap info again for verification. + + + + + + + + + + + + + Threads creation from Memory Pool. + + + 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. + + + CH_CFG_USE_MEMPOOLS + + + + + + + + + + + + + + + + Adding four working areas to the pool. + + + + + + + + + + + Getting base priority for threads. + + + + + + + + + + + Creating the five threads. + + + + + + + + + + + Testing that only the fifth thread creation failed. + + + + + + + + + + + Letting them run, free the memory then checking the execution sequence. + + + + + + + + + + + Testing that the pool contains four elements again. + + + + + + + + + + + + diff --git a/test/rt/source/test/test_root.c b/test/rt/source/test/test_root.c index 9ecbd3dea..fe8f096c8 100644 --- a/test/rt/source/test/test_root.c +++ b/test/rt/source/test/test_root.c @@ -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 }; diff --git a/test/rt/source/test/test_root.h b/test/rt/source/test/test_root.h index 6bbb1c989..e0e439eff 100644 --- a/test/rt/source/test/test_root.h +++ b/test/rt/source/test/test_root.h @@ -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]; diff --git a/test/rt/source/test/test_sequence_011.c b/test/rt/source/test/test_sequence_011.c new file mode 100644 index 000000000..0f1ac7b21 --- /dev/null +++ b/test/rt/source/test/test_sequence_011.c @@ -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 + * + *

Description

+ * This module implements the test sequence for the dynamic thread + * creation APIs. + * + *

Conditions

+ * This sequence is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_DYNAMIC + * . + * + *

Test Cases

+ * - @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 + * + *

Description

+ * 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.
The test expects the first two + * threads to successfully start and the last one to fail. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_HEAP + * . + * + *

Test Steps

+ * - [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 + * + *

Description

+ * Five thread creation are attempted from a pool containing only four + * elements.
The test expects the first four threads to + * successfully start and the last one to fail. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_MEMPOOLS + * . + * + *

Test Steps

+ * - [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 */ diff --git a/test/rt/source/test/test_sequence_011.h b/test/rt/source/test/test_sequence_011.h new file mode 100644 index 000000000..8d865a9f0 --- /dev/null +++ b/test/rt/source/test/test_sequence_011.h @@ -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[]; diff --git a/test/rt/test.mk b/test/rt/test.mk index 2afe2ce8d..b47ad6658 100644 --- a/test/rt/test.mk +++ b/test/rt/test.mk @@ -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 \