aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2008-06-26 10:54:55 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2008-06-26 10:54:55 +0000
commit300ecfe103d1d305e78a15196d2fa1aecfddc729 (patch)
treed4b2f54280a9fc8f6e7487f65687ad90e8ebb0e5
parenta108008263c8c8fe80921e549346b78462b76036 (diff)
downloadChibiOS-300ecfe103d1d305e78a15196d2fa1aecfddc729.tar.gz
ChibiOS-300ecfe103d1d305e78a15196d2fa1aecfddc729.tar.bz2
ChibiOS-300ecfe103d1d305e78a15196d2fa1aecfddc729.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@323 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r--demos/ARM7-LPC214x-GCC/Makefile4
-rw-r--r--readme.txt6
-rw-r--r--src/chsleep.c14
-rw-r--r--src/include/sleep.h3
-rw-r--r--test/test.c605
-rw-r--r--test/test.h30
-rw-r--r--test/testmsg.c65
-rw-r--r--test/testmsg.h25
-rw-r--r--test/testmtx.c219
-rw-r--r--test/testmtx.h25
-rw-r--r--test/testrdy.c86
-rw-r--r--test/testrdy.h25
-rw-r--r--test/testsem.c102
-rw-r--r--test/testsem.h25
14 files changed, 756 insertions, 478 deletions
diff --git a/demos/ARM7-LPC214x-GCC/Makefile b/demos/ARM7-LPC214x-GCC/Makefile
index 5d0450021..e0061f78b 100644
--- a/demos/ARM7-LPC214x-GCC/Makefile
+++ b/demos/ARM7-LPC214x-GCC/Makefile
@@ -70,7 +70,9 @@ ASRC = ../../ports/ARM7-LPC214x/chcore.c \
../../src/chschd.c ../../src/chthreads.c ../../src/chsem.c ../../src/chmtx.c \
../../src/chevents.c ../../src/chmsg.c ../../src/chsleep.c ../../src/chqueues.c \
../../src/chserial.c \
- ../../src/lib/evtimer.c ../../test/test.c \
+ ../../src/lib/evtimer.c \
+ ../../test/test.c ../../test/testrdy.c ../../test/testsem.c \
+ ../../test/testmtx.c ../../test/testmsg.c \
board.c buzzer.c mmcsd.c main.c
# List THUMB-mode C sources here
diff --git a/readme.txt b/readme.txt
index 262e24bfc..e54f5944f 100644
--- a/readme.txt
+++ b/readme.txt
@@ -75,6 +75,12 @@ Win32-MinGW - ChibiOS/RT simulator and demo into a WIN32 process,
*****************************************************************************
*** 0.6.6 ***
+- NEW: Improved test suite, now the suite is divided in modules and the code
+ is much easier to understand. The new framework simplifies the inclusion of
+ new test cases and makes possible to verify the exact sequence and the
+ timing of test events.
+- NEW: New API chSysInTimeWindow() that checks if the current system time is
+ within the specified time window.
- FIX: Fixed a problem in the STM32 port USART1 driver.
- Added the definitions for packed structures to the chtypes.h files.
- Fixed a problem in the MMC/SD driver in the LPC2148 demo.
diff --git a/src/chsleep.c b/src/chsleep.c
index 859333b79..7f9f161f1 100644
--- a/src/chsleep.c
+++ b/src/chsleep.c
@@ -39,4 +39,18 @@ void chThdSleep(systime_t time) {
}
#endif /* CH_USE_SLEEP */
+#ifdef CH_USE_SYSTEMTIME
+/**
+ * Checks if the current system time is within the specified time window.
+ * @param start the start of the time window (inclusive)
+ * @param end the end of the time window (non inclusive)
+ */
+bool_t chSysInTimeWindow(systime_t start, systime_t end) {
+
+ systime_t time = chSysGetTime();
+ return end >= start ? (time >= start) && (time < end) :
+ (time >= start) || (time < end);
+}
+#endif /* CH_USE_SYSTEMTIME */
+
/** @} */
diff --git a/src/include/sleep.h b/src/include/sleep.h
index 51c4ac5d0..c718bb4ba 100644
--- a/src/include/sleep.h
+++ b/src/include/sleep.h
@@ -31,6 +31,9 @@ extern "C" {
#ifdef CH_USE_SLEEP
void chThdSleep(systime_t time);
#endif /* CH_USE_SLEEP */
+#ifdef CH_USE_SYSTEMTIME
+bool_t chSysInTimeWindow(systime_t start, systime_t end);
+#endif /* CH_USE_SYSTEMTIME */
#ifdef __cplusplus
}
#endif
diff --git a/test/test.c b/test/test.c
index 22337132e..d6f9f0717 100644
--- a/test/test.c
+++ b/test/test.c
@@ -19,39 +19,46 @@
#include <ch.h>
-#if defined(WIN32)
-void ChkIntSources(void);
-#endif
+#include "test.h"
+#include "testrdy.h"
+#include "testsem.h"
+#include "testmtx.h"
+#include "testmsg.h"
-#if defined(WIN32)
-WorkingArea(wsT1, 512);
-WorkingArea(wsT2, 512);
-WorkingArea(wsT3, 512);
-WorkingArea(wsT4, 512);
-WorkingArea(wsT5, 512);
-#else
-WorkingArea(wsT1, 128);
-WorkingArea(wsT2, 128);
-WorkingArea(wsT3, 128);
-WorkingArea(wsT4, 128);
-WorkingArea(wsT5, 128);
-#endif
-static Thread *t1, *t2, *t3, *t4, *t5;
+/*
+ * Array of all the test cases.
+ */
+static const struct testcase *tests[] = {
+ &testrdy1,
+ &testrdy2,
+ &testsem1,
+ &testsem2,
+ &testmtx1,
+ &testmtx2,
+ &testmtx3,
+ &testmsg1,
+ NULL
+};
+
+static bool_t local_fail, global_fail;
+static char *failmsg;
+static char tokens_buffer[MAX_TOKENS];
+static char *tokp;
+static WorkingArea(waT0, THREADS_STACK_SIZE);
+static WorkingArea(waT1, THREADS_STACK_SIZE);
+static WorkingArea(waT2, THREADS_STACK_SIZE);
+static WorkingArea(waT3, THREADS_STACK_SIZE);
+static WorkingArea(waT4, THREADS_STACK_SIZE);
+
+void *wa[MAX_THREADS] = {waT0, waT1, waT2, waT3, waT4};
+Thread *threads[MAX_THREADS];
+/*
+ * Console output.
+ */
static FullDuplexDriver *comp;
-static Semaphore sem1;
-static Mutex m1, m2;
-static void wait(void) {
-
- chThdWait(t1);
- chThdWait(t2);
- chThdWait(t3);
- chThdWait(t4);
- chThdWait(t5);
-}
-
-static void printn(uint32_t n) {
+void test_printn(uint32_t n) {
char buf[16], *p;
if (!n)
@@ -65,506 +72,154 @@ static void printn(uint32_t n) {
}
}
-static void print(char *msgp) {
+void test_print(char *msgp) {
while (*msgp)
chFDDPut(comp, *msgp++);
}
-static void println(char *msgp) {
+void test_println(char *msgp) {
- print(msgp);
+ test_print(msgp);
chFDDPut(comp, '\r');
chFDDPut(comp, '\n');
}
-__attribute__((noinline))
-void CPU(systime_t ms) {
-
- systime_t time = chSysGetTime() + ms;
- while (chSysGetTime() != time) {
-#if defined(WIN32)
- ChkIntSources();
-#endif
- }
-}
-
-__attribute__((noinline))
-systime_t wait_tick(void) {
-
- systime_t time = chSysGetTime() + 1;
- while (chSysGetTime() < time) {
-#if defined(WIN32)
- ChkIntSources();
-#endif
- }
- return time;
-}
-
-msg_t Thread1(void *p) {
-
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
-}
-
-msg_t Thread2(void *p) {
-
- chSemWait(&sem1);
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
-}
-
-msg_t Thread3(void *p) {
-
- chMtxLock(&m1);
- chFDDPut(comp, *(uint8_t *)p);
- chMtxUnlock();
- return 0;
-}
-
-msg_t Thread4(void *p) {
- msg_t msg;
- int i;
-
- for (i = 0; i < 5; i++) {
- msg = chMsgSend(p, 'A' + i);
- chFDDPut(comp, msg);
- }
- chMsgSend(p, 0);
- return 0;
-}
-
-msg_t Thread6(void *p) {
-
- while (!chThdShouldTerminate())
- chMsgRelease(chMsgWait());
- return 0;
-}
-
-msg_t Thread7(void *p) {
-
- return (msg_t)NULL;
-}
-
-void testrdy1(void) {
-
- println("*** Ready List, priority enqueuing test #1, you should read ABCDE:");
- t5 = chThdCreate(chThdGetPriority()-5, 0, wsT5, sizeof(wsT5), Thread1, "E");
- t4 = chThdCreate(chThdGetPriority()-4, 0, wsT4, sizeof(wsT4), Thread1, "D");
- t3 = chThdCreate(chThdGetPriority()-3, 0, wsT3, sizeof(wsT3), Thread1, "C");
- t2 = chThdCreate(chThdGetPriority()-2, 0, wsT2, sizeof(wsT2), Thread1, "B");
- t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread1, "A");
- wait();
- println("");
-}
-
-void testrdy2(void) {
-
- println("*** Ready List, priority enqueuing test #2, you should read ABCDE:");
- t4 = chThdCreate(chThdGetPriority()-4, 0, wsT4, sizeof(wsT4), Thread1, "D");
- t5 = chThdCreate(chThdGetPriority()-5, 0, wsT5, sizeof(wsT5), Thread1, "E");
- t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread1, "A");
- t2 = chThdCreate(chThdGetPriority()-2, 0, wsT2, sizeof(wsT2), Thread1, "B");
- t3 = chThdCreate(chThdGetPriority()-3, 0, wsT3, sizeof(wsT3), Thread1, "C");
- wait();
- println("");
-}
-
-void testsem1(void) {
-
- println("*** Semaphores, FIFO enqueuing test, you should read ABCDE:");
- chSemInit(&sem1, 0);
- t1 = chThdCreate(chThdGetPriority()+5, 0, wsT1, sizeof(wsT1), Thread2, "A");
- t2 = chThdCreate(chThdGetPriority()+1, 0, wsT2, sizeof(wsT2), Thread2, "B");
- t3 = chThdCreate(chThdGetPriority()+3, 0, wsT3, sizeof(wsT3), Thread2, "C");
- t4 = chThdCreate(chThdGetPriority()+4, 0, wsT4, sizeof(wsT4), Thread2, "D");
- t5 = chThdCreate(chThdGetPriority()+2, 0, wsT5, sizeof(wsT5), Thread2, "E");
- chSemSignal(&sem1);
- chSemSignal(&sem1);
- chSemSignal(&sem1);
- chSemSignal(&sem1);
- chSemSignal(&sem1);
- wait();
- println("");
-}
-
-void testsem2(void) {
- unsigned int i;
-
- println("*** Semaphores, timeout test, you should read ABCDE (slowly):");
- chSemInit(&sem1, 0);
- for (i = 0; i < 5; i++) {
- chFDDPut(comp, 'A' + i);
- chSemWaitTimeout(&sem1, 500);
- }
- println("");
-}
-
-void testmtx1(void) {
-
- chMtxInit(&m1);
- println("*** Mutexes, priority enqueuing test, you should read ABCDE:");
- chMtxLock(&m1);
- t5 = chThdCreate(chThdGetPriority()+1, 0, wsT5, sizeof(wsT5), Thread3, "E");
- t4 = chThdCreate(chThdGetPriority()+3, 0, wsT4, sizeof(wsT4), Thread3, "D");
- t3 = chThdCreate(chThdGetPriority()+3, 0, wsT3, sizeof(wsT3), Thread3, "C");
- t2 = chThdCreate(chThdGetPriority()+4, 0, wsT2, sizeof(wsT2), Thread3, "B");
- t1 = chThdCreate(chThdGetPriority()+5, 0, wsT1, sizeof(wsT1), Thread3, "A");
- chMtxUnlock();
- wait();
- println("");
-}
-
-msg_t Thread8(void *p) {
-
- chThdSleep(5);
- chMtxLock(&m1);
- chMtxUnlock();
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
-}
-
-msg_t Thread9(void *p) {
-
- chMtxLock(&m1);
- chThdSleep(20);
- chMtxUnlock();
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
-}
-
-msg_t Thread10(void *p) {
+/*
+ * Tokens.
+ */
+static void clear_tokens(void) {
- chThdSleep(10);
- CPU(50);
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
+ tokp = tokens_buffer;
}
-msg_t Thread11(void *p) {
+static void print_tokens(void) {
+ char *cp = tokens_buffer;
- chThdSleep(5);
- chSemWait(&sem1);
- chSemSignal(&sem1);
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
+ while (cp < tokp)
+ chFDDPut(comp, *cp++);
}
-msg_t Thread12(void *p) {
+void test_emit_token(char token) {
- chSemWait(&sem1);
- chThdSleep(20);
- chSemSignal(&sem1);
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
+ chSysLock();
+ *tokp++ = token;
+ chSysUnlock();
}
/*
- * Time
- * 0 ++++++++++++++++++AL+....2++++++++++++++AU0------------------------------
- * 1 .....................++--------------------------------------------------
- * 2 .......................++AL.............+++++++++AU++++++++++++++++++++++
+ * Assertions.
*/
-void testmtx2(void) {
-
- chMtxInit(&m1);
- println("*** Mutexes, mutex with inheritance (simple case), you should read ABC:");
- t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread8, "A");
- t2 = chThdCreate(chThdGetPriority()-3, 0, wsT2, sizeof(wsT2), Thread9, "C");
- t3 = chThdCreate(chThdGetPriority()-2, 0, wsT3, sizeof(wsT3), Thread10, "B");
- chThdWait(t1);
- chThdWait(t2);
- chThdWait(t3);
- println("");
-}
+void test_fail(char * msg) {
-void testmtx3(void) {
-
- chSemInit(&sem1, 1);
- println("*** Mutexes, mutex without inheritance, inversion happens, you should read BAC:");
- t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread11, "A");
- t2 = chThdCreate(chThdGetPriority()-3, 0, wsT2, sizeof(wsT2), Thread12, "C");
- t3 = chThdCreate(chThdGetPriority()-2, 0, wsT3, sizeof(wsT3), Thread10, "B");
- chThdWait(t1);
- chThdWait(t2);
- chThdWait(t3);
- println("");
+ local_fail = TRUE;
+ global_fail = TRUE;
+ failmsg = msg;
}
-msg_t Thread13(void *p) {
-
- chMtxLock(&m1);
- CPU(50);
- chMtxUnlock();
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
-}
+void test_assert(bool_t condition, char * msg) {
-msg_t Thread14(void *p) {
-
- chThdSleep(10);
- chMtxLock(&m2);
- CPU(20);
- chMtxLock(&m1);
- CPU(50);
- chMtxUnlock();
- CPU(20);
- chMtxUnlock();
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
+ if (!condition)
+ test_fail(msg);
}
-msg_t Thread15(void *p) {
-
- chThdSleep(20);
- chMtxLock(&m2);
- CPU(50);
- chMtxUnlock();
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
-}
-
-msg_t Thread16(void *p) {
-
- chThdSleep(40);
- CPU(200);
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
+void test_assert_sequence(char *expected) {
+ char *cp = tokens_buffer;
+ while (cp < tokp) {
+ if (*cp++ != *expected++)
+ test_fail(NULL);
+ }
+ if (*expected)
+ test_fail(NULL);
}
-msg_t Thread17(void *p) {
+void test_assert_time_window(systime_t start, systime_t end) {
- chThdSleep(50);
- chMtxLock(&m2);
- CPU(50);
- chMtxUnlock();
- chFDDPut(comp, *(uint8_t *)p);
- return 0;
+ test_assert(chSysInTimeWindow(start, end), "time window error");
}
/*
- * Time 0 10 20 30 40 50
- * 0 +++BL++------------------2++++------4+++++BU0--------------------------
- * 1 .......++AL++--2+++++++++BL.........4.....++++++++BU4++++AU1-----------
- * 2 .............++AL............................................------++AU
- * 3 ..............................++++-------------------------------++....
- * 4 ..................................++AL...................++++AU++......
+ * Threads utils.
*/
-void testmtx4(void) {
-
- chMtxInit(&m1); /* B */
- chMtxInit(&m2); /* A */
- println("*** Mutexes, mutex with inheritance (complex case), you should read ABCDE:");
- t1 = chThdCreate(chThdGetPriority()-5, 0, wsT1, sizeof(wsT1), Thread13, "E");
- t2 = chThdCreate(chThdGetPriority()-4, 0, wsT2, sizeof(wsT2), Thread14, "D");
- t3 = chThdCreate(chThdGetPriority()-3, 0, wsT3, sizeof(wsT3), Thread15, "C");
- t4 = chThdCreate(chThdGetPriority()-2, 0, wsT4, sizeof(wsT4), Thread16, "B");
- t5 = chThdCreate(chThdGetPriority()-1, 0, wsT5, sizeof(wsT5), Thread17, "A");
- wait();
- println("");
-}
+void test_wait_threads(void) {
+ int i;
-void testmsg1(void) {
- msg_t msg;
-
- println("*** Messages, dispatch test, you should read AABBCCDDEE:");
- t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread4, chThdSelf());
- do {
- chMsgRelease(msg = chMsgWait());
- if (msg)
- chFDDPut(comp, msg);
- } while (msg);
- chThdWait(t1);
- println("");
+ for (i = 0; i < MAX_THREADS; i++)
+ if (threads[i])
+ chThdWait(threads[i]);
}
-__attribute__((noinline))
-unsigned int msg_loop_test(Thread *tp) {
- uint32_t i;
+void test_cpu_pulse(systime_t ms) {
- systime_t time = wait_tick() + 1000;
- i = 0;
- while (chSysGetTime() < time) {
- (void)chMsgSend(tp, 0);
- i++;
+ systime_t start = chSysGetTime();
+ while (chSysInTimeWindow(start, start + ms)) {
#if defined(WIN32)
ChkIntSources();
#endif
}
- return i;
}
-__attribute__((noinline))
-void precache(void) {
- uint32_t i;
-
- println("\r\nPreparing for benchmarks\r\n");
- t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread6, 0);
- i = msg_loop_test(t1);
- chThdTerminate(t1);
- chThdWait(t1);
-}
+/*
+ * Test suite execution.
+ */
+static void execute_test(const struct testcase *tcp) {
+ int i;
-__attribute__((noinline))
-void bench1(void) {
- uint32_t i;
-
- println("*** Kernel Benchmark, context switch test #1 (optimal):");
- t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread6, 0);
- i = msg_loop_test(t1);
- chThdTerminate(t1);
- chThdWait(t1);
- print("Messages throughput = ");
- printn(i);
- print(" msgs/S, ");
- printn(i << 1);
- println(" ctxswc/S");
-}
+ /* Initialization */
+ clear_tokens();
+ local_fail = FALSE;
+ for (i = 0; i < MAX_THREADS; i++)
+ threads[i] = NULL;
-__attribute__((noinline))
-void bench2(void) {
- uint32_t i;
-
- println("*** Kernel Benchmark, context switch test #2 (no threads in ready list):");
- t1 = chThdCreate(chThdGetPriority()+1, 0, wsT1, sizeof(wsT1), Thread6, 0);
- i = msg_loop_test(t1);
- chThdTerminate(t1);
-chMsgSend(t1, 0);
- chThdWait(t1);
- print("Messages throughput = ");
- printn(i);
- print(" msgs/S, ");
- printn(i << 1);
- println(" ctxswc/S");
+ tcp->setup();
+ tcp->execute();
+ tcp->teardown();
}
-__attribute__((noinline))
-void bench3(void) {
- uint32_t i;
-
- println("*** Kernel Benchmark, context switch test #3 (04 threads in ready list):");
- t1 = chThdCreate(chThdGetPriority()+1, 0, wsT1, sizeof(wsT1), Thread6, "A");
- t2 = chThdCreate(chThdGetPriority()-2, 0, wsT2, sizeof(wsT2), Thread7, "B");
- t3 = chThdCreate(chThdGetPriority()-3, 0, wsT3, sizeof(wsT3), Thread7, "C");
- t4 = chThdCreate(chThdGetPriority()-4, 0, wsT4, sizeof(wsT4), Thread7, "D");
- t5 = chThdCreate(chThdGetPriority()-5, 0, wsT5, sizeof(wsT5), Thread7, "E");
- i = msg_loop_test(t1);
- chThdTerminate(t1);
-chMsgSend(t1, 0);
- wait();
- print("Messages throughput = ");
- printn(i);
- print(" msgs/S, ");
- printn(i << 1);
- println(" ctxswc/S");
-}
+msg_t TestThread(void *p) {
+ int i;
-__attribute__((noinline))
-void bench4(void) {
- uint32_t i;
- systime_t time;
+ comp = p;
+ test_println("");
+ test_println("*****************************");
+ test_println("*** ChibiOS/RT test suite ***");
+ test_println("*****************************");
+ test_println("");
- println("*** Kernel Benchmark, threads creation/termination:");
- time = wait_tick() + 1000;
+ global_fail = FALSE;
i = 0;
- while (chSysGetTime() < time) {
- t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread7, NULL);
- chThdWait(t1);
- i++;
-#if defined(WIN32)
- ChkIntSources();
+ while (tests[i]) {
+#if DELAY_BETWEEN_TESTS > 0
+ chThdSleep(DELAY_BETWEEN_TESTS);
#endif
- }
- print("Threads throughput = ");
- printn(i);
- println(" threads/S");
-}
-
-__attribute__((noinline))
-void bench5(void) {
- static uint8_t ib[16];
- static Queue iq;
- uint32_t i;
- systime_t time;
-
- println("*** Kernel Benchmark, I/O Queues throughput:");
- chIQInit(&iq, ib, sizeof(ib), NULL);
- time = wait_tick() + 1000;
- i = 0;
- while (chSysGetTime() < time) {
- chIQPutI(&iq, 0);
- chIQPutI(&iq, 1);
- chIQPutI(&iq, 2);
- chIQPutI(&iq, 3);
- (void)chIQGet(&iq);
- (void)chIQGet(&iq);
- (void)chIQGet(&iq);
- (void)chIQGet(&iq);
+ test_println("------------------------------------------------------------");
+ test_print("--- Test Case ");
+ test_printn(i + 1);
+ test_print(" (");
+ test_print(tests[i]->gettest());
+ test_println(")");
+ execute_test(tests[i]);
+ if (local_fail) {
+ test_print("--- Result: FAIL (");
+ if (failmsg)
+ test_print(failmsg);
+ else {
+ test_print("sequence error: ");
+ print_tokens();
+ }
+ test_println(")");
+ }
+ else
+ test_println("--- Result: SUCCESS");
i++;
-#if defined(WIN32)
- ChkIntSources();
-#endif
}
- print("Queues throughput = ");
- printn(i * 4);
- println(" bytes/S");
-}
+ test_println("------------------------------------------------------------");
+ test_println("");
+ test_print("Final result: ");
+ if (global_fail)
+ test_println("FAIL");
+ else
+ test_println("SUCCESS");
-/**
- * Tester thread, this thread must be created with priority \p NORMALPRIO.
- */
-msg_t TestThread(void *p) {
-
- comp = p;
- println("*****************************");
- println("*** ChibiOS/RT test suite ***");
- println("*****************************");
- println("");
-
- /*
- * Ready list ordering tests.
- */
- testrdy1();
- testrdy2();
-
- /*
- * Semaphores tests.
- */
- testsem1();
- testsem2();
-
- /*
- * Mutexes tests.
- */
- testmtx1();
- testmtx2();
- testmtx3();
- testmtx4();
-
- /*
- * Messages tests.
- */
- testmsg1();
-
- /*
- * Kernel benchmarks.
- * NOTE: The calls to chThdSleep() are required in order to give I/O queues
- * enough time to transmit everything, else the tests would get some
- * extra interrupts to serve from previous tests.
- */
- precache();
- chThdSleep(100);
- bench1();
- chThdSleep(100);
- bench2();
- chThdSleep(100);
- bench3();
- chThdSleep(100);
- bench4();
- chThdSleep(100);
- bench5();
- chThdSleep(100);
-
- println("\r\nTest complete");
return 0;
}
diff --git a/test/test.h b/test/test.h
index b05f9aa61..9e2759ede 100644
--- a/test/test.h
+++ b/test/test.h
@@ -17,17 +17,43 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <ch.h>
-
#ifndef _TEST_H_
#define _TEST_H_
+#define MAX_THREADS 5
+#define MAX_TOKENS 16
+#define DELAY_BETWEEN_TESTS 200
+
+#if defined(CH_ARCHITECTURE_AVR) || defined(CH_ARCHITECTURE_MSP430)
+#define THREADS_STACK_SIZE 64
+#else
+#define THREADS_STACK_SIZE 128
+#endif
+#define STKSIZE UserStackSize(THREADS_STACK_SIZE)
+
+struct testcase {
+ char *(*gettest)(void);
+ void (*setup)(void);
+ void (*teardown)(void);
+ void (*execute)(void);
+};
+
#ifdef __cplusplus
extern "C" {
#endif
msg_t TestThread(void *p);
+ void test_emit_token(char token);
+ void test_fail(char * msg);
+ void test_assert(bool_t condition, char * msg);
+ void test_assert_sequence(char *expected);
+ void test_assert_time_window(systime_t start, systime_t end);
+ void test_wait_threads(void);
+ void test_cpu_pulse(systime_t ms);
#ifdef __cplusplus
}
#endif
+extern Thread *threads[MAX_THREADS];
+extern void *wa[MAX_THREADS];
+
#endif /* _TEST_H_ */
diff --git a/test/testmsg.c b/test/testmsg.c
new file mode 100644
index 000000000..31959c619
--- /dev/null
+++ b/test/testmsg.c
@@ -0,0 +1,65 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <ch.h>
+
+#include "test.h"
+
+static char *msg1_gettest(void) {
+
+ return "Messages, dispatch test";
+}
+
+static void msg1_setup(void) {
+}
+
+static void msg1_teardown(void) {
+}
+
+static msg_t thread(void *p) {
+ msg_t msg;
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ msg = chMsgSend(p, 'A' + i);
+ test_emit_token(msg);
+ }
+ chMsgSend(p, 0);
+ return 0;
+}
+
+static void msg1_execute(void) {
+ msg_t msg;
+
+ threads[0] = chThdCreate(chThdGetPriority()-1, 0, wa[0], STKSIZE, thread, chThdSelf());
+ do {
+ chMsgRelease(msg = chMsgWait());
+ if (msg)
+ test_emit_token(msg);
+ } while (msg);
+ test_wait_threads();
+ test_assert_sequence("AABBCCDDEE");
+}
+
+const struct testcase testmsg1 = {
+ msg1_gettest,
+ msg1_setup,
+ msg1_teardown,
+ msg1_execute
+};
diff --git a/test/testmsg.h b/test/testmsg.h
new file mode 100644
index 000000000..8c9631bb7
--- /dev/null
+++ b/test/testmsg.h
@@ -0,0 +1,25 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _TESTMSG_H_
+#define _TESTMSG_H_
+
+extern const struct testcase testmsg1;
+
+#endif /* _TESTMSG_H_ */
diff --git a/test/testmtx.c b/test/testmtx.c
new file mode 100644
index 000000000..2f1aaa33f
--- /dev/null
+++ b/test/testmtx.c
@@ -0,0 +1,219 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <ch.h>
+
+#include "test.h"
+
+#define ALLOWED_DELAY 5
+
+static Mutex m1, m2;
+
+static char *mtx1_gettest(void) {
+
+ return "Mutexes, priority enqueuing test";
+}
+
+static void mtx1_setup(void) {
+
+ chMtxInit(&m1);
+}
+
+static void mtx1_teardown(void) {
+}
+
+static msg_t thread1(void *p) {
+
+ chMtxLock(&m1);
+ test_emit_token(*(char *)p);
+ chMtxUnlock();
+ return 0;
+}
+
+static void mtx1_execute(void) {
+
+ chMtxLock(&m1);
+ threads[0] = chThdCreate(chThdGetPriority()+1, 0, wa[0], STKSIZE, thread1, "E");
+ threads[1] = chThdCreate(chThdGetPriority()+2, 0, wa[1], STKSIZE, thread1, "D");
+ threads[2] = chThdCreate(chThdGetPriority()+3, 0, wa[2], STKSIZE, thread1, "C");
+ threads[3] = chThdCreate(chThdGetPriority()+4, 0, wa[3], STKSIZE, thread1, "B");
+ threads[4] = chThdCreate(chThdGetPriority()+5, 0, wa[4], STKSIZE, thread1, "A");
+ chMtxUnlock();
+ test_wait_threads();
+ test_assert_sequence("ABCDE");
+}
+
+const struct testcase testmtx1 = {
+ mtx1_gettest,
+ mtx1_setup,
+ mtx1_teardown,
+ mtx1_execute
+};
+
+static char *mtx2_gettest(void) {
+
+ return "Mutexes, priority inheritance, simple case";
+}
+
+static void mtx2_setup(void) {
+
+ chMtxInit(&m1);
+}
+
+static void mtx2_teardown(void) {
+}
+
+static msg_t thread2(void *p) {
+
+ chThdSleep(5);
+ chMtxLock(&m1);
+ chMtxUnlock();
+ test_emit_token(*(char *)p);
+ return 0;
+}
+
+static msg_t thread3(void *p) {
+
+ chMtxLock(&m1);
+ chThdSleep(20);
+ chMtxUnlock();
+ test_emit_token(*(char *)p);
+ return 0;
+}
+
+static msg_t thread4(void *p) {
+
+ chThdSleep(10);
+ test_cpu_pulse(50);
+ test_emit_token(*(char *)p);
+ return 0;
+}
+
+/*
+ * Time
+ * 0 ++++++++++++++++++AL+....2++++++++++++++AU0------------------------------
+ * 1 .....................++--------------------------------------------------
+ * 2 .......................++AL.............+++++++++AU++++++++++++++++++++++
+ */
+static void mtx2_execute(void) {
+
+ threads[0] = chThdCreate(chThdGetPriority()-1, 0, wa[0], STKSIZE, thread2, "A");
+ threads[1] = chThdCreate(chThdGetPriority()-3, 0, wa[1], STKSIZE, thread3, "C");
+ threads[2] = chThdCreate(chThdGetPriority()-2, 0, wa[2], STKSIZE, thread4, "B");
+ test_wait_threads();
+ test_assert_sequence("ABC");
+}
+
+const struct testcase testmtx2 = {
+ mtx2_gettest,
+ mtx2_setup,
+ mtx2_teardown,
+ mtx2_execute
+};
+
+static char *mtx3_gettest(void) {
+
+ return "Mutexes, priority inheritance, complex case";
+}
+
+static void mtx3_setup(void) {
+
+ chMtxInit(&m1);
+ chMtxInit(&m2);
+}
+
+static void mtx3_teardown(void) {
+}
+
+static msg_t thread5(void *p) {
+
+ chMtxLock(&m1);
+ test_cpu_pulse(50);
+ chMtxUnlock();
+ test_emit_token(*(char *)p);
+ return 0;
+}
+
+static msg_t thread6(void *p) {
+
+ chThdSleep(10);
+ chMtxLock(&m2);
+ test_cpu_pulse(20);
+ chMtxLock(&m1);
+ test_cpu_pulse(50);
+ chMtxUnlock();
+ test_cpu_pulse(20);
+ chMtxUnlock();
+ test_emit_token(*(char *)p);
+ return 0;
+}
+
+static msg_t thread7(void *p) {
+
+ chThdSleep(20);
+ chMtxLock(&m2);
+ test_cpu_pulse(50);
+ chMtxUnlock();
+ test_emit_token(*(char *)p);
+ return 0;
+}
+
+static msg_t thread8(void *p) {
+
+ chThdSleep(40);
+ test_cpu_pulse(200);
+ test_emit_token(*(char *)p);
+ return 0;
+}
+
+static msg_t thread9(void *p) {
+
+ chThdSleep(50);
+ chMtxLock(&m2);
+ test_cpu_pulse(50);
+ chMtxUnlock();
+ test_emit_token(*(char *)p);
+ return 0;
+}
+
+/*
+ * Time 0 10 20 30 40 50
+ * 0 +++BL++------------------2++++------4+++++BU0--------------------------
+ * 1 .......++AL++--2+++++++++BL.........4.....++++++++BU4++++AU1-----------
+ * 2 .............++AL............................................------++AU
+ * 3 ..............................++++-------------------------------++....
+ * 4 ..................................++AL...................++++AU++......
+ */
+static void mtx3_execute(void) {
+
+ threads[0] = chThdCreate(chThdGetPriority()-5, 0, wa[0], STKSIZE, thread5, "E");
+ threads[1] = chThdCreate(chThdGetPriority()-4, 0, wa[1], STKSIZE, thread6, "D");
+ threads[2] = chThdCreate(chThdGetPriority()-3, 0, wa[2], STKSIZE, thread7, "C");
+ threads[3] = chThdCreate(chThdGetPriority()-2, 0, wa[3], STKSIZE, thread8, "B");
+ threads[4] = chThdCreate(chThdGetPriority()-1, 0, wa[4], STKSIZE, thread9, "A");
+ test_wait_threads();
+ test_assert_sequence("ABCDE");
+}
+
+const struct testcase testmtx3 = {
+ mtx3_gettest,
+ mtx3_setup,
+ mtx3_teardown,
+ mtx3_execute
+};
diff --git a/test/testmtx.h b/test/testmtx.h
new file mode 100644
index 000000000..068fbc7b8
--- /dev/null
+++ b/test/testmtx.h
@@ -0,0 +1,25 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _TESTMTX_H_
+#define _TESTMTX_H_
+
+extern const struct testcase testmtx1, testmtx2, testmtx3;
+
+#endif /* _TESTMTX_H_ */
diff --git a/test/testrdy.c b/test/testrdy.c
new file mode 100644
index 000000000..ec8a0d2dd
--- /dev/null
+++ b/test/testrdy.c
@@ -0,0 +1,86 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <ch.h>
+
+#include "test.h"
+
+static msg_t thread(void *p) {
+
+ test_emit_token(*(char *)p);
+ return 0;
+}
+
+static char *rdy1_gettest(void) {
+
+ return "Ready List, priority enqueuing test #1";
+}
+
+static void rdy1_setup(void) {
+}
+
+static void rdy1_teardown(void) {
+}
+
+static void rdy1_execute(void) {
+
+ threads[0] = chThdCreate(chThdGetPriority()-5, 0, wa[0], STKSIZE, thread, "E");
+ threads[1] = chThdCreate(chThdGetPriority()-4, 0, wa[1], STKSIZE, thread, "D");
+ threads[2] = chThdCreate(chThdGetPriority()-3, 0, wa[2], STKSIZE, thread, "C");
+ threads[3] = chThdCreate(chThdGetPriority()-2, 0, wa[3], STKSIZE, thread, "B");
+ threads[4] = chThdCreate(chThdGetPriority()-1, 0, wa[4], STKSIZE, thread, "A");
+ test_wait_threads();
+ test_assert_sequence("ABCDE");
+}
+
+const struct testcase testrdy1 = {
+ rdy1_gettest,
+ rdy1_setup,
+ rdy1_teardown,
+ rdy1_execute
+};
+
+static char *rdy2_gettest(void) {
+
+ return "Ready List, priority enqueuing test #2";
+}
+
+static void rdy2_setup(void) {
+}
+
+static void rdy2_teardown(void) {
+}
+
+static void rdy2_execute(void) {
+
+ threads[1] = chThdCreate(chThdGetPriority()-4, 0, wa[1], STKSIZE, thread, "D");
+ threads[0] = chThdCreate(chThdGetPriority()-5, 0, wa[0], STKSIZE, thread, "E");
+ threads[4] = chThdCreate(chThdGetPriority()-1, 0, wa[4], STKSIZE, thread, "A");
+ threads[3] = chThdCreate(chThdGetPriority()-2, 0, wa[3], STKSIZE, thread, "B");
+ threads[2] = chThdCreate(chThdGetPriority()-3, 0, wa[2], STKSIZE, thread, "C");
+ test_wait_threads();
+ test_assert_sequence("ABCDE");
+}
+
+const struct testcase testrdy2 = {
+ rdy2_gettest,
+ rdy2_setup,
+ rdy2_teardown,
+ rdy2_execute
+};
diff --git a/test/testrdy.h b/test/testrdy.h
new file mode 100644
index 000000000..68719351f
--- /dev/null
+++ b/test/testrdy.h
@@ -0,0 +1,25 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _TESTRDY_H_
+#define _TESTRDY_H_
+
+extern const struct testcase testrdy1, testrdy2;
+
+#endif /* _TESTRDY_H_ */
diff --git a/test/testsem.c b/test/testsem.c
new file mode 100644
index 000000000..ef6a664fd
--- /dev/null
+++ b/test/testsem.c
@@ -0,0 +1,102 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <ch.h>
+
+#include "test.h"
+
+#define ALLOWED_DELAY 5
+
+static Semaphore sem1;
+
+static char *sem1_gettest(void) {
+
+ return "Semaphores, FIFO enqueuing test";
+}
+
+static void sem1_setup(void) {
+
+ chSemInit(&sem1, 0);
+}
+
+static void sem1_teardown(void) {
+}
+
+static msg_t thread(void *p) {
+
+ chSemWait(&sem1);
+ test_emit_token(*(char *)p);
+ return 0;
+}
+
+static void sem1_execute(void) {
+
+ threads[0] = chThdCreate(chThdGetPriority()+5, 0, wa[0], STKSIZE, thread, "A");
+ threads[1] = chThdCreate(chThdGetPriority()+1, 0, wa[1], STKSIZE, thread, "B");
+ threads[2] = chThdCreate(chThdGetPriority()+3, 0, wa[2], STKSIZE, thread, "C");
+ threads[3] = chThdCreate(chThdGetPriority()+4, 0, wa[3], STKSIZE, thread, "D");
+ threads[4] = chThdCreate(chThdGetPriority()+2, 0, wa[4], STKSIZE, thread, "E");
+ chSemSignal(&sem1);
+ chSemSignal(&sem1);
+ chSemSignal(&sem1);
+ chSemSignal(&sem1);
+ chSemSignal(&sem1);
+ test_wait_threads();
+ test_assert_sequence("ABCDE");
+}
+
+const struct testcase testsem1 = {
+ sem1_gettest,
+ sem1_setup,
+ sem1_teardown,
+ sem1_execute
+};
+
+static char *sem2_gettest(void) {
+
+ return "Semaphores, timeout test";
+}
+
+static void sem2_setup(void) {
+
+ chSemInit(&sem1, 0);
+}
+
+static void sem2_teardown(void) {
+}
+
+static void sem2_execute(void) {
+ int i;
+ systime_t target_time;
+
+ target_time = chSysGetTime() + 5 * 500;
+ for (i = 0; i < 5; i++) {
+ test_emit_token('A' + i);
+ chSemWaitTimeout(&sem1, 500);
+ }
+ test_assert_sequence("ABCDE");
+ test_assert_time_window(target_time, target_time + ALLOWED_DELAY);
+}
+
+const struct testcase testsem2 = {
+ sem2_gettest,
+ sem2_setup,
+ sem2_teardown,
+ sem2_execute
+};
diff --git a/test/testsem.h b/test/testsem.h
new file mode 100644
index 000000000..8bb6b17bf
--- /dev/null
+++ b/test/testsem.h
@@ -0,0 +1,25 @@
+/*
+ ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
+
+ This file is part of ChibiOS/RT.
+
+ ChibiOS/RT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/RT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _TESTSEM_H_
+#define _TESTSEM_H_
+
+extern const struct testcase testsem1, testsem2;
+
+#endif /* _TESTSEM_H_ */