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