aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2016-03-31 14:03:43 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2016-03-31 14:03:43 +0000
commit7c20551c988918cdad797a343d2126820cd75e8f (patch)
tree52b0ec69c403a3b807b38542edb9ba9adfb524b2 /test
parent039a6c7349a3525842d1ffb8f0317cc6fcc3e454 (diff)
downloadChibiOS-7c20551c988918cdad797a343d2126820cd75e8f.tar.gz
ChibiOS-7c20551c988918cdad797a343d2126820cd75e8f.tar.bz2
ChibiOS-7c20551c988918cdad797a343d2126820cd75e8f.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9189 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'test')
-rw-r--r--test/rt/configuration.xml417
-rw-r--r--test/rt/source/test/test_root.c2
-rw-r--r--test/rt/source/test/test_root.h1
-rw-r--r--test/rt/source/test/test_sequence_007.c477
-rw-r--r--test/rt/source/test/test_sequence_008.c323
-rw-r--r--test/rt/source/test/test_sequence_009.c294
-rw-r--r--test/rt/source/test/test_sequence_010.c270
-rw-r--r--test/rt/source/test/test_sequence_010.h17
-rw-r--r--test/rt/test.mk3
9 files changed, 1324 insertions, 480 deletions
diff --git a/test/rt/configuration.xml b/test/rt/configuration.xml
index b77c0f831..607b4e474 100644
--- a/test/rt/configuration.xml
+++ b/test/rt/configuration.xml
@@ -1468,13 +1468,13 @@ static THD_FUNCTION(thread8, p) {
test_emit_token(*(char *)p);
chMtxUnlock(&m1);
chMtxUnlock(&m2);
-}
-
-static THD_FUNCTION(thread9, p) {
-
- chMtxLock(&m2);
- test_emit_token(*(char *)p);
- chMtxUnlock(&m2);
+}
+
+static THD_FUNCTION(thread9, p) {
+
+ chMtxLock(&m2);
+ test_emit_token(*(char *)p);
+ chMtxUnlock(&m2);
}
#endif /* CH_CFG_USE_CONDVARS */]]></value>
</shared_code>
@@ -2379,6 +2379,409 @@ test_assert_sequence("ABCD", "invalid sequence");]]></value>
<value>Internal Tests</value>
</type>
<brief>
+ <value>Event Sources and Event Flags.</value>
+ </brief>
+ <description>
+ <value>This module implements the test sequence for the Events subsystem.</value>
+ </description>
+ <condition>
+ <value>CH_CFG_USE_EVENTS</value>
+ </condition>
+ <shared_code>
+ <value><![CDATA[static EVENTSOURCE_DECL(es1);
+static EVENTSOURCE_DECL(es2);
+
+static void h1(eventid_t id) {(void)id;test_emit_token('A');}
+static void h2(eventid_t id) {(void)id;test_emit_token('B');}
+static void h3(eventid_t id) {(void)id;test_emit_token('C');}
+static ROMCONST evhandler_t evhndl[] = {h1, h2, h3};
+
+static THD_FUNCTION(evt_thread3, p) {
+
+ chThdSleepMilliseconds(50);
+ chEvtSignal((thread_t *)p, 1);
+}
+
+static THD_FUNCTION(evt_thread4, p) {
+
+ (void)p;
+ chEvtBroadcast(&es1);
+ chThdSleepMilliseconds(50);
+ chEvtBroadcast(&es2);
+}]]></value>
+ </shared_code>
+ <cases>
+ <case>
+ <brief>
+ <value>Events registration.</value>
+ </brief>
+ <description>
+ <value>Two event listeners are registered on an event source and then unregistered in the same order.&lt;br&gt;&#xD;
+The test expects that the even source has listeners after the registrations and after the first unregistration, then, after the second unegistration, the test expects no more listeners.</value>
+ </description>
+ <condition>
+ <value />
+ </condition>
+ <various_code>
+ <setup_code>
+ <value />
+ </setup_code>
+ <teardown_code>
+ <value />
+ </teardown_code>
+ <local_variables>
+ <value><![CDATA[event_listener_t el1, el2;]]></value>
+ </local_variables>
+ </various_code>
+ <steps>
+ <step>
+ <description>
+ <value>An Event Source is initialized.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[chEvtObjectInit(&es1);]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Two Event Listeners are registered on the Event Source, the Event Source is tested to have listeners.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[chEvtRegisterMask(&es1, &el1, 1);
+chEvtRegisterMask(&es1, &el2, 2);
+test_assert_lock(chEvtIsListeningI(&es1), "no listener");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>An Event Listener is unregistered, the Event Source must still have listeners.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[chEvtUnregister(&es1, &el1);
+test_assert_lock(chEvtIsListeningI(&es1), "no listener");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>An Event Listener is unregistered, the Event Source must not have listeners.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[chEvtUnregister(&es1, &el2);
+test_assert_lock(!chEvtIsListeningI(&es1), "stuck listener");]]></value>
+ </code>
+ </step>
+ </steps>
+ </case>
+ <case>
+ <brief>
+ <value>Event Flags dispatching.</value>
+ </brief>
+ <description>
+ <value>The test dispatches three event flags and verifies that the associated event handlers are invoked in LSb-first order.</value>
+ </description>
+ <condition>
+ <value />
+ </condition>
+ <various_code>
+ <setup_code>
+ <value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
+ </setup_code>
+ <teardown_code>
+ <value />
+ </teardown_code>
+ <local_variables>
+ <value />
+ </local_variables>
+ </various_code>
+ <steps>
+ <step>
+ <description>
+ <value>Three evenf flag bits are raised then chEvtDispatch() is invoked, the sequence of handlers calls is tested.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[chEvtDispatch(evhndl, 7);
+test_assert_sequence("ABC", "invalid sequence");]]></value>
+ </code>
+ </step>
+ </steps>
+ </case>
+ <case>
+ <brief>
+ <value>Events Flags wait using chEvtWaitOne().</value>
+ </brief>
+ <description>
+ <value>Functionality of chEvtWaitOne() is tested under various scenarios.</value>
+ </description>
+ <condition>
+ <value />
+ </condition>
+ <various_code>
+ <setup_code>
+ <value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
+ </setup_code>
+ <teardown_code>
+ <value />
+ </teardown_code>
+ <local_variables>
+ <value><![CDATA[eventmask_t m;
+systime_t target_time;]]></value>
+ </local_variables>
+ </various_code>
+ <steps>
+ <step>
+ <description>
+ <value>Setting three event flags.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[chEvtAddEvents(7);]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Calling chEvtWaitOne() three times, each time a single flag must be returned in order of priority.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[m = chEvtWaitOne(ALL_EVENTS);
+test_assert(m == 1, "single event error");
+m = chEvtWaitOne(ALL_EVENTS);
+test_assert(m == 2, "single event error");
+m = chEvtWaitOne(ALL_EVENTS);
+test_assert(m == 4, "single event error");
+m = chEvtGetAndClearEvents(ALL_EVENTS);
+test_assert(m == 0, "stuck event");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Getting current time and starting a signaler thread, the thread will set an event flag after 50mS.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[target_time = test_wait_tick() + MS2ST(50);
+threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
+ evt_thread3, chThdGetSelfX());]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Calling chEvtWaitOne() then verifying that the event has been received after 50mS and that the event flags mask has been emptied.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[m = chEvtWaitOne(ALL_EVENTS);
+test_assert_time_window(target_time, target_time + ALLOWED_DELAY,
+ "out of time window");
+test_assert(m == 1, "event flag error");
+m = chEvtGetAndClearEvents(ALL_EVENTS);
+test_assert(m == 0, "stuck event");
+test_wait_threads();]]></value>
+ </code>
+ </step>
+ </steps>
+ </case>
+ <case>
+ <brief>
+ <value>Events Flags wait using chEvtWaitAny().</value>
+ </brief>
+ <description>
+ <value>Functionality of chEvtWaitAny() is tested under various scenarios.</value>
+ </description>
+ <condition>
+ <value />
+ </condition>
+ <various_code>
+ <setup_code>
+ <value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
+ </setup_code>
+ <teardown_code>
+ <value />
+ </teardown_code>
+ <local_variables>
+ <value><![CDATA[eventmask_t m;
+systime_t target_time;]]></value>
+ </local_variables>
+ </various_code>
+ <steps>
+ <step>
+ <description>
+ <value>Setting two, non contiguous, event flags.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[chEvtAddEvents(5);]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Calling chEvtWaitAny() one time, the two flags must be returned.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[m = chEvtWaitAny(ALL_EVENTS);
+test_assert(m == 5, "unexpected pending bit");
+m = chEvtGetAndClearEvents(ALL_EVENTS);
+test_assert(m == 0, "stuck event");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Getting current time and starting a signaler thread, the thread will set an event flag after 50mS.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[target_time = test_wait_tick() + MS2ST(50);
+threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
+ evt_thread3, chThdGetSelfX());]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Calling chEvtWaitAny() then verifying that the event has been received after 50mS and that the event flags mask has been emptied.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[m = chEvtWaitAny(ALL_EVENTS);
+test_assert_time_window(target_time, target_time + ALLOWED_DELAY,
+ "out of time window");
+test_assert(m == 1, "event flag error");
+m = chEvtGetAndClearEvents(ALL_EVENTS);
+test_assert(m == 0, "stuck event");
+test_wait_threads();]]></value>
+ </code>
+ </step>
+ </steps>
+ </case>
+ <case>
+ <brief>
+ <value>Events Flags wait using chEvtWaitAll().</value>
+ </brief>
+ <description>
+ <value>Functionality of chEvtWaitAll() is tested under various scenarios.</value>
+ </description>
+ <condition>
+ <value />
+ </condition>
+ <various_code>
+ <setup_code>
+ <value><![CDATA[chEvtGetAndClearEvents(ALL_EVENTS);]]></value>
+ </setup_code>
+ <teardown_code>
+ <value />
+ </teardown_code>
+ <local_variables>
+ <value><![CDATA[eventmask_t m;
+systime_t target_time;]]></value>
+ </local_variables>
+ </various_code>
+ <steps>
+ <step>
+ <description>
+ <value>Setting two, non contiguous, event flags.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[chEvtAddEvents(5);]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Calling chEvtWaitAll() one time, the two flags must be returned.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[m = chEvtWaitAll(5);
+test_assert(m == 5, "unexpected pending bit");
+m = chEvtGetAndClearEvents(ALL_EVENTS);
+test_assert(m == 0, "stuck event");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Setting one event flag.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[chEvtAddEvents(4);]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Getting current time and starting a signaler thread, the thread will set another event flag after 50mS.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[target_time = test_wait_tick() + MS2ST(50);
+threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
+ evt_thread3, chThdGetSelfX());]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Calling chEvtWaitAll() then verifying that both event flags have been received after 50mS and that the event flags mask has been emptied.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[m = chEvtWaitAll(5);
+test_assert_time_window(target_time, target_time + ALLOWED_DELAY,
+ "out of time window");
+test_assert(m == 5, "event flags error");
+m = chEvtGetAndClearEvents(ALL_EVENTS);
+test_assert(m == 0, "stuck event");
+test_wait_threads();]]></value>
+ </code>
+ </step>
+ </steps>
+ </case>
+ </cases>
+ </sequence>
+ <sequence>
+ <type index="0">
+ <value>Internal Tests</value>
+ </type>
+ <brief>
<value>Mailboxes.</value>
</brief>
<description>
diff --git a/test/rt/source/test/test_root.c b/test/rt/source/test/test_root.c
index 796af8fbb..9ecbd3dea 100644
--- a/test/rt/source/test/test_root.c
+++ b/test/rt/source/test/test_root.c
@@ -30,6 +30,7 @@
* - @subpage test_sequence_007
* - @subpage test_sequence_008
* - @subpage test_sequence_009
+ * - @subpage test_sequence_010
* .
*/
@@ -61,6 +62,7 @@ const testcase_t * const *test_suite[] = {
test_sequence_007,
test_sequence_008,
test_sequence_009,
+ test_sequence_010,
NULL
};
diff --git a/test/rt/source/test/test_root.h b/test/rt/source/test/test_root.h
index 114bfd9bf..6bbb1c989 100644
--- a/test/rt/source/test/test_root.h
+++ b/test/rt/source/test/test_root.h
@@ -31,6 +31,7 @@
#include "test_sequence_007.h"
#include "test_sequence_008.h"
#include "test_sequence_009.h"
+#include "test_sequence_010.h"
#if !defined(__DOXYGEN__)
diff --git a/test/rt/source/test/test_sequence_007.c b/test/rt/source/test/test_sequence_007.c
index 9563965fb..2a7e014b3 100644
--- a/test/rt/source/test/test_sequence_007.c
+++ b/test/rt/source/test/test_sequence_007.c
@@ -19,355 +19,386 @@
#include "test_root.h"
/**
- * @page test_sequence_007 [7] Mailboxes
+ * @page test_sequence_007 [7] Event Sources and Event Flags
*
* File: @ref test_sequence_007.c
*
* <h2>Description</h2>
- * This sequence tests the ChibiOS/RT functionalities related to
- * mailboxes.
+ * This module implements the test sequence for the Events subsystem.
*
* <h2>Conditions</h2>
* This sequence is only executed if the following preprocessor condition
* evaluates to true:
- * - CH_CFG_USE_MAILBOXES
+ * - CH_CFG_USE_EVENTS
* .
*
* <h2>Test Cases</h2>
* - @subpage test_007_001
* - @subpage test_007_002
* - @subpage test_007_003
+ * - @subpage test_007_004
+ * - @subpage test_007_005
* .
*/
-#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__)
+#if (CH_CFG_USE_EVENTS) || defined(__DOXYGEN__)
/****************************************************************************
* Shared code.
****************************************************************************/
-#define MB_SIZE 4
+static EVENTSOURCE_DECL(es1);
+static EVENTSOURCE_DECL(es2);
-static msg_t mb_buffer[MB_SIZE];
-static MAILBOX_DECL(mb1, mb_buffer, MB_SIZE);
+static void h1(eventid_t id) {(void)id;test_emit_token('A');}
+static void h2(eventid_t id) {(void)id;test_emit_token('B');}
+static void h3(eventid_t id) {(void)id;test_emit_token('C');}
+static ROMCONST evhandler_t evhndl[] = {h1, h2, h3};
+
+static THD_FUNCTION(evt_thread3, p) {
+
+ chThdSleepMilliseconds(50);
+ chEvtSignal((thread_t *)p, 1);
+}
+
+static THD_FUNCTION(evt_thread4, p) {
+
+ (void)p;
+ chEvtBroadcast(&es1);
+ chThdSleepMilliseconds(50);
+ chEvtBroadcast(&es2);
+}
/****************************************************************************
* Test cases.
****************************************************************************/
/**
- * @page test_007_001 [7.1] Mailbox normal API, non-blocking tests
+ * @page test_007_001 [7.1] Events registration
*
* <h2>Description</h2>
- * The mailbox normal API is tested without triggering blocking
- * conditions.
+ * Two event listeners are registered on an event source and then
+ * unregistered in the same order.<br> The test expects that the even
+ * source has listeners after the registrations and after the first
+ * unregistration, then, after the second unegistration, the test
+ * expects no more listeners.
*
* <h2>Test Steps</h2>
- * - [7.1.1] Testing the mailbox size.
- * - [7.1.2] Resetting the mailbox, conditions are checked, no errors
- * expected.
- * - [7.1.3] Filling the mailbox using chMBPost() and chMBPostAhead()
- * once, no errors expected.
- * - [7.1.4] Testing intermediate conditions. Data pointers must be
- * aligned, semaphore counters are checked.
- * - [7.1.5] Emptying the mailbox using chMBFetch(), no errors
- * expected.
- * - [7.1.6] Posting and then fetching one more message, no errors
- * expected.
- * - [7.1.7] Testing final conditions. Data pointers must be aligned to
- * buffer start, semaphore counters are checked.
+ * - [7.1.1] An Event Source is initialized.
+ * - [7.1.2] Two Event Listeners are registered on the Event Source,
+ * the Event Source is tested to have listeners.
+ * - [7.1.3] An Event Listener is unregistered, the Event Source must
+ * still have listeners.
+ * - [7.1.4] An Event Listener is unregistered, the Event Source must
+ * not have listeners.
* .
*/
-static void test_007_001_setup(void) {
- chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
-}
-
-static void test_007_001_teardown(void) {
- chMBReset(&mb1);
-}
-
static void test_007_001_execute(void) {
- msg_t msg1, msg2;
- unsigned i;
+ event_listener_t el1, el2;
- /* [7.1.1] Testing the mailbox size.*/
+ /* [7.1.1] An Event Source is initialized.*/
test_set_step(1);
{
- test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size");
+ chEvtObjectInit(&es1);
}
- /* [7.1.2] Resetting the mailbox, conditions are checked, no errors
- expected.*/
+ /* [7.1.2] Two Event Listeners are registered on the Event Source,
+ the Event Source is tested to have listeners.*/
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");
+ chEvtRegisterMask(&es1, &el1, 1);
+ chEvtRegisterMask(&es1, &el2, 2);
+ test_assert_lock(chEvtIsListeningI(&es1), "no listener");
}
- /* [7.1.3] Filling the mailbox using chMBPost() and chMBPostAhead()
- once, no errors expected.*/
+ /* [7.1.3] An Event Listener is unregistered, the Event Source must
+ still have listeners.*/
test_set_step(3);
{
- 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");
+ chEvtUnregister(&es1, &el1);
+ test_assert_lock(chEvtIsListeningI(&es1), "no listener");
}
- /* [7.1.4] Testing intermediate conditions. Data pointers must be
- aligned, semaphore counters are checked.*/
+ /* [7.1.4] An Event Listener is unregistered, the Event Source must
+ not have listeners.*/
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");
- }
-
- /* [7.1.5] Emptying the mailbox using chMBFetch(), no errors
- expected.*/
- test_set_step(5);
- {
- 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");
- }
-
- /* [7.1.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");
- }
-
- /* [7.1.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");
+ chEvtUnregister(&es1, &el2);
+ test_assert_lock(!chEvtIsListeningI(&es1), "stuck listener");
}
}
static const testcase_t test_007_001 = {
- "Mailbox normal API, non-blocking tests",
- test_007_001_setup,
- test_007_001_teardown,
+ "Events registration",
+ NULL,
+ NULL,
test_007_001_execute
};
/**
- * @page test_007_002 [7.2] Mailbox I-Class API, non-blocking tests
+ * @page test_007_002 [7.2] Event Flags dispatching
*
* <h2>Description</h2>
- * The mailbox I-Class API is tested without triggering blocking
- * conditions.
+ * The test dispatches three event flags and verifies that the
+ * associated event handlers are invoked in LSb-first order.
*
* <h2>Test Steps</h2>
- * - [7.2.1] Testing the mailbox size.
- * - [7.2.2] Resetting the mailbox, conditions are checked, no errors
- * expected.
- * - [7.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI()
- * once, no errors expected.
- * - [7.2.4] Testing intermediate conditions. Data pointers must be
- * aligned, semaphore counters are checked.
- * - [7.2.5] Emptying the mailbox using chMBFetchI(), no errors
- * expected.
- * - [7.2.6] Posting and then fetching one more message, no errors
- * expected.
- * - [7.2.7] Testing final conditions. Data pointers must be aligned to
- * buffer start, semaphore counters are checked.
+ * - [7.2.1] Three evenf flag bits are raised then chEvtDispatch() is
+ * invoked, the sequence of handlers calls is tested.
* .
*/
static void test_007_002_setup(void) {
- chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
+ chEvtGetAndClearEvents(ALL_EVENTS);
}
-static void test_007_002_teardown(void) {
- chMBReset(&mb1);
+static void test_007_002_execute(void) {
+
+ /* [7.2.1] Three evenf flag bits are raised then chEvtDispatch() is
+ invoked, the sequence of handlers calls is tested.*/
+ test_set_step(1);
+ {
+ chEvtDispatch(evhndl, 7);
+ test_assert_sequence("ABC", "invalid sequence");
+ }
}
-static void test_007_002_execute(void) {
- msg_t msg1, msg2;
- unsigned i;
+static const testcase_t test_007_002 = {
+ "Event Flags dispatching",
+ test_007_002_setup,
+ NULL,
+ test_007_002_execute
+};
+
+/**
+ * @page test_007_003 [7.3] Events Flags wait using chEvtWaitOne()
+ *
+ * <h2>Description</h2>
+ * Functionality of chEvtWaitOne() is tested under various scenarios.
+ *
+ * <h2>Test Steps</h2>
+ * - [7.3.1] Setting three event flags.
+ * - [7.3.2] Calling chEvtWaitOne() three times, each time a single
+ * flag must be returned in order of priority.
+ * - [7.3.3] Getting current time and starting a signaler thread, the
+ * thread will set an event flag after 50mS.
+ * - [7.3.4] Calling chEvtWaitOne() then verifying that the event has
+ * been received after 50mS and that the event flags mask has been
+ * emptied.
+ * .
+ */
- /* [7.2.1] Testing the mailbox size.*/
+static void test_007_003_setup(void) {
+ chEvtGetAndClearEvents(ALL_EVENTS);
+}
+
+static void test_007_003_execute(void) {
+ eventmask_t m;
+ systime_t target_time;
+
+ /* [7.3.1] Setting three event flags.*/
test_set_step(1);
{
- test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size");
+ chEvtAddEvents(7);
}
- /* [7.2.2] Resetting the mailbox, conditions are checked, no errors
- expected.*/
+ /* [7.3.2] Calling chEvtWaitOne() three times, each time a single
+ flag must be returned in order of priority.*/
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");
+ m = chEvtWaitOne(ALL_EVENTS);
+ test_assert(m == 1, "single event error");
+ m = chEvtWaitOne(ALL_EVENTS);
+ test_assert(m == 2, "single event error");
+ m = chEvtWaitOne(ALL_EVENTS);
+ test_assert(m == 4, "single event error");
+ m = chEvtGetAndClearEvents(ALL_EVENTS);
+ test_assert(m == 0, "stuck event");
}
- /* [7.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI()
- once, no errors expected.*/
+ /* [7.3.3] Getting current time and starting a signaler thread, the
+ thread will set an event flag after 50mS.*/
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");
+ target_time = test_wait_tick() + MS2ST(50);
+ threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
+ evt_thread3, chThdGetSelfX());
}
- /* [7.2.4] Testing intermediate conditions. Data pointers must be
- aligned, semaphore counters are checked.*/
+ /* [7.3.4] Calling chEvtWaitOne() then verifying that the event has
+ been received after 50mS and that the event flags mask has been
+ emptied.*/
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");
+ m = chEvtWaitOne(ALL_EVENTS);
+ test_assert_time_window(target_time, target_time + ALLOWED_DELAY,
+ "out of time window");
+ test_assert(m == 1, "event flag error");
+ m = chEvtGetAndClearEvents(ALL_EVENTS);
+ test_assert(m == 0, "stuck event");
+ test_wait_threads();
}
+}
- /* [7.2.5] Emptying the mailbox using chMBFetchI(), no errors
- expected.*/
- test_set_step(5);
+static const testcase_t test_007_003 = {
+ "Events Flags wait using chEvtWaitOne()",
+ test_007_003_setup,
+ NULL,
+ test_007_003_execute
+};
+
+/**
+ * @page test_007_004 [7.4] Events Flags wait using chEvtWaitAny()
+ *
+ * <h2>Description</h2>
+ * Functionality of chEvtWaitAny() is tested under various scenarios.
+ *
+ * <h2>Test Steps</h2>
+ * - [7.4.1] Setting two, non contiguous, event flags.
+ * - [7.4.2] Calling chEvtWaitAny() one time, the two flags must be
+ * returned.
+ * - [7.4.3] Getting current time and starting a signaler thread, the
+ * thread will set an event flag after 50mS.
+ * - [7.4.4] Calling chEvtWaitAny() then verifying that the event has
+ * been received after 50mS and that the event flags mask has been
+ * emptied.
+ * .
+ */
+
+static void test_007_004_setup(void) {
+ chEvtGetAndClearEvents(ALL_EVENTS);
+}
+
+static void test_007_004_execute(void) {
+ eventmask_t m;
+ systime_t target_time;
+
+ /* [7.4.1] Setting two, non contiguous, event flags.*/
+ test_set_step(1);
{
- 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");
+ chEvtAddEvents(5);
}
- /* [7.2.6] Posting and then fetching one more message, no errors
- expected.*/
- test_set_step(6);
+ /* [7.4.2] Calling chEvtWaitAny() one time, the two flags must be
+ returned.*/
+ test_set_step(2);
+ {
+ m = chEvtWaitAny(ALL_EVENTS);
+ test_assert(m == 5, "unexpected pending bit");
+ m = chEvtGetAndClearEvents(ALL_EVENTS);
+ test_assert(m == 0, "stuck event");
+ }
+
+ /* [7.4.3] Getting current time and starting a signaler thread, the
+ thread will set an event flag after 50mS.*/
+ test_set_step(3);
{
- 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");
+ target_time = test_wait_tick() + MS2ST(50);
+ threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
+ evt_thread3, chThdGetSelfX());
}
- /* [7.2.7] Testing final conditions. Data pointers must be aligned to
- buffer start, semaphore counters are checked.*/
- test_set_step(7);
+ /* [7.4.4] Calling chEvtWaitAny() then verifying that the event has
+ been received after 50mS and that the event flags mask has been
+ emptied.*/
+ test_set_step(4);
{
- 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");
+ m = chEvtWaitAny(ALL_EVENTS);
+ test_assert_time_window(target_time, target_time + ALLOWED_DELAY,
+ "out of time window");
+ test_assert(m == 1, "event flag error");
+ m = chEvtGetAndClearEvents(ALL_EVENTS);
+ test_assert(m == 0, "stuck event");
+ test_wait_threads();
}
}
-static const testcase_t test_007_002 = {
- "Mailbox I-Class API, non-blocking tests",
- test_007_002_setup,
- test_007_002_teardown,
- test_007_002_execute
+static const testcase_t test_007_004 = {
+ "Events Flags wait using chEvtWaitAny()",
+ test_007_004_setup,
+ NULL,
+ test_007_004_execute
};
/**
- * @page test_007_003 [7.3] Mailbox timeouts
+ * @page test_007_005 [7.5] Events Flags wait using chEvtWaitAll()
*
* <h2>Description</h2>
- * The mailbox API is tested for timeouts.
+ * Functionality of chEvtWaitAll() is tested under various scenarios.
*
* <h2>Test Steps</h2>
- * - [7.3.1] Filling the mailbox.
- * - [7.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and
- * chMBPostAheadI() timeout.
- * - [7.3.3] Resetting the mailbox.
- * - [7.3.4] Testing chMBFetch() and chMBFetchI() timeout.
+ * - [7.5.1] Setting two, non contiguous, event flags.
+ * - [7.5.2] Calling chEvtWaitAll() one time, the two flags must be
+ * returned.
+ * - [7.5.3] Setting one event flag.
+ * - [7.5.4] Getting current time and starting a signaler thread, the
+ * thread will set another event flag after 50mS.
+ * - [7.5.5] Calling chEvtWaitAll() then verifying that both event
+ * flags have been received after 50mS and that the event flags mask
+ * has been emptied.
* .
*/
-static void test_007_003_setup(void) {
- chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
-}
-
-static void test_007_003_teardown(void) {
- chMBReset(&mb1);
+static void test_007_005_setup(void) {
+ chEvtGetAndClearEvents(ALL_EVENTS);
}
-static void test_007_003_execute(void) {
- msg_t msg1, msg2;
- unsigned i;
+static void test_007_005_execute(void) {
+ eventmask_t m;
+ systime_t target_time;
- /* [7.3.1] Filling the mailbox.*/
+ /* [7.5.1] Setting two, non contiguous, event flags.*/
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");
- }
+ chEvtAddEvents(5);
}
- /* [7.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and
- chMBPostAheadI() timeout.*/
+ /* [7.5.2] Calling chEvtWaitAll() one time, the two flags must be
+ returned.*/
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");
+ m = chEvtWaitAll(5);
+ test_assert(m == 5, "unexpected pending bit");
+ m = chEvtGetAndClearEvents(ALL_EVENTS);
+ test_assert(m == 0, "stuck event");
}
- /* [7.3.3] Resetting the mailbox.*/
+ /* [7.5.3] Setting one event flag.*/
test_set_step(3);
{
- chMBReset(&mb1);
+ chEvtAddEvents(4);
}
- /* [7.3.4] Testing chMBFetch() and chMBFetchI() timeout.*/
+ /* [7.5.4] Getting current time and starting a signaler thread, the
+ thread will set another event flag after 50mS.*/
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");
+ target_time = test_wait_tick() + MS2ST(50);
+ threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
+ evt_thread3, chThdGetSelfX());
+ }
+
+ /* [7.5.5] Calling chEvtWaitAll() then verifying that both event
+ flags have been received after 50mS and that the event flags mask
+ has been emptied.*/
+ test_set_step(5);
+ {
+ m = chEvtWaitAll(5);
+ test_assert_time_window(target_time, target_time + ALLOWED_DELAY,
+ "out of time window");
+ test_assert(m == 5, "event flags error");
+ m = chEvtGetAndClearEvents(ALL_EVENTS);
+ test_assert(m == 0, "stuck event");
+ test_wait_threads();
}
}
-static const testcase_t test_007_003 = {
- "Mailbox timeouts",
- test_007_003_setup,
- test_007_003_teardown,
- test_007_003_execute
+static const testcase_t test_007_005 = {
+ "Events Flags wait using chEvtWaitAll()",
+ test_007_005_setup,
+ NULL,
+ test_007_005_execute
};
/****************************************************************************
@@ -375,13 +406,15 @@ static const testcase_t test_007_003 = {
****************************************************************************/
/**
- * @brief Mailboxes.
+ * @brief Event Sources and Event Flags.
*/
const testcase_t * const test_sequence_007[] = {
&test_007_001,
&test_007_002,
&test_007_003,
+ &test_007_004,
+ &test_007_005,
NULL
};
-#endif /* CH_CFG_USE_MAILBOXES */
+#endif /* CH_CFG_USE_EVENTS */
diff --git a/test/rt/source/test/test_sequence_008.c b/test/rt/source/test/test_sequence_008.c
index 6e9c05f1c..4e3c1beb1 100644
--- a/test/rt/source/test/test_sequence_008.c
+++ b/test/rt/source/test/test_sequence_008.c
@@ -19,18 +19,18 @@
#include "test_root.h"
/**
- * @page test_sequence_008 [8] Memory Pools
+ * @page test_sequence_008 [8] Mailboxes
*
* File: @ref test_sequence_008.c
*
* <h2>Description</h2>
- * This sequence tests the ChibiOS/RT functionalities related to memory
- * pools.
+ * This sequence tests the ChibiOS/RT functionalities related to
+ * mailboxes.
*
* <h2>Conditions</h2>
* This sequence is only executed if the following preprocessor condition
* evaluates to true:
- * - CH_CFG_USE_MEMPOOLS
+ * - CH_CFG_USE_MAILBOXES
* .
*
* <h2>Test Cases</h2>
@@ -40,251 +40,348 @@
* .
*/
-#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
+#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__)
/****************************************************************************
* Shared code.
****************************************************************************/
-#define MEMORY_POOL_SIZE 4
+#define MB_SIZE 4
-static uint32_t objects[MEMORY_POOL_SIZE];
-static MEMORYPOOL_DECL(mp1, sizeof (uint32_t), NULL);
-static GUARDEDMEMORYPOOL_DECL(gmp1, sizeof (uint32_t));
-
-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_008_001 [8.1] Loading and emptying a memory pool
+ * @page test_008_001 [8.1] Mailbox normal API, non-blocking tests
*
* <h2>Description</h2>
- * 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.
*
* <h2>Test Steps</h2>
- * - [8.1.1] Adding the objects to the pool using chPoolLoadArray().
- * - [8.1.2] Emptying the pool using chPoolAlloc().
- * - [8.1.3] Now must be empty.
- * - [8.1.4] Adding the objects to the pool using chPoolFree().
- * - [8.1.5] Emptying the pool using chPoolAlloc() again.
- * - [8.1.6] Now must be empty again.
- * - [8.1.7] Covering the case where a provider is unable to return
- * more memory.
+ * - [8.1.1] Testing the mailbox size.
+ * - [8.1.2] Resetting the mailbox, conditions are checked, no errors
+ * expected.
+ * - [8.1.3] Filling the mailbox using chMBPost() and chMBPostAhead()
+ * once, no errors expected.
+ * - [8.1.4] Testing intermediate conditions. Data pointers must be
+ * aligned, semaphore counters are checked.
+ * - [8.1.5] Emptying the mailbox using chMBFetch(), no errors
+ * expected.
+ * - [8.1.6] Posting and then fetching one more message, no errors
+ * expected.
+ * - [8.1.7] Testing final conditions. Data pointers must be aligned to
+ * buffer start, semaphore counters are checked.
* .
*/
static void test_008_001_setup(void) {
- chPoolObjectInit(&mp1, sizeof (uint32_t), NULL);
+ chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
+}
+
+static void test_008_001_teardown(void) {
+ chMBReset(&mb1);
}
static void test_008_001_execute(void) {
+ msg_t msg1, msg2;
unsigned i;
- /* [8.1.1] Adding the objects to the pool using chPoolLoadArray().*/
+ /* [8.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");
}
- /* [8.1.2] Emptying the pool using chPoolAlloc().*/
+ /* [8.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");
}
- /* [8.1.3] Now must be empty.*/
+ /* [8.1.3] Filling the mailbox using chMBPost() and chMBPostAhead()
+ once, no errors expected.*/
test_set_step(3);
{
- test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
+ 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");
}
- /* [8.1.4] Adding the objects to the pool using chPoolFree().*/
+ /* [8.1.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++)
- chPoolFree(&mp1, &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");
}
- /* [8.1.5] Emptying the pool using chPoolAlloc() again.*/
+ /* [8.1.5] Emptying the mailbox using chMBFetch(), no errors
+ expected.*/
test_set_step(5);
{
- for (i = 0; i < MEMORY_POOL_SIZE; i++)
- test_assert(chPoolAlloc(&mp1) != NULL, "list 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");
}
- /* [8.1.6] Now must be empty again.*/
+ /* [8.1.6] Posting and then fetching one more message, no errors
+ expected.*/
test_set_step(6);
{
- test_assert(chPoolAlloc(&mp1) == 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");
}
- /* [8.1.7] Covering the case where a provider is unable to return
- more memory.*/
+ /* [8.1.7] Testing final conditions. Data pointers must be aligned to
+ buffer start, semaphore counters are checked.*/
test_set_step(7);
{
- chPoolObjectInit(&mp1, sizeof (uint32_t), null_provider);
- test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");
+ 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_008_001 = {
- "Loading and emptying a memory pool",
+ "Mailbox normal API, non-blocking tests",
test_008_001_setup,
- NULL,
+ test_008_001_teardown,
test_008_001_execute
};
-#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
/**
- * @page test_008_002 [8.2] Loading and emptying a guarded memory pool without waiting
+ * @page test_008_002 [8.2] Mailbox I-Class API, non-blocking tests
*
* <h2>Description</h2>
- * The memory pool functionality is tested by loading and emptying it,
- * all conditions are tested.
- *
- * <h2>Conditions</h2>
- * This test is only executed if the following preprocessor condition
- * evaluates to true:
- * - CH_CFG_USE_SEMAPHORES
- * .
+ * The mailbox I-Class API is tested without triggering blocking
+ * conditions.
*
* <h2>Test Steps</h2>
- * - [8.2.1] Adding the objects to the pool using
- * chGuardedPoolLoadArray().
- * - [8.2.2] Emptying the pool using chGuardedPoolAllocTimeout().
- * - [8.2.3] Now must be empty.
- * - [8.2.4] Adding the objects to the pool using chGuardedPoolFree().
- * - [8.2.5] Emptying the pool using chGuardedPoolAllocTimeout() again.
- * - [8.2.6] Now must be empty again.
+ * - [8.2.1] Testing the mailbox size.
+ * - [8.2.2] Resetting the mailbox, conditions are checked, no errors
+ * expected.
+ * - [8.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI()
+ * once, no errors expected.
+ * - [8.2.4] Testing intermediate conditions. Data pointers must be
+ * aligned, semaphore counters are checked.
+ * - [8.2.5] Emptying the mailbox using chMBFetchI(), no errors
+ * expected.
+ * - [8.2.6] Posting and then fetching one more message, no errors
+ * expected.
+ * - [8.2.7] Testing final conditions. Data pointers must be aligned to
+ * buffer start, semaphore counters are checked.
* .
*/
static void test_008_002_setup(void) {
- chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
+ chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
+}
+
+static void test_008_002_teardown(void) {
+ chMBReset(&mb1);
}
static void test_008_002_execute(void) {
+ msg_t msg1, msg2;
unsigned i;
- /* [8.2.1] Adding the objects to the pool using
- chGuardedPoolLoadArray().*/
+ /* [8.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");
}
- /* [8.2.2] Emptying the pool using chGuardedPoolAllocTimeout().*/
+ /* [8.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");
}
- /* [8.2.3] Now must be empty.*/
+ /* [8.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");
}
- /* [8.2.4] Adding the objects to the pool using
- chGuardedPoolFree().*/
+ /* [8.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");
}
- /* [8.2.5] Emptying the pool using chGuardedPoolAllocTimeout()
- again.*/
+ /* [8.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");
}
- /* [8.2.6] Now must be empty again.*/
+ /* [8.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");
+ }
+
+ /* [8.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_008_002 = {
- "Loading and emptying a guarded memory pool without waiting",
+ "Mailbox I-Class API, non-blocking tests",
test_008_002_setup,
- NULL,
+ test_008_002_teardown,
test_008_002_execute
};
-#endif /* CH_CFG_USE_SEMAPHORES */
-#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
/**
- * @page test_008_003 [8.3] Guarded Memory Pools timeout
+ * @page test_008_003 [8.3] Mailbox timeouts
*
* <h2>Description</h2>
- * The timeout features for the Guarded Memory Pools is tested.
- *
- * <h2>Conditions</h2>
- * This test is only executed if the following preprocessor condition
- * evaluates to true:
- * - CH_CFG_USE_SEMAPHORES
- * .
+ * The mailbox API is tested for timeouts.
*
* <h2>Test Steps</h2>
- * - [8.3.1] Trying to allocate with 100mS timeout, must fail because
- * the pool is empty.
+ * - [8.3.1] Filling the mailbox.
+ * - [8.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and
+ * chMBPostAheadI() timeout.
+ * - [8.3.3] Resetting the mailbox.
+ * - [8.3.4] Testing chMBFetch() and chMBFetchI() timeout.
* .
*/
static void test_008_003_setup(void) {
- chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
+ chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
+}
+
+static void test_008_003_teardown(void) {
+ chMBReset(&mb1);
}
static void test_008_003_execute(void) {
+ msg_t msg1, msg2;
+ unsigned i;
- /* [8.3.1] Trying to allocate with 100mS timeout, must fail because
- the pool is empty.*/
+ /* [8.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");
+ }
+ }
+
+ /* [8.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");
+ }
+
+ /* [8.3.3] Resetting the mailbox.*/
+ test_set_step(3);
+ {
+ chMBReset(&mb1);
+ }
+
+ /* [8.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_008_003 = {
- "Guarded Memory Pools timeout",
+ "Mailbox timeouts",
test_008_003_setup,
- NULL,
+ test_008_003_teardown,
test_008_003_execute
};
-#endif /* CH_CFG_USE_SEMAPHORES */
/****************************************************************************
* Exported data.
****************************************************************************/
/**
- * @brief Memory Pools.
+ * @brief Mailboxes.
*/
const testcase_t * const test_sequence_008[] = {
&test_008_001,
-#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
&test_008_002,
-#endif
-#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
&test_008_003,
-#endif
NULL
};
-#endif /* CH_CFG_USE_MEMPOOLS */
+#endif /* CH_CFG_USE_MAILBOXES */
diff --git a/test/rt/source/test/test_sequence_009.c b/test/rt/source/test/test_sequence_009.c
index b980b828e..63e9f2da2 100644
--- a/test/rt/source/test/test_sequence_009.c
+++ b/test/rt/source/test/test_sequence_009.c
@@ -19,252 +19,272 @@
#include "test_root.h"
/**
- * @page test_sequence_009 [9] Memory Heaps
+ * @page test_sequence_009 [9] Memory Pools
*
* File: @ref test_sequence_009.c
*
* <h2>Description</h2>
* This sequence tests the ChibiOS/RT functionalities related to memory
- * heaps.
+ * pools.
*
* <h2>Conditions</h2>
* This sequence is only executed if the following preprocessor condition
* evaluates to true:
- * - CH_CFG_USE_HEAP
+ * - CH_CFG_USE_MEMPOOLS
* .
*
* <h2>Test Cases</h2>
* - @subpage test_009_001
* - @subpage test_009_002
+ * - @subpage test_009_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);
+static GUARDEDMEMORYPOOL_DECL(gmp1, sizeof (uint32_t));
+
+static void *null_provider(size_t size, unsigned align) {
+
+ (void)size;
+ (void)align;
+
+ return NULL;
+}
/****************************************************************************
* Test cases.
****************************************************************************/
/**
- * @page test_009_001 [9.1] Allocation and fragmentation
+ * @page test_009_001 [9.1] Loading and emptying a memory pool
*
* <h2>Description</h2>
- * Series of allocations/deallocations are performed in carefully
- * designed sequences in order to stimulate all the possible code paths
- * inside the allocator. The test expects to find the heap back to the
- * initial status after each sequence.
+ * The memory pool functionality is tested by loading and emptying it,
+ * all conditions are tested.
*
* <h2>Test Steps</h2>
- * - [9.1.1] Testing initial conditions, the heap must not be
- * fragmented and one free block present.
- * - [9.1.2] Trying to allocate an block bigger than available space,
- * an error is expected.
- * - [9.1.3] Single block allocation using chHeapAlloc() then the block
- * is freed using chHeapFree(), must not fail.
- * - [9.1.4] Using chHeapStatus() to assess the heap state. There must
- * be at least one free block of sufficient size.
- * - [9.1.5] Allocating then freeing in the same order.
- * - [9.1.6] Allocating then freeing in reverse order.
- * - [9.1.7] Small fragments handling. Checking the behavior when
- * allocating blocks with size not multiple of alignment unit.
- * - [9.1.8] Skipping a fragment, the first fragment in the list is too
- * small so the allocator must pick the second one.
- * - [9.1.9] Allocating the whole available space.
- * - [9.1.10] Testing final conditions. The heap geometry must be the
- * same than the one registered at beginning.
+ * - [9.1.1] Adding the objects to the pool using chPoolLoadArray().
+ * - [9.1.2] Emptying the pool using chPoolAlloc().
+ * - [9.1.3] Now must be empty.
+ * - [9.1.4] Adding the objects to the pool using chPoolFree().
+ * - [9.1.5] Emptying the pool using chPoolAlloc() again.
+ * - [9.1.6] Now must be empty again.
+ * - [9.1.7] Covering the case where a provider is unable to return
+ * more memory.
* .
*/
static void test_009_001_setup(void) {
- chHeapObjectInit(&test_heap, myheap, sizeof(myheap));
+ chPoolObjectInit(&mp1, sizeof (uint32_t), NULL);
}
static void test_009_001_execute(void) {
- void *p1, *p2, *p3;
- size_t n, sz;
+ unsigned i;
- /* [9.1.1] Testing initial conditions, the heap must not be
- fragmented and one free block present.*/
+ /* [9.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);
}
- /* [9.1.2] Trying to allocate an block bigger than available space,
- an error is expected.*/
+ /* [9.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");
}
- /* [9.1.3] Single block allocation using chHeapAlloc() then the block
- is freed using chHeapFree(), must not fail.*/
+ /* [9.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");
}
- /* [9.1.4] Using chHeapStatus() to assess the heap state. There must
- be at least one free block of sufficient size.*/
+ /* [9.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]);
}
- /* [9.1.5] Allocating then freeing in the same order.*/
+ /* [9.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");
}
- /* [9.1.6] Allocating then freeing in reverse order.*/
+ /* [9.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");
}
- /* [9.1.7] Small fragments handling. Checking the behavior when
- allocating blocks with size not multiple of alignment unit.*/
+ /* [9.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");
- }
-
- /* [9.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");
- }
-
- /* [9.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);
- }
-
- /* [9.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_009_001 = {
- "Allocation and fragmentation",
+ "Loading and emptying a memory pool",
test_009_001_setup,
NULL,
test_009_001_execute
};
+#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
/**
- * @page test_009_002 [9.2] Default Heap
+ * @page test_009_002 [9.2] Loading and emptying a guarded memory pool without waiting
*
* <h2>Description</h2>
- * The default heap is pre-allocated in the system. We test base
- * functionality.
+ * The memory pool functionality is tested by loading and emptying it,
+ * all conditions are tested.
+ *
+ * <h2>Conditions</h2>
+ * This test is only executed if the following preprocessor condition
+ * evaluates to true:
+ * - CH_CFG_USE_SEMAPHORES
+ * .
*
* <h2>Test Steps</h2>
- * - [9.2.1] Single block allocation using chHeapAlloc() then the block
- * is freed using chHeapFree(), must not fail.
- * - [9.2.2] Testing allocation failure.
+ * - [9.2.1] Adding the objects to the pool using
+ * chGuardedPoolLoadArray().
+ * - [9.2.2] Emptying the pool using chGuardedPoolAllocTimeout().
+ * - [9.2.3] Now must be empty.
+ * - [9.2.4] Adding the objects to the pool using chGuardedPoolFree().
+ * - [9.2.5] Emptying the pool using chGuardedPoolAllocTimeout() again.
+ * - [9.2.6] Now must be empty again.
* .
*/
+static void test_009_002_setup(void) {
+ chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
+}
+
static void test_009_002_execute(void) {
- void *p1;
- size_t total_size, largest_size;
+ unsigned i;
- /* [9.2.1] Single block allocation using chHeapAlloc() then the block
- is freed using chHeapFree(), must not fail.*/
+ /* [9.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);
}
- /* [9.2.2] Testing allocation failure.*/
+ /* [9.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");
+ }
+
+ /* [9.2.3] Now must be empty.*/
+ test_set_step(3);
+ {
+ test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty");
+ }
+
+ /* [9.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]);
+ }
+
+ /* [9.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");
+ }
+
+ /* [9.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_009_002 = {
- "Default Heap",
- NULL,
+ "Loading and emptying a guarded memory pool without waiting",
+ test_009_002_setup,
NULL,
test_009_002_execute
};
+#endif /* CH_CFG_USE_SEMAPHORES */
+
+#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
+/**
+ * @page test_009_003 [9.3] Guarded Memory Pools timeout
+ *
+ * <h2>Description</h2>
+ * The timeout features for the Guarded Memory Pools is tested.
+ *
+ * <h2>Conditions</h2>
+ * This test is only executed if the following preprocessor condition
+ * evaluates to true:
+ * - CH_CFG_USE_SEMAPHORES
+ * .
+ *
+ * <h2>Test Steps</h2>
+ * - [9.3.1] Trying to allocate with 100mS timeout, must fail because
+ * the pool is empty.
+ * .
+ */
+
+static void test_009_003_setup(void) {
+ chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
+}
+
+static void test_009_003_execute(void) {
+
+ /* [9.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_009_003 = {
+ "Guarded Memory Pools timeout",
+ test_009_003_setup,
+ NULL,
+ test_009_003_execute
+};
+#endif /* CH_CFG_USE_SEMAPHORES */
/****************************************************************************
* Exported data.
****************************************************************************/
/**
- * @brief Memory Heaps.
+ * @brief Memory Pools.
*/
const testcase_t * const test_sequence_009[] = {
&test_009_001,
+#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
&test_009_002,
+#endif
+#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
+ &test_009_003,
+#endif
NULL
};
-#endif /* CH_CFG_USE_HEAP */
+#endif /* CH_CFG_USE_MEMPOOLS */
diff --git a/test/rt/source/test/test_sequence_010.c b/test/rt/source/test/test_sequence_010.c
new file mode 100644
index 000000000..dc76be9cc
--- /dev/null
+++ b/test/rt/source/test/test_sequence_010.c
@@ -0,0 +1,270 @@
+/*
+ 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_010 [10] Memory Heaps
+ *
+ * File: @ref test_sequence_010.c
+ *
+ * <h2>Description</h2>
+ * This sequence tests the ChibiOS/RT functionalities related to memory
+ * heaps.
+ *
+ * <h2>Conditions</h2>
+ * This sequence is only executed if the following preprocessor condition
+ * evaluates to true:
+ * - CH_CFG_USE_HEAP
+ * .
+ *
+ * <h2>Test Cases</h2>
+ * - @subpage test_010_001
+ * - @subpage test_010_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_010_001 [10.1] Allocation and fragmentation
+ *
+ * <h2>Description</h2>
+ * Series of allocations/deallocations are performed in carefully
+ * designed sequences in order to stimulate all the possible code paths
+ * inside the allocator. The test expects to find the heap back to the
+ * initial status after each sequence.
+ *
+ * <h2>Test Steps</h2>
+ * - [10.1.1] Testing initial conditions, the heap must not be
+ * fragmented and one free block present.
+ * - [10.1.2] Trying to allocate an block bigger than available space,
+ * an error is expected.
+ * - [10.1.3] Single block allocation using chHeapAlloc() then the
+ * block is freed using chHeapFree(), must not fail.
+ * - [10.1.4] Using chHeapStatus() to assess the heap state. There must
+ * be at least one free block of sufficient size.
+ * - [10.1.5] Allocating then freeing in the same order.
+ * - [10.1.6] Allocating then freeing in reverse order.
+ * - [10.1.7] Small fragments handling. Checking the behavior when
+ * allocating blocks with size not multiple of alignment unit.
+ * - [10.1.8] Skipping a fragment, the first fragment in the list is
+ * too small so the allocator must pick the second one.
+ * - [10.1.9] Allocating the whole available space.
+ * - [10.1.10] Testing final conditions. The heap geometry must be the
+ * same than the one registered at beginning.
+ * .
+ */
+
+static void test_010_001_setup(void) {
+ chHeapObjectInit(&test_heap, myheap, sizeof(myheap));
+}
+
+static void test_010_001_execute(void) {
+ void *p1, *p2, *p3;
+ size_t n, sz;
+
+ /* [10.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");
+ }
+
+ /* [10.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");
+ }
+
+ /* [10.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);
+ }
+
+ /* [10.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");
+ }
+
+ /* [10.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");
+ }
+
+ /* [10.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");
+ }
+
+ /* [10.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");
+ }
+
+ /* [10.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");
+ }
+
+ /* [10.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);
+ }
+
+ /* [10.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_010_001 = {
+ "Allocation and fragmentation",
+ test_010_001_setup,
+ NULL,
+ test_010_001_execute
+};
+
+/**
+ * @page test_010_002 [10.2] Default Heap
+ *
+ * <h2>Description</h2>
+ * The default heap is pre-allocated in the system. We test base
+ * functionality.
+ *
+ * <h2>Test Steps</h2>
+ * - [10.2.1] Single block allocation using chHeapAlloc() then the
+ * block is freed using chHeapFree(), must not fail.
+ * - [10.2.2] Testing allocation failure.
+ * .
+ */
+
+static void test_010_002_execute(void) {
+ void *p1;
+ size_t total_size, largest_size;
+
+ /* [10.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);
+ }
+
+ /* [10.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_010_002 = {
+ "Default Heap",
+ NULL,
+ NULL,
+ test_010_002_execute
+};
+
+/****************************************************************************
+ * Exported data.
+ ****************************************************************************/
+
+/**
+ * @brief Memory Heaps.
+ */
+const testcase_t * const test_sequence_010[] = {
+ &test_010_001,
+ &test_010_002,
+ NULL
+};
+
+#endif /* CH_CFG_USE_HEAP */
diff --git a/test/rt/source/test/test_sequence_010.h b/test/rt/source/test/test_sequence_010.h
new file mode 100644
index 000000000..b20e4a5cd
--- /dev/null
+++ b/test/rt/source/test/test_sequence_010.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_010[];
diff --git a/test/rt/test.mk b/test/rt/test.mk
index d2afbaf36..2afe2ce8d 100644
--- a/test/rt/test.mk
+++ b/test/rt/test.mk
@@ -9,7 +9,8 @@ TESTSRC = ${CHIBIOS}/test/lib/ch_test.c \
${CHIBIOS}/test/rt/source/test/test_sequence_006.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_009.c \
+ ${CHIBIOS}/test/rt/source/test/test_sequence_010.c
# Required include directories
TESTINC = ${CHIBIOS}/test/lib \