ChibiOS/RT Architecture - Reference Manual - Guides |
00001 /* 00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. 00003 00004 This file is part of ChibiOS/RT. 00005 00006 ChibiOS/RT is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 ChibiOS/RT is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 00019 --- 00020 00021 A special exception to the GPL can be applied should you wish to distribute 00022 a combined work that includes ChibiOS/RT, without being obliged to provide 00023 the source code for any proprietary components. See the file exception.txt 00024 for full details of how and when the exception can be applied. 00025 */ 00026 00027 #include "ch.h" 00028 #include "test.h" 00029 00030 /** 00031 * @page test_events Events test 00032 * 00033 * File: @ref testevt.c 00034 * 00035 * <h2>Description</h2> 00036 * This module implements the test sequence for the @ref events subsystem. 00037 * 00038 * <h2>Objective</h2> 00039 * Objective of the test module is to cover 100% of the @ref events subsystem. 00040 * 00041 * <h2>Preconditions</h2> 00042 * The module requires the following kernel options: 00043 * - @p CH_USE_EVENTS 00044 * - @p CH_USE_EVENTS_TIMEOUT 00045 * . 00046 * In case some of the required options are not enabled then some or all tests 00047 * may be skipped. 00048 * 00049 * <h2>Test Cases</h2> 00050 * - @subpage test_events_001 00051 * - @subpage test_events_002 00052 * - @subpage test_events_003 00053 * . 00054 * @file testevt.c 00055 * @brief Events test source file 00056 * @file testevt.h 00057 * @brief Events test header file 00058 */ 00059 00060 #if CH_USE_EVENTS 00061 00062 #define ALLOWED_DELAY MS2ST(5) 00063 00064 /* 00065 * Note, the static initializers are not really required because the 00066 * variables are explicitly initialized in each test case. It is done in order 00067 * to test the macros. 00068 */ 00069 static EVENTSOURCE_DECL(es1); 00070 static EVENTSOURCE_DECL(es2); 00071 00072 /** 00073 * @page test_events_001 Events registration and dispatch 00074 * 00075 * <h2>Description</h2> 00076 * Two event listeners are registered on an event source and then unregistered 00077 * in the same order.<br> 00078 * The test expects that the even source has listeners after the registrations 00079 * and after the first unregistration, then, after the second unegistration, 00080 * the test expects no more listeners.<br> 00081 * In the second part the test dispatches three event flags and verifies that 00082 * the associated event handlers are invoked in LSb-first order. 00083 */ 00084 00085 static char *evt1_gettest(void) { 00086 00087 return "Events, registration and dispatch"; 00088 } 00089 00090 static void evt1_setup(void) { 00091 00092 chEvtClear(ALL_EVENTS); 00093 } 00094 00095 static void h1(eventid_t id) {(void)id;test_emit_token('A');} 00096 static void h2(eventid_t id) {(void)id;test_emit_token('B');} 00097 static void h3(eventid_t id) {(void)id;test_emit_token('C');} 00098 static const evhandler_t evhndl[] = {h1, h2, h3}; 00099 00100 static void evt1_execute(void) { 00101 EventListener el1, el2; 00102 00103 /* 00104 * Testing chEvtRegisterMask() and chEvtUnregister(). 00105 */ 00106 chEvtInit(&es1); 00107 chEvtRegisterMask(&es1, &el1, 1); 00108 chEvtRegisterMask(&es1, &el2, 2); 00109 test_assert(1, chEvtIsListening(&es1), "no listener"); 00110 chEvtUnregister(&es1, &el1); 00111 test_assert(2, chEvtIsListening(&es1), "no listener"); 00112 chEvtUnregister(&es1, &el2); 00113 test_assert(3, !chEvtIsListening(&es1), "stuck listener"); 00114 00115 /* 00116 * Testing chEvtDispatch(). 00117 */ 00118 chEvtDispatch(evhndl, 7); 00119 test_assert_sequence(4, "ABC"); 00120 } 00121 00122 const struct testcase testevt1 = { 00123 evt1_gettest, 00124 evt1_setup, 00125 NULL, 00126 evt1_execute 00127 }; 00128 00129 /** 00130 * @page test_events_002 Events wait and broadcast 00131 * 00132 * <h2>Description</h2> 00133 * In this test the following APIs are indipently tested by starting threads 00134 * that signal/broadcast events after fixed delays: 00135 * - @p chEvtWaitOne() 00136 * - @p chEvtWaitAny() 00137 * - @p chEvtWaitAll() 00138 * . 00139 * After each test phase the test verifies that the events have been served at 00140 * the expected time and that there are no stuck event flags. 00141 */ 00142 00143 static char *evt2_gettest(void) { 00144 00145 return "Events, wait and broadcast"; 00146 } 00147 00148 static void evt2_setup(void) { 00149 00150 chEvtClear(ALL_EVENTS); 00151 } 00152 00153 static msg_t thread1(void *p) { 00154 00155 chThdSleepMilliseconds(50); 00156 chEvtSignal((Thread *)p, 1); 00157 return 0; 00158 } 00159 00160 static msg_t thread2(void *p) { 00161 00162 (void)p; 00163 chEvtBroadcast(&es1); 00164 chThdSleepMilliseconds(50); 00165 chEvtBroadcast(&es2); 00166 return 0; 00167 } 00168 00169 static void evt2_execute(void) { 00170 eventmask_t m; 00171 EventListener el1, el2; 00172 systime_t target_time; 00173 00174 /* 00175 * Test on chEvtWaitOne() without wait. 00176 */ 00177 chEvtPend(5); 00178 m = chEvtWaitOne(ALL_EVENTS); 00179 test_assert(1, m == 1, "single event error"); 00180 m = chEvtWaitOne(ALL_EVENTS); 00181 test_assert(2, m == 4, "single event error"); 00182 m = chEvtClear(ALL_EVENTS); 00183 test_assert(3, m == 0, "stuck event"); 00184 00185 /* 00186 * Test on chEvtWaitOne() with wait. 00187 */ 00188 test_wait_tick(); 00189 target_time = chTimeNow() + MS2ST(50); 00190 threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1, 00191 thread1, chThdSelf()); 00192 m = chEvtWaitOne(ALL_EVENTS); 00193 test_assert_time_window(4, target_time, target_time + ALLOWED_DELAY); 00194 test_assert(5, m == 1, "single event error"); 00195 m = chEvtClear(ALL_EVENTS); 00196 test_assert(6, m == 0, "stuck event"); 00197 test_wait_threads(); 00198 00199 /* 00200 * Test on chEvtWaitAny() without wait. 00201 */ 00202 chEvtPend(5); 00203 m = chEvtWaitAny(ALL_EVENTS); 00204 test_assert(7, m == 5, "unexpected pending bit"); 00205 m = chEvtClear(ALL_EVENTS); 00206 test_assert(8, m == 0, "stuck event"); 00207 00208 /* 00209 * Test on chEvtWaitAny() with wait. 00210 */ 00211 test_wait_tick(); 00212 target_time = chTimeNow() + MS2ST(50); 00213 threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1, 00214 thread1, chThdSelf()); 00215 m = chEvtWaitAny(ALL_EVENTS); 00216 test_assert_time_window(9, target_time, target_time + ALLOWED_DELAY); 00217 test_assert(10, m == 1, "single event error"); 00218 m = chEvtClear(ALL_EVENTS); 00219 test_assert(11, m == 0, "stuck event"); 00220 test_wait_threads(); 00221 00222 /* 00223 * Test on chEvtWaitAll(). 00224 */ 00225 chEvtInit(&es1); 00226 chEvtInit(&es2); 00227 chEvtRegisterMask(&es1, &el1, 1); 00228 chEvtRegisterMask(&es2, &el2, 4); 00229 test_wait_tick(); 00230 target_time = chTimeNow() + MS2ST(50); 00231 threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1, 00232 thread2, "A"); 00233 m = chEvtWaitAll(5); 00234 test_assert_time_window(12, target_time, target_time + ALLOWED_DELAY); 00235 m = chEvtClear(ALL_EVENTS); 00236 test_assert(13, m == 0, "stuck event"); 00237 test_wait_threads(); 00238 chEvtUnregister(&es1, &el1); 00239 chEvtUnregister(&es2, &el2); 00240 test_assert(14, !chEvtIsListening(&es1), "stuck listener"); 00241 test_assert(15, !chEvtIsListening(&es2), "stuck listener"); 00242 } 00243 00244 const struct testcase testevt2 = { 00245 evt2_gettest, 00246 evt2_setup, 00247 NULL, 00248 evt2_execute 00249 }; 00250 00251 #if CH_USE_EVENTS_TIMEOUT 00252 /** 00253 * @page test_events_003 Events timeout 00254 * 00255 * <h2>Description</h2> 00256 * In this test the following APIs are let to timeout twice: immediatly and 00257 * after 10ms: 00258 * In this test the following APIs are indipently tested by starting threads 00259 * that broadcast events after fixed delays: 00260 * - @p chEvtWaitOneTimeout() 00261 * - @p chEvtWaitAnyTimeout() 00262 * - @p chEvtWaitAllTimeout() 00263 * . 00264 * After each test phase the test verifies that there are no stuck event flags. 00265 */ 00266 00267 static char *evt3_gettest(void) { 00268 00269 return "Events, timeouts"; 00270 } 00271 00272 static void evt3_setup(void) { 00273 00274 chEvtClear(ALL_EVENTS); 00275 } 00276 00277 static void evt3_execute(void) { 00278 eventmask_t m; 00279 00280 /* 00281 * Tests various timeout situations. 00282 */ 00283 m = chEvtWaitOneTimeout(ALL_EVENTS, TIME_IMMEDIATE); 00284 test_assert(1, m == 0, "spurious event"); 00285 m = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_IMMEDIATE); 00286 test_assert(2, m == 0, "spurious event"); 00287 m = chEvtWaitAllTimeout(ALL_EVENTS, TIME_IMMEDIATE); 00288 test_assert(3, m == 0, "spurious event"); 00289 m = chEvtWaitOneTimeout(ALL_EVENTS, 10); 00290 test_assert(4, m == 0, "spurious event"); 00291 m = chEvtWaitAnyTimeout(ALL_EVENTS, 10); 00292 test_assert(5, m == 0, "spurious event"); 00293 m = chEvtWaitAllTimeout(ALL_EVENTS, 10); 00294 test_assert(6, m == 0, "spurious event"); 00295 } 00296 00297 const struct testcase testevt3 = { 00298 evt3_gettest, 00299 evt3_setup, 00300 NULL, 00301 evt3_execute 00302 }; 00303 #endif /* CH_USE_EVENTS_TIMEOUT */ 00304 00305 /** 00306 * @brief Test sequence for events. 00307 */ 00308 const struct testcase * const patternevt[] = { 00309 #if CH_USE_EVENTS 00310 &testevt1, 00311 &testevt2, 00312 #if CH_USE_EVENTS_TIMEOUT 00313 &testevt3, 00314 #endif 00315 #endif 00316 NULL 00317 }; 00318 00319 #endif /* CH_USE_EVENTS */