From a502cf5c12a910097c512658b1d4a05394deab22 2017-09-29 09:43:53 From: perrinel Date: 2017-09-29 09:43:53 Subject: [PATCH] Merge pull request #305 from SciQLop-fork develop Develop --- diff --git a/core/include/Data/DataSeries.h b/core/include/Data/DataSeries.h index 1669c91..dff18f8 100644 --- a/core/include/Data/DataSeries.h +++ b/core/include/Data/DataSeries.h @@ -148,15 +148,6 @@ public: int nbPoints() const override { return m_XAxisData->totalSize() + m_ValuesData->totalSize(); } - SqpRange range() const override - { - if (!m_XAxisData->cdata().empty()) { - return SqpRange{m_XAxisData->cdata().front(), m_XAxisData->cdata().back()}; - } - - return SqpRange{}; - } - void clear() { m_XAxisData->clear(); diff --git a/core/include/Data/IDataSeries.h b/core/include/Data/IDataSeries.h index f7c2aa1..19778fb 100644 --- a/core/include/Data/IDataSeries.h +++ b/core/include/Data/IDataSeries.h @@ -68,8 +68,6 @@ public: /// @return the total number of points contained in the data series virtual int nbPoints() const = 0; - virtual SqpRange range() const = 0; - // ///////// // // Iterators // // ///////// // diff --git a/core/src/Variable/VariableController.cpp b/core/src/Variable/VariableController.cpp index 6fa1b1e..7b231da 100644 --- a/core/src/Variable/VariableController.cpp +++ b/core/src/Variable/VariableController.cpp @@ -788,9 +788,7 @@ void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid qCDebug(LOG_VariableController()) << tr("2: onDataProvided") << varRequest.m_CacheRangeRequested; var->mergeDataSeries(varRequest.m_DataSeries); - qCDebug(LOG_VariableController()) << tr("3: onDataProvided") - << varRequest.m_DataSeries->range(); - qCDebug(LOG_VariableController()) << tr("4: onDataProvided"); + qCDebug(LOG_VariableController()) << tr("3: onDataProvided"); /// @todo MPL: confirm // Variable update is notified only if there is no pending request for it diff --git a/core/tests/Data/TestDataSeries.cpp b/core/tests/Data/TestDataSeries.cpp index 3551e87..15a9f10 100644 --- a/core/tests/Data/TestDataSeries.cpp +++ b/core/tests/Data/TestDataSeries.cpp @@ -125,6 +125,39 @@ private: expectedValuesData); } + template + void testMergeDifferentTypesStructure() + { + // ////////////// // + // Test structure // + // ////////////// // + + // Data series to merge + QTest::addColumn >("dest"); + QTest::addColumn >("source"); + + // Expected values in the dest data series after merge + QTest::addColumn("expectedXAxisData"); + QTest::addColumn("expectedValuesData"); + } + + template + void testMergeDifferentTypes() + { + // Merges series + QFETCH(std::shared_ptr, source); + QFETCH(std::shared_ptr, dest); + + dest->merge(source.get()); + + // Validates results : we check that the merge is valid and the data series is sorted on its + // x-axis data + QFETCH(DataContainer, expectedXAxisData); + QFETCH(DataContainer, expectedValuesData); + + validateRange(dest->cbegin(), dest->cend(), expectedXAxisData, expectedValuesData); + } + private slots: /// Input test data @@ -142,6 +175,13 @@ private slots: void testMerge(); /// Input test data + /// @sa testMergeVectorInScalar() + void testMergeVectorInScalar_data(); + + /// Tests merge of vector series in scalar series + void testMergeVectorInScalar(); + + /// Input test data /// @sa testPurgeScalar() void testPurgeScalar_data(); @@ -305,6 +345,11 @@ void TestDataSeries::testMerge_data() << createScalarSeries({1., 2., 3., 7., 10.}, {100., 200., 333., 777., 1000.}) << DataContainer{1., 2., 3., 4., 5., 7., 8., 10.} << DataContainer{100., 200., 300., 400., 500., 700., 800., 1000.}; + + QTest::newRow("emptySource") << createScalarSeries({3., 4., 5., 7., 8}, + {300., 400., 500., 700., 800.}) + << createScalarSeries({}, {}) << DataContainer{3., 4., 5., 7., 8.} + << DataContainer{300., 400., 500., 700., 800.}; } void TestDataSeries::testMerge() @@ -323,6 +368,26 @@ void TestDataSeries::testMerge() validateRange(dataSeries->cbegin(), dataSeries->cend(), expectedXAxisData, expectedValuesData); } +void TestDataSeries::testMergeVectorInScalar_data() +{ + testMergeDifferentTypesStructure(); + + // ////////// // + // Test cases // + // ////////// // + + QTest::newRow("purgeVectorInScalar") + << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) + << createVectorSeries({6., 7., 8., 9., 10.}, {600., 700., 800., 900., 1000.}, + {610., 710., 810., 910., 1010.}, {620., 720., 820., 920., 1020.}) + << DataContainer{1., 2., 3., 4., 5.} << DataContainer{100., 200., 300., 400., 500.}; +} + +void TestDataSeries::testMergeVectorInScalar() +{ + testMergeDifferentTypes(); +} + void TestDataSeries::testPurgeScalar_data() { testPurgeStructure(); @@ -335,6 +400,9 @@ void TestDataSeries::testPurgeScalar_data() {100., 200., 300., 400., 500.}) << 2. << 4. << DataContainer{2., 3., 4.} << std::vector{{200., 300., 400.}}; + QTest::newRow("purgeScalar1 (min/max swap)") + << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) << 4. << 2. + << DataContainer{2., 3., 4.} << std::vector{{200., 300., 400.}}; QTest::newRow("purgeScalar2") << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) << 0. << 2.5 << DataContainer{1., 2.} @@ -517,10 +585,13 @@ void TestDataSeries::testXAxisRange_data() // Test cases // // ////////// // - QTest::newRow("xAxisRange1") << createScalarSeries({1., 2., 3., 4., 5.}, - {100., 200., 300., 400., 500.}) - << -1. << 3.2 << DataContainer{1., 2., 3.} - << DataContainer{100., 200., 300.}; + QTest::newRow("xAxisRange") << createScalarSeries({1., 2., 3., 4., 5.}, + {100., 200., 300., 400., 500.}) + << -1. << 3.2 << DataContainer{1., 2., 3.} + << DataContainer{100., 200., 300.}; + QTest::newRow("xAxisRange1 (min/max swap)") + << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) << 3.2 << -1. + << DataContainer{1., 2., 3.} << DataContainer{100., 200., 300.}; QTest::newRow("xAxisRange2") << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) << 1. << 4. << DataContainer{1., 2., 3., 4.} diff --git a/core/tests/Variable/TestVariable.cpp b/core/tests/Variable/TestVariable.cpp index e6688fa..7511a24 100644 --- a/core/tests/Variable/TestVariable.cpp +++ b/core/tests/Variable/TestVariable.cpp @@ -1,19 +1,115 @@ #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 testNotInCacheRangeList(); + 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() { @@ -172,6 +268,142 @@ void TestVariable::testInCacheRangeList() QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRE)); } +namespace { + +/// Struct used to represent an operation for @sa TestVariable::testNbPoints() +struct NbPointsOperation { + SqpRange m_CacheRange; /// Range to set for the variable + std::shared_ptr 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 = series xAxis data + series 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), 20}); + + // 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, nullptr, 20}); + + // 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), 40}); + + // 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, nullptr, 10}); + + 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" diff --git a/plugins/mockplugin/meson.build b/plugins/mockplugin/meson.build index 25101a2..fb1070b 100644 --- a/plugins/mockplugin/meson.build +++ b/plugins/mockplugin/meson.build @@ -4,6 +4,7 @@ mockplugin_moc_headers = [ ] mockplugin_sources = [ + 'src/MockDefs.cpp', 'src/CosinusProvider.cpp', 'src/MockPlugin.cpp' ]