##// END OF EJS Templates
Removed useless function in Variable class...
jeandet -
r29:ab4890d233e8
parent child
Show More
@@ -1,135 +1,112
1 #ifndef SCIQLOP_VARIABLE_H
1 #ifndef SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
3
3
4 #include <optional>
4 #include <optional>
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8 #include <QUuid>
8 #include <QUuid>
9 #include <QReadWriteLock>
9 #include <QReadWriteLock>
10 #include <QDataStream>
10 #include <QDataStream>
11
11
12 #include "CoreGlobal.h"
12 #include "CoreGlobal.h"
13 #include <Data/DataSeriesIterator.h>
13 #include <Data/DataSeriesIterator.h>
14 #include <Data/DataSeriesType.h>
14 #include <Data/DataSeriesType.h>
15 #include <Data/DateTimeRange.h>
15 #include <Data/DateTimeRange.h>
16
16
17
17
18 #include <Common/deprecate.h>
18 #include <Common/deprecate.h>
19 #include <Common/MetaTypes.h>
19 #include <Common/MetaTypes.h>
20 #include <Common/spimpl.h>
20 #include <Common/spimpl.h>
21
21
22 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
22 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
23
23
24 class IDataSeries;
24 class IDataSeries;
25 class QString;
25 class QString;
26
26
27 /**
27 /**
28 * @brief The Variable class represents a variable in SciQlop.
28 * @brief The Variable class represents a variable in SciQlop.
29 */
29 */
30 class SCIQLOP_CORE_EXPORT Variable : public QObject {
30 class SCIQLOP_CORE_EXPORT Variable : public QObject {
31
31
32 Q_OBJECT
32 Q_OBJECT
33
33
34 public:
34 public:
35 explicit Variable(const QString &name, const QVariantHash &metadata = {});
35 explicit Variable(const QString &name, const QVariantHash &metadata = {});
36
36
37 /// Copy ctor
37 /// Copy ctor
38 explicit Variable(const Variable &other);
38 explicit Variable(const Variable &other);
39
39
40 std::shared_ptr<Variable> clone() const;
40 std::shared_ptr<Variable> clone() const;
41
41
42 QString name() const noexcept;
42 QString name() const noexcept;
43 void setName(const QString &name) noexcept;
43 void setName(const QString &name) noexcept;
44 DateTimeRange range() const noexcept;
44 DateTimeRange range() const noexcept;
45 void setRange(const DateTimeRange &range, bool notify=false) noexcept;
45 void setRange(const DateTimeRange &range, bool notify=false) noexcept;
46 DateTimeRange cacheRange() const noexcept;
46 DateTimeRange cacheRange() const noexcept;
47 void setCacheRange(const DateTimeRange &cacheRange) noexcept;
47 void setCacheRange(const DateTimeRange &cacheRange) noexcept;
48
48
49 /// @return the number of points hold by the variable. The number of points is updated each time
49 /// @return the number of points hold by the variable. The number of points is updated each time
50 /// the data series changes
50 /// the data series changes
51 unsigned int nbPoints() const noexcept;
51 unsigned int nbPoints() const noexcept;
52
52
53 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
53 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
54 /// series between the range of the variable. The real range is updated each time the variable
54 /// series between the range of the variable. The real range is updated each time the variable
55 /// range or the data series changed
55 /// range or the data series changed
56 /// @return the real range, invalid range if the data series is null or empty
56 /// @return the real range, invalid range if the data series is null or empty
57 /// @sa setDataSeries()
57 /// @sa setDataSeries()
58 /// @sa setRange()
58 /// @sa setRange()
59 std::optional<DateTimeRange> realRange() const noexcept;
59 std::optional<DateTimeRange> realRange() const noexcept;
60
60
61 /// @return the data of the variable, nullptr if there is no data
61 /// @return the data of the variable, nullptr if there is no data
62 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
62 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
63
63
64 /// @return the type of data that the variable holds
64 /// @return the type of data that the variable holds
65 DataSeriesType type() const noexcept;
65 DataSeriesType type() const noexcept;
66
66
67 QVariantHash metadata() const noexcept;
67 QVariantHash metadata() const noexcept;
68
68
69 void updateData(const std::vector<IDataSeries*>& dataSeries,
69 void updateData(const std::vector<IDataSeries*>& dataSeries,
70 const DateTimeRange& newRange, const DateTimeRange& newCacheRange,
70 const DateTimeRange& newRange, const DateTimeRange& newCacheRange,
71 bool notify=true);
71 bool notify=true);
72
72
73 static QByteArray mimeData(const std::vector<std::shared_ptr<Variable> > &variables)
73 static QByteArray mimeData(const std::vector<std::shared_ptr<Variable> > &variables)
74 {
74 {
75 auto encodedData = QByteArray{};
75 auto encodedData = QByteArray{};
76 QDataStream stream{&encodedData, QIODevice::WriteOnly};
76 QDataStream stream{&encodedData, QIODevice::WriteOnly};
77 for (auto &var : variables) {
77 for (auto &var : variables) {
78 stream << var->ID().toByteArray();
78 stream << var->ID().toByteArray();
79 }
79 }
80 return encodedData;
80 return encodedData;
81 }
81 }
82
82
83 static std::vector<QUuid> variablesIDs(QByteArray mimeData)
83 static std::vector<QUuid> variablesIDs(QByteArray mimeData)
84 {
84 {
85 std::vector<QUuid> variables;
85 std::vector<QUuid> variables;
86 QDataStream stream{mimeData};
86 QDataStream stream{mimeData};
87
87
88 QVariantList ids;
88 QVariantList ids;
89 stream >> ids;
89 stream >> ids;
90
90
91 for (const auto& id : ids) {
91 for (const auto& id : ids) {
92 variables.emplace_back (id.toByteArray());
92 variables.emplace_back (id.toByteArray());
93 }
93 }
94 return variables;
94 return variables;
95 }
95 }
96
96
97 DEPRECATE(
98
99 bool contains(const DateTimeRange &range) const noexcept;
100 bool intersect(const DateTimeRange &range) const noexcept;
101 bool isInside(const DateTimeRange &range) const noexcept;
102
103 bool cacheContains(const DateTimeRange &range) const noexcept;
104 bool cacheIntersect(const DateTimeRange &range) const noexcept;
105 bool cacheIsInside(const DateTimeRange &range) const noexcept;
106 QVector<DateTimeRange> provideNotInCacheRangeList(const DateTimeRange &range) const noexcept;
107 QVector<DateTimeRange> provideInCacheRangeList(const DateTimeRange &range) const noexcept;
108 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
109 static QVector<DateTimeRange> provideNotInCacheRangeList(const DateTimeRange &oldRange,
110 const DateTimeRange &nextRange);
111
112 static QVector<DateTimeRange> provideInCacheRangeList(const DateTimeRange &oldRange,
113 const DateTimeRange &nextRange);
114 )
115
116 operator QUuid() {return _uuid;}
97 operator QUuid() {return _uuid;}
117 QUuid ID(){return _uuid;}
98 QUuid ID(){return _uuid;}
118 signals:
99 signals:
119 void updated();
100 void updated();
120 DEPRECATE(
121 /// Signal emitted when when the data series of the variable is loaded for the first time
122 void dataInitialized();
123 )
124 private:
101 private:
125 class VariablePrivate;
102 class VariablePrivate;
126 spimpl::unique_impl_ptr<VariablePrivate> impl;
103 spimpl::unique_impl_ptr<VariablePrivate> impl;
127 QUuid _uuid;
104 QUuid _uuid;
128 QReadWriteLock m_lock;
105 QReadWriteLock m_lock;
129 };
106 };
130
107
131 // Required for using shared_ptr in signals/slots
108 // Required for using shared_ptr in signals/slots
132 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
109 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
133 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
110 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
134
111
135 #endif // SCIQLOP_VARIABLE_H
112 #endif // SCIQLOP_VARIABLE_H
@@ -1,436 +1,214
1 #include <optional>
1 #include <optional>
2 #include <QMutex>
2 #include <QMutex>
3 #include <QReadWriteLock>
3 #include <QReadWriteLock>
4 #include <QThread>
4 #include <QThread>
5
5
6 #include "Variable/Variable.h"
6 #include "Variable/Variable.h"
7
7
8 #include <Data/IDataSeries.h>
8 #include <Data/IDataSeries.h>
9 #include <Data/DateTimeRange.h>
9 #include <Data/DateTimeRange.h>
10
10
11 #include <Common/debug.h>
11 #include <Common/debug.h>
12
12
13 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
13 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
14
14
15
15
16 /**
16 /**
17 * Searches in metadata for a value that can be converted to DataSeriesType
17 * Searches in metadata for a value that can be converted to DataSeriesType
18 * @param metadata the metadata where to search
18 * @param metadata the metadata where to search
19 * @return the value converted to a DataSeriesType if it was found, UNKNOWN type otherwise
19 * @return the value converted to a DataSeriesType if it was found, UNKNOWN type otherwise
20 * @sa DataSeriesType
20 * @sa DataSeriesType
21 */
21 */
22 static DataSeriesType findDataSeriesType(const QVariantHash &metadata)
22 static DataSeriesType findDataSeriesType(const QVariantHash &metadata)
23 {
23 {
24 auto dataSeriesType = DataSeriesType::UNKNOWN;
24 auto dataSeriesType = DataSeriesType::UNKNOWN;
25
25
26 // Go through the metadata and stop at the first value that could be converted to DataSeriesType
26 // Go through the metadata and stop at the first value that could be converted to DataSeriesType
27 for (auto it = metadata.cbegin(), end = metadata.cend();
27 for (auto it = metadata.cbegin(), end = metadata.cend();
28 it != end && dataSeriesType == DataSeriesType::UNKNOWN; ++it) {
28 it != end && dataSeriesType == DataSeriesType::UNKNOWN; ++it) {
29 dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString());
29 dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString());
30 }
30 }
31
31
32 return dataSeriesType;
32 return dataSeriesType;
33 }
33 }
34
34
35
35
36 #define VP_PROPERTY(property,getter,setter,type) \
36 #define VP_PROPERTY(property,getter,setter,type) \
37 type getter() noexcept\
37 type getter() noexcept\
38 {\
38 {\
39 QReadLocker lock{&m_Lock};\
39 QReadLocker lock{&m_Lock};\
40 return property;\
40 return property;\
41 }\
41 }\
42 void setter(const type& getter) noexcept\
42 void setter(const type& getter) noexcept\
43 {\
43 {\
44 QWriteLocker lock{&m_Lock};\
44 QWriteLocker lock{&m_Lock};\
45 property = getter;\
45 property = getter;\
46 }\
46 }\
47 type property;\
47 type property;\
48
48
49 #define V_FW_GETTER_SETTER(getter,setter, type)\
49 #define V_FW_GETTER_SETTER(getter,setter, type)\
50 type Variable::getter() const noexcept \
50 type Variable::getter() const noexcept \
51 {\
51 {\
52 return impl->getter();\
52 return impl->getter();\
53 }\
53 }\
54 void Variable::setter(const type& getter) noexcept \
54 void Variable::setter(const type& getter) noexcept \
55 {\
55 {\
56 impl->setter(getter);\
56 impl->setter(getter);\
57 emit updated();\
57 }\
58 }\
58
59
59 struct Variable::VariablePrivate {
60 struct Variable::VariablePrivate {
60 explicit VariablePrivate(const QString &name, const QVariantHash &metadata)
61 explicit VariablePrivate(const QString &name, const QVariantHash &metadata)
61 : m_Name{name},
62 : m_Name{name},
62 m_Range{INVALID_RANGE},
63 m_Range{INVALID_RANGE},
63 m_CacheRange{INVALID_RANGE},
64 m_CacheRange{INVALID_RANGE},
64 m_Metadata{metadata},
65 m_Metadata{metadata},
65 m_DataSeries{nullptr},
66 m_DataSeries{nullptr},
66 m_RealRange{INVALID_RANGE},
67 m_RealRange{INVALID_RANGE},
67 m_NbPoints{0},
68 m_NbPoints{0},
68 m_Type{findDataSeriesType(m_Metadata)}
69 m_Type{findDataSeriesType(m_Metadata)}
69 {
70 {
70 }
71 }
71
72
72 VariablePrivate(const VariablePrivate &other)
73 VariablePrivate(const VariablePrivate &other)
73 : m_Name{other.m_Name},
74 : m_Name{other.m_Name},
74 m_Range{other.m_Range},
75 m_Range{other.m_Range},
75 m_CacheRange{other.m_CacheRange},
76 m_CacheRange{other.m_CacheRange},
76 m_Metadata{other.m_Metadata},
77 m_Metadata{other.m_Metadata},
77 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
78 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
78 m_RealRange{other.m_RealRange},
79 m_RealRange{other.m_RealRange},
79 m_NbPoints{other.m_NbPoints},
80 m_NbPoints{other.m_NbPoints},
80 m_Type{findDataSeriesType(m_Metadata)}
81 m_Type{findDataSeriesType(m_Metadata)}
81 {
82 {
82 }
83 }
83
84
84 void lockRead() { m_Lock.lockForRead(); }
85 void lockRead() { m_Lock.lockForRead(); }
85 void lockWrite() { m_Lock.lockForWrite(); }
86 void lockWrite() { m_Lock.lockForWrite(); }
86 void unlock() { m_Lock.unlock(); }
87 void unlock() { m_Lock.unlock(); }
87
88
88 void purgeDataSeries()
89 void purgeDataSeries()
89 {
90 {
90 if (m_DataSeries) {
91 if (m_DataSeries) {
91 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
92 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
92 }
93 }
93 updateRealRange();
94 updateRealRange();
94 updateNbPoints();
95 updateNbPoints();
95 }
96 }
96 void mergeDataSeries(const std::vector<IDataSeries*>& dataseries)
97 void mergeDataSeries(const std::vector<IDataSeries*>& dataseries)
97 {
98 {
98 QWriteLocker lock{&m_Lock};
99 QWriteLocker lock{&m_Lock};
99 for(auto ds:dataseries)
100 for(auto ds:dataseries)
100 {
101 {
101 if(m_DataSeries)
102 if(m_DataSeries)
102 m_DataSeries->merge(ds);
103 m_DataSeries->merge(ds);
103 else
104 else
104 m_DataSeries = ds->clone();
105 m_DataSeries = ds->clone();
105 }
106 }
106 }
107 }
107 void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
108 void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
108
109
109 /// Updates real range according to current variable range and data series
110 /// Updates real range according to current variable range and data series
110 void updateRealRange()
111 void updateRealRange()
111 {
112 {
112 if (m_DataSeries) {
113 if (m_DataSeries) {
113 auto lock = m_DataSeries->getReadLock();
114 auto lock = m_DataSeries->getReadLock();
114 auto end = m_DataSeries->cend();
115 auto end = m_DataSeries->cend();
115 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
116 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
116 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
117 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
117 if(minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x())
118 if(minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x())
118 m_RealRange = DateTimeRange{minXAxisIt->x(), maxXAxisIt->x()};
119 m_RealRange = DateTimeRange{minXAxisIt->x(), maxXAxisIt->x()};
119 else
120 else
120 m_RealRange = std::nullopt;
121 m_RealRange = std::nullopt;
121 }
122 }
122 else {
123 else {
123 m_RealRange = std::nullopt;
124 m_RealRange = std::nullopt;
124 }
125 }
125 }
126 }
126
127
127 VP_PROPERTY(m_Name, name, setName, QString)
128 VP_PROPERTY(m_Name, name, setName, QString)
128 VP_PROPERTY(m_Range, range, setRange, DateTimeRange)
129 VP_PROPERTY(m_Range, range, setRange, DateTimeRange)
129 VP_PROPERTY(m_CacheRange, cacheRange, setCacheRange, DateTimeRange)
130 VP_PROPERTY(m_CacheRange, cacheRange, setCacheRange, DateTimeRange)
130 VP_PROPERTY(m_Metadata, metadata, setMetadata, QVariantHash)
131 VP_PROPERTY(m_Metadata, metadata, setMetadata, QVariantHash)
131 VP_PROPERTY(m_DataSeries, dataSeries, setDataSeries, std::shared_ptr<IDataSeries>)
132 VP_PROPERTY(m_DataSeries, dataSeries, setDataSeries, std::shared_ptr<IDataSeries>)
132 VP_PROPERTY(m_RealRange, realRange, setRealRange, std::optional<DateTimeRange>)
133 VP_PROPERTY(m_RealRange, realRange, setRealRange, std::optional<DateTimeRange>)
133 unsigned int m_NbPoints;
134 unsigned int m_NbPoints;
134 VP_PROPERTY(m_Type, type, setType, DataSeriesType)
135 VP_PROPERTY(m_Type, type, setType, DataSeriesType)
135 QReadWriteLock m_Lock;
136 QReadWriteLock m_Lock;
136 };
137 };
137
138
138 Variable::Variable(const QString &name, const QVariantHash &metadata)
139 Variable::Variable(const QString &name, const QVariantHash &metadata)
139 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)},
140 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)},
140 _uuid{QUuid::createUuid()}
141 _uuid{QUuid::createUuid()}
141 {
142 {
142 }
143 }
143
144
144 Variable::Variable(const Variable &other)
145 Variable::Variable(const Variable &other)
145 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)},
146 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)},
146 _uuid{QUuid::createUuid()} //is a clone but must have a != uuid
147 _uuid{QUuid::createUuid()} //is a clone but must have a != uuid
147 {
148 {
148 }
149 }
149
150
150 std::shared_ptr<Variable> Variable::clone() const
151 std::shared_ptr<Variable> Variable::clone() const
151 {
152 {
152 return std::make_shared<Variable>(*this);
153 return std::make_shared<Variable>(*this);
153 }
154 }
154
155
155 V_FW_GETTER_SETTER(name,setName,QString)
156 V_FW_GETTER_SETTER(name,setName,QString)
156
157
157 DateTimeRange Variable::range() const noexcept
158 DateTimeRange Variable::range() const noexcept
158 {
159 {
159 return impl->range();
160 return impl->range();
160 }
161 }
161
162
162 void Variable::setRange(const DateTimeRange &range, bool notify) noexcept
163 void Variable::setRange(const DateTimeRange &range, bool notify) noexcept
163 {
164 {
164 impl->setRange(range);
165 impl->setRange(range);
165 impl->updateRealRange();
166 impl->updateRealRange();
166 if(notify)
167 if(notify)
167 emit this->updated();
168 emit this->updated();
168 }
169 }
169
170
170 V_FW_GETTER_SETTER(cacheRange, setCacheRange, DateTimeRange)
171 V_FW_GETTER_SETTER(cacheRange, setCacheRange, DateTimeRange)
171
172
172 unsigned int Variable::nbPoints() const noexcept
173 unsigned int Variable::nbPoints() const noexcept
173 {
174 {
174 return impl->m_NbPoints;
175 return impl->m_NbPoints;
175 }
176 }
176
177
177 std::optional<DateTimeRange> Variable::realRange() const noexcept
178 std::optional<DateTimeRange> Variable::realRange() const noexcept
178 {
179 {
179 return impl->realRange();
180 return impl->realRange();
180 }
181 }
181
182
182 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
183 {
184 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
185 << QThread::currentThread()->objectName();
186 if (!dataSeries) {
187 /// @todo ALX : log
188 return;
189 }
190
191 auto dataInit = false;
192
193 // Add or merge the data
194 impl->lockWrite();
195 if (!impl->m_DataSeries) {
196 impl->m_DataSeries = dataSeries->clone();
197 dataInit = true;
198 }
199 else {
200 impl->m_DataSeries->merge(dataSeries.get());
201 }
202 impl->purgeDataSeries();
203 impl->unlock();
204
205 if (dataInit) {
206 emit dataInitialized();
207 }
208 }
209
210 void Variable::updateData(const std::vector<IDataSeries *> &dataSeries, const DateTimeRange &newRange, const DateTimeRange &newCacheRange, bool notify)
183 void Variable::updateData(const std::vector<IDataSeries *> &dataSeries, const DateTimeRange &newRange, const DateTimeRange &newCacheRange, bool notify)
211 {
184 {
212 {
185 {
213 QWriteLocker lock{&m_lock};
186 QWriteLocker lock{&m_lock};
214 impl->mergeDataSeries(dataSeries);
187 impl->mergeDataSeries(dataSeries);
215 impl->setRange(newRange);
188 impl->setRange(newRange);
216 impl->setCacheRange(newCacheRange);
189 impl->setCacheRange(newCacheRange);
217 impl->purgeDataSeries();
190 impl->purgeDataSeries();
218 }
191 }
219 if(notify)
192 if(notify)
220 emit updated();
193 emit updated();
221 }
194 }
222
195
223
196
224 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
197 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
225 {
198 {
226 return impl->dataSeries();
199 return impl->dataSeries();
227 }
200 }
228
201
229 DataSeriesType Variable::type() const noexcept
202 DataSeriesType Variable::type() const noexcept
230 {
203 {
231 return impl->type();
204 return impl->type();
232 }
205 }
233
206
234 QVariantHash Variable::metadata() const noexcept
207 QVariantHash Variable::metadata() const noexcept
235 {
208 {
236 impl->lockRead();
209 impl->lockRead();
237 auto metadata = impl->m_Metadata;
210 auto metadata = impl->m_Metadata;
238 impl->unlock();
211 impl->unlock();
239 return metadata;
212 return metadata;
240 }
213 }
241
214
242 bool Variable::contains(const DateTimeRange &range) const noexcept
243 {
244 impl->lockRead();
245 auto res = impl->m_Range.contains(range);
246 impl->unlock();
247 return res;
248 }
249
250 bool Variable::intersect(const DateTimeRange &range) const noexcept
251 {
252
253 impl->lockRead();
254 auto res = impl->m_Range.intersect(range);
255 impl->unlock();
256 return res;
257 }
258
259 bool Variable::isInside(const DateTimeRange &range) const noexcept
260 {
261 impl->lockRead();
262 auto res = range.contains(DateTimeRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
263 impl->unlock();
264 return res;
265 }
266
267 bool Variable::cacheContains(const DateTimeRange &range) const noexcept
268 {
269 impl->lockRead();
270 auto res = impl->m_CacheRange.contains(range);
271 impl->unlock();
272 return res;
273 }
274
275 bool Variable::cacheIntersect(const DateTimeRange &range) const noexcept
276 {
277 impl->lockRead();
278 auto res = impl->m_CacheRange.intersect(range);
279 impl->unlock();
280 return res;
281 }
282
283 bool Variable::cacheIsInside(const DateTimeRange &range) const noexcept
284 {
285 impl->lockRead();
286 auto res = range.contains(DateTimeRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
287 impl->unlock();
288 return res;
289 }
290
291
292 QVector<DateTimeRange> Variable::provideNotInCacheRangeList(const DateTimeRange &range) const noexcept
293 {
294 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
295 auto notInCache = QVector<DateTimeRange>{};
296 if (impl->m_CacheRange != INVALID_RANGE) {
297
298 if (!this->cacheContains(range)) {
299 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
300 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
301 notInCache << range;
302 }
303 else if (range.m_TStart < impl->m_CacheRange.m_TStart
304 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
305 notInCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TStart};
306 }
307 else if (range.m_TStart < impl->m_CacheRange.m_TStart
308 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
309 notInCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TStart}
310 << DateTimeRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
311 }
312 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
313 notInCache << DateTimeRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
314 }
315 else {
316 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
317 << QThread::currentThread();
318 }
319 }
320 }
321 else {
322 notInCache << range;
323 }
324
325 return notInCache;
326 }
327
328 QVector<DateTimeRange> Variable::provideInCacheRangeList(const DateTimeRange &range) const noexcept
329 {
330 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
331
332 auto inCache = QVector<DateTimeRange>{};
333
334 if (impl->m_CacheRange != INVALID_RANGE) {
335
336 if (this->cacheIntersect(range)) {
337 if (range.m_TStart <= impl->m_CacheRange.m_TStart
338 && range.m_TEnd >= impl->m_CacheRange.m_TStart
339 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
340 inCache << DateTimeRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
341 }
342
343 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
344 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
345 inCache << range;
346 }
347 else if (range.m_TStart > impl->m_CacheRange.m_TStart
348 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
349 inCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
350 }
351 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
352 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
353 inCache << impl->m_CacheRange;
354 }
355 else {
356 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
357 << QThread::currentThread();
358 }
359 }
360 }
361
362 return inCache;
363 }
364
365
366 QVector<DateTimeRange> Variable::provideNotInCacheRangeList(const DateTimeRange &oldRange,
367 const DateTimeRange &nextRange)
368 {
369
370 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
371 auto notInCache = QVector<DateTimeRange>{};
372 if (oldRange != INVALID_RANGE) {
373
374 if (!oldRange.contains(nextRange)) {
375 if (nextRange.m_TEnd <= oldRange.m_TStart || nextRange.m_TStart >= oldRange.m_TEnd) {
376 notInCache << nextRange;
377 }
378 else if (nextRange.m_TStart < oldRange.m_TStart
379 && nextRange.m_TEnd <= oldRange.m_TEnd) {
380 notInCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TStart};
381 }
382 else if (nextRange.m_TStart < oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
383 notInCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TStart}
384 << DateTimeRange{oldRange.m_TEnd, nextRange.m_TEnd};
385 }
386 else if (nextRange.m_TStart < oldRange.m_TEnd) {
387 notInCache << DateTimeRange{oldRange.m_TEnd, nextRange.m_TEnd};
388 }
389 else {
390 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
391 << QThread::currentThread();
392 }
393 }
394 }
395 else {
396 notInCache << nextRange;
397 }
398
399 return notInCache;
400 }
401
402 QVector<DateTimeRange> Variable::provideInCacheRangeList(const DateTimeRange &oldRange,
403 const DateTimeRange &nextRange)
404 {
405 // This code assume that cach is contigue. Can return 0 or 1 SqpRange
406
407 auto inCache = QVector<DateTimeRange>{};
408
409 if (oldRange != INVALID_RANGE) {
410
411 if (oldRange.intersect(nextRange)) {
412 if (nextRange.m_TStart <= oldRange.m_TStart && nextRange.m_TEnd >= oldRange.m_TStart
413 && nextRange.m_TEnd < oldRange.m_TEnd) {
414 inCache << DateTimeRange{oldRange.m_TStart, nextRange.m_TEnd};
415 }
416
417 else if (nextRange.m_TStart >= oldRange.m_TStart
418 && nextRange.m_TEnd <= oldRange.m_TEnd) {
419 inCache << nextRange;
420 }
421 else if (nextRange.m_TStart > oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
422 inCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TEnd};
423 }
424 else if (nextRange.m_TStart <= oldRange.m_TStart
425 && nextRange.m_TEnd >= oldRange.m_TEnd) {
426 inCache << oldRange;
427 }
428 else {
429 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
430 << QThread::currentThread();
431 }
432 }
433 }
434
435 return inCache;
436 }
@@ -1,410 +1,23
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2
2
3 #include <Data/ScalarSeries.h>
3 #include <Data/ScalarSeries.h>
4
4
5 #include <QObject>
5 #include <QObject>
6 #include <QtTest>
6 #include <QtTest>
7
7
8 #include <memory>
8 #include <memory>
9
9
10 namespace {
11
10
12 /// Generates a date in double
13 auto date = [](int year, int month, int day, int hours, int minutes, int seconds) {
14 return DateUtils::secondsSinceEpoch(
15 QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC});
16 };
17
18 /// Generates a series of test data for a range
19 std::shared_ptr<ScalarSeries> dataSeries(const DateTimeRange &range)
20 {
21 auto xAxisData = std::vector<double>{};
22 auto valuesData = std::vector<double>{};
23
24 auto value = 0;
25 for (auto x = range.m_TStart; x <= range.m_TEnd; ++x, ++value) {
26 xAxisData.push_back(x);
27 valuesData.push_back(value);
28 }
29
30 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData), Unit{},
31 Unit{});
32 }
33
34 } // namespace
35
36 Q_DECLARE_METATYPE(std::shared_ptr<ScalarSeries>)
37
11
38 class TestVariable : public QObject {
12 class TestVariable : public QObject {
39 Q_OBJECT
13 Q_OBJECT
40
14
41 private slots:
15 private slots:
42 void initTestCase() { QSKIP("Skip it"); }
16 void initTestCase() { QSKIP("Please Write me! .·´¯`(>β–‚<)´¯`Β·. "); }
43 void testClone_data();
44 void testClone();
45
46 void testNotInCacheRangeList();
47 void testInCacheRangeList();
48
49 void testNbPoints_data();
50 void testNbPoints();
51
52 void testRealRange_data();
53 void testRealRange();
54 };
17 };
55
18
56 void TestVariable::testClone_data()
57 {
58 // ////////////// //
59 // Test structure //
60 // ////////////// //
61
62 QTest::addColumn<QString>("name");
63 QTest::addColumn<QVariantHash>("metadata");
64 QTest::addColumn<DateTimeRange>("range");
65 QTest::addColumn<DateTimeRange>("cacheRange");
66 QTest::addColumn<std::shared_ptr<ScalarSeries> >("dataSeries");
67
68 // ////////// //
69 // Test cases //
70 // ////////// //
71
72 auto cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 13, 0, 0)};
73 QTest::newRow("clone1") << QStringLiteral("var1")
74 << QVariantHash{{"data1", 1}, {"data2", "abc"}}
75 << DateTimeRange{date(2017, 1, 1, 12, 30, 0), (date(2017, 1, 1, 12, 45, 0))}
76 << cacheRange << dataSeries(cacheRange);
77 }
78
79 void TestVariable::testClone()
80 {
81 // Creates variable
82 QFETCH(QString, name);
83 QFETCH(QVariantHash, metadata);
84 QFETCH(DateTimeRange, range);
85 QFETCH(DateTimeRange, cacheRange);
86 QFETCH(std::shared_ptr<ScalarSeries>, dataSeries);
87
88 Variable variable{name, metadata};
89 variable.setRange(range);
90 variable.setCacheRange(cacheRange);
91 variable.mergeDataSeries(dataSeries);
92
93 // Clones variable
94 auto clone = variable.clone();
95
96 // Checks cloned variable's state
97 QCOMPARE(clone->name(), name);
98 QCOMPARE(clone->metadata(), metadata);
99 QCOMPARE(clone->range(), range);
100 QCOMPARE(clone->cacheRange(), cacheRange);
101
102 // Compares data series
103 if (dataSeries != nullptr) {
104 QVERIFY(clone->dataSeries() != nullptr);
105 QVERIFY(std::equal(dataSeries->cbegin(), dataSeries->cend(), clone->dataSeries()->cbegin(),
106 clone->dataSeries()->cend(), [](const auto &it1, const auto &it2) {
107 return it1.x() == it2.x() && it1.value() == it2.value();
108 }));
109 }
110 else {
111 QVERIFY(clone->dataSeries() == nullptr);
112 }
113 }
114
115 void TestVariable::testNotInCacheRangeList()
116 {
117 auto varRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
118 auto varRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 40, 0}};
119
120 auto sqpR = DateTimeRange{DateUtils::secondsSinceEpoch(varRS), DateUtils::secondsSinceEpoch(varRE)};
121
122 auto varCRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}};
123 auto varCRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
124
125 auto sqpCR
126 = DateTimeRange{DateUtils::secondsSinceEpoch(varCRS), DateUtils::secondsSinceEpoch(varCRE)};
127
128 Variable var{"Var test"};
129 var.setRange(sqpR);
130 var.setCacheRange(sqpCR);
131
132 // 1: [ts,te] < varTS
133 auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
134 auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}};
135 auto sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
136
137 auto notInCach = var.provideNotInCacheRangeList(sqp);
138
139 QCOMPARE(notInCach.size(), 1);
140
141 auto notInCachRange = notInCach.first();
142
143 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
144 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
145
146 // 2: ts < varTS < te < varTE
147 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
148 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
149 sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
150 notInCach = var.provideNotInCacheRangeList(sqp);
151 QCOMPARE(notInCach.size(), 1);
152 notInCachRange = notInCach.first();
153 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
154 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRS));
155
156 // 3: varTS < ts < te < varTE
157 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
158 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
159 sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
160 notInCach = var.provideNotInCacheRangeList(sqp);
161 QCOMPARE(notInCach.size(), 0);
162
163
164 // 4: varTS < ts < varTE < te
165 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
166 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
167 sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
168 notInCach = var.provideNotInCacheRangeList(sqp);
169 QCOMPARE(notInCach.size(), 1);
170 notInCachRange = notInCach.first();
171 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRE));
172 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
173
174 // 5: varTS < varTE < ts < te
175 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 20, 0}};
176 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
177 sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
178 notInCach = var.provideNotInCacheRangeList(sqp);
179 QCOMPARE(notInCach.size(), 1);
180 notInCachRange = notInCach.first();
181 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
182 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
183
184 // 6: ts <varTS < varTE < te
185 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}};
186 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
187 sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
188 notInCach = var.provideNotInCacheRangeList(sqp);
189 QCOMPARE(notInCach.size(), 2);
190 notInCachRange = notInCach.first();
191 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
192 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRS));
193 notInCachRange = notInCach[1];
194 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRE));
195 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
196 }
197
198
199 void TestVariable::testInCacheRangeList()
200 {
201 auto varRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
202 auto varRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 40, 0}};
203
204 auto sqpR = DateTimeRange{DateUtils::secondsSinceEpoch(varRS), DateUtils::secondsSinceEpoch(varRE)};
205
206 auto varCRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}};
207 auto varCRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
208 auto sqpCR
209 = DateTimeRange{DateUtils::secondsSinceEpoch(varCRS), DateUtils::secondsSinceEpoch(varCRE)};
210
211 Variable var{"Var test"};
212 var.setRange(sqpR);
213 var.setCacheRange(sqpCR);
214
215 // 1: [ts,te] < varTS
216 auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
217 auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}};
218 auto sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
219
220 auto notInCach = var.provideInCacheRangeList(sqp);
221
222 QCOMPARE(notInCach.size(), 0);
223
224 // 2: ts < varTS < te < varTE
225 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
226 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
227 sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
228 notInCach = var.provideInCacheRangeList(sqp);
229 QCOMPARE(notInCach.size(), 1);
230 auto notInCachRange = notInCach.first();
231 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRS));
232 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
233
234 // 3: varTS < ts < te < varTE
235 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
236 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
237 sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
238 notInCach = var.provideInCacheRangeList(sqp);
239 QCOMPARE(notInCach.size(), 1);
240 notInCachRange = notInCach.first();
241 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
242 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
243
244 // 4: varTS < ts < varTE < te
245 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
246 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
247 sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
248 notInCach = var.provideInCacheRangeList(sqp);
249 QCOMPARE(notInCach.size(), 1);
250 notInCachRange = notInCach.first();
251 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
252 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRE));
253
254 // 5: varTS < varTE < ts < te
255 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 20, 0}};
256 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
257 sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
258 notInCach = var.provideInCacheRangeList(sqp);
259 QCOMPARE(notInCach.size(), 0);
260
261 // 6: ts <varTS < varTE < te
262 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}};
263 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
264 sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
265 notInCach = var.provideInCacheRangeList(sqp);
266 QCOMPARE(notInCach.size(), 1);
267 notInCachRange = notInCach.first();
268 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRS));
269 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRE));
270 }
271
272 namespace {
273
274 /// Struct used to represent an operation for @sa TestVariable::testNbPoints()
275 struct NbPointsOperation {
276 DateTimeRange m_CacheRange; /// Range to set for the variable
277 std::shared_ptr<ScalarSeries> m_DataSeries; /// Series to merge in the variable
278 int m_ExpectedNbPoints; /// Number of points in the variable expected after operation
279 };
280
281 using NbPointsOperations = std::vector<NbPointsOperation>;
282
283 } // namespace
284
285 Q_DECLARE_METATYPE(NbPointsOperations)
286
287 void TestVariable::testNbPoints_data()
288 {
289 // ////////////// //
290 // Test structure //
291 // ////////////// //
292
293 QTest::addColumn<NbPointsOperations>("operations");
294
295 // ////////// //
296 // Test cases //
297 // ////////// //
298 NbPointsOperations operations{};
299
300 // Sets cache range (expected nb points = values data)
301 auto cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 9)};
302 operations.push_back({cacheRange, dataSeries(cacheRange), 10});
303
304 // Doubles cache but don't add data series (expected nb points don't change)
305 cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)};
306 operations.push_back({cacheRange, dataSeries(INVALID_RANGE), 10});
307
308 // Doubles cache and data series (expected nb points change)
309 cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)};
310 operations.push_back({cacheRange, dataSeries(cacheRange), 20});
311
312 // Decreases cache (expected nb points decreases as the series is purged)
313 cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 5), date(2017, 1, 1, 12, 0, 9)};
314 operations.push_back({cacheRange, dataSeries(INVALID_RANGE), 5});
315
316 QTest::newRow("nbPoints1") << operations;
317 }
318
319 void TestVariable::testNbPoints()
320 {
321 // Creates variable
322 Variable variable{"var"};
323 QCOMPARE(variable.nbPoints(), 0);
324
325 QFETCH(NbPointsOperations, operations);
326 for (const auto &operation : operations) {
327 // Sets cache range and merge data series
328 variable.setCacheRange(operation.m_CacheRange);
329 if (operation.m_DataSeries != nullptr) {
330 variable.mergeDataSeries(operation.m_DataSeries);
331 }
332
333 // Checks nb points
334 QCOMPARE(variable.nbPoints(), operation.m_ExpectedNbPoints);
335 }
336 }
337
338 namespace {
339
340 /// Struct used to represent a range operation on a variable
341 /// @sa TestVariable::testRealRange()
342 struct RangeOperation {
343 DateTimeRange m_CacheRange; /// Range to set for the variable
344 std::shared_ptr<ScalarSeries> m_DataSeries; /// Series to merge in the variable
345 DateTimeRange m_ExpectedRealRange; /// Real Range expected after operation on the variable
346 };
347
348 using RangeOperations = std::vector<RangeOperation>;
349
350 } // namespace
351
352 Q_DECLARE_METATYPE(RangeOperations)
353
354 void TestVariable::testRealRange_data()
355 {
356 // ////////////// //
357 // Test structure //
358 // ////////////// //
359
360 QTest::addColumn<RangeOperations>("operations");
361
362 // ////////// //
363 // Test cases //
364 // ////////// //
365 RangeOperations operations{};
366
367 // Inits cache range and data series (expected real range = cache range)
368 auto cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 13, 0, 0)};
369 operations.push_back({cacheRange, dataSeries(cacheRange), cacheRange});
370
371 // Changes cache range and updates data series (expected real range = cache range)
372 cacheRange = DateTimeRange{date(2017, 1, 1, 14, 0, 0), date(2017, 1, 1, 15, 0, 0)};
373 operations.push_back({cacheRange, dataSeries(cacheRange), cacheRange});
374
375 // Changes cache range and update data series but with a lower range (expected real range =
376 // data series range)
377 cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 16, 0, 0)};
378 auto dataSeriesRange = DateTimeRange{date(2017, 1, 1, 14, 0, 0), date(2017, 1, 1, 15, 0, 0)};
379 operations.push_back({cacheRange, dataSeries(dataSeriesRange), dataSeriesRange});
380
381 // Changes cache range but DON'T update data series (expected real range = cache range
382 // before operation)
383 cacheRange = DateTimeRange{date(2017, 1, 1, 10, 0, 0), date(2017, 1, 1, 17, 0, 0)};
384 operations.push_back({cacheRange, nullptr, dataSeriesRange});
385
386 QTest::newRow("realRange1") << operations;
387 }
388
389 void TestVariable::testRealRange()
390 {
391 // Creates variable (real range is invalid)
392 Variable variable{"var"};
393 QCOMPARE(variable.realRange(), INVALID_RANGE);
394
395 QFETCH(RangeOperations, operations);
396 for (const auto &operation : operations) {
397 // Sets cache range and merge data series
398 variable.setCacheRange(operation.m_CacheRange);
399 if (operation.m_DataSeries != nullptr) {
400 variable.mergeDataSeries(operation.m_DataSeries);
401 }
402
19
403 // Checks real range
404 QCOMPARE(variable.realRange(), operation.m_ExpectedRealRange);
405 }
406 }
407
20
408
21
409 QTEST_MAIN(TestVariable)
22 QTEST_MAIN(TestVariable)
410 #include "TestVariable.moc"
23 #include "TestVariable.moc"
General Comments 0
You need to be logged in to leave comments. Login now