From be0fa896d4994ea9d8882fd88814452792eee7a9 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Wed, 28 Aug 2019 09:04:03 +0000 Subject: [PATCH] Test code for objects caches, to be enhanced. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12959 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/oslib/include/chobjcaches.h | 30 +- test/oslib/configuration.xml | 241 ++++++ test/oslib/oslib_test.mk | 3 +- test/oslib/source/test/oslib_test_root.c | 10 +- test/oslib/source/test/oslib_test_root.h | 1 + .../source/test/oslib_test_sequence_001.c | 3 + .../source/test/oslib_test_sequence_002.c | 19 + .../source/test/oslib_test_sequence_003.c | 16 + .../source/test/oslib_test_sequence_004.c | 349 ++++---- .../source/test/oslib_test_sequence_005.c | 315 ++++--- .../source/test/oslib_test_sequence_006.c | 801 ++++------------- .../source/test/oslib_test_sequence_007.c | 817 ++++++++++++++++++ .../source/test/oslib_test_sequence_007.h | 27 + 13 files changed, 1649 insertions(+), 983 deletions(-) create mode 100644 test/oslib/source/test/oslib_test_sequence_007.c create mode 100644 test/oslib/source/test/oslib_test_sequence_007.h diff --git a/os/oslib/include/chobjcaches.h b/os/oslib/include/chobjcaches.h index db225d268..135da051d 100644 --- a/os/oslib/include/chobjcaches.h +++ b/os/oslib/include/chobjcaches.h @@ -184,11 +184,11 @@ struct ch_oc_object { * @note This pointer can be used to refer to external buffers, * @p chCacheObjectInit() initializes it to @p NULL. */ - void *dptr; + void *dptr; /** * @brief Embedded data as an open array. */ - uint8_t dbuf[]; + uint8_t dbuf[]; }; /** @@ -275,6 +275,32 @@ extern "C" { /* Module inline functions. */ /*===========================================================================*/ +/** + * @brief Releases an object into the cache. + * @note This function gives a meaning to the following flags: + * - @p OC_FLAG_INLRU must be cleared. + * - @p OC_FLAG_INHASH must be set. + * - @p OC_FLAG_SHARED must be cleared. + * - @p OC_FLAG_NOTSYNC invalidates the object and queues it on + * the LRU tail. + * - @p OC_FLAG_LAZYWRITE is ignored and kept, a write will occur + * when the object is removed from the LRU list (lazy write). + * . + * + * @param[in] ocp pointer to the @p objects_cache_t structure + * @param[in] objp pointer to the @p oc_object_t structure + * + * @api + */ +static inline void chCacheReleaseObject(objects_cache_t *ocp, + oc_object_t *objp) { + + chSysLock(); + chCacheReleaseObjectI(ocp, objp); + chSchRescheduleS(); + chSysUnlock(); +} + #endif /* CH_CFG_USE_OBJ_CACHES == TRUE */ #endif /* CHOBJCACHES_H */ diff --git a/test/oslib/configuration.xml b/test/oslib/configuration.xml index 7f907c531..6f4bafc83 100644 --- a/test/oslib/configuration.xml +++ b/test/oslib/configuration.xml @@ -1008,6 +1008,247 @@ test_assert((pipe1.rdptr == pipe1.wrptr) && + + + Internal Tests + + + Objects Caches + + + This sequence tests the ChibiOS library functionalities related to Objects Caches. + + + CH_CFG_USE_OBJ_CACHES + + + + +#define SIZE_OBJECTS 16 +#define NUM_OBJECTS 4 +#define NUM_HASH_ENTRIES (NUM_OBJECTS * 2) + +/* Cached object type used for test.*/ +typedef struct { + oc_object_t header; + uint8_t data[SIZE_OBJECTS]; +} cached_object_t; + +static oc_hash_header_t hash_headers[NUM_HASH_ENTRIES]; +static cached_object_t objects[NUM_OBJECTS]; +static objects_cache_t cache1; + +static bool obj_read(objects_cache_t *ocp, + oc_object_t *objp, + bool async) { + + test_emit_token('a' + objp->obj_key); + + objp->obj_flags &= ~OC_FLAG_NOTSYNC; + + if (async) { + chCacheReleaseObject(ocp, objp); + } + + return false; +} + +static bool obj_write(objects_cache_t *ocp, + oc_object_t *objp, + bool async) { + (void)ocp; + (void)async; + + test_emit_token('A' + objp->obj_key); + + return false; +}]]> + + + + + Cache initialization. + + + A cache object is initialized, some initial conditions are checked. + + + + + + + + + + + + + + + + + + + + Cache initialization. + + + + + + + + + + + Getting and releasing objects without initialization. + + + + + + obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) != 0U, "should not be in sync"); + + chCacheReleaseObject(&cache1, objp); +} + +test_assert_sequence("", "unexpected tokens"); +]]> + + + + + Getting and releasing objects with synchronous initialization. + + + + + + obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) != 0U, "in sync"); + + error = chCacheReadObject(&cache1, objp, false); + + test_assert(error == false, "returned error"); + test_assert((objp->obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) == 0U, "not in sync"); + + chCacheReleaseObject(&cache1, objp); +} + +test_assert_sequence("abcdefgh", "unexpected tokens"); +]]> + + + + + Getting and releasing objects with asynchronous initialization. + + + + + + obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) != 0U, "in sync"); + + error = chCacheReadObject(&cache1, objp, true); + + test_assert(error == false, "returned error"); + + objp = chCacheGetObject(&cache1, 0U, i); + + test_assert((objp->obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) == 0U, "not in sync"); + + chCacheReleaseObject(&cache1, objp); +} + +test_assert_sequence("abcdefgh", "unexpected tokens"); +]]> + + + + + Checking cached objects. + + + + + + obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) == 0U, "not in sync"); + + chCacheReleaseObject(&cache1, objp); +} + +test_assert_sequence("", "unexpected tokens"); +]]> + + + + + Checking non-cached objects. + + + + + + obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) != 0U, "in sync"); + + chCacheReleaseObject(&cache1, objp); +} + +test_assert_sequence("", "unexpected tokens"); +]]> + + + + + + Internal Tests diff --git a/test/oslib/oslib_test.mk b/test/oslib/oslib_test.mk index cf085f10d..e64d3be18 100644 --- a/test/oslib/oslib_test.mk +++ b/test/oslib/oslib_test.mk @@ -5,7 +5,8 @@ TESTSRC += ${CHIBIOS}/test/oslib/source/test/oslib_test_root.c \ ${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_003.c \ ${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_004.c \ ${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_005.c \ - ${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_006.c + ${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_006.c \ + ${CHIBIOS}/test/oslib/source/test/oslib_test_sequence_007.c # Required include directories TESTINC += ${CHIBIOS}/test/oslib/source/test diff --git a/test/oslib/source/test/oslib_test_root.c b/test/oslib/source/test/oslib_test_root.c index e167e29a0..a3dd9887f 100644 --- a/test/oslib/source/test/oslib_test_root.c +++ b/test/oslib/source/test/oslib_test_root.c @@ -27,6 +27,7 @@ * - @subpage oslib_test_sequence_004 * - @subpage oslib_test_sequence_005 * - @subpage oslib_test_sequence_006 + * - @subpage oslib_test_sequence_007 * . */ @@ -55,14 +56,17 @@ const testsequence_t * const oslib_test_suite_array[] = { #if (CH_CFG_USE_PIPES) || defined(__DOXYGEN__) &oslib_test_sequence_003, #endif -#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) +#if (CH_CFG_USE_OBJ_CACHES) || defined(__DOXYGEN__) &oslib_test_sequence_004, #endif -#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) +#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) &oslib_test_sequence_005, #endif -#if ((CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE)) || defined(__DOXYGEN__) +#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) &oslib_test_sequence_006, +#endif +#if ((CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE)) || defined(__DOXYGEN__) + &oslib_test_sequence_007, #endif NULL }; diff --git a/test/oslib/source/test/oslib_test_root.h b/test/oslib/source/test/oslib_test_root.h index b81cb93d1..d31bbb806 100644 --- a/test/oslib/source/test/oslib_test_root.h +++ b/test/oslib/source/test/oslib_test_root.h @@ -30,6 +30,7 @@ #include "oslib_test_sequence_004.h" #include "oslib_test_sequence_005.h" #include "oslib_test_sequence_006.h" +#include "oslib_test_sequence_007.h" #if !defined(__DOXYGEN__) diff --git a/test/oslib/source/test/oslib_test_sequence_001.c b/test/oslib/source/test/oslib_test_sequence_001.c index 334218e71..ae04aba25 100644 --- a/test/oslib/source/test/oslib_test_sequence_001.c +++ b/test/oslib/source/test/oslib_test_sequence_001.c @@ -94,6 +94,7 @@ static void oslib_test_001_001_execute(void) { test_println(""); #endif } + test_end_step(1); } static const testcase_t oslib_test_001_001 = { @@ -135,6 +136,7 @@ static void oslib_test_001_002_execute(void) { test_printn(CH_OSLIB_PATCH); test_println(""); } + test_end_step(1); } static const testcase_t oslib_test_001_002 = { @@ -200,6 +202,7 @@ static void oslib_test_001_003_execute(void) { test_printn(CH_CFG_FACTORY_PIPES); test_println(""); } + test_end_step(1); } static const testcase_t oslib_test_001_003 = { diff --git a/test/oslib/source/test/oslib_test_sequence_002.c b/test/oslib/source/test/oslib_test_sequence_002.c index 832a7a5ab..dc7d1acad 100644 --- a/test/oslib/source/test/oslib_test_sequence_002.c +++ b/test/oslib/source/test/oslib_test_sequence_002.c @@ -100,6 +100,7 @@ static void oslib_test_002_001_execute(void) { { test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size"); } + test_end_step(1); /* [2.1.2] Resetting the mailbox, conditions are checked, no errors expected.*/ @@ -111,6 +112,7 @@ static void oslib_test_002_001_execute(void) { 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"); } + test_end_step(2); /* [2.1.3] Testing the behavior of API when the mailbox is in reset state then return in active state.*/ @@ -124,6 +126,7 @@ static void oslib_test_002_001_execute(void) { test_assert(msg1 == MSG_RESET, "not in reset state"); chMBResumeX(&mb1); } + test_end_step(3); /* [2.1.4] Filling the mailbox using chMBPostTimeout() and chMBPostAheadTimeout() once, no errors expected.*/ @@ -136,6 +139,7 @@ static void oslib_test_002_001_execute(void) { msg1 = chMBPostAheadTimeout(&mb1, 'A', TIME_INFINITE); test_assert(msg1 == MSG_OK, "wrong wake-up message"); } + test_end_step(4); /* [2.1.5] Testing intermediate conditions. Data pointers must be aligned, semaphore counters are checked.*/ @@ -145,6 +149,7 @@ static void oslib_test_002_001_execute(void) { test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full"); test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned"); } + test_end_step(5); /* [2.1.6] Emptying the mailbox using chMBFetchTimeout(), no errors expected.*/ @@ -157,6 +162,7 @@ static void oslib_test_002_001_execute(void) { } test_assert_sequence("ABCD", "wrong get sequence"); } + test_end_step(6); /* [2.1.7] Posting and then fetching one more message, no errors expected.*/ @@ -167,6 +173,7 @@ static void oslib_test_002_001_execute(void) { msg1 = chMBFetchTimeout(&mb1, &msg2, TIME_INFINITE); test_assert(msg1 == MSG_OK, "wrong wake-up message"); } + test_end_step(7); /* [2.1.8] Testing final conditions. Data pointers must be aligned to buffer start, semaphore counters are checked.*/ @@ -177,6 +184,7 @@ static void oslib_test_002_001_execute(void) { test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); } + test_end_step(8); } static const testcase_t oslib_test_002_001 = { @@ -227,6 +235,7 @@ static void oslib_test_002_002_execute(void) { { test_assert_lock(chMBGetFreeCountI(&mb1) == MB_SIZE, "wrong size"); } + test_end_step(1); /* [2.2.2] Resetting the mailbox, conditions are checked, no errors expected. The mailbox is then returned in active state.*/ @@ -241,6 +250,7 @@ static void oslib_test_002_002_execute(void) { test_assert_lock(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); chMBResumeX(&mb1); } + test_end_step(2); /* [2.2.3] Filling the mailbox using chMBPostI() and chMBPostAheadI() once, no errors expected.*/ @@ -257,6 +267,7 @@ static void oslib_test_002_002_execute(void) { chSysUnlock(); test_assert(msg1 == MSG_OK, "wrong wake-up message"); } + test_end_step(3); /* [2.2.4] Testing intermediate conditions. Data pointers must be aligned, semaphore counters are checked.*/ @@ -266,6 +277,7 @@ static void oslib_test_002_002_execute(void) { test_assert_lock(chMBGetUsedCountI(&mb1) == MB_SIZE, "not full"); test_assert_lock(mb1.rdptr == mb1.wrptr, "pointers not aligned"); } + test_end_step(4); /* [2.2.5] Emptying the mailbox using chMBFetchI(), no errors expected.*/ @@ -280,6 +292,7 @@ static void oslib_test_002_002_execute(void) { } test_assert_sequence("ABCD", "wrong get sequence"); } + test_end_step(5); /* [2.2.6] Posting and then fetching one more message, no errors expected.*/ @@ -290,6 +303,7 @@ static void oslib_test_002_002_execute(void) { msg1 = chMBFetchTimeout(&mb1, &msg2, TIME_INFINITE); test_assert(msg1 == MSG_OK, "wrong wake-up message"); } + test_end_step(6); /* [2.2.7] Testing final conditions. Data pointers must be aligned to buffer start, semaphore counters are checked.*/ @@ -300,6 +314,7 @@ static void oslib_test_002_002_execute(void) { test_assert(mb1.buffer == mb1.wrptr, "write pointer not aligned to base"); test_assert(mb1.buffer == mb1.rdptr, "read pointer not aligned to base"); } + test_end_step(7); } static const testcase_t oslib_test_002_002 = { @@ -345,6 +360,7 @@ static void oslib_test_002_003_execute(void) { test_assert(msg1 == MSG_OK, "wrong wake-up message"); } } + test_end_step(1); /* [2.3.2] Testing chMBPostTimeout(), chMBPostI(), chMBPostAheadTimeout() and chMBPostAheadI() timeout.*/ @@ -363,6 +379,7 @@ static void oslib_test_002_003_execute(void) { chSysUnlock(); test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); } + test_end_step(2); /* [2.3.3] Resetting the mailbox. The mailbox is then returned in active state.*/ @@ -371,6 +388,7 @@ static void oslib_test_002_003_execute(void) { chMBReset(&mb1); chMBResumeX(&mb1); } + test_end_step(3); /* [2.3.4] Testing chMBFetchTimeout() and chMBFetchI() timeout.*/ test_set_step(4); @@ -382,6 +400,7 @@ static void oslib_test_002_003_execute(void) { chSysUnlock(); test_assert(msg1 == MSG_TIMEOUT, "wrong wake-up message"); } + test_end_step(4); } static const testcase_t oslib_test_002_003 = { diff --git a/test/oslib/source/test/oslib_test_sequence_003.c b/test/oslib/source/test/oslib_test_sequence_003.c index 554724e2c..ab320b3a6 100644 --- a/test/oslib/source/test/oslib_test_sequence_003.c +++ b/test/oslib/source/test/oslib_test_sequence_003.c @@ -101,6 +101,7 @@ static void oslib_test_003_001_execute(void) { (pipe1.cnt == 0), "invalid pipe state"); } + test_end_step(1); /* [3.1.2] Writing data, must fail.*/ test_set_step(2); @@ -114,6 +115,7 @@ static void oslib_test_003_001_execute(void) { (pipe1.cnt == 0), "invalid pipe state"); } + test_end_step(2); /* [3.1.3] Reading data, must fail.*/ test_set_step(3); @@ -128,6 +130,7 @@ static void oslib_test_003_001_execute(void) { (pipe1.cnt == 0), "invalid pipe state"); } + test_end_step(3); /* [3.1.4] Reactivating pipe.*/ test_set_step(4); @@ -138,6 +141,7 @@ static void oslib_test_003_001_execute(void) { (pipe1.cnt == 0), "invalid pipe state"); } + test_end_step(4); /* [3.1.5] Filling whole pipe.*/ test_set_step(5); @@ -151,6 +155,7 @@ static void oslib_test_003_001_execute(void) { (pipe1.cnt == PIPE_SIZE), "invalid pipe state"); } + test_end_step(5); /* [3.1.6] Emptying pipe.*/ test_set_step(6); @@ -166,6 +171,7 @@ static void oslib_test_003_001_execute(void) { "invalid pipe state"); test_assert(memcmp(pipe_pattern, buf, PIPE_SIZE) == 0, "content mismatch"); } + test_end_step(6); /* [3.1.7] Small write.*/ test_set_step(7); @@ -179,6 +185,7 @@ static void oslib_test_003_001_execute(void) { (pipe1.cnt == 4), "invalid pipe state"); } + test_end_step(7); /* [3.1.8] Filling remaining space.*/ test_set_step(8); @@ -192,6 +199,7 @@ static void oslib_test_003_001_execute(void) { (pipe1.cnt == PIPE_SIZE), "invalid pipe state"); } + test_end_step(8); /* [3.1.9] Small Read.*/ test_set_step(9); @@ -207,6 +215,7 @@ static void oslib_test_003_001_execute(void) { "invalid pipe state"); test_assert(memcmp(pipe_pattern, buf, 4) == 0, "content mismatch"); } + test_end_step(9); /* [3.1.10] Reading remaining data.*/ test_set_step(10); @@ -222,6 +231,7 @@ static void oslib_test_003_001_execute(void) { "invalid pipe state"); test_assert(memcmp(pipe_pattern, buf, PIPE_SIZE - 4) == 0, "content mismatch"); } + test_end_step(10); /* [3.1.11] Small Write.*/ test_set_step(11); @@ -235,6 +245,7 @@ static void oslib_test_003_001_execute(void) { (pipe1.cnt == 5), "invalid pipe state"); } + test_end_step(11); /* [3.1.12] Small Read.*/ test_set_step(12); @@ -250,6 +261,7 @@ static void oslib_test_003_001_execute(void) { "invalid pipe state"); test_assert(memcmp(pipe_pattern, buf, 5) == 0, "content mismatch"); } + test_end_step(12); /* [3.1.13] Write wrapping buffer boundary.*/ test_set_step(13); @@ -263,6 +275,7 @@ static void oslib_test_003_001_execute(void) { (pipe1.cnt == PIPE_SIZE), "invalid pipe state"); } + test_end_step(13); /* [3.1.14] Read wrapping buffer boundary.*/ test_set_step(14); @@ -278,6 +291,7 @@ static void oslib_test_003_001_execute(void) { "invalid pipe state"); test_assert(memcmp(pipe_pattern, buf, PIPE_SIZE) == 0, "content mismatch"); } + test_end_step(14); } static const testcase_t oslib_test_003_001 = { @@ -318,6 +332,7 @@ static void oslib_test_003_002_execute(void) { (pipe1.cnt == 0), "invalid pipe state"); } + test_end_step(1); /* [3.2.2] Writing a string larger than pipe buffer.*/ test_set_step(2); @@ -331,6 +346,7 @@ static void oslib_test_003_002_execute(void) { (pipe1.cnt == PIPE_SIZE / 2), "invalid pipe state"); } + test_end_step(2); } static const testcase_t oslib_test_003_002 = { diff --git a/test/oslib/source/test/oslib_test_sequence_004.c b/test/oslib/source/test/oslib_test_sequence_004.c index 7ecf4b6d6..e97fc3aac 100644 --- a/test/oslib/source/test/oslib_test_sequence_004.c +++ b/test/oslib/source/test/oslib_test_sequence_004.c @@ -21,48 +21,71 @@ * @file oslib_test_sequence_004.c * @brief Test Sequence 004 code. * - * @page oslib_test_sequence_004 [4] Memory Pools + * @page oslib_test_sequence_004 [4] Objects Caches * * File: @ref oslib_test_sequence_004.c * *

Description

* This sequence tests the ChibiOS library functionalities related to - * memory pools. + * Objects Caches. * *

Conditions

* This sequence is only executed if the following preprocessor condition * evaluates to true: - * - CH_CFG_USE_MEMPOOLS + * - CH_CFG_USE_OBJ_CACHES * . * *

Test Cases

* - @subpage oslib_test_004_001 - * - @subpage oslib_test_004_002 - * - @subpage oslib_test_004_003 * . */ -#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) +#if (CH_CFG_USE_OBJ_CACHES) || defined(__DOXYGEN__) /**************************************************************************** * Shared code. ****************************************************************************/ -#define MEMORY_POOL_SIZE 4 +#include -static uint32_t objects[MEMORY_POOL_SIZE]; -static MEMORYPOOL_DECL(mp1, sizeof (uint32_t), PORT_NATURAL_ALIGN, NULL); +#define SIZE_OBJECTS 16 +#define NUM_OBJECTS 4 +#define NUM_HASH_ENTRIES (NUM_OBJECTS * 2) -#if CH_CFG_USE_SEMAPHORES -static GUARDEDMEMORYPOOL_DECL(gmp1, sizeof (uint32_t), PORT_NATURAL_ALIGN); -#endif +/* Cached object type used for test.*/ +typedef struct { + oc_object_t header; + uint8_t data[SIZE_OBJECTS]; +} cached_object_t; -static void *null_provider(size_t size, unsigned align) { +static oc_hash_header_t hash_headers[NUM_HASH_ENTRIES]; +static cached_object_t objects[NUM_OBJECTS]; +static objects_cache_t cache1; - (void)size; - (void)align; +static bool obj_read(objects_cache_t *ocp, + oc_object_t *objp, + bool async) { - return NULL; + test_emit_token('a' + objp->obj_key); + + objp->obj_flags &= ~OC_FLAG_NOTSYNC; + + if (async) { + chCacheReleaseObject(ocp, objp); + } + + return false; +} + +static bool obj_write(objects_cache_t *ocp, + oc_object_t *objp, + bool async) { + (void)ocp; + (void)async; + + test_emit_token('A' + objp->obj_key); + + return false; } /**************************************************************************** @@ -70,210 +93,156 @@ static void *null_provider(size_t size, unsigned align) { ****************************************************************************/ /** - * @page oslib_test_004_001 [4.1] Loading and emptying a memory pool + * @page oslib_test_004_001 [4.1] Cache initialization * *

Description

- * The memory pool functionality is tested by loading and emptying it, - * all conditions are tested. + * A cache object is initialized, some initial conditions are checked. * *

Test Steps

- * - [4.1.1] Adding the objects to the pool using chPoolLoadArray(). - * - [4.1.2] Emptying the pool using chPoolAlloc(). - * - [4.1.3] Now must be empty. - * - [4.1.4] Adding the objects to the pool using chPoolFree(). - * - [4.1.5] Emptying the pool using chPoolAlloc() again. - * - [4.1.6] Now must be empty again. - * - [4.1.7] Covering the case where a provider is unable to return - * more memory. + * - [4.1.1] Cache initialization. + * - [4.1.2] Getting and releasing objects without initialization. + * - [4.1.3] Getting and releasing objects with synchronous + * initialization. + * - [4.1.4] Getting and releasing objects with asynchronous + * initialization. + * - [4.1.5] Checking cached objects. + * - [4.1.6] Checking non-cached objects. * . */ -static void oslib_test_004_001_setup(void) { - chPoolObjectInit(&mp1, sizeof (uint32_t), NULL); -} - static void oslib_test_004_001_execute(void) { - unsigned i; - /* [4.1.1] Adding the objects to the pool using chPoolLoadArray().*/ + /* [4.1.1] Cache initialization.*/ test_set_step(1); { - chPoolLoadArray(&mp1, objects, MEMORY_POOL_SIZE); + chCacheObjectInit(&cache1, + NUM_HASH_ENTRIES, + hash_headers, + NUM_OBJECTS, + sizeof (cached_object_t), + objects, + obj_read, + obj_write); } + test_end_step(1); - /* [4.1.2] Emptying the pool using chPoolAlloc().*/ + /* [4.1.2] Getting and releasing objects without initialization.*/ test_set_step(2); { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - test_assert(chPoolAlloc(&mp1) != NULL, "list empty"); - } + uint32_t i; - /* [4.1.3] Now must be empty.*/ + for (i = 0; i < (NUM_OBJECTS * 2); i++) { + oc_object_t * objp = chCacheGetObject(&cache1, 0U, i); + + test_assert((objp->obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) != 0U, "should not be in sync"); + + chCacheReleaseObject(&cache1, objp); + } + + test_assert_sequence("", "unexpected tokens"); + } + test_end_step(2); + + /* [4.1.3] Getting and releasing objects with synchronous + initialization.*/ test_set_step(3); { - test_assert(chPoolAlloc(&mp1) == NULL, "list not empty"); - } + uint32_t i; + bool error; - /* [4.1.4] Adding the objects to the pool using chPoolFree().*/ + for (i = 0; i < (NUM_OBJECTS * 2); i++) { + oc_object_t *objp = chCacheGetObject(&cache1, 0U, i); + + test_assert((objp->obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) != 0U, "in sync"); + + error = chCacheReadObject(&cache1, objp, false); + + test_assert(error == false, "returned error"); + test_assert((objp->obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) == 0U, "not in sync"); + + chCacheReleaseObject(&cache1, objp); + } + + test_assert_sequence("abcdefgh", "unexpected tokens"); + } + test_end_step(3); + + /* [4.1.4] Getting and releasing objects with asynchronous + initialization.*/ test_set_step(4); { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - chPoolFree(&mp1, &objects[i]); - } + uint32_t i; + bool error; - /* [4.1.5] Emptying the pool using chPoolAlloc() again.*/ + for (i = 0; i < (NUM_OBJECTS * 2); i++) { + oc_object_t *objp = chCacheGetObject(&cache1, 0U, i); + + test_assert((objp->obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) != 0U, "in sync"); + + error = chCacheReadObject(&cache1, objp, true); + + test_assert(error == false, "returned error"); + + objp = chCacheGetObject(&cache1, 0U, i); + + test_assert((objp->obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) == 0U, "not in sync"); + + chCacheReleaseObject(&cache1, objp); + } + + test_assert_sequence("abcdefgh", "unexpected tokens"); + } + test_end_step(4); + + /* [4.1.5] Checking cached objects.*/ test_set_step(5); { - for (i = 0; i < MEMORY_POOL_SIZE; i++) - test_assert(chPoolAlloc(&mp1) != NULL, "list empty"); - } + uint32_t i; - /* [4.1.6] Now must be empty again.*/ + for (i = NUM_OBJECTS; i < (NUM_OBJECTS * 2); i++) { + oc_object_t *objp = chCacheGetObject(&cache1, 0U, i); + + test_assert((objp->obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) == 0U, "not in sync"); + + chCacheReleaseObject(&cache1, objp); + } + + test_assert_sequence("", "unexpected tokens"); + } + test_end_step(5); + + /* [4.1.6] Checking non-cached objects.*/ test_set_step(6); { - test_assert(chPoolAlloc(&mp1) == NULL, "list not empty"); - } + uint32_t i; - /* [4.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"); + for (i = 0; i < NUM_OBJECTS; i++) { + oc_object_t *objp = chCacheGetObject(&cache1, 0U, i); + + test_assert((objp->obj_flags & OC_FLAG_INHASH) != 0U, "not in hash"); + test_assert((objp->obj_flags & OC_FLAG_NOTSYNC) != 0U, "in sync"); + + chCacheReleaseObject(&cache1, objp); + } + + test_assert_sequence("", "unexpected tokens"); } + test_end_step(6); } static const testcase_t oslib_test_004_001 = { - "Loading and emptying a memory pool", - oslib_test_004_001_setup, + "Cache initialization", + NULL, NULL, oslib_test_004_001_execute }; -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) -/** - * @page oslib_test_004_002 [4.2] Loading and emptying a guarded memory pool without waiting - * - *

Description

- * The memory pool functionality is tested by loading and emptying it, - * all conditions are tested. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_SEMAPHORES - * . - * - *

Test Steps

- * - [4.2.1] Adding the objects to the pool using - * chGuardedPoolLoadArray(). - * - [4.2.2] Emptying the pool using chGuardedPoolAllocTimeout(). - * - [4.2.3] Now must be empty. - * - [4.2.4] Adding the objects to the pool using chGuardedPoolFree(). - * - [4.2.5] Emptying the pool using chGuardedPoolAllocTimeout() again. - * - [4.2.6] Now must be empty again. - * . - */ - -static void oslib_test_004_002_setup(void) { - chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); -} - -static void oslib_test_004_002_execute(void) { - unsigned i; - - /* [4.2.1] Adding the objects to the pool using - chGuardedPoolLoadArray().*/ - test_set_step(1); - { - chGuardedPoolLoadArray(&gmp1, objects, MEMORY_POOL_SIZE); - } - - /* [4.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"); - } - - /* [4.2.3] Now must be empty.*/ - test_set_step(3); - { - test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty"); - } - - /* [4.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]); - } - - /* [4.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"); - } - - /* [4.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 oslib_test_004_002 = { - "Loading and emptying a guarded memory pool without waiting", - oslib_test_004_002_setup, - NULL, - oslib_test_004_002_execute -}; -#endif /* CH_CFG_USE_SEMAPHORES */ - -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) -/** - * @page oslib_test_004_003 [4.3] Guarded Memory Pools timeout - * - *

Description

- * The timeout features for the Guarded Memory Pools is tested. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_USE_SEMAPHORES - * . - * - *

Test Steps

- * - [4.3.1] Trying to allocate with 100mS timeout, must fail because - * the pool is empty. - * . - */ - -static void oslib_test_004_003_setup(void) { - chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); -} - -static void oslib_test_004_003_execute(void) { - - /* [4.3.1] Trying to allocate with 100mS timeout, must fail because - the pool is empty.*/ - test_set_step(1); - { - test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_MS2I(100)) == NULL, "list not empty"); - } -} - -static const testcase_t oslib_test_004_003 = { - "Guarded Memory Pools timeout", - oslib_test_004_003_setup, - NULL, - oslib_test_004_003_execute -}; -#endif /* CH_CFG_USE_SEMAPHORES */ - /**************************************************************************** * Exported data. ****************************************************************************/ @@ -283,21 +252,15 @@ static const testcase_t oslib_test_004_003 = { */ const testcase_t * const oslib_test_sequence_004_array[] = { &oslib_test_004_001, -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) - &oslib_test_004_002, -#endif -#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) - &oslib_test_004_003, -#endif NULL }; /** - * @brief Memory Pools. + * @brief Objects Caches. */ const testsequence_t oslib_test_sequence_004 = { - "Memory Pools", + "Objects Caches", oslib_test_sequence_004_array }; -#endif /* CH_CFG_USE_MEMPOOLS */ +#endif /* CH_CFG_USE_OBJ_CACHES */ diff --git a/test/oslib/source/test/oslib_test_sequence_005.c b/test/oslib/source/test/oslib_test_sequence_005.c index f33d9cadf..2748850a9 100644 --- a/test/oslib/source/test/oslib_test_sequence_005.c +++ b/test/oslib/source/test/oslib_test_sequence_005.c @@ -21,240 +21,272 @@ * @file oslib_test_sequence_005.c * @brief Test Sequence 005 code. * - * @page oslib_test_sequence_005 [5] Memory Heaps + * @page oslib_test_sequence_005 [5] Memory Pools * * File: @ref oslib_test_sequence_005.c * *

Description

* This sequence tests the ChibiOS library functionalities related to - * memory heaps. + * memory pools. * *

Conditions

* This sequence is only executed if the following preprocessor condition * evaluates to true: - * - CH_CFG_USE_HEAP + * - CH_CFG_USE_MEMPOOLS * . * *

Test Cases

* - @subpage oslib_test_005_001 * - @subpage oslib_test_005_002 + * - @subpage oslib_test_005_003 * . */ -#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__) +#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__) /**************************************************************************** * Shared code. ****************************************************************************/ -#define ALLOC_SIZE 16 -#define HEAP_SIZE (ALLOC_SIZE * 8) +#define MEMORY_POOL_SIZE 4 -static memory_heap_t test_heap; -static uint8_t test_heap_buffer[HEAP_SIZE]; +static uint32_t objects[MEMORY_POOL_SIZE]; +static MEMORYPOOL_DECL(mp1, sizeof (uint32_t), PORT_NATURAL_ALIGN, NULL); + +#if CH_CFG_USE_SEMAPHORES +static GUARDEDMEMORYPOOL_DECL(gmp1, sizeof (uint32_t), PORT_NATURAL_ALIGN); +#endif + +static void *null_provider(size_t size, unsigned align) { + + (void)size; + (void)align; + + return NULL; +} /**************************************************************************** * Test cases. ****************************************************************************/ /** - * @page oslib_test_005_001 [5.1] Allocation and fragmentation + * @page oslib_test_005_001 [5.1] Loading and emptying a memory pool * *

Description

- * 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. + * The memory pool functionality is tested by loading and emptying it, + * all conditions are tested. * *

Test Steps

- * - [5.1.1] Testing initial conditions, the heap must not be - * fragmented and one free block present. - * - [5.1.2] Trying to allocate an block bigger than available space, - * an error is expected. - * - [5.1.3] Single block allocation using chHeapAlloc() then the block - * is freed using chHeapFree(), must not fail. - * - [5.1.4] Using chHeapStatus() to assess the heap state. There must - * be at least one free block of sufficient size. - * - [5.1.5] Allocating then freeing in the same order. - * - [5.1.6] Allocating then freeing in reverse order. - * - [5.1.7] Small fragments handling. Checking the behavior when - * allocating blocks with size not multiple of alignment unit. - * - [5.1.8] Skipping a fragment, the first fragment in the list is too - * small so the allocator must pick the second one. - * - [5.1.9] Allocating the whole available space. - * - [5.1.10] Testing final conditions. The heap geometry must be the - * same than the one registered at beginning. + * - [5.1.1] Adding the objects to the pool using chPoolLoadArray(). + * - [5.1.2] Emptying the pool using chPoolAlloc(). + * - [5.1.3] Now must be empty. + * - [5.1.4] Adding the objects to the pool using chPoolFree(). + * - [5.1.5] Emptying the pool using chPoolAlloc() again. + * - [5.1.6] Now must be empty again. + * - [5.1.7] Covering the case where a provider is unable to return + * more memory. * . */ static void oslib_test_005_001_setup(void) { - chHeapObjectInit(&test_heap, test_heap_buffer, sizeof(test_heap_buffer)); + chPoolObjectInit(&mp1, sizeof (uint32_t), NULL); } static void oslib_test_005_001_execute(void) { - void *p1, *p2, *p3; - size_t n, sz; + unsigned i; - /* [5.1.1] Testing initial conditions, the heap must not be - fragmented and one free block present.*/ + /* [5.1.1] Adding the objects to the pool using chPoolLoadArray().*/ test_set_step(1); { - test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented"); + chPoolLoadArray(&mp1, objects, MEMORY_POOL_SIZE); } + test_end_step(1); - /* [5.1.2] Trying to allocate an block bigger than available space, - an error is expected.*/ + /* [5.1.2] Emptying the pool using chPoolAlloc().*/ test_set_step(2); { - p1 = chHeapAlloc(&test_heap, sizeof test_heap_buffer * 2); - test_assert(p1 == NULL, "allocation not failed"); + for (i = 0; i < MEMORY_POOL_SIZE; i++) + test_assert(chPoolAlloc(&mp1) != NULL, "list empty"); } + test_end_step(2); - /* [5.1.3] Single block allocation using chHeapAlloc() then the block - is freed using chHeapFree(), must not fail.*/ + /* [5.1.3] Now must be empty.*/ test_set_step(3); { - p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); - test_assert(p1 != NULL, "allocation failed"); - chHeapFree(p1); + test_assert(chPoolAlloc(&mp1) == NULL, "list not empty"); } + test_end_step(3); - /* [5.1.4] Using chHeapStatus() to assess the heap state. There must - be at least one free block of sufficient size.*/ + /* [5.1.4] Adding the objects to the pool using chPoolFree().*/ 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"); + for (i = 0; i < MEMORY_POOL_SIZE; i++) + chPoolFree(&mp1, &objects[i]); } + test_end_step(4); - /* [5.1.5] Allocating then freeing in the same order.*/ + /* [5.1.5] Emptying the pool using chPoolAlloc() again.*/ 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"); + for (i = 0; i < MEMORY_POOL_SIZE; i++) + test_assert(chPoolAlloc(&mp1) != NULL, "list empty"); } + test_end_step(5); - /* [5.1.6] Allocating then freeing in reverse order.*/ + /* [5.1.6] Now must be empty again.*/ 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"); + test_assert(chPoolAlloc(&mp1) == NULL, "list not empty"); } + test_end_step(6); - /* [5.1.7] Small fragments handling. Checking the behavior when - allocating blocks with size not multiple of alignment unit.*/ + /* [5.1.7] Covering the case where a provider is unable to return + more memory.*/ 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"); - } - - /* [5.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"); - } - - /* [5.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); - } - - /* [5.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"); + chPoolObjectInit(&mp1, sizeof (uint32_t), null_provider); + test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory"); } + test_end_step(7); } static const testcase_t oslib_test_005_001 = { - "Allocation and fragmentation", + "Loading and emptying a memory pool", oslib_test_005_001_setup, NULL, oslib_test_005_001_execute }; +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) /** - * @page oslib_test_005_002 [5.2] Default Heap + * @page oslib_test_005_002 [5.2] Loading and emptying a guarded memory pool without waiting * *

Description

- * The default heap is pre-allocated in the system. We test base - * functionality. + * The memory pool functionality is tested by loading and emptying it, + * all conditions are tested. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_SEMAPHORES + * . * *

Test Steps

- * - [5.2.1] Single block allocation using chHeapAlloc() then the block - * is freed using chHeapFree(), must not fail. - * - [5.2.2] Testing allocation failure. + * - [5.2.1] Adding the objects to the pool using + * chGuardedPoolLoadArray(). + * - [5.2.2] Emptying the pool using chGuardedPoolAllocTimeout(). + * - [5.2.3] Now must be empty. + * - [5.2.4] Adding the objects to the pool using chGuardedPoolFree(). + * - [5.2.5] Emptying the pool using chGuardedPoolAllocTimeout() again. + * - [5.2.6] Now must be empty again. * . */ -static void oslib_test_005_002_execute(void) { - void *p1; - size_t total_size, largest_size; +static void oslib_test_005_002_setup(void) { + chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); +} - /* [5.2.1] Single block allocation using chHeapAlloc() then the block - is freed using chHeapFree(), must not fail.*/ +static void oslib_test_005_002_execute(void) { + unsigned i; + + /* [5.2.1] Adding the objects to the pool using + chGuardedPoolLoadArray().*/ 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); + chGuardedPoolLoadArray(&gmp1, objects, MEMORY_POOL_SIZE); } + test_end_step(1); - /* [5.2.2] Testing allocation failure.*/ + /* [5.2.2] Emptying the pool using chGuardedPoolAllocTimeout().*/ test_set_step(2); { - p1 = chHeapAlloc(NULL, (size_t)-256); - test_assert(p1 == NULL, "allocation not failed"); + for (i = 0; i < MEMORY_POOL_SIZE; i++) + test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) != NULL, "list empty"); } + test_end_step(2); + + /* [5.2.3] Now must be empty.*/ + test_set_step(3); + { + test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty"); + } + test_end_step(3); + + /* [5.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]); + } + test_end_step(4); + + /* [5.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"); + } + test_end_step(5); + + /* [5.2.6] Now must be empty again.*/ + test_set_step(6); + { + test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_IMMEDIATE) == NULL, "list not empty"); + } + test_end_step(6); } static const testcase_t oslib_test_005_002 = { - "Default Heap", - NULL, + "Loading and emptying a guarded memory pool without waiting", + oslib_test_005_002_setup, NULL, oslib_test_005_002_execute }; +#endif /* CH_CFG_USE_SEMAPHORES */ + +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) +/** + * @page oslib_test_005_003 [5.3] Guarded Memory Pools timeout + * + *

Description

+ * The timeout features for the Guarded Memory Pools is tested. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_USE_SEMAPHORES + * . + * + *

Test Steps

+ * - [5.3.1] Trying to allocate with 100mS timeout, must fail because + * the pool is empty. + * . + */ + +static void oslib_test_005_003_setup(void) { + chGuardedPoolObjectInit(&gmp1, sizeof (uint32_t)); +} + +static void oslib_test_005_003_execute(void) { + + /* [5.3.1] Trying to allocate with 100mS timeout, must fail because + the pool is empty.*/ + test_set_step(1); + { + test_assert(chGuardedPoolAllocTimeout(&gmp1, TIME_MS2I(100)) == NULL, "list not empty"); + } + test_end_step(1); +} + +static const testcase_t oslib_test_005_003 = { + "Guarded Memory Pools timeout", + oslib_test_005_003_setup, + NULL, + oslib_test_005_003_execute +}; +#endif /* CH_CFG_USE_SEMAPHORES */ /**************************************************************************** * Exported data. @@ -265,16 +297,21 @@ static const testcase_t oslib_test_005_002 = { */ const testcase_t * const oslib_test_sequence_005_array[] = { &oslib_test_005_001, +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) &oslib_test_005_002, +#endif +#if (CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__) + &oslib_test_005_003, +#endif NULL }; /** - * @brief Memory Heaps. + * @brief Memory Pools. */ const testsequence_t oslib_test_sequence_005 = { - "Memory Heaps", + "Memory Pools", oslib_test_sequence_005_array }; -#endif /* CH_CFG_USE_HEAP */ +#endif /* CH_CFG_USE_MEMPOOLS */ diff --git a/test/oslib/source/test/oslib_test_sequence_006.c b/test/oslib/source/test/oslib_test_sequence_006.c index 0cef3a1ca..6f4e6669a 100644 --- a/test/oslib/source/test/oslib_test_sequence_006.c +++ b/test/oslib/source/test/oslib_test_sequence_006.c @@ -21,725 +21,252 @@ * @file oslib_test_sequence_006.c * @brief Test Sequence 006 code. * - * @page oslib_test_sequence_006 [6] Objects Factory + * @page oslib_test_sequence_006 [6] Memory Heaps * * File: @ref oslib_test_sequence_006.c * *

Description

* This sequence tests the ChibiOS library functionalities related to - * the object factory. + * memory heaps. * *

Conditions

* This sequence is only executed if the following preprocessor condition * evaluates to true: - * - (CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE) + * - CH_CFG_USE_HEAP * . * *

Test Cases

* - @subpage oslib_test_006_001 * - @subpage oslib_test_006_002 - * - @subpage oslib_test_006_003 - * - @subpage oslib_test_006_004 - * - @subpage oslib_test_006_005 - * - @subpage oslib_test_006_006 * . */ -#if ((CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE)) || defined(__DOXYGEN__) +#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 uint8_t test_heap_buffer[HEAP_SIZE]; /**************************************************************************** * Test cases. ****************************************************************************/ -#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) /** - * @page oslib_test_006_001 [6.1] Objects Registry + * @page oslib_test_006_001 [6.1] Allocation and fragmentation * *

Description

- * This test case verifies the static objects registry. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE - * . + * 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. * *

Test Steps

- * - [6.1.1] Retrieving a registered object by name, must not exist. - * - [6.1.2] Registering an object, it must not exists, must succeed. - * - [6.1.3] Registering an object with the same name, must fail. - * - [6.1.4] Retrieving the registered object by name, must exist, then - * increasing the reference counter, finally releasing both - * references. - * - [6.1.5] Releasing the first reference to the object, must not - * trigger an assertion. - * - [6.1.6] Retrieving the registered object by name again, must not - * exist. + * - [6.1.1] Testing initial conditions, the heap must not be + * fragmented and one free block present. + * - [6.1.2] Trying to allocate an block bigger than available space, + * an error is expected. + * - [6.1.3] Single block allocation using chHeapAlloc() then the block + * is freed using chHeapFree(), must not fail. + * - [6.1.4] Using chHeapStatus() to assess the heap state. There must + * be at least one free block of sufficient size. + * - [6.1.5] Allocating then freeing in the same order. + * - [6.1.6] Allocating then freeing in reverse order. + * - [6.1.7] Small fragments handling. Checking the behavior when + * allocating blocks with size not multiple of alignment unit. + * - [6.1.8] Skipping a fragment, the first fragment in the list is too + * small so the allocator must pick the second one. + * - [6.1.9] Allocating the whole available space. + * - [6.1.10] Testing final conditions. The heap geometry must be the + * same than the one registered at beginning. * . */ -static void oslib_test_006_001_teardown(void) { - registered_object_t *rop; - - rop = chFactoryFindObject("myobj"); - if (rop != NULL) { - while (rop->element.refs > 0U) { - chFactoryReleaseObject(rop); - } - } +static void oslib_test_006_001_setup(void) { + chHeapObjectInit(&test_heap, test_heap_buffer, sizeof(test_heap_buffer)); } static void oslib_test_006_001_execute(void) { - registered_object_t *rop; + void *p1, *p2, *p3; + size_t n, sz; - /* [6.1.1] Retrieving a registered object by name, must not exist.*/ + /* [6.1.1] Testing initial conditions, the heap must not be + fragmented and one free block present.*/ test_set_step(1); { - rop = chFactoryFindObject("myobj"); - test_assert(rop == NULL, "found"); + test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented"); } + test_end_step(1); - /* [6.1.2] Registering an object, it must not exists, must succeed.*/ + /* [6.1.2] Trying to allocate an block bigger than available space, + an error is expected.*/ test_set_step(2); { - static uint32_t myobj = 0x55aa; - - rop = chFactoryRegisterObject("myobj", (void *)&myobj); - test_assert(rop != NULL, "cannot register"); + p1 = chHeapAlloc(&test_heap, sizeof test_heap_buffer * 2); + test_assert(p1 == NULL, "allocation not failed"); } + test_end_step(2); - /* [6.1.3] Registering an object with the same name, must fail.*/ + /* [6.1.3] Single block allocation using chHeapAlloc() then the block + is freed using chHeapFree(), must not fail.*/ test_set_step(3); { - registered_object_t *rop1; - static uint32_t myobj = 0x55aa; - - rop1 = chFactoryRegisterObject("myobj", (void *)&myobj); - test_assert(rop1 == NULL, "can register"); + p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); + test_assert(p1 != NULL, "allocation failed"); + chHeapFree(p1); } + test_end_step(3); - /* [6.1.4] Retrieving the registered object by name, must exist, then - increasing the reference counter, finally releasing both - references.*/ + /* [6.1.4] Using chHeapStatus() to assess the heap state. There must + be at least one free block of sufficient size.*/ test_set_step(4); { - registered_object_t *rop1, *rop2; + size_t total_size, largest_size; - rop1 = chFactoryFindObject("myobj"); - test_assert(rop1 != NULL, "not found"); - test_assert(*(uint32_t *)(rop1->objp) == 0x55aa, "object mismatch"); - test_assert(rop == rop1, "object reference mismatch"); - test_assert(rop1->element.refs == 2, "object reference mismatch"); - - rop2 = (registered_object_t *)chFactoryDuplicateReference(&rop1->element); - test_assert(rop1 == rop2, "object reference mismatch"); - test_assert(*(uint32_t *)(rop2->objp) == 0x55aa, "object mismatch"); - test_assert(rop2->element.refs == 3, "object reference mismatch"); - - chFactoryReleaseObject(rop2); - test_assert(rop1->element.refs == 2, "references mismatch"); - - chFactoryReleaseObject(rop1); - test_assert(rop->element.refs == 1, "references mismatch"); + 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"); } + test_end_step(4); - /* [6.1.5] Releasing the first reference to the object, must not - trigger an assertion.*/ + /* [6.1.5] Allocating then freeing in the same order.*/ test_set_step(5); { - chFactoryReleaseObject(rop); + 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"); } + test_end_step(5); - /* [6.1.6] Retrieving the registered object by name again, must not - exist.*/ + /* [6.1.6] Allocating then freeing in reverse order.*/ test_set_step(6); { - rop = chFactoryFindObject("myobj"); - test_assert(rop == NULL, "found"); + 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"); } + test_end_step(6); + + /* [6.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"); + } + test_end_step(7); + + /* [6.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"); + } + test_end_step(8); + + /* [6.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); + } + test_end_step(9); + + /* [6.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"); + } + test_end_step(10); } static const testcase_t oslib_test_006_001 = { - "Objects Registry", + "Allocation and fragmentation", + oslib_test_006_001_setup, NULL, - oslib_test_006_001_teardown, oslib_test_006_001_execute }; -#endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */ -#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) /** - * @page oslib_test_006_002 [6.2] Dynamic Buffers Factory + * @page oslib_test_006_002 [6.2] Default Heap * *

Description

- * This test case verifies the dynamic buffers factory. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE - * . + * The default heap is pre-allocated in the system. We test base + * functionality. * *

Test Steps

- * - [6.2.1] Retrieving a dynamic buffer by name, must not exist. - * - [6.2.2] Creating a dynamic buffer it must not exists, must - * succeed. - * - [6.2.3] Creating a dynamic buffer with the same name, must fail. - * - [6.2.4] Retrieving the dynamic buffer by name, must exist, then - * increasing the reference counter, finally releasing both - * references. - * - [6.2.5] Releasing the first reference to the dynamic buffer, must - * not trigger an assertion. - * - [6.2.6] Retrieving the dynamic buffer by name again, must not - * exist. + * - [6.2.1] Single block allocation using chHeapAlloc() then the block + * is freed using chHeapFree(), must not fail. + * - [6.2.2] Testing allocation failure. * . */ -static void oslib_test_006_002_teardown(void) { - dyn_buffer_t *dbp; - - dbp = chFactoryFindBuffer("mybuf"); - if (dbp != NULL) { - while (dbp->element.refs > 0U) { - chFactoryReleaseBuffer(dbp); - } - } -} - static void oslib_test_006_002_execute(void) { - dyn_buffer_t *dbp; + void *p1; + size_t total_size, largest_size; - /* [6.2.1] Retrieving a dynamic buffer by name, must not exist.*/ + /* [6.2.1] Single block allocation using chHeapAlloc() then the block + is freed using chHeapFree(), must not fail.*/ test_set_step(1); { - dbp = chFactoryFindBuffer("mybuf"); - test_assert(dbp == NULL, "found"); + (void)chHeapStatus(NULL, &total_size, &largest_size); + p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); + test_assert(p1 != NULL, "allocation failed"); + chHeapFree(p1); } + test_end_step(1); - /* [6.2.2] Creating a dynamic buffer it must not exists, must - succeed.*/ + /* [6.2.2] Testing allocation failure.*/ test_set_step(2); { - dbp = chFactoryCreateBuffer("mybuf", 128U); - test_assert(dbp != NULL, "cannot create"); - } - - /* [6.2.3] Creating a dynamic buffer with the same name, must fail.*/ - test_set_step(3); - { - dyn_buffer_t *dbp1; - - dbp1 = chFactoryCreateBuffer("mybuf", 128U); - test_assert(dbp1 == NULL, "can create"); - } - - /* [6.2.4] Retrieving the dynamic buffer by name, must exist, then - increasing the reference counter, finally releasing both - references.*/ - test_set_step(4); - { - dyn_buffer_t *dbp1, *dbp2; - - dbp1 = chFactoryFindBuffer("mybuf"); - test_assert(dbp1 != NULL, "not found"); - test_assert(dbp == dbp1, "object reference mismatch"); - test_assert(dbp1->element.refs == 2, "object reference mismatch"); - - dbp2 = (dyn_buffer_t *)chFactoryDuplicateReference(&dbp1->element); - test_assert(dbp1 == dbp2, "object reference mismatch"); - test_assert(dbp2->element.refs == 3, "object reference mismatch"); - - chFactoryReleaseBuffer(dbp2); - test_assert(dbp1->element.refs == 2, "references mismatch"); - - chFactoryReleaseBuffer(dbp1); - test_assert(dbp->element.refs == 1, "references mismatch"); - } - - /* [6.2.5] Releasing the first reference to the dynamic buffer, must - not trigger an assertion.*/ - test_set_step(5); - { - chFactoryReleaseBuffer(dbp); - } - - /* [6.2.6] Retrieving the dynamic buffer by name again, must not - exist.*/ - test_set_step(6); - { - dbp = chFactoryFindBuffer("mybuf"); - test_assert(dbp == NULL, "found"); + p1 = chHeapAlloc(NULL, (size_t)-256); + test_assert(p1 == NULL, "allocation not failed"); } + test_end_step(2); } static const testcase_t oslib_test_006_002 = { - "Dynamic Buffers Factory", + "Default Heap", + NULL, NULL, - oslib_test_006_002_teardown, oslib_test_006_002_execute }; -#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE */ - -#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) -/** - * @page oslib_test_006_003 [6.3] Dynamic Semaphores Factory - * - *

Description

- * This test case verifies the dynamic semaphores factory. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_FACTORY_SEMAPHORES == TRUE - * . - * - *

Test Steps

- * - [6.3.1] Retrieving a dynamic semaphore by name, must not exist. - * - [6.3.2] Creating a dynamic semaphore it must not exists, must - * succeed. - * - [6.3.3] Creating a dynamic semaphore with the same name, must - * fail. - * - [6.3.4] Retrieving the dynamic semaphore by name, must exist, then - * increasing the reference counter, finally releasing both - * references. - * - [6.3.5] Releasing the first reference to the dynamic semaphore - * must not trigger an assertion. - * - [6.3.6] Retrieving the dynamic semaphore by name again, must not - * exist. - * . - */ - -static void oslib_test_006_003_teardown(void) { - dyn_semaphore_t *dsp; - - dsp = chFactoryFindSemaphore("mysem"); - if (dsp != NULL) { - while (dsp->element.refs > 0U) { - chFactoryReleaseSemaphore(dsp); - } - } -} - -static void oslib_test_006_003_execute(void) { - dyn_semaphore_t *dsp; - - /* [6.3.1] Retrieving a dynamic semaphore by name, must not exist.*/ - test_set_step(1); - { - dsp = chFactoryFindSemaphore("mysem"); - test_assert(dsp == NULL, "found"); - } - - /* [6.3.2] Creating a dynamic semaphore it must not exists, must - succeed.*/ - test_set_step(2); - { - dsp = chFactoryCreateSemaphore("mysem", 0); - test_assert(dsp != NULL, "cannot create"); - } - - /* [6.3.3] Creating a dynamic semaphore with the same name, must - fail.*/ - test_set_step(3); - { - dyn_semaphore_t *dsp1; - - dsp1 = chFactoryCreateSemaphore("mysem", 0); - test_assert(dsp1 == NULL, "can create"); - } - - /* [6.3.4] Retrieving the dynamic semaphore by name, must exist, then - increasing the reference counter, finally releasing both - references.*/ - test_set_step(4); - { - dyn_semaphore_t *dsp1, *dsp2; - - dsp1 = chFactoryFindSemaphore("mysem"); - test_assert(dsp1 != NULL, "not found"); - test_assert(dsp == dsp1, "object reference mismatch"); - test_assert(dsp1->element.refs == 2, "object reference mismatch"); - - dsp2 = (dyn_semaphore_t *)chFactoryDuplicateReference(&dsp1->element); - test_assert(dsp1 == dsp2, "object reference mismatch"); - test_assert(dsp2->element.refs == 3, "object reference mismatch"); - - chFactoryReleaseSemaphore(dsp2); - test_assert(dsp1->element.refs == 2, "references mismatch"); - - chFactoryReleaseSemaphore(dsp1); - test_assert(dsp->element.refs == 1, "references mismatch"); - } - - /* [6.3.5] Releasing the first reference to the dynamic semaphore - must not trigger an assertion.*/ - test_set_step(5); - { - chFactoryReleaseSemaphore(dsp); - } - - /* [6.3.6] Retrieving the dynamic semaphore by name again, must not - exist.*/ - test_set_step(6); - { - dsp = chFactoryFindSemaphore("mysem"); - test_assert(dsp == NULL, "found"); - } -} - -static const testcase_t oslib_test_006_003 = { - "Dynamic Semaphores Factory", - NULL, - oslib_test_006_003_teardown, - oslib_test_006_003_execute -}; -#endif /* CH_CFG_FACTORY_SEMAPHORES == TRUE */ - -#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) -/** - * @page oslib_test_006_004 [6.4] Dynamic Mailboxes Factory - * - *

Description

- * This test case verifies the dynamic mailboxes factory. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_FACTORY_MAILBOXES == TRUE - * . - * - *

Test Steps

- * - [6.4.1] Retrieving a dynamic mailbox by name, must not exist. - * - [6.4.2] Creating a dynamic mailbox it must not exists, must - * succeed. - * - [6.4.3] Creating a dynamic mailbox with the same name, must fail. - * - [6.4.4] Retrieving the dynamic mailbox by name, must exist, then - * increasing the reference counter, finally releasing both - * references. - * - [6.4.5] Releasing the first reference to the dynamic mailbox must - * not trigger an assertion. - * - [6.4.6] Retrieving the dynamic mailbox by name again, must not - * exist. - * . - */ - -static void oslib_test_006_004_teardown(void) { - dyn_mailbox_t *dmp; - - dmp = chFactoryFindMailbox("mymbx"); - if (dmp != NULL) { - while (dmp->element.refs > 0U) { - chFactoryReleaseMailbox(dmp); - } - } -} - -static void oslib_test_006_004_execute(void) { - dyn_mailbox_t *dmp; - - /* [6.4.1] Retrieving a dynamic mailbox by name, must not exist.*/ - test_set_step(1); - { - dmp = chFactoryFindMailbox("mymbx"); - test_assert(dmp == NULL, "found"); - } - - /* [6.4.2] Creating a dynamic mailbox it must not exists, must - succeed.*/ - test_set_step(2); - { - dmp = chFactoryCreateMailbox("mymbx", 16U); - test_assert(dmp != NULL, "cannot create"); - } - - /* [6.4.3] Creating a dynamic mailbox with the same name, must - fail.*/ - test_set_step(3); - { - dyn_mailbox_t *dmp1; - - dmp1 = chFactoryCreateMailbox("mymbx", 16U); - test_assert(dmp1 == NULL, "can create"); - } - - /* [6.4.4] Retrieving the dynamic mailbox by name, must exist, then - increasing the reference counter, finally releasing both - references.*/ - test_set_step(4); - { - dyn_mailbox_t *dmp1, *dmp2; - - dmp1 = chFactoryFindMailbox("mymbx"); - test_assert(dmp1 != NULL, "not found"); - test_assert(dmp == dmp1, "object reference mismatch"); - test_assert(dmp1->element.refs == 2, "object reference mismatch"); - - dmp2 = (dyn_mailbox_t *)chFactoryDuplicateReference(&dmp1->element); - test_assert(dmp1 == dmp2, "object reference mismatch"); - test_assert(dmp2->element.refs == 3, "object reference mismatch"); - - chFactoryReleaseMailbox(dmp2); - test_assert(dmp1->element.refs == 2, "references mismatch"); - - chFactoryReleaseMailbox(dmp1); - test_assert(dmp->element.refs == 1, "references mismatch"); - } - - /* [6.4.5] Releasing the first reference to the dynamic mailbox must - not trigger an assertion.*/ - test_set_step(5); - { - chFactoryReleaseMailbox(dmp); - } - - /* [6.4.6] Retrieving the dynamic mailbox by name again, must not - exist.*/ - test_set_step(6); - { - dmp = chFactoryFindMailbox("mymbx"); - test_assert(dmp == NULL, "found"); - } -} - -static const testcase_t oslib_test_006_004 = { - "Dynamic Mailboxes Factory", - NULL, - oslib_test_006_004_teardown, - oslib_test_006_004_execute -}; -#endif /* CH_CFG_FACTORY_MAILBOXES == TRUE */ - -#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) -/** - * @page oslib_test_006_005 [6.5] Dynamic Objects FIFOs Factory - * - *

Description

- * This test case verifies the dynamic objects FIFOs factory. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_FACTORY_OBJ_FIFOS == TRUE - * . - * - *

Test Steps

- * - [6.5.1] Retrieving a dynamic objects FIFO by name, must not exist. - * - [6.5.2] Creating a dynamic objects FIFO it must not exists, must - * succeed. - * - [6.5.3] Creating a dynamic objects FIFO with the same name, must - * fail. - * - [6.5.4] Retrieving the dynamic objects FIFO by name, must exist, - * then increasing the reference counter, finally releasing both - * references. - * - [6.5.5] Releasing the first reference to the dynamic objects FIFO - * must not trigger an assertion. - * - [6.5.6] Retrieving the dynamic objects FIFO by name again, must - * not exist. - * . - */ - -static void oslib_test_006_005_teardown(void) { - dyn_objects_fifo_t *dofp; - - dofp = chFactoryFindObjectsFIFO("myfifo"); - if (dofp != NULL) { - while (dofp->element.refs > 0U) { - chFactoryReleaseObjectsFIFO(dofp); - } - } -} - -static void oslib_test_006_005_execute(void) { - dyn_objects_fifo_t *dofp; - - /* [6.5.1] Retrieving a dynamic objects FIFO by name, must not - exist.*/ - test_set_step(1); - { - dofp = chFactoryFindObjectsFIFO("myfifo"); - test_assert(dofp == NULL, "found"); - } - - /* [6.5.2] Creating a dynamic objects FIFO it must not exists, must - succeed.*/ - test_set_step(2); - { - dofp = chFactoryCreateObjectsFIFO("myfifo", 16U, 16U, PORT_NATURAL_ALIGN); - test_assert(dofp != NULL, "cannot create"); - } - - /* [6.5.3] Creating a dynamic objects FIFO with the same name, must - fail.*/ - test_set_step(3); - { - dyn_objects_fifo_t *dofp1; - - dofp1 = chFactoryCreateObjectsFIFO("myfifo", 16U, 16U, PORT_NATURAL_ALIGN); - test_assert(dofp1 == NULL, "can create"); - } - - /* [6.5.4] Retrieving the dynamic objects FIFO by name, must exist, - then increasing the reference counter, finally releasing both - references.*/ - test_set_step(4); - { - dyn_objects_fifo_t *dofp1, *dofp2; - - dofp1 = chFactoryFindObjectsFIFO("myfifo"); - test_assert(dofp1 != NULL, "not found"); - test_assert(dofp == dofp1, "object reference mismatch"); - test_assert(dofp1->element.refs == 2, "object reference mismatch"); - - dofp2 = (dyn_objects_fifo_t *)chFactoryDuplicateReference(&dofp1->element); - test_assert(dofp1 == dofp2, "object reference mismatch"); - test_assert(dofp2->element.refs == 3, "object reference mismatch"); - - chFactoryReleaseObjectsFIFO(dofp2); - test_assert(dofp1->element.refs == 2, "references mismatch"); - - chFactoryReleaseObjectsFIFO(dofp1); - test_assert(dofp->element.refs == 1, "references mismatch"); - } - - /* [6.5.5] Releasing the first reference to the dynamic objects FIFO - must not trigger an assertion.*/ - test_set_step(5); - { - chFactoryReleaseObjectsFIFO(dofp); - } - - /* [6.5.6] Retrieving the dynamic objects FIFO by name again, must - not exist.*/ - test_set_step(6); - { - dofp = chFactoryFindObjectsFIFO("myfifo"); - test_assert(dofp == NULL, "found"); - } -} - -static const testcase_t oslib_test_006_005 = { - "Dynamic Objects FIFOs Factory", - NULL, - oslib_test_006_005_teardown, - oslib_test_006_005_execute -}; -#endif /* CH_CFG_FACTORY_OBJ_FIFOS == TRUE */ - -#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) -/** - * @page oslib_test_006_006 [6.6] Dynamic Pipes Factory - * - *

Description

- * This test case verifies the dynamic pipes factory. - * - *

Conditions

- * This test is only executed if the following preprocessor condition - * evaluates to true: - * - CH_CFG_FACTORY_PIPES == TRUE - * . - * - *

Test Steps

- * - [6.6.1] Retrieving a dynamic pipe by name, must not exist. - * - [6.6.2] Creating a dynamic pipe it must not exists, must succeed. - * - [6.6.3] Creating a dynamic pipe with the same name, must fail. - * - [6.6.4] Retrieving the dynamic pipe by name, must exist, then - * increasing the reference counter, finally releasing both - * references. - * - [6.6.5] Releasing the first reference to the dynamic pipe must not - * trigger an assertion. - * - [6.6.6] Retrieving the dynamic pipe by name again, must not exist. - * . - */ - -static void oslib_test_006_006_teardown(void) { - dyn_pipe_t *dpp; - - dpp = chFactoryFindPipe("mypipe"); - if (dpp != NULL) { - while (dpp->element.refs > 0U) { - chFactoryReleasePipe(dpp); - } - } -} - -static void oslib_test_006_006_execute(void) { - dyn_pipe_t *dpp; - - /* [6.6.1] Retrieving a dynamic pipe by name, must not exist.*/ - test_set_step(1); - { - dpp = chFactoryFindPipe("mypipe"); - test_assert(dpp == NULL, "found"); - } - - /* [6.6.2] Creating a dynamic pipe it must not exists, must - succeed.*/ - test_set_step(2); - { - dpp = chFactoryCreatePipe("mypipe", 16U); - test_assert(dpp != NULL, "cannot create"); - } - - /* [6.6.3] Creating a dynamic pipe with the same name, must fail.*/ - test_set_step(3); - { - dyn_pipe_t *dpp1; - - dpp1 = chFactoryCreatePipe("mypipe", 16U); - test_assert(dpp1 == NULL, "can create"); - } - - /* [6.6.4] Retrieving the dynamic pipe by name, must exist, then - increasing the reference counter, finally releasing both - references.*/ - test_set_step(4); - { - dyn_pipe_t *dpp1, *dpp2; - - dpp1 = chFactoryFindPipe("mypipe"); - test_assert(dpp1 != NULL, "not found"); - test_assert(dpp == dpp1, "object reference mismatch"); - test_assert(dpp1->element.refs == 2, "object reference mismatch"); - - dpp2 = (dyn_pipe_t *)chFactoryDuplicateReference(&dpp1->element); - test_assert(dpp1 == dpp2, "object reference mismatch"); - test_assert(dpp2->element.refs == 3, "object reference mismatch"); - - chFactoryReleasePipe(dpp2); - test_assert(dpp1->element.refs == 2, "references mismatch"); - - chFactoryReleasePipe(dpp1); - test_assert(dpp->element.refs == 1, "references mismatch"); - } - - /* [6.6.5] Releasing the first reference to the dynamic pipe must not - trigger an assertion.*/ - test_set_step(5); - { - chFactoryReleasePipe(dpp); - } - - /* [6.6.6] Retrieving the dynamic pipe by name again, must not - exist.*/ - test_set_step(6); - { - dpp = chFactoryFindPipe("mypipe"); - test_assert(dpp == NULL, "found"); - } -} - -static const testcase_t oslib_test_006_006 = { - "Dynamic Pipes Factory", - NULL, - oslib_test_006_006_teardown, - oslib_test_006_006_execute -}; -#endif /* CH_CFG_FACTORY_PIPES == TRUE */ /**************************************************************************** * Exported data. @@ -749,33 +276,17 @@ static const testcase_t oslib_test_006_006 = { * @brief Array of test cases. */ const testcase_t * const oslib_test_sequence_006_array[] = { -#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) &oslib_test_006_001, -#endif -#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) &oslib_test_006_002, -#endif -#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) - &oslib_test_006_003, -#endif -#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) - &oslib_test_006_004, -#endif -#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) - &oslib_test_006_005, -#endif -#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) - &oslib_test_006_006, -#endif NULL }; /** - * @brief Objects Factory. + * @brief Memory Heaps. */ const testsequence_t oslib_test_sequence_006 = { - "Objects Factory", + "Memory Heaps", oslib_test_sequence_006_array }; -#endif /* (CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE) */ +#endif /* CH_CFG_USE_HEAP */ diff --git a/test/oslib/source/test/oslib_test_sequence_007.c b/test/oslib/source/test/oslib_test_sequence_007.c new file mode 100644 index 000000000..b904d7dc7 --- /dev/null +++ b/test/oslib/source/test/oslib_test_sequence_007.c @@ -0,0 +1,817 @@ +/* + ChibiOS - Copyright (C) 2006..2017 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 "oslib_test_root.h" + +/** + * @file oslib_test_sequence_007.c + * @brief Test Sequence 007 code. + * + * @page oslib_test_sequence_007 [7] Objects Factory + * + * File: @ref oslib_test_sequence_007.c + * + *

Description

+ * This sequence tests the ChibiOS library functionalities related to + * the object factory. + * + *

Conditions

+ * This sequence is only executed if the following preprocessor condition + * evaluates to true: + * - (CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE) + * . + * + *

Test Cases

+ * - @subpage oslib_test_007_001 + * - @subpage oslib_test_007_002 + * - @subpage oslib_test_007_003 + * - @subpage oslib_test_007_004 + * - @subpage oslib_test_007_005 + * - @subpage oslib_test_007_006 + * . + */ + +#if ((CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE)) || defined(__DOXYGEN__) + +/**************************************************************************** + * Shared code. + ****************************************************************************/ + + +/**************************************************************************** + * Test cases. + ****************************************************************************/ + +#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) +/** + * @page oslib_test_007_001 [7.1] Objects Registry + * + *

Description

+ * This test case verifies the static objects registry. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE + * . + * + *

Test Steps

+ * - [7.1.1] Retrieving a registered object by name, must not exist. + * - [7.1.2] Registering an object, it must not exists, must succeed. + * - [7.1.3] Registering an object with the same name, must fail. + * - [7.1.4] Retrieving the registered object by name, must exist, then + * increasing the reference counter, finally releasing both + * references. + * - [7.1.5] Releasing the first reference to the object, must not + * trigger an assertion. + * - [7.1.6] Retrieving the registered object by name again, must not + * exist. + * . + */ + +static void oslib_test_007_001_teardown(void) { + registered_object_t *rop; + + rop = chFactoryFindObject("myobj"); + if (rop != NULL) { + while (rop->element.refs > 0U) { + chFactoryReleaseObject(rop); + } + } +} + +static void oslib_test_007_001_execute(void) { + registered_object_t *rop; + + /* [7.1.1] Retrieving a registered object by name, must not exist.*/ + test_set_step(1); + { + rop = chFactoryFindObject("myobj"); + test_assert(rop == NULL, "found"); + } + test_end_step(1); + + /* [7.1.2] Registering an object, it must not exists, must succeed.*/ + test_set_step(2); + { + static uint32_t myobj = 0x55aa; + + rop = chFactoryRegisterObject("myobj", (void *)&myobj); + test_assert(rop != NULL, "cannot register"); + } + test_end_step(2); + + /* [7.1.3] Registering an object with the same name, must fail.*/ + test_set_step(3); + { + registered_object_t *rop1; + static uint32_t myobj = 0x55aa; + + rop1 = chFactoryRegisterObject("myobj", (void *)&myobj); + test_assert(rop1 == NULL, "can register"); + } + test_end_step(3); + + /* [7.1.4] Retrieving the registered object by name, must exist, then + increasing the reference counter, finally releasing both + references.*/ + test_set_step(4); + { + registered_object_t *rop1, *rop2; + + rop1 = chFactoryFindObject("myobj"); + test_assert(rop1 != NULL, "not found"); + test_assert(*(uint32_t *)(rop1->objp) == 0x55aa, "object mismatch"); + test_assert(rop == rop1, "object reference mismatch"); + test_assert(rop1->element.refs == 2, "object reference mismatch"); + + rop2 = (registered_object_t *)chFactoryDuplicateReference(&rop1->element); + test_assert(rop1 == rop2, "object reference mismatch"); + test_assert(*(uint32_t *)(rop2->objp) == 0x55aa, "object mismatch"); + test_assert(rop2->element.refs == 3, "object reference mismatch"); + + chFactoryReleaseObject(rop2); + test_assert(rop1->element.refs == 2, "references mismatch"); + + chFactoryReleaseObject(rop1); + test_assert(rop->element.refs == 1, "references mismatch"); + } + test_end_step(4); + + /* [7.1.5] Releasing the first reference to the object, must not + trigger an assertion.*/ + test_set_step(5); + { + chFactoryReleaseObject(rop); + } + test_end_step(5); + + /* [7.1.6] Retrieving the registered object by name again, must not + exist.*/ + test_set_step(6); + { + rop = chFactoryFindObject("myobj"); + test_assert(rop == NULL, "found"); + } + test_end_step(6); +} + +static const testcase_t oslib_test_007_001 = { + "Objects Registry", + NULL, + oslib_test_007_001_teardown, + oslib_test_007_001_execute +}; +#endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */ + +#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) +/** + * @page oslib_test_007_002 [7.2] Dynamic Buffers Factory + * + *

Description

+ * This test case verifies the dynamic buffers factory. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE + * . + * + *

Test Steps

+ * - [7.2.1] Retrieving a dynamic buffer by name, must not exist. + * - [7.2.2] Creating a dynamic buffer it must not exists, must + * succeed. + * - [7.2.3] Creating a dynamic buffer with the same name, must fail. + * - [7.2.4] Retrieving the dynamic buffer by name, must exist, then + * increasing the reference counter, finally releasing both + * references. + * - [7.2.5] Releasing the first reference to the dynamic buffer, must + * not trigger an assertion. + * - [7.2.6] Retrieving the dynamic buffer by name again, must not + * exist. + * . + */ + +static void oslib_test_007_002_teardown(void) { + dyn_buffer_t *dbp; + + dbp = chFactoryFindBuffer("mybuf"); + if (dbp != NULL) { + while (dbp->element.refs > 0U) { + chFactoryReleaseBuffer(dbp); + } + } +} + +static void oslib_test_007_002_execute(void) { + dyn_buffer_t *dbp; + + /* [7.2.1] Retrieving a dynamic buffer by name, must not exist.*/ + test_set_step(1); + { + dbp = chFactoryFindBuffer("mybuf"); + test_assert(dbp == NULL, "found"); + } + test_end_step(1); + + /* [7.2.2] Creating a dynamic buffer it must not exists, must + succeed.*/ + test_set_step(2); + { + dbp = chFactoryCreateBuffer("mybuf", 128U); + test_assert(dbp != NULL, "cannot create"); + } + test_end_step(2); + + /* [7.2.3] Creating a dynamic buffer with the same name, must fail.*/ + test_set_step(3); + { + dyn_buffer_t *dbp1; + + dbp1 = chFactoryCreateBuffer("mybuf", 128U); + test_assert(dbp1 == NULL, "can create"); + } + test_end_step(3); + + /* [7.2.4] Retrieving the dynamic buffer by name, must exist, then + increasing the reference counter, finally releasing both + references.*/ + test_set_step(4); + { + dyn_buffer_t *dbp1, *dbp2; + + dbp1 = chFactoryFindBuffer("mybuf"); + test_assert(dbp1 != NULL, "not found"); + test_assert(dbp == dbp1, "object reference mismatch"); + test_assert(dbp1->element.refs == 2, "object reference mismatch"); + + dbp2 = (dyn_buffer_t *)chFactoryDuplicateReference(&dbp1->element); + test_assert(dbp1 == dbp2, "object reference mismatch"); + test_assert(dbp2->element.refs == 3, "object reference mismatch"); + + chFactoryReleaseBuffer(dbp2); + test_assert(dbp1->element.refs == 2, "references mismatch"); + + chFactoryReleaseBuffer(dbp1); + test_assert(dbp->element.refs == 1, "references mismatch"); + } + test_end_step(4); + + /* [7.2.5] Releasing the first reference to the dynamic buffer, must + not trigger an assertion.*/ + test_set_step(5); + { + chFactoryReleaseBuffer(dbp); + } + test_end_step(5); + + /* [7.2.6] Retrieving the dynamic buffer by name again, must not + exist.*/ + test_set_step(6); + { + dbp = chFactoryFindBuffer("mybuf"); + test_assert(dbp == NULL, "found"); + } + test_end_step(6); +} + +static const testcase_t oslib_test_007_002 = { + "Dynamic Buffers Factory", + NULL, + oslib_test_007_002_teardown, + oslib_test_007_002_execute +}; +#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE */ + +#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) +/** + * @page oslib_test_007_003 [7.3] Dynamic Semaphores Factory + * + *

Description

+ * This test case verifies the dynamic semaphores factory. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_FACTORY_SEMAPHORES == TRUE + * . + * + *

Test Steps

+ * - [7.3.1] Retrieving a dynamic semaphore by name, must not exist. + * - [7.3.2] Creating a dynamic semaphore it must not exists, must + * succeed. + * - [7.3.3] Creating a dynamic semaphore with the same name, must + * fail. + * - [7.3.4] Retrieving the dynamic semaphore by name, must exist, then + * increasing the reference counter, finally releasing both + * references. + * - [7.3.5] Releasing the first reference to the dynamic semaphore + * must not trigger an assertion. + * - [7.3.6] Retrieving the dynamic semaphore by name again, must not + * exist. + * . + */ + +static void oslib_test_007_003_teardown(void) { + dyn_semaphore_t *dsp; + + dsp = chFactoryFindSemaphore("mysem"); + if (dsp != NULL) { + while (dsp->element.refs > 0U) { + chFactoryReleaseSemaphore(dsp); + } + } +} + +static void oslib_test_007_003_execute(void) { + dyn_semaphore_t *dsp; + + /* [7.3.1] Retrieving a dynamic semaphore by name, must not exist.*/ + test_set_step(1); + { + dsp = chFactoryFindSemaphore("mysem"); + test_assert(dsp == NULL, "found"); + } + test_end_step(1); + + /* [7.3.2] Creating a dynamic semaphore it must not exists, must + succeed.*/ + test_set_step(2); + { + dsp = chFactoryCreateSemaphore("mysem", 0); + test_assert(dsp != NULL, "cannot create"); + } + test_end_step(2); + + /* [7.3.3] Creating a dynamic semaphore with the same name, must + fail.*/ + test_set_step(3); + { + dyn_semaphore_t *dsp1; + + dsp1 = chFactoryCreateSemaphore("mysem", 0); + test_assert(dsp1 == NULL, "can create"); + } + test_end_step(3); + + /* [7.3.4] Retrieving the dynamic semaphore by name, must exist, then + increasing the reference counter, finally releasing both + references.*/ + test_set_step(4); + { + dyn_semaphore_t *dsp1, *dsp2; + + dsp1 = chFactoryFindSemaphore("mysem"); + test_assert(dsp1 != NULL, "not found"); + test_assert(dsp == dsp1, "object reference mismatch"); + test_assert(dsp1->element.refs == 2, "object reference mismatch"); + + dsp2 = (dyn_semaphore_t *)chFactoryDuplicateReference(&dsp1->element); + test_assert(dsp1 == dsp2, "object reference mismatch"); + test_assert(dsp2->element.refs == 3, "object reference mismatch"); + + chFactoryReleaseSemaphore(dsp2); + test_assert(dsp1->element.refs == 2, "references mismatch"); + + chFactoryReleaseSemaphore(dsp1); + test_assert(dsp->element.refs == 1, "references mismatch"); + } + test_end_step(4); + + /* [7.3.5] Releasing the first reference to the dynamic semaphore + must not trigger an assertion.*/ + test_set_step(5); + { + chFactoryReleaseSemaphore(dsp); + } + test_end_step(5); + + /* [7.3.6] Retrieving the dynamic semaphore by name again, must not + exist.*/ + test_set_step(6); + { + dsp = chFactoryFindSemaphore("mysem"); + test_assert(dsp == NULL, "found"); + } + test_end_step(6); +} + +static const testcase_t oslib_test_007_003 = { + "Dynamic Semaphores Factory", + NULL, + oslib_test_007_003_teardown, + oslib_test_007_003_execute +}; +#endif /* CH_CFG_FACTORY_SEMAPHORES == TRUE */ + +#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) +/** + * @page oslib_test_007_004 [7.4] Dynamic Mailboxes Factory + * + *

Description

+ * This test case verifies the dynamic mailboxes factory. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_FACTORY_MAILBOXES == TRUE + * . + * + *

Test Steps

+ * - [7.4.1] Retrieving a dynamic mailbox by name, must not exist. + * - [7.4.2] Creating a dynamic mailbox it must not exists, must + * succeed. + * - [7.4.3] Creating a dynamic mailbox with the same name, must fail. + * - [7.4.4] Retrieving the dynamic mailbox by name, must exist, then + * increasing the reference counter, finally releasing both + * references. + * - [7.4.5] Releasing the first reference to the dynamic mailbox must + * not trigger an assertion. + * - [7.4.6] Retrieving the dynamic mailbox by name again, must not + * exist. + * . + */ + +static void oslib_test_007_004_teardown(void) { + dyn_mailbox_t *dmp; + + dmp = chFactoryFindMailbox("mymbx"); + if (dmp != NULL) { + while (dmp->element.refs > 0U) { + chFactoryReleaseMailbox(dmp); + } + } +} + +static void oslib_test_007_004_execute(void) { + dyn_mailbox_t *dmp; + + /* [7.4.1] Retrieving a dynamic mailbox by name, must not exist.*/ + test_set_step(1); + { + dmp = chFactoryFindMailbox("mymbx"); + test_assert(dmp == NULL, "found"); + } + test_end_step(1); + + /* [7.4.2] Creating a dynamic mailbox it must not exists, must + succeed.*/ + test_set_step(2); + { + dmp = chFactoryCreateMailbox("mymbx", 16U); + test_assert(dmp != NULL, "cannot create"); + } + test_end_step(2); + + /* [7.4.3] Creating a dynamic mailbox with the same name, must + fail.*/ + test_set_step(3); + { + dyn_mailbox_t *dmp1; + + dmp1 = chFactoryCreateMailbox("mymbx", 16U); + test_assert(dmp1 == NULL, "can create"); + } + test_end_step(3); + + /* [7.4.4] Retrieving the dynamic mailbox by name, must exist, then + increasing the reference counter, finally releasing both + references.*/ + test_set_step(4); + { + dyn_mailbox_t *dmp1, *dmp2; + + dmp1 = chFactoryFindMailbox("mymbx"); + test_assert(dmp1 != NULL, "not found"); + test_assert(dmp == dmp1, "object reference mismatch"); + test_assert(dmp1->element.refs == 2, "object reference mismatch"); + + dmp2 = (dyn_mailbox_t *)chFactoryDuplicateReference(&dmp1->element); + test_assert(dmp1 == dmp2, "object reference mismatch"); + test_assert(dmp2->element.refs == 3, "object reference mismatch"); + + chFactoryReleaseMailbox(dmp2); + test_assert(dmp1->element.refs == 2, "references mismatch"); + + chFactoryReleaseMailbox(dmp1); + test_assert(dmp->element.refs == 1, "references mismatch"); + } + test_end_step(4); + + /* [7.4.5] Releasing the first reference to the dynamic mailbox must + not trigger an assertion.*/ + test_set_step(5); + { + chFactoryReleaseMailbox(dmp); + } + test_end_step(5); + + /* [7.4.6] Retrieving the dynamic mailbox by name again, must not + exist.*/ + test_set_step(6); + { + dmp = chFactoryFindMailbox("mymbx"); + test_assert(dmp == NULL, "found"); + } + test_end_step(6); +} + +static const testcase_t oslib_test_007_004 = { + "Dynamic Mailboxes Factory", + NULL, + oslib_test_007_004_teardown, + oslib_test_007_004_execute +}; +#endif /* CH_CFG_FACTORY_MAILBOXES == TRUE */ + +#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) +/** + * @page oslib_test_007_005 [7.5] Dynamic Objects FIFOs Factory + * + *

Description

+ * This test case verifies the dynamic objects FIFOs factory. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_FACTORY_OBJ_FIFOS == TRUE + * . + * + *

Test Steps

+ * - [7.5.1] Retrieving a dynamic objects FIFO by name, must not exist. + * - [7.5.2] Creating a dynamic objects FIFO it must not exists, must + * succeed. + * - [7.5.3] Creating a dynamic objects FIFO with the same name, must + * fail. + * - [7.5.4] Retrieving the dynamic objects FIFO by name, must exist, + * then increasing the reference counter, finally releasing both + * references. + * - [7.5.5] Releasing the first reference to the dynamic objects FIFO + * must not trigger an assertion. + * - [7.5.6] Retrieving the dynamic objects FIFO by name again, must + * not exist. + * . + */ + +static void oslib_test_007_005_teardown(void) { + dyn_objects_fifo_t *dofp; + + dofp = chFactoryFindObjectsFIFO("myfifo"); + if (dofp != NULL) { + while (dofp->element.refs > 0U) { + chFactoryReleaseObjectsFIFO(dofp); + } + } +} + +static void oslib_test_007_005_execute(void) { + dyn_objects_fifo_t *dofp; + + /* [7.5.1] Retrieving a dynamic objects FIFO by name, must not + exist.*/ + test_set_step(1); + { + dofp = chFactoryFindObjectsFIFO("myfifo"); + test_assert(dofp == NULL, "found"); + } + test_end_step(1); + + /* [7.5.2] Creating a dynamic objects FIFO it must not exists, must + succeed.*/ + test_set_step(2); + { + dofp = chFactoryCreateObjectsFIFO("myfifo", 16U, 16U, PORT_NATURAL_ALIGN); + test_assert(dofp != NULL, "cannot create"); + } + test_end_step(2); + + /* [7.5.3] Creating a dynamic objects FIFO with the same name, must + fail.*/ + test_set_step(3); + { + dyn_objects_fifo_t *dofp1; + + dofp1 = chFactoryCreateObjectsFIFO("myfifo", 16U, 16U, PORT_NATURAL_ALIGN); + test_assert(dofp1 == NULL, "can create"); + } + test_end_step(3); + + /* [7.5.4] Retrieving the dynamic objects FIFO by name, must exist, + then increasing the reference counter, finally releasing both + references.*/ + test_set_step(4); + { + dyn_objects_fifo_t *dofp1, *dofp2; + + dofp1 = chFactoryFindObjectsFIFO("myfifo"); + test_assert(dofp1 != NULL, "not found"); + test_assert(dofp == dofp1, "object reference mismatch"); + test_assert(dofp1->element.refs == 2, "object reference mismatch"); + + dofp2 = (dyn_objects_fifo_t *)chFactoryDuplicateReference(&dofp1->element); + test_assert(dofp1 == dofp2, "object reference mismatch"); + test_assert(dofp2->element.refs == 3, "object reference mismatch"); + + chFactoryReleaseObjectsFIFO(dofp2); + test_assert(dofp1->element.refs == 2, "references mismatch"); + + chFactoryReleaseObjectsFIFO(dofp1); + test_assert(dofp->element.refs == 1, "references mismatch"); + } + test_end_step(4); + + /* [7.5.5] Releasing the first reference to the dynamic objects FIFO + must not trigger an assertion.*/ + test_set_step(5); + { + chFactoryReleaseObjectsFIFO(dofp); + } + test_end_step(5); + + /* [7.5.6] Retrieving the dynamic objects FIFO by name again, must + not exist.*/ + test_set_step(6); + { + dofp = chFactoryFindObjectsFIFO("myfifo"); + test_assert(dofp == NULL, "found"); + } + test_end_step(6); +} + +static const testcase_t oslib_test_007_005 = { + "Dynamic Objects FIFOs Factory", + NULL, + oslib_test_007_005_teardown, + oslib_test_007_005_execute +}; +#endif /* CH_CFG_FACTORY_OBJ_FIFOS == TRUE */ + +#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) +/** + * @page oslib_test_007_006 [7.6] Dynamic Pipes Factory + * + *

Description

+ * This test case verifies the dynamic pipes factory. + * + *

Conditions

+ * This test is only executed if the following preprocessor condition + * evaluates to true: + * - CH_CFG_FACTORY_PIPES == TRUE + * . + * + *

Test Steps

+ * - [7.6.1] Retrieving a dynamic pipe by name, must not exist. + * - [7.6.2] Creating a dynamic pipe it must not exists, must succeed. + * - [7.6.3] Creating a dynamic pipe with the same name, must fail. + * - [7.6.4] Retrieving the dynamic pipe by name, must exist, then + * increasing the reference counter, finally releasing both + * references. + * - [7.6.5] Releasing the first reference to the dynamic pipe must not + * trigger an assertion. + * - [7.6.6] Retrieving the dynamic pipe by name again, must not exist. + * . + */ + +static void oslib_test_007_006_teardown(void) { + dyn_pipe_t *dpp; + + dpp = chFactoryFindPipe("mypipe"); + if (dpp != NULL) { + while (dpp->element.refs > 0U) { + chFactoryReleasePipe(dpp); + } + } +} + +static void oslib_test_007_006_execute(void) { + dyn_pipe_t *dpp; + + /* [7.6.1] Retrieving a dynamic pipe by name, must not exist.*/ + test_set_step(1); + { + dpp = chFactoryFindPipe("mypipe"); + test_assert(dpp == NULL, "found"); + } + test_end_step(1); + + /* [7.6.2] Creating a dynamic pipe it must not exists, must + succeed.*/ + test_set_step(2); + { + dpp = chFactoryCreatePipe("mypipe", 16U); + test_assert(dpp != NULL, "cannot create"); + } + test_end_step(2); + + /* [7.6.3] Creating a dynamic pipe with the same name, must fail.*/ + test_set_step(3); + { + dyn_pipe_t *dpp1; + + dpp1 = chFactoryCreatePipe("mypipe", 16U); + test_assert(dpp1 == NULL, "can create"); + } + test_end_step(3); + + /* [7.6.4] Retrieving the dynamic pipe by name, must exist, then + increasing the reference counter, finally releasing both + references.*/ + test_set_step(4); + { + dyn_pipe_t *dpp1, *dpp2; + + dpp1 = chFactoryFindPipe("mypipe"); + test_assert(dpp1 != NULL, "not found"); + test_assert(dpp == dpp1, "object reference mismatch"); + test_assert(dpp1->element.refs == 2, "object reference mismatch"); + + dpp2 = (dyn_pipe_t *)chFactoryDuplicateReference(&dpp1->element); + test_assert(dpp1 == dpp2, "object reference mismatch"); + test_assert(dpp2->element.refs == 3, "object reference mismatch"); + + chFactoryReleasePipe(dpp2); + test_assert(dpp1->element.refs == 2, "references mismatch"); + + chFactoryReleasePipe(dpp1); + test_assert(dpp->element.refs == 1, "references mismatch"); + } + test_end_step(4); + + /* [7.6.5] Releasing the first reference to the dynamic pipe must not + trigger an assertion.*/ + test_set_step(5); + { + chFactoryReleasePipe(dpp); + } + test_end_step(5); + + /* [7.6.6] Retrieving the dynamic pipe by name again, must not + exist.*/ + test_set_step(6); + { + dpp = chFactoryFindPipe("mypipe"); + test_assert(dpp == NULL, "found"); + } + test_end_step(6); +} + +static const testcase_t oslib_test_007_006 = { + "Dynamic Pipes Factory", + NULL, + oslib_test_007_006_teardown, + oslib_test_007_006_execute +}; +#endif /* CH_CFG_FACTORY_PIPES == TRUE */ + +/**************************************************************************** + * Exported data. + ****************************************************************************/ + +/** + * @brief Array of test cases. + */ +const testcase_t * const oslib_test_sequence_007_array[] = { +#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) + &oslib_test_007_001, +#endif +#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) + &oslib_test_007_002, +#endif +#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) + &oslib_test_007_003, +#endif +#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) + &oslib_test_007_004, +#endif +#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) + &oslib_test_007_005, +#endif +#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) + &oslib_test_007_006, +#endif + NULL +}; + +/** + * @brief Objects Factory. + */ +const testsequence_t oslib_test_sequence_007 = { + "Objects Factory", + oslib_test_sequence_007_array +}; + +#endif /* (CH_CFG_USE_FACTORY == TRUE) && (CH_CFG_USE_MEMPOOLS == TRUE) && (CH_CFG_USE_HEAP == TRUE) */ diff --git a/test/oslib/source/test/oslib_test_sequence_007.h b/test/oslib/source/test/oslib_test_sequence_007.h new file mode 100644 index 000000000..04817872d --- /dev/null +++ b/test/oslib/source/test/oslib_test_sequence_007.h @@ -0,0 +1,27 @@ +/* + ChibiOS - Copyright (C) 2006..2017 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 oslib_test_sequence_007.h + * @brief Test Sequence 007 header. + */ + +#ifndef OSLIB_TEST_SEQUENCE_007_H +#define OSLIB_TEST_SEQUENCE_007_H + +extern const testsequence_t oslib_test_sequence_007; + +#endif /* OSLIB_TEST_SEQUENCE_007_H */