100% code coverage for heap, semaphores and events.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@903 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
gdisirio 2009-04-17 14:53:04 +00:00
parent e8ae833287
commit 0a37ec19f6
5 changed files with 248 additions and 61 deletions

View File

@ -84,11 +84,11 @@ Win32-MinGW - ChibiOS/RT simulator and demo into a WIN32 process,
- FIX: Removed usused list functions (bug 2755230)(backported in stable
branch).
- NEW: Added a code coverage analysis application under ./tests/coverage.
- Added more test cases in order to improve the test suite code coverage (it
was 74% in version 1.2.0).
- Added a new "naked" context switch benchmark that better defines the
real context switch time, for the STM32 the context switch is performed
under 1.48uS.
- NEW: Added more test cases in order to improve the test suite code coverage
(it was 74% in version 1.2.0).
- NEW: Added a new "naked" context switch benchmark that better defines the
real context switch time, previous benchmarks introduced too much overhead
to the measurement. The STM32 performs the context switch in under 1.48uS.
*** 1.2.0 ***
- Added license exception text to the 1.2.0 branch.

View File

@ -29,7 +29,7 @@ static EventSource es1, es2;
static char *evt1_gettest(void) {
return "Events, wait and broadcast";
return "Events, registration and dispatch";
}
static void evt1_setup(void) {
@ -37,58 +37,31 @@ static void evt1_setup(void) {
chEvtClear(ALL_EVENTS);
}
static msg_t thread(void *p) {
chEvtBroadcast(&es1);
chThdSleepMilliseconds(50);
chEvtBroadcast(&es2);
return 0;
}
static void h1(eventid_t id) {test_emit_token('A');}
static void h2(eventid_t id) {test_emit_token('B');}
static void h3(eventid_t id) {test_emit_token('C');}
static const evhandler_t evhndl[] = {h1, h2, h3};
static void evt1_execute(void) {
eventmask_t m;
EventListener el1, el2;
systime_t target_time;
/*
* Test on chEvtWaitOne().
*/
chEvtPend(5);
m = chEvtWaitOne(ALL_EVENTS);
test_assert(m == 1, "#1"); /* Single bit error.*/
m = chEvtWaitOne(ALL_EVENTS);
test_assert(m == 4, "#2"); /* Single bit error.*/
m = chEvtClear(0);
test_assert(m == 0, "#3"); /* Stuck event.*/
/*
* Test on chEvtWaitAny().
*/
chEvtPend(5);
m = chEvtWaitAny(ALL_EVENTS);
test_assert(m == 5, "#4"); /* Unexpected pending.*/
m = chEvtClear(0);
test_assert(m == 0, "#5"); /* Stuck event.*/
/*
* Test on chEvtWaitAll(), chEvtRegisterMask() and chEvtUnregister().
* Testing chEvtRegisterMask() and chEvtUnregister().
*/
chEvtInit(&es1);
chEvtInit(&es2);
chEvtRegisterMask(&es1, &el1, 1);
chEvtRegisterMask(&es2, &el2, 4);
target_time = chTimeNow() + MS2ST(50);
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-1, thread, "A");
m = chEvtWaitAll(5);
test_assert_time_window(target_time, target_time + ALLOWED_DELAY);
m = chEvtClear(0);
test_assert(m == 0, "#6"); /* Stuck event.*/
test_wait_threads();
chEvtRegisterMask(&es1, &el2, 2);
test_assert(chEvtIsListening(&es1), "#1"); /* Must not be empty */
chEvtUnregister(&es1, &el1);
chEvtUnregister(&es2, &el2);
test_assert(!chEvtIsListening(&es1), "#7"); /* Stuck listener.*/
test_assert(!chEvtIsListening(&es2), "#8"); /* Stuck listener.*/
test_assert(chEvtIsListening(&es1), "#2"); /* Must not be empty */
chEvtUnregister(&es1, &el2);
test_assert(!chEvtIsListening(&es1), "#3"); /* Stuck listener.*/
/*
* Testing chEvtDispatch().
*/
chEvtDispatch(evhndl, 7);
test_assert_sequence("ABC");
}
const struct testcase testevt1 = {
@ -98,6 +71,152 @@ const struct testcase testevt1 = {
evt1_execute
};
static char *evt2_gettest(void) {
return "Events, wait and broadcast";
}
static void evt2_setup(void) {
chEvtClear(ALL_EVENTS);
}
static msg_t thread1(void *p) {
chThdSleepMilliseconds(50);
chEvtSignal((Thread *)p, 1);
return 0;
}
static msg_t thread2(void *p) {
chEvtBroadcast(&es1);
chThdSleepMilliseconds(50);
chEvtBroadcast(&es2);
return 0;
}
static void evt2_execute(void) {
eventmask_t m;
EventListener el1, el2;
systime_t target_time;
/*
* Test on chEvtWaitOne() without wait.
*/
chEvtPend(5);
m = chEvtWaitOne(ALL_EVENTS);
test_assert(m == 1, "#1"); /* Single bit error.*/
m = chEvtWaitOne(ALL_EVENTS);
test_assert(m == 4, "#2"); /* Single bit error.*/
m = chEvtClear(0);
test_assert(m == 0, "#3"); /* Stuck bit.*/
/*
* Test on chEvtWaitOne() with wait.
*/
test_wait_tick();
target_time = chTimeNow() + MS2ST(50);
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1,
thread1, chThdSelf());
m = chEvtWaitOne(ALL_EVENTS);
test_assert_time_window(target_time, target_time + ALLOWED_DELAY);
test_assert(m == 1, "#5"); /* Single bit error.*/
m = chEvtClear(0);
test_assert(m == 0, "#6"); /* Stuck bit.*/
test_wait_threads();
/*
* Test on chEvtWaitAny() without wait.
*/
chEvtPend(5);
m = chEvtWaitAny(ALL_EVENTS);
test_assert(m == 5, "#7"); /* Unexpected pending bit.*/
m = chEvtClear(0);
test_assert(m == 0, "#8"); /* Stuck bit.*/
/*
* Test on chEvtWaitAny() with wait.
*/
test_wait_tick();
target_time = chTimeNow() + MS2ST(50);
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1,
thread1, chThdSelf());
m = chEvtWaitAny(ALL_EVENTS);
test_assert_time_window(target_time, target_time + ALLOWED_DELAY);
test_assert(m == 1, "#9"); /* Single bit error.*/
m = chEvtClear(0);
test_assert(m == 0, "#10"); /* Stuck bit.*/
test_wait_threads();
/*
* Test on chEvtWaitAll().
*/
chEvtInit(&es1);
chEvtInit(&es2);
chEvtRegisterMask(&es1, &el1, 1);
chEvtRegisterMask(&es2, &el2, 4);
test_wait_tick();
target_time = chTimeNow() + MS2ST(50);
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1,
thread2, "A");
m = chEvtWaitAll(5);
test_assert_time_window(target_time, target_time + ALLOWED_DELAY);
m = chEvtClear(0);
test_assert(m == 0, "#11"); /* Stuck event.*/
test_wait_threads();
chEvtUnregister(&es1, &el1);
chEvtUnregister(&es2, &el2);
test_assert(!chEvtIsListening(&es1), "#12"); /* Stuck listener.*/
test_assert(!chEvtIsListening(&es2), "#13"); /* Stuck listener.*/
}
const struct testcase testevt2 = {
evt2_gettest,
evt2_setup,
NULL,
evt2_execute
};
#if CH_USE_EVENTS_TIMEOUT
static char *evt3_gettest(void) {
return "Events, timeouts";
}
static void evt3_setup(void) {
chEvtClear(ALL_EVENTS);
}
static void evt3_execute(void) {
eventmask_t m;
/*
* Tests various timeout situations.
*/
m = chEvtWaitOneTimeout(ALL_EVENTS, TIME_IMMEDIATE);
test_assert(m == 0, "#1");
m = chEvtWaitAnyTimeout(ALL_EVENTS, TIME_IMMEDIATE);
test_assert(m == 0, "#2");
m = chEvtWaitAllTimeout(ALL_EVENTS, TIME_IMMEDIATE);
test_assert(m == 0, "#3");
m = chEvtWaitOneTimeout(ALL_EVENTS, 10);
test_assert(m == 0, "#4");
m = chEvtWaitAnyTimeout(ALL_EVENTS, 10);
test_assert(m == 0, "#5");
m = chEvtWaitAllTimeout(ALL_EVENTS, 10);
test_assert(m == 0, "#6");
#endif
}
const struct testcase testevt3 = {
evt3_gettest,
evt3_setup,
NULL,
evt3_execute
};
#endif /* CH_USE_EVENTS */
/*
@ -106,6 +225,10 @@ const struct testcase testevt1 = {
const struct testcase * const patternevt[] = {
#if CH_USE_EVENTS
&testevt1,
&testevt2,
#if CH_USE_EVENTS_TIMEOUT
&testevt3,
#endif
#endif
NULL
};

View File

@ -44,21 +44,38 @@ static void heap1_execute(void) {
p1 = chHeapAlloc(SIZE);
p2 = chHeapAlloc(SIZE);
p3 = chHeapAlloc(SIZE);
chHeapFree(p1); /* Does not merge */
chHeapFree(p2); /* Merges backward */
chHeapFree(p3); /* Merges both sides */
chHeapFree(p1); /* Does not merge */
chHeapFree(p2); /* Merges backward */
chHeapFree(p3); /* Merges both sides */
test_assert(chHeapStatus(&n) == 1, "#1"); /* Heap fragmented.*/
/* Reverse order */
p1 = chHeapAlloc(SIZE);
p2 = chHeapAlloc(SIZE);
p3 = chHeapAlloc(SIZE);
chHeapFree(p3); /* Merges forward */
chHeapFree(p2); /* Merges forward */
chHeapFree(p1); /* Merges forward */
chHeapFree(p3); /* Merges forward */
chHeapFree(p2); /* Merges forward */
chHeapFree(p1); /* Merges forward */
test_assert(chHeapStatus(&n) == 1, "#2"); /* Heap fragmented.*/
test_assert(n == sz, "#3"); /* Heap size changed.*/
/* Small fragments handling */
p1 = chHeapAlloc(SIZE + 1);
p2 = chHeapAlloc(SIZE);
chHeapFree(p1);
test_assert(chHeapStatus(&n) == 2, "#3"); /* Heap must contain 2 blocks.*/
p1 = chHeapAlloc(SIZE);
test_assert(chHeapStatus(&n) == 1, "#4"); /* Heap fragmented.*/
chHeapFree(p2);
chHeapFree(p1);
/* Allocate all handling */
(void)chHeapStatus(&n);
p1 = chHeapAlloc(n);
test_assert(chHeapStatus(&n) == 0, "#5"); /* Heap must be empty.*/
chHeapFree(p1);
test_assert(chHeapStatus(&n) == 1, "#6"); /* Heap fragmented.*/
test_assert(n == sz, "#7"); /* Heap size changed.*/
}
else {
test_print("--- Size : ");

View File

@ -85,7 +85,10 @@ static void sem2_setup(void) {
static msg_t thread2(void *p) {
chThdSleepMilliseconds(50);
chSemSignal(&sem1);
chSysLock();
chSemSignalI(&sem1); /* For coverage reasons */
chSchRescheduleS();
chSysUnlock();
return 0;
}
@ -115,6 +118,7 @@ static void sem2_execute(void) {
/*
* Testing timeout condition.
*/
test_wait_tick();
target_time = chTimeNow() + MS2ST(5 * 500);
for (i = 0; i < 5; i++) {
test_emit_token('A' + i);
@ -134,6 +138,44 @@ const struct testcase testsem2 = {
sem2_execute
};
#endif /* CH_USE_SEMAPHORES_TIMEOUT */
#if CH_USE_SEMSW
static char *sem3_gettest(void) {
return "Semaphores, atomic signal-wait";
}
static void sem3_setup(void) {
chSemInit(&sem1, 0);
}
static msg_t thread3(void *p) {
chSemWait(&sem1);
chSemSignal(&sem1);
return 0;
}
static void sem3_execute(void) {
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread3, "A");
chSemSignalWait(&sem1, &sem1);
test_assert(isempty(&sem1.s_queue), "#1"); /* Queue not empty */
test_assert(sem1.s_cnt == 0, "#2"); /* Counter not zero */
chSemSignalWait(&sem1, &sem1);
test_assert(isempty(&sem1.s_queue), "#3"); /* Queue not empty */
test_assert(sem1.s_cnt == 0, "#4"); /* Counter not zero */
}
const struct testcase testsem3 = {
sem3_gettest,
sem3_setup,
NULL,
sem3_execute
};
#endif /* CH_USE_SEMSW */
#endif /* CH_USE_SEMAPHORES */
/*
@ -145,6 +187,9 @@ const struct testcase * const patternsem[] = {
#if CH_USE_SEMAPHORES_TIMEOUT
&testsem2,
#endif
#if CH_USE_SEMSW
&testsem3,
#endif
#endif
NULL
};

View File

@ -130,25 +130,27 @@ static char *thd4_gettest(void) {
static void thd4_execute(void) {
systime_t time;
test_wait_tick();
/* Timeouts in microseconds.*/
time = chTimeNow();
chThdSleepMicroseconds(100000);
test_assert(chTimeIsWithin(time + US2ST(100000), time + US2ST(100000) + 1), "#1");
test_assert_time_window(time + US2ST(100000), time + US2ST(100000) + 1);
/* Timeouts in milliseconds.*/
time = chTimeNow();
chThdSleepMilliseconds(100);
test_assert(chTimeIsWithin(time + MS2ST(100), time + MS2ST(100) + 1), "#2");
test_assert_time_window(time + MS2ST(100), time + MS2ST(100) + 1);
/* Timeouts in seconds.*/
time = chTimeNow();
chThdSleepSeconds(1);
test_assert(chTimeIsWithin(time + S2ST(1), time + S2ST(1) + 1), "#3");
test_assert_time_window(time + S2ST(1), time + S2ST(1) + 1);
/* Absolute timelines.*/
time = chTimeNow() + MS2ST(100);
chThdSleepUntil(time);
test_assert(chTimeIsWithin(time, time + 1), "#4");
test_assert_time_window(time, time + 1);
}
const struct testcase testthd4 = {