1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-16 00:00:02 +01:00
VILLASnode/tests/unit/queue_signalled.cpp

156 lines
3.5 KiB
C++
Raw Normal View History

/* Unit tests for queue_signalled.
*
* Author: Steffen Vogel <post@steffenvogel.de>
* SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
* SPDX-License-Identifier: Apache-2.0
*/
#include <criterion/criterion.h>
#include <criterion/parameterized.h>
#include <pthread.h>
#include <poll.h>
#include <villas/utils.hpp>
#include <villas/node/memory.hpp>
2018-03-26 12:50:15 +02:00
#include <villas/queue_signalled.h>
using namespace villas::node;
extern
void init_memory();
#define NUM_ELEM 1000
struct param {
2019-06-23 16:13:23 +02:00
enum QueueSignalledMode mode;
int flags;
2018-10-21 13:00:50 +01:00
bool polled;
};
static
void * producer(void * ctx)
{
int ret;
struct CQueueSignalled *q = (struct CQueueSignalled *) ctx;
for (intptr_t i = 0; i < NUM_ELEM; i++) {
ret = queue_signalled_push(q, (void *) i);
if (ret != 1)
return (void *) 1; // Indicates an error to the parent thread
2018-03-26 12:50:15 +02:00
usleep(0.1e-3 * 1e6); // 1 ms
}
2018-03-26 12:50:15 +02:00
2018-08-27 11:21:57 +02:00
return nullptr;
}
static
void * consumer(void * ctx)
{
int ret;
struct CQueueSignalled *q = (struct CQueueSignalled *) ctx;
2018-03-26 12:50:15 +02:00
void *data[NUM_ELEM];
2018-03-26 12:50:15 +02:00
for (intptr_t i = 0; i < NUM_ELEM;) {
ret = queue_signalled_pull_many(q, data, ARRAY_LEN(data));
if (ret <= 0)
return (void *) 1; // Indicates an error to the parent thread
2018-03-26 12:50:15 +02:00
for (intptr_t j = 0; j < ret; j++, i++) {
if ((intptr_t) data[j] != i)
return (void *) 2; // Indicates an error to the parent thread
}
}
2018-08-27 11:21:57 +02:00
return nullptr;
}
2018-03-26 12:50:15 +02:00
void * polled_consumer(void *ctx)
{
int ret, fd;
struct CQueueSignalled *q = (struct CQueueSignalled *) ctx;
2018-03-26 12:50:15 +02:00
fd = queue_signalled_fd(q);
cr_assert_geq(fd, 0);
struct pollfd pfd = {
.fd = fd,
.events = POLLIN
};
for (intptr_t i = 0; i < NUM_ELEM; i++) {
again: ret = poll(&pfd, 1, -1);
if (ret < 0)
return (void *) 3;
else if (ret == 0)
goto again;
2018-03-26 12:50:15 +02:00
void *p;
ret = queue_signalled_pull(q, &p);
if (ret != 1)
return (void *) 1; // Indicates an error to the parent thread
2018-03-26 12:50:15 +02:00
if ((intptr_t) p != i)
return (void *) 2; // Indicates an error to the parent thread
}
2018-03-26 12:50:15 +02:00
2018-08-27 11:21:57 +02:00
return nullptr;
}
ParameterizedTestParameters(queue_signalled, simple)
{
static
struct param params[] = {
2019-06-23 16:13:23 +02:00
{ QueueSignalledMode::AUTO, 0, false },
{ QueueSignalledMode::PTHREAD, 0, false },
{ QueueSignalledMode::PTHREAD, 0, false },
{ QueueSignalledMode::PTHREAD, (int) QueueSignalledFlags::PROCESS_SHARED, false },
{ QueueSignalledMode::POLLING, 0, false },
2018-08-09 14:19:35 +02:00
#if defined(__linux__) && defined(HAS_EVENTFD)
2019-06-23 16:13:23 +02:00
{ QueueSignalledMode::EVENTFD, 0, false },
{ QueueSignalledMode::EVENTFD, 0, true }
#endif
};
2018-03-26 12:50:15 +02:00
return cr_make_param_array(struct param, params, ARRAY_LEN(params));
}
// cppcheck-suppress unknownMacro
ParameterizedTest(struct param *param, queue_signalled, simple, .timeout = 5, .init = init_memory)
{
int ret;
void *r1, *r2;
struct CQueueSignalled q;
2018-03-26 12:50:15 +02:00
pthread_t t1, t2;
2018-03-26 12:50:15 +02:00
ret = queue_signalled_init(&q, LOG2_CEIL(NUM_ELEM), &memory::heap, param->mode, param->flags);
2019-06-23 16:13:23 +02:00
cr_assert_eq(ret, 0, "Failed to initialize queue: mode=%d, flags=%#x, ret=%d", (int) param->mode, param->flags, ret);
2018-03-26 12:50:15 +02:00
2018-08-27 11:21:57 +02:00
ret = pthread_create(&t1, nullptr, producer, &q);
cr_assert_eq(ret, 0);
2018-03-26 12:50:15 +02:00
2018-08-27 11:21:57 +02:00
ret = pthread_create(&t2, nullptr, param->polled ? polled_consumer : consumer, &q);
cr_assert_eq(ret, 0);
2018-03-26 12:50:15 +02:00
ret = pthread_join(t1, &r1);
cr_assert_eq(ret, 0);
2018-03-26 12:50:15 +02:00
ret = pthread_join(t2, &r2);
cr_assert_eq(ret, 0);
2018-03-26 12:50:15 +02:00
cr_assert_null(r1, "Producer failed: %p", r1);
cr_assert_null(r2, "Consumer failed: %p", r2);
2018-03-26 12:50:15 +02:00
ret = queue_signalled_available(&q);
cr_assert_eq(ret, 0);
ret = queue_signalled_close(&q);
2018-03-26 12:50:15 +02:00
cr_assert_eq(ret, 0);
ret = queue_signalled_destroy(&q);
2018-03-26 12:50:15 +02:00
cr_assert_eq(ret, 0);
}