#include #include #include #include #include namespace { /// Generates a date in double auto date = [](int year, int month, int day, int hours, int minutes, int seconds) { return DateUtils::secondsSinceEpoch( QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC}); }; /// Generates a series of test data for a range std::shared_ptr dataSeries(const SqpRange &range) { auto xAxisData = std::vector{}; auto valuesData = std::vector{}; auto value = 0; for (auto x = range.m_TStart; x <= range.m_TEnd; ++x, ++value) { xAxisData.push_back(x); valuesData.push_back(value); } return std::make_shared(std::move(xAxisData), std::move(valuesData), Unit{}, Unit{}); } } // namespace Q_DECLARE_METATYPE(std::shared_ptr) class TestVariable : public QObject { Q_OBJECT private slots: void testClone_data(); void testClone(); void testNotInCacheRangeList(); void testInCacheRangeList(); void testNbPoints_data(); void testNbPoints(); void testRealRange_data(); void testRealRange(); }; void TestVariable::testClone_data() { // ////////////// // // Test structure // // ////////////// // QTest::addColumn("name"); QTest::addColumn("metadata"); QTest::addColumn("range"); QTest::addColumn("cacheRange"); QTest::addColumn >("dataSeries"); // ////////// // // Test cases // // ////////// // auto cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 13, 0, 0)}; QTest::newRow("clone1") << QStringLiteral("var1") << QVariantHash{{"data1", 1}, {"data2", "abc"}} << SqpRange{date(2017, 1, 1, 12, 30, 0), (date(2017, 1, 1, 12, 45, 0))} << cacheRange << dataSeries(cacheRange); } void TestVariable::testClone() { // Creates variable QFETCH(QString, name); QFETCH(QVariantHash, metadata); QFETCH(SqpRange, range); QFETCH(SqpRange, cacheRange); QFETCH(std::shared_ptr, dataSeries); Variable variable{name, metadata}; variable.setRange(range); variable.setCacheRange(cacheRange); variable.mergeDataSeries(dataSeries); // Clones variable auto clone = variable.clone(); // Checks cloned variable's state QCOMPARE(clone->name(), name); QCOMPARE(clone->metadata(), metadata); QCOMPARE(clone->range(), range); QCOMPARE(clone->cacheRange(), cacheRange); // Compares data series if (dataSeries != nullptr) { QVERIFY(clone->dataSeries() != nullptr); QVERIFY(std::equal(dataSeries->cbegin(), dataSeries->cend(), clone->dataSeries()->cbegin(), clone->dataSeries()->cend(), [](const auto &it1, const auto &it2) { return it1.x() == it2.x() && it1.value() == it2.value(); })); } else { QVERIFY(clone->dataSeries() == nullptr); } } void TestVariable::testNotInCacheRangeList() { auto varRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}}; auto varRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 40, 0}}; auto sqpR = SqpRange{DateUtils::secondsSinceEpoch(varRS), DateUtils::secondsSinceEpoch(varRE)}; auto varCRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}}; auto varCRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}}; auto sqpCR = SqpRange{DateUtils::secondsSinceEpoch(varCRS), DateUtils::secondsSinceEpoch(varCRE)}; Variable var{"Var test"}; var.setRange(sqpR); var.setCacheRange(sqpCR); // 1: [ts,te] < varTS auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}}; auto sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; auto notInCach = var.provideNotInCacheRangeList(sqp); QCOMPARE(notInCach.size(), 1); auto notInCachRange = notInCach.first(); QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts)); QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te)); // 2: ts < varTS < te < varTE ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; notInCach = var.provideNotInCacheRangeList(sqp); QCOMPARE(notInCach.size(), 1); notInCachRange = notInCach.first(); QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts)); QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRS)); // 3: varTS < ts < te < varTE ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}}; te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; notInCach = var.provideNotInCacheRangeList(sqp); QCOMPARE(notInCach.size(), 0); // 4: varTS < ts < varTE < te ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}}; te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; notInCach = var.provideNotInCacheRangeList(sqp); QCOMPARE(notInCach.size(), 1); notInCachRange = notInCach.first(); QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRE)); QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te)); // 5: varTS < varTE < ts < te ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 20, 0}}; te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; notInCach = var.provideNotInCacheRangeList(sqp); QCOMPARE(notInCach.size(), 1); notInCachRange = notInCach.first(); QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts)); QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te)); // 6: ts m_DataSeries; /// Series to merge in the variable int m_ExpectedNbPoints; /// Number of points in the variable expected after operation }; using NbPointsOperations = std::vector; } // namespace Q_DECLARE_METATYPE(NbPointsOperations) void TestVariable::testNbPoints_data() { // ////////////// // // Test structure // // ////////////// // QTest::addColumn("operations"); // ////////// // // Test cases // // ////////// // NbPointsOperations operations{}; // Sets cache range (expected nb points = values data) auto cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 9)}; operations.push_back({cacheRange, dataSeries(cacheRange), 10}); // Doubles cache but don't add data series (expected nb points don't change) cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)}; operations.push_back({cacheRange, dataSeries(INVALID_RANGE), 10}); // Doubles cache and data series (expected nb points change) cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)}; operations.push_back({cacheRange, dataSeries(cacheRange), 20}); // Decreases cache (expected nb points decreases as the series is purged) cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 5), date(2017, 1, 1, 12, 0, 9)}; operations.push_back({cacheRange, dataSeries(INVALID_RANGE), 5}); QTest::newRow("nbPoints1") << operations; } void TestVariable::testNbPoints() { // Creates variable Variable variable{"var"}; QCOMPARE(variable.nbPoints(), 0); QFETCH(NbPointsOperations, operations); for (const auto &operation : operations) { // Sets cache range and merge data series variable.setCacheRange(operation.m_CacheRange); if (operation.m_DataSeries != nullptr) { variable.mergeDataSeries(operation.m_DataSeries); } // Checks nb points QCOMPARE(variable.nbPoints(), operation.m_ExpectedNbPoints); } } namespace { /// Struct used to represent a range operation on a variable /// @sa TestVariable::testRealRange() struct RangeOperation { SqpRange m_CacheRange; /// Range to set for the variable std::shared_ptr m_DataSeries; /// Series to merge in the variable SqpRange m_ExpectedRealRange; /// Real Range expected after operation on the variable }; using RangeOperations = std::vector; } // namespace Q_DECLARE_METATYPE(RangeOperations) void TestVariable::testRealRange_data() { // ////////////// // // Test structure // // ////////////// // QTest::addColumn("operations"); // ////////// // // Test cases // // ////////// // RangeOperations operations{}; // Inits cache range and data series (expected real range = cache range) auto cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 13, 0, 0)}; operations.push_back({cacheRange, dataSeries(cacheRange), cacheRange}); // Changes cache range and updates data series (expected real range = cache range) cacheRange = SqpRange{date(2017, 1, 1, 14, 0, 0), date(2017, 1, 1, 15, 0, 0)}; operations.push_back({cacheRange, dataSeries(cacheRange), cacheRange}); // Changes cache range and update data series but with a lower range (expected real range = // data series range) cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 16, 0, 0)}; auto dataSeriesRange = SqpRange{date(2017, 1, 1, 14, 0, 0), date(2017, 1, 1, 15, 0, 0)}; operations.push_back({cacheRange, dataSeries(dataSeriesRange), dataSeriesRange}); // Changes cache range but DON'T update data series (expected real range = cache range // before operation) cacheRange = SqpRange{date(2017, 1, 1, 10, 0, 0), date(2017, 1, 1, 17, 0, 0)}; operations.push_back({cacheRange, nullptr, dataSeriesRange}); QTest::newRow("realRange1") << operations; } void TestVariable::testRealRange() { // Creates variable (real range is invalid) Variable variable{"var"}; QCOMPARE(variable.realRange(), INVALID_RANGE); QFETCH(RangeOperations, operations); for (const auto &operation : operations) { // Sets cache range and merge data series variable.setCacheRange(operation.m_CacheRange); if (operation.m_DataSeries != nullptr) { variable.mergeDataSeries(operation.m_DataSeries); } // Checks real range QCOMPARE(variable.realRange(), operation.m_ExpectedRealRange); } } QTEST_MAIN(TestVariable) #include "TestVariable.moc"