New style test sequences for RT (not complete).
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9179 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
8a88814260
commit
ea61c2791c
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @mainpage Test Suite Specification
|
||||
* Test suite for ChibiOS/RT. The purpose of this suite is to perform
|
||||
* unit tests on the RT modules and to converge to 100% code coverage
|
||||
* through successive improvements.
|
||||
*
|
||||
* <h2>Test Sequences</h2>
|
||||
* - @subpage test_sequence_001
|
||||
* - @subpage test_sequence_002
|
||||
* - @subpage test_sequence_003
|
||||
* - @subpage test_sequence_004
|
||||
* - @subpage test_sequence_005
|
||||
* - @subpage test_sequence_006
|
||||
* - @subpage test_sequence_007
|
||||
* - @subpage test_sequence_008
|
||||
* .
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test_root.c
|
||||
* @brief Test Suite root structures code.
|
||||
*/
|
||||
|
||||
#include "hal.h"
|
||||
#include "ch_test.h"
|
||||
#include "test_root.h"
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Array of all the test sequences.
|
||||
*/
|
||||
const testcase_t * const *test_suite[] = {
|
||||
test_sequence_001,
|
||||
test_sequence_002,
|
||||
test_sequence_003,
|
||||
test_sequence_004,
|
||||
test_sequence_005,
|
||||
test_sequence_006,
|
||||
test_sequence_007,
|
||||
test_sequence_008,
|
||||
NULL
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Shared code. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*
|
||||
* Static working areas, the following areas can be used for threads or
|
||||
* used as temporary buffers.
|
||||
*/
|
||||
union test_buffers test;
|
||||
|
||||
/*
|
||||
* Pointers to the spawned threads.
|
||||
*/
|
||||
thread_t *threads[MAX_THREADS];
|
||||
|
||||
/*
|
||||
* Pointers to the working areas.
|
||||
*/
|
||||
void * ROMCONST wa[5] = {test.wa.T0, test.wa.T1, test.wa.T2,
|
||||
test.wa.T3, test.wa.T4};
|
||||
|
||||
/*
|
||||
* Sets a termination request in all the test-spawned threads.
|
||||
*/
|
||||
void test_terminate_threads(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_THREADS; i++)
|
||||
if (threads[i])
|
||||
chThdTerminate(threads[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Waits for the completion of all the test-spawned threads.
|
||||
*/
|
||||
void test_wait_threads(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_THREADS; i++)
|
||||
if (threads[i] != NULL) {
|
||||
chThdWait(threads[i]);
|
||||
threads[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
systime_t test_wait_tick(void) {
|
||||
|
||||
chThdSleep(1);
|
||||
return chVTGetSystemTime();
|
||||
}
|
||||
|
||||
#endif /* !defined(__DOXYGEN__) */
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test_root.h
|
||||
* @brief Test Suite root structures header.
|
||||
*/
|
||||
|
||||
#ifndef _SPC5_TEST_ROOT_H_
|
||||
#define _SPC5_TEST_ROOT_H_
|
||||
|
||||
#include "test_sequence_001.h"
|
||||
#include "test_sequence_002.h"
|
||||
#include "test_sequence_003.h"
|
||||
#include "test_sequence_004.h"
|
||||
#include "test_sequence_005.h"
|
||||
#include "test_sequence_006.h"
|
||||
#include "test_sequence_007.h"
|
||||
#include "test_sequence_008.h"
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
extern const testcase_t * const *test_suite[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Shared definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define TEST_SUITE_NAME "ChibiOS/RT Test Suite"
|
||||
|
||||
/*
|
||||
* Allowed delay in timeout checks.
|
||||
*/
|
||||
#define ALLOWED_DELAY MS2ST(2)
|
||||
|
||||
/*
|
||||
* Maximum number of test threads.
|
||||
*/
|
||||
#define MAX_THREADS 5
|
||||
|
||||
/*
|
||||
* Stack size of test threads.
|
||||
*/
|
||||
#if defined(CH_ARCHITECTURE_AVR) || defined(CH_ARCHITECTURE_MSP430)
|
||||
#define THREADS_STACK_SIZE 48
|
||||
#elif defined(CH_ARCHITECTURE_STM8)
|
||||
#define THREADS_STACK_SIZE 64
|
||||
#elif defined(CH_ARCHITECTURE_SIMIA32)
|
||||
#define THREADS_STACK_SIZE 512
|
||||
#else
|
||||
#define THREADS_STACK_SIZE 128
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Working Area size of test threads.
|
||||
*/
|
||||
#define WA_SIZE THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE)
|
||||
|
||||
/*
|
||||
* Union of all Working Areas, usable as a single large buffer if required.
|
||||
*/
|
||||
union test_buffers {
|
||||
struct {
|
||||
THD_WORKING_AREA(T0, THREADS_STACK_SIZE);
|
||||
THD_WORKING_AREA(T1, THREADS_STACK_SIZE);
|
||||
THD_WORKING_AREA(T2, THREADS_STACK_SIZE);
|
||||
THD_WORKING_AREA(T3, THREADS_STACK_SIZE);
|
||||
THD_WORKING_AREA(T4, THREADS_STACK_SIZE);
|
||||
} wa;
|
||||
uint8_t buffer[WA_SIZE * 5];
|
||||
};
|
||||
|
||||
extern thread_t *threads[MAX_THREADS];
|
||||
extern void * ROMCONST wa[5];
|
||||
|
||||
void test_terminate_threads(void);
|
||||
void test_wait_threads(void);
|
||||
systime_t test_wait_tick(void);
|
||||
|
||||
#endif /* !defined(__DOXYGEN__) */
|
||||
|
||||
#endif /* _SPC5_TEST_ROOT_H_ */
|
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
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_001 [1] System layer and port interface
|
||||
*
|
||||
* File: @ref test_sequence_001.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The functionality of the system layer and port interface is tested.
|
||||
* Basic RT functionality is taken for granted or this test suite could
|
||||
* not even be executed. Errors in implementation are detected by
|
||||
* executing this sequence with the state checker enabled
|
||||
* (CH_DBG_STATE_CHECKER=TRUE).
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_001_001
|
||||
* - @subpage test_001_002
|
||||
* - @subpage test_001_003
|
||||
* - @subpage test_001_004
|
||||
* .
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Shared code.
|
||||
****************************************************************************/
|
||||
|
||||
/* Timer callback for testing system functions in ISR context.*/
|
||||
static void vtcb(void *p) {
|
||||
syssts_t sts;
|
||||
|
||||
(void)p;
|
||||
|
||||
/* Testing normal case.*/
|
||||
chSysLockFromISR();
|
||||
chSysUnlockFromISR();
|
||||
|
||||
/* Reentrant case.*/
|
||||
chSysLockFromISR();
|
||||
sts = chSysGetStatusAndLockX();
|
||||
chSysRestoreStatusX(sts);
|
||||
chSysUnlockFromISR();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Test cases.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @page test_001_001 [1.1] System integrity functionality
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The system self-test functionality is invoked in order to make an
|
||||
* initial system state assessment and for coverage.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [1.1.1] Testing Ready List integrity.
|
||||
* - [1.1.2] Testing Virtual Timers List integrity.
|
||||
* - [1.1.3] Testing Registry List integrity.
|
||||
* - [1.1.4] Testing Port-defined integrity.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_001_001_execute(void) {
|
||||
bool result;
|
||||
|
||||
/* [1.1.1] Testing Ready List integrity.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
chSysLock();
|
||||
result = chSysIntegrityCheckI(CH_INTEGRITY_RLIST);
|
||||
chSysUnlock();
|
||||
test_assert(result == false, "ready list check failed");
|
||||
}
|
||||
|
||||
/* [1.1.2] Testing Virtual Timers List integrity.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
chSysLock();
|
||||
result = chSysIntegrityCheckI(CH_INTEGRITY_VTLIST);
|
||||
chSysUnlock();
|
||||
test_assert(result == false, "virtual timers list check failed");
|
||||
}
|
||||
|
||||
/* [1.1.3] Testing Registry List integrity.*/
|
||||
test_set_step(3);
|
||||
{
|
||||
chSysLock();
|
||||
result = chSysIntegrityCheckI(CH_INTEGRITY_REGISTRY);
|
||||
chSysUnlock();
|
||||
test_assert(result == false, "registry list check failed");
|
||||
}
|
||||
|
||||
/* [1.1.4] Testing Port-defined integrity.*/
|
||||
test_set_step(4);
|
||||
{
|
||||
chSysLock();
|
||||
result = chSysIntegrityCheckI(CH_INTEGRITY_PORT);
|
||||
chSysUnlock();
|
||||
test_assert(result == false, "port layer check failed");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_001_001 = {
|
||||
"System integrity functionality",
|
||||
NULL,
|
||||
NULL,
|
||||
test_001_001_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_001_002 [1.2] Critical zones functionality
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The critical zones API is invoked for coverage.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [1.2.1] Testing chSysGetStatusAndLockX() and
|
||||
* chSysRestoreStatusX(), non reentrant case.
|
||||
* - [1.2.2] Testing chSysGetStatusAndLockX() and
|
||||
* chSysRestoreStatusX(), reentrant case.
|
||||
* - [1.2.3] Testing chSysUnconditionalLock().
|
||||
* - [1.2.4] Testing chSysUnconditionalUnlock().
|
||||
* - [1.2.5] Testing from ISR context using a virtual timer.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_001_002_execute(void) {
|
||||
syssts_t sts;
|
||||
virtual_timer_t vt;
|
||||
|
||||
/* [1.2.1] Testing chSysGetStatusAndLockX() and
|
||||
chSysRestoreStatusX(), non reentrant case.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
sts = chSysGetStatusAndLockX();
|
||||
chSysRestoreStatusX(sts);
|
||||
}
|
||||
|
||||
/* [1.2.2] Testing chSysGetStatusAndLockX() and
|
||||
chSysRestoreStatusX(), reentrant case.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
chSysLock();
|
||||
sts = chSysGetStatusAndLockX();
|
||||
chSysRestoreStatusX(sts);
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/* [1.2.3] Testing chSysUnconditionalLock().*/
|
||||
test_set_step(3);
|
||||
{
|
||||
chSysUnconditionalLock();
|
||||
chSysUnconditionalLock();
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/* [1.2.4] Testing chSysUnconditionalUnlock().*/
|
||||
test_set_step(4);
|
||||
{
|
||||
chSysLock();
|
||||
chSysUnconditionalUnlock();
|
||||
chSysUnconditionalUnlock();
|
||||
}
|
||||
|
||||
/* [1.2.5] Testing from ISR context using a virtual timer.*/
|
||||
test_set_step(5);
|
||||
{
|
||||
chVTObjectInit(&vt);
|
||||
chVTSet(&vt, 1, vtcb, NULL);
|
||||
chThdSleep(10);
|
||||
|
||||
test_assert(chVTIsArmed(&vt) == false, "timer still armed");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_001_002 = {
|
||||
"Critical zones functionality",
|
||||
NULL,
|
||||
NULL,
|
||||
test_001_002_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_001_003 [1.3] Interrupts handling functionality
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The interrupts handling API is invoked for coverage.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [1.3.1] Testing chSysSuspend(), chSysDisable() and chSysEnable().
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_001_003_execute(void) {
|
||||
|
||||
/* [1.3.1] Testing chSysSuspend(), chSysDisable() and
|
||||
chSysEnable().*/
|
||||
test_set_step(1);
|
||||
{
|
||||
chSysSuspend();
|
||||
chSysDisable();
|
||||
chSysSuspend();
|
||||
chSysEnable();
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_001_003 = {
|
||||
"Interrupts handling functionality",
|
||||
NULL,
|
||||
NULL,
|
||||
test_001_003_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_001_004 [1.4] System Tick Counter functionality
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The functionality of the API @p chVTGetSystemTimeX() is tested.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [1.4.1] A System Tick Counter increment is expected, the test
|
||||
* simply hangs if it does not happen.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_001_004_execute(void) {
|
||||
|
||||
/* [1.4.1] A System Tick Counter increment is expected, the test
|
||||
simply hangs if it does not happen.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
systime_t time = chVTGetSystemTimeX();
|
||||
while (time == chVTGetSystemTimeX()) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_001_004 = {
|
||||
"System Tick Counter functionality",
|
||||
NULL,
|
||||
NULL,
|
||||
test_001_004_execute
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Exported data.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief System layer and port interface.
|
||||
*/
|
||||
const testcase_t * const test_sequence_001[] = {
|
||||
&test_001_001,
|
||||
&test_001_002,
|
||||
&test_001_003,
|
||||
&test_001_004,
|
||||
NULL
|
||||
};
|
|
@ -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_001[];
|
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
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_002 [2] Threads Functionality
|
||||
*
|
||||
* File: @ref test_sequence_002.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This sequence tests the ChibiOS/RT functionalities related to
|
||||
* threading.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_002_001
|
||||
* - @subpage test_002_002
|
||||
* - @subpage test_002_003
|
||||
* - @subpage test_002_004
|
||||
* .
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Shared code.
|
||||
****************************************************************************/
|
||||
|
||||
static THD_FUNCTION(thread, p) {
|
||||
|
||||
test_emit_token(*(char *)p);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Test cases.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @page test_002_001 [2.1] Thread Sleep functionality
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The functionality of @p chThdSleep() and derivatives is tested.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [2.1.1] The current system time is read then a sleep is performed
|
||||
* for 100 system ticks and on exit the system time is verified
|
||||
* again.
|
||||
* - [2.1.2] The current system time is read then a sleep is performed
|
||||
* for 100000 microseconds and on exit the system time is verified
|
||||
* again.
|
||||
* - [2.1.3] The current system time is read then a sleep is performed
|
||||
* for 100 milliseconds and on exit the system time is verified
|
||||
* again.
|
||||
* - [2.1.4] The current system time is read then a sleep is performed
|
||||
* for 1 second and on exit the system time is verified again.
|
||||
* - [2.1.5] Function chThdSleepUntil() is tested with a timeline of
|
||||
* "now" + 100 ticks.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_002_001_execute(void) {
|
||||
systime_t time;
|
||||
|
||||
/* [2.1.1] The current system time is read then a sleep is performed
|
||||
for 100 system ticks and on exit the system time is verified
|
||||
again.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
time = chVTGetSystemTimeX();
|
||||
chThdSleep(100);
|
||||
test_assert_time_window(time + 100,
|
||||
time + 100 + CH_CFG_ST_TIMEDELTA + 1,
|
||||
"out of time window");
|
||||
}
|
||||
|
||||
/* [2.1.2] The current system time is read then a sleep is performed
|
||||
for 100000 microseconds and on exit the system time is verified
|
||||
again.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
time = chVTGetSystemTimeX();
|
||||
chThdSleepMicroseconds(100000);
|
||||
test_assert_time_window(time + US2ST(100000),
|
||||
time + US2ST(100000) + CH_CFG_ST_TIMEDELTA + 1,
|
||||
"out of time window");
|
||||
}
|
||||
|
||||
/* [2.1.3] The current system time is read then a sleep is performed
|
||||
for 100 milliseconds and on exit the system time is verified
|
||||
again.*/
|
||||
test_set_step(3);
|
||||
{
|
||||
time = chVTGetSystemTimeX();
|
||||
chThdSleepMilliseconds(100);
|
||||
test_assert_time_window(time + MS2ST(100),
|
||||
time + MS2ST(100) + CH_CFG_ST_TIMEDELTA + 1,
|
||||
"out of time window");
|
||||
}
|
||||
|
||||
/* [2.1.4] The current system time is read then a sleep is performed
|
||||
for 1 second and on exit the system time is verified again.*/
|
||||
test_set_step(4);
|
||||
{
|
||||
time = chVTGetSystemTimeX();
|
||||
chThdSleepSeconds(1);
|
||||
test_assert_time_window(time + S2ST(1),
|
||||
time + S2ST(1) + CH_CFG_ST_TIMEDELTA + 1,
|
||||
"out of time window");
|
||||
}
|
||||
|
||||
/* [2.1.5] Function chThdSleepUntil() is tested with a timeline of
|
||||
"now" + 100 ticks.*/
|
||||
test_set_step(5);
|
||||
{
|
||||
time = chVTGetSystemTimeX();
|
||||
chThdSleepUntil(time + 100);
|
||||
test_assert_time_window(time + 100,
|
||||
time + 100 + CH_CFG_ST_TIMEDELTA + 1,
|
||||
"out of time window");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_002_001 = {
|
||||
"Thread Sleep functionality",
|
||||
NULL,
|
||||
NULL,
|
||||
test_002_001_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_002_002 [2.2] Ready List functionality, threads priority order
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five threads, are enqueued in the ready list and atomically
|
||||
* executed. The test expects the threads to perform their operations
|
||||
* in correct priority order regardless of the initial order.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [2.2.1] Creating 5 threads with increasing priority, execution
|
||||
* sequence is tested.
|
||||
* - [2.2.2] Creating 5 threads with decreasing priority, execution
|
||||
* sequence is tested.
|
||||
* - [2.2.3] Creating 5 threads with pseudo-random priority, execution
|
||||
* sequence is tested.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_002_002_execute(void) {
|
||||
|
||||
/* [2.2.1] Creating 5 threads with increasing priority, execution
|
||||
sequence is tested.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E");
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D");
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C");
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B");
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A");
|
||||
test_wait_threads();
|
||||
test_assert_sequence("ABCDE", "invalid sequence");
|
||||
}
|
||||
|
||||
/* [2.2.2] Creating 5 threads with decreasing priority, execution
|
||||
sequence is tested.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A");
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B");
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C");
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D");
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E");
|
||||
test_wait_threads();
|
||||
test_assert_sequence("ABCDE", "invalid sequence");
|
||||
}
|
||||
|
||||
/* [2.2.3] Creating 5 threads with pseudo-random priority, execution
|
||||
sequence is tested.*/
|
||||
test_set_step(3);
|
||||
{
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D");
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E");
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A");
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B");
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C");
|
||||
test_wait_threads();
|
||||
test_assert_sequence("ABCDE", "invalid sequence");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_002_002 = {
|
||||
"Ready List functionality, threads priority order",
|
||||
NULL,
|
||||
NULL,
|
||||
test_002_002_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_002_003 [2.3] Priority change test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* A series of priority changes are performed on the current thread in
|
||||
* order to verify that the priority change happens as expected.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [2.3.1] Thread priority is increased by one then a check is
|
||||
* performed.
|
||||
* - [2.3.2] Thread priority is returned to the previous value then a
|
||||
* check is performed.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_002_003_execute(void) {
|
||||
tprio_t prio, p1;
|
||||
|
||||
/* [2.3.1] Thread priority is increased by one then a check is
|
||||
performed.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
prio = chThdGetPriorityX();
|
||||
p1 = chThdSetPriority(prio + 1);
|
||||
test_assert(p1 == prio, "unexpected returned priority level");
|
||||
test_assert(chThdGetPriorityX() == prio + 1, "unexpected priority level");
|
||||
}
|
||||
|
||||
/* [2.3.2] Thread priority is returned to the previous value then a
|
||||
check is performed.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
p1 = chThdSetPriority(p1);
|
||||
test_assert(p1 == prio + 1, "unexpected returned priority level");
|
||||
test_assert(chThdGetPriorityX() == prio, "unexpected priority level");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_002_003 = {
|
||||
"Priority change test",
|
||||
NULL,
|
||||
NULL,
|
||||
test_002_003_execute
|
||||
};
|
||||
|
||||
#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_002_004 [2.4] Priority change test with Priority Inheritance
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* A series of priority changes are performed on the current thread in
|
||||
* order to verify that the priority change happens as expected.
|
||||
*
|
||||
* <h2>Conditions</h2>
|
||||
* This test is only executed if the following preprocessor condition
|
||||
* evaluates to true:
|
||||
* - CH_CFG_USE_MUTEXES
|
||||
* .
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [2.4.1] Simulating a priority boost situation (prio > realprio).
|
||||
* - [2.4.2] Raising thread priority above original priority but below
|
||||
* the boosted level.
|
||||
* - [2.4.3] Raising thread priority above the boosted level.
|
||||
* - [2.4.4] Restoring original conditions.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_002_004_execute(void) {
|
||||
tprio_t prio, p1;
|
||||
|
||||
/* [2.4.1] Simulating a priority boost situation (prio > realprio).*/
|
||||
test_set_step(1);
|
||||
{
|
||||
prio = chThdGetPriorityX();
|
||||
chThdGetSelfX()->prio += 2;
|
||||
test_assert(chThdGetPriorityX() == prio + 2, "unexpected priority level");
|
||||
}
|
||||
|
||||
/* [2.4.2] Raising thread priority above original priority but below
|
||||
the boosted level.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
p1 = chThdSetPriority(prio + 1);
|
||||
test_assert(p1 == prio, "unexpected returned priority level");
|
||||
test_assert(chThdGetSelfX()->prio == prio + 2, "unexpected priority level");
|
||||
test_assert(chThdGetSelfX()->realprio == prio + 1, "unexpected returned real priority level");
|
||||
}
|
||||
|
||||
/* [2.4.3] Raising thread priority above the boosted level.*/
|
||||
test_set_step(3);
|
||||
{
|
||||
p1 = chThdSetPriority(prio + 3);
|
||||
test_assert(p1 == prio + 1, "unexpected returned priority level");
|
||||
test_assert(chThdGetSelfX()->prio == prio + 3, "unexpected priority level");
|
||||
test_assert(chThdGetSelfX()->realprio == prio + 3, "unexpected real priority level");
|
||||
}
|
||||
|
||||
/* [2.4.4] Restoring original conditions.*/
|
||||
test_set_step(4);
|
||||
{
|
||||
chSysLock();
|
||||
chThdGetSelfX()->prio = prio;
|
||||
chThdGetSelfX()->realprio = prio;
|
||||
chSysUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_002_004 = {
|
||||
"Priority change test with Priority Inheritance",
|
||||
NULL,
|
||||
NULL,
|
||||
test_002_004_execute
|
||||
};
|
||||
#endif /* CH_CFG_USE_MUTEXES */
|
||||
|
||||
/****************************************************************************
|
||||
* Exported data.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Threads Functionality.
|
||||
*/
|
||||
const testcase_t * const test_sequence_002[] = {
|
||||
&test_002_001,
|
||||
&test_002_002,
|
||||
&test_002_003,
|
||||
#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__)
|
||||
&test_002_004,
|
||||
#endif
|
||||
NULL
|
||||
};
|
|
@ -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_002[];
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
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_003 [3] Suspend/Resume
|
||||
*
|
||||
* File: @ref test_sequence_003.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This sequence tests the ChibiOS/RT functionalities related to
|
||||
* threads suspend/resume.
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_003_001
|
||||
* .
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Shared code.
|
||||
****************************************************************************/
|
||||
|
||||
static thread_reference_t tr1;
|
||||
|
||||
static THD_FUNCTION(thread1, p) {
|
||||
|
||||
chThdResumeI(&tr1, MSG_OK);
|
||||
test_emit_token(*(char *)p);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Test cases.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @page test_003_001 [3.1] Suspend and Resume functionality
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The functionality of chThdSuspendTimeoutS() and chThdResumeI() is
|
||||
* tested.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [3.1.1] The function chThdSuspendTimeoutS() is invoked, the thread
|
||||
* is remotely resumed with message @p MSG_OK. On return the message
|
||||
* and the state of the reference are tested.
|
||||
* - [3.1.2] The function chThdSuspendTimeoutS() is invoked, the thread
|
||||
* is not resumed so a timeout must occur. On return the message and
|
||||
* the state of the reference are tested.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_003_001_setup(void) {
|
||||
tr1 = NULL;
|
||||
}
|
||||
|
||||
static void test_003_001_execute(void) {
|
||||
systime_t time;
|
||||
msg_t msg;
|
||||
|
||||
/* [3.1.1] The function chThdSuspendTimeoutS() is invoked, the thread
|
||||
is remotely resumed with message @p MSG_OK. On return the message
|
||||
and the state of the reference are tested.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-1, thread1, "A");
|
||||
chSysLock();
|
||||
msg = chThdSuspendTimeoutS(&tr1, TIME_INFINITE);
|
||||
chSysUnlock();
|
||||
test_assert(NULL == tr1, "not NULL");
|
||||
test_assert(MSG_OK == msg,"wrong returned message");
|
||||
test_wait_threads();
|
||||
}
|
||||
|
||||
/* [3.1.2] The function chThdSuspendTimeoutS() is invoked, the thread
|
||||
is not resumed so a timeout must occur. On return the message and
|
||||
the state of the reference are tested.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
chSysLock();
|
||||
time = chVTGetSystemTimeX();
|
||||
msg = chThdSuspendTimeoutS(&tr1, MS2ST(1000));
|
||||
chSysUnlock();
|
||||
test_assert_time_window(time + MS2ST(1000),
|
||||
time + MS2ST(1000) + 1,
|
||||
"out of time window");
|
||||
test_assert(NULL == tr1, "not NULL");
|
||||
test_assert(MSG_TIMEOUT == msg, "wrong returned message");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_003_001 = {
|
||||
"Suspend and Resume functionality",
|
||||
test_003_001_setup,
|
||||
NULL,
|
||||
test_003_001_execute
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Exported data.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Suspend/Resume.
|
||||
*/
|
||||
const testcase_t * const test_sequence_003[] = {
|
||||
&test_003_001,
|
||||
NULL
|
||||
};
|
|
@ -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_003[];
|
|
@ -0,0 +1,497 @@
|
|||
/*
|
||||
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_004 [4] Counter and Binary Semaphores
|
||||
*
|
||||
* File: @ref test_sequence_004.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This sequence tests the ChibiOS/RT functionalities related to
|
||||
* counter semaphores.
|
||||
*
|
||||
* <h2>Conditions</h2>
|
||||
* This sequence is only executed if the following preprocessor condition
|
||||
* evaluates to true:
|
||||
* - CH_CFG_USE_SEMAPHORES
|
||||
* .
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_004_001
|
||||
* - @subpage test_004_002
|
||||
* - @subpage test_004_003
|
||||
* - @subpage test_004_004
|
||||
* - @subpage test_004_005
|
||||
* - @subpage test_004_006
|
||||
* .
|
||||
*/
|
||||
|
||||
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
||||
|
||||
/****************************************************************************
|
||||
* Shared code.
|
||||
****************************************************************************/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
static semaphore_t sem1;
|
||||
|
||||
static THD_FUNCTION(thread1, p) {
|
||||
|
||||
chSemWait(&sem1);
|
||||
test_emit_token(*(char *)p);
|
||||
}
|
||||
|
||||
static THD_FUNCTION(thread2, p) {
|
||||
|
||||
(void)p;
|
||||
chThdSleepMilliseconds(50);
|
||||
chSysLock();
|
||||
chSemSignalI(&sem1); /* For coverage reasons */
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
static THD_FUNCTION(thread3, p) {
|
||||
|
||||
(void)p;
|
||||
chSemWait(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
}
|
||||
|
||||
static THD_FUNCTION(thread4, p) {
|
||||
|
||||
chBSemSignal((binary_semaphore_t *)p);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Test cases.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @page test_004_001 [4.1] Semaphore primitives, no state change
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Wait, Signal and Reset primitives are tested. The testing thread
|
||||
* does not trigger a state change.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [4.1.1] The function chSemWait() is invoked, after return the
|
||||
* counter and the returned message are tested.
|
||||
* - [4.1.2] The function chSemSignal() is invoked, after return the
|
||||
* counter is tested.
|
||||
* - [4.1.3] The function chSemReset() is invoked, after return the
|
||||
* counter is tested.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_004_001_setup(void) {
|
||||
chSemObjectInit(&sem1, 1);
|
||||
}
|
||||
|
||||
static void test_004_001_teardown(void) {
|
||||
chSemReset(&sem1, 0);
|
||||
}
|
||||
|
||||
static void test_004_001_execute(void) {
|
||||
|
||||
/* [4.1.1] The function chSemWait() is invoked, after return the
|
||||
counter and the returned message are tested.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
msg_t msg;
|
||||
|
||||
msg = chSemWait(&sem1);
|
||||
test_assert_lock(chSemGetCounterI(&sem1) == 0, "wrong counter value");
|
||||
test_assert(MSG_OK == msg, "wrong returned message");
|
||||
}
|
||||
|
||||
/* [4.1.2] The function chSemSignal() is invoked, after return the
|
||||
counter is tested.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
chSemSignal(&sem1);
|
||||
test_assert_lock(chSemGetCounterI(&sem1) == 1, "wrong counter value");
|
||||
}
|
||||
|
||||
/* [4.1.3] The function chSemReset() is invoked, after return the
|
||||
counter is tested.*/
|
||||
test_set_step(3);
|
||||
{
|
||||
chSemReset(&sem1, 2);
|
||||
test_assert_lock(chSemGetCounterI(&sem1) == 2, "wrong counter value");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_004_001 = {
|
||||
"Semaphore primitives, no state change",
|
||||
test_004_001_setup,
|
||||
test_004_001_teardown,
|
||||
test_004_001_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_004_002 [4.2] Semaphore enqueuing test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* Five threads with randomized priorities are enqueued to a semaphore
|
||||
* then awakened one at time. The test expects that the threads reach
|
||||
* their goal in FIFO order or priority order depending on the @p
|
||||
* CH_CFG_USE_SEMAPHORES_PRIORITY configuration setting.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [4.2.1] Five threads are created with mixed priority levels (not
|
||||
* increasing nor decreasing). Threads enqueue on a semaphore
|
||||
* initialized to zero.
|
||||
* - [4.2.2] The semaphore is signaled 5 times. The thread activation
|
||||
* sequence is tested.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_004_002_setup(void) {
|
||||
chSemObjectInit(&sem1, 0);
|
||||
}
|
||||
|
||||
static void test_004_002_execute(void) {
|
||||
|
||||
/* [4.2.1] Five threads are created with mixed priority levels (not
|
||||
increasing nor decreasing). Threads enqueue on a semaphore
|
||||
initialized to zero.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+5, thread1, "A");
|
||||
threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()+1, thread1, "B");
|
||||
threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()+3, thread1, "C");
|
||||
threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()+4, thread1, "D");
|
||||
threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()+2, thread1, "E");
|
||||
}
|
||||
|
||||
/* [4.2.2] The semaphore is signaled 5 times. The thread activation
|
||||
sequence is tested.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
chSemSignal(&sem1);
|
||||
test_wait_threads();
|
||||
#if CH_CFG_USE_SEMAPHORES_PRIORITY
|
||||
test_assert_sequence("ADCEB", "invalid sequence");
|
||||
#else
|
||||
test_assert_sequence("ABCDE", "invalid sequence");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_004_002 = {
|
||||
"Semaphore enqueuing test",
|
||||
test_004_002_setup,
|
||||
NULL,
|
||||
test_004_002_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_004_003 [4.3] Semaphore timeout test
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The three possible semaphore waiting modes (do not wait, wait with
|
||||
* timeout, wait without timeout) are explored. The test expects that
|
||||
* the semaphore wait function returns the correct value in each of the
|
||||
* above scenario and that the semaphore structure status is correct
|
||||
* after each operation.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [4.3.1] Testing special case TIME_IMMEDIATE.
|
||||
* - [4.3.2] Testing non-timeout condition.
|
||||
* - [4.3.3] Testing timeout condition.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_004_003_setup(void) {
|
||||
chSemObjectInit(&sem1, 0);
|
||||
}
|
||||
|
||||
static void test_004_003_execute(void) {
|
||||
unsigned i;
|
||||
systime_t target_time;
|
||||
msg_t msg;
|
||||
|
||||
/* [4.3.1] Testing special case TIME_IMMEDIATE.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
msg = chSemWaitTimeout(&sem1, TIME_IMMEDIATE);
|
||||
test_assert(msg == MSG_TIMEOUT, "wrong wake-up message");
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");
|
||||
}
|
||||
|
||||
/* [4.3.2] Testing non-timeout condition.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX() - 1,
|
||||
thread2, 0);
|
||||
msg = chSemWaitTimeout(&sem1, MS2ST(500));
|
||||
test_wait_threads();
|
||||
test_assert(msg == MSG_OK, "wrong wake-up message");
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");
|
||||
}
|
||||
|
||||
/* [4.3.3] Testing timeout condition.*/
|
||||
test_set_step(3);
|
||||
{
|
||||
target_time = test_wait_tick() + MS2ST(5 * 50);
|
||||
for (i = 0; i < 5; i++) {
|
||||
test_emit_token('A' + i);
|
||||
msg = chSemWaitTimeout(&sem1, MS2ST(50));
|
||||
test_assert(msg == MSG_TIMEOUT, "wrong wake-up message");
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");
|
||||
}
|
||||
test_assert_sequence("ABCDE", "invalid sequence");
|
||||
test_assert_time_window(target_time, target_time + ALLOWED_DELAY,
|
||||
"out of time window");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_004_003 = {
|
||||
"Semaphore timeout test",
|
||||
test_004_003_setup,
|
||||
NULL,
|
||||
test_004_003_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_004_004 [4.4] Testing chSemAddCounterI() functionality
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The functon is tested by waking up a thread then the semaphore
|
||||
* counter value is tested.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [4.4.1] A thread is created, it goes to wait on the semaphore.
|
||||
* - [4.4.2] The semaphore counter is increased by two, it is then
|
||||
* tested to be one, the thread must have completed.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_004_004_setup(void) {
|
||||
chSemObjectInit(&sem1, 0);
|
||||
}
|
||||
|
||||
static void test_004_004_execute(void) {
|
||||
|
||||
/* [4.4.1] A thread is created, it goes to wait on the semaphore.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, thread1, "A");
|
||||
}
|
||||
|
||||
/* [4.4.2] The semaphore counter is increased by two, it is then
|
||||
tested to be one, the thread must have completed.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
chSysLock();
|
||||
chSemAddCounterI(&sem1, 2);
|
||||
chSchRescheduleS();
|
||||
chSysUnlock();
|
||||
test_wait_threads();
|
||||
test_assert_lock(chSemGetCounterI(&sem1) == 1, "invalid counter");
|
||||
test_assert_sequence("A", "invalid sequence");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_004_004 = {
|
||||
"Testing chSemAddCounterI() functionality",
|
||||
test_004_004_setup,
|
||||
NULL,
|
||||
test_004_004_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_004_005 [4.5] Testing chSemWaitSignal() functionality
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This test case explicitly addresses the @p chSemWaitSignal()
|
||||
* function. A thread is created that performs a wait and a signal
|
||||
* operations. The tester thread is awakened from an atomic wait/signal
|
||||
* operation. The test expects that the semaphore wait function returns
|
||||
* the correct value in each of the above scenario and that the
|
||||
* semaphore structure status is correct after each operation.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [4.5.1] An higher priority thread is created that performs
|
||||
* non-atomical wait and signal operations on a semaphore.
|
||||
* - [4.5.2] The function chSemSignalWait() is invoked by specifying
|
||||
* the same semaphore for the wait and signal phases. The counter
|
||||
* value must be one on exit.
|
||||
* - [4.5.3] The function chSemSignalWait() is invoked again by
|
||||
* specifying the same semaphore for the wait and signal phases. The
|
||||
* counter value must be one on exit.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_004_005_setup(void) {
|
||||
chSemObjectInit(&sem1, 0);
|
||||
}
|
||||
|
||||
static void test_004_005_execute(void) {
|
||||
|
||||
/* [4.5.1] An higher priority thread is created that performs
|
||||
non-atomical wait and signal operations on a semaphore.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()+1, thread3, 0);
|
||||
}
|
||||
|
||||
/* [4.5.2] The function chSemSignalWait() is invoked by specifying
|
||||
the same semaphore for the wait and signal phases. The counter
|
||||
value must be one on exit.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
chSemSignalWait(&sem1, &sem1);
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");
|
||||
}
|
||||
|
||||
/* [4.5.3] The function chSemSignalWait() is invoked again by
|
||||
specifying the same semaphore for the wait and signal phases. The
|
||||
counter value must be one on exit.*/
|
||||
test_set_step(3);
|
||||
{
|
||||
chSemSignalWait(&sem1, &sem1);
|
||||
test_assert(queue_isempty(&sem1.queue), "queue not empty");
|
||||
test_assert(sem1.cnt == 0, "counter not zero");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_004_005 = {
|
||||
"Testing chSemWaitSignal() functionality",
|
||||
test_004_005_setup,
|
||||
NULL,
|
||||
test_004_005_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_004_006 [4.6] Testing Binary Semaphores special case
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This test case tests the binary semaphores functionality. The test
|
||||
* both checks the binary semaphore status and the expected status of
|
||||
* the underlying counting semaphore.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [4.6.1] Creating a binary semaphore in "taken" state, the state is
|
||||
* checked.
|
||||
* - [4.6.2] Resetting the binary semaphore in "taken" state, the state
|
||||
* must not change.
|
||||
* - [4.6.3] Starting a signaler thread at a lower priority.
|
||||
* - [4.6.4] Waiting for the binary semaphore to be signaled, the
|
||||
* semaphore is expected to be taken.
|
||||
* - [4.6.5] Signaling the binary semaphore, checking the binary
|
||||
* semaphore state to be "not taken" and the underlying counter
|
||||
* semaphore counter to be one.
|
||||
* - [4.6.6] Signaling the binary semaphore again, the internal state
|
||||
* must not change from "not taken".
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_004_006_execute(void) {
|
||||
binary_semaphore_t bsem;
|
||||
msg_t msg;
|
||||
|
||||
/* [4.6.1] Creating a binary semaphore in "taken" state, the state is
|
||||
checked.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
chBSemObjectInit(&bsem, true);
|
||||
test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken");
|
||||
}
|
||||
|
||||
/* [4.6.2] Resetting the binary semaphore in "taken" state, the state
|
||||
must not change.*/
|
||||
test_set_step(2);
|
||||
{
|
||||
chBSemReset(&bsem, true);
|
||||
test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken");
|
||||
}
|
||||
|
||||
/* [4.6.3] Starting a signaler thread at a lower priority.*/
|
||||
test_set_step(3);
|
||||
{
|
||||
threads[0] = chThdCreateStatic(wa[0], WA_SIZE,
|
||||
chThdGetPriorityX()-1, thread4, &bsem);
|
||||
}
|
||||
|
||||
/* [4.6.4] Waiting for the binary semaphore to be signaled, the
|
||||
semaphore is expected to be taken.*/
|
||||
test_set_step(4);
|
||||
{
|
||||
msg = chBSemWait(&bsem);
|
||||
test_assert_lock(chBSemGetStateI(&bsem) == true, "not taken");
|
||||
test_assert(msg == MSG_OK, "unexpected message");
|
||||
}
|
||||
|
||||
/* [4.6.5] Signaling the binary semaphore, checking the binary
|
||||
semaphore state to be "not taken" and the underlying counter
|
||||
semaphore counter to be one.*/
|
||||
test_set_step(5);
|
||||
{
|
||||
chBSemSignal(&bsem);
|
||||
test_assert_lock(chBSemGetStateI(&bsem) ==false, "still taken");
|
||||
test_assert_lock(chSemGetCounterI(&bsem.sem) == 1, "unexpected counter");
|
||||
}
|
||||
|
||||
/* [4.6.6] Signaling the binary semaphore again, the internal state
|
||||
must not change from "not taken".*/
|
||||
test_set_step(6);
|
||||
{
|
||||
chBSemSignal(&bsem);
|
||||
test_assert_lock(chBSemGetStateI(&bsem) == false, "taken");
|
||||
test_assert_lock(chSemGetCounterI(&bsem.sem) == 1, "unexpected counter");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_004_006 = {
|
||||
"Testing Binary Semaphores special case",
|
||||
NULL,
|
||||
NULL,
|
||||
test_004_006_execute
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Exported data.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Counter and Binary Semaphores.
|
||||
*/
|
||||
const testcase_t * const test_sequence_004[] = {
|
||||
&test_004_001,
|
||||
&test_004_002,
|
||||
&test_004_003,
|
||||
&test_004_004,
|
||||
&test_004_005,
|
||||
&test_004_006,
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* CH_CFG_USE_SEMAPHORES */
|
|
@ -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_004[];
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
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_005 [5] Mutexes, Condition Variables and Priority Inheritance
|
||||
*
|
||||
* File: @ref test_sequence_005.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This sequence tests the ChibiOS/RT functionalities related to
|
||||
* mutexes, condition variables and priority inheritance algorithm.
|
||||
*
|
||||
* <h2>Conditions</h2>
|
||||
* This sequence is only executed if the following preprocessor condition
|
||||
* evaluates to true:
|
||||
* - CH_CFG_USE_MUTEXES
|
||||
* .
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* No test cases defined in the test sequence.
|
||||
*/
|
||||
|
||||
#if (CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__)
|
||||
|
||||
/****************************************************************************
|
||||
* Shared code.
|
||||
****************************************************************************/
|
||||
|
||||
static MUTEX_DECL(m1);
|
||||
static MUTEX_DECL(m2);
|
||||
#if CH_CFG_USE_CONDVARS || defined(__DOXYGEN__)
|
||||
static CONDVAR_DECL(c1);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Test cases.
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Exported data.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Mutexes, Condition Variables and Priority Inheritance.
|
||||
*/
|
||||
const testcase_t * const test_sequence_005[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* CH_CFG_USE_MUTEXES */
|
|
@ -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_005[];
|
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
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_006 [6] Mailboxes
|
||||
*
|
||||
* File: @ref test_sequence_006.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* 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_MAILBOXES
|
||||
* .
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_006_001
|
||||
* - @subpage test_006_002
|
||||
* - @subpage test_006_003
|
||||
* .
|
||||
*/
|
||||
|
||||
#if (CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__)
|
||||
|
||||
/****************************************************************************
|
||||
* Shared code.
|
||||
****************************************************************************/
|
||||
|
||||
#define MB_SIZE 4
|
||||
|
||||
static msg_t mb_buffer[MB_SIZE];
|
||||
static MAILBOX_DECL(mb1, mb_buffer, MB_SIZE);
|
||||
|
||||
/****************************************************************************
|
||||
* Test cases.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @page test_006_001 [6.1] Mailbox normal API, non-blocking tests
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The mailbox normal API is tested without triggering blocking
|
||||
* conditions.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [6.1.1] Testing the mailbox size.
|
||||
* - [6.1.2] Resetting the mailbox, conditions are checked, no errors
|
||||
* expected.
|
||||
* - [6.1.3] Filling the mailbox using chMBPost() and chMBPostAhead()
|
||||
* once, no errors expected.
|
||||
* - [6.1.4] Testing intermediate conditions. Data pointers must be
|
||||
* aligned, semaphore counters are checked.
|
||||
* - [6.1.5] Emptying the mailbox using chMBFetch(), no errors
|
||||
* expected.
|
||||
* - [6.1.6] Posting and then fetching one more message, no errors
|
||||
* expected.
|
||||
* - [6.1.7] Testing final conditions. Data pointers must be aligned to
|
||||
* buffer start, semaphore counters are checked.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_006_001_setup(void) {
|
||||
chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
|
||||
}
|
||||
|
||||
static void test_006_001_teardown(void) {
|
||||
chMBReset(&mb1);
|
||||
}
|
||||
|
||||
static void test_006_001_execute(void) {
|
||||
msg_t msg1, msg2;
|
||||
unsigned i;
|
||||
|
||||
/* [6.1.1] Testing the mailbox size.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size");
|
||||
}
|
||||
|
||||
/* [6.1.2] Resetting the mailbox, conditions are checked, no errors
|
||||
expected.*/
|
||||
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");
|
||||
}
|
||||
|
||||
/* [6.1.3] Filling the mailbox using chMBPost() and chMBPostAhead()
|
||||
once, no errors expected.*/
|
||||
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");
|
||||
}
|
||||
|
||||
/* [6.1.4] Testing intermediate conditions. Data pointers must be
|
||||
aligned, semaphore counters are checked.*/
|
||||
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");
|
||||
}
|
||||
|
||||
/* [6.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");
|
||||
}
|
||||
|
||||
/* [6.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");
|
||||
}
|
||||
|
||||
/* [6.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");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_006_001 = {
|
||||
"Mailbox normal API, non-blocking tests",
|
||||
test_006_001_setup,
|
||||
test_006_001_teardown,
|
||||
test_006_001_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_006_002 [6.2] Mailbox I-Class API, non-blocking tests
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The mailbox I-Class API is tested without triggering blocking
|
||||
* conditions.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [6.2.1] Testing the mailbox size.
|
||||
* - [6.2.2] Resetting the mailbox, conditions are checked, no errors
|
||||
* expected.
|
||||
* - [6.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI()
|
||||
* once, no errors expected.
|
||||
* - [6.2.4] Testing intermediate conditions. Data pointers must be
|
||||
* aligned, semaphore counters are checked.
|
||||
* - [6.2.5] Emptying the mailbox using chMBFetchI(), no errors
|
||||
* expected.
|
||||
* - [6.2.6] Posting and then fetching one more message, no errors
|
||||
* expected.
|
||||
* - [6.2.7] Testing final conditions. Data pointers must be aligned to
|
||||
* buffer start, semaphore counters are checked.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_006_002_setup(void) {
|
||||
chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
|
||||
}
|
||||
|
||||
static void test_006_002_teardown(void) {
|
||||
chMBReset(&mb1);
|
||||
}
|
||||
|
||||
static void test_006_002_execute(void) {
|
||||
msg_t msg1, msg2;
|
||||
unsigned i;
|
||||
|
||||
/* [6.2.1] Testing the mailbox size.*/
|
||||
test_set_step(1);
|
||||
{
|
||||
test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size");
|
||||
}
|
||||
|
||||
/* [6.2.2] Resetting the mailbox, conditions are checked, no errors
|
||||
expected.*/
|
||||
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");
|
||||
}
|
||||
|
||||
/* [6.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI()
|
||||
once, no errors expected.*/
|
||||
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");
|
||||
}
|
||||
|
||||
/* [6.2.4] Testing intermediate conditions. Data pointers must be
|
||||
aligned, semaphore counters are checked.*/
|
||||
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");
|
||||
}
|
||||
|
||||
/* [6.2.5] Emptying the mailbox using chMBFetchI(), no errors
|
||||
expected.*/
|
||||
test_set_step(5);
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
/* [6.2.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");
|
||||
}
|
||||
|
||||
/* [6.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_006_002 = {
|
||||
"Mailbox I-Class API, non-blocking tests",
|
||||
test_006_002_setup,
|
||||
test_006_002_teardown,
|
||||
test_006_002_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_006_003 [6.3] Mailbox timeouts
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The mailbox API is tested for timeouts.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [6.3.1] Filling the mailbox.
|
||||
* - [6.3.2] Testing chMBPost(), chMBPostI(), chMBPostAhead() and
|
||||
* chMBPostAheadI() timeout.
|
||||
* - [6.3.3] Resetting the mailbox.
|
||||
* - [6.3.4] Testing chMBFetch() and chMBFetchI() timeout.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_006_003_setup(void) {
|
||||
chMBObjectInit(&mb1, mb_buffer, MB_SIZE);
|
||||
}
|
||||
|
||||
static void test_006_003_teardown(void) {
|
||||
chMBReset(&mb1);
|
||||
}
|
||||
|
||||
static void test_006_003_execute(void) {
|
||||
msg_t msg1, msg2;
|
||||
unsigned i;
|
||||
|
||||
/* [6.3.1] Filling the mailbox.*/
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/* [6.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");
|
||||
}
|
||||
|
||||
/* [6.3.3] Resetting the mailbox.*/
|
||||
test_set_step(3);
|
||||
{
|
||||
chMBReset(&mb1);
|
||||
}
|
||||
|
||||
/* [6.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_006_003 = {
|
||||
"Mailbox timeouts",
|
||||
test_006_003_setup,
|
||||
test_006_003_teardown,
|
||||
test_006_003_execute
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Exported data.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Mailboxes.
|
||||
*/
|
||||
const testcase_t * const test_sequence_006[] = {
|
||||
&test_006_001,
|
||||
&test_006_002,
|
||||
&test_006_003,
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* CH_CFG_USE_MAILBOXES */
|
|
@ -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_006[];
|
|
@ -0,0 +1,290 @@
|
|||
/*
|
||||
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_007 [7] Memory Pools
|
||||
*
|
||||
* File: @ref test_sequence_007.c
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* This sequence tests the ChibiOS/RT functionalities related to memory
|
||||
* pools.
|
||||
*
|
||||
* <h2>Conditions</h2>
|
||||
* This sequence is only executed if the following preprocessor condition
|
||||
* evaluates to true:
|
||||
* - CH_CFG_USE_MEMPOOLS
|
||||
* .
|
||||
*
|
||||
* <h2>Test Cases</h2>
|
||||
* - @subpage test_007_001
|
||||
* - @subpage test_007_002
|
||||
* - @subpage test_007_003
|
||||
* .
|
||||
*/
|
||||
|
||||
#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
|
||||
|
||||
/****************************************************************************
|
||||
* Shared code.
|
||||
****************************************************************************/
|
||||
|
||||
#define MEMORY_POOL_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;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Test cases.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @page test_007_001 [7.1] Loading and emptying a memory pool
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The memory pool functionality is tested by loading and emptying it,
|
||||
* all conditions are tested.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [7.1.1] Adding the objects to the pool using chPoolLoadArray().
|
||||
* - [7.1.2] Emptying the pool using chPoolAlloc().
|
||||
* - [7.1.3] Now must be empty.
|
||||
* - [7.1.4] Adding the objects to the pool using chPoolFree().
|
||||
* - [7.1.5] Emptying the pool using chPoolAlloc() again.
|
||||
* - [7.1.6] Now must be empty again.
|
||||
* - [7.1.7] Covering the case where a provider is unable to return
|
||||
* more memory.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_007_001_setup(void) {
|
||||
chPoolObjectInit(&mp1, sizeof (uint32_t), NULL);
|
||||
}
|
||||
|
||||
static void test_007_001_execute(void) {
|
||||
unsigned i;
|
||||
|
||||
/* [7.1.1] Adding the objects to the pool using chPoolLoadArray().*/
|
||||
test_set_step(1);
|
||||
{
|
||||
chPoolLoadArray(&mp1, objects, MEMORY_POOL_SIZE);
|
||||
}
|
||||
|
||||
/* [7.1.2] Emptying the pool using chPoolAlloc().*/
|
||||
test_set_step(2);
|
||||
{
|
||||
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
||||
test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
|
||||
}
|
||||
|
||||
/* [7.1.3] Now must be empty.*/
|
||||
test_set_step(3);
|
||||
{
|
||||
test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
|
||||
}
|
||||
|
||||
/* [7.1.4] Adding the objects to the pool using chPoolFree().*/
|
||||
test_set_step(4);
|
||||
{
|
||||
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
||||
chPoolFree(&mp1, &objects[i]);
|
||||
}
|
||||
|
||||
/* [7.1.5] Emptying the pool using chPoolAlloc() again.*/
|
||||
test_set_step(5);
|
||||
{
|
||||
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
||||
test_assert(chPoolAlloc(&mp1) != NULL, "list empty");
|
||||
}
|
||||
|
||||
/* [7.1.6] Now must be empty again.*/
|
||||
test_set_step(6);
|
||||
{
|
||||
test_assert(chPoolAlloc(&mp1) == NULL, "list not empty");
|
||||
}
|
||||
|
||||
/* [7.1.7] Covering the case where a provider is unable to return
|
||||
more memory.*/
|
||||
test_set_step(7);
|
||||
{
|
||||
chPoolObjectInit(&mp1, sizeof (uint32_t), null_provider);
|
||||
test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");
|
||||
}
|
||||
}
|
||||
|
||||
static const testcase_t test_007_001 = {
|
||||
"Loading and emptying a memory pool",
|
||||
test_007_001_setup,
|
||||
NULL,
|
||||
test_007_001_execute
|
||||
};
|
||||
|
||||
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_007_002 [7.2] Loading and emptying a guarded memory pool without waiting
|
||||
*
|
||||
* <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
|
||||
* .
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [7.2.1] Adding the objects to the pool using
|
||||
* chGuardedPoolLoadArray().
|
||||
* - [7.2.2] Emptying the pool using chGuardedPoolAllocTimeout().
|
||||
* - [7.2.3] Now must be empty.
|
||||
* - [7.2.4] Adding the objects to the pool using chGuardedPoolFree().
|
||||
* - [7.2.5] Emptying the pool using chGuardedPoolAllocTimeout() again.
|
||||
* - [7.2.6] Now must be empty again.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_007_002_setup(void) {
|
||||
chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
|
||||
}
|
||||
|
||||
static void test_007_002_execute(void) {
|
||||
unsigned i;
|
||||
|
||||
/* [7.2.1] Adding the objects to the pool using
|
||||
chGuardedPoolLoadArray().*/
|
||||
test_set_step(1);
|
||||
{
|
||||
chGuardedPoolLoadArray(&gmp1, objects, MEMORY_POOL_SIZE);
|
||||
}
|
||||
|
||||
/* [7.2.2] Emptying the pool using chGuardedPoolAllocTimeout().*/
|
||||
test_set_step(2);
|
||||
{
|
||||
for (i = 0; i < MEMORY_POOL_SIZE; i++)
|
||||
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty");
|
||||
}
|
||||
|
||||
/* [7.2.3] Now must be empty.*/
|
||||
test_set_step(3);
|
||||
{
|
||||
test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty");
|
||||
}
|
||||
|
||||
/* [7.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]);
|
||||
}
|
||||
|
||||
/* [7.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");
|
||||
}
|
||||
|
||||
/* [7.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_007_002 = {
|
||||
"Loading and emptying a guarded memory pool without waiting",
|
||||
test_007_002_setup,
|
||||
NULL,
|
||||
test_007_002_execute
|
||||
};
|
||||
#endif /* CH_CFG_USE_SEMAPHORES */
|
||||
|
||||
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @page test_007_003 [7.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>
|
||||
* - [7.3.1] Trying to allocate with 100mS timeout, must fail because
|
||||
* the pool is empty.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_007_003_setup(void) {
|
||||
chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t));
|
||||
}
|
||||
|
||||
static void test_007_003_execute(void) {
|
||||
|
||||
/* [7.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_007_003 = {
|
||||
"Guarded Memory Pools timeout",
|
||||
test_007_003_setup,
|
||||
NULL,
|
||||
test_007_003_execute
|
||||
};
|
||||
#endif /* CH_CFG_USE_SEMAPHORES */
|
||||
|
||||
/****************************************************************************
|
||||
* Exported data.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Memory Pools.
|
||||
*/
|
||||
const testcase_t * const test_sequence_007[] = {
|
||||
&test_007_001,
|
||||
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
||||
&test_007_002,
|
||||
#endif
|
||||
#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
|
||||
&test_007_003,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* CH_CFG_USE_MEMPOOLS */
|
|
@ -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_007[];
|
|
@ -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_008 [8] Memory Heaps
|
||||
*
|
||||
* File: @ref test_sequence_008.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_008_001
|
||||
* - @subpage test_008_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_008_001 [8.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>
|
||||
* - [8.1.1] Testing initial conditions, the heap must not be
|
||||
* fragmented and one free block present.
|
||||
* - [8.1.2] Trying to allocate an block bigger than available space,
|
||||
* an error is expected.
|
||||
* - [8.1.3] Single block allocation using chHeapAlloc() then the block
|
||||
* is freed using chHeapFree(), must not fail.
|
||||
* - [8.1.4] Using chHeapStatus() to assess the heap state. There must
|
||||
* be at least one free block of sufficient size.
|
||||
* - [8.1.5] Allocating then freeing in the same order.
|
||||
* - [8.1.6] Allocating then freeing in reverse order.
|
||||
* - [8.1.7] Small fragments handling. Checking the behavior when
|
||||
* allocating blocks with size not multiple of alignment unit.
|
||||
* - [8.1.8] Skipping a fragment, the first fragment in the list is too
|
||||
* small so the allocator must pick the second one.
|
||||
* - [8.1.9] Allocating the whole available space.
|
||||
* - [8.1.10] Testing final conditions. The heap geometry must be the
|
||||
* same than the one registered at beginning.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_008_001_setup(void) {
|
||||
chHeapObjectInit(&test_heap, myheap, sizeof(myheap));
|
||||
}
|
||||
|
||||
static void test_008_001_execute(void) {
|
||||
void *p1, *p2, *p3;
|
||||
size_t n, sz;
|
||||
|
||||
/* [8.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");
|
||||
}
|
||||
|
||||
/* [8.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");
|
||||
}
|
||||
|
||||
/* [8.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);
|
||||
}
|
||||
|
||||
/* [8.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");
|
||||
}
|
||||
|
||||
/* [8.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");
|
||||
}
|
||||
|
||||
/* [8.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");
|
||||
}
|
||||
|
||||
/* [8.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");
|
||||
}
|
||||
|
||||
/* [8.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");
|
||||
}
|
||||
|
||||
/* [8.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);
|
||||
}
|
||||
|
||||
/* [8.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_008_001 = {
|
||||
"Allocation and fragmentation",
|
||||
test_008_001_setup,
|
||||
NULL,
|
||||
test_008_001_execute
|
||||
};
|
||||
|
||||
/**
|
||||
* @page test_008_002 [8.2] Default Heap
|
||||
*
|
||||
* <h2>Description</h2>
|
||||
* The default heap is pre-allocated in the system. We test base
|
||||
* functionality.
|
||||
*
|
||||
* <h2>Test Steps</h2>
|
||||
* - [8.2.1] Single block allocation using chHeapAlloc() then the block
|
||||
* is freed using chHeapFree(), must not fail.
|
||||
* - [8.2.2] Testing allocation failure.
|
||||
* .
|
||||
*/
|
||||
|
||||
static void test_008_002_execute(void) {
|
||||
void *p1;
|
||||
size_t total_size, largest_size;
|
||||
|
||||
/* [8.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);
|
||||
}
|
||||
|
||||
/* [8.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_008_002 = {
|
||||
"Default Heap",
|
||||
NULL,
|
||||
NULL,
|
||||
test_008_002_execute
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Exported data.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Memory Heaps.
|
||||
*/
|
||||
const testcase_t * const test_sequence_008[] = {
|
||||
&test_008_001,
|
||||
&test_008_002,
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* CH_CFG_USE_HEAP */
|
|
@ -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_008[];
|
Loading…
Reference in New Issue