ChibiOS OS Library Test Suite.
Test suite for ChibiOS OS Library. The purpose of this
suite is to perform unit tests on the library modules and to
converge to 100% code coverage through successive improvements.
oslib_
Internal Tests
Information.
This sequence reports configuration and version
information about the OS library.
Port Info.
Port-related info are reported.
Prints the version string.
OS Library Info.
The version numbers are reported.
Prints the version string.
OS Library Settings.
The static OS Library settings are reported.
Prints the configuration options settings.
Internal Tests
Mailboxes.
This sequence tests the ChibiOS library functionalities
related to mailboxes.
Mailbox normal API, non-blocking tests.
The mailbox normal API is tested without triggering
blocking conditions.
Testing the mailbox size.
Resetting the mailbox, conditions are checked, no
errors expected.
Testing the behavior of API when the mailbox is
in reset state then return in active state.
Filling the mailbox using chMBPostTimeout() and
chMBPostAheadTimeout() once, no errors expected.
Testing intermediate conditions. Data pointers
must be aligned, semaphore counters are checked.
Emptying the mailbox using chMBFetchTimeout(), no
errors expected.
Posting and then fetching one more message, no
errors expected.
Testing final conditions. Data pointers must be
aligned to buffer start, semaphore counters are
checked.
Mailbox I-Class API, non-blocking tests.
The mailbox I-Class API is tested without triggering
blocking conditions.
Testing the mailbox size.
Resetting the mailbox, conditions are checked, no
errors expected. The mailbox is then returned in
active state.
Filling the mailbox using chMBPostI() and
chMBPostAheadI() once, no errors expected.
Testing intermediate conditions. Data pointers
must be aligned, semaphore counters are checked.
Emptying the mailbox using chMBFetchI(), no
errors expected.
Posting and then fetching one more message, no
errors expected.
Testing final conditions. Data pointers must be
aligned to buffer start, semaphore counters are
checked.
Mailbox timeouts.
The mailbox API is tested for timeouts.
Filling the mailbox.
Testing chMBPostTimeout(), chMBPostI(),
chMBPostAheadTimeout() and chMBPostAheadI() timeout.
Resetting the mailbox. The mailbox is then
returned in active state.
Testing chMBFetchTimeout() and chMBFetchI()
timeout.
Internal Tests
Pipes
This sequence tests the ChibiOS library functionalities
related to pipes.
#define PIPE_SIZE 16
static uint8_t buffer[PIPE_SIZE];
static PIPE_DECL(pipe1, buffer, PIPE_SIZE);
static const uint8_t pipe_pattern[] = "0123456789ABCDEF";]]>
Pipes normal API, non-blocking tests.
The pipe functionality is tested by loading and
emptying it, all conditions are tested.
Resetting pipe.
Writing data, must fail.
Reading data, must fail.
Reactivating pipe.
Filling whole pipe.
Emptying pipe.
Small write.
Filling remaining space.
Small Read.
Reading remaining data.
Small Write.
Small Read.
Write wrapping buffer boundary.
Read wrapping buffer boundary.
Pipe timeouts.
The pipe API is tested for timeouts.
Reading while pipe is empty.
Writing a string larger than pipe buffer.
Internal Tests
Jobs Queues
This sequence tests the ChibiOS library functionalities
related to Jobs Queues.
Dispatcher test.
The dispatcher API is tested for functionality.
Initializing the Jobs Queue object.
Starting the dispatcher threads.
Sending jobs with various timings.
jobfunc = job_slow;
jdp->jobarg = (void *)('a' + i);
chJobPost(&jq, jdp);
}
]]>
Sending two null jobs to make threads exit.
jobfunc = NULL;
jdp->jobarg = NULL;
chJobPost(&jq, jdp);
jdp = chJobGet(&jq);
jdp->jobfunc = NULL;
jdp->jobarg = NULL;
chJobPost(&jq, jdp);
(void) chThdWait(tp1);
(void) chThdWait(tp2);
test_assert_sequence("abcdefgh", "unexpected tokens");
]]>
Internal Tests
Thread Delegates
This sequence tests the ChibiOS library functionalities
related to Thread Delegates.
Dispatcher test.
The dispatcher API is tested for functionality.
Starting the dispatcher thread.
Calling the default veneers, checking the result
and the emitted tokens.
Waiting for the thread to terminate-
Internal Tests
Objects Caches
This sequence tests the ChibiOS library functionalities
related to Objects 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
Memory Pools.
This sequence tests the ChibiOS library functionalities
related to memory pools.
Loading and emptying a memory pool.
The memory pool functionality is tested by loading
and emptying it, all conditions are tested.
Adding the objects to the pool using
chPoolLoadArray().
Emptying the pool using chPoolAlloc().
Now must be empty.
Adding the objects to the pool using
chPoolFree().
Emptying the pool using chPoolAlloc() again.
Now must be empty again.
Covering the case where a provider is unable to
return more memory.
Loading and emptying a guarded memory pool without waiting.
The memory pool functionality is tested by loading
and emptying it, all conditions are tested.
Adding the objects to the pool using
chGuardedPoolLoadArray().
Emptying the pool using
chGuardedPoolAllocTimeout().
Now must be empty.
Adding the objects to the pool using
chGuardedPoolFree().
Emptying the pool using
chGuardedPoolAllocTimeout() again.
Now must be empty again.
Guarded Memory Pools timeout.
The timeout features for the Guarded Memory Pools is
tested.
Trying to allocate with 100mS timeout, must fail
because the pool is empty.
Internal Tests
Memory Heaps.
This sequence tests the ChibiOS library functionalities
related to memory heaps.
Allocation and fragmentation.
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.
Testing initial conditions, the heap must not be
fragmented and one free block present, finally, integrity is checked.
Trying to allocate an block bigger than available
space, an error is expected, finally, integrity is checked.
Single block allocation using chHeapAlloc() then
the block is freed using chHeapFree(), must not fail, finally,
integrity is checked.
Using chHeapStatus() to assess the heap state.
There must be at least one free block of sufficient
size, finally, integrity is checked.
= ALLOC_SIZE, "unexpected heap state");
test_assert(total_size == largest_size, "unexpected heap state");
test_assert(!chHeapIntegrityCheck(&test_heap), "integrity failure");]]>
Allocating then freeing in the same order, finally,
integrity is checked.
Allocating then freeing in reverse order, finally,
integrity is checked.
Small fragments handling. Checking the behavior
when allocating blocks with size not multiple of
alignment unit, finally, integrity is checked.
Skipping a fragment, the first fragment in the
list is too small so the allocator must pick the
second one, finally, integrity is checked.
Allocating the whole available space, finally,
integrity is checked.
Testing final conditions. The heap geometry must
be the same than the one registered at beginning, finally,
integrity is checked.
Default Heap.
The default heap is pre-allocated in the system. We
test base functionality.
Single block allocation using chHeapAlloc() then
the block is freed using chHeapFree(), must not fail.
Testing allocation failure.
Internal Tests
Objects Factory.
This sequence tests the ChibiOS library functionalities
related to the object factory.
Objects Registry.
This test case verifies the static objects registry.
element.refs > 0U) {
chFactoryReleaseObject(rop);
}
}]]>
Retrieving a registered object by name, must not
exist.
Registering an object, it must not exists, must
succeed.
Registering an object with the same name, must
fail.
Retrieving the registered object by name, must
exist, then increasing the reference counter, finally
releasing both references.
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");]]>
Releasing the first reference to the object, must
not trigger an assertion.
Retrieving the registered object by name again,
must not exist.
Dynamic Buffers Factory.
This test case verifies the dynamic buffers factory.
element.refs > 0U) {
chFactoryReleaseBuffer(dbp);
}
}]]>
Retrieving a dynamic buffer by name, must not
exist.
Creating a dynamic buffer it must not exists,
must succeed.
Creating a dynamic buffer with the same name,
must fail.
Retrieving the dynamic buffer by name, must
exist, then increasing the reference counter, finally
releasing both references.
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");]]>
Releasing the first reference to the dynamic
buffer, must not trigger an assertion.
Retrieving the dynamic buffer by name again, must
not exist.
Dynamic Semaphores Factory.
This test case verifies the dynamic semaphores
factory.
element.refs > 0U) {
chFactoryReleaseSemaphore(dsp);
}
}]]>
Retrieving a dynamic semaphore by name, must not
exist.
Creating a dynamic semaphore it must not exists,
must succeed.
Creating a dynamic semaphore with the same name,
must fail.
Retrieving the dynamic semaphore by name, must
exist, then increasing the reference counter, finally
releasing both references.
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");]]>
Releasing the first reference to the dynamic
semaphore must not trigger an assertion.
Retrieving the dynamic semaphore by name again,
must not exist.
Dynamic Mailboxes Factory.
This test case verifies the dynamic mailboxes
factory.
element.refs > 0U) {
chFactoryReleaseMailbox(dmp);
}
}]]>
Retrieving a dynamic mailbox by name, must not
exist.
Creating a dynamic mailbox it must not exists,
must succeed.
Creating a dynamic mailbox with the same name,
must fail.
Retrieving the dynamic mailbox by name, must
exist, then increasing the reference counter, finally
releasing both references.
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");]]>
Releasing the first reference to the dynamic
mailbox must not trigger an assertion.
Retrieving the dynamic mailbox by name again,
must not exist.
Dynamic Objects FIFOs Factory.
This test case verifies the dynamic objects FIFOs
factory.
element.refs > 0U) {
chFactoryReleaseObjectsFIFO(dofp);
}
}]]>
Retrieving a dynamic objects FIFO by name, must
not exist.
Creating a dynamic objects FIFO it must not
exists, must succeed.
Creating a dynamic objects FIFO with the same
name, must fail.
Retrieving the dynamic objects FIFO by name, must
exist, then increasing the reference counter, finally
releasing both references.
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");]]>
Releasing the first reference to the dynamic
objects FIFO must not trigger an assertion.
Retrieving the dynamic objects FIFO by name
again, must not exist.
Dynamic Pipes Factory.
This test case verifies the dynamic pipes factory.
element.refs > 0U) {
chFactoryReleasePipe(dpp);
}
}]]>
Retrieving a dynamic pipe by name, must not
exist.
Creating a dynamic pipe it must not exists, must
succeed.
Creating a dynamic pipe with the same name, must
fail.
Retrieving the dynamic pipe by name, must exist,
then increasing the reference counter, finally
releasing both references.
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");]]>
Releasing the first reference to the dynamic pipe
must not trigger an assertion.
Retrieving the dynamic pipe by name again, must
not exist.