///------------------------------------------------------------------------------------------------- /// /// \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); } } //---------------------------------------------------------------------------------------------------