1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

tests: fixed unit tests for new io and tasks modules

This commit is contained in:
Steffen Vogel 2017-08-20 10:48:44 +02:00
parent fbd3f2c008
commit 0239a15a84
7 changed files with 152 additions and 87 deletions

View file

@ -171,7 +171,19 @@ static int advio_xferinfo(void *p, curl_off_t dl_total_bytes, curl_off_t dl_byte
int aislocal(const char *uri)
{
return access(uri, F_OK) != -1;
char *sep;
const char *supported_schemas[] = { "file", "http", "https", "tftp", "ftp", "scp", "sftp", "smb", "smbs" };
sep = strstr(uri, "://");
if (!sep)
return 1; /* no schema, we assume its a local file */
for (int i = 0; i < ARRAY_LEN(supported_schemas); i++) {
if (!strncmp(supported_schemas[i], uri, sep - uri))
return 0;
}
return -1; /* none of the supported schemas match. this is an invalid uri */
}
AFILE * afopen(const char *uri, const char *mode)

View file

@ -26,22 +26,23 @@
#include "utils.h"
#include "periodic_task.h"
#include "task.h"
#include "timing.h"
#if PERIODIC_TASK_IMPL == TIMERFD
#include <sys/timerfd.h>
#endif
int periodic_task_init(struct periodic_task *t, double rate)
int task_init(struct task *t, double rate, int clock)
{
t->period = time_from_double(1.0 / rate);
t->clock = clock;
t->period = rate ? time_from_double(1.0 / rate) : (struct timespec) { 0, 0 };
#if PERIODIC_TASK_IMPL == CLOCK_NANOSLEEP || PERIODIC_TASK_IMPL == NANOSLEEP
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
clock_gettime(t->clock, &now);
t->next_period = time_add(&now, &t->period);
#elif PERIODIC_TASK_IMPL == TIMERFD
int ret;
@ -51,7 +52,7 @@ int periodic_task_init(struct periodic_task *t, double rate)
.it_value = t->period
};
t->fd = timerfd_create(CLOCK_MONOTONIC, 0);
t->fd = timerfd_create(t->clock, 0);
if (t->fd < 0)
return -1;
@ -65,7 +66,7 @@ int periodic_task_init(struct periodic_task *t, double rate)
return 0;
}
int periodic_task_destroy(struct periodic_task *t)
int task_destroy(struct task *t)
{
#if PERIODIC_TASK_IMPL == TIMERFD
return close(t->fd);
@ -86,17 +87,17 @@ static int time_lt(const struct timespec *lhs, const struct timespec *rhs)
}
#endif
uint64_t periodic_task_wait_until_next_period(struct periodic_task *t)
uint64_t task_wait_until_next_period(struct task *t)
{
uint64_t runs;
int ret;
#if PERIODIC_TASK_IMPL == CLOCK_NANOSLEEP || PERIODIC_TASK_IMPL == NANOSLEEP
ret = periodic_task_wait_until(t, &t->next_period);
ret = task_wait_until(t, &t->next_period);
struct timespec now;
ret = clock_gettime(CLOCK_MONOTONIC, &now);
ret = clock_gettime(t->clock, &now);
if (ret)
return 0;
@ -115,18 +116,18 @@ uint64_t periodic_task_wait_until_next_period(struct periodic_task *t)
}
int periodic_task_wait_until(struct periodic_task *t, const struct timespec *until)
int task_wait_until(struct task *t, const struct timespec *until)
{
int ret;
#if PERIODIC_TASK_IMPL == CLOCK_NANOSLEEP
retry: ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, until, NULL);
retry: ret = clock_nanosleep(t->clock, TIMER_ABSTIME, until, NULL);
if (ret == EINTR)
goto retry;
#elif PERIODIC_TASK_IMPL == NANOSLEEP
struct timespec now, delta;
ret = clock_gettime(CLOCK_MONOTONIC, &now);
ret = clock_gettime(t->clock, &now);
if (ret)
return ret;
@ -147,10 +148,10 @@ retry: ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, until, NULL);
ret = read(t->fd, &runs, sizeof(runs));
if (ret < 0)
return 0;
return ret;
#else
#error "Invalid period task implementation"
#endif
return ret;
return 0;
}

View file

@ -28,12 +28,26 @@
#include <villas/utils.h>
#include <villas/advio.h>
#include <villas/sample.h>
#include <villas/formats/villas.h>
#include <villas/io/villas.h>
/** This URI points to a Sciebo share which contains some test files.
* The Sciebo share is read/write accessible via WebDAV. */
#define BASE_URI "https://1Nrd46fZX8HbggT:badpass@rwth-aachen.sciebo.de/public.php/webdav/node/tests"
Test(advio, islocal)
{
int ret;
ret = aislocal("/var/log/villas/dta.dat");
cr_assert_eq(ret, 1);
ret = aislocal("http://www.google.de");
cr_assert_eq(ret, 0);
ret = aislocal("torrent://www.google.de");
cr_assert_eq(ret, -1);
}
Test(advio, local)
{
AFILE *af;
@ -81,7 +95,7 @@ Test(advio, download_large)
af = afopen(BASE_URI "/download-large" , "r");
cr_assert(af, "Failed to download file");
ret = io_format_villas_fscan(af->file, &smp, 1, NULL);
ret = villas_fscan(af->file, &smp, 1, NULL);
cr_assert_eq(ret, 1);
cr_assert_eq(smp->sequence, 0);

View file

@ -78,7 +78,7 @@ ParameterizedTestParameters(io, highlevel)
"json",
"msg",
"gtnet",
"gtnet-fake",
"gtnet-fake"
};
return cr_make_param_array(char[32], formats, ARRAY_LEN(formats));
@ -125,6 +125,7 @@ ParameterizedTest(char *fmt, io, highlevel)
strncpy(dir, "/tmp/villas.XXXXXX", sizeof(dir));
mkdtemp(dir);
// ret = asprintf(&fn, "file://%s/file", dir);
ret = asprintf(&fn, "%s/file", dir);
cr_assert_gt(ret, 0);
@ -134,16 +135,16 @@ ParameterizedTest(char *fmt, io, highlevel)
ret = io_init(&io, f, IO_FORMAT_ALL);
cr_assert_eq(ret, 0);
ret = io_open(&io, fn, "w+");
ret = io_open(&io, fn);
cr_assert_eq(ret, 0);
ret = io_print(&io, smps, NUM_SAMPLES);
cr_assert_eq(ret, NUM_SAMPLES);
ret = io_flush(&io);
cr_assert_eq(ret, 0);
ret = io_close(&io);
cr_assert_eq(ret, 0);
#if 1 /* Show the file contents */
#if 0 /* Show the file contents */
char cmd[128];
if (!strcmp(fmt, "json") || !strcmp(fmt, "villas"))
snprintf(cmd, sizeof(cmd), "cat %s", fn);
@ -152,10 +153,13 @@ ParameterizedTest(char *fmt, io, highlevel)
system(cmd);
#endif
ret = io_open(&io, fn, "r");
cr_assert_eq(ret, 0);
if (io.mode == IO_MODE_ADVIO)
adownload(io.advio.input, 0);
io_rewind(&io);
cnt = io_scan(&io, smpt, NUM_SAMPLES);
cr_assert_gt(cnt, 0, "Failed to read samples back");
/* The RAW format has certain limitations:
* - limited accuracy if smaller datatypes are used
@ -165,7 +169,7 @@ ParameterizedTest(char *fmt, io, highlevel)
*/
if (f->sscan == raw_sscan) {
cr_assert_eq(cnt, 1);
cr_assert_eq(smpt[0]->length, smpt[0]->capacity);
cr_assert_eq(smpt[0]->length, smpt[0]->capacity, "Expected values: %d, Received values: %d", smpt[0]->capacity, smpt[0]->length);
if (io.flags & RAW_FAKE) {
}

View file

@ -36,16 +36,16 @@ int main(int argc, char *argv[])
struct log log;
ret = log_init(&log, V, LOG_ALL);
if (ret) {
if (ret)
error("Failed to initialize logging sub-system");
return ret;
}
ret = log_start(&log);
if (ret)
error("Failed to start logging sub-system");
ret = memory_init(DEFAULT_NR_HUGEPAGES);
if (ret) {
if (ret)
error("Failed to initialize memory sub-system");
return ret;
}
/* Run criterion tests */
tests = criterion_initialize();

88
tests/unit/task.c Normal file
View file

@ -0,0 +1,88 @@
/** Unit tests for periodic tasks
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <criterion/criterion.h>
#include <math.h>
#include "task.h"
#include "timing.h"
Test(task, rate, .timeout = 10)
{
int ret;
double rate = 5, waited;
struct timespec start, end;
struct task task;
ret = task_init(&task, rate, CLOCK_MONOTONIC);
cr_assert_eq(ret, 0);
int i;
for (i = 0; i < 10; i++) {
clock_gettime(CLOCK_MONOTONIC, &start);
task_wait_until_next_period(&task);
clock_gettime(CLOCK_MONOTONIC, &end);
waited = time_delta(&start, &end);
if (fabs(waited - 1.0 / rate) > 10e-3)
break;
}
if (i < 10)
cr_assert_float_eq(waited, 1.0 / rate, 1e-2, "We slept for %f instead of %f secs in round %d", waited, 1.0 / rate, i);
ret = task_destroy(&task);
cr_assert_eq(ret, 0);
}
Test(task, wait_until, .timeout = 5)
{
int ret;
struct task task;
struct timespec start, end, diff, future;
ret = task_init(&task, 1, CLOCK_REALTIME);
cr_assert_eq(ret, 0);
double waitfor = 3.423456789;
start = time_now();
diff = time_from_double(waitfor);
future = time_add(&start, &diff);
ret = task_wait_until(&task, &future);
end = time_now();
cr_assert_eq(ret, 0);
double waited = time_delta(&start, &end);
cr_assert_float_eq(waited, waitfor, 1e-2, "We slept for %f instead of %f secs", waited, waitfor);
ret = task_destroy(&task);
cr_assert_eq(ret, 0);
}

View file

@ -89,58 +89,4 @@ Test(timing, time_to_from_double)
double dbl = time_to_double(&ts);
cr_assert_float_eq(dbl, ref, 1e-9);
}
Test(timing, timerfd_create_rate, .timeout = 20)
{
struct timespec start, end;
double rate = 5, waited;
int tfd = timerfd_create_rate(rate);
cr_assert(tfd > 0);
timerfd_wait(tfd);
int i;
for (i = 0; i < 10; i++) {
start = time_now();
timerfd_wait(tfd);
end = time_now();
waited = time_delta(&start, &end);
if (fabs(waited - 1.0 / rate) > 10e-3)
break;
}
if (i < 10)
cr_assert_float_eq(waited, 1.0 / rate, 1e-2, "We slept for %f instead of %f secs in round %d", waited, 1.0 / rate, i);
close(tfd);
}
Test(timing, timerfd_wait_until, .timeout = 10)
{
int tfd = timerfd_create(CLOCK_REALTIME, 0);
cr_assert(tfd > 0);
double waitfor = 2.423456789;
struct timespec start = time_now();
struct timespec diff = time_from_double(waitfor);
struct timespec future = time_add(&start, &diff);
timerfd_wait_until(tfd, &future);
struct timespec end = time_now();
double waited = time_delta(&start, &end);
cr_assert_float_eq(waited, waitfor, 1e-2, "We slept for %f instead of %f secs", waited, waitfor);
close(tfd);
}