///-------------------------------------------------------------------------------------------------
///
/// \file CMatrixTest.hpp
/// \brief Test Definitions for OpenViBE Matrix Class.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 11/05/2020.
/// \copyright GNU Affero General Public License v3.0.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include
#include
#include
#include
#include "utils.hpp"
//---------------------------------------------------------------------------------------------------
namespace Dataset {
const double HOUR = 60 * 60;
const double DAY = 24 * HOUR;
const double WEEK = 7 * DAY;
const double MONTH = 30 * DAY;
const double YEAR = 365 * DAY;
/// time values to test in seconds
const std::vector SECONDS =
{
0, 0.001, 0.01, 0.1, 0.2, 0.25, 0.5, 1.0, 1.1, 1.5, 2,
1.000001, 1.999, 1.999999,
5, 10, 50, 100, 123.456789, 128.0, 500, 1000, 2500, 5000,
DAY, DAY + 0.03, DAY + 0.999, DAY + 1,
WEEK, WEEK + 0.03, WEEK + 0.999, WEEK + 1,
MONTH, MONTH + 0.03, MONTH + 0.999, MONTH + 1,
YEAR, YEAR + 0.03, YEAR + 0.999, YEAR + 1,
};
/// Time values to test in fixed point format.
const std::vector FIXED_POINT =
{
1LL << 8, 1LL << 16, 1L << 19, 1LL << 22, 1LL << 27, 1L << 30, 1LL << 32, 10LL << 32, 100LL << 32, 123LL << 32, 500LL << 32, 512LL << 32, 1000LL << 32,
1024LL << 32, 2001LL << 32, 5000LL << 32
};
/// Sampling rates to test.
const std::vector SAMPLINGS = { 100, 128, 512, 1000, 1024, 16000, 44100 };
/// Samples to test.
const std::vector SAMPLES = { 0, 1, 100, 128, 512, 1000, 1021, 1024, 5005, 12345, 59876, 100000, 717893, 1000001 };
/// Epoch durations to test.
const std::vector DURATIONS = { 0.01, 0.1, 0.2, 0.25, 0.5, 1.0, 1.1, 1.5, 2, 5, 10, 50, 100 };
/// We select 10-9 tolerance for seconds, being the best precision capacity of the CTime class.
const double TOLERANCE = 10e-9;
} // namespace Dataset
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST(CTime_Tests, constructor_time)
{
for (auto ref : Dataset::FIXED_POINT)
{
const OpenViBE::CTime res(ref);
EXPECT_EQ(res.time(), ref) << ErrorMsg("Constructor with time", ref, res.time());
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST(CTime_Tests, constructor_seconds)
{
// test construction & conversion second -> fixed point -> second
for (auto ref : Dataset::SECONDS)
{
const auto res = OpenViBE::CTime(ref).toSeconds();
EXPECT_LT(std::abs(res - ref), Dataset::TOLERANCE) << ErrorMsg("Constructor with seconds and conversion to seconds", ref, res);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST(CTime_Tests, constructor_sampling)
{
// test construction & conversion sample -> time -> sample
for (auto sampling : Dataset::SAMPLINGS)
{
for (auto ref : Dataset::SAMPLES)
{
const auto res = OpenViBE::CTime(sampling, ref).toSampleCount(sampling);
EXPECT_EQ(ref, res) << ErrorMsg("Constructor with sampling and sample count and conversion to sample count", ref, res);
}
}
EXPECT_TRUE(OpenViBE::CTime(0, 1) == OpenViBE::CTime::max()) << ErrorMsg("Special Case if sampling = 0",
OpenViBE::CTime::max(), OpenViBE::CTime(0, 1));
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST(CTime_Tests, ceil)
{
// Ceil Test
const OpenViBE::CTime t0 = OpenViBE::CTime().min().ceil();
const OpenViBE::CTime t1 = OpenViBE::CTime().max().ceil();
const OpenViBE::CTime t2 = OpenViBE::CTime(0xFEDCBA9876543210).ceil();
const OpenViBE::CTime t3 = OpenViBE::CTime(0xFEDCBA9900000000);
EXPECT_TRUE(t0 == t0) << ErrorMsg("ceil of Time Min (0)", t0, t0);
EXPECT_TRUE(t1 == t0) << ErrorMsg("ceil of Time Max (0xFFFFFFFFFFFFFFFF)", t0, t1);
EXPECT_TRUE(t2 == t3) << ErrorMsg("ceil of Time (0xFEDCBA9876543210)", t3, t2);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST(CTime_Tests, operators)
{
// Operators Tests
const OpenViBE::CTime t0 = OpenViBE::CTime(1.0) + OpenViBE::CTime(1.0);
const OpenViBE::CTime t1 = OpenViBE::CTime(4.0) - OpenViBE::CTime(1.0);
const OpenViBE::CTime t2 = OpenViBE::CTime(1.0) - OpenViBE::CTime(4.0);
const OpenViBE::CTime r0 = OpenViBE::CTime(2.0);
const OpenViBE::CTime r1 = OpenViBE::CTime(3.0);
// we remove 2 second from the max
// - We have -3 as result, with uint max = -1 so result is max - 2
// and max seconds = 2^32 - 1 (0xFFFFFFFF) so result is max - 2 : 0xFFFFFFFD so in Fixed Point 0xFFFFFFFD00000000)
const OpenViBE::CTime r2 = OpenViBE::CTime(0xFFFFFFFD00000000);
// Comparison
EXPECT_TRUE(r0 == r0) << ErrorMsg("ref == calc", t0, t0);
EXPECT_FALSE(r0 != r0) << ErrorMsg("!(ref != calc)", t1, t1);
EXPECT_TRUE(r0 < r1) << ErrorMsg("(ref < calc)", r0, r1);
EXPECT_TRUE(r0 <= r1) << ErrorMsg("(ref <= calc)", r0, r1);
EXPECT_TRUE(r1 > r0) << ErrorMsg("(ref > calc)", r1, r0);
EXPECT_TRUE(r1 >= r0) << ErrorMsg("(ref >= calc)", r1, r0);
// Operation
EXPECT_TRUE(t0 == r0) << ErrorMsg("Addition result", r0, t0);
EXPECT_TRUE(t1 == r1) << ErrorMsg("Substract result", r1, t1);
EXPECT_TRUE(t2 == r2) << ErrorMsg("substract with negative result", r2, t2);
// Str
EXPECT_EQ("1.000 sec (0x0000000100000000)", OpenViBE::CTime(1.0).str(true, true));
EXPECT_EQ("1.000 sec", OpenViBE::CTime(1.0).str(true, false));
EXPECT_EQ("4294967296 (0x0000000100000000)", OpenViBE::CTime(1.0).str(false, true));
EXPECT_EQ("4294967296", OpenViBE::CTime(1.0).str(false, false));
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST(CTime_Tests, conversion_chain)
{
// test conversion time -> sample -> time
for (auto sampling : Dataset::SAMPLINGS)
{
for (auto seconds : Dataset::SECONDS)
{
auto tmp = OpenViBE::CTime(seconds).time();
// If the sample count would overflow an uint64_t we skip the test
if (std::log2(sampling) + std::log2(tmp) >= 64) { continue; }
const uint64_t compute = OpenViBE::CTime(sampling, OpenViBE::CTime(tmp).toSampleCount(sampling)).time();
const uint64_t difference = uint64_t(std::abs(int64_t(compute) - int64_t(tmp)));
EXPECT_LT(OpenViBE::CTime(difference).toSeconds(), (1.0 / double(sampling)))
<< "Time difference too large between OV(" << seconds << ") and "
<< "SCtoOV(" << sampling << ", OVtoSC(" << sampling << "," << tmp << "))";
}
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST(CTime_Tests, legacy_epoching)
{
// compare second -> time conversion to legacy method
for (auto duration : Dataset::DURATIONS)
{
const auto legacy = uint64_t(duration * (1LL << 32)); // Legacy code from stimulationBasedEpoching
const auto res = OpenViBE::CTime(duration).time();
EXPECT_EQ(res, legacy) << ErrorMsg("Legacy Epoching for duration : " + std::to_string(duration), legacy, res);
}
}
//---------------------------------------------------------------------------------------------------