##// END OF EJS Templates
Implements validation of variable's data (4)...
Alexandre Leroux -
r1234:76dbe6c8f09b
parent child
Show More
@@ -1,200 +1,228
1 #include "FuzzingValidators.h"
1 #include "FuzzingValidators.h"
2 #include "FuzzingDefs.h"
2 #include "FuzzingDefs.h"
3
3
4 #include <Data/DataSeries.h>
4 #include <Data/DataSeries.h>
5 #include <Variable/Variable.h>
5 #include <Variable/Variable.h>
6
6
7 #include <QTest>
7 #include <QTest>
8
8
9 #include <functional>
9 #include <functional>
10
10
11 Q_LOGGING_CATEGORY(LOG_FuzzingValidators, "FuzzingValidators")
11 Q_LOGGING_CATEGORY(LOG_FuzzingValidators, "FuzzingValidators")
12
12
13 namespace {
13 namespace {
14
14
15 // ////////////// //
15 // ////////////// //
16 // DATA VALIDATOR //
16 // DATA VALIDATOR //
17 // ////////////// //
17 // ////////////// //
18
18
19 /// Singleton used to validate data of a variable
19 /// Singleton used to validate data of a variable
20 class DataValidatorHelper {
20 class DataValidatorHelper {
21 public:
21 public:
22 /// @return the single instance of the helper
22 /// @return the single instance of the helper
23 static DataValidatorHelper &instance();
23 static DataValidatorHelper &instance();
24 virtual ~DataValidatorHelper() noexcept = default;
24 virtual ~DataValidatorHelper() noexcept = default;
25
25
26 virtual void validate(const VariableState &variableState) const = 0;
26 virtual void validate(const VariableState &variableState) const = 0;
27 };
27 };
28
28
29 /**
29 /**
30 * Default implementation of @sa DataValidatorHelper
30 * Default implementation of @sa DataValidatorHelper
31 */
31 */
32 class DefaultDataValidatorHelper : public DataValidatorHelper {
32 class DefaultDataValidatorHelper : public DataValidatorHelper {
33 public:
33 public:
34 void validate(const VariableState &variableState) const override
34 void validate(const VariableState &variableState) const override
35 {
35 {
36 Q_UNUSED(variableState);
36 Q_UNUSED(variableState);
37 qCWarning(LOG_FuzzingValidators()).noquote() << "Checking variable's data... WARN: no data "
37 qCWarning(LOG_FuzzingValidators()).noquote() << "Checking variable's data... WARN: no data "
38 "verification is available for this server";
38 "verification is available for this server";
39 }
39 }
40 };
40 };
41
41
42 /// Data resolution in local server's files
42 /// Data resolution in local server's files
43 const auto LOCALHOST_SERVER_RESOLUTION = 4;
43 const auto LOCALHOST_SERVER_RESOLUTION = 4;
44 /// Reference value used to generate the data on the local server (a value is the number of seconds
45 /// between the data date and this reference date)
46 const auto LOCALHOST_REFERENCE_VALUE
47 = DateUtils::secondsSinceEpoch(QDateTime{QDate{2000, 1, 1}, QTime{}, Qt::UTC});
48
44 /**
49 /**
45 * Implementation of @sa DataValidatorHelper for the local AMDA server
50 * Implementation of @sa DataValidatorHelper for the local AMDA server
46 */
51 */
47 class LocalhostServerDataValidatorHelper : public DataValidatorHelper {
52 class LocalhostServerDataValidatorHelper : public DataValidatorHelper {
48 public:
53 public:
49 void validate(const VariableState &variableState) const override
54 void validate(const VariableState &variableState) const override
50 {
55 {
51 // Don't check data for null variable
56 // Don't check data for null variable
52 if (!variableState.m_Variable || variableState.m_Range == INVALID_RANGE) {
57 if (!variableState.m_Variable || variableState.m_Range == INVALID_RANGE) {
53 return;
58 return;
54 }
59 }
55
60
56 auto message = "Checking variable's data...";
61 auto message = "Checking variable's data...";
57 auto toDateString = [](double value) { return DateUtils::dateTime(value).toString(); };
62 auto toDateString = [](double value) { return DateUtils::dateTime(value).toString(); };
58
63
59 // Checks that data are defined
64 // Checks that data are defined
60 auto variableDataSeries = variableState.m_Variable->dataSeries();
65 auto variableDataSeries = variableState.m_Variable->dataSeries();
61 if (variableDataSeries == nullptr && variableState.m_Range != INVALID_RANGE) {
66 if (variableDataSeries == nullptr && variableState.m_Range != INVALID_RANGE) {
62 qCInfo(LOG_FuzzingValidators()).noquote()
67 qCInfo(LOG_FuzzingValidators()).noquote()
63 << message << "FAIL: the variable has no data while a range is defined";
68 << message << "FAIL: the variable has no data while a range is defined";
64 QFAIL("");
69 QFAIL("");
65 }
70 }
66
71
67 auto dataIts = variableDataSeries->xAxisRange(variableState.m_Range.m_TStart,
72 auto dataIts = variableDataSeries->xAxisRange(variableState.m_Range.m_TStart,
68 variableState.m_Range.m_TEnd);
73 variableState.m_Range.m_TEnd);
69
74
70 // Checks that the data are well defined in the range:
75 // Checks that the data are well defined in the range:
71 // - there is at least one data
76 // - there is at least one data
72 // - the data are consistent (no data holes)
77 // - the data are consistent (no data holes)
73 if (std::distance(dataIts.first, dataIts.second) == 0) {
78 if (std::distance(dataIts.first, dataIts.second) == 0) {
74 qCInfo(LOG_FuzzingValidators()).noquote()
79 qCInfo(LOG_FuzzingValidators()).noquote()
75 << message << "FAIL: the variable has no data";
80 << message << "FAIL: the variable has no data";
76 QFAIL("");
81 QFAIL("");
77 }
82 }
78
83
79 auto firstXAxisData = dataIts.first->x();
84 auto firstXAxisData = dataIts.first->x();
80 auto lastXAxisData = (dataIts.second - 1)->x();
85 auto lastXAxisData = (dataIts.second - 1)->x();
81
86
82 if (std::abs(firstXAxisData - variableState.m_Range.m_TStart) > LOCALHOST_SERVER_RESOLUTION
87 if (std::abs(firstXAxisData - variableState.m_Range.m_TStart) > LOCALHOST_SERVER_RESOLUTION
83 || std::abs(lastXAxisData - variableState.m_Range.m_TEnd)
88 || std::abs(lastXAxisData - variableState.m_Range.m_TEnd)
84 > LOCALHOST_SERVER_RESOLUTION) {
89 > LOCALHOST_SERVER_RESOLUTION) {
85 qCInfo(LOG_FuzzingValidators()).noquote()
90 qCInfo(LOG_FuzzingValidators()).noquote()
86 << message << "FAIL: the data in the defined range are inconsistent (data hole "
91 << message << "FAIL: the data in the defined range are inconsistent (data hole "
87 "found at the beginning or the end)";
92 "found at the beginning or the end)";
88 QFAIL("");
93 QFAIL("");
89 }
94 }
90
95
91 auto dataHoleIt = std::adjacent_find(
96 auto dataHoleIt = std::adjacent_find(
92 dataIts.first, dataIts.second, [](const auto &it1, const auto &it2) {
97 dataIts.first, dataIts.second, [](const auto &it1, const auto &it2) {
93 /// @todo: validate resolution
98 /// @todo: validate resolution
94 return std::abs(it1.x() - it2.x()) > 2 * (LOCALHOST_SERVER_RESOLUTION - 1);
99 return std::abs(it1.x() - it2.x()) > 2 * (LOCALHOST_SERVER_RESOLUTION - 1);
95 });
100 });
96
101
97 if (dataHoleIt != dataIts.second) {
102 if (dataHoleIt != dataIts.second) {
98 qCInfo(LOG_FuzzingValidators()).noquote()
103 qCInfo(LOG_FuzzingValidators()).noquote()
99 << message << "FAIL: the data in the defined range are inconsistent (data hole "
104 << message << "FAIL: the data in the defined range are inconsistent (data hole "
100 "found between times "
105 "found between times "
101 << toDateString(dataHoleIt->x()) << "and " << toDateString((dataHoleIt + 1)->x())
106 << toDateString(dataHoleIt->x()) << "and " << toDateString((dataHoleIt + 1)->x())
102 << ")";
107 << ")";
103 QFAIL("");
108 QFAIL("");
104 }
109 }
105
110
111 // Checks values
112 auto dataIndex = 0;
113 for (auto dataIt = dataIts.first; dataIt != dataIts.second; ++dataIt, ++dataIndex) {
114 auto xAxisData = dataIt->x();
115 auto valuesData = dataIt->values();
116 for (auto valueIndex = 0, valueEnd = valuesData.size(); valueIndex < valueEnd;
117 ++valueIndex) {
118 auto value = valuesData.at(valueIndex);
119 auto expectedValue = xAxisData + valueIndex * LOCALHOST_SERVER_RESOLUTION
120 - LOCALHOST_REFERENCE_VALUE;
121
122 if (value != expectedValue) {
123 qCInfo(LOG_FuzzingValidators()).noquote()
124 << message << "FAIL: incorrect value data at time"
125 << toDateString(xAxisData) << ", index" << valueIndex << "(found:" << value
126 << ", expected:" << expectedValue << ")";
127 QFAIL("");
128 }
129 }
130 }
131
132 // At this step validation is OK
133 qCInfo(LOG_FuzzingValidators()).noquote() << message << "OK";
106 }
134 }
107 };
135 };
108
136
109 /// Creates the @sa DataValidatorHelper according to the server passed in parameter
137 /// Creates the @sa DataValidatorHelper according to the server passed in parameter
110 std::unique_ptr<DataValidatorHelper> createDataValidatorInstance(const QString &server)
138 std::unique_ptr<DataValidatorHelper> createDataValidatorInstance(const QString &server)
111 {
139 {
112 if (server == QString{"localhost"}) {
140 if (server == QString{"localhost"}) {
113 return std::make_unique<LocalhostServerDataValidatorHelper>();
141 return std::make_unique<LocalhostServerDataValidatorHelper>();
114 }
142 }
115 else {
143 else {
116 return std::make_unique<DefaultDataValidatorHelper>();
144 return std::make_unique<DefaultDataValidatorHelper>();
117 }
145 }
118 }
146 }
119
147
120 DataValidatorHelper &DataValidatorHelper::instance()
148 DataValidatorHelper &DataValidatorHelper::instance()
121 {
149 {
122 // Creates instance depending on the SCIQLOP_AMDA_SERVER value at compile time
150 // Creates instance depending on the SCIQLOP_AMDA_SERVER value at compile time
123 static auto instance = createDataValidatorInstance(SCIQLOP_AMDA_SERVER);
151 static auto instance = createDataValidatorInstance(SCIQLOP_AMDA_SERVER);
124 return *instance;
152 return *instance;
125 }
153 }
126
154
127 // /////////////// //
155 // /////////////// //
128 // RANGE VALIDATOR //
156 // RANGE VALIDATOR //
129 // /////////////// //
157 // /////////////// //
130
158
131 /**
159 /**
132 * Checks that a range of a variable matches the expected range passed as a parameter
160 * Checks that a range of a variable matches the expected range passed as a parameter
133 * @param variable the variable for which to check the range
161 * @param variable the variable for which to check the range
134 * @param expectedRange the expected range
162 * @param expectedRange the expected range
135 * @param getVariableRangeFun the function to retrieve the range from the variable
163 * @param getVariableRangeFun the function to retrieve the range from the variable
136 * @remarks if the variable is null, checks that the expected range is the invalid range
164 * @remarks if the variable is null, checks that the expected range is the invalid range
137 */
165 */
138 void validateRange(std::shared_ptr<Variable> variable, const SqpRange &expectedRange,
166 void validateRange(std::shared_ptr<Variable> variable, const SqpRange &expectedRange,
139 std::function<SqpRange(const Variable &)> getVariableRangeFun)
167 std::function<SqpRange(const Variable &)> getVariableRangeFun)
140 {
168 {
141 auto compare = [](const auto &range, const auto &expectedRange, const auto &message) {
169 auto compare = [](const auto &range, const auto &expectedRange, const auto &message) {
142 if (range == expectedRange) {
170 if (range == expectedRange) {
143 qCInfo(LOG_FuzzingValidators()).noquote() << message << "OK";
171 qCInfo(LOG_FuzzingValidators()).noquote() << message << "OK";
144 }
172 }
145 else {
173 else {
146 qCInfo(LOG_FuzzingValidators()).noquote()
174 qCInfo(LOG_FuzzingValidators()).noquote()
147 << message << "FAIL (current range:" << range
175 << message << "FAIL (current range:" << range
148 << ", expected range:" << expectedRange << ")";
176 << ", expected range:" << expectedRange << ")";
149 QFAIL("");
177 QFAIL("");
150 }
178 }
151 };
179 };
152
180
153 if (variable) {
181 if (variable) {
154 compare(getVariableRangeFun(*variable), expectedRange, "Checking variable's range...");
182 compare(getVariableRangeFun(*variable), expectedRange, "Checking variable's range...");
155 }
183 }
156 else {
184 else {
157 compare(INVALID_RANGE, expectedRange, "Checking that there is no range set...");
185 compare(INVALID_RANGE, expectedRange, "Checking that there is no range set...");
158 }
186 }
159 }
187 }
160
188
161 /**
189 /**
162 * Default implementation of @sa IFuzzingValidator. This validator takes as parameter of its
190 * Default implementation of @sa IFuzzingValidator. This validator takes as parameter of its
163 * construction a function of validation which is called in the validate() method
191 * construction a function of validation which is called in the validate() method
164 */
192 */
165 class FuzzingValidator : public IFuzzingValidator {
193 class FuzzingValidator : public IFuzzingValidator {
166 public:
194 public:
167 /// Signature of a validation function
195 /// Signature of a validation function
168 using ValidationFunction = std::function<void(const VariableState &variableState)>;
196 using ValidationFunction = std::function<void(const VariableState &variableState)>;
169
197
170 explicit FuzzingValidator(ValidationFunction fun) : m_Fun(std::move(fun)) {}
198 explicit FuzzingValidator(ValidationFunction fun) : m_Fun(std::move(fun)) {}
171
199
172 void validate(const VariableState &variableState) const override { m_Fun(variableState); }
200 void validate(const VariableState &variableState) const override { m_Fun(variableState); }
173
201
174 private:
202 private:
175 ValidationFunction m_Fun;
203 ValidationFunction m_Fun;
176 };
204 };
177
205
178 } // namespace
206 } // namespace
179
207
180 std::unique_ptr<IFuzzingValidator> FuzzingValidatorFactory::create(FuzzingValidatorType type)
208 std::unique_ptr<IFuzzingValidator> FuzzingValidatorFactory::create(FuzzingValidatorType type)
181 {
209 {
182 switch (type) {
210 switch (type) {
183 case FuzzingValidatorType::DATA:
211 case FuzzingValidatorType::DATA:
184 return std::make_unique<FuzzingValidator>([](const VariableState &variableState) {
212 return std::make_unique<FuzzingValidator>([](const VariableState &variableState) {
185 DataValidatorHelper::instance().validate(variableState);
213 DataValidatorHelper::instance().validate(variableState);
186 });
214 });
187 case FuzzingValidatorType::RANGE:
215 case FuzzingValidatorType::RANGE:
188 return std::make_unique<FuzzingValidator>([](const VariableState &variableState) {
216 return std::make_unique<FuzzingValidator>([](const VariableState &variableState) {
189 auto getVariableRange = [](const Variable &variable) { return variable.range(); };
217 auto getVariableRange = [](const Variable &variable) { return variable.range(); };
190 validateRange(variableState.m_Variable, variableState.m_Range, getVariableRange);
218 validateRange(variableState.m_Variable, variableState.m_Range, getVariableRange);
191 });
219 });
192 default:
220 default:
193 // Default case returns invalid validator
221 // Default case returns invalid validator
194 break;
222 break;
195 }
223 }
196
224
197 // Invalid validator
225 // Invalid validator
198 return std::make_unique<FuzzingValidator>(
226 return std::make_unique<FuzzingValidator>(
199 [](const VariableState &) { QFAIL("Invalid validator"); });
227 [](const VariableState &) { QFAIL("Invalid validator"); });
200 }
228 }
General Comments 0
You need to be logged in to leave comments. Login now