##// END OF EJS Templates
Updates unit tests
Alexandre Leroux -
r604:da7f81670868
parent child
Show More
@@ -1,522 +1,519
1 1 #include "Data/DataSeries.h"
2 2 #include "Data/ScalarSeries.h"
3 3 #include "Data/VectorSeries.h"
4 4
5 5 #include <cmath>
6 6
7 7 #include <QObject>
8 8 #include <QtTest>
9 9
10 10 Q_DECLARE_METATYPE(std::shared_ptr<ScalarSeries>)
11 11 Q_DECLARE_METATYPE(std::shared_ptr<VectorSeries>)
12 12
13 namespace {
14
15 void validateRange(DataSeriesIterator first, DataSeriesIterator last, const QVector<double> &xData,
16 const QVector<double> &valuesData)
17 {
18 QVERIFY(std::equal(first, last, xData.cbegin(), xData.cend(),
19 [](const auto &it, const auto &expectedX) { return it.x() == expectedX; }));
20 QVERIFY(std::equal(
21 first, last, valuesData.cbegin(), valuesData.cend(),
22 [](const auto &it, const auto &expectedVal) { return it.value() == expectedVal; }));
23 }
24
25 } // namespace
26
13 27 class TestDataSeries : public QObject {
14 28 Q_OBJECT
15 29 private:
16 30 template <typename T>
17 31 void testValuesBoundsStructure()
18 32 {
19 33 // ////////////// //
20 34 // Test structure //
21 35 // ////////////// //
22 36
23 37 // Data series to get values bounds
24 38 QTest::addColumn<std::shared_ptr<T> >("dataSeries");
25 39
26 40 // x-axis range
27 41 QTest::addColumn<double>("minXAxis");
28 42 QTest::addColumn<double>("maxXAxis");
29 43
30 44 // Expected results
31 45 QTest::addColumn<bool>(
32 46 "expectedOK"); // Test is expected to be ok (i.e. method doesn't return end iterators)
33 47 QTest::addColumn<double>("expectedMinValue");
34 48 QTest::addColumn<double>("expectedMaxValue");
35 49 }
36 50
37 51 template <typename T>
38 52 void testValuesBounds()
39 53 {
40 54 QFETCH(std::shared_ptr<T>, dataSeries);
41 55 QFETCH(double, minXAxis);
42 56 QFETCH(double, maxXAxis);
43 57
44 58 QFETCH(bool, expectedOK);
45 59 QFETCH(double, expectedMinValue);
46 60 QFETCH(double, expectedMaxValue);
47 61
48 62 auto minMaxIts = dataSeries->valuesBounds(minXAxis, maxXAxis);
49 63 auto end = dataSeries->cend();
50 64
51 65 // Checks iterators with expected result
52 66 QCOMPARE(expectedOK, minMaxIts.first != end && minMaxIts.second != end);
53 67
54 68 if (expectedOK) {
55 69 auto compare = [](const auto &v1, const auto &v2) {
56 70 return (std::isnan(v1) && std::isnan(v2)) || v1 == v2;
57 71 };
58 72
59 73 QVERIFY(compare(expectedMinValue, minMaxIts.first->minValue()));
60 74 QVERIFY(compare(expectedMaxValue, minMaxIts.second->maxValue()));
61 75 }
62 76 }
63 77
64 78 private slots:
65 79 /// Input test data
66 80 /// @sa testCtor()
67 81 void testCtor_data();
68 82
69 83 /// Tests construction of a data series
70 84 void testCtor();
71 85
72 86 /// Input test data
73 87 /// @sa testMerge()
74 88 void testMerge_data();
75 89
76 90 /// Tests merge of two data series
77 91 void testMerge();
78 92
79 93 /// Input test data
80 94 /// @sa testMinXAxisData()
81 95 void testMinXAxisData_data();
82 96
83 97 /// Tests get min x-axis data of a data series
84 98 void testMinXAxisData();
85 99
86 100 /// Input test data
87 101 /// @sa testMaxXAxisData()
88 102 void testMaxXAxisData_data();
89 103
90 104 /// Tests get max x-axis data of a data series
91 105 void testMaxXAxisData();
92 106
93 107 /// Input test data
94 108 /// @sa testXAxisRange()
95 109 void testXAxisRange_data();
96 110
97 111 /// Tests get x-axis range of a data series
98 112 void testXAxisRange();
99 113
100 114 /// Input test data
101 115 /// @sa testValuesBoundsScalar()
102 116 void testValuesBoundsScalar_data();
103 117
104 118 /// Tests get values bounds of a scalar series
105 119 void testValuesBoundsScalar();
106 120
107 121 /// Input test data
108 122 /// @sa testValuesBoundsVector()
109 123 void testValuesBoundsVector_data();
110 124
111 125 /// Tests get values bounds of a vector series
112 126 void testValuesBoundsVector();
113 127 };
114 128
115 129 void TestDataSeries::testCtor_data()
116 130 {
117 131 // ////////////// //
118 132 // Test structure //
119 133 // ////////////// //
120 134
121 135 // x-axis data
122 136 QTest::addColumn<QVector<double> >("xAxisData");
123 137 // values data
124 138 QTest::addColumn<QVector<double> >("valuesData");
125 139
126 140 // expected x-axis data
127 141 QTest::addColumn<QVector<double> >("expectedXAxisData");
128 142 // expected values data
129 143 QTest::addColumn<QVector<double> >("expectedValuesData");
130 144
131 145 // ////////// //
132 146 // Test cases //
133 147 // ////////// //
134 148
135 149 QTest::newRow("invalidData (different sizes of vectors)")
136 150 << QVector<double>{1., 2., 3., 4., 5.} << QVector<double>{100., 200., 300.}
137 151 << QVector<double>{} << QVector<double>{};
138 152
139 153 QTest::newRow("sortedData") << QVector<double>{1., 2., 3., 4., 5.}
140 154 << QVector<double>{100., 200., 300., 400., 500.}
141 155 << QVector<double>{1., 2., 3., 4., 5.}
142 156 << QVector<double>{100., 200., 300., 400., 500.};
143 157
144 158 QTest::newRow("unsortedData") << QVector<double>{5., 4., 3., 2., 1.}
145 159 << QVector<double>{100., 200., 300., 400., 500.}
146 160 << QVector<double>{1., 2., 3., 4., 5.}
147 161 << QVector<double>{500., 400., 300., 200., 100.};
148 162
149 163 QTest::newRow("unsortedData2")
150 164 << QVector<double>{1., 4., 3., 5., 2.} << QVector<double>{100., 200., 300., 400., 500.}
151 165 << QVector<double>{1., 2., 3., 4., 5.} << QVector<double>{100., 500., 300., 200., 400.};
152 166 }
153 167
154 168 void TestDataSeries::testCtor()
155 169 {
156 170 // Creates series
157 171 QFETCH(QVector<double>, xAxisData);
158 172 QFETCH(QVector<double>, valuesData);
159 173
160 174 auto series = std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
161 175 Unit{}, Unit{});
162 176
163 177 // Validates results : we check that the data series is sorted on its x-axis data
164 178 QFETCH(QVector<double>, expectedXAxisData);
165 179 QFETCH(QVector<double>, expectedValuesData);
166 180
167 auto seriesXAxisData = series->xAxisData()->data();
168 auto seriesValuesData = series->valuesData()->data();
169
170 QVERIFY(
171 std::equal(expectedXAxisData.cbegin(), expectedXAxisData.cend(), seriesXAxisData.cbegin()));
172 QVERIFY(std::equal(expectedValuesData.cbegin(), expectedValuesData.cend(),
173 seriesValuesData.cbegin()));
181 validateRange(series->cbegin(), series->cend(), expectedXAxisData, expectedValuesData);
174 182 }
175 183
176 184 namespace {
177 185
178 186 std::shared_ptr<ScalarSeries> createScalarSeries(QVector<double> xAxisData,
179 187 QVector<double> valuesData)
180 188 {
181 189 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData), Unit{},
182 190 Unit{});
183 191 }
184 192
185 193 std::shared_ptr<VectorSeries> createVectorSeries(QVector<double> xAxisData,
186 194 QVector<double> xValuesData,
187 195 QVector<double> yValuesData,
188 196 QVector<double> zValuesData)
189 197 {
190 198 return std::make_shared<VectorSeries>(std::move(xAxisData), std::move(xValuesData),
191 199 std::move(yValuesData), std::move(zValuesData), Unit{},
192 200 Unit{});
193 201 }
194 202
195 203 } // namespace
196 204
197 205 void TestDataSeries::testMerge_data()
198 206 {
199 207 // ////////////// //
200 208 // Test structure //
201 209 // ////////////// //
202 210
203 211 // Data series to merge
204 212 QTest::addColumn<std::shared_ptr<ScalarSeries> >("dataSeries");
205 213 QTest::addColumn<std::shared_ptr<ScalarSeries> >("dataSeries2");
206 214
207 215 // Expected values in the first data series after merge
208 216 QTest::addColumn<QVector<double> >("expectedXAxisData");
209 217 QTest::addColumn<QVector<double> >("expectedValuesData");
210 218
211 219 // ////////// //
212 220 // Test cases //
213 221 // ////////// //
214 222
215 223 QTest::newRow("sortedMerge")
216 224 << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.})
217 225 << createScalarSeries({6., 7., 8., 9., 10.}, {600., 700., 800., 900., 1000.})
218 226 << QVector<double>{1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}
219 227 << QVector<double>{100., 200., 300., 400., 500., 600., 700., 800., 900., 1000.};
220 228
221 229 QTest::newRow("unsortedMerge")
222 230 << createScalarSeries({6., 7., 8., 9., 10.}, {600., 700., 800., 900., 1000.})
223 231 << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.})
224 232 << QVector<double>{1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}
225 233 << QVector<double>{100., 200., 300., 400., 500., 600., 700., 800., 900., 1000.};
226 234
227 235 QTest::newRow("unsortedMerge2")
228 236 << createScalarSeries({1., 2., 8., 9., 10}, {100., 200., 300., 400., 500.})
229 237 << createScalarSeries({3., 4., 5., 6., 7.}, {600., 700., 800., 900., 1000.})
230 238 << QVector<double>{1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}
231 239 << QVector<double>{100., 200., 600., 700., 800., 900., 1000., 300., 400., 500.};
232 240
233 241 QTest::newRow("unsortedMerge3")
234 242 << createScalarSeries({3., 5., 8., 7., 2}, {100., 200., 300., 400., 500.})
235 243 << createScalarSeries({6., 4., 9., 10., 1.}, {600., 700., 800., 900., 1000.})
236 244 << QVector<double>{1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}
237 245 << QVector<double>{1000., 500., 100., 700., 200., 600., 400., 300., 800., 900.};
238 246 }
239 247
240 248 void TestDataSeries::testMerge()
241 249 {
242 250 // Merges series
243 251 QFETCH(std::shared_ptr<ScalarSeries>, dataSeries);
244 252 QFETCH(std::shared_ptr<ScalarSeries>, dataSeries2);
245 253
246 254 dataSeries->merge(dataSeries2.get());
247 255
248 256 // Validates results : we check that the merge is valid and the data series is sorted on its
249 257 // x-axis data
250 258 QFETCH(QVector<double>, expectedXAxisData);
251 259 QFETCH(QVector<double>, expectedValuesData);
252 260
253 auto seriesXAxisData = dataSeries->xAxisData()->data();
254 auto seriesValuesData = dataSeries->valuesData()->data();
255
256 QVERIFY(
257 std::equal(expectedXAxisData.cbegin(), expectedXAxisData.cend(), seriesXAxisData.cbegin()));
258 QVERIFY(std::equal(expectedValuesData.cbegin(), expectedValuesData.cend(),
259 seriesValuesData.cbegin()));
261 validateRange(dataSeries->cbegin(), dataSeries->cend(), expectedXAxisData, expectedValuesData);
260 262 }
261 263
262 264 void TestDataSeries::testMinXAxisData_data()
263 265 {
264 266 // ////////////// //
265 267 // Test structure //
266 268 // ////////////// //
267 269
268 270 // Data series to get min data
269 271 QTest::addColumn<std::shared_ptr<ScalarSeries> >("dataSeries");
270 272
271 273 // Min data
272 274 QTest::addColumn<double>("min");
273 275
274 276 // Expected results
275 277 QTest::addColumn<bool>(
276 278 "expectedOK"); // if true, expects to have a result (i.e. the iterator != end iterator)
277 279 QTest::addColumn<double>(
278 280 "expectedMin"); // Expected value when method doesn't return end iterator
279 281
280 282 // ////////// //
281 283 // Test cases //
282 284 // ////////// //
283 285
284 286 QTest::newRow("minData1") << createScalarSeries({1., 2., 3., 4., 5.},
285 287 {100., 200., 300., 400., 500.})
286 288 << 0. << true << 1.;
287 289 QTest::newRow("minData2") << createScalarSeries({1., 2., 3., 4., 5.},
288 290 {100., 200., 300., 400., 500.})
289 291 << 1. << true << 1.;
290 292 QTest::newRow("minData3") << createScalarSeries({1., 2., 3., 4., 5.},
291 293 {100., 200., 300., 400., 500.})
292 294 << 1.1 << true << 2.;
293 295 QTest::newRow("minData4") << createScalarSeries({1., 2., 3., 4., 5.},
294 296 {100., 200., 300., 400., 500.})
295 297 << 5. << true << 5.;
296 298 QTest::newRow("minData5") << createScalarSeries({1., 2., 3., 4., 5.},
297 299 {100., 200., 300., 400., 500.})
298 300 << 5.1 << false << std::numeric_limits<double>::quiet_NaN();
299 301 QTest::newRow("minData6") << createScalarSeries({}, {}) << 1.1 << false
300 302 << std::numeric_limits<double>::quiet_NaN();
301 303 }
302 304
303 305 void TestDataSeries::testMinXAxisData()
304 306 {
305 307 QFETCH(std::shared_ptr<ScalarSeries>, dataSeries);
306 308 QFETCH(double, min);
307 309
308 310 QFETCH(bool, expectedOK);
309 311 QFETCH(double, expectedMin);
310 312
311 313 auto it = dataSeries->minXAxisData(min);
312 314
313 315 QCOMPARE(expectedOK, it != dataSeries->cend());
314 316
315 317 // If the method doesn't return a end iterator, checks with expected value
316 318 if (expectedOK) {
317 319 QCOMPARE(expectedMin, it->x());
318 320 }
319 321 }
320 322
321 323 void TestDataSeries::testMaxXAxisData_data()
322 324 {
323 325 // ////////////// //
324 326 // Test structure //
325 327 // ////////////// //
326 328
327 329 // Data series to get max data
328 330 QTest::addColumn<std::shared_ptr<ScalarSeries> >("dataSeries");
329 331
330 332 // Max data
331 333 QTest::addColumn<double>("max");
332 334
333 335 // Expected results
334 336 QTest::addColumn<bool>(
335 337 "expectedOK"); // if true, expects to have a result (i.e. the iterator != end iterator)
336 338 QTest::addColumn<double>(
337 339 "expectedMax"); // Expected value when method doesn't return end iterator
338 340
339 341 // ////////// //
340 342 // Test cases //
341 343 // ////////// //
342 344
343 345 QTest::newRow("maxData1") << createScalarSeries({1., 2., 3., 4., 5.},
344 346 {100., 200., 300., 400., 500.})
345 347 << 6. << true << 5.;
346 348 QTest::newRow("maxData2") << createScalarSeries({1., 2., 3., 4., 5.},
347 349 {100., 200., 300., 400., 500.})
348 350 << 5. << true << 5.;
349 351 QTest::newRow("maxData3") << createScalarSeries({1., 2., 3., 4., 5.},
350 352 {100., 200., 300., 400., 500.})
351 353 << 4.9 << true << 4.;
352 354 QTest::newRow("maxData4") << createScalarSeries({1., 2., 3., 4., 5.},
353 355 {100., 200., 300., 400., 500.})
354 356 << 1.1 << true << 1.;
355 357 QTest::newRow("maxData5") << createScalarSeries({1., 2., 3., 4., 5.},
356 358 {100., 200., 300., 400., 500.})
357 359 << 1. << true << 1.;
358 360 QTest::newRow("maxData6") << createScalarSeries({}, {}) << 1.1 << false
359 361 << std::numeric_limits<double>::quiet_NaN();
360 362 }
361 363
362 364 void TestDataSeries::testMaxXAxisData()
363 365 {
364 366 QFETCH(std::shared_ptr<ScalarSeries>, dataSeries);
365 367 QFETCH(double, max);
366 368
367 369 QFETCH(bool, expectedOK);
368 370 QFETCH(double, expectedMax);
369 371
370 372 auto it = dataSeries->maxXAxisData(max);
371 373
372 374 QCOMPARE(expectedOK, it != dataSeries->cend());
373 375
374 376 // If the method doesn't return a end iterator, checks with expected value
375 377 if (expectedOK) {
376 378 QCOMPARE(expectedMax, it->x());
377 379 }
378 380 }
379 381
380 382 void TestDataSeries::testXAxisRange_data()
381 383 {
382 384 // ////////////// //
383 385 // Test structure //
384 386 // ////////////// //
385 387
386 388 // Data series to get x-axis range
387 389 QTest::addColumn<std::shared_ptr<ScalarSeries> >("dataSeries");
388 390
389 391 // Min/max values
390 392 QTest::addColumn<double>("min");
391 393 QTest::addColumn<double>("max");
392 394
393 395 // Expected values
394 396 QTest::addColumn<QVector<double> >("expectedXAxisData");
395 397 QTest::addColumn<QVector<double> >("expectedValuesData");
396 398
397 399 // ////////// //
398 400 // Test cases //
399 401 // ////////// //
400 402
401 403 QTest::newRow("xAxisRange1") << createScalarSeries({1., 2., 3., 4., 5.},
402 404 {100., 200., 300., 400., 500.})
403 405 << -1. << 3.2 << QVector<double>{1., 2., 3.}
404 406 << QVector<double>{100., 200., 300.};
405 407 QTest::newRow("xAxisRange2") << createScalarSeries({1., 2., 3., 4., 5.},
406 408 {100., 200., 300., 400., 500.})
407 409 << 1. << 4. << QVector<double>{1., 2., 3., 4.}
408 410 << QVector<double>{100., 200., 300., 400.};
409 411 QTest::newRow("xAxisRange3") << createScalarSeries({1., 2., 3., 4., 5.},
410 412 {100., 200., 300., 400., 500.})
411 413 << 1. << 3.9 << QVector<double>{1., 2., 3.}
412 414 << QVector<double>{100., 200., 300.};
413 415 QTest::newRow("xAxisRange4") << createScalarSeries({1., 2., 3., 4., 5.},
414 416 {100., 200., 300., 400., 500.})
415 417 << 0. << 0.9 << QVector<double>{} << QVector<double>{};
416 418 QTest::newRow("xAxisRange5") << createScalarSeries({1., 2., 3., 4., 5.},
417 419 {100., 200., 300., 400., 500.})
418 420 << 0. << 1. << QVector<double>{1.} << QVector<double>{100.};
419 421 QTest::newRow("xAxisRange6") << createScalarSeries({1., 2., 3., 4., 5.},
420 422 {100., 200., 300., 400., 500.})
421 423 << 2.1 << 6. << QVector<double>{3., 4., 5.}
422 424 << QVector<double>{300., 400., 500.};
423 425 QTest::newRow("xAxisRange7") << createScalarSeries({1., 2., 3., 4., 5.},
424 426 {100., 200., 300., 400., 500.})
425 427 << 6. << 9. << QVector<double>{} << QVector<double>{};
426 428 QTest::newRow("xAxisRange8") << createScalarSeries({1., 2., 3., 4., 5.},
427 429 {100., 200., 300., 400., 500.})
428 430 << 5. << 9. << QVector<double>{5.} << QVector<double>{500.};
429 431 }
430 432
431 433 void TestDataSeries::testXAxisRange()
432 434 {
433 435 QFETCH(std::shared_ptr<ScalarSeries>, dataSeries);
434 436 QFETCH(double, min);
435 437 QFETCH(double, max);
436 438
437 439 QFETCH(QVector<double>, expectedXAxisData);
438 440 QFETCH(QVector<double>, expectedValuesData);
439 441
440 442 auto bounds = dataSeries->xAxisRange(min, max);
441 QVERIFY(std::equal(bounds.first, bounds.second, expectedXAxisData.cbegin(),
442 expectedXAxisData.cend(),
443 [](const auto &it, const auto &expectedX) { return it.x() == expectedX; }));
444 QVERIFY(std::equal(
445 bounds.first, bounds.second, expectedValuesData.cbegin(), expectedValuesData.cend(),
446 [](const auto &it, const auto &expectedVal) { return it.value() == expectedVal; }));
443 validateRange(bounds.first, bounds.second, expectedXAxisData, expectedValuesData);
447 444 }
448 445
449 446 void TestDataSeries::testValuesBoundsScalar_data()
450 447 {
451 448 testValuesBoundsStructure<ScalarSeries>();
452 449
453 450 // ////////// //
454 451 // Test cases //
455 452 // ////////// //
456 453 auto nan = std::numeric_limits<double>::quiet_NaN();
457 454
458 455 QTest::newRow("scalarBounds1")
459 456 << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) << 0. << 6.
460 457 << true << 100. << 500.;
461 458 QTest::newRow("scalarBounds2")
462 459 << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) << 2. << 4.
463 460 << true << 200. << 400.;
464 461 QTest::newRow("scalarBounds3")
465 462 << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) << 0. << 0.5
466 463 << false << nan << nan;
467 464 QTest::newRow("scalarBounds4")
468 465 << createScalarSeries({1., 2., 3., 4., 5.}, {100., 200., 300., 400., 500.}) << 5.1 << 6.
469 466 << false << nan << nan;
470 467 QTest::newRow("scalarBounds5") << createScalarSeries({1.}, {100.}) << 0. << 2. << true << 100.
471 468 << 100.;
472 469 QTest::newRow("scalarBounds6") << createScalarSeries({}, {}) << 0. << 2. << false << nan << nan;
473 470
474 471 // Tests with NaN values: NaN values are not included in min/max search
475 472 QTest::newRow("scalarBounds7")
476 473 << createScalarSeries({1., 2., 3., 4., 5.}, {nan, 200., 300., 400., nan}) << 0. << 6.
477 474 << true << 200. << 400.;
478 475 QTest::newRow("scalarBounds8")
479 476 << createScalarSeries({1., 2., 3., 4., 5.}, {nan, nan, nan, nan, nan}) << 0. << 6. << true
480 477 << std::numeric_limits<double>::quiet_NaN() << std::numeric_limits<double>::quiet_NaN();
481 478 }
482 479
483 480 void TestDataSeries::testValuesBoundsScalar()
484 481 {
485 482 testValuesBounds<ScalarSeries>();
486 483 }
487 484
488 485 void TestDataSeries::testValuesBoundsVector_data()
489 486 {
490 487 testValuesBoundsStructure<VectorSeries>();
491 488
492 489 // ////////// //
493 490 // Test cases //
494 491 // ////////// //
495 492 auto nan = std::numeric_limits<double>::quiet_NaN();
496 493
497 494 QTest::newRow("vectorBounds1")
498 495 << createVectorSeries({1., 2., 3., 4., 5.}, {10., 15., 20., 13., 12.},
499 496 {35., 24., 10., 9., 0.3}, {13., 14., 12., 9., 24.})
500 497 << 0. << 6. << true << 0.3 << 35.; // min/max in same component
501 498 QTest::newRow("vectorBounds2")
502 499 << createVectorSeries({1., 2., 3., 4., 5.}, {2.3, 15., 20., 13., 12.},
503 500 {35., 24., 10., 9., 4.}, {13., 14., 12., 9., 24.})
504 501 << 0. << 6. << true << 2.3 << 35.; // min/max in same entry
505 502 QTest::newRow("vectorBounds3")
506 503 << createVectorSeries({1., 2., 3., 4., 5.}, {2.3, 15., 20., 13., 12.},
507 504 {35., 24., 10., 9., 4.}, {13., 14., 12., 9., 24.})
508 505 << 2. << 3. << true << 10. << 24.;
509 506
510 507 // Tests with NaN values: NaN values are not included in min/max search
511 508 QTest::newRow("vectorBounds4")
512 509 << createVectorSeries({1., 2.}, {nan, nan}, {nan, nan}, {nan, nan}) << 0. << 6. << true
513 510 << nan << nan;
514 511 }
515 512
516 513 void TestDataSeries::testValuesBoundsVector()
517 514 {
518 515 testValuesBounds<VectorSeries>();
519 516 }
520 517
521 518 QTEST_MAIN(TestDataSeries)
522 519 #include "TestDataSeries.moc"
@@ -1,199 +1,181
1 1 #include "Data/ArrayData.h"
2 2 #include <QObject>
3 3 #include <QtTest>
4 4
5 namespace {
6
7 void verifyArrayData(const ArrayData<1> &arrayData, const QVector<double> &expectedData)
8 {
9 QVERIFY(std::equal(
10 arrayData.cbegin(), arrayData.cend(), expectedData.cbegin(), expectedData.cend(),
11 [](const auto &it, const auto &expectedData) { return it.at(0) == expectedData; }));
12 }
13
14 } // namespace
15
5 16 class TestOneDimArrayData : public QObject {
6 17 Q_OBJECT
7 18 private slots:
8 19 /// Tests @sa ArrayData::data()
9 20 void testData_data();
10 21 void testData();
11 22
12 /// Tests @sa ArrayData::data(int componentIndex)
13 void testDataByComponentIndex_data();
14 void testDataByComponentIndex();
15
16 23 /// Tests @sa ArrayData::add()
17 24 void testAdd_data();
18 25 void testAdd();
19 26
20 27 /// Tests @sa ArrayData::at(int index)
21 28 void testAt_data();
22 29 void testAt();
23 30
24 31 /// Tests @sa ArrayData::clear()
25 32 void testClear_data();
26 33 void testClear();
27 34
28 35 /// Tests @sa ArrayData::size()
29 36 void testSize_data();
30 37 void testSize();
31 38
32 39 /// Tests @sa ArrayData::sort()
33 40 void testSort_data();
34 41 void testSort();
35 42 };
36 43
37 44 void TestOneDimArrayData::testData_data()
38 45 {
39 46 // Test structure
40 47 QTest::addColumn<QVector<double> >("inputData"); // array's data input
41 48 QTest::addColumn<QVector<double> >("expectedData"); // expected data
42 49
43 50 // Test cases
44 51 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.}
45 52 << QVector<double>{1., 2., 3., 4., 5.};
46 53 }
47 54
48 55 void TestOneDimArrayData::testData()
49 56 {
50 57 QFETCH(QVector<double>, inputData);
51 58 QFETCH(QVector<double>, expectedData);
52 59
53 60 ArrayData<1> arrayData{inputData};
54 QVERIFY(arrayData.data() == expectedData);
55 }
56
57 void TestOneDimArrayData::testDataByComponentIndex_data()
58 {
59 // Test structure
60 QTest::addColumn<QVector<double> >("inputData"); // array data's input
61 QTest::addColumn<int>("componentIndex"); // component index to test
62 QTest::addColumn<QVector<double> >("expectedData"); // expected data
63
64 // Test cases
65 QTest::newRow("validIndex") << QVector<double>{1., 2., 3., 4., 5.} << 0
66 << QVector<double>{1., 2., 3., 4., 5.};
67 QTest::newRow("invalidIndex1") << QVector<double>{1., 2., 3., 4., 5.} << -1
68 << QVector<double>{};
69 QTest::newRow("invalidIndex2") << QVector<double>{1., 2., 3., 4., 5.} << 1 << QVector<double>{};
70 }
71
72 void TestOneDimArrayData::testDataByComponentIndex()
73 {
74 QFETCH(QVector<double>, inputData);
75 QFETCH(int, componentIndex);
76 QFETCH(QVector<double>, expectedData);
77
78 ArrayData<1> arrayData{inputData};
79 QVERIFY(arrayData.data(componentIndex) == expectedData);
61 verifyArrayData(arrayData, expectedData);
80 62 }
81 63
82 64 void TestOneDimArrayData::testAdd_data()
83 65 {
84 66 // Test structure
85 67 QTest::addColumn<QVector<double> >("inputData"); // array's data input
86 68 QTest::addColumn<QVector<double> >("otherData"); // array data's input to merge with
87 69 QTest::addColumn<bool>("prepend"); // prepend or append merge
88 70 QTest::addColumn<QVector<double> >("expectedData"); // expected data after merge
89 71
90 72 // Test cases
91 73 QTest::newRow("appendMerge") << QVector<double>{1., 2., 3., 4., 5.}
92 74 << QVector<double>{6., 7., 8.} << false
93 75 << QVector<double>{1., 2., 3., 4., 5., 6., 7., 8.};
94 76 QTest::newRow("prependMerge") << QVector<double>{1., 2., 3., 4., 5.}
95 77 << QVector<double>{6., 7., 8.} << true
96 78 << QVector<double>{6., 7., 8., 1., 2., 3., 4., 5.};
97 79 }
98 80
99 81 void TestOneDimArrayData::testAdd()
100 82 {
101 83 QFETCH(QVector<double>, inputData);
102 84 QFETCH(QVector<double>, otherData);
103 85 QFETCH(bool, prepend);
104 86 QFETCH(QVector<double>, expectedData);
105 87
106 88 ArrayData<1> arrayData{inputData};
107 89 ArrayData<1> other{otherData};
108 90
109 91 arrayData.add(other, prepend);
110 QVERIFY(arrayData.data() == expectedData);
92 verifyArrayData(arrayData, expectedData);
111 93 }
112 94
113 95 void TestOneDimArrayData::testAt_data()
114 96 {
115 97 // Test structure
116 98 QTest::addColumn<QVector<double> >("inputData"); // array data's input
117 99 QTest::addColumn<int>("index"); // index to retrieve data
118 100 QTest::addColumn<double>("expectedData"); // expected data at index
119 101
120 102 // Test cases
121 103 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.} << 0 << 1.;
122 104 QTest::newRow("data2") << QVector<double>{1., 2., 3., 4., 5.} << 3 << 4.;
123 105 }
124 106
125 107 void TestOneDimArrayData::testAt()
126 108 {
127 109 QFETCH(QVector<double>, inputData);
128 110 QFETCH(int, index);
129 111 QFETCH(double, expectedData);
130 112
131 113 ArrayData<1> arrayData{inputData};
132 114 QVERIFY(arrayData.at(index) == expectedData);
133 115 }
134 116
135 117 void TestOneDimArrayData::testClear_data()
136 118 {
137 119 // Test structure
138 120 QTest::addColumn<QVector<double> >("inputData"); // array data's input
139 121
140 122 // Test cases
141 123 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.};
142 124 }
143 125
144 126 void TestOneDimArrayData::testClear()
145 127 {
146 128 QFETCH(QVector<double>, inputData);
147 129
148 130 ArrayData<1> arrayData{inputData};
149 131 arrayData.clear();
150 QVERIFY(arrayData.data() == QVector<double>{});
132 verifyArrayData(arrayData, QVector<double>{});
151 133 }
152 134
153 135 void TestOneDimArrayData::testSize_data()
154 136 {
155 137 // Test structure
156 138 QTest::addColumn<QVector<double> >("inputData"); // array data's input
157 139 QTest::addColumn<int>("expectedSize"); // expected array data size
158 140
159 141 // Test cases
160 142 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.} << 5;
161 143 }
162 144
163 145 void TestOneDimArrayData::testSize()
164 146 {
165 147 QFETCH(QVector<double>, inputData);
166 148 QFETCH(int, expectedSize);
167 149
168 150 ArrayData<1> arrayData{inputData};
169 151 QVERIFY(arrayData.size() == expectedSize);
170 152 }
171 153
172 154 void TestOneDimArrayData::testSort_data()
173 155 {
174 156 // Test structure
175 157 QTest::addColumn<QVector<double> >("inputData"); // array data's input
176 158 QTest::addColumn<std::vector<int> >("sortPermutation"); // permutation used to sort data
177 159 QTest::addColumn<QVector<double> >("expectedData"); // expected data after sorting
178 160
179 161 // Test cases
180 162 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.} << std::vector<int>{0, 2, 3, 1, 4}
181 163 << QVector<double>{1., 3., 4., 2., 5.};
182 164 QTest::newRow("data2") << QVector<double>{1., 2., 3., 4., 5.} << std::vector<int>{4, 1, 2, 3, 0}
183 165 << QVector<double>{5., 2., 3., 4., 1.};
184 166 }
185 167
186 168 void TestOneDimArrayData::testSort()
187 169 {
188 170 QFETCH(QVector<double>, inputData);
189 171 QFETCH(std::vector<int>, sortPermutation);
190 172 QFETCH(QVector<double>, expectedData);
191 173
192 174 ArrayData<1> arrayData{inputData};
193 175 auto sortedArrayData = arrayData.sort(sortPermutation);
194 176 QVERIFY(sortedArrayData != nullptr);
195 QVERIFY(sortedArrayData->data() == expectedData);
177 verifyArrayData(*sortedArrayData, expectedData);
196 178 }
197 179
198 180 QTEST_MAIN(TestOneDimArrayData)
199 181 #include "TestOneDimArrayData.moc"
@@ -1,224 +1,239
1 1 #include "Data/ArrayData.h"
2 2 #include <QObject>
3 3 #include <QtTest>
4 4
5 using DataContainer = QVector<QVector<double> >;
5 using Container = QVector<QVector<double> >;
6 using InputData = QPair<QVector<double>, int>;
7
8 namespace {
9
10 InputData flatten(const Container &container)
11 {
12 if (container.isEmpty()) {
13 return {};
14 }
15
16 // We assume here that each component of the container have the same size
17 auto containerSize = container.size();
18 auto componentSize = container.first().size();
19
20 auto result = QVector<double>{};
21 result.reserve(componentSize * containerSize);
22
23 for (auto i = 0; i < componentSize; ++i) {
24 for (auto j = 0; j < containerSize; ++j) {
25 result.append(container.at(j).at(i));
26 }
27 }
28
29 return {result, containerSize};
30 }
31
32 void verifyArrayData(const ArrayData<2> &arrayData, const Container &expectedData)
33 {
34 auto verifyComponent = [&arrayData](const auto &componentData, const auto &equalFun) {
35 QVERIFY(std::equal(arrayData.cbegin(), arrayData.cend(), componentData.cbegin(),
36 componentData.cend(),
37 [&equalFun](const auto &dataSeriesIt, const auto &expectedValue) {
38 return equalFun(dataSeriesIt, expectedValue);
39 }));
40 };
41
42 for (auto i = 0; i < expectedData.size(); ++i) {
43 verifyComponent(expectedData.at(i), [i](const auto &seriesIt, const auto &value) {
44 return seriesIt.at(i) == value;
45 });
46 }
47 }
48
49 } // namespace
6 50
7 51 class TestTwoDimArrayData : public QObject {
8 52 Q_OBJECT
9 53 private slots:
10 /// Tests @sa ArrayData::data(int componentIndex)
11 void testDataByComponentIndex_data();
12 void testDataByComponentIndex();
13
14 54 /// Tests @sa ArrayData ctor
15 55 void testCtor_data();
16 56 void testCtor();
17 57
18 58 /// Tests @sa ArrayData::add()
19 59 void testAdd_data();
20 60 void testAdd();
21 61
22 62 /// Tests @sa ArrayData::clear()
23 63 void testClear_data();
24 64 void testClear();
25 65
26 66 /// Tests @sa ArrayData::size()
27 67 void testSize_data();
28 68 void testSize();
29 69
30 70 /// Tests @sa ArrayData::sort()
31 71 void testSort_data();
32 72 void testSort();
33 73 };
34 74
35 void TestTwoDimArrayData::testDataByComponentIndex_data()
36 {
37 // Test structure
38 QTest::addColumn<DataContainer>("inputData"); // array data's input
39 QTest::addColumn<int>("componentIndex"); // component index to test
40 QTest::addColumn<QVector<double> >("expectedData"); // expected data
41
42 // Test cases
43 auto inputData
44 = DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}};
45
46 QTest::newRow("validIndex1") << inputData << 0 << QVector<double>{1., 2., 3., 4., 5.};
47 QTest::newRow("validIndex2") << inputData << 1 << QVector<double>{6., 7., 8., 9., 10.};
48 QTest::newRow("validIndex3") << inputData << 2 << QVector<double>{11., 12., 13., 14., 15.};
49 QTest::newRow("invalidIndex1") << inputData << -1 << QVector<double>{};
50 QTest::newRow("invalidIndex2") << inputData << 3 << QVector<double>{};
51 }
52
53 void TestTwoDimArrayData::testDataByComponentIndex()
54 {
55 QFETCH(DataContainer, inputData);
56 QFETCH(int, componentIndex);
57 QFETCH(QVector<double>, expectedData);
58
59 ArrayData<2> arrayData{inputData};
60 QVERIFY(arrayData.data(componentIndex) == expectedData);
61 }
62
63 75 void TestTwoDimArrayData::testCtor_data()
64 76 {
65 77 // Test structure
66 QTest::addColumn<DataContainer>("inputData"); // array data's input
67 QTest::addColumn<bool>("success"); // array data has been successfully constructed
68 QTest::addColumn<DataContainer>("expectedData"); // expected array data (when success)
78 QTest::addColumn<InputData>("inputData"); // array data's input
79 QTest::addColumn<bool>("success"); // array data has been successfully constructed
80 QTest::addColumn<Container>("expectedData"); // expected array data (when success)
69 81
70 82 // Test cases
71 QTest::newRow("validInput")
72 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}
73 << true
74 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}};
75 QTest::newRow("malformedInput (components of the array data haven't the same size")
76 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8.}, {11., 12.}} << true
77 << DataContainer{{}, {}, {}};
78 QTest::newRow("invalidInput (less than tow components") << DataContainer{{1., 2., 3., 4., 5.}}
79 << false << DataContainer{{}, {}, {}};
83 QTest::newRow("validInput") << flatten(Container{{1., 2., 3., 4., 5.},
84 {6., 7., 8., 9., 10.},
85 {11., 12., 13., 14., 15.}})
86 << true << Container{{1., 2., 3., 4., 5.},
87 {6., 7., 8., 9., 10.},
88 {11., 12., 13., 14., 15.}};
89 QTest::newRow("invalidInput (invalid data size")
90 << InputData{{1., 2., 3., 4., 5., 6., 7.}, 3} << false << Container{{}, {}, {}};
91 QTest::newRow("invalidInput (less than two components")
92 << flatten(Container{{1., 2., 3., 4., 5.}}) << false << Container{{}, {}, {}};
80 93 }
81 94
82 95 void TestTwoDimArrayData::testCtor()
83 96 {
84 QFETCH(DataContainer, inputData);
97 QFETCH(InputData, inputData);
85 98 QFETCH(bool, success);
86 99
87 100 if (success) {
88 QFETCH(DataContainer, expectedData);
89
90 ArrayData<2> arrayData{inputData};
101 QFETCH(Container, expectedData);
91 102
92 for (auto i = 0; i < expectedData.size(); ++i) {
93 QVERIFY(arrayData.data(i) == expectedData.at(i));
94 }
103 ArrayData<2> arrayData{inputData.first, inputData.second};
104 verifyArrayData(arrayData, expectedData);
95 105 }
96 106 else {
97 QVERIFY_EXCEPTION_THROWN(ArrayData<2> arrayData{inputData}, std::invalid_argument);
107 QVERIFY_EXCEPTION_THROWN(ArrayData<2>(inputData.first, inputData.second),
108 std::invalid_argument);
98 109 }
99 110 }
100 111
101 112 void TestTwoDimArrayData::testAdd_data()
102 113 {
103 114 // Test structure
104 QTest::addColumn<DataContainer>("inputData"); // array's data input
105 QTest::addColumn<DataContainer>("otherData"); // array data's input to merge with
106 QTest::addColumn<bool>("prepend"); // prepend or append merge
107 QTest::addColumn<DataContainer>("expectedData"); // expected data after merge
115 QTest::addColumn<InputData>("inputData"); // array's data input
116 QTest::addColumn<InputData>("otherData"); // array data's input to merge with
117 QTest::addColumn<bool>("prepend"); // prepend or append merge
118 QTest::addColumn<Container>("expectedData"); // expected data after merge
108 119
109 120 // Test cases
110 auto inputData
111 = DataContainer{{1., 2., 3., 4., 5.}, {11., 12., 13., 14., 15.}, {21., 22., 23., 24., 25.}};
121 auto inputData = flatten(
122 Container{{1., 2., 3., 4., 5.}, {11., 12., 13., 14., 15.}, {21., 22., 23., 24., 25.}});
112 123
113 auto vectorContainer = DataContainer{{6., 7., 8.}, {16., 17., 18.}, {26., 27., 28}};
114 auto tensorContainer = DataContainer{{6., 7., 8.}, {16., 17., 18.}, {26., 27., 28},
115 {36., 37., 38.}, {46., 47., 48.}, {56., 57., 58}};
124 auto vectorContainer = flatten(Container{{6., 7., 8.}, {16., 17., 18.}, {26., 27., 28}});
125 auto tensorContainer = flatten(Container{{6., 7., 8.},
126 {16., 17., 18.},
127 {26., 27., 28},
128 {36., 37., 38.},
129 {46., 47., 48.},
130 {56., 57., 58}});
116 131
117 132 QTest::newRow("appendMerge") << inputData << vectorContainer << false
118 << DataContainer{{1., 2., 3., 4., 5., 6., 7., 8.},
119 {11., 12., 13., 14., 15., 16., 17., 18.},
120 {21., 22., 23., 24., 25., 26., 27., 28}};
133 << Container{{1., 2., 3., 4., 5., 6., 7., 8.},
134 {11., 12., 13., 14., 15., 16., 17., 18.},
135 {21., 22., 23., 24., 25., 26., 27., 28}};
121 136 QTest::newRow("prependMerge") << inputData << vectorContainer << true
122 << DataContainer{{6., 7., 8., 1., 2., 3., 4., 5.},
123 {16., 17., 18., 11., 12., 13., 14., 15.},
124 {26., 27., 28, 21., 22., 23., 24., 25.}};
125 QTest::newRow("invalidMerge") << inputData << tensorContainer << false << inputData;
137 << Container{{6., 7., 8., 1., 2., 3., 4., 5.},
138 {16., 17., 18., 11., 12., 13., 14., 15.},
139 {26., 27., 28, 21., 22., 23., 24., 25.}};
140 QTest::newRow("invalidMerge") << inputData << tensorContainer << false
141 << Container{{1., 2., 3., 4., 5.},
142 {11., 12., 13., 14., 15.},
143 {21., 22., 23., 24., 25.}};
126 144 }
127 145
128 146 void TestTwoDimArrayData::testAdd()
129 147 {
130 QFETCH(DataContainer, inputData);
131 QFETCH(DataContainer, otherData);
148 QFETCH(InputData, inputData);
149 QFETCH(InputData, otherData);
132 150 QFETCH(bool, prepend);
133 QFETCH(DataContainer, expectedData);
151 QFETCH(Container, expectedData);
134 152
135 ArrayData<2> arrayData{inputData};
136 ArrayData<2> other{otherData};
153 ArrayData<2> arrayData{inputData.first, inputData.second};
154 ArrayData<2> other{otherData.first, otherData.second};
137 155
138 156 arrayData.add(other, prepend);
139 157
140 for (auto i = 0; i < expectedData.size(); ++i) {
141 QVERIFY(arrayData.data(i) == expectedData.at(i));
142 }
158 verifyArrayData(arrayData, expectedData);
143 159 }
144 160
145 161 void TestTwoDimArrayData::testClear_data()
146 162 {
147 163 // Test structure
148 QTest::addColumn<DataContainer>("inputData"); // array data's input
164 QTest::addColumn<InputData>("inputData"); // array data's input
149 165
150 166 // Test cases
151 QTest::newRow("data1") << DataContainer{
152 {1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}};
167 QTest::newRow("data1") << flatten(
168 Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}});
153 169 }
154 170
155 171 void TestTwoDimArrayData::testClear()
156 172 {
157 QFETCH(DataContainer, inputData);
173 QFETCH(InputData, inputData);
158 174
159 ArrayData<2> arrayData{inputData};
175 ArrayData<2> arrayData{inputData.first, inputData.second};
160 176 arrayData.clear();
161 177
162 for (auto i = 0; i < inputData.size(); ++i) {
163 QVERIFY(arrayData.data(i) == QVector<double>{});
164 }
178 auto emptyData = Container(inputData.second, QVector<double>{});
179 verifyArrayData(arrayData, emptyData);
165 180 }
166 181
167 182 void TestTwoDimArrayData::testSize_data()
168 183 {
169 184 // Test structure
170 QTest::addColumn<QVector<QVector<double> > >("inputData"); // array data's input
171 QTest::addColumn<int>("expectedSize"); // expected array data size
185 QTest::addColumn<InputData>("inputData"); // array data's input
186 QTest::addColumn<int>("expectedSize"); // expected array data size
172 187
173 188 // Test cases
174 QTest::newRow("data1") << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}} << 5;
175 QTest::newRow("data2") << DataContainer{{1., 2., 3., 4., 5.},
176 {6., 7., 8., 9., 10.},
177 {11., 12., 13., 14., 15.}}
189 QTest::newRow("data1") << flatten(Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}}) << 5;
190 QTest::newRow("data2") << flatten(Container{{1., 2., 3., 4., 5.},
191 {6., 7., 8., 9., 10.},
192 {11., 12., 13., 14., 15.}})
178 193 << 5;
179 194 }
180 195
181 196 void TestTwoDimArrayData::testSize()
182 197 {
183 QFETCH(DataContainer, inputData);
198 QFETCH(InputData, inputData);
184 199 QFETCH(int, expectedSize);
185 200
186 ArrayData<2> arrayData{inputData};
201 ArrayData<2> arrayData{inputData.first, inputData.second};
187 202 QVERIFY(arrayData.size() == expectedSize);
188 203 }
189 204
190 205 void TestTwoDimArrayData::testSort_data()
191 206 {
192 207 // Test structure
193 QTest::addColumn<DataContainer>("inputData"); // array data's input
208 QTest::addColumn<InputData>("inputData"); // array data's input
194 209 QTest::addColumn<std::vector<int> >("sortPermutation"); // permutation used to sort data
195 QTest::addColumn<DataContainer>("expectedData"); // expected data after sorting
210 QTest::addColumn<Container>("expectedData"); // expected data after sorting
196 211
197 212 // Test cases
198 213 QTest::newRow("data1")
199 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}
214 << flatten(
215 Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}})
200 216 << std::vector<int>{0, 2, 3, 1, 4}
201 << DataContainer{{1., 3., 4., 2., 5.}, {6., 8., 9., 7., 10.}, {11., 13., 14., 12., 15.}};
217 << Container{{1., 3., 4., 2., 5.}, {6., 8., 9., 7., 10.}, {11., 13., 14., 12., 15.}};
202 218 QTest::newRow("data2")
203 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}
219 << flatten(
220 Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}})
204 221 << std::vector<int>{2, 4, 3, 0, 1}
205 << DataContainer{{3., 5., 4., 1., 2.}, {8., 10., 9., 6., 7.}, {13., 15., 14., 11., 12.}};
222 << Container{{3., 5., 4., 1., 2.}, {8., 10., 9., 6., 7.}, {13., 15., 14., 11., 12.}};
206 223 }
207 224
208 225 void TestTwoDimArrayData::testSort()
209 226 {
210 QFETCH(DataContainer, inputData);
227 QFETCH(InputData, inputData);
211 228 QFETCH(std::vector<int>, sortPermutation);
212 QFETCH(DataContainer, expectedData);
229 QFETCH(Container, expectedData);
213 230
214 ArrayData<2> arrayData{inputData};
231 ArrayData<2> arrayData{inputData.first, inputData.second};
215 232 auto sortedArrayData = arrayData.sort(sortPermutation);
216 233 QVERIFY(sortedArrayData != nullptr);
217 234
218 for (auto i = 0; i < expectedData.size(); ++i) {
219 QVERIFY(sortedArrayData->data(i) == expectedData.at(i));
220 }
235 verifyArrayData(*sortedArrayData, expectedData);
221 236 }
222 237
223 238 QTEST_MAIN(TestTwoDimArrayData)
224 239 #include "TestTwoDimArrayData.moc"
@@ -1,310 +1,281
1 1 #include "AmdaResultParser.h"
2 2
3 3 #include <Data/ScalarSeries.h>
4 4 #include <Data/VectorSeries.h>
5 5
6 6 #include <QObject>
7 7 #include <QtTest>
8 8
9 9 namespace {
10 10
11 11 /// Path for the tests
12 12 const auto TESTS_RESOURCES_PATH
13 13 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaResultParser"}.absoluteFilePath();
14 14
15 15 QDateTime dateTime(int year, int month, int day, int hours, int minutes, int seconds)
16 16 {
17 17 return QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC};
18 18 }
19 19
20 /// Compares two vectors that can potentially contain NaN values
21 bool compareVectors(const QVector<double> &v1, const QVector<double> &v2)
22 {
23 if (v1.size() != v2.size()) {
24 return false;
25 }
26
27 auto result = true;
28 auto v2It = v2.cbegin();
29 for (auto v1It = v1.cbegin(), v1End = v1.cend(); v1It != v1End && result; ++v1It, ++v2It) {
30 auto v1Value = *v1It;
31 auto v2Value = *v2It;
32
33 // If v1 is NaN, v2 has to be NaN too
34 result = std::isnan(v1Value) ? std::isnan(v2Value) : (v1Value == v2Value);
35 }
36
37 return result;
38 }
39
40 bool compareVectors(const QVector<QVector<double> > &v1, const QVector<QVector<double> > &v2)
41 {
42 if (v1.size() != v2.size()) {
43 return false;
44 }
45
46 auto result = true;
47 for (auto i = 0; i < v1.size() && result; ++i) {
48 result &= compareVectors(v1.at(i), v2.at(i));
49 }
50
51 return result;
52 }
53
54 QVector<QVector<double> > valuesData(const ArrayData<1> &arrayData)
55 {
56 return QVector<QVector<double> >{arrayData.data()};
57 }
58
59 QVector<QVector<double> > valuesData(const ArrayData<2> &arrayData)
60 {
61 return arrayData.data();
62 }
63
64
65 20 QString inputFilePath(const QString &inputFileName)
66 21 {
67 22 return QFileInfo{TESTS_RESOURCES_PATH, inputFileName}.absoluteFilePath();
68 23 }
69 24
70 25 template <typename T>
71 26 struct ExpectedResults {
72 27 explicit ExpectedResults() = default;
73 28
74 29 explicit ExpectedResults(Unit xAxisUnit, Unit valuesUnit, const QVector<QDateTime> &xAxisData,
75 30 QVector<double> valuesData)
76 31 : ExpectedResults(xAxisUnit, valuesUnit, xAxisData,
77 32 QVector<QVector<double> >{std::move(valuesData)})
78 33 {
79 34 }
80 35
81 36 /// Ctor with QVector<QDateTime> as x-axis data. Datetimes are converted to doubles
82 37 explicit ExpectedResults(Unit xAxisUnit, Unit valuesUnit, const QVector<QDateTime> &xAxisData,
83 38 QVector<QVector<double> > valuesData)
84 39 : m_ParsingOK{true},
85 40 m_XAxisUnit{xAxisUnit},
86 41 m_ValuesUnit{valuesUnit},
87 42 m_XAxisData{},
88 43 m_ValuesData{std::move(valuesData)}
89 44 {
90 45 // Converts QVector<QDateTime> to QVector<double>
91 46 std::transform(xAxisData.cbegin(), xAxisData.cend(), std::back_inserter(m_XAxisData),
92 47 [](const auto &dateTime) { return dateTime.toMSecsSinceEpoch() / 1000.; });
93 48 }
94 49
95 50 /**
96 51 * Validates a DataSeries compared to the expected results
97 52 * @param results the DataSeries to validate
98 53 */
99 54 void validate(std::shared_ptr<IDataSeries> results)
100 55 {
101 56 if (m_ParsingOK) {
102 57 auto dataSeries = dynamic_cast<T *>(results.get());
103 58 QVERIFY(dataSeries != nullptr);
104 59
105 60 // Checks units
106 61 QVERIFY(dataSeries->xAxisUnit() == m_XAxisUnit);
107 62 QVERIFY(dataSeries->valuesUnit() == m_ValuesUnit);
108 63
109 // Checks values : as the vectors can potentially contain NaN values, we must use a
110 // custom vector comparison method
111 QVERIFY(compareVectors(dataSeries->xAxisData()->data(), m_XAxisData));
112 QVERIFY(compareVectors(valuesData(*dataSeries->valuesData()), m_ValuesData));
64 auto verifyRange = [dataSeries](const auto &expectedData, const auto &equalFun) {
65 QVERIFY(std::equal(dataSeries->cbegin(), dataSeries->cend(), expectedData.cbegin(),
66 expectedData.cend(),
67 [&equalFun](const auto &dataSeriesIt, const auto &expectedX) {
68 return equalFun(dataSeriesIt, expectedX);
69 }));
70 };
71
72 // Checks x-axis data
73 verifyRange(m_XAxisData, [](const auto &seriesIt, const auto &value) {
74 return seriesIt.x() == value;
75 });
76
77 // Checks values data of each component
78 for (auto i = 0; i < m_ValuesData.size(); ++i) {
79 verifyRange(m_ValuesData.at(i), [i](const auto &seriesIt, const auto &value) {
80 auto itValue = seriesIt.value(i);
81 return (std::isnan(itValue) && std::isnan(value)) || seriesIt.value(i) == value;
82 });
83 }
113 84 }
114 85 else {
115 86 QVERIFY(results == nullptr);
116 87 }
117 88 }
118 89
119 90 // Parsing was successfully completed
120 91 bool m_ParsingOK{false};
121 92 // Expected x-axis unit
122 93 Unit m_XAxisUnit{};
123 94 // Expected values unit
124 95 Unit m_ValuesUnit{};
125 96 // Expected x-axis data
126 97 QVector<double> m_XAxisData{};
127 98 // Expected values data
128 99 QVector<QVector<double> > m_ValuesData{};
129 100 };
130 101
131 102 } // namespace
132 103
133 104 Q_DECLARE_METATYPE(ExpectedResults<ScalarSeries>)
134 105 Q_DECLARE_METATYPE(ExpectedResults<VectorSeries>)
135 106
136 107 class TestAmdaResultParser : public QObject {
137 108 Q_OBJECT
138 109 private:
139 110 template <typename T>
140 111 void testReadDataStructure()
141 112 {
142 113 // ////////////// //
143 114 // Test structure //
144 115 // ////////////// //
145 116
146 117 // Name of TXT file to read
147 118 QTest::addColumn<QString>("inputFileName");
148 119 // Expected results
149 120 QTest::addColumn<ExpectedResults<T> >("expectedResults");
150 121 }
151 122
152 123 template <typename T>
153 124 void testRead(AmdaResultParser::ValueType valueType)
154 125 {
155 126 QFETCH(QString, inputFileName);
156 127 QFETCH(ExpectedResults<T>, expectedResults);
157 128
158 129 // Parses file
159 130 auto filePath = inputFilePath(inputFileName);
160 131 auto results = AmdaResultParser::readTxt(filePath, valueType);
161 132
162 133 // ///////////////// //
163 134 // Validates results //
164 135 // ///////////////// //
165 136 expectedResults.validate(results);
166 137 }
167 138
168 139 private slots:
169 140 /// Input test data
170 141 /// @sa testReadScalarTxt()
171 142 void testReadScalarTxt_data();
172 143
173 144 /// Tests parsing scalar series of a TXT file
174 145 void testReadScalarTxt();
175 146
176 147 /// Input test data
177 148 /// @sa testReadVectorTxt()
178 149 void testReadVectorTxt_data();
179 150
180 151 /// Tests parsing vector series of a TXT file
181 152 void testReadVectorTxt();
182 153 };
183 154
184 155 void TestAmdaResultParser::testReadScalarTxt_data()
185 156 {
186 157 testReadDataStructure<ScalarSeries>();
187 158
188 159 // ////////// //
189 160 // Test cases //
190 161 // ////////// //
191 162
192 163 // Valid files
193 164 QTest::newRow("Valid file")
194 165 << QStringLiteral("ValidScalar1.txt")
195 166 << ExpectedResults<ScalarSeries>{
196 167 Unit{QStringLiteral("nT"), true}, Unit{},
197 168 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
198 169 dateTime(2013, 9, 23, 9, 2, 30), dateTime(2013, 9, 23, 9, 3, 30),
199 170 dateTime(2013, 9, 23, 9, 4, 30), dateTime(2013, 9, 23, 9, 5, 30),
200 171 dateTime(2013, 9, 23, 9, 6, 30), dateTime(2013, 9, 23, 9, 7, 30),
201 172 dateTime(2013, 9, 23, 9, 8, 30), dateTime(2013, 9, 23, 9, 9, 30)},
202 173 QVector<double>{-2.83950, -2.71850, -2.52150, -2.57633, -2.58050, -2.48325, -2.63025,
203 174 -2.55800, -2.43250, -2.42200}};
204 175
205 176 QTest::newRow("Valid file (value of first line is invalid but it is converted to NaN")
206 177 << QStringLiteral("WrongValue.txt")
207 178 << ExpectedResults<ScalarSeries>{
208 179 Unit{QStringLiteral("nT"), true}, Unit{},
209 180 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
210 181 dateTime(2013, 9, 23, 9, 2, 30)},
211 182 QVector<double>{std::numeric_limits<double>::quiet_NaN(), -2.71850, -2.52150}};
212 183
213 184 QTest::newRow("Valid file that contains NaN values")
214 185 << QStringLiteral("NaNValue.txt")
215 186 << ExpectedResults<ScalarSeries>{
216 187 Unit{QStringLiteral("nT"), true}, Unit{},
217 188 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
218 189 dateTime(2013, 9, 23, 9, 2, 30)},
219 190 QVector<double>{std::numeric_limits<double>::quiet_NaN(), -2.71850, -2.52150}};
220 191
221 192 // Valid files but with some invalid lines (wrong unit, wrong values, etc.)
222 193 QTest::newRow("No unit file") << QStringLiteral("NoUnit.txt")
223 194 << ExpectedResults<ScalarSeries>{Unit{QStringLiteral(""), true},
224 195 Unit{}, QVector<QDateTime>{},
225 196 QVector<double>{}};
226 197 QTest::newRow("Wrong unit file")
227 198 << QStringLiteral("WrongUnit.txt")
228 199 << ExpectedResults<ScalarSeries>{Unit{QStringLiteral(""), true}, Unit{},
229 200 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30),
230 201 dateTime(2013, 9, 23, 9, 1, 30),
231 202 dateTime(2013, 9, 23, 9, 2, 30)},
232 203 QVector<double>{-2.83950, -2.71850, -2.52150}};
233 204
234 205 QTest::newRow("Wrong results file (date of first line is invalid")
235 206 << QStringLiteral("WrongDate.txt")
236 207 << ExpectedResults<ScalarSeries>{
237 208 Unit{QStringLiteral("nT"), true}, Unit{},
238 209 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
239 210 QVector<double>{-2.71850, -2.52150}};
240 211
241 212 QTest::newRow("Wrong results file (too many values for first line")
242 213 << QStringLiteral("TooManyValues.txt")
243 214 << ExpectedResults<ScalarSeries>{
244 215 Unit{QStringLiteral("nT"), true}, Unit{},
245 216 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
246 217 QVector<double>{-2.71850, -2.52150}};
247 218
248 219 QTest::newRow("Wrong results file (x of first line is NaN")
249 220 << QStringLiteral("NaNX.txt")
250 221 << ExpectedResults<ScalarSeries>{
251 222 Unit{QStringLiteral("nT"), true}, Unit{},
252 223 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
253 224 QVector<double>{-2.71850, -2.52150}};
254 225
255 226 QTest::newRow("Invalid file type (vector)")
256 227 << QStringLiteral("ValidVector1.txt")
257 228 << ExpectedResults<ScalarSeries>{Unit{QStringLiteral("nT"), true}, Unit{},
258 229 QVector<QDateTime>{}, QVector<double>{}};
259 230
260 231 // Invalid files
261 232 QTest::newRow("Invalid file (unexisting file)") << QStringLiteral("UnexistingFile.txt")
262 233 << ExpectedResults<ScalarSeries>{};
263 234
264 235 QTest::newRow("Invalid file (file not found on server)") << QStringLiteral("FileNotFound.txt")
265 236 << ExpectedResults<ScalarSeries>{};
266 237 }
267 238
268 239 void TestAmdaResultParser::testReadScalarTxt()
269 240 {
270 241 testRead<ScalarSeries>(AmdaResultParser::ValueType::SCALAR);
271 242 }
272 243
273 244 void TestAmdaResultParser::testReadVectorTxt_data()
274 245 {
275 246 testReadDataStructure<VectorSeries>();
276 247
277 248 // ////////// //
278 249 // Test cases //
279 250 // ////////// //
280 251
281 252 // Valid files
282 253 QTest::newRow("Valid file")
283 254 << QStringLiteral("ValidVector1.txt")
284 255 << ExpectedResults<VectorSeries>{
285 256 Unit{QStringLiteral("nT"), true}, Unit{},
286 257 QVector<QDateTime>{dateTime(2013, 7, 2, 9, 13, 50), dateTime(2013, 7, 2, 9, 14, 6),
287 258 dateTime(2013, 7, 2, 9, 14, 22), dateTime(2013, 7, 2, 9, 14, 38),
288 259 dateTime(2013, 7, 2, 9, 14, 54), dateTime(2013, 7, 2, 9, 15, 10),
289 260 dateTime(2013, 7, 2, 9, 15, 26), dateTime(2013, 7, 2, 9, 15, 42),
290 261 dateTime(2013, 7, 2, 9, 15, 58), dateTime(2013, 7, 2, 9, 16, 14)},
291 262 QVector<QVector<double> >{
292 263 {-0.332, -1.011, -1.457, -1.293, -1.217, -1.443, -1.278, -1.202, -1.22, -1.259},
293 264 {3.206, 2.999, 2.785, 2.736, 2.612, 2.564, 2.892, 2.862, 2.859, 2.764},
294 265 {0.058, 0.496, 1.018, 1.485, 1.662, 1.505, 1.168, 1.244, 1.15, 1.358}}};
295 266
296 267 // Valid files but with some invalid lines (wrong unit, wrong values, etc.)
297 268 QTest::newRow("Invalid file type (scalar)")
298 269 << QStringLiteral("ValidScalar1.txt")
299 270 << ExpectedResults<VectorSeries>{Unit{QStringLiteral("nT"), true}, Unit{},
300 271 QVector<QDateTime>{},
301 272 QVector<QVector<double> >{{}, {}, {}}};
302 273 }
303 274
304 275 void TestAmdaResultParser::testReadVectorTxt()
305 276 {
306 277 testRead<VectorSeries>(AmdaResultParser::ValueType::VECTOR);
307 278 }
308 279
309 280 QTEST_MAIN(TestAmdaResultParser)
310 281 #include "TestAmdaResultParser.moc"
General Comments 0
You need to be logged in to leave comments. Login now