git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@323 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2008-06-26 10:54:55 +00:00
parent a108008263
commit 300ecfe103
14 changed files with 779 additions and 501 deletions

View File

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

View File

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

View File

@ -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 */
/** @} */

View File

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

View File

@ -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) {
/*
* Tokens.
*/
static void clear_tokens(void) {
systime_t time = chSysGetTime() + ms;
while (chSysGetTime() != time) {
#if defined(WIN32)
ChkIntSources();
#endif
tokp = tokens_buffer;
}
static void print_tokens(void) {
char *cp = tokens_buffer;
while (cp < tokp)
chFDDPut(comp, *cp++);
}
void test_emit_token(char token) {
chSysLock();
*tokp++ = token;
chSysUnlock();
}
/*
* Assertions.
*/
void test_fail(char * msg) {
local_fail = TRUE;
global_fail = TRUE;
failmsg = msg;
}
void test_assert(bool_t condition, char * msg) {
if (!condition)
test_fail(msg);
}
void test_assert_sequence(char *expected) {
char *cp = tokens_buffer;
while (cp < tokp) {
if (*cp++ != *expected++)
test_fail(NULL);
}
if (*expected)
test_fail(NULL);
}
__attribute__((noinline))
systime_t wait_tick(void) {
void test_assert_time_window(systime_t start, systime_t end) {
systime_t time = chSysGetTime() + 1;
while (chSysGetTime() < time) {
#if defined(WIN32)
ChkIntSources();
#endif
}
return time;
test_assert(chSysInTimeWindow(start, end), "time window error");
}
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;
/*
* Threads utils.
*/
void test_wait_threads(void) {
int i;
for (i = 0; i < 5; i++) {
msg = chMsgSend(p, 'A' + i);
chFDDPut(comp, msg);
for (i = 0; i < MAX_THREADS; i++)
if (threads[i])
chThdWait(threads[i]);
}
void test_cpu_pulse(systime_t ms) {
systime_t start = chSysGetTime();
while (chSysInTimeWindow(start, start + ms)) {
#if defined(WIN32)
ChkIntSources();
#endif
}
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) {
chThdSleep(10);
CPU(50);
chFDDPut(comp, *(uint8_t *)p);
return 0;
}
msg_t Thread11(void *p) {
chThdSleep(5);
chSemWait(&sem1);
chSemSignal(&sem1);
chFDDPut(comp, *(uint8_t *)p);
return 0;
}
msg_t Thread12(void *p) {
chSemWait(&sem1);
chThdSleep(20);
chSemSignal(&sem1);
chFDDPut(comp, *(uint8_t *)p);
return 0;
}
/*
* Time
* 0 ++++++++++++++++++AL+....2++++++++++++++AU0------------------------------
* 1 .....................++--------------------------------------------------
* 2 .......................++AL.............+++++++++AU++++++++++++++++++++++
* Test suite execution.
*/
void testmtx2(void) {
static void execute_test(const struct testcase *tcp) {
int i;
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("");
/* Initialization */
clear_tokens();
local_fail = FALSE;
for (i = 0; i < MAX_THREADS; i++)
threads[i] = NULL;
tcp->setup();
tcp->execute();
tcp->teardown();
}
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("");
}
msg_t Thread13(void *p) {
chMtxLock(&m1);
CPU(50);
chMtxUnlock();
chFDDPut(comp, *(uint8_t *)p);
return 0;
}
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;
}
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;
}
msg_t Thread17(void *p) {
chThdSleep(50);
chMtxLock(&m2);
CPU(50);
chMtxUnlock();
chFDDPut(comp, *(uint8_t *)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++......
*/
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 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("");
}
__attribute__((noinline))
unsigned int msg_loop_test(Thread *tp) {
uint32_t i;
systime_t time = wait_tick() + 1000;
i = 0;
while (chSysGetTime() < time) {
(void)chMsgSend(tp, 0);
i++;
#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);
}
__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");
}
__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");
}
__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");
}
__attribute__((noinline))
void bench4(void) {
uint32_t i;
systime_t time;
println("*** Kernel Benchmark, threads creation/termination:");
time = wait_tick() + 1000;
i = 0;
while (chSysGetTime() < time) {
t1 = chThdCreate(chThdGetPriority()-1, 0, wsT1, sizeof(wsT1), Thread7, NULL);
chThdWait(t1);
i++;
#if defined(WIN32)
ChkIntSources();
#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);
i++;
#if defined(WIN32)
ChkIntSources();
#endif
}
print("Queues throughput = ");
printn(i * 4);
println(" bytes/S");
}
/**
* Tester thread, this thread must be created with priority \p NORMALPRIO.
*/
msg_t TestThread(void *p) {
int i;
comp = p;
println("*****************************");
println("*** ChibiOS/RT test suite ***");
println("*****************************");
println("");
test_println("");
test_println("*****************************");
test_println("*** ChibiOS/RT test suite ***");
test_println("*****************************");
test_println("");
/*
* Ready list ordering tests.
*/
testrdy1();
testrdy2();
global_fail = FALSE;
i = 0;
while (tests[i]) {
#if DELAY_BETWEEN_TESTS > 0
chThdSleep(DELAY_BETWEEN_TESTS);
#endif
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++;
}
test_println("------------------------------------------------------------");
test_println("");
test_print("Final result: ");
if (global_fail)
test_println("FAIL");
else
test_println("SUCCESS");
/*
* 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;
}

View File

@ -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_ */

65
test/testmsg.c Normal file
View File

@ -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
};

25
test/testmsg.h Normal file
View File

@ -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_ */

219
test/testmtx.c Normal file
View File

@ -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
};

25
test/testmtx.h Normal file
View File

@ -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_ */

86
test/testrdy.c Normal file
View File

@ -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
};

25
test/testrdy.h Normal file
View File

@ -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_ */

102
test/testsem.c Normal file
View File

@ -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
};

25
test/testsem.h Normal file
View File

@ -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_ */