@@ -148,15 +148,6 public: | |||
|
148 | 148 | |
|
149 | 149 | int nbPoints() const override { return m_XAxisData->totalSize() + m_ValuesData->totalSize(); } |
|
150 | 150 | |
|
151 | SqpRange range() const override | |
|
152 | { | |
|
153 | if (!m_XAxisData->cdata().empty()) { | |
|
154 | return SqpRange{m_XAxisData->cdata().front(), m_XAxisData->cdata().back()}; | |
|
155 | } | |
|
156 | ||
|
157 | return SqpRange{}; | |
|
158 | } | |
|
159 | ||
|
160 | 151 | void clear() |
|
161 | 152 | { |
|
162 | 153 | m_XAxisData->clear(); |
@@ -68,8 +68,6 public: | |||
|
68 | 68 | /// @return the total number of points contained in the data series |
|
69 | 69 | virtual int nbPoints() const = 0; |
|
70 | 70 | |
|
71 | virtual SqpRange range() const = 0; | |
|
72 | ||
|
73 | 71 | // ///////// // |
|
74 | 72 | // Iterators // |
|
75 | 73 | // ///////// // |
@@ -788,9 +788,7 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid | |||
|
788 | 788 | qCDebug(LOG_VariableController()) << tr("2: onDataProvided") |
|
789 | 789 | << varRequest.m_CacheRangeRequested; |
|
790 | 790 | var->mergeDataSeries(varRequest.m_DataSeries); |
|
791 | qCDebug(LOG_VariableController()) << tr("3: onDataProvided") | |
|
792 | << varRequest.m_DataSeries->range(); | |
|
793 | qCDebug(LOG_VariableController()) << tr("4: onDataProvided"); | |
|
791 | qCDebug(LOG_VariableController()) << tr("3: onDataProvided"); | |
|
794 | 792 | |
|
795 | 793 | /// @todo MPL: confirm |
|
796 | 794 | // Variable update is notified only if there is no pending request for it |
@@ -125,6 +125,39 private: | |||
|
125 | 125 | expectedValuesData); |
|
126 | 126 | } |
|
127 | 127 | |
|
128 | template <typename SourceType, typename DestType> | |
|
129 | void testMergeDifferentTypesStructure() | |
|
130 | { | |
|
131 | // ////////////// // | |
|
132 | // Test structure // | |
|
133 | // ////////////// // | |
|
134 | ||
|
135 | // Data series to merge | |
|
136 | QTest::addColumn<std::shared_ptr<DestType> >("dest"); | |
|
137 | QTest::addColumn<std::shared_ptr<SourceType> >("source"); | |
|
138 | ||
|
139 | // Expected values in the dest data series after merge | |
|
140 | QTest::addColumn<DataContainer>("expectedXAxisData"); | |
|
141 | QTest::addColumn<DataContainer>("expectedValuesData"); | |
|
142 | } | |
|
143 | ||
|
144 | template <typename SourceType, typename DestType> | |
|
145 | void testMergeDifferentTypes() | |
|
146 | { | |
|
147 | // Merges series | |
|
148 | QFETCH(std::shared_ptr<SourceType>, source); | |
|
149 | QFETCH(std::shared_ptr<DestType>, dest); | |
|
150 | ||
|
151 | dest->merge(source.get()); | |
|
152 | ||
|
153 | // Validates results : we check that the merge is valid and the data series is sorted on its | |
|
154 | // x-axis data | |
|
155 | QFETCH(DataContainer, expectedXAxisData); | |
|
156 | QFETCH(DataContainer, expectedValuesData); | |
|
157 | ||
|
158 | validateRange(dest->cbegin(), dest->cend(), expectedXAxisData, expectedValuesData); | |
|
159 | } | |
|
160 | ||
|
128 | 161 | private slots: |
|
129 | 162 | |
|
130 | 163 | /// Input test data |
@@ -142,6 +175,13 private slots: | |||
|
142 | 175 | void testMerge(); |
|
143 | 176 | |
|
144 | 177 | /// Input test data |
|
178 | /// @sa testMergeVectorInScalar() | |
|
179 | void testMergeVectorInScalar_data(); | |
|
180 | ||
|
181 | /// Tests merge of vector series in scalar series | |
|
182 | void testMergeVectorInScalar(); | |
|
183 | ||
|
184 | /// Input test data | |
|
145 | 185 | /// @sa testPurgeScalar() |
|
146 | 186 | void testPurgeScalar_data(); |
|
147 | 187 | |
@@ -305,6 +345,11 void TestDataSeries::testMerge_data() | |||
|
305 | 345 | << createScalarSeries({1., 2., 3., 7., 10.}, {100., 200., 333., 777., 1000.}) |
|
306 | 346 | << DataContainer{1., 2., 3., 4., 5., 7., 8., 10.} |
|
307 | 347 | << DataContainer{100., 200., 300., 400., 500., 700., 800., 1000.}; |
|
348 | ||
|
349 | QTest::newRow("emptySource") << createScalarSeries({3., 4., 5., 7., 8}, | |
|
350 | {300., 400., 500., 700., 800.}) | |
|
351 | << createScalarSeries({}, {}) << DataContainer{3., 4., 5., 7., 8.} | |
|
352 | << DataContainer{300., 400., 500., 700., 800.}; | |
|
308 | 353 | } |
|
309 | 354 | |
|
310 | 355 | void TestDataSeries::testMerge() |
@@ -323,6 +368,26 void TestDataSeries::testMerge() | |||
|
323 | 368 | validateRange(dataSeries->cbegin(), dataSeries->cend(), expectedXAxisData, expectedValuesData); |
|
324 | 369 | } |
|
325 | 370 | |
|
371 | void TestDataSeries::testMergeVectorInScalar_data() | |
|
372 | { | |
|
373 | testMergeDifferentTypesStructure<VectorSeries, ScalarSeries>(); | |
|
374 | ||
|
375 | // ////////// // | |
|
376 | // Test cases // | |
|
377 | // ////////// // | |
|
378 | ||
|
379 | QTest::newRow("purgeVectorInScalar") | |
|
380 | << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) | |
|
381 | << createVectorSeries({6., 7., 8., 9., 10.}, {600., 700., 800., 900., 1000.}, | |
|
382 | {610., 710., 810., 910., 1010.}, {620., 720., 820., 920., 1020.}) | |
|
383 | << DataContainer{1., 2., 3., 4., 5.} << DataContainer{100., 200., 300., 400., 500.}; | |
|
384 | } | |
|
385 | ||
|
386 | void TestDataSeries::testMergeVectorInScalar() | |
|
387 | { | |
|
388 | testMergeDifferentTypes<VectorSeries, ScalarSeries>(); | |
|
389 | } | |
|
390 | ||
|
326 | 391 | void TestDataSeries::testPurgeScalar_data() |
|
327 | 392 | { |
|
328 | 393 | testPurgeStructure<ScalarSeries>(); |
@@ -335,6 +400,9 void TestDataSeries::testPurgeScalar_data() | |||
|
335 | 400 | {100., 200., 300., 400., 500.}) |
|
336 | 401 | << 2. << 4. << DataContainer{2., 3., 4.} |
|
337 | 402 | << std::vector<DataContainer>{{200., 300., 400.}}; |
|
403 | QTest::newRow("purgeScalar1 (min/max swap)") | |
|
404 | << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) << 4. << 2. | |
|
405 | << DataContainer{2., 3., 4.} << std::vector<DataContainer>{{200., 300., 400.}}; | |
|
338 | 406 | QTest::newRow("purgeScalar2") << createScalarSeries({1., 2., 3., 4., 5.}, |
|
339 | 407 | {100., 200., 300., 400., 500.}) |
|
340 | 408 | << 0. << 2.5 << DataContainer{1., 2.} |
@@ -517,10 +585,13 void TestDataSeries::testXAxisRange_data() | |||
|
517 | 585 | // Test cases // |
|
518 | 586 | // ////////// // |
|
519 | 587 | |
|
520 |
QTest::newRow("xAxisRange |
|
|
588 | QTest::newRow("xAxisRange") << createScalarSeries({1., 2., 3., 4., 5.}, | |
|
521 | 589 |
|
|
522 | 590 |
|
|
523 | 591 |
|
|
592 | QTest::newRow("xAxisRange1 (min/max swap)") | |
|
593 | << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) << 3.2 << -1. | |
|
594 | << DataContainer{1., 2., 3.} << DataContainer{100., 200., 300.}; | |
|
524 | 595 | QTest::newRow("xAxisRange2") << createScalarSeries({1., 2., 3., 4., 5.}, |
|
525 | 596 | {100., 200., 300., 400., 500.}) |
|
526 | 597 | << 1. << 4. << DataContainer{1., 2., 3., 4.} |
@@ -581,8 +652,8 void TestDataSeries::testValuesBoundsScalar_data() | |||
|
581 | 652 | QTest::newRow("scalarBounds4") |
|
582 | 653 | << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) << 5.1 << 6. |
|
583 | 654 | << false << nan << nan; |
|
584 | QTest::newRow("scalarBounds5") << createScalarSeries({1.}, {100.}) << 0. << 2. << true << 100. | |
|
585 | << 100.; | |
|
655 | QTest::newRow("scalarBounds5") | |
|
656 | << createScalarSeries({1.}, {100.}) << 0. << 2. << true << 100. << 100.; | |
|
586 | 657 | QTest::newRow("scalarBounds6") << createScalarSeries({}, {}) << 0. << 2. << false << nan << nan; |
|
587 | 658 | |
|
588 | 659 | // Tests with NaN values: NaN values are not included in min/max search |
@@ -1,19 +1,115 | |||
|
1 | 1 | #include <Variable/Variable.h> |
|
2 | 2 | |
|
3 | #include <Data/ScalarSeries.h> | |
|
4 | ||
|
3 | 5 | #include <QObject> |
|
4 | 6 | #include <QtTest> |
|
5 | 7 | |
|
6 | 8 | #include <memory> |
|
7 | 9 | |
|
10 | namespace { | |
|
11 | ||
|
12 | /// Generates a date in double | |
|
13 | auto date = [](int year, int month, int day, int hours, int minutes, int seconds) { | |
|
14 | return DateUtils::secondsSinceEpoch( | |
|
15 | QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC}); | |
|
16 | }; | |
|
17 | ||
|
18 | /// Generates a series of test data for a range | |
|
19 | std::shared_ptr<ScalarSeries> dataSeries(const SqpRange &range) | |
|
20 | { | |
|
21 | auto xAxisData = std::vector<double>{}; | |
|
22 | auto valuesData = std::vector<double>{}; | |
|
23 | ||
|
24 | auto value = 0; | |
|
25 | for (auto x = range.m_TStart; x <= range.m_TEnd; ++x, ++value) { | |
|
26 | xAxisData.push_back(x); | |
|
27 | valuesData.push_back(value); | |
|
28 | } | |
|
29 | ||
|
30 | return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData), Unit{}, | |
|
31 | Unit{}); | |
|
32 | } | |
|
33 | ||
|
34 | } // namespace | |
|
35 | ||
|
36 | Q_DECLARE_METATYPE(std::shared_ptr<ScalarSeries>) | |
|
37 | ||
|
8 | 38 | class TestVariable : public QObject { |
|
9 | 39 | Q_OBJECT |
|
10 | 40 | |
|
11 | 41 | private slots: |
|
12 |
void test |
|
|
42 | void testClone_data(); | |
|
43 | void testClone(); | |
|
13 | 44 | |
|
45 | void testNotInCacheRangeList(); | |
|
14 | 46 | void testInCacheRangeList(); |
|
47 | ||
|
48 | void testNbPoints_data(); | |
|
49 | void testNbPoints(); | |
|
50 | ||
|
51 | void testRealRange_data(); | |
|
52 | void testRealRange(); | |
|
15 | 53 | }; |
|
16 | 54 | |
|
55 | void TestVariable::testClone_data() | |
|
56 | { | |
|
57 | // ////////////// // | |
|
58 | // Test structure // | |
|
59 | // ////////////// // | |
|
60 | ||
|
61 | QTest::addColumn<QString>("name"); | |
|
62 | QTest::addColumn<QVariantHash>("metadata"); | |
|
63 | QTest::addColumn<SqpRange>("range"); | |
|
64 | QTest::addColumn<SqpRange>("cacheRange"); | |
|
65 | QTest::addColumn<std::shared_ptr<ScalarSeries> >("dataSeries"); | |
|
66 | ||
|
67 | // ////////// // | |
|
68 | // Test cases // | |
|
69 | // ////////// // | |
|
70 | ||
|
71 | auto cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 13, 0, 0)}; | |
|
72 | QTest::newRow("clone1") << QStringLiteral("var1") | |
|
73 | << QVariantHash{{"data1", 1}, {"data2", "abc"}} | |
|
74 | << SqpRange{date(2017, 1, 1, 12, 30, 0), (date(2017, 1, 1, 12, 45, 0))} | |
|
75 | << cacheRange << dataSeries(cacheRange); | |
|
76 | } | |
|
77 | ||
|
78 | void TestVariable::testClone() | |
|
79 | { | |
|
80 | // Creates variable | |
|
81 | QFETCH(QString, name); | |
|
82 | QFETCH(QVariantHash, metadata); | |
|
83 | QFETCH(SqpRange, range); | |
|
84 | QFETCH(SqpRange, cacheRange); | |
|
85 | QFETCH(std::shared_ptr<ScalarSeries>, dataSeries); | |
|
86 | ||
|
87 | Variable variable{name, metadata}; | |
|
88 | variable.setRange(range); | |
|
89 | variable.setCacheRange(cacheRange); | |
|
90 | variable.mergeDataSeries(dataSeries); | |
|
91 | ||
|
92 | // Clones variable | |
|
93 | auto clone = variable.clone(); | |
|
94 | ||
|
95 | // Checks cloned variable's state | |
|
96 | QCOMPARE(clone->name(), name); | |
|
97 | QCOMPARE(clone->metadata(), metadata); | |
|
98 | QCOMPARE(clone->range(), range); | |
|
99 | QCOMPARE(clone->cacheRange(), cacheRange); | |
|
100 | ||
|
101 | // Compares data series | |
|
102 | if (dataSeries != nullptr) { | |
|
103 | QVERIFY(clone->dataSeries() != nullptr); | |
|
104 | QVERIFY(std::equal(dataSeries->cbegin(), dataSeries->cend(), clone->dataSeries()->cbegin(), | |
|
105 | clone->dataSeries()->cend(), [](const auto &it1, const auto &it2) { | |
|
106 | return it1.x() == it2.x() && it1.value() == it2.value(); | |
|
107 | })); | |
|
108 | } | |
|
109 | else { | |
|
110 | QVERIFY(clone->dataSeries() == nullptr); | |
|
111 | } | |
|
112 | } | |
|
17 | 113 | |
|
18 | 114 | void TestVariable::testNotInCacheRangeList() |
|
19 | 115 | { |
@@ -172,6 +268,142 void TestVariable::testInCacheRangeList() | |||
|
172 | 268 | QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRE)); |
|
173 | 269 | } |
|
174 | 270 | |
|
271 | namespace { | |
|
272 | ||
|
273 | /// Struct used to represent an operation for @sa TestVariable::testNbPoints() | |
|
274 | struct NbPointsOperation { | |
|
275 | SqpRange m_CacheRange; /// Range to set for the variable | |
|
276 | std::shared_ptr<ScalarSeries> m_DataSeries; /// Series to merge in the variable | |
|
277 | int m_ExpectedNbPoints; /// Number of points in the variable expected after operation | |
|
278 | }; | |
|
279 | ||
|
280 | using NbPointsOperations = std::vector<NbPointsOperation>; | |
|
281 | ||
|
282 | } // namespace | |
|
283 | ||
|
284 | Q_DECLARE_METATYPE(NbPointsOperations) | |
|
285 | ||
|
286 | void TestVariable::testNbPoints_data() | |
|
287 | { | |
|
288 | // ////////////// // | |
|
289 | // Test structure // | |
|
290 | // ////////////// // | |
|
291 | ||
|
292 | QTest::addColumn<NbPointsOperations>("operations"); | |
|
293 | ||
|
294 | // ////////// // | |
|
295 | // Test cases // | |
|
296 | // ////////// // | |
|
297 | NbPointsOperations operations{}; | |
|
298 | ||
|
299 | // Sets cache range (expected nb points = series xAxis data + series values data) | |
|
300 | auto cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 9)}; | |
|
301 | operations.push_back({cacheRange, dataSeries(cacheRange), 20}); | |
|
302 | ||
|
303 | // Doubles cache but don't add data series (expected nb points don't change) | |
|
304 | cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)}; | |
|
305 | operations.push_back({cacheRange, nullptr, 20}); | |
|
306 | ||
|
307 | // Doubles cache and data series (expected nb points change) | |
|
308 | cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)}; | |
|
309 | operations.push_back({cacheRange, dataSeries(cacheRange), 40}); | |
|
310 | ||
|
311 | // Decreases cache (expected nb points decreases as the series is purged) | |
|
312 | cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 5), date(2017, 1, 1, 12, 0, 9)}; | |
|
313 | operations.push_back({cacheRange, nullptr, 10}); | |
|
314 | ||
|
315 | QTest::newRow("nbPoints1") << operations; | |
|
316 | } | |
|
317 | ||
|
318 | void TestVariable::testNbPoints() | |
|
319 | { | |
|
320 | // Creates variable | |
|
321 | Variable variable{"var"}; | |
|
322 | QCOMPARE(variable.nbPoints(), 0); | |
|
323 | ||
|
324 | QFETCH(NbPointsOperations, operations); | |
|
325 | for (const auto &operation : operations) { | |
|
326 | // Sets cache range and merge data series | |
|
327 | variable.setCacheRange(operation.m_CacheRange); | |
|
328 | if (operation.m_DataSeries != nullptr) { | |
|
329 | variable.mergeDataSeries(operation.m_DataSeries); | |
|
330 | } | |
|
331 | ||
|
332 | // Checks nb points | |
|
333 | QCOMPARE(variable.nbPoints(), operation.m_ExpectedNbPoints); | |
|
334 | } | |
|
335 | } | |
|
336 | ||
|
337 | namespace { | |
|
338 | ||
|
339 | /// Struct used to represent a range operation on a variable | |
|
340 | /// @sa TestVariable::testRealRange() | |
|
341 | struct RangeOperation { | |
|
342 | SqpRange m_CacheRange; /// Range to set for the variable | |
|
343 | std::shared_ptr<ScalarSeries> m_DataSeries; /// Series to merge in the variable | |
|
344 | SqpRange m_ExpectedRealRange; /// Real Range expected after operation on the variable | |
|
345 | }; | |
|
346 | ||
|
347 | using RangeOperations = std::vector<RangeOperation>; | |
|
348 | ||
|
349 | } // namespace | |
|
350 | ||
|
351 | Q_DECLARE_METATYPE(RangeOperations) | |
|
352 | ||
|
353 | void TestVariable::testRealRange_data() | |
|
354 | { | |
|
355 | // ////////////// // | |
|
356 | // Test structure // | |
|
357 | // ////////////// // | |
|
358 | ||
|
359 | QTest::addColumn<RangeOperations>("operations"); | |
|
360 | ||
|
361 | // ////////// // | |
|
362 | // Test cases // | |
|
363 | // ////////// // | |
|
364 | RangeOperations operations{}; | |
|
365 | ||
|
366 | // Inits cache range and data series (expected real range = cache range) | |
|
367 | auto cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 13, 0, 0)}; | |
|
368 | operations.push_back({cacheRange, dataSeries(cacheRange), cacheRange}); | |
|
369 | ||
|
370 | // Changes cache range and updates data series (expected real range = cache range) | |
|
371 | cacheRange = SqpRange{date(2017, 1, 1, 14, 0, 0), date(2017, 1, 1, 15, 0, 0)}; | |
|
372 | operations.push_back({cacheRange, dataSeries(cacheRange), cacheRange}); | |
|
373 | ||
|
374 | // Changes cache range and update data series but with a lower range (expected real range = | |
|
375 | // data series range) | |
|
376 | cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 16, 0, 0)}; | |
|
377 | auto dataSeriesRange = SqpRange{date(2017, 1, 1, 14, 0, 0), date(2017, 1, 1, 15, 0, 0)}; | |
|
378 | operations.push_back({cacheRange, dataSeries(dataSeriesRange), dataSeriesRange}); | |
|
379 | ||
|
380 | // Changes cache range but DON'T update data series (expected real range = cache range | |
|
381 | // before operation) | |
|
382 | cacheRange = SqpRange{date(2017, 1, 1, 10, 0, 0), date(2017, 1, 1, 17, 0, 0)}; | |
|
383 | operations.push_back({cacheRange, nullptr, dataSeriesRange}); | |
|
384 | ||
|
385 | QTest::newRow("realRange1") << operations; | |
|
386 | } | |
|
387 | ||
|
388 | void TestVariable::testRealRange() | |
|
389 | { | |
|
390 | // Creates variable (real range is invalid) | |
|
391 | Variable variable{"var"}; | |
|
392 | QCOMPARE(variable.realRange(), INVALID_RANGE); | |
|
393 | ||
|
394 | QFETCH(RangeOperations, operations); | |
|
395 | for (const auto &operation : operations) { | |
|
396 | // Sets cache range and merge data series | |
|
397 | variable.setCacheRange(operation.m_CacheRange); | |
|
398 | if (operation.m_DataSeries != nullptr) { | |
|
399 | variable.mergeDataSeries(operation.m_DataSeries); | |
|
400 | } | |
|
401 | ||
|
402 | // Checks real range | |
|
403 | QCOMPARE(variable.realRange(), operation.m_ExpectedRealRange); | |
|
404 | } | |
|
405 | } | |
|
406 | ||
|
175 | 407 | |
|
176 | 408 | QTEST_MAIN(TestVariable) |
|
177 | 409 | #include "TestVariable.moc" |
General Comments 0
You need to be logged in to leave comments.
Login now