mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
Merge branch 'develop' into feature-mpmc-queue
This commit is contained in:
commit
3e93dfe17c
24 changed files with 288 additions and 106 deletions
|
@ -19,7 +19,8 @@ docker-image:
|
|||
stage: prepare
|
||||
# Must match the docker version on the build machine!
|
||||
before_script:
|
||||
- git submodule update --init --recursive
|
||||
- git submodule sync --recursive
|
||||
- git submodule update --recursive --init
|
||||
- docker info
|
||||
script:
|
||||
- docker build -t $DOCKER_REGISTRY/$DOCKER_IMAGE .
|
||||
|
@ -78,8 +79,7 @@ unit:
|
|||
dependencies:
|
||||
- build
|
||||
script:
|
||||
- make tests
|
||||
- build/release/testsuite
|
||||
- make run-tests
|
||||
image: $DOCKER_REGISTRY/$DOCKER_IMAGE
|
||||
tags:
|
||||
- docker
|
||||
|
|
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -9,7 +9,7 @@
|
|||
url = https://github.com/warmcat/libwebsockets
|
||||
[submodule "thirdparty/criterion"]
|
||||
path = thirdparty/criterion
|
||||
url = https://github.com/stv0g/Criterion
|
||||
url = https://github.com/Snaipe/Criterion
|
||||
[submodule "thirdparty/libnl"]
|
||||
path = thirdparty/libnl
|
||||
url = https://github.com/thom311/libnl.git
|
||||
|
|
3
config.h
3
config.h
|
@ -24,9 +24,6 @@
|
|||
#define DEFAULT_VALUES 64
|
||||
#define DEFAULT_QUEUELEN 1024
|
||||
|
||||
/** Whether or not to send / receive timestamp & sequence number as first values of payload */
|
||||
#define GTNET_SKT_HEADER 1
|
||||
|
||||
/** Width of log output in characters */
|
||||
#define LOG_WIDTH 132
|
||||
|
||||
|
|
|
@ -26,16 +26,24 @@ nodes = {
|
|||
|
||||
### The following settings are specific to the socket node-type!! ###
|
||||
|
||||
layer = "udp" # Layer can be one of:
|
||||
# udp Send / recv UDP packets
|
||||
# ip Send / recv IP packets
|
||||
# eth Send / recv raw Ethernet frames (IEEE802.3)
|
||||
layer = "udp", # Layer can be one of:
|
||||
# udp Send / receive UDP packets
|
||||
# ip Send / receive IP packets
|
||||
# eth Send / receive raw Ethernet frames (IEEE802.3)
|
||||
|
||||
|
||||
header = "gtnet-skt:fake", # Header can be one of:
|
||||
# default | villas Use VILLASnode protocol (see struct msg) (default)
|
||||
# none | gtnet-skt Use no header, send raw data as used by RTDS GTNETv2-SKT
|
||||
# fake | gtnet-skt:fake Same as 'none', but use first three data values as
|
||||
# sequence, seconds & nanoseconds timestamp
|
||||
# In this mode values are uint32_t not floats!
|
||||
|
||||
|
||||
local = "127.0.0.1:12001", # This node only received messages on this IP:Port pair
|
||||
remote = "127.0.0.1:12000" # This node sents outgoing messages to this IP:Port pair
|
||||
|
||||
combine = 30 # Receive and sent 30 samples per message (multiplexing).
|
||||
vectorize = 30 # Receive and sent 30 samples per message (combining).
|
||||
},
|
||||
ethernet_node = {
|
||||
type = "socket", # See above.
|
||||
|
@ -141,7 +149,7 @@ paths = (
|
|||
hook = "print", # Register custom hook funktion (see src/hooks.c)
|
||||
|
||||
poolsize = 30 # The amount of samples which are kept in a circular buffer.
|
||||
# This number must be larger than the 'combine' settings of all
|
||||
# This number must be larger than the 'vectorize' settings of all
|
||||
# associated input and output nodes!
|
||||
},
|
||||
{
|
||||
|
|
|
@ -32,8 +32,8 @@ nodes = {
|
|||
node1 = {
|
||||
type = "socket",
|
||||
layer = "udp",
|
||||
local = "192.168.88.128:12002", # Local ip:port, use '*' for random port
|
||||
remote = "192.168.88.129:12001",
|
||||
local = "134.130.169.31:12002", # Local ip:port, use '*' for random port
|
||||
remote = "134.130.169.98:12001",
|
||||
header = "gtnet-skt", # 'gtnet-skt' or 'villas'. If not provided, 'villas' header will be used
|
||||
vectorize = 1, # Number of samples to fetch per iteration from the socket
|
||||
netem = {
|
|
@ -22,6 +22,7 @@
|
|||
#define _HOOKS_H_
|
||||
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "queue.h"
|
||||
#include "list.h"
|
||||
|
|
|
@ -8,10 +8,13 @@
|
|||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef _MEMORY_H_
|
||||
#define _MEMORY_H_
|
||||
|
||||
#define HUGEPAGESIZE (1 << 21)
|
||||
|
||||
typedef void *(*memzone_allocator_t)(size_t len);
|
||||
typedef int (*memzone_deallocator_t)(void *ptr, size_t len);
|
||||
|
||||
|
|
|
@ -47,6 +47,8 @@ struct node
|
|||
|
||||
int vectorize; /**< Number of messages to send / recv at once (scatter / gather) */
|
||||
int affinity; /**< CPU Affinity of this node */
|
||||
|
||||
unsigned long sequence; /**< This is a counter of received samples, in case the node-type does not generate sequence numbers itself. */
|
||||
|
||||
enum node_state {
|
||||
NODE_INVALID, /**< This node object is not in a valid state. */
|
||||
|
|
|
@ -29,8 +29,9 @@ enum socket_layer {
|
|||
};
|
||||
|
||||
enum socket_header {
|
||||
SOCKET_HEADER_DEFAULT, /**< Default header in the payload, (see msg_format.h) */
|
||||
SOCKET_HEADER_GTNET_SKT /**< No header in the payload, same as HDR_NONE*/
|
||||
SOCKET_HEADER_DEFAULT, /**> Default header in the payload, (see msg_format.h) */
|
||||
SOCKET_HEADER_NONE, /**> No header in the payload, same as HDR_NONE*/
|
||||
SOCKET_HEADER_FAKE /**> Same as SOCKET_HEADER_NONE but using the first three data values as: sequence, seconds & nano-seconds. */
|
||||
};
|
||||
|
||||
union sockaddr_union {
|
||||
|
@ -41,29 +42,19 @@ union sockaddr_union {
|
|||
};
|
||||
|
||||
struct socket {
|
||||
/** The socket descriptor */
|
||||
int sd;
|
||||
/** Socket mark for netem, routing and filtering */
|
||||
int mark;
|
||||
int sd; /**> The socket descriptor */
|
||||
int mark; /**> Socket mark for netem, routing and filtering */
|
||||
|
||||
/** The OSI / IP layer which should be used for this socket */
|
||||
enum socket_layer layer;
|
||||
enum socket_layer layer; /**> The OSI / IP layer which should be used for this socket */
|
||||
enum socket_header header; /**> Payload header type */
|
||||
|
||||
/** Payload header type */
|
||||
enum socket_header header;
|
||||
union sockaddr_union local; /**> Local address of the socket */
|
||||
union sockaddr_union remote; /**> Remote address of the socket */
|
||||
|
||||
/** Local address of the socket */
|
||||
union sockaddr_union local;
|
||||
/** Remote address of the socket */
|
||||
union sockaddr_union remote;
|
||||
struct rtnl_qdisc *tc_qdisc; /**> libnl3: Network emulator queuing discipline */
|
||||
struct rtnl_cls *tc_classifier; /**> libnl3: Firewall mark classifier */
|
||||
|
||||
/** libnl3: Network emulator queuing discipline */
|
||||
struct rtnl_qdisc *tc_qdisc;
|
||||
/** libnl3: Firewall mark classifier */
|
||||
struct rtnl_cls *tc_classifier;
|
||||
|
||||
/* Linked list _per_interface_ */
|
||||
struct socket *next;
|
||||
struct socket *next; /* Linked list _per_interface_ */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -59,7 +59,10 @@
|
|||
#define CEIL(x, y) (((x) + (y) - 1) / (y))
|
||||
|
||||
/** Get nearest up-rounded power of 2 */
|
||||
#define LOG2_CEIL(x) (1 << log2i((x) - 1) + 1)
|
||||
#define LOG2_CEIL(x) (1 << (log2i((x) - 1) + 1))
|
||||
|
||||
/** Check if the number is a power of 2 */
|
||||
#define IS_POW2(x) (((x) != 0) && !((x) & ((x) - 1)))
|
||||
|
||||
/** Calculate the number of elements in an array. */
|
||||
#define ARRAY_LEN(a) ( sizeof (a) / sizeof (a)[0] )
|
||||
|
@ -184,7 +187,7 @@ struct version {
|
|||
};
|
||||
|
||||
/** Compare two versions. */
|
||||
int version_compare(struct version *a, struct version *b);
|
||||
int version_cmp(struct version *a, struct version *b);
|
||||
|
||||
/** Parse a dotted version string. */
|
||||
int version_parse(const char *s, struct version *v);
|
||||
|
|
|
@ -101,7 +101,7 @@ int kernel_has_version(int maj, int min)
|
|||
if (version_parse(uts.release, ¤t))
|
||||
return -1;
|
||||
|
||||
return version_compare(¤t, &required) < 0;
|
||||
return version_cmp(¤t, &required) < 0;
|
||||
}
|
||||
|
||||
int kernel_is_rt()
|
||||
|
|
|
@ -65,6 +65,8 @@ static void * memory_hugepage_alloc(size_t len)
|
|||
|
||||
static int memory_hugepage_free(void *ptr, size_t len)
|
||||
{
|
||||
len = ALIGN(len, HUGEPAGESIZE); /* ugly see: https://lkml.org/lkml/2015/3/27/171 */
|
||||
|
||||
return munmap(ptr, len);
|
||||
}
|
||||
|
||||
|
|
|
@ -113,6 +113,8 @@ int node_start(struct node *n)
|
|||
if (ret == 0)
|
||||
n->state = NODE_RUNNING;
|
||||
|
||||
n->sequence = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,8 +103,9 @@ char * socket_print(struct node *n)
|
|||
}
|
||||
|
||||
switch (s->header) {
|
||||
case SOCKET_HEADER_GTNET_SKT: header = "gtnet-skt"; break;
|
||||
case SOCKET_HEADER_DEFAULT: header = "villas"; break;
|
||||
case SOCKET_HEADER_NONE: header = "none"; break;
|
||||
case SOCKET_HEADER_FAKE: header = "fake"; break;
|
||||
case SOCKET_HEADER_DEFAULT: header = "default"; break;
|
||||
}
|
||||
|
||||
char *local = socket_print_addr((struct sockaddr *) &s->local);
|
||||
|
@ -214,34 +215,29 @@ int socket_read(struct node *n, struct sample *smps[], unsigned cnt)
|
|||
int samples, ret, received, length;
|
||||
ssize_t bytes;
|
||||
|
||||
if (s->header == SOCKET_HEADER_GTNET_SKT) {
|
||||
if (s->header == SOCKET_HEADER_NONE || s->header == SOCKET_HEADER_FAKE) {
|
||||
if (cnt < 1)
|
||||
return 0;
|
||||
|
||||
/* The GTNETv2-SKT protocol send every sample in a single packet.
|
||||
* socket_read() receives a single packet. */
|
||||
int iov_len = s->header == SOCKET_HEADER_FAKE ? 2 : 1;
|
||||
struct iovec iov[iov_len];
|
||||
struct sample *smp = smps[0];
|
||||
|
||||
#if defined(GTNET_SKT_HEADER) && GTNET_SKT_HEADER
|
||||
|
||||
uint32_t header[3];
|
||||
|
||||
struct iovec iov[] = {
|
||||
{ /* First three values are sequence, seconds and nano-seconds */
|
||||
.iov_base = header,
|
||||
.iov_len = sizeof(header)
|
||||
},
|
||||
#else
|
||||
struct iovec iov[] = {
|
||||
#endif
|
||||
{ /* Remaining values are payload */
|
||||
.iov_base = &smp->data,
|
||||
.iov_len = SAMPLE_DATA_LEN(smp->capacity)
|
||||
}
|
||||
};
|
||||
if (s->header == SOCKET_HEADER_FAKE) {
|
||||
iov[0].iov_base = header;
|
||||
iov[0].iov_len = sizeof(header);
|
||||
}
|
||||
|
||||
/* Remaining values are payload */
|
||||
iov[iov_len-1].iov_base = &smp->data;
|
||||
iov[iov_len-1].iov_len = SAMPLE_DATA_LEN(smp->capacity);
|
||||
|
||||
struct msghdr mhdr = {
|
||||
.msg_iov = iov,
|
||||
.msg_iovlen = ARRAY_LEN(iov),
|
||||
.msg_iovlen = iov_len,
|
||||
.msg_name = (struct sockaddr *) &s->remote,
|
||||
.msg_namelen = sizeof(s->remote)
|
||||
};
|
||||
|
@ -258,28 +254,23 @@ int socket_read(struct node *n, struct sample *smps[], unsigned cnt)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#if defined(GTNET_SKT_HEADER) && GTNET_SKT_HEADER
|
||||
length = (bytes - sizeof(header)) / SAMPLE_DATA_LEN(1);
|
||||
#else
|
||||
length = bytes / SAMPLE_DATA_LEN(1);
|
||||
#endif
|
||||
length = (s->header == SOCKET_HEADER_FAKE ? bytes - sizeof(header) : bytes) / SAMPLE_DATA_LEN(1);
|
||||
if (length > smp->capacity) {
|
||||
warn("Node %s received more values than supported. Dropping %u values", node_name(n), length - smp->capacity);
|
||||
length = smp->capacity;
|
||||
}
|
||||
|
||||
/** @todo Should we generate sequence no here manually?
|
||||
* Or maybe optinally use the first data value as a sequence?
|
||||
* However this would require the RTDS model to be changed. */
|
||||
#if defined(GTNET_SKT_HEADER) && GTNET_SKT_HEADER
|
||||
smp->sequence = header[0];
|
||||
smp->ts.origin.tv_sec = header[1];
|
||||
smp->ts.origin.tv_nsec = header[2];
|
||||
#else
|
||||
smp->sequence = -1;
|
||||
smp->ts.origin.tv_sec = -1;
|
||||
smp->ts.origin.tv_nsec = -1;
|
||||
#endif
|
||||
if (s->header == SOCKET_HEADER_FAKE) {
|
||||
smp->sequence = header[0];
|
||||
smp->ts.origin.tv_sec = header[1];
|
||||
smp->ts.origin.tv_nsec = header[2];
|
||||
}
|
||||
else {
|
||||
smp->sequence = n->sequence++; /* Fake sequence no generated by VILLASnode */
|
||||
smp->ts.origin.tv_sec = -1;
|
||||
smp->ts.origin.tv_nsec = -1;
|
||||
}
|
||||
|
||||
smp->ts.received.tv_sec = -1;
|
||||
smp->ts.received.tv_nsec = -1;
|
||||
|
||||
|
@ -376,35 +367,32 @@ int socket_write(struct node *n, struct sample *smps[], unsigned cnt)
|
|||
int sent = 0;
|
||||
|
||||
/* Construct iovecs */
|
||||
if (s->header == SOCKET_HEADER_GTNET_SKT) {
|
||||
if (s->header == SOCKET_HEADER_NONE || s->header == SOCKET_HEADER_FAKE) {
|
||||
if (cnt < 1)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
#if defined(GTNET_SKT_HEADER) && GTNET_SKT_HEADER
|
||||
uint32_t header[] = {
|
||||
smps[i]->sequence,
|
||||
smps[i]->ts.origin.tv_sec,
|
||||
smps[i]->ts.origin.tv_nsec
|
||||
};
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
int iov_len = s->header == SOCKET_HEADER_FAKE ? 2 : 1;
|
||||
struct iovec iov[iov_len];
|
||||
|
||||
struct iovec iov[] = {
|
||||
{ /* First three values are sequence, seconds and nano-seconds */
|
||||
.iov_base = header,
|
||||
.iov_len = sizeof(header)
|
||||
},
|
||||
#else
|
||||
struct iovec iov[] = {
|
||||
#endif
|
||||
{ /* Remaining values are payload */
|
||||
.iov_base = &smps[i]->data,
|
||||
.iov_len = SAMPLE_DATA_LEN(smps[i]->length)
|
||||
}
|
||||
};
|
||||
/* First three values are sequence, seconds and nano-seconds timestamps */
|
||||
uint32_t header[3];
|
||||
if (s->header == SOCKET_HEADER_FAKE) {
|
||||
header[0] = smps[i]->sequence;
|
||||
header[1] = smps[i]->ts.origin.tv_sec;
|
||||
header[2] = smps[i]->ts.origin.tv_nsec;
|
||||
|
||||
iov[0].iov_base = header;
|
||||
iov[0].iov_len = sizeof(header);
|
||||
}
|
||||
|
||||
/* Remaining values are payload */
|
||||
iov[iov_len-1].iov_base = &smps[i]->data;
|
||||
iov[iov_len-1].iov_len = SAMPLE_DATA_LEN(smps[i]->length);
|
||||
|
||||
struct msghdr mhdr = {
|
||||
.msg_iov = iov,
|
||||
.msg_iovlen = ARRAY_LEN(iov),
|
||||
.msg_iovlen = iov_len,
|
||||
.msg_name = (struct sockaddr *) &s->remote,
|
||||
.msg_namelen = sizeof(s->remote)
|
||||
};
|
||||
|
@ -480,9 +468,11 @@ int socket_parse(struct node *n, config_setting_t *cfg)
|
|||
if (!config_setting_lookup_string(cfg, "header", &hdr))
|
||||
s->header = SOCKET_HEADER_DEFAULT;
|
||||
else {
|
||||
if (!strcmp(hdr, "gtnet-skt") || (!strcmp(hdr, "none")))
|
||||
s->header = SOCKET_HEADER_GTNET_SKT;
|
||||
else if (!strcmp(hdr, "default") || !strcmp(hdr, "villas"))
|
||||
if (!strcmp(hdr, "gtnet-skt") || (!strcmp(hdr, "none")))
|
||||
s->header = SOCKET_HEADER_NONE;
|
||||
else if (!strcmp(hdr, "gtnet-skt:fake") || (!strcmp(hdr, "fake")))
|
||||
s->header = SOCKET_HEADER_FAKE;
|
||||
else if (!strcmp(hdr, "villas") || !strcmp(hdr, "default"))
|
||||
s->header = SOCKET_HEADER_DEFAULT;
|
||||
else
|
||||
cerror(cfg, "Invalid application header type '%s' for node %s", hdr, node_name(n));
|
||||
|
|
|
@ -35,7 +35,7 @@ int version_parse(const char *s, struct version *v)
|
|||
return sscanf(s, "%u.%u", &v->major, &v->minor) != 2;
|
||||
}
|
||||
|
||||
int version_compare(struct version *a, struct version *b) {
|
||||
int version_cmp(struct version *a, struct version *b) {
|
||||
int major = a->major - b->major;
|
||||
int minor = a->minor - b->minor;
|
||||
|
||||
|
|
|
@ -7,6 +7,10 @@ TEST_LDLIBS = $(LDLIBS) -lcriterion -lvillas -pthread
|
|||
|
||||
tests: $(BUILDDIR)/testsuite
|
||||
|
||||
run-tests: tests
|
||||
echo 25 > /proc/sys/vm/nr_hugepages
|
||||
$(BUILDDIR)/testsuite
|
||||
|
||||
# Compile
|
||||
$(BUILDDIR)/tests/%.o: tests/%.c | $$(dir $$@)
|
||||
$(CC) $(TEST_CFLAGS) -c $< -o $@
|
||||
|
@ -25,4 +29,4 @@ install-tests:
|
|||
clean-tests:
|
||||
rm -rf $(BUILDDIR)/tests $(BUILDDIR)/testsuite
|
||||
|
||||
.PHONY: tests install-tests clean-tests
|
||||
.PHONY: tests install-tests clean-tests run-tests
|
39
tests/memory.c
Normal file
39
tests/memory.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/** Unit tests for memory management
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC
|
||||
* This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential.
|
||||
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <criterion/criterion.h>
|
||||
#include <criterion/theories.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "memory.h"
|
||||
#include "utils.h"
|
||||
|
||||
TheoryDataPoints(memory, aligned) = {
|
||||
// DataPoints(size_t, 1, 32, 55, 1 << 10, 1 << 20),
|
||||
DataPoints(size_t, 1<<12),
|
||||
DataPoints(size_t, 1, 8, 1 << 12),
|
||||
DataPoints(const struct memtype *, &memtype_heap, &memtype_hugepage)
|
||||
};
|
||||
|
||||
Theory((size_t len, size_t align, const struct memtype *m), memory, aligned) {
|
||||
int ret;
|
||||
void *ptr;
|
||||
|
||||
ptr = memory_alloc_aligned(m, len, align);
|
||||
cr_assert_neq(ptr, NULL, "Failed to allocate memory");
|
||||
|
||||
//cr_assert(IS_ALIGNED(ptr, align));
|
||||
|
||||
if (m == &memtype_hugepage) {
|
||||
cr_assert(IS_ALIGNED(ptr, HUGEPAGESIZE));
|
||||
}
|
||||
|
||||
ret = memory_free(m, ptr, len);
|
||||
cr_assert_eq(ret, 0, "Failed to release memory: ret=%d, ptr=%p, len=%zu: %s", ret, ptr, len, strerror(errno));
|
||||
}
|
68
tests/pool.c
Normal file
68
tests/pool.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/** Unit tests for memory pool
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC
|
||||
* This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential.
|
||||
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <criterion/criterion.h>
|
||||
#include <criterion/parameterized.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "pool.h"
|
||||
#include "utils.h"
|
||||
|
||||
struct param {
|
||||
int thread_count;
|
||||
int pool_size;
|
||||
size_t block_size;
|
||||
const struct memtype *memtype;
|
||||
};
|
||||
|
||||
ParameterizedTestParameters(pool, basic)
|
||||
{
|
||||
static struct param params[] = {
|
||||
{ 1, 4096, 150, &memtype_heap },
|
||||
{ 1, 128, 8, &memtype_hugepage },
|
||||
{ 1, 4, 8192, &memtype_hugepage },
|
||||
{ 1, 1 << 13, 4, &memtype_heap }
|
||||
};
|
||||
|
||||
return cr_make_param_array(struct param, params, ARRAY_LEN(params));
|
||||
}
|
||||
|
||||
ParameterizedTest(struct param *p, pool, basic)
|
||||
{
|
||||
int ret;
|
||||
struct pool pool;
|
||||
|
||||
void *ptr, *ptrs[p->pool_size];
|
||||
|
||||
ret = pool_init(&pool, p->pool_size, p->block_size, p->memtype);
|
||||
cr_assert_eq(ret, 0, "Failed to create pool");
|
||||
|
||||
ptr = pool_get(&pool);
|
||||
cr_assert_neq(ptr, NULL);
|
||||
|
||||
memset(ptr, 1, p->block_size); /* check that we dont get a seg fault */
|
||||
|
||||
int i;
|
||||
for (i = 1; i < p->pool_size; i++) {
|
||||
ptrs[i] = pool_get(&pool);
|
||||
|
||||
if (ptrs[i] == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < p->pool_size)
|
||||
cr_assert_neq(ptrs[i], NULL);
|
||||
|
||||
ptr = pool_get(&pool);
|
||||
cr_assert_eq(ptr, NULL);
|
||||
|
||||
ret = pool_destroy(&pool);
|
||||
cr_assert_eq(ret, 0, "Failed to destroy pool");
|
||||
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
*********************************************************************************/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <criterion/criterion.h>
|
||||
|
||||
#include "timing.h"
|
||||
|
@ -86,7 +87,10 @@ Test(timing, timerfd_create_rate, .timeout = 20)
|
|||
|
||||
cr_assert(tfd > 0);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
timerfd_wait(tfd);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 10; i++) {
|
||||
start = time_now();
|
||||
|
||||
timerfd_wait(tfd);
|
||||
|
@ -94,9 +98,13 @@ Test(timing, timerfd_create_rate, .timeout = 20)
|
|||
end = time_now();
|
||||
waited = time_delta(&start, &end);
|
||||
|
||||
cr_assert_float_eq(waited, 1.0 / rate, 10e-3, "We slept for %f instead of %f secs in round %d", waited, 1.0 / rate, i);
|
||||
if (fabs(waited - 1.0 / rate) > 10e-3)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 10)
|
||||
cr_assert_float_eq(waited, 1.0 / rate, 10e-3, "We slept for %f instead of %f secs in round %d", waited, 1.0 / rate, i);
|
||||
|
||||
close(tfd);
|
||||
}
|
||||
|
||||
|
|
64
tests/utils.c
Normal file
64
tests/utils.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/** Unit tests for utilities
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC
|
||||
* This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential.
|
||||
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <criterion/criterion.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
Test(utils, is_aligned)
|
||||
{
|
||||
/* Positive */
|
||||
cr_assert(IS_ALIGNED(1, 1));
|
||||
cr_assert(IS_ALIGNED(128, 64));
|
||||
|
||||
/* Negative */
|
||||
cr_assert(!IS_ALIGNED(55, 16));
|
||||
cr_assert(!IS_ALIGNED(55, 55));
|
||||
cr_assert(!IS_ALIGNED(1128, 256));
|
||||
}
|
||||
|
||||
Test(utils, ceil)
|
||||
{
|
||||
cr_assert_eq(CEIL(10, 3), 4);
|
||||
cr_assert_eq(CEIL(10, 5), 2);
|
||||
cr_assert_eq(CEIL(4, 3), 2);
|
||||
}
|
||||
|
||||
Test(utils, is_pow2)
|
||||
{
|
||||
/* Positive */
|
||||
cr_assert(IS_POW2(1));
|
||||
cr_assert(IS_POW2(2));
|
||||
cr_assert(IS_POW2(64));
|
||||
|
||||
/* Negative */
|
||||
cr_assert(!IS_POW2(0));
|
||||
cr_assert(!IS_POW2(3));
|
||||
cr_assert(!IS_POW2(11111));
|
||||
cr_assert(!IS_POW2(-1));
|
||||
}
|
||||
|
||||
struct version_param {
|
||||
const char *v1, *v2;
|
||||
int result;
|
||||
};
|
||||
|
||||
Test(utils, version)
|
||||
{
|
||||
struct version v1, v2, v3, v4;
|
||||
|
||||
version_parse("1.2", &v1);
|
||||
version_parse("1.3", &v2);
|
||||
version_parse("55", &v3);
|
||||
version_parse("66", &v4);
|
||||
|
||||
cr_assert_lt(version_cmp(&v1, &v2), 0);
|
||||
cr_assert_eq(version_cmp(&v1, &v1), 0);
|
||||
cr_assert_gt(version_cmp(&v2, &v1), 0);
|
||||
cr_assert_lt(version_cmp(&v3, &v4), 0);
|
||||
}
|
2
thirdparty/criterion
vendored
2
thirdparty/criterion
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 1b687a9f6a0e51c9e9b0a047e1fcd6c94de7a080
|
||||
Subproject commit 101d0e0f3a71c414c7d2a7a2a2fa465969b6b667
|
Loading…
Add table
Reference in a new issue