2021-05-10 00:12:30 +02:00
|
|
|
/* Unit tests for formatters.
|
2017-08-05 21:02:09 +02:00
|
|
|
*
|
2022-03-15 09:18:01 -04:00
|
|
|
* Author: Steffen Vogel <post@steffenvogel.de>
|
2022-03-15 09:28:57 -04:00
|
|
|
* SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
|
2022-07-04 18:20:03 +02:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2017-08-05 21:02:09 +02:00
|
|
|
*/
|
|
|
|
|
2018-10-20 14:24:51 +02:00
|
|
|
#include <complex>
|
2023-09-07 11:46:39 +02:00
|
|
|
#include <float.h>
|
|
|
|
#include <stdio.h>
|
2017-08-05 21:02:09 +02:00
|
|
|
|
|
|
|
#include <criterion/criterion.h>
|
|
|
|
#include <criterion/parameterized.h>
|
|
|
|
|
2021-05-10 00:12:30 +02:00
|
|
|
#include <villas/format.hpp>
|
2018-10-20 14:24:51 +02:00
|
|
|
#include <villas/log.hpp>
|
2023-09-07 11:46:39 +02:00
|
|
|
#include <villas/pool.hpp>
|
|
|
|
#include <villas/sample.hpp>
|
|
|
|
#include <villas/signal.hpp>
|
|
|
|
#include <villas/timing.hpp>
|
|
|
|
#include <villas/utils.hpp>
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2020-01-26 16:17:59 +01:00
|
|
|
#include "helpers.hpp"
|
|
|
|
|
2018-10-20 14:24:51 +02:00
|
|
|
using namespace villas;
|
2021-05-10 00:12:30 +02:00
|
|
|
using namespace villas::node;
|
2018-10-20 14:24:51 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
extern void init_memory();
|
2018-08-20 18:32:10 +02:00
|
|
|
|
2017-08-05 21:02:09 +02:00
|
|
|
#define NUM_VALUES 10
|
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
using string =
|
|
|
|
std::basic_string<char, std::char_traits<char>, criterion::allocator<char>>;
|
2020-01-26 16:17:59 +01:00
|
|
|
|
2020-06-16 01:00:57 +02:00
|
|
|
struct Param {
|
2020-01-26 16:17:59 +01:00
|
|
|
public:
|
2023-09-07 11:46:39 +02:00
|
|
|
Param(const char *f, int c, int b) : fmt(f), cnt(c), bits(b) {}
|
2020-06-16 01:00:57 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
string fmt;
|
|
|
|
int cnt;
|
|
|
|
int bits;
|
2018-08-20 18:32:10 +02:00
|
|
|
};
|
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
void fill_sample_data(SignalList::Ptr signals, struct Sample *smps[],
|
|
|
|
unsigned cnt) {
|
|
|
|
struct timespec delta, now;
|
|
|
|
|
|
|
|
now = time_now();
|
|
|
|
delta = time_from_double(50e-6);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < cnt; i++) {
|
|
|
|
struct Sample *smp = smps[i];
|
|
|
|
|
|
|
|
smps[i]->flags = (int)SampleFlags::HAS_SEQUENCE |
|
|
|
|
(int)SampleFlags::HAS_DATA |
|
|
|
|
(int)SampleFlags::HAS_TS_ORIGIN;
|
|
|
|
smps[i]->length = signals->size();
|
|
|
|
smps[i]->sequence = 235 + i;
|
|
|
|
smps[i]->ts.origin = now;
|
|
|
|
smps[i]->signals = signals;
|
|
|
|
|
|
|
|
for (size_t j = 0; j < signals->size(); j++) {
|
|
|
|
auto sig = signals->getByIndex(j);
|
|
|
|
auto *data = &smp->data[j];
|
|
|
|
|
|
|
|
switch (sig->type) {
|
|
|
|
case SignalType::BOOLEAN:
|
|
|
|
data->b = j * 0.1 + i * 100;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SignalType::COMPLEX: {
|
|
|
|
// TODO: Port to proper C++
|
|
|
|
std::complex<float> z = {j * 0.1f, i * 100.0f};
|
|
|
|
memcpy(&data->z, &z, sizeof(data->z));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SignalType::FLOAT:
|
|
|
|
data->f = j * 0.1 + i * 100;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SignalType::INTEGER:
|
|
|
|
data->i = j + i * 1000;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
now = time_add(&now, &delta);
|
|
|
|
}
|
2018-03-26 12:50:30 +02:00
|
|
|
}
|
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
void cr_assert_eq_sample(struct Sample *a, struct Sample *b, int flags) {
|
|
|
|
cr_assert_eq(a->length, b->length, "a->length=%d, b->length=%d", a->length,
|
|
|
|
b->length);
|
|
|
|
|
|
|
|
if (flags & (int)SampleFlags::HAS_SEQUENCE)
|
|
|
|
cr_assert_eq(a->sequence, b->sequence);
|
|
|
|
|
|
|
|
if (flags & (int)SampleFlags::HAS_TS_ORIGIN) {
|
|
|
|
cr_assert_eq(a->ts.origin.tv_sec, b->ts.origin.tv_sec);
|
|
|
|
cr_assert_eq(a->ts.origin.tv_nsec, b->ts.origin.tv_nsec);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & (int)SampleFlags::HAS_DATA) {
|
|
|
|
for (unsigned j = 0; j < MIN(a->length, b->length); j++) {
|
|
|
|
cr_assert_eq(sample_format(a, j), sample_format(b, j));
|
|
|
|
|
|
|
|
switch (sample_format(b, j)) {
|
|
|
|
case SignalType::FLOAT:
|
|
|
|
cr_assert_float_eq(a->data[j].f, b->data[j].f, 1e-3,
|
|
|
|
"Sample data mismatch at index %d: %f != %f", j,
|
|
|
|
a->data[j].f, b->data[j].f);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SignalType::INTEGER:
|
|
|
|
cr_assert_eq(a->data[j].i, b->data[j].i,
|
|
|
|
"Sample data mismatch at index %d: %lld != %lld", j,
|
|
|
|
a->data[j].i, b->data[j].i);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SignalType::BOOLEAN:
|
|
|
|
cr_assert_eq(a->data[j].b, b->data[j].b,
|
|
|
|
"Sample data mismatch at index %d: %s != %s", j,
|
|
|
|
a->data[j].b ? "true" : "false",
|
|
|
|
b->data[j].b ? "true" : "false");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SignalType::COMPLEX: {
|
|
|
|
auto ca = *(std::complex<float> *)&a->data[j].z;
|
|
|
|
auto cb = *(std::complex<float> *)&b->data[j].z;
|
|
|
|
|
|
|
|
cr_assert_float_eq(std::abs(ca - cb), 0, 1e-6,
|
|
|
|
"Sample data mismatch at index %d: %f+%fi != %f+%fi",
|
|
|
|
j, ca.real(), ca.imag(), cb.real(), cb.imag());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default: {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-08-23 15:45:28 +02:00
|
|
|
}
|
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
void cr_assert_eq_sample_raw(struct Sample *a, struct Sample *b, int flags,
|
|
|
|
int bits) {
|
|
|
|
cr_assert_eq(a->length, b->length);
|
|
|
|
|
|
|
|
if (flags & (int)SampleFlags::HAS_SEQUENCE)
|
|
|
|
cr_assert_eq(a->sequence, b->sequence);
|
|
|
|
|
|
|
|
if (flags & (int)SampleFlags::HAS_TS_ORIGIN) {
|
|
|
|
cr_assert_eq(a->ts.origin.tv_sec, b->ts.origin.tv_sec);
|
|
|
|
cr_assert_eq(a->ts.origin.tv_nsec, b->ts.origin.tv_nsec);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & (int)SampleFlags::HAS_DATA) {
|
|
|
|
for (unsigned j = 0; j < MIN(a->length, b->length); j++) {
|
|
|
|
cr_assert_eq(sample_format(a, j), sample_format(b, j));
|
|
|
|
|
|
|
|
switch (sample_format(b, j)) {
|
|
|
|
case SignalType::FLOAT:
|
|
|
|
if (bits != 8 && bits != 16)
|
|
|
|
cr_assert_float_eq(a->data[j].f, b->data[j].f, 1e-3,
|
|
|
|
"Sample data mismatch at index %d: %f != %f", j,
|
|
|
|
a->data[j].f, b->data[j].f);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SignalType::INTEGER:
|
|
|
|
cr_assert_eq(a->data[j].i, b->data[j].i,
|
|
|
|
"Sample data mismatch at index %d: %lld != %lld", j,
|
|
|
|
a->data[j].i, b->data[j].i);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SignalType::BOOLEAN:
|
|
|
|
cr_assert_eq(a->data[j].b, b->data[j].b,
|
|
|
|
"Sample data mismatch at index %d: %s != %s", j,
|
|
|
|
a->data[j].b ? "true" : "false",
|
|
|
|
b->data[j].b ? "true" : "false");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SignalType::COMPLEX:
|
|
|
|
if (bits != 8 && bits != 16) {
|
|
|
|
auto ca = *(std::complex<float> *)&a->data[j].z;
|
|
|
|
auto cb = *(std::complex<float> *)&b->data[j].z;
|
|
|
|
|
|
|
|
cr_assert_float_eq(
|
|
|
|
std::abs(ca - cb), 0, 1e-6,
|
|
|
|
"Sample data mismatch at index %d: %f+%fi != %f+%fi", j,
|
|
|
|
ca.real(), ca.imag(), cb.real(), cb.imag());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-08-05 21:02:09 +02:00
|
|
|
}
|
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ParameterizedTestParameters(format, lowlevel) {
|
|
|
|
static criterion::parameters<Param> params;
|
|
|
|
|
|
|
|
params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32);
|
|
|
|
params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32);
|
|
|
|
params.emplace_back("{ \"type\": \"raw\", \"bits\": 8 }", 1, 8);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"big\" }", 1, 16);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"little\" }", 1, 16);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"big\" }", 1, 32);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"little\" }", 1, 32);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"big\" }", 1, 64);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"little\" }", 1, 64);
|
|
|
|
params.emplace_back("{ \"type\": \"villas.human\" }", 10, 0);
|
|
|
|
params.emplace_back("{ \"type\": \"villas.binary\" }", 10, 0);
|
|
|
|
params.emplace_back("{ \"type\": \"csv\" }", 10, 0);
|
|
|
|
params.emplace_back("{ \"type\": \"tsv\" }", 10, 0);
|
|
|
|
params.emplace_back("{ \"type\": \"json\" }", 10, 0);
|
|
|
|
// params.emplace_back("{ \"type\": \"json.kafka\" }", 10, 0); # broken due to signal names
|
|
|
|
// params.emplace_back("{ \"type\": \"json.reserve\" }", 10, 0);
|
2020-06-16 01:00:57 +02:00
|
|
|
#ifdef PROTOBUF_FOUND
|
2023-09-07 11:46:39 +02:00
|
|
|
params.emplace_back("{ \"type\": \"protobuf\" }", 10, 0);
|
2020-06-16 01:00:57 +02:00
|
|
|
#endif
|
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
return params;
|
2017-08-23 15:45:28 +02:00
|
|
|
}
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2020-09-11 14:57:05 +02:00
|
|
|
// cppcheck-suppress unknownMacro
|
2023-09-07 11:46:39 +02:00
|
|
|
ParameterizedTest(Param *p, format, lowlevel, .init = init_memory) {
|
|
|
|
int ret;
|
|
|
|
unsigned cnt;
|
|
|
|
char buf[8192];
|
|
|
|
size_t wbytes, rbytes;
|
2017-09-04 14:30:07 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
Logger logger = logging.get("test:format:lowlevel");
|
2018-10-20 14:24:51 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
logger->info("Running test for format={}, cnt={}", p->fmt, p->cnt);
|
2018-10-20 14:24:51 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
struct Pool pool;
|
|
|
|
Format *fmt;
|
|
|
|
struct Sample *smps[p->cnt];
|
|
|
|
struct Sample *smpt[p->cnt];
|
2017-08-23 15:45:28 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = pool_init(&pool, 2 * p->cnt, SAMPLE_LENGTH(NUM_VALUES));
|
|
|
|
cr_assert_eq(ret, 0);
|
2017-08-23 15:45:28 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
auto signals = std::make_shared<SignalList>(NUM_VALUES, SignalType::FLOAT);
|
2018-08-20 18:32:10 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = sample_alloc_many(&pool, smps, p->cnt);
|
|
|
|
cr_assert_eq(ret, p->cnt);
|
2018-03-26 12:50:30 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = sample_alloc_many(&pool, smpt, p->cnt);
|
|
|
|
cr_assert_eq(ret, p->cnt);
|
2017-09-04 14:30:07 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
fill_sample_data(signals, smps, p->cnt);
|
2017-09-04 14:30:07 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
json_t *json_format = json_loads(p->fmt.c_str(), 0, nullptr);
|
|
|
|
cr_assert_not_null(json_format);
|
2018-08-20 18:32:10 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
fmt = FormatFactory::make(json_format);
|
|
|
|
cr_assert_not_null(fmt, "Failed to create formatter of type '%s'",
|
|
|
|
p->fmt.c_str());
|
2018-05-12 15:25:47 +02:00
|
|
|
|
2023-09-13 10:16:39 +02:00
|
|
|
fmt->start(signals, (int)SampleFlags::ALL);
|
2017-09-04 14:30:07 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
cnt = fmt->sprint(buf, sizeof(buf), &wbytes, smps, p->cnt);
|
|
|
|
cr_assert_eq(cnt, p->cnt, "Written only %d of %d samples", cnt, p->cnt);
|
2021-05-10 00:12:30 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
cnt = fmt->sscan(buf, wbytes, &rbytes, smpt, p->cnt);
|
|
|
|
cr_assert_eq(cnt, p->cnt, "Read only %d of %d samples back", cnt, p->cnt);
|
2017-09-04 14:30:07 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
cr_assert_eq(rbytes, wbytes, "rbytes != wbytes: %#zx != %#zx", rbytes,
|
|
|
|
wbytes);
|
2017-08-23 15:45:28 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
for (unsigned i = 0; i < cnt; i++) {
|
|
|
|
if (p->bits)
|
|
|
|
cr_assert_eq_sample_raw(smps[i], smpt[i], fmt->getFlags(), p->bits);
|
|
|
|
else
|
|
|
|
cr_assert_eq_sample(smps[i], smpt[i], fmt->getFlags());
|
|
|
|
}
|
2018-08-20 18:32:10 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
sample_free_many(smps, p->cnt);
|
|
|
|
sample_free_many(smpt, p->cnt);
|
2018-08-20 18:32:10 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = pool_destroy(&pool);
|
|
|
|
cr_assert_eq(ret, 0);
|
2017-08-23 15:45:28 +02:00
|
|
|
}
|
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ParameterizedTestParameters(format, highlevel) {
|
|
|
|
static criterion::parameters<Param> params;
|
|
|
|
|
|
|
|
params.emplace_back("{ \"type\": \"gtnet\" }", 1, 32);
|
|
|
|
params.emplace_back("{ \"type\": \"gtnet\", \"fake\": true }", 1, 32);
|
|
|
|
params.emplace_back("{ \"type\": \"raw\", \"bits\": 8 }", 1, 8);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"big\" }", 1, 16);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 16, \"endianess\": \"little\" }", 1, 16);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"big\" }", 1, 32);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 32, \"endianess\": \"little\" }", 1, 32);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"big\" }", 1, 64);
|
|
|
|
params.emplace_back(
|
|
|
|
"{ \"type\": \"raw\", \"bits\": 64, \"endianess\": \"little\" }", 1, 64);
|
|
|
|
params.emplace_back("{ \"type\": \"villas.human\" }", 10, 0);
|
|
|
|
params.emplace_back("{ \"type\": \"villas.binary\" }", 10, 0);
|
|
|
|
params.emplace_back("{ \"type\": \"csv\" }", 10, 0);
|
|
|
|
params.emplace_back("{ \"type\": \"tsv\" }", 10, 0);
|
|
|
|
params.emplace_back("{ \"type\": \"json\" }", 10, 0);
|
|
|
|
// params.emplace_back("{ \"type\": \"json.kafka\" }", 10, 0); # broken due to signal names
|
|
|
|
// params.emplace_back("{ \"type\": \"json.reserve\" }", 10, 0);
|
2020-06-16 01:00:57 +02:00
|
|
|
#ifdef PROTOBUF_FOUND
|
2023-09-07 11:46:39 +02:00
|
|
|
params.emplace_back("{ \"type\": \"protobuf\" }", 10, 0);
|
2020-06-16 01:00:57 +02:00
|
|
|
#endif
|
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
return params;
|
2017-08-05 21:02:09 +02:00
|
|
|
}
|
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ParameterizedTest(Param *p, format, highlevel, .init = init_memory) {
|
|
|
|
int ret, cnt;
|
|
|
|
char *retp;
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
Logger logger = logging.get("test:format:highlevel");
|
2018-10-20 14:24:51 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
logger->info("Running test for format={}, cnt={}", p->fmt, p->cnt);
|
2018-10-20 14:24:51 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
struct Sample *smps[p->cnt];
|
|
|
|
struct Sample *smpt[p->cnt];
|
2018-05-12 13:56:12 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
struct Pool pool;
|
|
|
|
Format *fmt;
|
2020-06-16 02:35:34 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = pool_init(&pool, 2 * p->cnt, SAMPLE_LENGTH(NUM_VALUES));
|
|
|
|
cr_assert_eq(ret, 0);
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = sample_alloc_many(&pool, smps, p->cnt);
|
|
|
|
cr_assert_eq(ret, p->cnt);
|
2018-08-20 18:32:10 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = sample_alloc_many(&pool, smpt, p->cnt);
|
|
|
|
cr_assert_eq(ret, p->cnt);
|
2018-08-20 18:32:10 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
auto signals = std::make_shared<SignalList>(NUM_VALUES, SignalType::FLOAT);
|
2018-08-20 18:32:10 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
fill_sample_data(signals, smps, p->cnt);
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
// Open a file for testing the formatter
|
|
|
|
char *fn, dir[64];
|
|
|
|
strncpy(dir, "/tmp/villas.XXXXXX", sizeof(dir));
|
2017-09-04 14:30:07 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
retp = mkdtemp(dir);
|
|
|
|
cr_assert_not_null(retp);
|
2017-10-20 11:37:25 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = asprintf(&fn, "%s/file", dir);
|
|
|
|
cr_assert_gt(ret, 0);
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
json_t *json_format = json_loads(p->fmt.c_str(), 0, nullptr);
|
|
|
|
cr_assert_not_null(json_format);
|
2018-08-20 18:32:10 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
fmt = FormatFactory::make(json_format);
|
|
|
|
cr_assert_not_null(fmt, "Failed to create formatter of type '%s'",
|
|
|
|
p->fmt.c_str());
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2023-09-13 10:16:39 +02:00
|
|
|
fmt->start(signals, (int)SampleFlags::ALL);
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
auto *stream = fopen(fn, "w+");
|
|
|
|
cr_assert_not_null(stream);
|
2017-09-04 14:30:07 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
cnt = fmt->print(stream, smps, p->cnt);
|
|
|
|
cr_assert_eq(cnt, p->cnt, "Written only %d of %d samples", cnt, p->cnt);
|
2021-05-10 00:12:30 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = fflush(stream);
|
|
|
|
cr_assert_eq(ret, 0);
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2017-08-20 10:48:44 +02:00
|
|
|
#if 0 // Show the file contents
|
2024-02-29 21:58:34 +01:00
|
|
|
char cmd[128];
|
|
|
|
if (p->fmt == "csv" || p->fmt == "json" || p->fmt == "villas.human")
|
|
|
|
snprintf(cmd, sizeof(cmd), "cat %s", fn);
|
|
|
|
else
|
|
|
|
snprintf(cmd, sizeof(cmd), "hexdump -C %s", fn);
|
|
|
|
system(cmd);
|
2017-08-14 14:42:07 +02:00
|
|
|
#endif
|
2017-09-04 14:30:07 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
rewind(stream);
|
2017-08-14 14:42:07 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
cnt = fmt->scan(stream, smpt, p->cnt);
|
|
|
|
cr_assert_eq(cnt, p->cnt, "Read only %d of %d samples back", cnt, p->cnt);
|
2018-08-20 18:32:10 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
for (int i = 0; i < cnt; i++) {
|
|
|
|
if (p->bits)
|
|
|
|
cr_assert_eq_sample_raw(smps[i], smpt[i], fmt->getFlags(), p->bits);
|
|
|
|
else
|
|
|
|
cr_assert_eq_sample(smps[i], smpt[i], fmt->getFlags());
|
|
|
|
}
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = fclose(stream);
|
|
|
|
cr_assert_eq(ret, 0);
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
delete fmt;
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = unlink(fn);
|
|
|
|
cr_assert_eq(ret, 0);
|
2017-09-04 14:30:07 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = rmdir(dir);
|
|
|
|
cr_assert_eq(ret, 0);
|
2017-09-04 14:30:07 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
free(fn);
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
sample_free_many(smps, p->cnt);
|
|
|
|
sample_free_many(smpt, p->cnt);
|
2017-08-05 21:02:09 +02:00
|
|
|
|
2023-09-07 11:46:39 +02:00
|
|
|
ret = pool_destroy(&pool);
|
|
|
|
cr_assert_eq(ret, 0);
|
2017-08-05 21:02:09 +02:00
|
|
|
}
|