ud3tn/test/unit/test_simple_queue.c
Felix Walter 62d563449f test: Remove the Unity wrappers for memory allocation functions
This adds a custom header that does explicitly not include the Unity
wrappers for malloc, free, etc. by defining the guard used by that header
file. This way we can remove the wrappers provided via the linker
altogether.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2023-05-15 11:39:29 +02:00

377 lines
10 KiB
C

// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#ifdef PLATFORM_POSIX
#include "platform/hal_semaphore.h"
#include "platform/posix/hal_types.h"
#include "platform/posix/simple_queue.h"
#include "testud3tn_unity.h"
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <time.h>
#ifndef __APPLE__
#include <semaphore.h>
#endif //__APPLE__
TEST_GROUP(simple_queue);
TEST_SETUP(simple_queue)
{
}
TEST_TEAR_DOWN(simple_queue)
{
}
TEST(simple_queue, test_createQueue)
{
// create a queue
Queue_t *q = queueCreate(2, 4);
TEST_ASSERT_NOT_NULL(q);
TEST_ASSERT_EQUAL_UINT(q->item_length, 2);
TEST_ASSERT_EQUAL_UINT(q->item_size, 4);
TEST_ASSERT_NOT_NULL(q->abs_start);
TEST_ASSERT_NOT_NULL(q->abs_end);
TEST_ASSERT_NOT_NULL(q->current_start);
TEST_ASSERT_NOT_NULL(q->current_end);
TEST_ASSERT_EQUAL_PTR(q->abs_start, q->current_start);
TEST_ASSERT_EQUAL_PTR(q->abs_start, q->current_end);
TEST_ASSERT_EQUAL_PTR(q->abs_end, q->abs_start+8);
}
TEST(simple_queue, test_PushPopBasic)
{
// create a queue
Queue_t *q = queueCreate(1, sizeof(int));
const int i = 42;
TEST_ASSERT_EQUAL_PTR(q->abs_start, q->current_start);
TEST_ASSERT_EQUAL_PTR(q->abs_start, q->current_end);
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &i, 0, false));
TEST_ASSERT_EQUAL_INT(i, (int)(q->current_start)[0]);
int j;
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &j, 0));
TEST_ASSERT_EQUAL_INT(i, j);
}
TEST(simple_queue, test_PushFullPopFull)
{
// create a queue
Queue_t *q = queueCreate(10, sizeof(int));
int i, j;
for (i = 0; i <= 9; i++) {
// the first ten insertions should be successful
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &i, 0, false));
}
// the eleventh insertion (without force) should fail
TEST_ASSERT_EQUAL_INT(1, queuePush(q, &i, 0, false));
for (i = 0; i <= 9; i++) {
// the first ten removals should be successful
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &j, 0));
// the removed values should have the correct order
TEST_ASSERT_EQUAL_INT(i, j);
}
// the eleventh removal should fail
TEST_ASSERT_EQUAL_INT(1, queuePop(q, &j, 0));
}
TEST(simple_queue, test_PushEndPopEnd)
{
// create a queue
Queue_t *q = queueCreate(10, sizeof(int));
int i, j;
for (i = 0; i <= 9; i++) {
// the first ten insertions should be successful
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &i, 0, false));
}
for (i = 0; i <= 9; i++) {
// the first ten removals should be successful
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &j, 0));
// the removed values should have the correct order
TEST_ASSERT_EQUAL_INT(i, j);
}
// from here on we should start at the abs_start of the queue again!
for (i = 20; i <= 29; i++) {
// the first ten insertions should be successful
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &i, 0, false));
}
for (i = 20; i <= 29; i++) {
// the first ten removals should be successful
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &j, 0));
// the removed values should have the correct order
TEST_ASSERT_EQUAL_INT(i, j);
}
}
TEST(simple_queue, test_CircularBehaviour)
{
// create a queue
Queue_t *q = queueCreate(10, sizeof(int));
int i, j, k, l, m, n;
// test for two circular rounds with two elements
for (i = 0; i <= 19; i += 2) {
j = i+1;
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &i, 0, false));
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &j, 0, false));
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &k, 0));
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &l, 0));
// the removed values should have the correct values
TEST_ASSERT_EQUAL_INT(i, k);
TEST_ASSERT_EQUAL_INT(j, l);
}
// test for three circular rounds with three elements
for (i = 0; i <= 29; i += 3) {
j = i + 1;
k = j + 1;
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &i, 0, false));
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &j, 0, false));
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &k, 0, false));
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &l, 0));
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &m, 0));
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &n, 0));
// the removed values should have the correct values
TEST_ASSERT_EQUAL_INT(i, l);
TEST_ASSERT_EQUAL_INT(j, m);
TEST_ASSERT_EQUAL_INT(k, n);
}
}
TEST(simple_queue, test_ResetQueue)
{
// create a queue
Queue_t *q = queueCreate(10, sizeof(int));
int i, j;
for (i = 0; i <= 5; i++)
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &i, 0, false));
for (i = 0; i <= 3; i++) {
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &j, 0));
TEST_ASSERT_EQUAL_INT(i, j);
}
// check that the ptrs are not equal
TEST_ASSERT_NOT_EQUAL(q->abs_start, q->current_start);
TEST_ASSERT_NOT_EQUAL(q->abs_start, q->current_end);
#ifndef __APPLE__
// Apple systems use another implementation of the semaphore.
int value_pop, value_push;
sem_getvalue(&q->sem_pop->sem, &value_pop);
sem_getvalue(&q->sem_push->sem, &value_push);
TEST_ASSERT_EQUAL_INT(2, value_pop);
TEST_ASSERT_EQUAL_INT(8, value_push);
#endif //__APPLE__
queueReset(q);
TEST_ASSERT_EQUAL_PTR(q->abs_start, q->current_start);
TEST_ASSERT_EQUAL_PTR(q->abs_start, q->current_end);
#ifndef __APPLE__
sem_getvalue(&q->sem_pop->sem, &value_pop);
sem_getvalue(&q->sem_push->sem, &value_push);
TEST_ASSERT_EQUAL_INT(0, value_pop);
TEST_ASSERT_EQUAL_INT(10, value_push);
#endif //__APPLE__
}
TEST(simple_queue, test_NrOfWaitingElements)
{
// create a queue
Queue_t *q = queueCreate(10, sizeof(int));
int i, j;
for (i = 0; i <= 8; i++)
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &i, 0, false));
#ifndef __APPLE__
int value;
sem_getvalue(&q->sem_pop->sem, &value);
TEST_ASSERT_EQUAL_UINT(9, value);
#endif //__APPLE__
for (i = 0; i <= 3; i++) {
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &j, 0));
TEST_ASSERT_EQUAL_INT(i, j);
}
#ifndef __APPLE__
sem_getvalue(&q->sem_pop->sem, &value);
TEST_ASSERT_EQUAL_UINT(5, value);
#endif //__APPLE__
for (i = 4; i <= 8; i++) {
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &j, 0));
TEST_ASSERT_EQUAL_INT(i, j);
}
#ifndef __APPLE__
sem_getvalue(&q->sem_pop->sem, &value);
TEST_ASSERT_EQUAL_UINT(0, value);
#endif //__APPLE__
}
TEST(simple_queue, test_ForcePush)
{
// create a queue
Queue_t *q = queueCreate(10, sizeof(int));
int i, j;
for (i = 0; i <= 9; i++) {
// the first ten insertions should be successful
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &i, 0, false));
}
// the eleventh insertion (without force) should fail
TEST_ASSERT_EQUAL_INT(1, queuePush(q, &i, 0, false));
i = 42;
// the eleventh insertion (with force) should succeed
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &i, 0, true));
for (i = 0; i <= 8; i++) {
// the first nine removals should be standard
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &j, 0));
// the removed values should have the correct order
TEST_ASSERT_EQUAL_INT(i, j);
}
// the last removal should still be successful
TEST_ASSERT_EQUAL_INT(0, queuePop(q, &j, 0));
// the removed value should have the forced value
TEST_ASSERT_EQUAL_INT(42, j);
}
// returns difference in ms
int ms_diff(struct timespec *start, struct timespec *stop)
{
struct timespec result;
if ((stop->tv_nsec - start->tv_nsec) < 0) {
result.tv_sec = stop->tv_sec - start->tv_sec - 1;
result.tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;
} else {
result.tv_sec = stop->tv_sec - start->tv_sec;
result.tv_nsec = stop->tv_nsec - start->tv_nsec;
}
return result.tv_sec * 1000 + (result.tv_nsec / 1000000);
}
#define MAX_DELAY_INCREASE_MS 200
TEST(simple_queue, test_SemaphoreTimingBehaviour)
{
struct timespec ts1, ts2;
// create a queue
Queue_t *q = queueCreate(10, sizeof(int));
int i, j;
// a removal with timeout 0 should fail immediately
clock_gettime(CLOCK_REALTIME, &ts1);
TEST_ASSERT_EQUAL_INT(1, queuePop(q, &j, 0));
clock_gettime(CLOCK_REALTIME, &ts2);
// allow a little deviation due to the overhead
TEST_ASSERT_TRUE(ms_diff(&ts1, &ts2) < MAX_DELAY_INCREASE_MS);
// a removal with timeout 100ms should fail eventually
clock_gettime(CLOCK_REALTIME, &ts1);
TEST_ASSERT_EQUAL_INT(1, queuePop(q, &j, 100));
clock_gettime(CLOCK_REALTIME, &ts2);
// allow a little deviation due to the overhead
TEST_ASSERT_TRUE(ms_diff(&ts1, &ts2) > 98);
TEST_ASSERT_TRUE(ms_diff(&ts1, &ts2) < 100 + MAX_DELAY_INCREASE_MS);
// a removal with timeout 2000ms should fail eventually
clock_gettime(CLOCK_REALTIME, &ts1);
TEST_ASSERT_EQUAL_INT(1, queuePop(q, &j, 2000));
clock_gettime(CLOCK_REALTIME, &ts2);
// allow a little deviation due to the overhead
TEST_ASSERT_TRUE(ms_diff(&ts1, &ts2) > 1998);
TEST_ASSERT_TRUE(ms_diff(&ts1, &ts2) < 2000 + MAX_DELAY_INCREASE_MS);
for (i = 0; i <= 9; i++) {
// the first ten insertions should be successful
TEST_ASSERT_EQUAL_INT(0, queuePush(q, &i, 0, false));
}
// a insertion with timeout 0 should fail immediately
clock_gettime(CLOCK_REALTIME, &ts1);
TEST_ASSERT_EQUAL_INT(1, queuePush(q, &i, 0, false));
clock_gettime(CLOCK_REALTIME, &ts2);
// allow a little deviation due to the overhead
TEST_ASSERT_TRUE(ms_diff(&ts1, &ts2) < MAX_DELAY_INCREASE_MS);
// a insertion with timeout 100ms should fail eventually
clock_gettime(CLOCK_REALTIME, &ts1);
TEST_ASSERT_EQUAL_INT(1, queuePush(q, &i, 100, false));
clock_gettime(CLOCK_REALTIME, &ts2);
// allow a little deviation due to the overhead
TEST_ASSERT_TRUE(ms_diff(&ts1, &ts2) > 98);
TEST_ASSERT_TRUE(ms_diff(&ts1, &ts2) < 100 + MAX_DELAY_INCREASE_MS);
// a insertion with timeout 2000ms should fail eventually
clock_gettime(CLOCK_REALTIME, &ts1);
TEST_ASSERT_EQUAL_INT(1, queuePush(q, &i, 2000, false));
clock_gettime(CLOCK_REALTIME, &ts2);
// allow a little deviation due to the overhead
TEST_ASSERT_TRUE(ms_diff(&ts1, &ts2) > 1998);
TEST_ASSERT_TRUE(ms_diff(&ts1, &ts2) < 2000 + MAX_DELAY_INCREASE_MS);
}
TEST_GROUP_RUNNER(simple_queue)
{
RUN_TEST_CASE(simple_queue, test_createQueue);
RUN_TEST_CASE(simple_queue, test_PushPopBasic);
RUN_TEST_CASE(simple_queue, test_PushFullPopFull);
RUN_TEST_CASE(simple_queue, test_PushEndPopEnd);
RUN_TEST_CASE(simple_queue, test_CircularBehaviour);
RUN_TEST_CASE(simple_queue, test_ResetQueue);
RUN_TEST_CASE(simple_queue, test_NrOfWaitingElements);
RUN_TEST_CASE(simple_queue, test_ForcePush);
RUN_TEST_CASE(simple_queue, test_SemaphoreTimingBehaviour);
}
#endif // PLATFORM_POSIX