##// END OF EJS Templates
Move the AMDA data type to a type accessible from core
Alexandre Leroux -
r1332:d3daab81283b
parent child
Show More
@@ -0,0 +1,26
1 #ifndef SCIQLOP_DATASERIESTYPE_H
2 #define SCIQLOP_DATASERIESTYPE_H
3
4 #include <QString>
5
6 enum class DataSeriesType { SCALAR, SPECTROGRAM, VECTOR, UNKNOWN };
7
8 struct DataSeriesTypeUtils {
9 static DataSeriesType fromString(const QString &type)
10 {
11 if (type == QStringLiteral("scalar")) {
12 return DataSeriesType::SCALAR;
13 }
14 else if (type == QStringLiteral("spectrogram")) {
15 return DataSeriesType::SPECTROGRAM;
16 }
17 else if (type == QStringLiteral("vector")) {
18 return DataSeriesType::VECTOR;
19 }
20 else {
21 return DataSeriesType::UNKNOWN;
22 }
23 }
24 };
25
26 #endif // SCIQLOP_DATASERIESTYPE_H
@@ -1,21 +1,21
1 #ifndef SCIQLOP_AMDARESULTPARSER_H
1 #ifndef SCIQLOP_AMDARESULTPARSER_H
2 #define SCIQLOP_AMDARESULTPARSER_H
2 #define SCIQLOP_AMDARESULTPARSER_H
3
3
4 #include "AmdaGlobal.h"
4 #include "AmdaGlobal.h"
5
5
6 #include <Data/DataSeriesType.h>
7
6 #include <QLoggingCategory>
8 #include <QLoggingCategory>
7
9
8 #include <memory>
10 #include <memory>
9
11
10 class IDataSeries;
12 class IDataSeries;
11
13
12 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaResultParser)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaResultParser)
13
15
14 struct SCIQLOP_AMDA_EXPORT AmdaResultParser {
16 struct SCIQLOP_AMDA_EXPORT AmdaResultParser {
15 enum class ValueType { SCALAR, SPECTROGRAM, VECTOR, UNKNOWN };
16
17 static std::shared_ptr<IDataSeries> readTxt(const QString &filePath,
17 static std::shared_ptr<IDataSeries> readTxt(const QString &filePath,
18 ValueType valueType) noexcept;
18 DataSeriesType valueType) noexcept;
19 };
19 };
20
20
21 #endif // SCIQLOP_AMDARESULTPARSER_H
21 #endif // SCIQLOP_AMDARESULTPARSER_H
@@ -1,288 +1,274
1 #include "AmdaProvider.h"
1 #include "AmdaProvider.h"
2 #include "AmdaDefs.h"
2 #include "AmdaDefs.h"
3 #include "AmdaResultParser.h"
3 #include "AmdaResultParser.h"
4 #include "AmdaServer.h"
4 #include "AmdaServer.h"
5
5
6 #include <Common/DateUtils.h>
6 #include <Common/DateUtils.h>
7 #include <Data/DataProviderParameters.h>
7 #include <Data/DataProviderParameters.h>
8 #include <Network/NetworkController.h>
8 #include <Network/NetworkController.h>
9 #include <SqpApplication.h>
9 #include <SqpApplication.h>
10 #include <Variable/Variable.h>
10 #include <Variable/Variable.h>
11
11
12 #include <QNetworkAccessManager>
12 #include <QNetworkAccessManager>
13 #include <QNetworkReply>
13 #include <QNetworkReply>
14 #include <QTemporaryFile>
14 #include <QTemporaryFile>
15 #include <QThread>
15 #include <QThread>
16
16
17 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
17 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
18
18
19 namespace {
19 namespace {
20
20
21 /// URL format for a request on AMDA server. The parameters are as follows:
21 /// URL format for a request on AMDA server. The parameters are as follows:
22 /// - %1: server URL
22 /// - %1: server URL
23 /// - %2: start date
23 /// - %2: start date
24 /// - %3: end date
24 /// - %3: end date
25 /// - %4: parameter id
25 /// - %4: parameter id
26 /// AMDA V2: http://amdatest.irap.omp.eu/php/rest/
26 /// AMDA V2: http://amdatest.irap.omp.eu/php/rest/
27 const auto AMDA_URL_FORMAT = QStringLiteral(
27 const auto AMDA_URL_FORMAT = QStringLiteral(
28 "http://%1/php/rest/"
28 "http://%1/php/rest/"
29 "getParameter.php?startTime=%2&stopTime=%3&parameterID=%4&outputFormat=ASCII&"
29 "getParameter.php?startTime=%2&stopTime=%3&parameterID=%4&outputFormat=ASCII&"
30 "timeFormat=ISO8601&gzip=0");
30 "timeFormat=ISO8601&gzip=0");
31
31
32 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
32 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
33 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
33 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
34
34
35 /// Formats a time to a date that can be passed in URL
35 /// Formats a time to a date that can be passed in URL
36 QString dateFormat(double sqpRange) noexcept
36 QString dateFormat(double sqpRange) noexcept
37 {
37 {
38 auto dateTime = DateUtils::dateTime(sqpRange);
38 auto dateTime = DateUtils::dateTime(sqpRange);
39 return dateTime.toString(AMDA_TIME_FORMAT);
39 return dateTime.toString(AMDA_TIME_FORMAT);
40 }
40 }
41
41
42 AmdaResultParser::ValueType valueType(const QString &valueType)
43 {
44 if (valueType == QStringLiteral("scalar")) {
45 return AmdaResultParser::ValueType::SCALAR;
46 }
47 else if (valueType == QStringLiteral("spectrogram")) {
48 return AmdaResultParser::ValueType::SPECTROGRAM;
49 }
50 else if (valueType == QStringLiteral("vector")) {
51 return AmdaResultParser::ValueType::VECTOR;
52 }
53 else {
54 return AmdaResultParser::ValueType::UNKNOWN;
55 }
56 }
57
42
58 } // namespace
43 } // namespace
59
44
60 AmdaProvider::AmdaProvider()
45 AmdaProvider::AmdaProvider()
61 {
46 {
62 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
47 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
63 if (auto app = sqpApp) {
48 if (auto app = sqpApp) {
64 auto &networkController = app->networkController();
49 auto &networkController = app->networkController();
65 connect(this, SIGNAL(requestConstructed(std::shared_ptr<QNetworkRequest>, QUuid,
50 connect(this, SIGNAL(requestConstructed(std::shared_ptr<QNetworkRequest>, QUuid,
66 std::function<void(QNetworkReply *, QUuid)>)),
51 std::function<void(QNetworkReply *, QUuid)>)),
67 &networkController,
52 &networkController,
68 SLOT(onProcessRequested(std::shared_ptr<QNetworkRequest>, QUuid,
53 SLOT(onProcessRequested(std::shared_ptr<QNetworkRequest>, QUuid,
69 std::function<void(QNetworkReply *, QUuid)>)));
54 std::function<void(QNetworkReply *, QUuid)>)));
70
55
71
56
72 connect(&sqpApp->networkController(),
57 connect(&sqpApp->networkController(),
73 SIGNAL(replyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)),
58 SIGNAL(replyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)),
74 this,
59 this,
75 SLOT(onReplyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)));
60 SLOT(onReplyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)));
76 }
61 }
77 }
62 }
78
63
79 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
64 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
80 {
65 {
81 // No copy is made in the clone
66 // No copy is made in the clone
82 return std::make_shared<AmdaProvider>();
67 return std::make_shared<AmdaProvider>();
83 }
68 }
84
69
85 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
70 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
86 {
71 {
87 // NOTE: Try to use multithread if possible
72 // NOTE: Try to use multithread if possible
88 const auto times = parameters.m_Times;
73 const auto times = parameters.m_Times;
89 const auto data = parameters.m_Data;
74 const auto data = parameters.m_Data;
90 for (const auto &dateTime : qAsConst(times)) {
75 for (const auto &dateTime : qAsConst(times)) {
91 qCDebug(LOG_AmdaProvider()) << tr("TORM AmdaProvider::requestDataLoading ") << acqIdentifier
76 qCDebug(LOG_AmdaProvider()) << tr("TORM AmdaProvider::requestDataLoading ") << acqIdentifier
92 << dateTime;
77 << dateTime;
93 this->retrieveData(acqIdentifier, dateTime, data);
78 this->retrieveData(acqIdentifier, dateTime, data);
94
79
95
80
96 // TORM when AMDA will support quick asynchrone request
81 // TORM when AMDA will support quick asynchrone request
97 QThread::msleep(1000);
82 QThread::msleep(1000);
98 }
83 }
99 }
84 }
100
85
101 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
86 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
102 {
87 {
103 if (auto app = sqpApp) {
88 if (auto app = sqpApp) {
104 auto &networkController = app->networkController();
89 auto &networkController = app->networkController();
105 networkController.onReplyCanceled(acqIdentifier);
90 networkController.onReplyCanceled(acqIdentifier);
106 }
91 }
107 }
92 }
108
93
109 void AmdaProvider::onReplyDownloadProgress(QUuid acqIdentifier,
94 void AmdaProvider::onReplyDownloadProgress(QUuid acqIdentifier,
110 std::shared_ptr<QNetworkRequest> networkRequest,
95 std::shared_ptr<QNetworkRequest> networkRequest,
111 double progress)
96 double progress)
112 {
97 {
113 qCDebug(LOG_AmdaProvider()) << tr("onReplyDownloadProgress") << acqIdentifier
98 qCDebug(LOG_AmdaProvider()) << tr("onReplyDownloadProgress") << acqIdentifier
114 << networkRequest.get() << progress;
99 << networkRequest.get() << progress;
115 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
100 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
116 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
101 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
117
102
118 // Update the progression for the current request
103 // Update the progression for the current request
119 auto requestPtr = networkRequest;
104 auto requestPtr = networkRequest;
120 auto findRequest = [requestPtr](const auto &entry) { return requestPtr == entry.first; };
105 auto findRequest = [requestPtr](const auto &entry) { return requestPtr == entry.first; };
121
106
122 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
107 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
123 auto requestProgressMapEnd = requestProgressMap.end();
108 auto requestProgressMapEnd = requestProgressMap.end();
124 auto requestProgressMapIt
109 auto requestProgressMapIt
125 = std::find_if(requestProgressMap.begin(), requestProgressMapEnd, findRequest);
110 = std::find_if(requestProgressMap.begin(), requestProgressMapEnd, findRequest);
126
111
127 if (requestProgressMapIt != requestProgressMapEnd) {
112 if (requestProgressMapIt != requestProgressMapEnd) {
128 requestProgressMapIt->second = progress;
113 requestProgressMapIt->second = progress;
129 }
114 }
130 else {
115 else {
131 // This case can happened when a progression is send after the request has been
116 // This case can happened when a progression is send after the request has been
132 // finished.
117 // finished.
133 // Generaly the case when aborting a request
118 // Generaly the case when aborting a request
134 qCDebug(LOG_AmdaProvider()) << tr("Can't retrieve Request in progress") << acqIdentifier
119 qCDebug(LOG_AmdaProvider()) << tr("Can't retrieve Request in progress") << acqIdentifier
135 << networkRequest.get() << progress;
120 << networkRequest.get() << progress;
136 }
121 }
137
122
138 // Compute the current final progress and notify it
123 // Compute the current final progress and notify it
139 double finalProgress = 0.0;
124 double finalProgress = 0.0;
140
125
141 auto fraq = requestProgressMap.size();
126 auto fraq = requestProgressMap.size();
142
127
143 for (auto requestProgress : requestProgressMap) {
128 for (auto requestProgress : requestProgressMap) {
144 finalProgress += requestProgress.second;
129 finalProgress += requestProgress.second;
145 qCDebug(LOG_AmdaProvider()) << tr("Current final progress without fraq:")
130 qCDebug(LOG_AmdaProvider()) << tr("Current final progress without fraq:")
146 << finalProgress << requestProgress.second;
131 << finalProgress << requestProgress.second;
147 }
132 }
148
133
149 if (fraq > 0) {
134 if (fraq > 0) {
150 finalProgress = finalProgress / fraq;
135 finalProgress = finalProgress / fraq;
151 }
136 }
152
137
153 qCDebug(LOG_AmdaProvider()) << tr("Current final progress: ") << fraq << finalProgress;
138 qCDebug(LOG_AmdaProvider()) << tr("Current final progress: ") << fraq << finalProgress;
154 emit dataProvidedProgress(acqIdentifier, finalProgress);
139 emit dataProvidedProgress(acqIdentifier, finalProgress);
155 }
140 }
156 else {
141 else {
157 // This case can happened when a progression is send after the request has been finished.
142 // This case can happened when a progression is send after the request has been finished.
158 // Generaly the case when aborting a request
143 // Generaly the case when aborting a request
159 emit dataProvidedProgress(acqIdentifier, 100.0);
144 emit dataProvidedProgress(acqIdentifier, 100.0);
160 }
145 }
161 }
146 }
162
147
163 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
148 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
164 {
149 {
165 // Retrieves product ID from data: if the value is invalid, no request is made
150 // Retrieves product ID from data: if the value is invalid, no request is made
166 auto productId = data.value(AMDA_XML_ID_KEY).toString();
151 auto productId = data.value(AMDA_XML_ID_KEY).toString();
167 if (productId.isNull()) {
152 if (productId.isNull()) {
168 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
153 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
169 return;
154 return;
170 }
155 }
171
156
172 // Retrieves the data type that determines whether the expected format for the result file is
157 // Retrieves the data type that determines whether the expected format for the result file is
173 // scalar, vector...
158 // scalar, vector...
174 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
159 auto productValueType
160 = DataSeriesTypeUtils::fromString(data.value(AMDA_DATA_TYPE_KEY).toString());
175
161
176 // /////////// //
162 // /////////// //
177 // Creates URL //
163 // Creates URL //
178 // /////////// //
164 // /////////// //
179
165
180 auto startDate = dateFormat(dateTime.m_TStart);
166 auto startDate = dateFormat(dateTime.m_TStart);
181 auto endDate = dateFormat(dateTime.m_TEnd);
167 auto endDate = dateFormat(dateTime.m_TEnd);
182
168
183 QVariantHash urlProperties{{AMDA_SERVER_KEY, data.value(AMDA_SERVER_KEY)}};
169 QVariantHash urlProperties{{AMDA_SERVER_KEY, data.value(AMDA_SERVER_KEY)}};
184 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(AmdaServer::instance().url(urlProperties),
170 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(AmdaServer::instance().url(urlProperties),
185 startDate, endDate, productId)};
171 startDate, endDate, productId)};
186 qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
172 qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
187 auto tempFile = std::make_shared<QTemporaryFile>();
173 auto tempFile = std::make_shared<QTemporaryFile>();
188
174
189 // LAMBDA
175 // LAMBDA
190 auto httpDownloadFinished = [this, dateTime, tempFile,
176 auto httpDownloadFinished = [this, dateTime, tempFile,
191 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
177 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
192
178
193 // Don't do anything if the reply was abort
179 // Don't do anything if the reply was abort
194 if (reply->error() == QNetworkReply::NoError) {
180 if (reply->error() == QNetworkReply::NoError) {
195
181
196 if (tempFile) {
182 if (tempFile) {
197 auto replyReadAll = reply->readAll();
183 auto replyReadAll = reply->readAll();
198 if (!replyReadAll.isEmpty()) {
184 if (!replyReadAll.isEmpty()) {
199 tempFile->write(replyReadAll);
185 tempFile->write(replyReadAll);
200 }
186 }
201 tempFile->close();
187 tempFile->close();
202
188
203 // Parse results file
189 // Parse results file
204 if (auto dataSeries
190 if (auto dataSeries
205 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
191 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
206 emit dataProvided(dataId, dataSeries, dateTime);
192 emit dataProvided(dataId, dataSeries, dateTime);
207 }
193 }
208 else {
194 else {
209 /// @todo ALX : debug
195 /// @todo ALX : debug
210 emit dataProvidedFailed(dataId);
196 emit dataProvidedFailed(dataId);
211 }
197 }
212 }
198 }
213 m_AcqIdToRequestProgressMap.erase(dataId);
199 m_AcqIdToRequestProgressMap.erase(dataId);
214 }
200 }
215 else {
201 else {
216 qCCritical(LOG_AmdaProvider()) << tr("httpDownloadFinished ERROR");
202 qCCritical(LOG_AmdaProvider()) << tr("httpDownloadFinished ERROR");
217 emit dataProvidedFailed(dataId);
203 emit dataProvidedFailed(dataId);
218 }
204 }
219
205
220 };
206 };
221 auto httpFinishedLambda
207 auto httpFinishedLambda
222 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
208 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
223
209
224 // Don't do anything if the reply was abort
210 // Don't do anything if the reply was abort
225 if (reply->error() == QNetworkReply::NoError) {
211 if (reply->error() == QNetworkReply::NoError) {
226 auto downloadFileUrl = QUrl{QString{reply->readAll()}.trimmed()};
212 auto downloadFileUrl = QUrl{QString{reply->readAll()}.trimmed()};
227
213
228 qCInfo(LOG_AmdaProvider())
214 qCInfo(LOG_AmdaProvider())
229 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
215 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
230 // Executes request for downloading file //
216 // Executes request for downloading file //
231
217
232 // Creates destination file
218 // Creates destination file
233 if (tempFile->open()) {
219 if (tempFile->open()) {
234 // Executes request and store the request for progression
220 // Executes request and store the request for progression
235 auto request = std::make_shared<QNetworkRequest>(downloadFileUrl);
221 auto request = std::make_shared<QNetworkRequest>(downloadFileUrl);
236 updateRequestProgress(dataId, request, 0.0);
222 updateRequestProgress(dataId, request, 0.0);
237 emit requestConstructed(request, dataId, httpDownloadFinished);
223 emit requestConstructed(request, dataId, httpDownloadFinished);
238 }
224 }
239 else {
225 else {
240 emit dataProvidedFailed(dataId);
226 emit dataProvidedFailed(dataId);
241 }
227 }
242 }
228 }
243 else {
229 else {
244 qCCritical(LOG_AmdaProvider()) << tr("httpFinishedLambda ERROR");
230 qCCritical(LOG_AmdaProvider()) << tr("httpFinishedLambda ERROR");
245 m_AcqIdToRequestProgressMap.erase(dataId);
231 m_AcqIdToRequestProgressMap.erase(dataId);
246 emit dataProvidedFailed(dataId);
232 emit dataProvidedFailed(dataId);
247 }
233 }
248 };
234 };
249
235
250 // //////////////// //
236 // //////////////// //
251 // Executes request //
237 // Executes request //
252 // //////////////// //
238 // //////////////// //
253
239
254 auto request = std::make_shared<QNetworkRequest>(url);
240 auto request = std::make_shared<QNetworkRequest>(url);
255 qCDebug(LOG_AmdaProvider()) << tr("First Request creation") << request.get();
241 qCDebug(LOG_AmdaProvider()) << tr("First Request creation") << request.get();
256 updateRequestProgress(token, request, 0.0);
242 updateRequestProgress(token, request, 0.0);
257
243
258 emit requestConstructed(request, token, httpFinishedLambda);
244 emit requestConstructed(request, token, httpFinishedLambda);
259 }
245 }
260
246
261 void AmdaProvider::updateRequestProgress(QUuid acqIdentifier,
247 void AmdaProvider::updateRequestProgress(QUuid acqIdentifier,
262 std::shared_ptr<QNetworkRequest> request, double progress)
248 std::shared_ptr<QNetworkRequest> request, double progress)
263 {
249 {
264 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress request") << request.get();
250 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress request") << request.get();
265 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
251 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
266 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
252 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
267 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
253 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
268 auto requestProgressMapIt = requestProgressMap.find(request);
254 auto requestProgressMapIt = requestProgressMap.find(request);
269 if (requestProgressMapIt != requestProgressMap.end()) {
255 if (requestProgressMapIt != requestProgressMap.end()) {
270 requestProgressMapIt->second = progress;
256 requestProgressMapIt->second = progress;
271 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new progress for request")
257 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new progress for request")
272 << acqIdentifier << request.get() << progress;
258 << acqIdentifier << request.get() << progress;
273 }
259 }
274 else {
260 else {
275 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new request") << acqIdentifier
261 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new request") << acqIdentifier
276 << request.get() << progress;
262 << request.get() << progress;
277 acqIdToRequestProgressMapIt->second.insert(std::make_pair(request, progress));
263 acqIdToRequestProgressMapIt->second.insert(std::make_pair(request, progress));
278 }
264 }
279 }
265 }
280 else {
266 else {
281 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new acqIdentifier")
267 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new acqIdentifier")
282 << acqIdentifier << request.get() << progress;
268 << acqIdentifier << request.get() << progress;
283 auto requestProgressMap = std::map<std::shared_ptr<QNetworkRequest>, double>{};
269 auto requestProgressMap = std::map<std::shared_ptr<QNetworkRequest>, double>{};
284 requestProgressMap.insert(std::make_pair(request, progress));
270 requestProgressMap.insert(std::make_pair(request, progress));
285 m_AcqIdToRequestProgressMap.insert(
271 m_AcqIdToRequestProgressMap.insert(
286 std::make_pair(acqIdentifier, std::move(requestProgressMap)));
272 std::make_pair(acqIdentifier, std::move(requestProgressMap)));
287 }
273 }
288 }
274 }
@@ -1,133 +1,133
1 #include "AmdaResultParser.h"
1 #include "AmdaResultParser.h"
2
2
3 #include "AmdaResultParserHelper.h"
3 #include "AmdaResultParserHelper.h"
4
4
5 #include <QFile>
5 #include <QFile>
6
6
7 #include <cmath>
7 #include <cmath>
8
8
9 Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser")
9 Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser")
10
10
11 namespace {
11 namespace {
12
12
13 /// Message in result file when the file was not found on server
13 /// Message in result file when the file was not found on server
14 const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found");
14 const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found");
15
15
16 /// Checks if a line is a comment line
16 /// Checks if a line is a comment line
17 bool isCommentLine(const QString &line)
17 bool isCommentLine(const QString &line)
18 {
18 {
19 return line.startsWith("#");
19 return line.startsWith("#");
20 }
20 }
21
21
22 /**
22 /**
23 * Creates helper that will be used to read AMDA file, according to the type passed as parameter
23 * Creates helper that will be used to read AMDA file, according to the type passed as parameter
24 * @param valueType the type of values expected in the AMDA file (scalars, vectors, spectrograms...)
24 * @param valueType the type of values expected in the AMDA file (scalars, vectors, spectrograms...)
25 * @return the helper created
25 * @return the helper created
26 */
26 */
27 std::unique_ptr<IAmdaResultParserHelper> createHelper(AmdaResultParser::ValueType valueType)
27 std::unique_ptr<IAmdaResultParserHelper> createHelper(DataSeriesType valueType)
28 {
28 {
29 switch (valueType) {
29 switch (valueType) {
30 case AmdaResultParser::ValueType::SCALAR:
30 case DataSeriesType::SCALAR:
31 return std::make_unique<ScalarParserHelper>();
31 return std::make_unique<ScalarParserHelper>();
32 case AmdaResultParser::ValueType::SPECTROGRAM:
32 case DataSeriesType::SPECTROGRAM:
33 return std::make_unique<SpectrogramParserHelper>();
33 return std::make_unique<SpectrogramParserHelper>();
34 case AmdaResultParser::ValueType::VECTOR:
34 case DataSeriesType::VECTOR:
35 return std::make_unique<VectorParserHelper>();
35 return std::make_unique<VectorParserHelper>();
36 case AmdaResultParser::ValueType::UNKNOWN:
36 case DataSeriesType::UNKNOWN:
37 // Invalid case
37 // Invalid case
38 break;
38 break;
39 }
39 }
40
40
41 // Invalid cases
41 // Invalid cases
42 qCCritical(LOG_AmdaResultParser())
42 qCCritical(LOG_AmdaResultParser())
43 << QObject::tr("Can't create helper to read result file: unsupported type");
43 << QObject::tr("Can't create helper to read result file: unsupported type");
44 return nullptr;
44 return nullptr;
45 }
45 }
46
46
47 /**
47 /**
48 * Reads properties of the stream passed as parameter
48 * Reads properties of the stream passed as parameter
49 * @param helper the helper used to read properties line by line
49 * @param helper the helper used to read properties line by line
50 * @param stream the stream to read
50 * @param stream the stream to read
51 */
51 */
52 void readProperties(IAmdaResultParserHelper &helper, QTextStream &stream)
52 void readProperties(IAmdaResultParserHelper &helper, QTextStream &stream)
53 {
53 {
54 // Searches properties in the comment lines (as long as the reading has not reached the data)
54 // Searches properties in the comment lines (as long as the reading has not reached the data)
55 // AMDA V2: while (stream.readLineInto(&line) && !line.contains(DATA_HEADER_REGEX)) {
55 // AMDA V2: while (stream.readLineInto(&line) && !line.contains(DATA_HEADER_REGEX)) {
56 QString line{};
56 QString line{};
57 while (stream.readLineInto(&line) && isCommentLine(line)) {
57 while (stream.readLineInto(&line) && isCommentLine(line)) {
58 helper.readPropertyLine(line);
58 helper.readPropertyLine(line);
59 }
59 }
60 }
60 }
61
61
62 /**
62 /**
63 * Reads results of the stream passed as parameter
63 * Reads results of the stream passed as parameter
64 * @param helper the helper used to read results line by line
64 * @param helper the helper used to read results line by line
65 * @param stream the stream to read
65 * @param stream the stream to read
66 */
66 */
67 void readResults(IAmdaResultParserHelper &helper, QTextStream &stream)
67 void readResults(IAmdaResultParserHelper &helper, QTextStream &stream)
68 {
68 {
69 QString line{};
69 QString line{};
70
70
71 // Skip comment lines
71 // Skip comment lines
72 while (stream.readLineInto(&line) && isCommentLine(line)) {
72 while (stream.readLineInto(&line) && isCommentLine(line)) {
73 }
73 }
74
74
75 if (!stream.atEnd()) {
75 if (!stream.atEnd()) {
76 do {
76 do {
77 helper.readResultLine(line);
77 helper.readResultLine(line);
78 } while (stream.readLineInto(&line));
78 } while (stream.readLineInto(&line));
79 }
79 }
80 }
80 }
81
81
82 } // namespace
82 } // namespace
83
83
84 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath,
84 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath,
85 ValueType valueType) noexcept
85 DataSeriesType type) noexcept
86 {
86 {
87 if (valueType == ValueType::UNKNOWN) {
87 if (type == DataSeriesType::UNKNOWN) {
88 qCCritical(LOG_AmdaResultParser())
88 qCCritical(LOG_AmdaResultParser())
89 << QObject::tr("Can't retrieve AMDA data: the type of values to be read is unknown");
89 << QObject::tr("Can't retrieve AMDA data: the type of values to be read is unknown");
90 return nullptr;
90 return nullptr;
91 }
91 }
92
92
93 QFile file{filePath};
93 QFile file{filePath};
94
94
95 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
95 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
96 qCCritical(LOG_AmdaResultParser())
96 qCCritical(LOG_AmdaResultParser())
97 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
97 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
98 .arg(filePath, file.errorString());
98 .arg(filePath, file.errorString());
99 return nullptr;
99 return nullptr;
100 }
100 }
101
101
102 QTextStream stream{&file};
102 QTextStream stream{&file};
103
103
104 // Checks if the file was found on the server
104 // Checks if the file was found on the server
105 auto firstLine = stream.readLine();
105 auto firstLine = stream.readLine();
106 if (firstLine.compare(FILE_NOT_FOUND_MESSAGE) == 0) {
106 if (firstLine.compare(FILE_NOT_FOUND_MESSAGE) == 0) {
107 qCCritical(LOG_AmdaResultParser())
107 qCCritical(LOG_AmdaResultParser())
108 << QObject::tr("Can't retrieve AMDA data from file %1: file was not found on server")
108 << QObject::tr("Can't retrieve AMDA data from file %1: file was not found on server")
109 .arg(filePath);
109 .arg(filePath);
110 return nullptr;
110 return nullptr;
111 }
111 }
112
112
113 auto helper = createHelper(valueType);
113 auto helper = createHelper(type);
114 Q_ASSERT(helper != nullptr);
114 Q_ASSERT(helper != nullptr);
115
115
116 // Reads header file to retrieve properties
116 // Reads header file to retrieve properties
117 stream.seek(0); // returns to the beginning of the file
117 stream.seek(0); // returns to the beginning of the file
118 readProperties(*helper, stream);
118 readProperties(*helper, stream);
119
119
120 // Checks properties
120 // Checks properties
121 if (helper->checkProperties()) {
121 if (helper->checkProperties()) {
122 // Reads results
122 // Reads results
123 // AMDA V2: remove line
123 // AMDA V2: remove line
124 stream.seek(0); // returns to the beginning of the file
124 stream.seek(0); // returns to the beginning of the file
125 readResults(*helper, stream);
125 readResults(*helper, stream);
126
126
127 // Creates data series
127 // Creates data series
128 return helper->createSeries();
128 return helper->createSeries();
129 }
129 }
130 else {
130 else {
131 return nullptr;
131 return nullptr;
132 }
132 }
133 }
133 }
@@ -1,164 +1,164
1 #include "AmdaProvider.h"
1 #include "AmdaProvider.h"
2 #include "AmdaResultParser.h"
2 #include "AmdaResultParser.h"
3
3
4 #include "SqpApplication.h"
4 #include "SqpApplication.h"
5 #include <Data/DataSeries.h>
5 #include <Data/DataSeries.h>
6 #include <Data/IDataSeries.h>
6 #include <Data/IDataSeries.h>
7 #include <Data/ScalarSeries.h>
7 #include <Data/ScalarSeries.h>
8 #include <Time/TimeController.h>
8 #include <Time/TimeController.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11
11
12 #include <QObject>
12 #include <QObject>
13 #include <QtTest>
13 #include <QtTest>
14
14
15 #include <memory>
15 #include <memory>
16
16
17 // TEST with REF:
17 // TEST with REF:
18 // AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00
18 // AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00
19 // imf(0) - Type : Local Parameter @ CDPP/AMDA -
19 // imf(0) - Type : Local Parameter @ CDPP/AMDA -
20 // Name : bx_gse - Units : nT - Size : 1 -
20 // Name : bx_gse - Units : nT - Size : 1 -
21 // Frame : GSE - Mission : ACE -
21 // Frame : GSE - Mission : ACE -
22 // Instrument : MFI - Dataset : mfi_final-prelim
22 // Instrument : MFI - Dataset : mfi_final-prelim
23 // REFERENCE DOWNLOAD FILE =
23 // REFERENCE DOWNLOAD FILE =
24 // http://amdatest.irap.omp.eu/php/rest/getParameter.php?startTime=2012-01-01T12:00:00&stopTime=2012-01-03T12:00:00&parameterID=imf(0)&outputFormat=ASCII&timeFormat=ISO8601&gzip=0
24 // http://amdatest.irap.omp.eu/php/rest/getParameter.php?startTime=2012-01-01T12:00:00&stopTime=2012-01-03T12:00:00&parameterID=imf(0)&outputFormat=ASCII&timeFormat=ISO8601&gzip=0
25
25
26 namespace {
26 namespace {
27
27
28 /// Path for the tests
28 /// Path for the tests
29 const auto TESTS_RESOURCES_PATH
29 const auto TESTS_RESOURCES_PATH
30 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaAcquisition"}.absoluteFilePath();
30 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaAcquisition"}.absoluteFilePath();
31
31
32 /// Delay after each operation on the variable before validating it (in ms)
32 /// Delay after each operation on the variable before validating it (in ms)
33 const auto OPERATION_DELAY = 10000;
33 const auto OPERATION_DELAY = 10000;
34
34
35 template <typename T>
35 template <typename T>
36 bool compareDataSeries(std::shared_ptr<IDataSeries> candidate, SqpRange candidateCacheRange,
36 bool compareDataSeries(std::shared_ptr<IDataSeries> candidate, SqpRange candidateCacheRange,
37 std::shared_ptr<IDataSeries> reference)
37 std::shared_ptr<IDataSeries> reference)
38 {
38 {
39 auto compareLambda = [](const auto &it1, const auto &it2) {
39 auto compareLambda = [](const auto &it1, const auto &it2) {
40 return (it1.x() == it2.x()) && (it1.value() == it2.value());
40 return (it1.x() == it2.x()) && (it1.value() == it2.value());
41 };
41 };
42
42
43 auto candidateDS = std::dynamic_pointer_cast<T>(candidate);
43 auto candidateDS = std::dynamic_pointer_cast<T>(candidate);
44 auto referenceDS = std::dynamic_pointer_cast<T>(reference);
44 auto referenceDS = std::dynamic_pointer_cast<T>(reference);
45
45
46 if (candidateDS && referenceDS) {
46 if (candidateDS && referenceDS) {
47
47
48 auto itRefs
48 auto itRefs
49 = referenceDS->xAxisRange(candidateCacheRange.m_TStart, candidateCacheRange.m_TEnd);
49 = referenceDS->xAxisRange(candidateCacheRange.m_TStart, candidateCacheRange.m_TEnd);
50 qDebug() << " DISTANCE" << std::distance(candidateDS->cbegin(), candidateDS->cend())
50 qDebug() << " DISTANCE" << std::distance(candidateDS->cbegin(), candidateDS->cend())
51 << std::distance(itRefs.first, itRefs.second);
51 << std::distance(itRefs.first, itRefs.second);
52
52
53 return std::equal(candidateDS->cbegin(), candidateDS->cend(), itRefs.first, itRefs.second,
53 return std::equal(candidateDS->cbegin(), candidateDS->cend(), itRefs.first, itRefs.second,
54 compareLambda);
54 compareLambda);
55 }
55 }
56 else {
56 else {
57 return false;
57 return false;
58 }
58 }
59 }
59 }
60 }
60 }
61
61
62 class TestAmdaAcquisition : public QObject {
62 class TestAmdaAcquisition : public QObject {
63 Q_OBJECT
63 Q_OBJECT
64
64
65 private slots:
65 private slots:
66 /// Input data for @sa testAcquisition()
66 /// Input data for @sa testAcquisition()
67 void testAcquisition_data();
67 void testAcquisition_data();
68 void testAcquisition();
68 void testAcquisition();
69 };
69 };
70
70
71 void TestAmdaAcquisition::testAcquisition_data()
71 void TestAmdaAcquisition::testAcquisition_data()
72 {
72 {
73 // ////////////// //
73 // ////////////// //
74 // Test structure //
74 // Test structure //
75 // ////////////// //
75 // ////////////// //
76
76
77 QTest::addColumn<QString>("dataFilename"); // File containing expected data of acquisitions
77 QTest::addColumn<QString>("dataFilename"); // File containing expected data of acquisitions
78 QTest::addColumn<SqpRange>("initialRange"); // First acquisition
78 QTest::addColumn<SqpRange>("initialRange"); // First acquisition
79 QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
79 QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
80
80
81 // ////////// //
81 // ////////// //
82 // Test cases //
82 // Test cases //
83 // ////////// //
83 // ////////// //
84
84
85 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
85 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
86 return DateUtils::secondsSinceEpoch(
86 return DateUtils::secondsSinceEpoch(
87 QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC});
87 QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC});
88 };
88 };
89
89
90
90
91 QTest::newRow("amda")
91 QTest::newRow("amda")
92 << "AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00.txt"
92 << "AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00.txt"
93 << SqpRange{dateTime(2012, 1, 2, 2, 3, 0), dateTime(2012, 1, 2, 2, 4, 0)}
93 << SqpRange{dateTime(2012, 1, 2, 2, 3, 0), dateTime(2012, 1, 2, 2, 4, 0)}
94 << std::vector<SqpRange>{
94 << std::vector<SqpRange>{
95 // 2 : pan (jump) left for two min
95 // 2 : pan (jump) left for two min
96 SqpRange{dateTime(2012, 1, 2, 2, 1, 0), dateTime(2012, 1, 2, 2, 2, 0)},
96 SqpRange{dateTime(2012, 1, 2, 2, 1, 0), dateTime(2012, 1, 2, 2, 2, 0)},
97 // 3 : pan (jump) right for four min
97 // 3 : pan (jump) right for four min
98 SqpRange{dateTime(2012, 1, 2, 2, 5, 0), dateTime(2012, 1, 2, 2, 6, 0)},
98 SqpRange{dateTime(2012, 1, 2, 2, 5, 0), dateTime(2012, 1, 2, 2, 6, 0)},
99 // 4 : pan (overlay) right for 30 sec
99 // 4 : pan (overlay) right for 30 sec
100 /*SqpRange{dateTime(2012, 1, 2, 2, 5, 30), dateTime(2012, 1, 2, 2, 6, 30)},
100 /*SqpRange{dateTime(2012, 1, 2, 2, 5, 30), dateTime(2012, 1, 2, 2, 6, 30)},
101 // 5 : pan (overlay) left for 30 sec
101 // 5 : pan (overlay) left for 30 sec
102 SqpRange{dateTime(2012, 1, 2, 2, 5, 0), dateTime(2012, 1, 2, 2, 6, 0)},
102 SqpRange{dateTime(2012, 1, 2, 2, 5, 0), dateTime(2012, 1, 2, 2, 6, 0)},
103 // 6 : pan (overlay) left for 30 sec - BIS
103 // 6 : pan (overlay) left for 30 sec - BIS
104 SqpRange{dateTime(2012, 1, 2, 2, 4, 30), dateTime(2012, 1, 2, 2, 5, 30)},
104 SqpRange{dateTime(2012, 1, 2, 2, 4, 30), dateTime(2012, 1, 2, 2, 5, 30)},
105 // 7 : Zoom in Inside 20 sec range
105 // 7 : Zoom in Inside 20 sec range
106 SqpRange{dateTime(2012, 1, 2, 2, 4, 50), dateTime(2012, 1, 2, 2, 5, 10)},
106 SqpRange{dateTime(2012, 1, 2, 2, 4, 50), dateTime(2012, 1, 2, 2, 5, 10)},
107 // 8 : Zoom out Inside 20 sec range
107 // 8 : Zoom out Inside 20 sec range
108 SqpRange{dateTime(2012, 1, 2, 2, 4, 30), dateTime(2012, 1, 2, 2, 5, 30)}*/};
108 SqpRange{dateTime(2012, 1, 2, 2, 4, 30), dateTime(2012, 1, 2, 2, 5, 30)}*/};
109 }
109 }
110
110
111 void TestAmdaAcquisition::testAcquisition()
111 void TestAmdaAcquisition::testAcquisition()
112 {
112 {
113 /// @todo: update test to be compatible with AMDA v2
113 /// @todo: update test to be compatible with AMDA v2
114
114
115 // Retrieves data file
115 // Retrieves data file
116 QFETCH(QString, dataFilename);
116 QFETCH(QString, dataFilename);
117 auto filePath = QFileInfo{TESTS_RESOURCES_PATH, dataFilename}.absoluteFilePath();
117 auto filePath = QFileInfo{TESTS_RESOURCES_PATH, dataFilename}.absoluteFilePath();
118 auto results = AmdaResultParser::readTxt(filePath, AmdaResultParser::ValueType::SCALAR);
118 auto results = AmdaResultParser::readTxt(filePath, DataSeriesType::SCALAR);
119
119
120 /// Lambda used to validate a variable at each step
120 /// Lambda used to validate a variable at each step
121 auto validateVariable = [results](std::shared_ptr<Variable> variable, const SqpRange &range) {
121 auto validateVariable = [results](std::shared_ptr<Variable> variable, const SqpRange &range) {
122 // Checks that the variable's range has changed
122 // Checks that the variable's range has changed
123 qInfo() << tr("Compare var range vs range") << variable->range() << range;
123 qInfo() << tr("Compare var range vs range") << variable->range() << range;
124 QCOMPARE(variable->range(), range);
124 QCOMPARE(variable->range(), range);
125
125
126 // Checks the variable's data series
126 // Checks the variable's data series
127 QVERIFY(compareDataSeries<ScalarSeries>(variable->dataSeries(), variable->cacheRange(),
127 QVERIFY(compareDataSeries<ScalarSeries>(variable->dataSeries(), variable->cacheRange(),
128 results));
128 results));
129 qInfo() << "\n";
129 qInfo() << "\n";
130 };
130 };
131
131
132 // Creates variable
132 // Creates variable
133 QFETCH(SqpRange, initialRange);
133 QFETCH(SqpRange, initialRange);
134 sqpApp->timeController().onTimeToUpdate(initialRange);
134 sqpApp->timeController().onTimeToUpdate(initialRange);
135 auto provider = std::make_shared<AmdaProvider>();
135 auto provider = std::make_shared<AmdaProvider>();
136 auto variable = sqpApp->variableController().createVariable(
136 auto variable = sqpApp->variableController().createVariable(
137 "bx_gse", {{"dataType", "scalar"}, {"xml:id", "imf(0)"}}, provider);
137 "bx_gse", {{"dataType", "scalar"}, {"xml:id", "imf(0)"}}, provider);
138
138
139 QTest::qWait(OPERATION_DELAY);
139 QTest::qWait(OPERATION_DELAY);
140 validateVariable(variable, initialRange);
140 validateVariable(variable, initialRange);
141
141
142 // Makes operations on the variable
142 // Makes operations on the variable
143 QFETCH(std::vector<SqpRange>, operations);
143 QFETCH(std::vector<SqpRange>, operations);
144 for (const auto &operation : operations) {
144 for (const auto &operation : operations) {
145 // Asks request on the variable and waits during its execution
145 // Asks request on the variable and waits during its execution
146 sqpApp->variableController().onRequestDataLoading({variable}, operation, false);
146 sqpApp->variableController().onRequestDataLoading({variable}, operation, false);
147
147
148 QTest::qWait(OPERATION_DELAY);
148 QTest::qWait(OPERATION_DELAY);
149 validateVariable(variable, operation);
149 validateVariable(variable, operation);
150 }
150 }
151 }
151 }
152
152
153 int main(int argc, char *argv[])
153 int main(int argc, char *argv[])
154 {
154 {
155 SqpApplication app(argc, argv);
155 SqpApplication app(argc, argv);
156 app.setAttribute(Qt::AA_Use96Dpi, true);
156 app.setAttribute(Qt::AA_Use96Dpi, true);
157 TestAmdaAcquisition tc;
157 TestAmdaAcquisition tc;
158 QTEST_SET_MAIN_SOURCE_PATH
158 QTEST_SET_MAIN_SOURCE_PATH
159 return QTest::qExec(&tc, argc, argv);
159 return QTest::qExec(&tc, argc, argv);
160 }
160 }
161
161
162 // QTEST_MAIN(TestAmdaAcquisition)
162 // QTEST_MAIN(TestAmdaAcquisition)
163
163
164 #include "TestAmdaAcquisition.moc"
164 #include "TestAmdaAcquisition.moc"
@@ -1,579 +1,579
1 #include "AmdaResultParser.h"
1 #include "AmdaResultParser.h"
2
2
3 #include <Data/ScalarSeries.h>
3 #include <Data/ScalarSeries.h>
4 #include <Data/SpectrogramSeries.h>
4 #include <Data/SpectrogramSeries.h>
5 #include <Data/VectorSeries.h>
5 #include <Data/VectorSeries.h>
6
6
7 #include <QObject>
7 #include <QObject>
8 #include <QtTest>
8 #include <QtTest>
9
9
10 namespace {
10 namespace {
11
11
12 /// Path for the tests
12 /// Path for the tests
13 const auto TESTS_RESOURCES_PATH
13 const auto TESTS_RESOURCES_PATH
14 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaResultParser"}.absoluteFilePath();
14 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaResultParser"}.absoluteFilePath();
15
15
16 QDateTime dateTime(int year, int month, int day, int hours, int minutes, int seconds)
16 QDateTime dateTime(int year, int month, int day, int hours, int minutes, int seconds)
17 {
17 {
18 return QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC};
18 return QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC};
19 }
19 }
20
20
21 QString inputFilePath(const QString &inputFileName)
21 QString inputFilePath(const QString &inputFileName)
22 {
22 {
23 return QFileInfo{TESTS_RESOURCES_PATH, inputFileName}.absoluteFilePath();
23 return QFileInfo{TESTS_RESOURCES_PATH, inputFileName}.absoluteFilePath();
24 }
24 }
25
25
26 template <typename T>
26 template <typename T>
27 struct ExpectedResults {
27 struct ExpectedResults {
28
28
29 ExpectedResults &setParsingOK(bool parsingOK)
29 ExpectedResults &setParsingOK(bool parsingOK)
30 {
30 {
31 m_ParsingOK = parsingOK;
31 m_ParsingOK = parsingOK;
32 return *this;
32 return *this;
33 }
33 }
34
34
35 ExpectedResults &setXAxisUnit(Unit xAxisUnit)
35 ExpectedResults &setXAxisUnit(Unit xAxisUnit)
36 {
36 {
37 m_XAxisUnit = std::move(xAxisUnit);
37 m_XAxisUnit = std::move(xAxisUnit);
38 return *this;
38 return *this;
39 }
39 }
40
40
41 ExpectedResults &setXAxisData(const QVector<QDateTime> &xAxisData)
41 ExpectedResults &setXAxisData(const QVector<QDateTime> &xAxisData)
42 {
42 {
43 m_XAxisData.clear();
43 m_XAxisData.clear();
44
44
45 // Converts QVector<QDateTime> to QVector<double>
45 // Converts QVector<QDateTime> to QVector<double>
46 std::transform(xAxisData.cbegin(), xAxisData.cend(), std::back_inserter(m_XAxisData),
46 std::transform(xAxisData.cbegin(), xAxisData.cend(), std::back_inserter(m_XAxisData),
47 [](const auto &dateTime) { return dateTime.toMSecsSinceEpoch() / 1000.; });
47 [](const auto &dateTime) { return dateTime.toMSecsSinceEpoch() / 1000.; });
48
48
49 return *this;
49 return *this;
50 }
50 }
51
51
52 ExpectedResults &setValuesUnit(Unit valuesUnit)
52 ExpectedResults &setValuesUnit(Unit valuesUnit)
53 {
53 {
54 m_ValuesUnit = std::move(valuesUnit);
54 m_ValuesUnit = std::move(valuesUnit);
55 return *this;
55 return *this;
56 }
56 }
57
57
58 ExpectedResults &setValuesData(QVector<double> valuesData)
58 ExpectedResults &setValuesData(QVector<double> valuesData)
59 {
59 {
60 m_ValuesData.clear();
60 m_ValuesData.clear();
61 m_ValuesData.push_back(std::move(valuesData));
61 m_ValuesData.push_back(std::move(valuesData));
62 return *this;
62 return *this;
63 }
63 }
64
64
65 ExpectedResults &setValuesData(QVector<QVector<double> > valuesData)
65 ExpectedResults &setValuesData(QVector<QVector<double> > valuesData)
66 {
66 {
67 m_ValuesData = std::move(valuesData);
67 m_ValuesData = std::move(valuesData);
68 return *this;
68 return *this;
69 }
69 }
70
70
71 ExpectedResults &setYAxisEnabled(bool yAxisEnabled)
71 ExpectedResults &setYAxisEnabled(bool yAxisEnabled)
72 {
72 {
73 m_YAxisEnabled = yAxisEnabled;
73 m_YAxisEnabled = yAxisEnabled;
74 return *this;
74 return *this;
75 }
75 }
76
76
77 ExpectedResults &setYAxisUnit(Unit yAxisUnit)
77 ExpectedResults &setYAxisUnit(Unit yAxisUnit)
78 {
78 {
79 m_YAxisUnit = std::move(yAxisUnit);
79 m_YAxisUnit = std::move(yAxisUnit);
80 return *this;
80 return *this;
81 }
81 }
82
82
83 ExpectedResults &setYAxisData(QVector<double> yAxisData)
83 ExpectedResults &setYAxisData(QVector<double> yAxisData)
84 {
84 {
85 m_YAxisData = std::move(yAxisData);
85 m_YAxisData = std::move(yAxisData);
86 return *this;
86 return *this;
87 }
87 }
88
88
89 /**
89 /**
90 * Validates a DataSeries compared to the expected results
90 * Validates a DataSeries compared to the expected results
91 * @param results the DataSeries to validate
91 * @param results the DataSeries to validate
92 */
92 */
93 void validate(std::shared_ptr<IDataSeries> results)
93 void validate(std::shared_ptr<IDataSeries> results)
94 {
94 {
95 if (m_ParsingOK) {
95 if (m_ParsingOK) {
96 auto dataSeries = dynamic_cast<T *>(results.get());
96 auto dataSeries = dynamic_cast<T *>(results.get());
97 if (dataSeries == nullptr) {
97 if (dataSeries == nullptr) {
98
98
99 // No unit detected, parsink ok but data is nullptr
99 // No unit detected, parsink ok but data is nullptr
100 // TODO, improve the test to verify that the data is null
100 // TODO, improve the test to verify that the data is null
101 return;
101 return;
102 }
102 }
103
103
104 // Checks units
104 // Checks units
105 QVERIFY(dataSeries->xAxisUnit() == m_XAxisUnit);
105 QVERIFY(dataSeries->xAxisUnit() == m_XAxisUnit);
106 QVERIFY(dataSeries->valuesUnit() == m_ValuesUnit);
106 QVERIFY(dataSeries->valuesUnit() == m_ValuesUnit);
107
107
108 auto verifyRange = [dataSeries](const auto &expectedData, const auto &equalFun) {
108 auto verifyRange = [dataSeries](const auto &expectedData, const auto &equalFun) {
109 QVERIFY(std::equal(dataSeries->cbegin(), dataSeries->cend(), expectedData.cbegin(),
109 QVERIFY(std::equal(dataSeries->cbegin(), dataSeries->cend(), expectedData.cbegin(),
110 expectedData.cend(),
110 expectedData.cend(),
111 [&equalFun](const auto &dataSeriesIt, const auto &expectedX) {
111 [&equalFun](const auto &dataSeriesIt, const auto &expectedX) {
112 return equalFun(dataSeriesIt, expectedX);
112 return equalFun(dataSeriesIt, expectedX);
113 }));
113 }));
114 };
114 };
115
115
116 // Checks x-axis data
116 // Checks x-axis data
117 verifyRange(m_XAxisData, [](const auto &seriesIt, const auto &value) {
117 verifyRange(m_XAxisData, [](const auto &seriesIt, const auto &value) {
118 return seriesIt.x() == value;
118 return seriesIt.x() == value;
119 });
119 });
120
120
121 // Checks values data of each component
121 // Checks values data of each component
122 for (auto i = 0; i < m_ValuesData.size(); ++i) {
122 for (auto i = 0; i < m_ValuesData.size(); ++i) {
123 verifyRange(m_ValuesData.at(i), [i](const auto &seriesIt, const auto &value) {
123 verifyRange(m_ValuesData.at(i), [i](const auto &seriesIt, const auto &value) {
124 auto itValue = seriesIt.value(i);
124 auto itValue = seriesIt.value(i);
125 return (std::isnan(itValue) && std::isnan(value)) || seriesIt.value(i) == value;
125 return (std::isnan(itValue) && std::isnan(value)) || seriesIt.value(i) == value;
126 });
126 });
127 }
127 }
128
128
129 // Checks y-axis (if defined)
129 // Checks y-axis (if defined)
130 auto yAxis = dataSeries->yAxis();
130 auto yAxis = dataSeries->yAxis();
131 QCOMPARE(yAxis.isDefined(), m_YAxisEnabled);
131 QCOMPARE(yAxis.isDefined(), m_YAxisEnabled);
132
132
133 if (m_YAxisEnabled) {
133 if (m_YAxisEnabled) {
134 // Unit
134 // Unit
135 QCOMPARE(yAxis.unit(), m_YAxisUnit);
135 QCOMPARE(yAxis.unit(), m_YAxisUnit);
136
136
137 // Data
137 // Data
138 QVERIFY(std::equal(yAxis.cbegin(), yAxis.cend(), m_YAxisData.cbegin(),
138 QVERIFY(std::equal(yAxis.cbegin(), yAxis.cend(), m_YAxisData.cbegin(),
139 m_YAxisData.cend(), [](const auto &it, const auto &expectedVal) {
139 m_YAxisData.cend(), [](const auto &it, const auto &expectedVal) {
140 return it.first() == expectedVal;
140 return it.first() == expectedVal;
141 }));
141 }));
142 }
142 }
143 }
143 }
144 else {
144 else {
145 QVERIFY(results == nullptr);
145 QVERIFY(results == nullptr);
146 }
146 }
147 }
147 }
148
148
149 // Parsing was successfully completed
149 // Parsing was successfully completed
150 bool m_ParsingOK{false};
150 bool m_ParsingOK{false};
151 // Expected x-axis unit
151 // Expected x-axis unit
152 Unit m_XAxisUnit{};
152 Unit m_XAxisUnit{};
153 // Expected x-axis data
153 // Expected x-axis data
154 QVector<double> m_XAxisData{};
154 QVector<double> m_XAxisData{};
155 // Expected values unit
155 // Expected values unit
156 Unit m_ValuesUnit{};
156 Unit m_ValuesUnit{};
157 // Expected values data
157 // Expected values data
158 QVector<QVector<double> > m_ValuesData{};
158 QVector<QVector<double> > m_ValuesData{};
159 // Expected data series has y-axis
159 // Expected data series has y-axis
160 bool m_YAxisEnabled{false};
160 bool m_YAxisEnabled{false};
161 // Expected y-axis unit (if axis defined)
161 // Expected y-axis unit (if axis defined)
162 Unit m_YAxisUnit{};
162 Unit m_YAxisUnit{};
163 // Expected y-axis data (if axis defined)
163 // Expected y-axis data (if axis defined)
164 QVector<double> m_YAxisData{};
164 QVector<double> m_YAxisData{};
165 };
165 };
166
166
167 } // namespace
167 } // namespace
168
168
169 Q_DECLARE_METATYPE(ExpectedResults<ScalarSeries>)
169 Q_DECLARE_METATYPE(ExpectedResults<ScalarSeries>)
170 Q_DECLARE_METATYPE(ExpectedResults<SpectrogramSeries>)
170 Q_DECLARE_METATYPE(ExpectedResults<SpectrogramSeries>)
171 Q_DECLARE_METATYPE(ExpectedResults<VectorSeries>)
171 Q_DECLARE_METATYPE(ExpectedResults<VectorSeries>)
172
172
173 class TestAmdaResultParser : public QObject {
173 class TestAmdaResultParser : public QObject {
174 Q_OBJECT
174 Q_OBJECT
175 private:
175 private:
176 template <typename T>
176 template <typename T>
177 void testReadDataStructure()
177 void testReadDataStructure()
178 {
178 {
179 // ////////////// //
179 // ////////////// //
180 // Test structure //
180 // Test structure //
181 // ////////////// //
181 // ////////////// //
182
182
183 // Name of TXT file to read
183 // Name of TXT file to read
184 QTest::addColumn<QString>("inputFileName");
184 QTest::addColumn<QString>("inputFileName");
185 // Expected results
185 // Expected results
186 QTest::addColumn<ExpectedResults<T> >("expectedResults");
186 QTest::addColumn<ExpectedResults<T> >("expectedResults");
187 }
187 }
188
188
189 template <typename T>
189 template <typename T>
190 void testRead(AmdaResultParser::ValueType valueType)
190 void testRead(DataSeriesType valueType)
191 {
191 {
192 QFETCH(QString, inputFileName);
192 QFETCH(QString, inputFileName);
193 QFETCH(ExpectedResults<T>, expectedResults);
193 QFETCH(ExpectedResults<T>, expectedResults);
194
194
195 // Parses file
195 // Parses file
196 auto filePath = inputFilePath(inputFileName);
196 auto filePath = inputFilePath(inputFileName);
197 auto results = AmdaResultParser::readTxt(filePath, valueType);
197 auto results = AmdaResultParser::readTxt(filePath, valueType);
198
198
199 // ///////////////// //
199 // ///////////////// //
200 // Validates results //
200 // Validates results //
201 // ///////////////// //
201 // ///////////////// //
202 expectedResults.validate(results);
202 expectedResults.validate(results);
203 }
203 }
204
204
205 private slots:
205 private slots:
206 /// Input test data
206 /// Input test data
207 /// @sa testReadScalarTxt()
207 /// @sa testReadScalarTxt()
208 void testReadScalarTxt_data();
208 void testReadScalarTxt_data();
209
209
210 /// Tests parsing scalar series of a TXT file
210 /// Tests parsing scalar series of a TXT file
211 void testReadScalarTxt();
211 void testReadScalarTxt();
212
212
213 /// Input test data
213 /// Input test data
214 /// @sa testReadSpectrogramTxt()
214 /// @sa testReadSpectrogramTxt()
215 void testReadSpectrogramTxt_data();
215 void testReadSpectrogramTxt_data();
216
216
217 /// Tests parsing spectrogram series of a TXT file
217 /// Tests parsing spectrogram series of a TXT file
218 void testReadSpectrogramTxt();
218 void testReadSpectrogramTxt();
219
219
220 /// Input test data
220 /// Input test data
221 /// @sa testReadVectorTxt()
221 /// @sa testReadVectorTxt()
222 void testReadVectorTxt_data();
222 void testReadVectorTxt_data();
223
223
224 /// Tests parsing vector series of a TXT file
224 /// Tests parsing vector series of a TXT file
225 void testReadVectorTxt();
225 void testReadVectorTxt();
226 };
226 };
227
227
228 void TestAmdaResultParser::testReadScalarTxt_data()
228 void TestAmdaResultParser::testReadScalarTxt_data()
229 {
229 {
230 testReadDataStructure<ScalarSeries>();
230 testReadDataStructure<ScalarSeries>();
231
231
232 // ////////// //
232 // ////////// //
233 // Test cases //
233 // Test cases //
234 // ////////// //
234 // ////////// //
235
235
236 // Valid files
236 // Valid files
237 QTest::newRow("Valid file")
237 QTest::newRow("Valid file")
238 << QStringLiteral("ValidScalar1.txt")
238 << QStringLiteral("ValidScalar1.txt")
239 << ExpectedResults<ScalarSeries>{}
239 << ExpectedResults<ScalarSeries>{}
240 .setParsingOK(true)
240 .setParsingOK(true)
241 .setXAxisUnit(Unit{"nT", true})
241 .setXAxisUnit(Unit{"nT", true})
242 .setXAxisData({dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
242 .setXAxisData({dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
243 dateTime(2013, 9, 23, 9, 2, 30), dateTime(2013, 9, 23, 9, 3, 30),
243 dateTime(2013, 9, 23, 9, 2, 30), dateTime(2013, 9, 23, 9, 3, 30),
244 dateTime(2013, 9, 23, 9, 4, 30), dateTime(2013, 9, 23, 9, 5, 30),
244 dateTime(2013, 9, 23, 9, 4, 30), dateTime(2013, 9, 23, 9, 5, 30),
245 dateTime(2013, 9, 23, 9, 6, 30), dateTime(2013, 9, 23, 9, 7, 30),
245 dateTime(2013, 9, 23, 9, 6, 30), dateTime(2013, 9, 23, 9, 7, 30),
246 dateTime(2013, 9, 23, 9, 8, 30), dateTime(2013, 9, 23, 9, 9, 30)})
246 dateTime(2013, 9, 23, 9, 8, 30), dateTime(2013, 9, 23, 9, 9, 30)})
247 .setValuesData({-2.83950, -2.71850, -2.52150, -2.57633, -2.58050, -2.48325, -2.63025,
247 .setValuesData({-2.83950, -2.71850, -2.52150, -2.57633, -2.58050, -2.48325, -2.63025,
248 -2.55800, -2.43250, -2.42200});
248 -2.55800, -2.43250, -2.42200});
249
249
250 QTest::newRow("Valid file (value of first line is invalid but it is converted to NaN")
250 QTest::newRow("Valid file (value of first line is invalid but it is converted to NaN")
251 << QStringLiteral("WrongValue.txt")
251 << QStringLiteral("WrongValue.txt")
252 << ExpectedResults<ScalarSeries>{}
252 << ExpectedResults<ScalarSeries>{}
253 .setParsingOK(true)
253 .setParsingOK(true)
254 .setXAxisUnit(Unit{"nT", true})
254 .setXAxisUnit(Unit{"nT", true})
255 .setXAxisData({dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
255 .setXAxisData({dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
256 dateTime(2013, 9, 23, 9, 2, 30)})
256 dateTime(2013, 9, 23, 9, 2, 30)})
257 .setValuesData({std::numeric_limits<double>::quiet_NaN(), -2.71850, -2.52150});
257 .setValuesData({std::numeric_limits<double>::quiet_NaN(), -2.71850, -2.52150});
258
258
259 QTest::newRow("Valid file that contains NaN values")
259 QTest::newRow("Valid file that contains NaN values")
260 << QStringLiteral("NaNValue.txt")
260 << QStringLiteral("NaNValue.txt")
261 << ExpectedResults<ScalarSeries>{}
261 << ExpectedResults<ScalarSeries>{}
262 .setParsingOK(true)
262 .setParsingOK(true)
263 .setXAxisUnit(Unit{("nT"), true})
263 .setXAxisUnit(Unit{("nT"), true})
264 .setXAxisData({dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
264 .setXAxisData({dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
265 dateTime(2013, 9, 23, 9, 2, 30)})
265 dateTime(2013, 9, 23, 9, 2, 30)})
266 .setValuesData({std::numeric_limits<double>::quiet_NaN(), -2.71850, -2.52150});
266 .setValuesData({std::numeric_limits<double>::quiet_NaN(), -2.71850, -2.52150});
267
267
268 // Valid files but with some invalid lines (wrong unit, wrong values, etc.)
268 // Valid files but with some invalid lines (wrong unit, wrong values, etc.)
269 QTest::newRow("No unit file")
269 QTest::newRow("No unit file")
270 << QStringLiteral("NoUnit.txt")
270 << QStringLiteral("NoUnit.txt")
271 << ExpectedResults<ScalarSeries>{}.setParsingOK(true).setXAxisUnit(Unit{"", true});
271 << ExpectedResults<ScalarSeries>{}.setParsingOK(true).setXAxisUnit(Unit{"", true});
272
272
273 QTest::newRow("Wrong unit file")
273 QTest::newRow("Wrong unit file")
274 << QStringLiteral("WrongUnit.txt")
274 << QStringLiteral("WrongUnit.txt")
275 << ExpectedResults<ScalarSeries>{}
275 << ExpectedResults<ScalarSeries>{}
276 .setParsingOK(true)
276 .setParsingOK(true)
277 .setXAxisUnit(Unit{"", true})
277 .setXAxisUnit(Unit{"", true})
278 .setXAxisData({dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
278 .setXAxisData({dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
279 dateTime(2013, 9, 23, 9, 2, 30)})
279 dateTime(2013, 9, 23, 9, 2, 30)})
280 .setValuesData({-2.83950, -2.71850, -2.52150});
280 .setValuesData({-2.83950, -2.71850, -2.52150});
281
281
282 QTest::newRow("Wrong results file (date of first line is invalid")
282 QTest::newRow("Wrong results file (date of first line is invalid")
283 << QStringLiteral("WrongDate.txt")
283 << QStringLiteral("WrongDate.txt")
284 << ExpectedResults<ScalarSeries>{}
284 << ExpectedResults<ScalarSeries>{}
285 .setParsingOK(true)
285 .setParsingOK(true)
286 .setXAxisUnit(Unit{"nT", true})
286 .setXAxisUnit(Unit{"nT", true})
287 .setXAxisData({dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)})
287 .setXAxisData({dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)})
288 .setValuesData({-2.71850, -2.52150});
288 .setValuesData({-2.71850, -2.52150});
289
289
290 QTest::newRow("Wrong results file (too many values for first line")
290 QTest::newRow("Wrong results file (too many values for first line")
291 << QStringLiteral("TooManyValues.txt")
291 << QStringLiteral("TooManyValues.txt")
292 << ExpectedResults<ScalarSeries>{}
292 << ExpectedResults<ScalarSeries>{}
293 .setParsingOK(true)
293 .setParsingOK(true)
294 .setXAxisUnit(Unit{"nT", true})
294 .setXAxisUnit(Unit{"nT", true})
295 .setXAxisData({dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)})
295 .setXAxisData({dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)})
296 .setValuesData({-2.71850, -2.52150});
296 .setValuesData({-2.71850, -2.52150});
297
297
298 QTest::newRow("Wrong results file (x of first line is NaN")
298 QTest::newRow("Wrong results file (x of first line is NaN")
299 << QStringLiteral("NaNX.txt")
299 << QStringLiteral("NaNX.txt")
300 << ExpectedResults<ScalarSeries>{}
300 << ExpectedResults<ScalarSeries>{}
301 .setParsingOK(true)
301 .setParsingOK(true)
302 .setXAxisUnit(Unit{"nT", true})
302 .setXAxisUnit(Unit{"nT", true})
303 .setXAxisData({dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)})
303 .setXAxisData({dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)})
304 .setValuesData({-2.71850, -2.52150});
304 .setValuesData({-2.71850, -2.52150});
305
305
306 QTest::newRow("Invalid file type (vector)")
306 QTest::newRow("Invalid file type (vector)")
307 << QStringLiteral("ValidVector1.txt")
307 << QStringLiteral("ValidVector1.txt")
308 << ExpectedResults<ScalarSeries>{}.setParsingOK(true).setXAxisUnit(Unit{"nT", true});
308 << ExpectedResults<ScalarSeries>{}.setParsingOK(true).setXAxisUnit(Unit{"nT", true});
309
309
310 // Invalid files
310 // Invalid files
311 QTest::newRow("Invalid file (unexisting file)")
311 QTest::newRow("Invalid file (unexisting file)")
312 << QStringLiteral("UnexistingFile.txt")
312 << QStringLiteral("UnexistingFile.txt")
313 << ExpectedResults<ScalarSeries>{}.setParsingOK(false);
313 << ExpectedResults<ScalarSeries>{}.setParsingOK(false);
314
314
315 QTest::newRow("Invalid file (file not found on server)")
315 QTest::newRow("Invalid file (file not found on server)")
316 << QStringLiteral("FileNotFound.txt")
316 << QStringLiteral("FileNotFound.txt")
317 << ExpectedResults<ScalarSeries>{}.setParsingOK(false);
317 << ExpectedResults<ScalarSeries>{}.setParsingOK(false);
318 }
318 }
319
319
320 void TestAmdaResultParser::testReadScalarTxt()
320 void TestAmdaResultParser::testReadScalarTxt()
321 {
321 {
322 testRead<ScalarSeries>(AmdaResultParser::ValueType::SCALAR);
322 testRead<ScalarSeries>(DataSeriesType::SCALAR);
323 }
323 }
324
324
325 void TestAmdaResultParser::testReadSpectrogramTxt_data()
325 void TestAmdaResultParser::testReadSpectrogramTxt_data()
326 {
326 {
327 testReadDataStructure<SpectrogramSeries>();
327 testReadDataStructure<SpectrogramSeries>();
328
328
329 // ////////// //
329 // ////////// //
330 // Test cases //
330 // Test cases //
331 // ////////// //
331 // ////////// //
332
332
333 // Valid files
333 // Valid files
334 QTest::newRow("Valid file (three bands)")
334 QTest::newRow("Valid file (three bands)")
335 << QStringLiteral("spectro/ValidSpectrogram1.txt")
335 << QStringLiteral("spectro/ValidSpectrogram1.txt")
336 << ExpectedResults<SpectrogramSeries>{}
336 << ExpectedResults<SpectrogramSeries>{}
337 .setParsingOK(true)
337 .setParsingOK(true)
338 .setXAxisUnit(Unit{"t", true})
338 .setXAxisUnit(Unit{"t", true})
339 .setXAxisData({dateTime(2012, 11, 6, 9, 14, 35), dateTime(2012, 11, 6, 9, 16, 10),
339 .setXAxisData({dateTime(2012, 11, 6, 9, 14, 35), dateTime(2012, 11, 6, 9, 16, 10),
340 dateTime(2012, 11, 6, 9, 17, 45), dateTime(2012, 11, 6, 9, 19, 20),
340 dateTime(2012, 11, 6, 9, 17, 45), dateTime(2012, 11, 6, 9, 19, 20),
341 dateTime(2012, 11, 6, 9, 20, 55)})
341 dateTime(2012, 11, 6, 9, 20, 55)})
342 .setYAxisEnabled(true)
342 .setYAxisEnabled(true)
343 .setYAxisUnit(Unit{"eV"})
343 .setYAxisUnit(Unit{"eV"})
344 .setYAxisData({5.75, 7.6, 10.05}) // middle of the intervals of each band
344 .setYAxisData({5.75, 7.6, 10.05}) // middle of the intervals of each band
345 .setValuesUnit(Unit{"eV/(cm^2-s-sr-eV)"})
345 .setValuesUnit(Unit{"eV/(cm^2-s-sr-eV)"})
346 .setValuesData(QVector<QVector<double> >{
346 .setValuesData(QVector<QVector<double> >{
347 {16313.780, 12631.465, 8223.368, 27595.301, 12820.613},
347 {16313.780, 12631.465, 8223.368, 27595.301, 12820.613},
348 {15405.838, 11957.925, 15026.249, 25617.533, 11179.109},
348 {15405.838, 11957.925, 15026.249, 25617.533, 11179.109},
349 {8946.475, 18133.158, 10875.621, 24051.619, 19283.221}});
349 {8946.475, 18133.158, 10875.621, 24051.619, 19283.221}});
350
350
351 auto fourBandsResult
351 auto fourBandsResult
352 = ExpectedResults<SpectrogramSeries>{}
352 = ExpectedResults<SpectrogramSeries>{}
353 .setParsingOK(true)
353 .setParsingOK(true)
354 .setXAxisUnit(Unit{"t", true})
354 .setXAxisUnit(Unit{"t", true})
355 .setXAxisData({dateTime(2012, 11, 6, 9, 14, 35), dateTime(2012, 11, 6, 9, 16, 10),
355 .setXAxisData({dateTime(2012, 11, 6, 9, 14, 35), dateTime(2012, 11, 6, 9, 16, 10),
356 dateTime(2012, 11, 6, 9, 17, 45), dateTime(2012, 11, 6, 9, 19, 20),
356 dateTime(2012, 11, 6, 9, 17, 45), dateTime(2012, 11, 6, 9, 19, 20),
357 dateTime(2012, 11, 6, 9, 20, 55)})
357 dateTime(2012, 11, 6, 9, 20, 55)})
358 .setYAxisEnabled(true)
358 .setYAxisEnabled(true)
359 .setYAxisUnit(Unit{"eV"})
359 .setYAxisUnit(Unit{"eV"})
360 .setYAxisData({5.75, 7.6, 10.05, 13.}) // middle of the intervals of each band
360 .setYAxisData({5.75, 7.6, 10.05, 13.}) // middle of the intervals of each band
361 .setValuesUnit(Unit{"eV/(cm^2-s-sr-eV)"})
361 .setValuesUnit(Unit{"eV/(cm^2-s-sr-eV)"})
362 .setValuesData(QVector<QVector<double> >{
362 .setValuesData(QVector<QVector<double> >{
363 {16313.780, 12631.465, 8223.368, 27595.301, 12820.613},
363 {16313.780, 12631.465, 8223.368, 27595.301, 12820.613},
364 {15405.838, 11957.925, 15026.249, 25617.533, 11179.109},
364 {15405.838, 11957.925, 15026.249, 25617.533, 11179.109},
365 {8946.475, 18133.158, 10875.621, 24051.619, 19283.221},
365 {8946.475, 18133.158, 10875.621, 24051.619, 19283.221},
366 {20907.664, 32076.725, 13008.381, 13142.759, 23226.998}});
366 {20907.664, 32076.725, 13008.381, 13142.759, 23226.998}});
367
367
368 QTest::newRow("Valid file (four bands)") << QStringLiteral("spectro/ValidSpectrogram2.txt")
368 QTest::newRow("Valid file (four bands)") << QStringLiteral("spectro/ValidSpectrogram2.txt")
369 << fourBandsResult;
369 << fourBandsResult;
370 QTest::newRow("Valid file (four unsorted bands)")
370 QTest::newRow("Valid file (four unsorted bands)")
371 << QStringLiteral("spectro/ValidSpectrogram3.txt")
371 << QStringLiteral("spectro/ValidSpectrogram3.txt")
372 << fourBandsResult; // Bands and values are sorted
372 << fourBandsResult; // Bands and values are sorted
373
373
374 auto nan = std::numeric_limits<double>::quiet_NaN();
374 auto nan = std::numeric_limits<double>::quiet_NaN();
375
375
376 auto nanValuesResult
376 auto nanValuesResult
377 = ExpectedResults<SpectrogramSeries>{}
377 = ExpectedResults<SpectrogramSeries>{}
378 .setParsingOK(true)
378 .setParsingOK(true)
379 .setXAxisUnit(Unit{"t", true})
379 .setXAxisUnit(Unit{"t", true})
380 .setXAxisData({dateTime(2012, 11, 6, 9, 14, 35), dateTime(2012, 11, 6, 9, 16, 10),
380 .setXAxisData({dateTime(2012, 11, 6, 9, 14, 35), dateTime(2012, 11, 6, 9, 16, 10),
381 dateTime(2012, 11, 6, 9, 17, 45), dateTime(2012, 11, 6, 9, 19, 20),
381 dateTime(2012, 11, 6, 9, 17, 45), dateTime(2012, 11, 6, 9, 19, 20),
382 dateTime(2012, 11, 6, 9, 20, 55)})
382 dateTime(2012, 11, 6, 9, 20, 55)})
383 .setYAxisEnabled(true)
383 .setYAxisEnabled(true)
384 .setYAxisUnit(Unit{"eV"})
384 .setYAxisUnit(Unit{"eV"})
385 .setYAxisData({5.75, 7.6, 10.05, 13.}) // middle of the intervals of each band
385 .setYAxisData({5.75, 7.6, 10.05, 13.}) // middle of the intervals of each band
386 .setValuesUnit(Unit{"eV/(cm^2-s-sr-eV)"})
386 .setValuesUnit(Unit{"eV/(cm^2-s-sr-eV)"})
387 .setValuesData(
387 .setValuesData(
388 QVector<QVector<double> >{{nan, 12631.465, 8223.368, 27595.301, 12820.613},
388 QVector<QVector<double> >{{nan, 12631.465, 8223.368, 27595.301, 12820.613},
389 {15405.838, nan, nan, 25617.533, 11179.109},
389 {15405.838, nan, nan, 25617.533, 11179.109},
390 {8946.475, 18133.158, 10875.621, 24051.619, 19283.221},
390 {8946.475, 18133.158, 10875.621, 24051.619, 19283.221},
391 {nan, nan, nan, nan, nan}});
391 {nan, nan, nan, nan, nan}});
392
392
393 QTest::newRow("Valid file (containing NaN values)")
393 QTest::newRow("Valid file (containing NaN values)")
394 << QStringLiteral("spectro/ValidSpectrogramNaNValues.txt") << nanValuesResult;
394 << QStringLiteral("spectro/ValidSpectrogramNaNValues.txt") << nanValuesResult;
395 QTest::newRow("Valid file (containing fill values)")
395 QTest::newRow("Valid file (containing fill values)")
396 << QStringLiteral("spectro/ValidSpectrogramFillValues.txt")
396 << QStringLiteral("spectro/ValidSpectrogramFillValues.txt")
397 << nanValuesResult; // Fill values are replaced by NaN values in the data series
397 << nanValuesResult; // Fill values are replaced by NaN values in the data series
398
398
399 QTest::newRow("Valid file (containing data holes, resolution = 3 minutes)")
399 QTest::newRow("Valid file (containing data holes, resolution = 3 minutes)")
400 << QStringLiteral("spectro/ValidSpectrogramDataHoles.txt")
400 << QStringLiteral("spectro/ValidSpectrogramDataHoles.txt")
401 << ExpectedResults<SpectrogramSeries>{}
401 << ExpectedResults<SpectrogramSeries>{}
402 .setParsingOK(true)
402 .setParsingOK(true)
403 .setXAxisUnit(Unit{"t", true})
403 .setXAxisUnit(Unit{"t", true})
404 .setXAxisData({dateTime(2011, 12, 10, 12, 10, 54), //
404 .setXAxisData({dateTime(2011, 12, 10, 12, 10, 54), //
405 dateTime(2011, 12, 10, 12, 13, 54), // Data hole
405 dateTime(2011, 12, 10, 12, 13, 54), // Data hole
406 dateTime(2011, 12, 10, 12, 16, 54), // Data hole
406 dateTime(2011, 12, 10, 12, 16, 54), // Data hole
407 dateTime(2011, 12, 10, 12, 17, 23), //
407 dateTime(2011, 12, 10, 12, 17, 23), //
408 dateTime(2011, 12, 10, 12, 20, 23), // Data hole
408 dateTime(2011, 12, 10, 12, 20, 23), // Data hole
409 dateTime(2011, 12, 10, 12, 23, 23), // Data hole
409 dateTime(2011, 12, 10, 12, 23, 23), // Data hole
410 dateTime(2011, 12, 10, 12, 23, 51), //
410 dateTime(2011, 12, 10, 12, 23, 51), //
411 dateTime(2011, 12, 10, 12, 26, 51), // Data hole
411 dateTime(2011, 12, 10, 12, 26, 51), // Data hole
412 dateTime(2011, 12, 10, 12, 29, 51), // Data hole
412 dateTime(2011, 12, 10, 12, 29, 51), // Data hole
413 dateTime(2011, 12, 10, 12, 30, 19), //
413 dateTime(2011, 12, 10, 12, 30, 19), //
414 dateTime(2011, 12, 10, 12, 33, 19), // Data hole
414 dateTime(2011, 12, 10, 12, 33, 19), // Data hole
415 dateTime(2011, 12, 10, 12, 35, 04), //
415 dateTime(2011, 12, 10, 12, 35, 04), //
416 dateTime(2011, 12, 10, 12, 36, 41), //
416 dateTime(2011, 12, 10, 12, 36, 41), //
417 dateTime(2011, 12, 10, 12, 38, 18), //
417 dateTime(2011, 12, 10, 12, 38, 18), //
418 dateTime(2011, 12, 10, 12, 39, 55)})
418 dateTime(2011, 12, 10, 12, 39, 55)})
419 .setYAxisEnabled(true)
419 .setYAxisEnabled(true)
420 .setYAxisUnit(Unit{"eV"})
420 .setYAxisUnit(Unit{"eV"})
421 .setYAxisData({16485.85, 20996.1}) // middle of the intervals of each band
421 .setYAxisData({16485.85, 20996.1}) // middle of the intervals of each band
422 .setValuesUnit(Unit{"eV/(cm^2-s-sr-eV)"})
422 .setValuesUnit(Unit{"eV/(cm^2-s-sr-eV)"})
423 .setValuesData(QVector<QVector<double> >{{2577578.000, //
423 .setValuesData(QVector<QVector<double> >{{2577578.000, //
424 nan, // Data hole
424 nan, // Data hole
425 nan, // Data hole
425 nan, // Data hole
426 2314121.500, //
426 2314121.500, //
427 nan, // Data hole
427 nan, // Data hole
428 nan, // Data hole
428 nan, // Data hole
429 2063608.750, //
429 2063608.750, //
430 nan, // Data hole
430 nan, // Data hole
431 nan, // Data hole
431 nan, // Data hole
432 2234525.500, //
432 2234525.500, //
433 nan, // Data hole
433 nan, // Data hole
434 1670215.250, //
434 1670215.250, //
435 1689243.250, //
435 1689243.250, //
436 1654617.125, //
436 1654617.125, //
437 1504983.750},
437 1504983.750},
438 {2336016.000, //
438 {2336016.000, //
439 nan, // Data hole
439 nan, // Data hole
440 nan, // Data hole
440 nan, // Data hole
441 1712093.125, //
441 1712093.125, //
442 nan, // Data hole
442 nan, // Data hole
443 nan, // Data hole
443 nan, // Data hole
444 1614491.625, //
444 1614491.625, //
445 nan, // Data hole
445 nan, // Data hole
446 nan, // Data hole
446 nan, // Data hole
447 1764516.500, //
447 1764516.500, //
448 nan, // Data hole
448 nan, // Data hole
449 1688078.500, //
449 1688078.500, //
450 1743183.500, //
450 1743183.500, //
451 1733603.250, //
451 1733603.250, //
452 1708356.500}});
452 1708356.500}});
453
453
454 QTest::newRow(
454 QTest::newRow(
455 "Valid file (containing data holes at the beginning and the end, resolution = 4 minutes)")
455 "Valid file (containing data holes at the beginning and the end, resolution = 4 minutes)")
456 << QStringLiteral("spectro/ValidSpectrogramDataHoles2.txt")
456 << QStringLiteral("spectro/ValidSpectrogramDataHoles2.txt")
457 << ExpectedResults<SpectrogramSeries>{}
457 << ExpectedResults<SpectrogramSeries>{}
458 .setParsingOK(true)
458 .setParsingOK(true)
459 .setXAxisUnit(Unit{"t", true})
459 .setXAxisUnit(Unit{"t", true})
460 .setXAxisData({
460 .setXAxisData({
461 dateTime(2011, 12, 10, 12, 2, 54), // Data hole
461 dateTime(2011, 12, 10, 12, 2, 54), // Data hole
462 dateTime(2011, 12, 10, 12, 6, 54), // Data hole
462 dateTime(2011, 12, 10, 12, 6, 54), // Data hole
463 dateTime(2011, 12, 10, 12, 10, 54), //
463 dateTime(2011, 12, 10, 12, 10, 54), //
464 dateTime(2011, 12, 10, 12, 14, 54), // Data hole
464 dateTime(2011, 12, 10, 12, 14, 54), // Data hole
465 dateTime(2011, 12, 10, 12, 17, 23), //
465 dateTime(2011, 12, 10, 12, 17, 23), //
466 dateTime(2011, 12, 10, 12, 21, 23), // Data hole
466 dateTime(2011, 12, 10, 12, 21, 23), // Data hole
467 dateTime(2011, 12, 10, 12, 23, 51), //
467 dateTime(2011, 12, 10, 12, 23, 51), //
468 dateTime(2011, 12, 10, 12, 27, 51), // Data hole
468 dateTime(2011, 12, 10, 12, 27, 51), // Data hole
469 dateTime(2011, 12, 10, 12, 30, 19), //
469 dateTime(2011, 12, 10, 12, 30, 19), //
470 dateTime(2011, 12, 10, 12, 34, 19), // Data hole
470 dateTime(2011, 12, 10, 12, 34, 19), // Data hole
471 dateTime(2011, 12, 10, 12, 35, 04), //
471 dateTime(2011, 12, 10, 12, 35, 04), //
472 dateTime(2011, 12, 10, 12, 36, 41), //
472 dateTime(2011, 12, 10, 12, 36, 41), //
473 dateTime(2011, 12, 10, 12, 38, 18), //
473 dateTime(2011, 12, 10, 12, 38, 18), //
474 dateTime(2011, 12, 10, 12, 39, 55),
474 dateTime(2011, 12, 10, 12, 39, 55),
475 dateTime(2011, 12, 10, 12, 43, 55), // Data hole
475 dateTime(2011, 12, 10, 12, 43, 55), // Data hole
476 dateTime(2011, 12, 10, 12, 47, 55), // Data hole
476 dateTime(2011, 12, 10, 12, 47, 55), // Data hole
477 dateTime(2011, 12, 10, 12, 51, 55), // Data hole
477 dateTime(2011, 12, 10, 12, 51, 55), // Data hole
478 dateTime(2011, 12, 10, 12, 55, 55), // Data hole
478 dateTime(2011, 12, 10, 12, 55, 55), // Data hole
479 dateTime(2011, 12, 10, 12, 59, 55) // Data hole
479 dateTime(2011, 12, 10, 12, 59, 55) // Data hole
480 })
480 })
481 .setYAxisEnabled(true)
481 .setYAxisEnabled(true)
482 .setYAxisUnit(Unit{"eV"})
482 .setYAxisUnit(Unit{"eV"})
483 .setYAxisData({16485.85, 20996.1}) // middle of the intervals of each band
483 .setYAxisData({16485.85, 20996.1}) // middle of the intervals of each band
484 .setValuesUnit(Unit{"eV/(cm^2-s-sr-eV)"})
484 .setValuesUnit(Unit{"eV/(cm^2-s-sr-eV)"})
485 .setValuesData(QVector<QVector<double> >{{
485 .setValuesData(QVector<QVector<double> >{{
486 nan, // Data hole
486 nan, // Data hole
487 nan, // Data hole
487 nan, // Data hole
488 2577578.000, //
488 2577578.000, //
489 nan, // Data hole
489 nan, // Data hole
490 2314121.500, //
490 2314121.500, //
491 nan, // Data hole
491 nan, // Data hole
492 2063608.750, //
492 2063608.750, //
493 nan, // Data hole
493 nan, // Data hole
494 2234525.500, //
494 2234525.500, //
495 nan, // Data hole
495 nan, // Data hole
496 1670215.250, //
496 1670215.250, //
497 1689243.250, //
497 1689243.250, //
498 1654617.125, //
498 1654617.125, //
499 1504983.750, //
499 1504983.750, //
500 nan, // Data hole
500 nan, // Data hole
501 nan, // Data hole
501 nan, // Data hole
502 nan, // Data hole
502 nan, // Data hole
503 nan, // Data hole
503 nan, // Data hole
504 nan // Data hole
504 nan // Data hole
505 },
505 },
506 {
506 {
507 nan, // Data hole
507 nan, // Data hole
508 nan, // Data hole
508 nan, // Data hole
509 2336016.000, //
509 2336016.000, //
510 nan, // Data hole
510 nan, // Data hole
511 1712093.125, //
511 1712093.125, //
512 nan, // Data hole
512 nan, // Data hole
513 1614491.625, //
513 1614491.625, //
514 nan, // Data hole
514 nan, // Data hole
515 1764516.500, //
515 1764516.500, //
516 nan, // Data hole
516 nan, // Data hole
517 1688078.500, //
517 1688078.500, //
518 1743183.500, //
518 1743183.500, //
519 1733603.250, //
519 1733603.250, //
520 1708356.500, //
520 1708356.500, //
521 nan, // Data hole
521 nan, // Data hole
522 nan, // Data hole
522 nan, // Data hole
523 nan, // Data hole
523 nan, // Data hole
524 nan, // Data hole
524 nan, // Data hole
525 nan // Data hole
525 nan // Data hole
526 }});
526 }});
527
527
528 // Invalid files
528 // Invalid files
529 QTest::newRow("Invalid file (inconsistent bands)")
529 QTest::newRow("Invalid file (inconsistent bands)")
530 << QStringLiteral("spectro/InvalidSpectrogramWrongBands.txt")
530 << QStringLiteral("spectro/InvalidSpectrogramWrongBands.txt")
531 << ExpectedResults<SpectrogramSeries>{}.setParsingOK(false);
531 << ExpectedResults<SpectrogramSeries>{}.setParsingOK(false);
532 }
532 }
533
533
534 void TestAmdaResultParser::testReadSpectrogramTxt()
534 void TestAmdaResultParser::testReadSpectrogramTxt()
535 {
535 {
536 testRead<SpectrogramSeries>(AmdaResultParser::ValueType::SPECTROGRAM);
536 testRead<SpectrogramSeries>(DataSeriesType::SPECTROGRAM);
537 }
537 }
538
538
539 void TestAmdaResultParser::testReadVectorTxt_data()
539 void TestAmdaResultParser::testReadVectorTxt_data()
540 {
540 {
541 testReadDataStructure<VectorSeries>();
541 testReadDataStructure<VectorSeries>();
542
542
543 // ////////// //
543 // ////////// //
544 // Test cases //
544 // Test cases //
545 // ////////// //
545 // ////////// //
546
546
547 // Valid files
547 // Valid files
548 QTest::newRow("Valid file")
548 QTest::newRow("Valid file")
549 << QStringLiteral("ValidVector1.txt")
549 << QStringLiteral("ValidVector1.txt")
550 << ExpectedResults<VectorSeries>{}
550 << ExpectedResults<VectorSeries>{}
551 .setParsingOK(true)
551 .setParsingOK(true)
552 .setXAxisUnit(Unit{"nT", true})
552 .setXAxisUnit(Unit{"nT", true})
553 .setXAxisData({dateTime(2013, 7, 2, 9, 13, 50), dateTime(2013, 7, 2, 9, 14, 6),
553 .setXAxisData({dateTime(2013, 7, 2, 9, 13, 50), dateTime(2013, 7, 2, 9, 14, 6),
554 dateTime(2013, 7, 2, 9, 14, 22), dateTime(2013, 7, 2, 9, 14, 38),
554 dateTime(2013, 7, 2, 9, 14, 22), dateTime(2013, 7, 2, 9, 14, 38),
555 dateTime(2013, 7, 2, 9, 14, 54), dateTime(2013, 7, 2, 9, 15, 10),
555 dateTime(2013, 7, 2, 9, 14, 54), dateTime(2013, 7, 2, 9, 15, 10),
556 dateTime(2013, 7, 2, 9, 15, 26), dateTime(2013, 7, 2, 9, 15, 42),
556 dateTime(2013, 7, 2, 9, 15, 26), dateTime(2013, 7, 2, 9, 15, 42),
557 dateTime(2013, 7, 2, 9, 15, 58), dateTime(2013, 7, 2, 9, 16, 14)})
557 dateTime(2013, 7, 2, 9, 15, 58), dateTime(2013, 7, 2, 9, 16, 14)})
558 .setValuesData(
558 .setValuesData(
559 {{-0.332, -1.011, -1.457, -1.293, -1.217, -1.443, -1.278, -1.202, -1.22, -1.259},
559 {{-0.332, -1.011, -1.457, -1.293, -1.217, -1.443, -1.278, -1.202, -1.22, -1.259},
560 {3.206, 2.999, 2.785, 2.736, 2.612, 2.564, 2.892, 2.862, 2.859, 2.764},
560 {3.206, 2.999, 2.785, 2.736, 2.612, 2.564, 2.892, 2.862, 2.859, 2.764},
561 {0.058, 0.496, 1.018, 1.485, 1.662, 1.505, 1.168, 1.244, 1.15, 1.358}});
561 {0.058, 0.496, 1.018, 1.485, 1.662, 1.505, 1.168, 1.244, 1.15, 1.358}});
562
562
563 // Valid files but with some invalid lines (wrong unit, wrong values, etc.)
563 // Valid files but with some invalid lines (wrong unit, wrong values, etc.)
564 QTest::newRow("Invalid file type (scalar)")
564 QTest::newRow("Invalid file type (scalar)")
565 << QStringLiteral("ValidScalar1.txt")
565 << QStringLiteral("ValidScalar1.txt")
566 << ExpectedResults<VectorSeries>{}
566 << ExpectedResults<VectorSeries>{}
567 .setParsingOK(true)
567 .setParsingOK(true)
568 .setXAxisUnit(Unit{"nT", true})
568 .setXAxisUnit(Unit{"nT", true})
569 .setXAxisData({})
569 .setXAxisData({})
570 .setValuesData(QVector<QVector<double> >{{}, {}, {}});
570 .setValuesData(QVector<QVector<double> >{{}, {}, {}});
571 }
571 }
572
572
573 void TestAmdaResultParser::testReadVectorTxt()
573 void TestAmdaResultParser::testReadVectorTxt()
574 {
574 {
575 testRead<VectorSeries>(AmdaResultParser::ValueType::VECTOR);
575 testRead<VectorSeries>(DataSeriesType::VECTOR);
576 }
576 }
577
577
578 QTEST_MAIN(TestAmdaResultParser)
578 QTEST_MAIN(TestAmdaResultParser)
579 #include "TestAmdaResultParser.moc"
579 #include "TestAmdaResultParser.moc"
General Comments 0
You need to be logged in to leave comments. Login now