##// END OF EJS Templates
Fixed tests due to async var creation, plus minor stuff...
jeandet -
r30:02d2d8643fcb
parent child
Show More
@@ -1,18 +1,18
1 1 #ifndef SCIQLOP_DATAPROVIDERPARAMETERS_H
2 2 #define SCIQLOP_DATAPROVIDERPARAMETERS_H
3 3
4 4 #include "DateTimeRange.h"
5 5
6 6 /**
7 7 * @brief The DataProviderParameters struct holds the information needed to retrieve data from a
8 8 * data provider
9 9 * @sa IDataProvider
10 10 */
11 11 struct DataProviderParameters {
12 12 /// Times for which retrieve data
13 QVector<DateTimeRange> m_Times;
13 DateTimeRange m_Range;
14 14 /// Extra data that can be used by the provider to retrieve data
15 15 QVariantHash m_Data;
16 16 };
17 17
18 18 #endif // SCIQLOP_DATAPROVIDERPARAMETERS_H
@@ -1,52 +1,51
1 1 #ifndef VARIABLECONTROLLER2_H
2 2 #define VARIABLECONTROLLER2_H
3 3 #include <memory>
4 4 #include <vector>
5 5 #include <set>
6 6 #include <QHash>
7 7 #include <QObject>
8 8 #include <QMutexLocker>
9 9 #include <QUuid>
10 10 #include <QByteArray>
11 11 #include <QItemSelectionModel>
12 12 #include <Common/spimpl.h>
13 13 #include <Variable/Variable.h>
14 14 #include <Data/IDataProvider.h>
15 15 #include "Data/DateTimeRange.h"
16 16
17 17 class VariableController2: public QObject
18 18 {
19 19 class VariableController2Private;
20 20 Q_OBJECT
21 21
22 22 spimpl::unique_impl_ptr<VariableController2Private> impl;
23 23
24 24 public:
25 25 explicit VariableController2();
26 26 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
27 27 const std::shared_ptr<IDataProvider>& provider,
28 28 const DateTimeRange &range);
29 29
30 30 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable);
31 31 void deleteVariable(const std::shared_ptr<Variable>& variable);
32 32 void changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
33 33 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
34 34 const std::vector<std::shared_ptr<Variable>> variables();
35 35
36 36 bool isReady(const std::shared_ptr<Variable>& variable);
37 bool isReady();
38
37 39
38 40 void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with);
39 41
40 42 const std::vector<std::shared_ptr<Variable>> variables(const std::vector<QUuid>& ids);
41 43
42 const std::shared_ptr<Variable>& operator[] (int index) const;
43 std::shared_ptr<Variable> operator[] (int index);
44
45 44
46 45 signals:
47 46 void variableAdded(const std::shared_ptr<Variable>&);
48 47 void variableDeleted(const std::shared_ptr<Variable>&);
49 48
50 49 };
51 50
52 51 #endif //VARIABLECONTROLLER2_H
@@ -1,66 +1,68
1 1 #ifndef SCIQLOP_VARIABLEMODEL2_H
2 2 #define SCIQLOP_VARIABLEMODEL2_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/DateTimeRange.h>
7 7
8 8 #include <QAbstractTableModel>
9 9 #include <QLoggingCategory>
10 10
11 11 #include <Common/MetaTypes.h>
12 12 #include <Common/spimpl.h>
13 13
14 14
15 15
16 16 class IDataSeries;
17 17 class Variable;
18 18 class VariableController2;
19 19
20 20 enum VariableRoles { ProgressRole = Qt::UserRole };
21 21
22 22 /**
23 23 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
24 24 */
25 25 class SCIQLOP_CORE_EXPORT VariableModel2 : public QAbstractTableModel {
26 26 Q_OBJECT
27 27 // read only mirror of VariableController2 content
28 28 std::vector<std::shared_ptr<Variable>> _variables;
29 29 public:
30 30 explicit VariableModel2(QObject *parent = nullptr);
31 31
32 32 // /////////////////////////// //
33 33 // QAbstractTableModel methods //
34 34 // /////////////////////////// //
35 35
36 36 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
37 37 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
38 38 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
39 39 virtual QVariant headerData(int section, Qt::Orientation orientation,
40 40 int role = Qt::DisplayRole) const override;
41 41 virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
42 42
43 43 // ///////////////// //
44 44 // Drag&Drop methods //
45 45 // ///////////////// //
46 46
47 47 virtual Qt::DropActions supportedDropActions() const override;
48 48 virtual Qt::DropActions supportedDragActions() const override;
49 49 virtual QStringList mimeTypes() const override;
50 50 virtual QMimeData *mimeData(const QModelIndexList &indexes) const override;
51 51 virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
52 52 const QModelIndex &parent) const override;
53 53 virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
54 54 const QModelIndex &parent) override;
55 const std::vector<std::shared_ptr<Variable>>& variables() const
56 {return _variables;}
55 57
56 58 signals:
57 59 void createVariable(const QVariantHash &productData);
58 60 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
59 61 public slots:
60 62 /// Slot called when data of a variable has been updated
61 63 void variableUpdated() noexcept;
62 64 void variableAdded(const std::shared_ptr<Variable>&);
63 65 void variableDeleted(const std::shared_ptr<Variable>&);
64 66 };
65 67
66 68 #endif // SCIQLOP_VARIABLEMODEL2_H
@@ -1,390 +1,396
1 1 #include <QQueue>
2 2 #include <QThreadPool>
3 3 #include <QRunnable>
4 4 #include <QObject>
5 5 #include <QDataStream>
6 6
7 7 #include "Variable/VariableController2.h"
8 8 #include "Variable/VariableSynchronizationGroup2.h"
9 9 #include <Common/containers.h>
10 10 #include <Common/debug.h>
11 11 #include <Data/DataProviderParameters.h>
12 12 #include <Data/DateTimeRangeHelper.h>
13 13 #include <Data/DateTimeRange.h>
14 14 #include <Variable/VariableCacheStrategyFactory.h>
15 15 #include <Variable/private/VCTransaction.h>
16 16 #include <QCoreApplication>
17 17
18 18
19 19
20 20 class VariableController2::VariableController2Private
21 21 {
22 22 struct threadSafeVaraiblesMaps
23 23 {
24 24 inline void addVariable(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider, const std::shared_ptr<VariableSynchronizationGroup2>& synchronizationGroup)
25 25 {
26 26 QWriteLocker lock{&_lock};
27 27 _variables[*variable] = variable;
28 28 _providers[*variable] = provider;
29 29 _synchronizationGroups[*variable] = synchronizationGroup;
30 30 }
31 31
32 32 inline void removeVariable(const std::shared_ptr<Variable>& variable)
33 33 {
34 34 QWriteLocker lock{&_lock};
35 35 _variables.erase(*variable);
36 36 _providers.remove(*variable);
37 37 _synchronizationGroups.remove(*variable);
38 38 }
39 39
40 40 inline void synchronize(const std::shared_ptr<Variable>& variable, const std::optional<std::shared_ptr<Variable>>& with)
41 41 {
42 42 QWriteLocker lock{&_lock};
43 43 if(with.has_value())
44 44 {
45 45 auto newGroup = _synchronizationGroups[*with.value()];
46 46 newGroup->addVariable(*variable);
47 47 _synchronizationGroups[*variable] = newGroup;
48 48 }
49 49 else
50 50 {
51 51 _synchronizationGroups[*variable] = std::make_shared<VariableSynchronizationGroup2>(*variable);
52 52 }
53 53 }
54 54
55 55 inline std::shared_ptr<Variable> variable(QUuid variable)
56 56 {
57 57 QReadLocker lock{&_lock};
58 58 auto it = _variables.find(variable);
59 59 [[unlikely]]
60 60 if(it==_variables.end())
61 61 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
62 62 return (*it).second;
63 63 }
64 64
65 65 inline std::shared_ptr<Variable> variable(int index)
66 66 {
67 67 QReadLocker lock{&_lock};
68 68 [[unlikely]]
69 69 if(!_variables.size() > index)
70 70 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Index is out of bounds");
71 71 auto it = _variables.cbegin();
72 72 while (index!=0) {
73 73 index-=1;
74 74 it++;
75 75 }
76 76 return (*it).second;
77 77 }
78 78
79 79 inline const std::vector<std::shared_ptr<Variable>> variables()
80 80 {
81 81 std::vector<std::shared_ptr<Variable>> vars;
82 82 QReadLocker lock{&_lock};
83 83 for(const auto&[id, var]:_variables)
84 84 {
85 85 vars.push_back(var);
86 86 }
87 87 return vars;
88 88 }
89 89
90 90 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
91 91 {
92 92 QReadLocker lock{&_lock};
93 93 [[unlikely]]
94 94 if(!_providers.contains(variable))
95 95 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
96 96 return _providers[variable];
97 97 }
98 98
99 99 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
100 100 {
101 101 QReadLocker lock{&_lock};
102 102 [[unlikely]]
103 103 if(!_synchronizationGroups.contains(variable))
104 104 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
105 105 return _synchronizationGroups[variable];
106 106 }
107 107
108 108 inline bool has(const std::shared_ptr<Variable>& variable)
109 109 {
110 110 QReadLocker lock{&_lock};
111 111 return _variables.find(*variable)==_variables.end();
112 112 }
113 113
114 114 private:
115 115 std::map<QUuid,std::shared_ptr<Variable>> _variables;
116 116 QMap<QUuid,std::shared_ptr<IDataProvider>> _providers;
117 117 QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups;
118 118 QReadWriteLock _lock{QReadWriteLock::Recursive};
119 119 }_maps;
120 120 QThreadPool* _ThreadPool;
121 121 VCTransactionsQueues _transactions;
122 122 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
123 123
124 124 void _transactionComplete(QUuid group, std::shared_ptr<VCTransaction> transaction)
125 125 {
126 126 if(transaction->done())
127 127 {
128 128 _transactions.complete(group);
129 129 }
130 130 this->_processTransactions();
131 131 }
132 132 void _processTransactions()
133 133 {
134 134 auto nextTransactions = _transactions.nextTransactions();
135 135 auto pendingTransactions = _transactions.pendingTransactions();
136 136 for( auto [groupID, newTransaction] : nextTransactions)
137 137 {
138 138 if(newTransaction.has_value() && !pendingTransactions[groupID].has_value())
139 139 {
140 140 _transactions.start(groupID);
141 141 auto refVar = _maps.variable(newTransaction.value()->refVar);
142 142 auto ranges = _computeAllRangesInGroup(refVar,newTransaction.value()->range);
143 143 for( auto const& [ID, range] : ranges)
144 144 {
145 145 auto provider = _maps.provider(ID);
146 146 auto variable = _maps.variable(ID);
147 147 auto [missingRanges, newCacheRange] = _computeMissingRanges(variable,range);
148 148 auto exe = new TransactionExe(variable, provider, missingRanges, range, newCacheRange);
149 149 QObject::connect(exe,
150 150 &TransactionExe::transactionComplete,
151 151 [groupID=groupID,transaction=newTransaction.value(),this]()
152 152 {
153 153 this->_transactionComplete(groupID, transaction);
154 154 }
155 155 );
156 156 _ThreadPool->start(exe);
157 157 }
158 158 }
159 159 }
160 160 }
161 161
162 162 std::map<QUuid,DateTimeRange> _computeAllRangesInGroup(const std::shared_ptr<Variable>& refVar, DateTimeRange r)
163 163 {
164 164 std::map<QUuid,DateTimeRange> ranges;
165 165 if(!DateTimeRangeHelper::hasnan(r))
166 166 {
167 167 auto group = _maps.group(*refVar);
168 168 if(auto transformation = DateTimeRangeHelper::computeTransformation(refVar->range(),r);
169 169 transformation.has_value())
170 170 {
171 171 for(auto varId:group->variables())
172 172 {
173 173 auto var = _maps.variable(varId);
174 174 auto newRange = var->range().transform(transformation.value());
175 175 ranges[varId] = newRange;
176 176 }
177 177 }
178 178 else // force new range to all variables -> may be weird if more than one var in the group
179 179 // @TODO ensure that there is no side effects
180 180 {
181 181 for(auto varId:group->variables())
182 182 {
183 183 auto var = _maps.variable(varId);
184 184 ranges[varId] = r;
185 185 }
186 186 }
187 187 }
188 188 else
189 189 {
190 190 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
191 191 }
192 192 return ranges;
193 193 }
194 194
195 195 std::pair<std::vector<DateTimeRange>,DateTimeRange> _computeMissingRanges(const std::shared_ptr<Variable>& var, DateTimeRange r)
196 196 {
197 197 DateTimeRange newCacheRange;
198 198 std::vector<DateTimeRange> missingRanges;
199 199 if(DateTimeRangeHelper::hasnan(var->cacheRange()))
200 200 {
201 201 newCacheRange = _cacheStrategy->computeRange(r,r);
202 202 missingRanges = {newCacheRange};
203 203 }
204 204 else
205 205 {
206 206 newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r);
207 207 missingRanges = newCacheRange - var->cacheRange();
208 208 }
209 209 return {missingRanges,newCacheRange};
210 210 }
211 211
212 212 void _changeRange(QUuid id, DateTimeRange r)
213 213 {
214 214 _changeRange(_maps.variable(id) ,r);
215 215 }
216 216 void _changeRange(const std::shared_ptr<Variable>& var, DateTimeRange r)
217 217 {
218 218 auto provider = _maps.provider(*var);
219 219 auto [missingRanges, newCacheRange] = _computeMissingRanges(var,r);
220 220 std::vector<IDataSeries*> data;
221 221 for(auto range:missingRanges)
222 222 {
223 223 data.push_back(provider->getData(DataProviderParameters{{range}, var->metadata()}));
224 224 }
225 225 var->updateData(data, r, newCacheRange, true);
226 226 }
227 227 public:
228 228 VariableController2Private(QObject* parent=Q_NULLPTR)
229 229 :_cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(CacheStrategy::SingleThreshold))
230 230 {
231 231 Q_UNUSED(parent);
232 232 this->_ThreadPool = new QThreadPool();
233 233 this->_ThreadPool->setMaxThreadCount(32);
234 234 }
235 235
236 236 /*
237 237 * This dtor has to like this even if this is ugly, because default dtor would rely on
238 238 * declaration order to destruct members and that would always lead to regressions when
239 239 * modifying class members
240 240 */
241 241 ~VariableController2Private()
242 242 {
243 243 delete this->_ThreadPool;
244 244 }
245 245
246 246 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider)
247 247 {
248 248 auto newVar = std::make_shared<Variable>(name,metadata);
249 249 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
250 250 _maps.addVariable(newVar,std::move(provider),group);
251 251 this->_transactions.addEntry(*group);
252 252 return newVar;
253 253 }
254 254
255 255 std::shared_ptr<Variable> variable(QUuid ID)
256 256 {
257 257 return _maps.variable(ID);
258 258 }
259 259
260 260 std::shared_ptr<Variable> variable(int index)
261 261 {
262 262 return _maps.variable(index);
263 263 }
264 264
265 265 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable)
266 266 {
267 267 auto newVar = variable->clone();
268 268 _maps.synchronize(newVar,std::nullopt);
269 269 _maps.addVariable(newVar,_maps.provider(*variable),_maps.group(*newVar));
270 270 this->_transactions.addEntry(*_maps.group(*newVar));
271 271 return newVar;
272 272 }
273 273
274 274 bool hasPendingTransactions(const std::shared_ptr<Variable>& variable)
275 275 {
276 276 return _transactions.active(*_maps.group(*variable));
277 277 }
278 278
279 bool hasPendingTransactions()
280 {
281 bool has = false;
282 for(const auto& var:_maps.variables())
283 {
284 has |= _transactions.active(*_maps.group(*var));
285 }
286 return has;
287 }
288
279 289 void deleteVariable(const std::shared_ptr<Variable>& variable)
280 290 {
281 291 _maps.removeVariable(variable);
282 292 }
283 293
284 294 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
285 295 {
286 296 if(!DateTimeRangeHelper::hasnan(r))
287 297 {
288 298 auto group = _maps.group(*variable);
289 299 // Just overwrite next transaction
290 300 {
291 301 _transactions.enqueue(*group,std::make_shared<VCTransaction>(variable->ID(), r, static_cast<int>(group->variables().size())));
292 302 }
293 303 _processTransactions();
294 304 }
295 305 else
296 306 {
297 307 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
298 308 }
299 309 }
300 310
301 311 void changeRange(const std::shared_ptr<Variable>& variable, DateTimeRange r)
302 312 {
303 313 asyncChangeRange(variable,r);
304 314 while (hasPendingTransactions(variable))
305 315 {
306 316 QCoreApplication::processEvents();
307 317 }
308 318 }
309 319
310 320 inline void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with)
311 321 {
312 322 _maps.synchronize(var, with);
313 323 }
314 324
315 325 inline const std::vector<std::shared_ptr<Variable>> variables()
316 326 {
317 327 return _maps.variables();
318 328 }
319 329
320 330 };
321 331
322 332 VariableController2::VariableController2()
323 333 :impl{spimpl::make_unique_impl<VariableController2Private>()}
324 334 {}
325 335
326 336 std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, const std::shared_ptr<IDataProvider>& provider, const DateTimeRange &range)
327 337 {
328 338 auto var = impl->createVariable(name, metadata, provider);
339 var->setRange(range); // even with no data this is it's range
329 340 emit variableAdded(var);
330 341 if(!DateTimeRangeHelper::hasnan(range))
331 342 impl->asyncChangeRange(var,range);
332 343 else
333 344 SCIQLOP_ERROR(VariableController2, "Creating a variable with default constructed DateTimeRange is an error");
334 345 return var;
335 346 }
336 347
337 348 std::shared_ptr<Variable> VariableController2::cloneVariable(const std::shared_ptr<Variable> &variable)
338 349 {
339 350 return impl->cloneVariable(variable);
340 351 }
341 352
342 353 void VariableController2::deleteVariable(const std::shared_ptr<Variable>& variable)
343 354 {
344 355 impl->deleteVariable(variable);
345 356 emit variableDeleted(variable);
346 357 }
347 358
348 359 void VariableController2::changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
349 360 {
350 361 impl->changeRange(variable, r);
351 362 }
352 363
353 364 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &variable, const DateTimeRange &r)
354 365 {
355 366 impl->asyncChangeRange(variable, r);
356 367 }
357 368
358 369 const std::vector<std::shared_ptr<Variable> > VariableController2::variables()
359 370 {
360 371 return impl->variables();
361 372 }
362 373
363 374 bool VariableController2::isReady(const std::shared_ptr<Variable> &variable)
364 375 {
365 return impl->hasPendingTransactions(variable);
376 return !impl->hasPendingTransactions(variable);
377 }
378
379 bool VariableController2::isReady()
380 {
381 return !impl->hasPendingTransactions();
366 382 }
367 383
368 384 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, const std::shared_ptr<Variable> &with)
369 385 {
370 386 impl->synchronize(var, with);
371 387 }
372 388
373 389 const std::vector<std::shared_ptr<Variable>> VariableController2::variables(const std::vector<QUuid> &ids)
374 390 {
375 391 std::vector<std::shared_ptr<Variable>> variables;
376 392 for (const auto& id : ids) {
377 393 variables.push_back(impl->variable(id));
378 394 }
379 395 return variables;
380 396 }
381
382 const std::shared_ptr<Variable> &VariableController2::operator[](int index) const
383 {
384 return impl->variable (index);
385 }
386
387 std::shared_ptr<Variable> VariableController2::operator[](int index)
388 {
389 return impl->variable (index);
390 }
@@ -1,83 +1,83
1 1 #ifndef TESTPROVIDER_H
2 2 #define TESTPROVIDER_H
3 3
4 4 #include <memory>
5 5 #include <cmath>
6 6 #include <algorithm>
7 7 #include <numeric>
8 8
9 9 #include <QUuid>
10 10 #include <QtGlobal>
11 11 #include <QtTest>
12 12
13 13 #include <Data/IDataProvider.h>
14 14 #include <Data/DataProviderParameters.h>
15 15 #include <Data/DataSeries.h>
16 16 #include <Data/ScalarSeries.h>
17 17 #include <Variable/Variable.h>
18 18
19 19
20 20 template<int slope>
21 21 class SimpleRange: public IDataProvider
22 22 {
23 23 public:
24 24 SimpleRange() = default;
25 25
26 26 int callCounter = 0;
27 27 std::shared_ptr<IDataProvider> clone() const override{ return std::make_shared<SimpleRange>(); }
28 28
29 29 IDataSeries* getData(const DataProviderParameters &parameters) override
30 30 {
31 31 callCounter+=1;
32 auto tstart = parameters.m_Times[0].m_TStart;
33 auto tend = parameters.m_Times[0].m_TEnd;
32 auto tstart = parameters.m_Range.m_TStart;
33 auto tend = parameters.m_Range.m_TEnd;
34 34 std::vector<double> x;
35 35 std::vector<double> y;
36 36 for(double i = ceil(tstart);i<=floor(tend);i+=1.) //1 seconde data resolution
37 37 {
38 38 x.push_back(i);
39 39 y.push_back(i*slope);
40 40 }
41 41 auto serie = new ScalarSeries(std::move(x),std::move(y),Unit("Secondes",true),Unit("Volts",false));
42 42 return serie;
43 43 }
44 44
45 45 };
46 46
47 47
48 48 template <class T>
49 49 auto sumdiff(T begin, T end)
50 50 {
51 51 std::vector<double> diff_vect(end-begin-1);
52 52 auto diff = [](auto next,auto item)
53 53 {
54 54 return next.value() - item.value();
55 55 };
56 56 std::transform (begin+1, end, begin, diff_vect.begin(),diff);
57 57 return std::accumulate(diff_vect.cbegin(), diff_vect.cend(), 0);
58 58 }
59 59
60 60 template <int slope=1>
61 61 struct RangeType
62 62 {
63 63 static void check_properties(std::shared_ptr<Variable> v, DateTimeRange r)
64 64 {
65 65 auto bounds = v->dataSeries()->valuesBounds(r.m_TStart, r.m_TEnd);
66 66 auto s = sumdiff(bounds.first, bounds.second) / slope;
67 67 auto nbpoints = bounds.second - bounds.first+1.;
68 68 QCOMPARE(nbpoints, int(s)+2);//<- @TODO weird has to be investigated why +2?
69 69 QCOMPARE(bounds.first->x(), bounds.first->value()/slope);
70 70 }
71 71 };
72 72
73 73 template <class T>
74 74 void check_variable_state(std::shared_ptr<Variable> v, DateTimeRange r)
75 75 {
76 76 auto bounds = v->dataSeries()->valuesBounds(r.m_TStart, r.m_TEnd);
77 77 //generated data has to be inside range
78 78 QVERIFY(bounds.first->x() >= r.m_TStart);
79 79 QVERIFY(bounds.second->x() <= r.m_TEnd);
80 80 T::check_properties(v,r);
81 81 }
82 82
83 83 #endif
@@ -1,144 +1,146
1 1 #include <cmath>
2 2 #include <algorithm>
3 3 #include <numeric>
4 4 #include <QtTest>
5 5 #include <QObject>
6 6 #include <Variable/VariableController2.h>
7 7 #include <Data/DateTimeRange.h>
8 8 #include <Data/IDataProvider.h>
9 9 #include <Data/ScalarSeries.h>
10 10 #include <Data/DataProviderParameters.h>
11 11 #include <Common/containers.h>
12 12
13 13 #include <TestUtils/TestProviders.h>
14 14
15 15 #define TEST_VC2_FIXTURE(slope) \
16 16 VariableController2 vc; \
17 17 auto provider = std::make_shared<SimpleRange<slope>>();\
18 18
19 19 #define TEST_VC2_CREATE_DEFAULT_VAR(name)\
20 20 auto range = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(14,00),\
21 21 QDate(2018,8,7),QTime(16,00));\
22 22 auto name = vc.createVariable("name", {}, provider, range);\
23 while(!vc.isReady(name))QCoreApplication::processEvents();\
23 24
24 25 Q_DECLARE_METATYPE(DateTimeRangeTransformation);
25 26
26 27
27 28 class TestVariableController2 : public QObject
28 29 {
29 30 Q_OBJECT
30 31 public:
31 32 explicit TestVariableController2(QObject *parent = nullptr) : QObject(parent){}
32 33 signals:
33 34
34 35 private slots:
35 36 void initTestCase(){}
36 37 void cleanupTestCase(){}
37 38
38 39 void testCreateVariable()
39 40 {
40 41 TEST_VC2_FIXTURE(2);
41 42 auto range = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(14,00),
42 43 QDate(2018,8,7),QTime(16,00));
43 44 bool callbackCalled = false;
44 45 connect(&vc,&VariableController2::variableAdded, [&callbackCalled](std::shared_ptr<Variable>){callbackCalled=true;});
45 46 QVERIFY(!callbackCalled);
46 47 auto var1 = vc.createVariable("var1", {}, provider, range);
47 48 QVERIFY(SciQLop::containers::contains(vc.variables(), var1));
48 49 QVERIFY(callbackCalled);
49 50 }
50 51
51 52 void testDeleteVariable()
52 53 {
53 54 TEST_VC2_FIXTURE(1);
54 55 auto range = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(14,00),
55 56 QDate(2018,8,7),QTime(16,00));
56 57 bool callbackCalled = false;
57 58 connect(&vc,&VariableController2::variableDeleted, [&callbackCalled](std::shared_ptr<Variable>){callbackCalled=true;});
58 59 auto var1 = vc.createVariable("var1", {}, provider, range);
60 while(!vc.isReady(var1))QCoreApplication::processEvents();
59 61 QVERIFY(SciQLop::containers::contains(vc.variables(), var1));
60 62 QVERIFY(!callbackCalled);
61 63 vc.deleteVariable(var1);
62 64 QVERIFY(!SciQLop::containers::contains(vc.variables(), var1));
63 65 QVERIFY(callbackCalled);
64 66 }
65 67
66 68 void testGetData()
67 69 {
68 70 TEST_VC2_FIXTURE(10);
69 71 TEST_VC2_CREATE_DEFAULT_VAR(var1);
70 72 check_variable_state<RangeType<10>>(var1, range);
71 73 }
72 74
73 75 void testZoom_data()
74 76 {
75 77 QTest::addColumn<double>("zoom");
76 78 QTest::newRow("Zoom IN 10x") << .1;
77 79 QTest::newRow("Zoom OUT 10x") << 10.;
78 80 QTest::newRow("Zoom IN 1x") << 1.;
79 81 }
80 82 void testZoom()
81 83 {
82 84 TEST_VC2_FIXTURE(100);
83 85 TEST_VC2_CREATE_DEFAULT_VAR(var1);
84 86 check_variable_state<RangeType<100>>(var1, range);
85 87
86 88 QFETCH(double, zoom);
87 89 range *=zoom;
88 90 vc.changeRange(var1, range);
89 91 check_variable_state<RangeType<100>>(var1, range);
90 92 }
91 93
92 94 void testPan_data()
93 95 {
94 96 QTest::addColumn<double>("pan");
95 97 QTest::newRow("Right 1000 seconds") << 1000.;
96 98 QTest::newRow("Left 1000 seconds") << -1000.;
97 99 QTest::newRow("Right 0.1 seconds") << .1;
98 100 QTest::newRow("Left 0.1 seconds") << -.1;
99 101 }
100 102 void testPan()
101 103 {
102 104 TEST_VC2_FIXTURE(10);
103 105 TEST_VC2_CREATE_DEFAULT_VAR(var1);
104 106 check_variable_state<RangeType<10>>(var1, range);
105 107
106 108 QFETCH(double, pan);
107 109
108 110 range += Seconds<double>{pan};
109 111 vc.changeRange(var1, range);
110 112 check_variable_state<RangeType<10>>(var1, range);
111 113 }
112 114
113 115 void testCache_data()
114 116 {
115 117 QTest::addColumn<DateTimeRangeTransformation>("transformation");
116 118 QTest::addColumn<int>("expectedIncrement");
117 119 QTest::newRow("zoom in") << DateTimeRangeTransformation{0.8,Seconds<double>(0.)} << 0;
118 120 QTest::newRow("tiny zoom out") << DateTimeRangeTransformation{1.01,Seconds<double>(0.)} << 0;
119 121 QTest::newRow("just under cache zoom out") << DateTimeRangeTransformation{2.0/1.1,Seconds<double>(0.)} << 0;
120 122 QTest::newRow("just over cache zoom out") << DateTimeRangeTransformation{2.001/1.1, Seconds<double>(0.)} << 2;
121 123 QTest::newRow("tiny pan left") << DateTimeRangeTransformation{1.,Seconds<double>(-100.)} << 0;
122 124 QTest::newRow("tiny pan right") << DateTimeRangeTransformation{1.,Seconds<double>(100.)} << 0;
123 125 }
124 126 void testCache()
125 127 {
126 128 TEST_VC2_FIXTURE(10);
127 129 TEST_VC2_CREATE_DEFAULT_VAR(var1);
128 130 check_variable_state<RangeType<10>>(var1, range);
129 131
130 132 QFETCH(DateTimeRangeTransformation, transformation);
131 133 QFETCH(int, expectedIncrement);
132 134 auto initialCount = provider->callCounter;
133 135 range = range.transform(transformation);
134 136 vc.changeRange(var1, range);
135 137 check_variable_state<RangeType<10>>(var1, range);
136 138 QCOMPARE(provider->callCounter-initialCount, expectedIncrement);
137 139 }
138 140 };
139 141
140 142
141 143 QTEST_MAIN(TestVariableController2)
142 144
143 145 #include "TestVariableController2.moc"
144 146
@@ -1,127 +1,129
1 1 #include <cmath>
2 2 #include <algorithm>
3 3 #include <numeric>
4 4 #include <QtTest>
5 5 #include <QObject>
6 6 #include <Variable/VariableController2.h>
7 7 #include <Data/DateTimeRange.h>
8 8 #include <Data/IDataProvider.h>
9 9 #include <Data/ScalarSeries.h>
10 10 #include <Data/DataProviderParameters.h>
11 11 #include <Common/containers.h>
12 12
13 13 #include <TestUtils/TestProviders.h>
14 14
15 15 #define TEST_VC2_FIXTURE(slope) \
16 16 VariableController2 vc; \
17 17 auto provider = std::make_shared<SimpleRange<slope>>();\
18 18
19 19 #define TEST_VC2_CREATE_DEFAULT_VARS(name1, name2, name3)\
20 20 auto range = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(14,00),\
21 21 QDate(2018,8,7),QTime(16,00));\
22 22 auto name1 = vc.createVariable("name1", {}, provider, range);\
23 while(!vc.isReady(name1))QCoreApplication::processEvents();\
23 24 auto name2 = vc.cloneVariable(name1);\
24 25 auto name3 = vc.cloneVariable(name2);\
25 26 vc.synchronize(name1,name2);\
27 while(!vc.isReady(name1))QCoreApplication::processEvents();\
26 28
27 29
28 30 class TestVariableController2WithSync : public QObject
29 31 {
30 32 Q_OBJECT
31 33 public:
32 34 explicit TestVariableController2WithSync(QObject *parent = nullptr) : QObject(parent){}
33 35 signals:
34 36
35 37 private slots:
36 38 void initTestCase(){}
37 39 void cleanupTestCase(){}
38 40
39 41 void testCreateVariable()
40 42 {
41 43 TEST_VC2_FIXTURE(2);
42 44 auto range = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(14,00),
43 45 QDate(2018,8,7),QTime(16,00));
44 46 bool callbackCalled = false;
45 47 connect(&vc,&VariableController2::variableAdded, [&callbackCalled](std::shared_ptr<Variable>){callbackCalled=true;});
46 48 QVERIFY(!callbackCalled);
47 49 auto var1 = vc.createVariable("var1", {}, provider, range);
48 50 QVERIFY(SciQLop::containers::contains(vc.variables(), var1));
49 51 QVERIFY(callbackCalled);
50 52 }
51 53
52 54 void testDeleteVariable()
53 55 {
54 56 TEST_VC2_FIXTURE(1);
55 57 auto range = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(14,00),
56 58 QDate(2018,8,7),QTime(16,00));
57 59 bool callbackCalled = false;
58 60 connect(&vc,&VariableController2::variableDeleted, [&callbackCalled](std::shared_ptr<Variable>){callbackCalled=true;});
59 61 auto var1 = vc.createVariable("var1", {}, provider, range);
60 62 QVERIFY(SciQLop::containers::contains(vc.variables(), var1));
61 63 QVERIFY(!callbackCalled);
62 64 vc.deleteVariable(var1);
63 65 QVERIFY(!SciQLop::containers::contains(vc.variables(), var1));
64 66 QVERIFY(callbackCalled);
65 67 }
66 68
67 69 void testGetData()
68 70 {
69 71 TEST_VC2_FIXTURE(10);
70 72 TEST_VC2_CREATE_DEFAULT_VARS(var1,var2,var3);
71 73 check_variable_state<RangeType<10>>(var1, range);
72 74 auto newRange = var2->range()*1.5 + Seconds<double>{1000.};
73 75 vc.changeRange(var2, newRange);
74 76 check_variable_state<RangeType<10>>(var1, newRange);
75 77 check_variable_state<RangeType<10>>(var2, newRange);
76 78 check_variable_state<RangeType<10>>(var3, range);
77 79 }
78 80
79 81 void testZoom_data()
80 82 {
81 83 QTest::addColumn<double>("zoom");
82 84 QTest::newRow("Zoom IN 10x") << .1;
83 85 QTest::newRow("Zoom OUT 10x") << 10.;
84 86 QTest::newRow("Zoom IN 1x") << 1.;
85 87 }
86 88 void testZoom()
87 89 {
88 90 TEST_VC2_FIXTURE(100);
89 91 TEST_VC2_CREATE_DEFAULT_VARS(var1,var2,var3);
90 92 check_variable_state<RangeType<100>>(var1, range);
91 93
92 94 QFETCH(double, zoom);
93 95 range *=zoom;
94 96 vc.changeRange(var1, range);
95 97 check_variable_state<RangeType<100>>(var1, range);
96 98 check_variable_state<RangeType<100>>(var2, range);
97 99 }
98 100
99 101 void testPan_data()
100 102 {
101 103 QTest::addColumn<double>("pan");
102 104 QTest::newRow("Right 1000 seconds") << 1000.;
103 105 QTest::newRow("Left 1000 seconds") << -1000.;
104 106 QTest::newRow("Right 0.1 seconds") << .1;
105 107 QTest::newRow("Left 0.1 seconds") << -.1;
106 108 }
107 109 void testPan()
108 110 {
109 111 TEST_VC2_FIXTURE(10);
110 112 TEST_VC2_CREATE_DEFAULT_VARS(var1,var2,var3);
111 113 check_variable_state<RangeType<10>>(var1, range);
112 114
113 115 QFETCH(double, pan);
114 116
115 117 range += Seconds<double>{pan};
116 118 vc.changeRange(var1, range);
117 119 check_variable_state<RangeType<10>>(var1, range);
118 120 check_variable_state<RangeType<10>>(var2, range);
119 121 }
120 122
121 123 };
122 124
123 125
124 126 QTEST_MAIN(TestVariableController2WithSync)
125 127
126 128 #include "TestVariableController2WithSync.moc"
127 129
General Comments 0
You need to be logged in to leave comments. Login now