From 3b3afb7d55d3822b4ae734d166022e327ee0c563 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sun, 17 Sep 2017 15:38:40 +0000 Subject: Improved RT and NIL test suite. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10614 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- test/nil/source/test/test_root.c | 12 +- test/nil/source/test/test_root.h | 1 + test/nil/source/test/test_sequence_001.c | 162 ++++++------- test/nil/source/test/test_sequence_002.c | 226 ++++++------------ test/nil/source/test/test_sequence_003.c | 234 ++++++++++++------- test/nil/source/test/test_sequence_004.c | 387 +++++++------------------------ test/nil/source/test/test_sequence_005.c | 342 ++++++++++++++++++--------- test/nil/source/test/test_sequence_006.c | 297 +++++++++++++----------- test/nil/source/test/test_sequence_007.c | 273 ++++++++++++++++++++++ test/nil/source/test/test_sequence_007.h | 27 +++ 10 files changed, 1083 insertions(+), 878 deletions(-) create mode 100644 test/nil/source/test/test_sequence_007.c create mode 100644 test/nil/source/test/test_sequence_007.h (limited to 'test/nil/source') diff --git a/test/nil/source/test/test_root.c b/test/nil/source/test/test_root.c index 177a46853..a41bb56bc 100644 --- a/test/nil/source/test/test_root.c +++ b/test/nil/source/test/test_root.c @@ -27,6 +27,7 @@ * - @subpage test_sequence_004 * - @subpage test_sequence_005 * - @subpage test_sequence_006 + * - @subpage test_sequence_007 * . */ @@ -50,18 +51,19 @@ */ const testcase_t * const *test_suite[] = { test_sequence_001, -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) test_sequence_002, -#endif +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) test_sequence_003, -#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__) +#endif test_sequence_004, +#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__) + test_sequence_005, #endif #if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) - test_sequence_005, + test_sequence_006, #endif #if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) - test_sequence_006, + test_sequence_007, #endif NULL }; diff --git a/test/nil/source/test/test_root.h b/test/nil/source/test/test_root.h index 694abf9c5..a5b5d6958 100644 --- a/test/nil/source/test/test_root.h +++ b/test/nil/source/test/test_root.h @@ -28,6 +28,7 @@ #include "test_sequence_004.h" #include "test_sequence_005.h" #include "test_sequence_006.h" +#include "test_sequence_007.h" #if !defined(__DOXYGEN__) diff --git a/test/nil/source/test/test_sequence_001.c b/test/nil/source/test/test_sequence_001.c index df99ee49b..683a26f3f 100644 --- a/test/nil/source/test/test_sequence_001.c +++ b/test/nil/source/test/test_sequence_001.c @@ -22,13 +22,13 @@ * @file test_sequence_001.c * @brief Test Sequence 001 code. * - * @page test_sequence_001 [1] Threads Functionality + * @page test_sequence_001 [1] Information * * File: @ref test_sequence_001.c * *

Description

- * This sequence tests the ChibiOS/NIL functionalities related to - * threading. + * This sequence reports configuration and version information about + * the NIL kernel. * *

Test Cases

* - @subpage test_001_001 @@ -47,123 +47,115 @@ ****************************************************************************/ /** - * @page test_001_001 [1.1] System Tick Counter functionality + * @page test_001_001 [1.1] Kernel Info * *

Description

- * The functionality of the API @p chVTGetSystemTimeX() is tested. + * The version numbers are reported. * *

Test Steps

- * - [1.1.1] A System Tick Counter increment is expected, the test - * simply hangs if it does not happen. + * - [1.1.1] Prints the version string. * . */ static void test_001_001_execute(void) { - /* [1.1.1] A System Tick Counter increment is expected, the test - simply hangs if it does not happen.*/ + /* [1.1.1] Prints the version string.*/ test_set_step(1); { - systime_t time = chVTGetSystemTimeX(); - while (time == chVTGetSystemTimeX()) { - } + test_println("*** Product: ChibiOS/NIL"); + test_print("*** Stable Flag: "); + test_printn(CH_KERNEL_STABLE); + test_println(""); + test_print("*** Version String: "); + test_println(CH_KERNEL_VERSION); + test_print("*** Major Number: "); + test_printn(CH_KERNEL_MAJOR); + test_println(""); + test_print("*** Minor Number: "); + test_printn(CH_KERNEL_MINOR); + test_println(""); + test_print("*** Patch Number: "); + test_printn(CH_KERNEL_PATCH); + test_println(""); } } static const testcase_t test_001_001 = { - "System Tick Counter functionality", + "Kernel Info", NULL, NULL, test_001_001_execute }; /** - * @page test_001_002 [1.2] Thread Sleep functionality + * @page test_001_002 [1.2] Kernel Settings * *

Description

- * The functionality of @p chThdSleep() and derivatives is tested. + * The static kernel settings are reported. * *

Test Steps

- * - [1.2.1] The current system time is read then a sleep is performed - * for 100 system ticks and on exit the system time is verified - * again. - * - [1.2.2] The current system time is read then a sleep is performed - * for 100000 microseconds and on exit the system time is verified - * again. - * - [1.2.3] The current system time is read then a sleep is performed - * for 100 milliseconds and on exit the system time is verified - * again. - * - [1.2.4] The current system time is read then a sleep is performed - * for 1 second and on exit the system time is verified again. - * - [1.2.5] Function chThdSleepUntil() is tested with a timeline of - * "now" + 100 ticks. + * - [1.2.1] Prints the configuration options settings. * . */ static void test_001_002_execute(void) { - systime_t time; - /* [1.2.1] The current system time is read then a sleep is performed - for 100 system ticks and on exit the system time is verified - again.*/ + /* [1.2.1] Prints the configuration options settings.*/ test_set_step(1); { - time = chVTGetSystemTimeX(); - chThdSleep(100); - test_assert_time_window(time + 100, - time + 100 + 1, - "out of time window"); - } - - /* [1.2.2] The current system time is read then a sleep is performed - for 100000 microseconds and on exit the system time is verified - again.*/ - test_set_step(2); - { - time = chVTGetSystemTimeX(); - chThdSleepMicroseconds(100000); - test_assert_time_window(time + US2ST(100000), - time + US2ST(100000) + 1, - "out of time window"); - } - - /* [1.2.3] The current system time is read then a sleep is performed - for 100 milliseconds and on exit the system time is verified - again.*/ - test_set_step(3); - { - time = chVTGetSystemTimeX(); - chThdSleepMilliseconds(100); - test_assert_time_window(time + MS2ST(100), - time + MS2ST(100) + 1, - "out of time window"); - } - - /* [1.2.4] The current system time is read then a sleep is performed - for 1 second and on exit the system time is verified again.*/ - test_set_step(4); - { - time = chVTGetSystemTimeX(); - chThdSleepSeconds(1); - test_assert_time_window(time + S2ST(1), - time + S2ST(1) + 1, - "out of time window"); - } - - /* [1.2.5] Function chThdSleepUntil() is tested with a timeline of - "now" + 100 ticks.*/ - test_set_step(5); - { - time = chVTGetSystemTimeX(); - chThdSleepUntil(time + 100); - test_assert_time_window(time + 100, - time + 100 + 1, - "out of time window"); + test_print("*** CH_CFG_NUM_THREADS: "); + test_printn(CH_CFG_NUM_THREADS); + test_println(""); + test_print("*** CH_CFG_ST_RESOLUTION: "); + test_printn(CH_CFG_ST_RESOLUTION); + test_println(""); + test_print("*** CH_CFG_ST_FREQUENCY: "); + test_printn(CH_CFG_ST_FREQUENCY); + test_println(""); + test_print("*** CH_CFG_ST_TIMEDELTA: "); + test_printn(CH_CFG_ST_TIMEDELTA); + test_println(""); + test_print("*** CH_CFG_USE_SEMAPHORES: "); + test_printn(CH_CFG_USE_SEMAPHORES); + test_println(""); + test_print("*** CH_CFG_USE_MUTEXES: "); + test_printn(CH_CFG_USE_MUTEXES); + test_println(""); + test_print("*** CH_CFG_USE_EVENTS: "); + test_printn(CH_CFG_USE_EVENTS); + test_println(""); + test_print("*** CH_CFG_USE_MAILBOXES: "); + test_printn(CH_CFG_USE_MAILBOXES); + test_println(""); + test_print("*** CH_CFG_USE_MEMCORE: "); + test_printn(CH_CFG_USE_MEMCORE); + test_println(""); + test_print("*** CH_CFG_USE_HEAP: "); + test_printn(CH_CFG_USE_HEAP); + test_println(""); + test_print("*** CH_CFG_USE_MEMPOOLS: "); + test_printn(CH_CFG_USE_MEMPOOLS); + test_println(""); + test_print("*** CH_DBG_STATISTICS: "); + test_printn(CH_DBG_STATISTICS); + test_println(""); + test_print("*** CH_DBG_SYSTEM_STATE_CHECK: "); + test_printn(CH_DBG_SYSTEM_STATE_CHECK); + test_println(""); + test_print("*** CH_DBG_ENABLE_CHECKS: "); + test_printn(CH_DBG_ENABLE_CHECKS); + test_println(""); + test_print("*** CH_DBG_ENABLE_ASSERTS: "); + test_printn(CH_DBG_ENABLE_ASSERTS); + test_println(""); + test_print("*** CH_DBG_ENABLE_STACK_CHECK: "); + test_printn(CH_DBG_ENABLE_STACK_CHECK); + test_println(""); } } static const testcase_t test_001_002 = { - "Thread Sleep functionality", + "Kernel Settings", NULL, NULL, test_001_002_execute @@ -174,7 +166,7 @@ static const testcase_t test_001_002 = { ****************************************************************************/ /** - * @brief Threads Functionality. + * @brief Information. */ const testcase_t * const test_sequence_001[] = { &test_001_001, diff --git a/test/nil/source/test/test_sequence_002.c b/test/nil/source/test/test_sequence_002.c index 1e0f41d43..9e72d707d 100644 --- a/test/nil/source/test/test_sequence_002.c +++ b/test/nil/source/test/test_sequence_002.c @@ -22,224 +22,151 @@ * @file test_sequence_002.c * @brief Test Sequence 002 code. * - * @page test_sequence_002 [2] Semaphores + * @page test_sequence_002 [2] Threads Functionality * * File: @ref test_sequence_002.c * *

Description

* This sequence tests the ChibiOS/NIL functionalities related to - * counter semaphores. - * - *

Conditions

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

Test Cases

* - @subpage test_002_001 * - @subpage test_002_002 - * - @subpage test_002_003 * . */ -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) - /**************************************************************************** * Shared code. ****************************************************************************/ #include "ch.h" -static semaphore_t sem1; - /**************************************************************************** * Test cases. ****************************************************************************/ /** - * @page test_002_001 [2.1] Semaphore primitives, no state change + * @page test_002_001 [2.1] System Tick Counter functionality * *

Description

- * Wait, Signal and Reset primitives are tested. The testing thread - * does not trigger a state change. + * The functionality of the API @p chVTGetSystemTimeX() is tested. * *

Test Steps

- * - [2.1.1] The function chSemWait() is invoked, after return the - * counter and the returned message are tested. - * - [2.1.2] The function chSemSignal() is invoked, after return the - * counter is tested. - * - [2.1.3] The function chSemReset() is invoked, after return the - * counter is tested. + * - [2.1.1] A System Tick Counter increment is expected, the test + * simply hangs if it does not happen. * . */ -static void test_002_001_setup(void) { - chSemObjectInit(&sem1, 1); -} - -static void test_002_001_teardown(void) { - chSemReset(&sem1, 0); -} - static void test_002_001_execute(void) { - /* [2.1.1] The function chSemWait() is invoked, after return the - counter and the returned message are tested.*/ + /* [2.1.1] A System Tick Counter increment is expected, the test + simply hangs if it does not happen.*/ test_set_step(1); { - msg_t msg; - - msg = chSemWait(&sem1); - test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value"); - test_assert(MSG_OK == msg, "wrong returned message"); - } - - /* [2.1.2] The function chSemSignal() is invoked, after return the - counter is tested.*/ - test_set_step(2); - { - chSemSignal(&sem1); - test_assert_lock(chSemGetCounterI(&sem1) == 1, "wrong counter value"); - } - - /* [2.1.3] The function chSemReset() is invoked, after return the - counter is tested.*/ - test_set_step(3); - { - chSemReset(&sem1, 2); - test_assert_lock(chSemGetCounterI(&sem1) == 2, "wrong counter value"); + systime_t time = chVTGetSystemTimeX(); + while (time == chVTGetSystemTimeX()) { + } } } static const testcase_t test_002_001 = { - "Semaphore primitives, no state change", - test_002_001_setup, - test_002_001_teardown, + "System Tick Counter functionality", + NULL, + NULL, test_002_001_execute }; /** - * @page test_002_002 [2.2] Semaphore primitives, with state change + * @page test_002_002 [2.2] Thread Sleep functionality * *

Description

- * Wait, Signal and Reset primitives are tested. The testing thread - * triggers a state change. + * The functionality of @p chThdSleep() and derivatives is tested. * *

Test Steps

- * - [2.2.1] The function chSemWait() is invoked, after return the - * counter and the returned message are tested. The semaphore is - * signaled by another thread. - * - [2.2.2] The function chSemWait() is invoked, after return the - * counter and the returned message are tested. The semaphore is - * reset by another thread. + * - [2.2.1] The current system time is read then a sleep is performed + * for 100 system ticks and on exit the system time is verified + * again. + * - [2.2.2] The current system time is read then a sleep is performed + * for 100000 microseconds and on exit the system time is verified + * again. + * - [2.2.3] The current system time is read then a sleep is performed + * for 100 milliseconds and on exit the system time is verified + * again. + * - [2.2.4] The current system time is read then a sleep is performed + * for 1 second and on exit the system time is verified again. + * - [2.2.5] Function chThdSleepUntil() is tested with a timeline of + * "now" + 100 ticks. * . */ -static void test_002_002_setup(void) { - chSemObjectInit(&gsem1, 0); -} - -static void test_002_002_teardown(void) { - chSemReset(&gsem1, 0); -} - static void test_002_002_execute(void) { + systime_t time; - /* [2.2.1] The function chSemWait() is invoked, after return the - counter and the returned message are tested. The semaphore is - signaled by another thread.*/ + /* [2.2.1] The current system time is read then a sleep is performed + for 100 system ticks and on exit the system time is verified + again.*/ test_set_step(1); { - msg_t msg; - - msg = chSemWait(&gsem1); - test_assert_lock(chSemGetCounterI(&gsem1) == 0, "wrong counter value"); - test_assert(MSG_OK == msg, "wrong returned message"); + time = chVTGetSystemTimeX(); + chThdSleep(100); + test_assert_time_window(time + 100, + time + 100 + 1, + "out of time window"); } - /* [2.2.2] The function chSemWait() is invoked, after return the - counter and the returned message are tested. The semaphore is - reset by another thread.*/ + /* [2.2.2] The current system time is read then a sleep is performed + for 100000 microseconds and on exit the system time is verified + again.*/ test_set_step(2); { - msg_t msg; - - msg = chSemWait(&gsem2); - test_assert_lock(chSemGetCounterI(&gsem2) == 0,"wrong counter value"); - test_assert(MSG_RESET == msg, "wrong returned message"); + time = chVTGetSystemTimeX(); + chThdSleepMicroseconds(100000); + test_assert_time_window(time + US2ST(100000), + time + US2ST(100000) + 1, + "out of time window"); } -} - -static const testcase_t test_002_002 = { - "Semaphore primitives, with state change", - test_002_002_setup, - test_002_002_teardown, - test_002_002_execute -}; - -/** - * @page test_002_003 [2.3] Semaphores timeout - * - *

Description

- * Timeout on semaphores is tested. - * - *

Test Steps

- * - [2.3.1] The function chSemWaitTimeout() is invoked a first time, - * after return the system time, the counter and the returned message - * are tested. - * - [2.3.2] The function chSemWaitTimeout() is invoked again, after - * return the system time, the counter and the returned message are - * tested. - * . - */ - -static void test_002_003_setup(void) { - chSemObjectInit(&sem1, 0); -} - -static void test_002_003_teardown(void) { - chSemReset(&sem1, 0); -} -static void test_002_003_execute(void) { - systime_t time; - msg_t msg; + /* [2.2.3] The current system time is read then a sleep is performed + for 100 milliseconds and on exit the system time is verified + again.*/ + test_set_step(3); + { + time = chVTGetSystemTimeX(); + chThdSleepMilliseconds(100); + test_assert_time_window(time + MS2ST(100), + time + MS2ST(100) + 1, + "out of time window"); + } - /* [2.3.1] The function chSemWaitTimeout() is invoked a first time, - after return the system time, the counter and the returned message - are tested.*/ - test_set_step(1); + /* [2.2.4] The current system time is read then a sleep is performed + for 1 second and on exit the system time is verified again.*/ + test_set_step(4); { time = chVTGetSystemTimeX(); - msg = chSemWaitTimeout(&sem1, MS2ST(1000)); - test_assert_time_window(time + MS2ST(1000), - time + MS2ST(1000) + 1, + chThdSleepSeconds(1); + test_assert_time_window(time + S2ST(1), + time + S2ST(1) + 1, "out of time window"); - test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value"); - test_assert(MSG_TIMEOUT == msg, "wrong timeout message"); } - /* [2.3.2] The function chSemWaitTimeout() is invoked again, after - return the system time, the counter and the returned message are - tested.*/ - test_set_step(2); + /* [2.2.5] Function chThdSleepUntil() is tested with a timeline of + "now" + 100 ticks.*/ + test_set_step(5); { time = chVTGetSystemTimeX(); - msg = chSemWaitTimeout(&sem1, MS2ST(1000)); - test_assert_time_window(time + MS2ST(1000), - time + MS2ST(1000) + 1, + chThdSleepUntil(time + 100); + test_assert_time_window(time + 100, + time + 100 + 1, "out of time window"); - test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value"); - test_assert(MSG_TIMEOUT == msg, "wrong timeout message"); } } -static const testcase_t test_002_003 = { - "Semaphores timeout", - test_002_003_setup, - test_002_003_teardown, - test_002_003_execute +static const testcase_t test_002_002 = { + "Thread Sleep functionality", + NULL, + NULL, + test_002_002_execute }; /**************************************************************************** @@ -247,13 +174,10 @@ static const testcase_t test_002_003 = { ****************************************************************************/ /** - * @brief Semaphores. + * @brief Threads Functionality. */ const testcase_t * const test_sequence_002[] = { &test_002_001, &test_002_002, - &test_002_003, NULL }; - -#endif /* CH_CFG_USE_SEMAPHORES */ diff --git a/test/nil/source/test/test_sequence_003.c b/test/nil/source/test/test_sequence_003.c index bf5c7941f..22e233620 100644 --- a/test/nil/source/test/test_sequence_003.c +++ b/test/nil/source/test/test_sequence_003.c @@ -22,178 +22,238 @@ * @file test_sequence_003.c * @brief Test Sequence 003 code. * - * @page test_sequence_003 [3] Suspend/Resume and Event Flags + * @page test_sequence_003 [3] Semaphores * * File: @ref test_sequence_003.c * *

Description

* This sequence tests the ChibiOS/NIL functionalities related to - * threads suspend/resume and event flags. + * counter semaphores. + * + *

Conditions

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

Test Cases

* - @subpage test_003_001 * - @subpage test_003_002 + * - @subpage test_003_003 * . */ +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) + /**************************************************************************** * Shared code. ****************************************************************************/ -static thread_reference_t tr1; +#include "ch.h" + +static semaphore_t sem1; /**************************************************************************** * Test cases. ****************************************************************************/ /** - * @page test_003_001 [3.1] Suspend and Resume functionality + * @page test_003_001 [3.1] Semaphore primitives, no state change * *

Description

- * The functionality of chThdSuspendTimeoutS() and chThdResumeI() is - * tested. + * Wait, Signal and Reset primitives are tested. The testing thread + * does not trigger a state change. * *

Test Steps

- * - [3.1.1] The function chThdSuspendTimeoutS() is invoked, the thread - * is remotely resumed with message @p MSG_OK. On return the message - * and the state of the reference are tested. - * - [3.1.2] The function chThdSuspendTimeoutS() is invoked, the thread - * is not resumed so a timeout must occur. On return the message and - * the state of the reference are tested. + * - [3.1.1] The function chSemWait() is invoked, after return the + * counter and the returned message are tested. + * - [3.1.2] The function chSemSignal() is invoked, after return the + * counter is tested. + * - [3.1.3] The function chSemReset() is invoked, after return the + * counter is tested. * . */ static void test_003_001_setup(void) { - tr1 = NULL; + chSemObjectInit(&sem1, 1); +} + +static void test_003_001_teardown(void) { + chSemReset(&sem1, 0); } static void test_003_001_execute(void) { - systime_t time; - msg_t msg; - /* [3.1.1] The function chThdSuspendTimeoutS() is invoked, the thread - is remotely resumed with message @p MSG_OK. On return the message - and the state of the reference are tested.*/ + /* [3.1.1] The function chSemWait() is invoked, after return the + counter and the returned message are tested.*/ test_set_step(1); { - chSysLock(); - msg = chThdSuspendTimeoutS(>r1, TIME_INFINITE); - chSysUnlock(); - test_assert(NULL == gtr1, "not NULL"); - test_assert(MSG_OK == msg,"wrong returned message"); + msg_t msg; + + msg = chSemWait(&sem1); + test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value"); + test_assert(MSG_OK == msg, "wrong returned message"); } - /* [3.1.2] The function chThdSuspendTimeoutS() is invoked, the thread - is not resumed so a timeout must occur. On return the message and - the state of the reference are tested.*/ + /* [3.1.2] The function chSemSignal() is invoked, after return the + counter is tested.*/ test_set_step(2); { - chSysLock(); - time = chVTGetSystemTimeX(); - msg = chThdSuspendTimeoutS(&tr1, MS2ST(1000)); - chSysUnlock(); - test_assert_time_window(time + MS2ST(1000), - time + MS2ST(1000) + 1, - "out of time window"); - test_assert(NULL == tr1, "not NULL"); - test_assert(MSG_TIMEOUT == msg, "wrong returned message"); + chSemSignal(&sem1); + test_assert_lock(chSemGetCounterI(&sem1) == 1, "wrong counter value"); + } + + /* [3.1.3] The function chSemReset() is invoked, after return the + counter is tested.*/ + test_set_step(3); + { + chSemReset(&sem1, 2); + test_assert_lock(chSemGetCounterI(&sem1) == 2, "wrong counter value"); } } static const testcase_t test_003_001 = { - "Suspend and Resume functionality", + "Semaphore primitives, no state change", test_003_001_setup, - NULL, + test_003_001_teardown, test_003_001_execute }; -#if (CH_CFG_USE_EVENTS) || defined(__DOXYGEN__) /** - * @page test_003_002 [3.2] Events Flags functionality + * @page test_003_002 [3.2] Semaphore primitives, with state change * *

Description

- * Event flags functionality is tested. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_EVENTS - * . + * Wait, Signal and Reset primitives are tested. The testing thread + * triggers a state change. * *

Test Steps

- * - [3.2.1] A set of event flags are set on the current thread then - * the function chEvtWaitAnyTimeout() is invoked, the function is - * supposed to return immediately because the event flags are already - * pending, after return the events mask is tested. - * - [3.2.2] The pending event flags mask is cleared then the function - * chEvtWaitAnyTimeout() is invoked, after return the events mask is - * tested. The thread is signaled by another thread. - * - [3.2.3] The function chEvtWaitAnyTimeout() is invoked, no event - * can wakeup the thread, the function must return because timeout. + * - [3.2.1] The function chSemWait() is invoked, after return the + * counter and the returned message are tested. The semaphore is + * signaled by another thread. + * - [3.2.2] The function chSemWait() is invoked, after return the + * counter and the returned message are tested. The semaphore is + * reset by another thread. * . */ +static void test_003_002_setup(void) { + chSemObjectInit(&gsem1, 0); +} + +static void test_003_002_teardown(void) { + chSemReset(&gsem1, 0); +} + static void test_003_002_execute(void) { - systime_t time; - eventmask_t events; - /* [3.2.1] A set of event flags are set on the current thread then - the function chEvtWaitAnyTimeout() is invoked, the function is - supposed to return immediately because the event flags are already - pending, after return the events mask is tested.*/ + /* [3.2.1] The function chSemWait() is invoked, after return the + counter and the returned message are tested. The semaphore is + signaled by another thread.*/ test_set_step(1); { - time = chVTGetSystemTimeX(); - chEvtSignal(chThdGetSelfX(), 0x55); - events = chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(1000)); - test_assert((eventmask_t)0 != events, "timed out"); - test_assert((eventmask_t)0x55 == events, "wrong events mask"); + msg_t msg; + + msg = chSemWait(&gsem1); + test_assert_lock(chSemGetCounterI(&gsem1) == 0, "wrong counter value"); + test_assert(MSG_OK == msg, "wrong returned message"); } - /* [3.2.2] The pending event flags mask is cleared then the function - chEvtWaitAnyTimeout() is invoked, after return the events mask is - tested. The thread is signaled by another thread.*/ + /* [3.2.2] The function chSemWait() is invoked, after return the + counter and the returned message are tested. The semaphore is + reset by another thread.*/ test_set_step(2); + { + msg_t msg; + + msg = chSemWait(&gsem2); + test_assert_lock(chSemGetCounterI(&gsem2) == 0,"wrong counter value"); + test_assert(MSG_RESET == msg, "wrong returned message"); + } +} + +static const testcase_t test_003_002 = { + "Semaphore primitives, with state change", + test_003_002_setup, + test_003_002_teardown, + test_003_002_execute +}; + +/** + * @page test_003_003 [3.3] Semaphores timeout + * + *

Description

+ * Timeout on semaphores is tested. + * + *

Test Steps

+ * - [3.3.1] The function chSemWaitTimeout() is invoked a first time, + * after return the system time, the counter and the returned message + * are tested. + * - [3.3.2] The function chSemWaitTimeout() is invoked again, after + * return the system time, the counter and the returned message are + * tested. + * . + */ + +static void test_003_003_setup(void) { + chSemObjectInit(&sem1, 0); +} + +static void test_003_003_teardown(void) { + chSemReset(&sem1, 0); +} + +static void test_003_003_execute(void) { + systime_t time; + msg_t msg; + + /* [3.3.1] The function chSemWaitTimeout() is invoked a first time, + after return the system time, the counter and the returned message + are tested.*/ + test_set_step(1); { time = chVTGetSystemTimeX(); - chThdGetSelfX()->epmask = 0; - events = chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(1000)); - test_assert((eventmask_t)0 != events, "timed out"); - test_assert((eventmask_t)0x55 == events, "wrong events mask"); + msg = chSemWaitTimeout(&sem1, MS2ST(1000)); + test_assert_time_window(time + MS2ST(1000), + time + MS2ST(1000) + 1, + "out of time window"); + test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value"); + test_assert(MSG_TIMEOUT == msg, "wrong timeout message"); } - /* [3.2.3] The function chEvtWaitAnyTimeout() is invoked, no event - can wakeup the thread, the function must return because timeout.*/ - test_set_step(3); + /* [3.3.2] The function chSemWaitTimeout() is invoked again, after + return the system time, the counter and the returned message are + tested.*/ + test_set_step(2); { time = chVTGetSystemTimeX(); - events = chEvtWaitAnyTimeout(0, MS2ST(1000)); + msg = chSemWaitTimeout(&sem1, MS2ST(1000)); test_assert_time_window(time + MS2ST(1000), time + MS2ST(1000) + 1, "out of time window"); - test_assert((eventmask_t)0 == events, "wrong events mask"); + test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value"); + test_assert(MSG_TIMEOUT == msg, "wrong timeout message"); } } -static const testcase_t test_003_002 = { - "Events Flags functionality", - NULL, - NULL, - test_003_002_execute +static const testcase_t test_003_003 = { + "Semaphores timeout", + test_003_003_setup, + test_003_003_teardown, + test_003_003_execute }; -#endif /* CH_CFG_USE_EVENTS */ /**************************************************************************** * Exported data. ****************************************************************************/ /** - * @brief Suspend/Resume and Event Flags. + * @brief Semaphores. */ const testcase_t * const test_sequence_003[] = { &test_003_001, -#if (CH_CFG_USE_EVENTS) || defined(__DOXYGEN__) &test_003_002, -#endif + &test_003_003, NULL }; + +#endif /* CH_CFG_USE_SEMAPHORES */ diff --git a/test/nil/source/test/test_sequence_004.c b/test/nil/source/test/test_sequence_004.c index c3f3463d3..52e3e88d0 100644 --- a/test/nil/source/test/test_sequence_004.c +++ b/test/nil/source/test/test_sequence_004.c @@ -22,387 +22,178 @@ * @file test_sequence_004.c * @brief Test Sequence 004 code. * - * @page test_sequence_004 [4] Mailboxes + * @page test_sequence_004 [4] Suspend/Resume and Event Flags * * File: @ref test_sequence_004.c * *

Description

* This sequence tests the ChibiOS/NIL functionalities related to - * mailboxes. - * - *

Conditions

- * This sequence is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_MAILBOXES - * . + * threads suspend/resume and event flags. * *

Test Cases

* - @subpage test_004_001 * - @subpage test_004_002 - * - @subpage test_004_003 * . */ -#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__) - /**************************************************************************** * Shared code. ****************************************************************************/ -#define ALLOWED_DELAY MS2ST(5) -#define MB_SIZE 4 - -static msg_t mb_buffer[MB_SIZE]; -static MAILBOX_DECL(mb1, mb_buffer, MB_SIZE); +static thread_reference_t tr1; /**************************************************************************** * Test cases. ****************************************************************************/ /** - * @page test_004_001 [4.1] Mailbox normal API, non-blocking tests + * @page test_004_001 [4.1] Suspend and Resume functionality * *

Description

- * The mailbox normal API is tested without triggering blocking - * conditions. + * The functionality of chThdSuspendTimeoutS() and chThdResumeI() is + * tested. * *

Test Steps

- * - [4.1.1] Testing the mailbox size. - * - [4.1.2] Resetting the mailbox, conditions are checked, no errors - * expected. - * - [4.1.3] Testing the behavior of API when the mailbox is in reset - * state then return in active state. - * - [4.1.4] Filling the mailbox using chMBPost() and chMBPostAhead() - * once, no errors expected. - * - [4.1.5] Testing intermediate conditions. Data pointers must be - * aligned, semaphore counters are checked. - * - [4.1.6] Emptying the mailbox using chMBFetch(), no errors - * expected. - * - [4.1.7] Posting and then fetching one more message, no errors - * expected. - * - [4.1.8] Testing final conditions. Data pointers must be aligned to - * buffer start, semaphore counters are checked. + * - [4.1.1] The function chThdSuspendTimeoutS() is invoked, the thread + * is remotely resumed with message @p MSG_OK. On return the message + * and the state of the reference are tested. + * - [4.1.2] The function chThdSuspendTimeoutS() is invoked, the thread + * is not resumed so a timeout must occur. On return the message and + * the state of the reference are tested. * . */ static void test_004_001_setup(void) { - chMBObjectInit(&mb1, mb_buffer, MB_SIZE); -} - -static void test_004_001_teardown(void) { - chMBReset(&mb1); + tr1 = NULL; } static void test_004_001_execute(void) { - msg_t msg1, msg2; - unsigned i; + systime_t time; + msg_t msg; - /* [4.1.1] Testing the mailbox size.*/ + /* [4.1.1] The function chThdSuspendTimeoutS() is invoked, the thread + is remotely resumed with message @p MSG_OK. On return the message + and the state of the reference are tested.*/ test_set_step(1); { - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size"); + chSysLock(); + msg = chThdSuspendTimeoutS(>r1, TIME_INFINITE); + chSysUnlock(); + test_assert(NULL == gtr1, "not NULL"); + test_assert(MSG_OK == msg,"wrong returned message"); } - /* [4.1.2] Resetting the mailbox, conditions are checked, no errors - expected.*/ + /* [4.1.2] The function chThdSuspendTimeoutS() is invoked, the thread + is not resumed so a timeout must occur. On return the message and + the state of the reference are tested.*/ test_set_step(2); { - chMBReset(&mb1); - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); - test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); - test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); - } - - /* [4.1.3] Testing the behavior of API when the mailbox is in reset - state then return in active state.*/ - test_set_step(3); - { - msg1 = chMBPost(&mb1, (msg_t)0, TIME_INFINITE); - test_assert(msg1 == MSG_RESET, "not in reset state"); - msg1 = chMBPostAhead(&mb1, (msg_t)0, TIME_INFINITE); - test_assert(msg1 == MSG_RESET, "not in reset state"); - msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE); - test_assert(msg1 == MSG_RESET, "not in reset state"); - chMBResumeX(&mb1); - } - - /* [4.1.4] Filling the mailbox using chMBPost() and chMBPostAhead() - once, no errors expected.*/ - test_set_step(4); - { - for (i = 0; i < MB_SIZE - 1; i++) { - msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - msg1 = chMBPostAhead(&mb1, 'A', TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - - /* [4.1.5] Testing intermediate conditions. Data pointers must be - aligned, semaphore counters are checked.*/ - test_set_step(5); - { - test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full"); - test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned"); - } - - /* [4.1.6] Emptying the mailbox using chMBFetch(), no errors - expected.*/ - test_set_step(6); - { - for (i = 0; i < MB_SIZE; i++) { - msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - test_emit_token(msg2); - } - test_assert_sequence("ABCD", "wrong get sequence"); - } - - /* [4.1.7] Posting and then fetching one more message, no errors - expected.*/ - test_set_step(7); - { - msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - - /* [4.1.8] Testing final conditions. Data pointers must be aligned to - buffer start, semaphore counters are checked.*/ - test_set_step(8); - { - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); - test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); - test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); + chSysLock(); + time = chVTGetSystemTimeX(); + msg = chThdSuspendTimeoutS(&tr1, MS2ST(1000)); + chSysUnlock(); + test_assert_time_window(time + MS2ST(1000), + time + MS2ST(1000) + 1, + "out of time window"); + test_assert(NULL == tr1, "not NULL"); + test_assert(MSG_TIMEOUT == msg, "wrong returned message"); } } static const testcase_t test_004_001 = { - "Mailbox normal API, non-blocking tests", + "Suspend and Resume functionality", test_004_001_setup, - test_004_001_teardown, + NULL, test_004_001_execute }; +#if (CH_CFG_USE_EVENTS) || defined(__DOXYGEN__) /** - * @page test_004_002 [4.2] Mailbox I-Class API, non-blocking tests + * @page test_004_002 [4.2] Events Flags functionality * *

Description

- * The mailbox I-Class API is tested without triggering blocking - * conditions. + * Event flags functionality is tested. + * + *

Conditions

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

Test Steps

- * - [4.2.1] Testing the mailbox size. - * - [4.2.2] Resetting the mailbox, conditions are checked, no errors - * expected. - * - [4.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI() - * once, no errors expected. - * - [4.2.4] Testing intermediate conditions. Data pointers must be - * aligned, semaphore counters are checked. - * - [4.2.5] Emptying the mailbox using chMBFetchI(), no errors - * expected. - * - [4.2.6] Posting and then fetching one more message, no errors - * expected. - * - [4.2.7] Testing final conditions. Data pointers must be aligned to - * buffer start, semaphore counters are checked. + * - [4.2.1] A set of event flags are set on the current thread then + * the function chEvtWaitAnyTimeout() is invoked, the function is + * supposed to return immediately because the event flags are already + * pending, after return the events mask is tested. + * - [4.2.2] The pending event flags mask is cleared then the function + * chEvtWaitAnyTimeout() is invoked, after return the events mask is + * tested. The thread is signaled by another thread. + * - [4.2.3] The function chEvtWaitAnyTimeout() is invoked, no event + * can wakeup the thread, the function must return because timeout. * . */ -static void test_004_002_setup(void) { - chMBObjectInit(&mb1, mb_buffer, MB_SIZE); -} - -static void test_004_002_teardown(void) { - chMBReset(&mb1); -} - static void test_004_002_execute(void) { - msg_t msg1, msg2; - unsigned i; + systime_t time; + eventmask_t events; - /* [4.2.1] Testing the mailbox size.*/ + /* [4.2.1] A set of event flags are set on the current thread then + the function chEvtWaitAnyTimeout() is invoked, the function is + supposed to return immediately because the event flags are already + pending, after return the events mask is tested.*/ test_set_step(1); { - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size"); + time = chVTGetSystemTimeX(); + chEvtSignal(chThdGetSelfX(), 0x55); + events = chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(1000)); + test_assert((eventmask_t)0 != events, "timed out"); + test_assert((eventmask_t)0x55 == events, "wrong events mask"); } - /* [4.2.2] Resetting the mailbox, conditions are checked, no errors - expected.*/ + /* [4.2.2] The pending event flags mask is cleared then the function + chEvtWaitAnyTimeout() is invoked, after return the events mask is + tested. The thread is signaled by another thread.*/ test_set_step(2); { - chSysLock(); - chMBResetI(&mb1); - chSysUnlock(); - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); - test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); - test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); - chMBResumeX(&mb1); + time = chVTGetSystemTimeX(); + chThdGetSelfX()->epmask = 0; + events = chEvtWaitAnyTimeout(ALL_EVENTS, MS2ST(1000)); + test_assert((eventmask_t)0 != events, "timed out"); + test_assert((eventmask_t)0x55 == events, "wrong events mask"); } - /* [4.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI() - once, no errors expected.*/ + /* [4.2.3] The function chEvtWaitAnyTimeout() is invoked, no event + can wakeup the thread, the function must return because timeout.*/ test_set_step(3); { - for (i = 0; i < MB_SIZE - 1; i++) { - chSysLock(); - msg1 = chMBPostI(&mb1, 'B' + i); - chSysUnlock(); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - chSysLock(); - msg1 = chMBPostAheadI(&mb1, 'A'); - chSysUnlock(); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - - /* [4.2.4] Testing intermediate conditions. Data pointers must be - aligned, semaphore counters are checked.*/ - test_set_step(4); - { - test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full"); - test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned"); - } - - /* [4.2.5] Emptying the mailbox using chMBFetchI(), no errors - expected.*/ - test_set_step(5); - { - for (i = 0; i < MB_SIZE; i++) { - chSysLock(); - msg1 = chMBFetchI(&mb1, &msg2); - chSysUnlock(); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - test_emit_token(msg2); - } - test_assert_sequence("ABCD", "wrong get sequence"); - } - - /* [4.2.6] Posting and then fetching one more message, no errors - expected.*/ - test_set_step(6); - { - msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - - /* [4.2.7] Testing final conditions. Data pointers must be aligned to - buffer start, semaphore counters are checked.*/ - test_set_step(7); - { - test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); - test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); - test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); - test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); + time = chVTGetSystemTimeX(); + events = chEvtWaitAnyTimeout(0, MS2ST(1000)); + test_assert_time_window(time + MS2ST(1000), + time + MS2ST(1000) + 1, + "out of time window"); + test_assert((eventmask_t)0 == events, "wrong events mask"); } } static const testcase_t test_004_002 = { - "Mailbox I-Class API, non-blocking tests", - test_004_002_setup, - test_004_002_teardown, + "Events Flags functionality", + NULL, + NULL, test_004_002_execute }; - -/** - * @page test_004_003 [4.3] Mailbox timeouts - * - *

Description

- * The mailbox API is tested for timeouts. - * - *

Test Steps

- * - [4.3.1] Filling the mailbox. - * - [4.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and - * chMBPostAheadI() timeout. - * - [4.3.3] Resetting the mailbox. - * - [4.3.4] Testing chMBFetch() and chMBFetchI() timeout. - * . - */ - -static void test_004_003_setup(void) { - chMBObjectInit(&mb1, mb_buffer, MB_SIZE); -} - -static void test_004_003_teardown(void) { - chMBReset(&mb1); -} - -static void test_004_003_execute(void) { - msg_t msg1, msg2; - unsigned i; - - /* [4.3.1] Filling the mailbox.*/ - test_set_step(1); - { - for (i = 0; i < MB_SIZE; i++) { - msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE); - test_assert(msg1 == MSG_OK, "wrong wake-up message"); - } - } - - /* [4.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and - chMBPostAheadI() timeout.*/ - test_set_step(2); - { - msg1 = chMBPost(&mb1, 'X', 1); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - chSysLock(); - msg1 = chMBPostI(&mb1, 'X'); - chSysUnlock(); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - msg1 = chMBPostAhead(&mb1, 'X', 1); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - chSysLock(); - msg1 = chMBPostAheadI(&mb1, 'X'); - chSysUnlock(); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - } - - /* [4.3.3] Resetting the mailbox.*/ - test_set_step(3); - { - chMBReset(&mb1);; - chMBResumeX(&mb1); - } - - /* [4.3.4] Testing chMBFetch() and chMBFetchI() timeout.*/ - test_set_step(4); - { - msg1 = chMBFetch(&mb1, &msg2, 1); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - chSysLock(); - msg1 = chMBFetchI(&mb1, &msg2); - chSysUnlock(); - test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); - } -} - -static const testcase_t test_004_003 = { - "Mailbox timeouts", - test_004_003_setup, - test_004_003_teardown, - test_004_003_execute -}; +#endif /* CH_CFG_USE_EVENTS */ /**************************************************************************** * Exported data. ****************************************************************************/ /** - * @brief Mailboxes. + * @brief Suspend/Resume and Event Flags. */ const testcase_t * const test_sequence_004[] = { &test_004_001, +#if (CH_CFG_USE_EVENTS) || defined(__DOXYGEN__) &test_004_002, - &test_004_003, +#endif NULL }; - -#endif /* CH_CFG_USE_MAILBOXES */ diff --git a/test/nil/source/test/test_sequence_005.c b/test/nil/source/test/test_sequence_005.c index 3c0ef8668..70954f1d1 100644 --- a/test/nil/source/test/test_sequence_005.c +++ b/test/nil/source/test/test_sequence_005.c @@ -22,18 +22,18 @@ * @file test_sequence_005.c * @brief Test Sequence 005 code. * - * @page test_sequence_005 [5] Memory Pools + * @page test_sequence_005 [5] Mailboxes * * File: @ref test_sequence_005.c * *

Description

* This sequence tests the ChibiOS/NIL functionalities related to - * memory pools. + * mailboxes. * *

Conditions

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

Test Cases

@@ -43,254 +43,366 @@ * . */ -#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) +#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__) /**************************************************************************** * Shared code. ****************************************************************************/ -#define MEMORY_POOL_SIZE 4 +#define ALLOWED_DELAY MS2ST(5) +#define MB_SIZE 4 -static uint32_t objects[MEMORY_POOL_SIZE]; -static MEMORYPOOL_DECL(mp1, sizeof (uint32_t), NULL); - -#if CH_CFG_USE_SEMAPHORES -static GUARDEDMEMORYPOOL_DECL(gmp1, sizeof (uint32_t)); -#endif - -static void *null_provider(size_t size, unsigned align) { - - (void)size; - (void)align; - - return NULL; -} +static msg_t mb_buffer[MB_SIZE]; +static MAILBOX_DECL(mb1, mb_buffer, MB_SIZE); /**************************************************************************** * Test cases. ****************************************************************************/ /** - * @page test_005_001 [5.1] Loading and emptying a memory pool + * @page test_005_001 [5.1] Mailbox normal API, non-blocking tests * *

Description

- * The memory pool functionality is tested by loading and emptying it, - * all conditions are tested. + * The mailbox normal API is tested without triggering blocking + * conditions. * *

Test Steps

- * - [5.1.1] Adding the objects to the pool using chPoolLoadArray(). - * - [5.1.2] Emptying the pool using chPoolAlloc(). - * - [5.1.3] Now must be empty. - * - [5.1.4] Adding the objects to the pool using chPoolFree(). - * - [5.1.5] Emptying the pool using chPoolAlloc() again. - * - [5.1.6] Now must be empty again. - * - [5.1.7] Covering the case where a provider is unable to return - * more memory. + * - [5.1.1] Testing the mailbox size. + * - [5.1.2] Resetting the mailbox, conditions are checked, no errors + * expected. + * - [5.1.3] Testing the behavior of API when the mailbox is in reset + * state then return in active state. + * - [5.1.4] Filling the mailbox using chMBPost() and chMBPostAhead() + * once, no errors expected. + * - [5.1.5] Testing intermediate conditions. Data pointers must be + * aligned, semaphore counters are checked. + * - [5.1.6] Emptying the mailbox using chMBFetch(), no errors + * expected. + * - [5.1.7] Posting and then fetching one more message, no errors + * expected. + * - [5.1.8] Testing final conditions. Data pointers must be aligned to + * buffer start, semaphore counters are checked. * . */ static void test_005_001_setup(void) { - chPoolObjectInit(&mp1, sizeof (uint32_t), NULL); + chMBObjectInit(&mb1, mb_buffer, MB_SIZE); +} + +static void test_005_001_teardown(void) { + chMBReset(&mb1); } static void test_005_001_execute(void) { + msg_t msg1, msg2; unsigned i; - /* [5.1.1] Adding the objects to the pool using chPoolLoadArray().*/ + /* [5.1.1] Testing the mailbox size.*/ test_set_step(1); { - chPoolLoadArray(&mp1, objects, MEMORY_POOL_SIZE); + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size"); } - /* [5.1.2] Emptying the pool using chPoolAlloc().*/ + /* [5.1.2] Resetting the mailbox, conditions are checked, no errors + expected.*/ test_set_step(2); { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - test_assert(chPoolAlloc(&mp1) != NULL, "list empty"); + chMBReset(&mb1); + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); + test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); + test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); } - /* [5.1.3] Now must be empty.*/ + /* [5.1.3] Testing the behavior of API when the mailbox is in reset + state then return in active state.*/ test_set_step(3); { - test_assert(chPoolAlloc(&mp1) == NULL, "list not empty"); + msg1 = chMBPost(&mb1, (msg_t)0, TIME_INFINITE); + test_assert(msg1 == MSG_RESET, "not in reset state"); + msg1 = chMBPostAhead(&mb1, (msg_t)0, TIME_INFINITE); + test_assert(msg1 == MSG_RESET, "not in reset state"); + msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE); + test_assert(msg1 == MSG_RESET, "not in reset state"); + chMBResumeX(&mb1); } - /* [5.1.4] Adding the objects to the pool using chPoolFree().*/ + /* [5.1.4] Filling the mailbox using chMBPost() and chMBPostAhead() + once, no errors expected.*/ test_set_step(4); { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - chPoolFree(&mp1, &objects[i]); + for (i = 0; i < MB_SIZE - 1; i++) { + msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + msg1 = chMBPostAhead(&mb1, 'A', TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); } - /* [5.1.5] Emptying the pool using chPoolAlloc() again.*/ + /* [5.1.5] Testing intermediate conditions. Data pointers must be + aligned, semaphore counters are checked.*/ test_set_step(5); { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - test_assert(chPoolAlloc(&mp1) != NULL, "list empty"); + test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full"); + test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned"); } - /* [5.1.6] Now must be empty again.*/ + /* [5.1.6] Emptying the mailbox using chMBFetch(), no errors + expected.*/ test_set_step(6); { - test_assert(chPoolAlloc(&mp1) == NULL, "list not empty"); + for (i = 0; i < MB_SIZE; i++) { + msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + test_emit_token(msg2); + } + test_assert_sequence("ABCD", "wrong get sequence"); } - /* [5.1.7] Covering the case where a provider is unable to return - more memory.*/ + /* [5.1.7] Posting and then fetching one more message, no errors + expected.*/ test_set_step(7); { - chPoolObjectInit(&mp1, sizeof (uint32_t), null_provider); - test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory"); + msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + + /* [5.1.8] Testing final conditions. Data pointers must be aligned to + buffer start, semaphore counters are checked.*/ + test_set_step(8); + { + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); + test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); + test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); } } static const testcase_t test_005_001 = { - "Loading and emptying a memory pool", + "Mailbox normal API, non-blocking tests", test_005_001_setup, - NULL, + test_005_001_teardown, test_005_001_execute }; -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) /** - * @page test_005_002 [5.2] Loading and emptying a guarded memory pool without waiting + * @page test_005_002 [5.2] Mailbox I-Class API, non-blocking tests * *

Description

- * The memory pool functionality is tested by loading and emptying it, - * all conditions are tested. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_SEMAPHORES - * . + * The mailbox I-Class API is tested without triggering blocking + * conditions. * *

Test Steps

- * - [5.2.1] Adding the objects to the pool using - * chGuardedPoolLoadArray(). - * - [5.2.2] Emptying the pool using chGuardedPoolAllocTimeout(). - * - [5.2.3] Now must be empty. - * - [5.2.4] Adding the objects to the pool using chGuardedPoolFree(). - * - [5.2.5] Emptying the pool using chGuardedPoolAllocTimeout() again. - * - [5.2.6] Now must be empty again. + * - [5.2.1] Testing the mailbox size. + * - [5.2.2] Resetting the mailbox, conditions are checked, no errors + * expected. + * - [5.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI() + * once, no errors expected. + * - [5.2.4] Testing intermediate conditions. Data pointers must be + * aligned, semaphore counters are checked. + * - [5.2.5] Emptying the mailbox using chMBFetchI(), no errors + * expected. + * - [5.2.6] Posting and then fetching one more message, no errors + * expected. + * - [5.2.7] Testing final conditions. Data pointers must be aligned to + * buffer start, semaphore counters are checked. * . */ static void test_005_002_setup(void) { - chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); + chMBObjectInit(&mb1, mb_buffer, MB_SIZE); +} + +static void test_005_002_teardown(void) { + chMBReset(&mb1); } static void test_005_002_execute(void) { + msg_t msg1, msg2; unsigned i; - /* [5.2.1] Adding the objects to the pool using - chGuardedPoolLoadArray().*/ + /* [5.2.1] Testing the mailbox size.*/ test_set_step(1); { - chGuardedPoolLoadArray(&gmp1, objects, MEMORY_POOL_SIZE); + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size"); } - /* [5.2.2] Emptying the pool using chGuardedPoolAllocTimeout().*/ + /* [5.2.2] Resetting the mailbox, conditions are checked, no errors + expected.*/ test_set_step(2); { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty"); + chSysLock(); + chMBResetI(&mb1); + chSysUnlock(); + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); + test_assert_lock(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); + test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); + chMBResumeX(&mb1); } - /* [5.2.3] Now must be empty.*/ + /* [5.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI() + once, no errors expected.*/ test_set_step(3); { - test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty"); + for (i = 0; i < MB_SIZE - 1; i++) { + chSysLock(); + msg1 = chMBPostI(&mb1, 'B' + i); + chSysUnlock(); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + chSysLock(); + msg1 = chMBPostAheadI(&mb1, 'A'); + chSysUnlock(); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); } - /* [5.2.4] Adding the objects to the pool using - chGuardedPoolFree().*/ + /* [5.2.4] Testing intermediate conditions. Data pointers must be + aligned, semaphore counters are checked.*/ test_set_step(4); { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - chGuardedPoolFree(&gmp1, &objects[i]); + test_assert_lock(chMBGetFreeCountI(&mb1) == 0, "still empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full"); + test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned"); } - /* [5.2.5] Emptying the pool using chGuardedPoolAllocTimeout() - again.*/ + /* [5.2.5] Emptying the mailbox using chMBFetchI(), no errors + expected.*/ test_set_step(5); { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty"); + for (i = 0; i < MB_SIZE; i++) { + chSysLock(); + msg1 = chMBFetchI(&mb1, &msg2); + chSysUnlock(); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + test_emit_token(msg2); + } + test_assert_sequence("ABCD", "wrong get sequence"); } - /* [5.2.6] Now must be empty again.*/ + /* [5.2.6] Posting and then fetching one more message, no errors + expected.*/ test_set_step(6); { - test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty"); + msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + msg1 = chMBFetch(&mb1, &msg2, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + + /* [5.2.7] Testing final conditions. Data pointers must be aligned to + buffer start, semaphore counters are checked.*/ + test_set_step(7); + { + test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "not empty"); + test_assert_lock(chMBGetUsedCountI(&mb1) == 0, "still full"); + test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); + test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); } } static const testcase_t test_005_002 = { - "Loading and emptying a guarded memory pool without waiting", + "Mailbox I-Class API, non-blocking tests", test_005_002_setup, - NULL, + test_005_002_teardown, test_005_002_execute }; -#endif /* CH_CFG_USE_SEMAPHORES */ -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) /** - * @page test_005_003 [5.3] Guarded Memory Pools timeout + * @page test_005_003 [5.3] Mailbox timeouts * *

Description

- * The timeout features for the Guarded Memory Pools is tested. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_SEMAPHORES - * . + * The mailbox API is tested for timeouts. * *

Test Steps

- * - [5.3.1] Trying to allocate with 100mS timeout, must fail because - * the pool is empty. + * - [5.3.1] Filling the mailbox. + * - [5.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and + * chMBPostAheadI() timeout. + * - [5.3.3] Resetting the mailbox. + * - [5.3.4] Testing chMBFetch() and chMBFetchI() timeout. * . */ static void test_005_003_setup(void) { - chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); + chMBObjectInit(&mb1, mb_buffer, MB_SIZE); +} + +static void test_005_003_teardown(void) { + chMBReset(&mb1); } static void test_005_003_execute(void) { + msg_t msg1, msg2; + unsigned i; - /* [5.3.1] Trying to allocate with 100mS timeout, must fail because - the pool is empty.*/ + /* [5.3.1] Filling the mailbox.*/ test_set_step(1); { - test_assert(chGuardedPoolAllocTimeout(&gmp1, MS2ST(100)) == NULL, "list not empty"); + for (i = 0; i < MB_SIZE; i++) { + msg1 = chMBPost(&mb1, 'B' + i, TIME_INFINITE); + test_assert(msg1 == MSG_OK, "wrong wake-up message"); + } + } + + /* [5.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and + chMBPostAheadI() timeout.*/ + test_set_step(2); + { + msg1 = chMBPost(&mb1, 'X', 1); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); + chSysLock(); + msg1 = chMBPostI(&mb1, 'X'); + chSysUnlock(); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); + msg1 = chMBPostAhead(&mb1, 'X', 1); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); + chSysLock(); + msg1 = chMBPostAheadI(&mb1, 'X'); + chSysUnlock(); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); + } + + /* [5.3.3] Resetting the mailbox.*/ + test_set_step(3); + { + chMBReset(&mb1);; + chMBResumeX(&mb1); + } + + /* [5.3.4] Testing chMBFetch() and chMBFetchI() timeout.*/ + test_set_step(4); + { + msg1 = chMBFetch(&mb1, &msg2, 1); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); + chSysLock(); + msg1 = chMBFetchI(&mb1, &msg2); + chSysUnlock(); + test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); } } static const testcase_t test_005_003 = { - "Guarded Memory Pools timeout", + "Mailbox timeouts", test_005_003_setup, - NULL, + test_005_003_teardown, test_005_003_execute }; -#endif /* CH_CFG_USE_SEMAPHORES */ /**************************************************************************** * Exported data. ****************************************************************************/ /** - * @brief Memory Pools. + * @brief Mailboxes. */ const testcase_t * const test_sequence_005[] = { &test_005_001, -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) &test_005_002, -#endif -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) &test_005_003, -#endif NULL }; -#endif /* CH_CFG_USE_MEMPOOLS */ +#endif /* CH_CFG_USE_MAILBOXES */ diff --git a/test/nil/source/test/test_sequence_006.c b/test/nil/source/test/test_sequence_006.c index ba3e8cbf9..dad464e6c 100644 --- a/test/nil/source/test/test_sequence_006.c +++ b/test/nil/source/test/test_sequence_006.c @@ -22,252 +22,275 @@ * @file test_sequence_006.c * @brief Test Sequence 006 code. * - * @page test_sequence_006 [6] Memory Heaps + * @page test_sequence_006 [6] Memory Pools * * File: @ref test_sequence_006.c * *

Description

* This sequence tests the ChibiOS/NIL functionalities related to - * memory heaps. + * memory pools. * *

Conditions

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

Test Cases

* - @subpage test_006_001 * - @subpage test_006_002 + * - @subpage test_006_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 CH_HEAP_AREA(myheap, HEAP_SIZE); +static uint32_t objects[MEMORY_POOL_SIZE]; +static MEMORYPOOL_DECL(mp1, sizeof (uint32_t), NULL); + +#if CH_CFG_USE_SEMAPHORES +static GUARDEDMEMORYPOOL_DECL(gmp1, sizeof (uint32_t)); +#endif + +static void *null_provider(size_t size, unsigned align) { + + (void)size; + (void)align; + + return NULL; +} /**************************************************************************** * Test cases. ****************************************************************************/ /** - * @page test_006_001 [6.1] Allocation and fragmentation + * @page test_006_001 [6.1] Loading and emptying a memory pool * *

Description

- * 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. * *

Test Steps

- * - [6.1.1] Testing initial conditions, the heap must not be - * fragmented and one free block present. - * - [6.1.2] Trying to allocate an block bigger than available space, - * an error is expected. - * - [6.1.3] Single block allocation using chHeapAlloc() then the block - * is freed using chHeapFree(), must not fail. - * - [6.1.4] Using chHeapStatus() to assess the heap state. There must - * be at least one free block of sufficient size. - * - [6.1.5] Allocating then freeing in the same order. - * - [6.1.6] Allocating then freeing in reverse order. - * - [6.1.7] Small fragments handling. Checking the behavior when - * allocating blocks with size not multiple of alignment unit. - * - [6.1.8] Skipping a fragment, the first fragment in the list is too - * small so the allocator must pick the second one. - * - [6.1.9] Allocating the whole available space. - * - [6.1.10] Testing final conditions. The heap geometry must be the - * same than the one registered at beginning. + * - [6.1.1] Adding the objects to the pool using chPoolLoadArray(). + * - [6.1.2] Emptying the pool using chPoolAlloc(). + * - [6.1.3] Now must be empty. + * - [6.1.4] Adding the objects to the pool using chPoolFree(). + * - [6.1.5] Emptying the pool using chPoolAlloc() again. + * - [6.1.6] Now must be empty again. + * - [6.1.7] Covering the case where a provider is unable to return + * more memory. * . */ static void test_006_001_setup(void) { - chHeapObjectInit(&test_heap, myheap, sizeof(myheap)); + chPoolObjectInit(&mp1, sizeof (uint32_t), NULL); } static void test_006_001_execute(void) { - void *p1, *p2, *p3; - size_t n, sz; + unsigned i; - /* [6.1.1] Testing initial conditions, the heap must not be - fragmented and one free block present.*/ + /* [6.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); } - /* [6.1.2] Trying to allocate an block bigger than available space, - an error is expected.*/ + /* [6.1.2] Emptying the pool using chPoolAlloc().*/ test_set_step(2); { - p1 = chHeapAlloc(&test_heap, HEAP_SIZE * 2); - test_assert(p1 == NULL, "allocation not failed"); + for (i = 0; i < MEMORY_POOL_SIZE; i++) + test_assert(chPoolAlloc(&mp1) != NULL, "list empty"); } - /* [6.1.3] Single block allocation using chHeapAlloc() then the block - is freed using chHeapFree(), must not fail.*/ + /* [6.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"); } - /* [6.1.4] Using chHeapStatus() to assess the heap state. There must - be at least one free block of sufficient size.*/ + /* [6.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]); } - /* [6.1.5] Allocating then freeing in the same order.*/ + /* [6.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"); } - /* [6.1.6] Allocating then freeing in reverse order.*/ + /* [6.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"); } - /* [6.1.7] Small fragments handling. Checking the behavior when - allocating blocks with size not multiple of alignment unit.*/ + /* [6.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"); - } - - /* [6.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"); - } - - /* [6.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); - } - - /* [6.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 test_006_001 = { - "Allocation and fragmentation", + "Loading and emptying a memory pool", test_006_001_setup, NULL, test_006_001_execute }; +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) /** - * @page test_006_002 [6.2] Default Heap + * @page test_006_002 [6.2] Loading and emptying a guarded memory pool without waiting * *

Description

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

Conditions

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

Test Steps

- * - [6.2.1] Single block allocation using chHeapAlloc() then the block - * is freed using chHeapFree(), must not fail. - * - [6.2.2] Testing allocation failure. + * - [6.2.1] Adding the objects to the pool using + * chGuardedPoolLoadArray(). + * - [6.2.2] Emptying the pool using chGuardedPoolAllocTimeout(). + * - [6.2.3] Now must be empty. + * - [6.2.4] Adding the objects to the pool using chGuardedPoolFree(). + * - [6.2.5] Emptying the pool using chGuardedPoolAllocTimeout() again. + * - [6.2.6] Now must be empty again. * . */ +static void test_006_002_setup(void) { + chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); +} + static void test_006_002_execute(void) { - void *p1; - size_t total_size, largest_size; + unsigned i; - /* [6.2.1] Single block allocation using chHeapAlloc() then the block - is freed using chHeapFree(), must not fail.*/ + /* [6.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); } - /* [6.2.2] Testing allocation failure.*/ + /* [6.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"); + } + + /* [6.2.3] Now must be empty.*/ + test_set_step(3); + { + test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty"); + } + + /* [6.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]); + } + + /* [6.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"); + } + + /* [6.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 test_006_002 = { - "Default Heap", - NULL, + "Loading and emptying a guarded memory pool without waiting", + test_006_002_setup, NULL, test_006_002_execute }; +#endif /* CH_CFG_USE_SEMAPHORES */ + +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) +/** + * @page test_006_003 [6.3] Guarded Memory Pools timeout + * + *

Description

+ * The timeout features for the Guarded Memory Pools is tested. + * + *

Conditions

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

Test Steps

+ * - [6.3.1] Trying to allocate with 100mS timeout, must fail because + * the pool is empty. + * . + */ + +static void test_006_003_setup(void) { + chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); +} + +static void test_006_003_execute(void) { + + /* [6.3.1] Trying to allocate with 100mS timeout, must fail because + the pool is empty.*/ + test_set_step(1); + { + test_assert(chGuardedPoolAllocTimeout(&gmp1, MS2ST(100)) == NULL, "list not empty"); + } +} + +static const testcase_t test_006_003 = { + "Guarded Memory Pools timeout", + test_006_003_setup, + NULL, + test_006_003_execute +}; +#endif /* CH_CFG_USE_SEMAPHORES */ /**************************************************************************** * Exported data. ****************************************************************************/ /** - * @brief Memory Heaps. + * @brief Memory Pools. */ const testcase_t * const test_sequence_006[] = { &test_006_001, +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) &test_006_002, +#endif +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) + &test_006_003, +#endif NULL }; -#endif /* CH_CFG_USE_HEAP */ +#endif /* CH_CFG_USE_MEMPOOLS */ diff --git a/test/nil/source/test/test_sequence_007.c b/test/nil/source/test/test_sequence_007.c new file mode 100644 index 000000000..4cd0c804e --- /dev/null +++ b/test/nil/source/test/test_sequence_007.c @@ -0,0 +1,273 @@ +/* + 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" + +/** + * @file test_sequence_007.c + * @brief Test Sequence 007 code. + * + * @page test_sequence_007 [7] Memory Heaps + * + * File: @ref test_sequence_007.c + * + *

Description

+ * This sequence tests the ChibiOS/NIL functionalities related to + * memory heaps. + * + *

Conditions

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

Test Cases

+ * - @subpage test_007_001 + * - @subpage test_007_002 + * . + */ + +#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 CH_HEAP_AREA(myheap, HEAP_SIZE); + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +/** + * @page test_007_001 [7.1] Allocation and fragmentation + * + *

Description

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

Test Steps

+ * - [7.1.1] Testing initial conditions, the heap must not be + * fragmented and one free block present. + * - [7.1.2] Trying to allocate an block bigger than available space, + * an error is expected. + * - [7.1.3] Single block allocation using chHeapAlloc() then the block + * is freed using chHeapFree(), must not fail. + * - [7.1.4] Using chHeapStatus() to assess the heap state. There must + * be at least one free block of sufficient size. + * - [7.1.5] Allocating then freeing in the same order. + * - [7.1.6] Allocating then freeing in reverse order. + * - [7.1.7] Small fragments handling. Checking the behavior when + * allocating blocks with size not multiple of alignment unit. + * - [7.1.8] Skipping a fragment, the first fragment in the list is too + * small so the allocator must pick the second one. + * - [7.1.9] Allocating the whole available space. + * - [7.1.10] Testing final conditions. The heap geometry must be the + * same than the one registered at beginning. + * . + */ + +static void test_007_001_setup(void) { + chHeapObjectInit(&test_heap, myheap, sizeof(myheap)); +} + +static void test_007_001_execute(void) { + void *p1, *p2, *p3; + size_t n, sz; + + /* [7.1.1] Testing initial conditions, the heap must not be + fragmented and one free block present.*/ + test_set_step(1); + { + test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented"); + } + + /* [7.1.2] Trying to allocate an block bigger than available space, + an error is expected.*/ + test_set_step(2); + { + p1 = chHeapAlloc(&test_heap, HEAP_SIZE * 2); + test_assert(p1 == NULL, "allocation not failed"); + } + + /* [7.1.3] Single block allocation using chHeapAlloc() then the block + is freed using chHeapFree(), must not fail.*/ + test_set_step(3); + { + p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); + test_assert(p1 != NULL, "allocation failed"); + chHeapFree(p1); + } + + /* [7.1.4] Using chHeapStatus() to assess the heap state. There must + be at least one free block of sufficient size.*/ + 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"); + } + + /* [7.1.5] Allocating then freeing in the same order.*/ + 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"); + } + + /* [7.1.6] Allocating then freeing in reverse order.*/ + 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"); + } + + /* [7.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"); + } + + /* [7.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"); + } + + /* [7.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); + } + + /* [7.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 test_007_001 = { + "Allocation and fragmentation", + test_007_001_setup, + NULL, + test_007_001_execute +}; + +/** + * @page test_007_002 [7.2] Default Heap + * + *

Description

+ * The default heap is pre-allocated in the system. We test base + * functionality. + * + *

Test Steps

+ * - [7.2.1] Single block allocation using chHeapAlloc() then the block + * is freed using chHeapFree(), must not fail. + * - [7.2.2] Testing allocation failure. + * . + */ + +static void test_007_002_execute(void) { + void *p1; + size_t total_size, largest_size; + + /* [7.2.1] Single block allocation using chHeapAlloc() then the block + is freed using chHeapFree(), must not fail.*/ + 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); + } + + /* [7.2.2] Testing allocation failure.*/ + test_set_step(2); + { + p1 = chHeapAlloc(NULL, (size_t)-256); + test_assert(p1 == NULL, "allocation not failed"); + } +} + +static const testcase_t test_007_002 = { + "Default Heap", + NULL, + NULL, + test_007_002_execute +}; + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Memory Heaps. + */ +const testcase_t * const test_sequence_007[] = { + &test_007_001, + &test_007_002, + NULL +}; + +#endif /* CH_CFG_USE_HEAP */ diff --git a/test/nil/source/test/test_sequence_007.h b/test/nil/source/test/test_sequence_007.h new file mode 100644 index 000000000..18b68a556 --- /dev/null +++ b/test/nil/source/test/test_sequence_007.h @@ -0,0 +1,27 @@ +/* + 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. +*/ + +/** + * @file test_sequence_007.h + * @brief Test Sequence 007 header. + */ + +#ifndef TEST_SEQUENCE_007_H +#define TEST_SEQUENCE_007_H + +extern const testcase_t * const test_sequence_007[]; + +#endif /* TEST_SEQUENCE_007_H */ -- cgit v1.2.3