mirror of
https://gitlab.com/d3tn/ud3tn.git
synced 2026-08-13 12:33:27 +02:00
392 lines
10 KiB
C
392 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);
|
|
|
|
queueDelete(q);
|
|
}
|
|
|
|
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);
|
|
|
|
queueDelete(q);
|
|
}
|
|
|
|
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));
|
|
|
|
queueDelete(q);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
queueDelete(q);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
queueDelete(q);
|
|
}
|
|
|
|
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__
|
|
|
|
queueDelete(q);
|
|
}
|
|
|
|
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__
|
|
|
|
queueDelete(q);
|
|
}
|
|
|
|
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);
|
|
|
|
queueDelete(q);
|
|
}
|
|
|
|
// 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);
|
|
|
|
queueDelete(q);
|
|
}
|
|
|
|
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
|