##// END OF EJS Templates
Modification of the test for the new vc request kernel
perrinel -
r830:8991b585417a
parent child
Show More
@@ -1,551 +1,553
1 1 #include <QObject>
2 2 #include <QtTest>
3 3
4 4 #include <memory>
5 5
6 6 #include <Data/DataProviderParameters.h>
7 7 #include <Data/IDataProvider.h>
8 8 #include <Data/ScalarSeries.h>
9 9 #include <Time/TimeController.h>
10 10 #include <Variable/Variable.h>
11 11 #include <Variable/VariableController.h>
12 12 #include <Variable/VariableModel.h>
13 13
14 14 namespace {
15 15
16 16 /// Delay after each operation on the variable before validating it (in ms)
17 17 const auto OPERATION_DELAY = 100;
18 18
19 19 /**
20 20 * Generates values according to a range. The value generated for a time t is the number of seconds
21 21 * of difference between t and a reference value (which is midnight -> 00:00:00)
22 22 *
23 23 * Example: For a range between 00:00:10 and 00:00:20, the generated values are
24 24 * {10,11,12,13,14,15,16,17,18,19,20}
25 25 */
26 26 std::vector<double> values(const SqpRange &range)
27 27 {
28 28 QTime referenceTime{0, 0};
29 29
30 30 std::vector<double> result{};
31 31
32 32 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
33 33 auto time = DateUtils::dateTime(i).time();
34 34 result.push_back(referenceTime.secsTo(time));
35 35 }
36 36
37 37 return result;
38 38 }
39 39
40 40 /// Provider used for the tests
41 41 class TestProvider : public IDataProvider {
42 42 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
43 43
44 44 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
45 45 {
46 46 const auto &ranges = parameters.m_Times;
47 47
48 48 for (const auto &range : ranges) {
49 49 // Generates data series
50 50 auto valuesData = values(range);
51 51
52 52 std::vector<double> xAxisData{};
53 53 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
54 54 xAxisData.push_back(i);
55 55 }
56 56
57 57 auto dataSeries = std::make_shared<ScalarSeries>(
58 58 std::move(xAxisData), std::move(valuesData), Unit{"t", true}, Unit{});
59 59
60 60 emit dataProvided(acqIdentifier, dataSeries, range);
61 61 }
62 62 }
63 63
64 64 void requestDataAborting(QUuid acqIdentifier) override
65 65 {
66 66 // Does nothing
67 67 }
68 68 };
69 69
70 70 /**
71 71 * Interface representing an operation performed on a variable controller.
72 72 * This interface is used in tests to apply a set of operations and check the status of the
73 73 * controller after each operation
74 74 */
75 75 struct IOperation {
76 76 virtual ~IOperation() = default;
77 77 /// Executes the operation on the variable controller
78 78 virtual void exec(VariableController &variableController) const = 0;
79 79 };
80 80
81 81 /**
82 82 *Variable creation operation in the controller
83 83 */
84 84 struct Create : public IOperation {
85 85 explicit Create(int index) : m_Index{index} {}
86 86
87 87 void exec(VariableController &variableController) const override
88 88 {
89 89 auto variable = variableController.createVariable(QString::number(m_Index), {},
90 90 std::make_unique<TestProvider>());
91 91 }
92 92
93 93 int m_Index; ///< The index of the variable to create in the controller
94 94 };
95 95
96 96 /**
97 97 * Variable move/shift operation in the controller
98 98 */
99 99 struct Move : public IOperation {
100 100 explicit Move(int index, const SqpRange &newRange, bool shift = false)
101 101 : m_Index{index}, m_NewRange{newRange}, m_Shift{shift}
102 102 {
103 103 }
104 104
105 105 void exec(VariableController &variableController) const override
106 106 {
107 107 if (auto variable = variableController.variableModel()->variable(m_Index)) {
108 108 variableController.onRequestDataLoading({variable}, m_NewRange, !m_Shift);
109 109 }
110 110 }
111 111
112 112 int m_Index; ///< The index of the variable to move
113 113 SqpRange m_NewRange; ///< The new range of the variable
114 114 bool m_Shift; ///< Performs a shift (
115 115 };
116 116
117 117 /**
118 118 * Variable synchronization/desynchronization operation in the controller
119 119 */
120 120 struct Synchronize : public IOperation {
121 121 explicit Synchronize(int index, QUuid syncId, bool synchronize = true)
122 122 : m_Index{index}, m_SyncId{syncId}, m_Synchronize{synchronize}
123 123 {
124 124 }
125 125
126 126 void exec(VariableController &variableController) const override
127 127 {
128 128 if (auto variable = variableController.variableModel()->variable(m_Index)) {
129 129 if (m_Synchronize) {
130 130 variableController.onAddSynchronized(variable, m_SyncId);
131 131 }
132 132 else {
133 133 variableController.desynchronize(variable, m_SyncId);
134 134 }
135 135 }
136 136 }
137 137
138 138 int m_Index; ///< The index of the variable to sync/desync
139 139 QUuid m_SyncId; ///< The synchronization group of the variable
140 140 bool m_Synchronize; ///< Performs sync or desync operation
141 141 };
142 142
143 143 /**
144 144 * Test Iteration
145 145 *
146 146 * A test iteration includes an operation to be performed, and a set of expected ranges after each
147 147 * operation. Each range is tested after the operation to ensure that:
148 148 * - the range of the variable is the expected range
149 149 * - the data of the variable are those generated for the expected range
150 150 */
151 151 struct Iteration {
152 152 std::shared_ptr<IOperation> m_Operation; ///< Operation to perform
153 153 std::map<int, SqpRange> m_ExpectedRanges; ///< Expected ranges (by variable index)
154 154 };
155 155
156 156 using Iterations = std::vector<Iteration>;
157 157
158 158 } // namespace
159 159
160 160 Q_DECLARE_METATYPE(Iterations)
161 161
162 162 class TestVariableSync : public QObject {
163 163 Q_OBJECT
164 164
165 165 private slots:
166 166 /// Input data for @sa testSync()
167 167 void testSync_data();
168 168
169 169 /// Input data for @sa testSyncWithAborting()
170 170 void testSyncWithAborting_data();
171 171
172 172 /// Tests synchronization between variables through several operations with aborting
173 173 void testSyncWithAborting();
174 174
175 175 /// Tests synchronization between variables through several operations
176 176 void testSync();
177 177 };
178 178
179 179 namespace {
180 180
181 181 void testSyncCase1()
182 182 {
183 183 // Id used to synchronize variables in the controller
184 184 auto syncId = QUuid::createUuid();
185 185
186 186 /// Generates a range according to a start time and a end time (the date is the same)
187 187 auto range = [](const QTime &startTime, const QTime &endTime) {
188 188 return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}),
189 189 DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})};
190 190 };
191 191
192 192 auto initialRange = range({12, 0}, {13, 0});
193 193
194 194 Iterations iterations{};
195 195 // Creates variables var0, var1 and var2
196 196 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
197 197 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
198 198 iterations.push_back(
199 199 {std::make_shared<Create>(2), {{0, initialRange}, {1, initialRange}, {2, initialRange}}});
200 200
201 201 // Adds variables into the sync group (ranges don't need to be tested here)
202 202 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
203 203 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
204 204 iterations.push_back({std::make_shared<Synchronize>(2, syncId)});
205 205
206 206 // Moves var0: ranges of var0, var1 and var2 change
207 207 auto newRange = range({12, 30}, {13, 30});
208 208 iterations.push_back(
209 209 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
210 210
211 211 // Moves var1: ranges of var0, var1 and var2 change
212 212 newRange = range({13, 0}, {14, 0});
213 213 iterations.push_back(
214 214 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
215 215
216 216 // Moves var2: ranges of var0, var1 and var2 change
217 217 newRange = range({13, 30}, {14, 30});
218 218 iterations.push_back(
219 219 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
220 220
221 221 // Desyncs var2 and moves var0:
222 222 // - ranges of var0 and var1 change
223 223 // - range of var2 doesn't change anymore
224 224 auto var2Range = newRange;
225 225 newRange = range({13, 45}, {14, 45});
226 226 iterations.push_back({std::make_shared<Synchronize>(2, syncId, false)});
227 227 iterations.push_back(
228 228 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, var2Range}}});
229 229
230 230 // Shifts var0: although var1 is synchronized with var0, its range doesn't change
231 231 auto var1Range = newRange;
232 232 newRange = range({14, 45}, {15, 45});
233 233 iterations.push_back({std::make_shared<Move>(0, newRange, true),
234 234 {{0, newRange}, {1, var1Range}, {2, var2Range}}});
235 235
236 236 // Moves var0 through several operations:
237 237 // - range of var0 changes
238 238 // - range or var1 changes according to the previous shift (one hour)
239 239 auto moveVar0 = [&iterations](const auto &var0NewRange, const auto &var1ExpectedRange) {
240 240 iterations.push_back(
241 241 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}});
242 242 };
243 243
244 244 // Pan left
245 245 moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30}));
246 246 // Pan right
247 247 moveVar0(range({16, 0}, {17, 0}), range({15, 0}, {16, 0}));
248 248 // Zoom in
249 249 moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45}));
250 250 // Zoom out
251 251 moveVar0(range({16, 15}, {17, 0}), range({15, 15}, {16, 0}));
252 252
253 253 QTest::newRow("sync1") << syncId << initialRange << std::move(iterations) << 200;
254 254 }
255 255
256 256 void testSyncCase1WithAborting()
257 257 {
258 258 // Id used to synchronize variables in the controller
259 259 auto syncId = QUuid::createUuid();
260 260
261 261 /// Generates a range according to a start time and a end time (the date is the same)
262 262 auto range = [](const QTime &startTime, const QTime &endTime) {
263 263 return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}),
264 264 DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})};
265 265 };
266 266
267 267 auto initialRange = range({12, 0}, {13, 0});
268 268
269 269 Iterations creations{};
270 270 // Creates variables var0, var1 and var2
271 271 creations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
272 272 creations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
273 273
274 274 // Adds variables into the sync group (ranges don't need to be tested here)
275 275 Iterations iterations{};
276 276 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
277 277 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
278 278
279 // Moves var0: ranges of var0, var1 and var2 change
280 auto newRange = range({12, 30}, {13, 30});
281 iterations.push_back({std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}}});
279 // Moves var0: ranges of var0, var1
280 auto currentRange = range({12, 30}, {13, 30});
281 iterations.push_back(
282 {std::make_shared<Move>(0, currentRange), {{0, currentRange}, {1, currentRange}}});
282 283
283 // Moves var1: ranges of var0, var1 and var2 change
284 newRange = range({13, 0}, {14, 0});
285 iterations.push_back({std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}}});
284 // Moves var0: ranges of var0, var1
285 auto pendingRange = range({13, 0}, {14, 0});
286 iterations.push_back(
287 {std::make_shared<Move>(0, pendingRange), {{0, pendingRange}, {1, pendingRange}}});
286 288
287 // Moves var2: ranges of var0, var1 and var2 change
288 newRange = range({13, 30}, {14, 30});
289 // Moves var0: ranges of var0, var1
290 pendingRange = range({13, 30}, {14, 30});
289 291 iterations.push_back(
290 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
292 {std::make_shared<Move>(0, pendingRange), {{0, pendingRange}, {1, pendingRange}}});
291 293
292 // Desyncs var2 and moves var0:
294 // moves var0:
293 295 // - ranges of var0 and var1 change
294 // - range of var2 doesn't change anymore
295 auto var2Range = newRange;
296 newRange = range({13, 45}, {14, 45});
297 iterations.push_back({std::make_shared<Synchronize>(2, syncId, false)});
298 iterations.push_back({std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}}});
296 auto var2Range = pendingRange;
297 pendingRange = range({13, 45}, {14, 45});
298 iterations.push_back(
299 {std::make_shared<Move>(0, pendingRange), {{0, pendingRange}, {1, pendingRange}}});
299 300
300 301 // Shifts var0: although var1 is synchronized with var0, its range doesn't change
301 auto var1Range = newRange;
302 newRange = range({14, 45}, {15, 45});
302 auto var1Range = pendingRange;
303 pendingRange = range({14, 45}, {15, 45});
303 304 iterations.push_back(
304 {std::make_shared<Move>(0, newRange, true), {{0, newRange}, {1, var1Range}}});
305 {std::make_shared<Move>(0, pendingRange, false), {{0, pendingRange}, {1, pendingRange}}});
305 306
306 307 // Moves var0 through several operations:
307 308 // - range of var0 changes
308 309 // - range or var1 changes according to the previous shift (one hour)
309 310 auto moveVar0 = [&iterations](const auto &var0NewRange, const auto &var1ExpectedRange) {
310 311 iterations.push_back(
311 312 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}});
312 313 };
313 314
314 315 // auto oldRange = newRange;
315 316 // newRange = range({14, 30}, {15, 30});
316 317 // auto expectedRange = oldRange;
317 318 // iterations.push_back(
318 319 // {std::make_shared<Move>(0, newRange), {{0, oldRange}, {1, expectedRange}}});
319 320
320 321 // Pan left
321 moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30}));
322 moveVar0(range({14, 30}, {15, 30}), range({14, 30}, {15, 30}));
322 323 // Pan right
323 moveVar0(range({16, 0}, {17, 0}), range({15, 0}, {16, 0}));
324 moveVar0(range({16, 0}, {17, 0}), range({16, 0}, {17, 0}));
324 325 // Zoom in
325 moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45}));
326 moveVar0(range({16, 30}, {16, 45}), range({16, 30}, {16, 45}));
326 327 // Zoom out
327 moveVar0(range({16, 15}, {17, 0}), range({15, 15}, {16, 0}));
328 moveVar0(range({16, 15}, {17, 0}), range({16, 15}, {17, 0}));
328 329
329 QTest::newRow("syncWithAborting1") << syncId << initialRange << std::move(creations)
330 QTest::newRow("syncWithAborting1") << syncId << currentRange << std::move(creations)
330 331 << std::move(iterations) << 200;
331 332 }
332 333
333 334 void testSyncCase2()
334 335 {
335 336 // Id used to synchronize variables in the controller
336 337 auto syncId = QUuid::createUuid();
337 338
338 339 /// Generates a range according to a start time and a end time (the date is the same)
339 340 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
340 341 return DateUtils::secondsSinceEpoch(
341 342 QDateTime{{year, month, day}, QTime{hours, minutes, seconds}, Qt::UTC});
342 343 };
343 344
344 345 auto initialRange = SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)};
345 346
346 347 Iterations iterations{};
347 348 // Creates variables var0 and var1
348 349 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
349 350 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
350 351
351 352 // Adds variables into the sync group (ranges don't need to be tested here)
352 353 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
353 354 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
354 355
355 356
356 357 // Moves var0 through several operations:
357 358 // - range of var0 changes
358 359 // - range or var1 changes according to the previous shift (one hour)
359 360 auto moveVar0 = [&iterations](const auto &var0NewRange) {
360 361 iterations.push_back(
361 362 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var0NewRange}}});
362 363 };
363 364 moveVar0(SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)});
364 365 moveVar0(SqpRange{dateTime(2017, 1, 1, 14, 0, 0), dateTime(2017, 1, 1, 15, 0, 0)});
365 366 moveVar0(SqpRange{dateTime(2017, 1, 1, 8, 0, 0), dateTime(2017, 1, 1, 9, 0, 0)});
366 367 // moveVar0(SqpRange{dateTime(2017, 1, 1, 7, 30, 0), dateTime(2017, 1, 1, 9, 30, 0)});
367 368 moveVar0(SqpRange{dateTime(2017, 1, 1, 2, 0, 0), dateTime(2017, 1, 1, 4, 0, 0)});
368 369 moveVar0(SqpRange{dateTime(2017, 1, 1, 6, 0, 0), dateTime(2017, 1, 1, 8, 0, 0)});
369 370
370 371 moveVar0(SqpRange{dateTime(2017, 1, 10, 6, 0, 0), dateTime(2017, 1, 15, 8, 0, 0)});
371 372 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 1, 25, 8, 0, 0)});
372 373 moveVar0(SqpRange{dateTime(2017, 1, 2, 6, 0, 0), dateTime(2017, 1, 8, 8, 0, 0)});
373 374
374 375 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
375 376 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
376 377 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
377 378 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
378 379 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
379 380 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
380 381 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
381 382 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
382 383 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
383 384 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
384 385 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
385 386 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
386 387
387 388
388 389 QTest::newRow("sync2") << syncId << initialRange << iterations << 4000;
389 390 // QTest::newRow("sync3") << syncId << initialRange << iterations << 5000;
390 391 }
391 392 }
392 393
393 394 void TestVariableSync::testSync_data()
394 395 {
395 396 // ////////////// //
396 397 // Test structure //
397 398 // ////////////// //
398 399
399 400 QTest::addColumn<QUuid>("syncId");
400 401 QTest::addColumn<SqpRange>("initialRange");
401 402 QTest::addColumn<Iterations>("iterations");
402 403 QTest::addColumn<int>("operationDelay");
403 404
404 405 // ////////// //
405 406 // Test cases //
406 407 // ////////// //
407 408
408 409 testSyncCase1();
409 410 testSyncCase2();
410 411 }
411 412
412 413 void TestVariableSync::testSyncWithAborting_data()
413 414 {
414 415 // ////////////// //
415 416 // Test structure //
416 417 // ////////////// //
417 418
418 419 QTest::addColumn<QUuid>("syncId");
419 420 QTest::addColumn<SqpRange>("initialRange");
420 421 QTest::addColumn<Iterations>("creations");
421 422 QTest::addColumn<Iterations>("iterations");
422 423 QTest::addColumn<int>("operationDelay");
423 424
424 425 // ////////// //
425 426 // Test cases //
426 427 // ////////// //
427 428
428 429 testSyncCase1WithAborting();
429 430 }
430 431
431 432 void TestVariableSync::testSync()
432 433 {
433 434 return;
434 435
435 436 // Inits controllers
436 437 TimeController timeController{};
437 438 VariableController variableController{};
438 439 variableController.setTimeController(&timeController);
439 440
440 441 QFETCH(QUuid, syncId);
441 442 QFETCH(SqpRange, initialRange);
442 443 timeController.onTimeToUpdate(initialRange);
443 444
444 445 // Synchronization group used
445 446 variableController.onAddSynchronizationGroupId(syncId);
446 447
447 448 auto validateRanges = [&variableController](const auto &expectedRanges) {
448 449 for (const auto &expectedRangeEntry : expectedRanges) {
449 450 auto variableIndex = expectedRangeEntry.first;
450 451 auto expectedRange = expectedRangeEntry.second;
451 452
452 453 // Gets the variable in the controller
453 454 auto variable = variableController.variableModel()->variable(variableIndex);
454 455
455 456 // Compares variable's range to the expected range
456 457 QVERIFY(variable != nullptr);
457 458 auto range = variable->range();
458 459 QCOMPARE(range, expectedRange);
459 460
460 461 // Compares variable's data with values expected for its range
461 462 auto dataSeries = variable->dataSeries();
462 463 QVERIFY(dataSeries != nullptr);
463 464
464 465 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
465 466 auto expectedValues = values(range);
466 467 qInfo() << std::distance(it.first, it.second) << expectedValues.size();
467 468 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
468 469 [](const auto &dataSeriesIt, const auto &expectedValue) {
469 470 return dataSeriesIt.value() == expectedValue;
470 471 }));
471 472 }
472 473 };
473 474
474 475 // For each iteration:
475 476 // - execute operation
476 477 // - compare the variables' state to the expected states
477 478 QFETCH(Iterations, iterations);
478 479 QFETCH(int, operationDelay);
479 480 for (const auto &iteration : iterations) {
480 481 iteration.m_Operation->exec(variableController);
481 482 QTest::qWait(operationDelay);
482 483
483 484 validateRanges(iteration.m_ExpectedRanges);
484 485 }
485 486 }
486 487
487 488 void TestVariableSync::testSyncWithAborting()
488 489 {
489 490 // Inits controllers
490 491 TimeController timeController{};
491 492 VariableController variableController{};
492 493 variableController.setTimeController(&timeController);
493 494
494 495 QFETCH(QUuid, syncId);
495 496 QFETCH(SqpRange, initialRange);
496 497 timeController.onTimeToUpdate(initialRange);
497 498
498 499 // Synchronization group used
499 500 variableController.onAddSynchronizationGroupId(syncId);
500 501
501 502 auto validateRanges = [&variableController](const auto &expectedRanges) {
502 503 for (const auto &expectedRangeEntry : expectedRanges) {
503 504 auto variableIndex = expectedRangeEntry.first;
504 505 auto expectedRange = expectedRangeEntry.second;
505 506
506 507 // Gets the variable in the controller
507 508 auto variable = variableController.variableModel()->variable(variableIndex);
508 509
509 510 // Compares variable's range to the expected range
510 511 QVERIFY(variable != nullptr);
511 512 auto range = variable->range();
513 qInfo() << "range vs expected range" << range << variable->range();
512 514 QCOMPARE(range, expectedRange);
513 515
514 516 // Compares variable's data with values expected for its range
515 517 auto dataSeries = variable->dataSeries();
516 518 QVERIFY(dataSeries != nullptr);
517 519
518 520 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
519 521 auto expectedValues = values(range);
520 522 qInfo() << std::distance(it.first, it.second) << expectedValues.size();
521 523 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
522 524 [](const auto &dataSeriesIt, const auto &expectedValue) {
523 525 return dataSeriesIt.value() == expectedValue;
524 526 }));
525 527 }
526 528 };
527 529
528 530 // For each iteration:
529 531 // - execute operation
530 532 // - compare the variables' state to the expected states
531 533 QFETCH(Iterations, iterations);
532 534 QFETCH(Iterations, creations);
533 535 QFETCH(int, operationDelay);
534 536
535 537 for (const auto &creation : creations) {
536 538 creation.m_Operation->exec(variableController);
537 539 QTest::qWait(operationDelay);
538 540 }
539 541
540 542 for (const auto &iteration : iterations) {
541 543 iteration.m_Operation->exec(variableController);
542 544 }
543 545
544 546 QTest::qWait(operationDelay);
545 547 validateRanges(iterations.back().m_ExpectedRanges);
546 548 }
547 549
548 550
549 551 QTEST_MAIN(TestVariableSync)
550 552
551 553 #include "TestVariableSync.moc"
@@ -1,192 +1,195
1 1 #include "CosinusProvider.h"
2 2 #include "MockDefs.h"
3 3
4 4 #include <Data/DataProviderParameters.h>
5 5 #include <Data/ScalarSeries.h>
6 6 #include <SqpApplication.h>
7 7 #include <Time/TimeController.h>
8 8 #include <Variable/Variable.h>
9 9 #include <Variable/VariableController.h>
10 10
11 11 #include <QObject>
12 12 #include <QtTest>
13 13
14 14 #include <cmath>
15 15 #include <memory>
16 16
17 17 namespace {
18 18
19 19 /// Path for the tests
20 20 const auto TESTS_RESOURCES_PATH = QFileInfo{
21 21 QString{MOCKPLUGIN_TESTS_RESOURCES_DIR},
22 22 "TestCosinusAcquisition"}.absoluteFilePath();
23 23
24 24 /// Format of dates in data files
25 25 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
26 26
27 27 /**
28 28 * Verifies that the data in the candidate series are identical to the data in the reference series
29 29 * in a specific range
30 30 * @param candidate the candidate data series
31 31 * @param range the range to check
32 32 * @param reference the reference data series
33 33 * @return true if the data of the candidate series and the reference series are identical in the
34 34 * range, false otherwise
35 35 */
36 36 bool checkDataSeries(std::shared_ptr<IDataSeries> candidate, const SqpRange &range,
37 37 std::shared_ptr<IDataSeries> reference)
38 38 {
39 39 if (candidate == nullptr || reference == nullptr) {
40 40 return candidate == reference;
41 41 }
42 42
43 43 auto referenceIt = reference->xAxisRange(range.m_TStart, range.m_TEnd);
44 44
45 45 qInfo() << "candidateSize" << std::distance(candidate->cbegin(), candidate->cend());
46 46 qInfo() << "refSize" << std::distance(referenceIt.first, referenceIt.second);
47 47
48 48 return std::equal(candidate->cbegin(), candidate->cend(), referenceIt.first, referenceIt.second,
49 49 [](const auto &it1, const auto &it2) {
50 50 // - milliseconds precision for time
51 51 // - 1e-6 precision for value
52 52 return std::abs(it1.x() - it2.x()) < 1e-3
53 53 && std::abs(it1.value() - it2.value()) < 1e-6;
54 54 });
55 55 }
56 56
57 57 } // namespace
58 58
59 59 /**
60 60 * @brief The TestCosinusAcquisition class tests acquisition in SciQlop (operations like zooms in,
61 61 * zooms out, pans) of data from CosinusProvider
62 62 * @sa CosinusProvider
63 63 */
64 64 class TestCosinusAcquisition : public QObject {
65 65 Q_OBJECT
66 66
67 67 private slots:
68 68 /// Input data for @sa testAcquisition()
69 69 void testAcquisition_data();
70 70 void testAcquisition();
71 71 };
72 72
73 73 void TestCosinusAcquisition::testAcquisition_data()
74 74 {
75 75 // ////////////// //
76 76 // Test structure //
77 77 // ////////////// //
78 78
79 79 QTest::addColumn<SqpRange>("referenceRange"); // Range for generating reference series
80 80 QTest::addColumn<SqpRange>("initialRange"); // First acquisition
81 81 QTest::addColumn<int>("operationDelay"); // Acquisitions to make
82 82 QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
83 83
84 84 // ////////// //
85 85 // Test cases //
86 86 // ////////// //
87 87
88 88 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
89 89 return DateUtils::secondsSinceEpoch(
90 90 QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC});
91 91 };
92 92
93 93 QTest::newRow("cosinus")
94 94 << SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)}
95 95 << SqpRange{dateTime(2017, 1, 1, 12, 30, 0), dateTime(2017, 1, 1, 12, 35, 1)} << 250
96 96 << std::vector<SqpRange>{
97 97 // Pan (jump) left
98 98 SqpRange{dateTime(2017, 1, 1, 12, 45, 0), dateTime(2017, 1, 1, 12, 50, 0)},
99 99 // Pan (jump) right
100 100 SqpRange{dateTime(2017, 1, 1, 12, 15, 0), dateTime(2017, 1, 1, 12, 20, 0)},
101 101 // Pan (overlay) right
102 102 SqpRange{dateTime(2017, 1, 1, 12, 14, 0), dateTime(2017, 1, 1, 12, 19, 0)},
103 103 // Pan (overlay) left
104 104 SqpRange{dateTime(2017, 1, 1, 12, 15, 0), dateTime(2017, 1, 1, 12, 20, 0)},
105 105 // Pan (overlay) left
106 106 SqpRange{dateTime(2017, 1, 1, 12, 16, 0), dateTime(2017, 1, 1, 12, 21, 0)},
107 107 // Zoom in
108 108 SqpRange{dateTime(2017, 1, 1, 12, 17, 30), dateTime(2017, 1, 1, 12, 19, 30)},
109 109 // Zoom out
110 110 SqpRange{dateTime(2017, 1, 1, 12, 12, 30), dateTime(2017, 1, 1, 12, 24, 30)}};
111 111
112 112 QTest::newRow("cosinus_big")
113 113 << SqpRange{dateTime(2017, 1, 1, 1, 0, 0), dateTime(2017, 1, 5, 13, 0, 0)}
114 114 << SqpRange{dateTime(2017, 1, 2, 6, 30, 0), dateTime(2017, 1, 2, 18, 30, 0)} << 5000
115 115 << std::vector<SqpRange>{
116 116 // Pan (jump) left
117 117 SqpRange{dateTime(2017, 1, 1, 13, 30, 0), dateTime(2017, 1, 1, 18, 30, 0)},
118 118 // Pan (jump) right
119 119 SqpRange{dateTime(2017, 1, 3, 4, 30, 0), dateTime(2017, 1, 3, 10, 30, 0)},
120 120 // Pan (overlay) right
121 121 SqpRange{dateTime(2017, 1, 3, 8, 30, 0), dateTime(2017, 1, 3, 12, 30, 0)},
122 122 // Pan (overlay) left
123 123 SqpRange{dateTime(2017, 1, 2, 8, 30, 0), dateTime(2017, 1, 3, 10, 30, 0)},
124 124 // Pan (overlay) left
125 125 SqpRange{dateTime(2017, 1, 1, 12, 30, 0), dateTime(2017, 1, 3, 5, 30, 0)},
126 126 // Zoom in
127 127 SqpRange{dateTime(2017, 1, 2, 2, 30, 0), dateTime(2017, 1, 2, 8, 30, 0)},
128 128 // Zoom out
129 129 SqpRange{dateTime(2017, 1, 1, 14, 30, 0), dateTime(2017, 1, 3, 12, 30, 0)}};
130 130 }
131 131
132 132 void TestCosinusAcquisition::testAcquisition()
133 133 {
134 134 // Retrieves reference range
135 135 QFETCH(SqpRange, referenceRange);
136 136 CosinusProvider referenceProvider{};
137 137 auto dataSeries = referenceProvider.provideDataSeries(
138 138 referenceRange, {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 100.}});
139 139
140 140 auto end = dataSeries->cend() - 1;
141 141 qInfo() << dataSeries->nbPoints() << dataSeries->cbegin()->x() << end->x();
142 142
143 143 /// Lambda used to validate a variable at each step
144 144 auto validateVariable
145 145 = [dataSeries](std::shared_ptr<Variable> variable, const SqpRange &range) {
146 146 // Checks that the variable's range has changed
147 qInfo() << "range vs expected range" << variable->range() << range;
147 148 QCOMPARE(variable->range(), range);
148 149
149 150 // Checks the variable's data series
150 151 QVERIFY(checkDataSeries(variable->dataSeries(), variable->cacheRange(), dataSeries));
151 152 };
152 153
153 154 // Creates variable
154 155 QFETCH(SqpRange, initialRange);
155 156 sqpApp->timeController().onTimeToUpdate(initialRange);
156 157 auto provider = std::make_shared<CosinusProvider>();
157 158 auto variable = sqpApp->variableController().createVariable(
158 159 "MMS", {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 100.}}, provider);
159 160
161
160 162 QFETCH(int, operationDelay);
161 163 QTest::qWait(operationDelay);
162 164 validateVariable(variable, initialRange);
163 165
166 QTest::qWait(operationDelay);
164 167 // Makes operations on the variable
165 168 QFETCH(std::vector<SqpRange>, operations);
166 169 for (const auto &operation : operations) {
167 170 // Asks request on the variable and waits during its execution
168 sqpApp->variableController().onRequestDataLoading({variable}, operation, true);
171 sqpApp->variableController().onRequestDataLoading({variable}, operation, false);
169 172
170 173 QTest::qWait(operationDelay);
171 174 validateVariable(variable, operation);
172 175 }
173 176
174 177
175 178 for (const auto &operation : operations) {
176 179 // Asks request on the variable and waits during its execution
177 sqpApp->variableController().onRequestDataLoading({variable}, operation, true);
180 sqpApp->variableController().onRequestDataLoading({variable}, operation, false);
178 181 }
179 182 QTest::qWait(operationDelay);
180 183 validateVariable(variable, operations.back());
181 184 }
182 185
183 186 int main(int argc, char *argv[])
184 187 {
185 188 SqpApplication app{argc, argv};
186 189 app.setAttribute(Qt::AA_Use96Dpi, true);
187 190 TestCosinusAcquisition testObject{};
188 191 QTEST_SET_MAIN_SOURCE_PATH
189 192 return QTest::qExec(&testObject, argc, argv);
190 193 }
191 194
192 195 #include "TestCosinusAcquisition.moc"
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

Merge lasted acquisition developpement on main Sciqlop branch

You need to be logged in to leave comments. Login now