##// END OF EJS Templates
Calls validation after each operation
Alexandre Leroux -
r1229:8028c7299f05
parent child
Show More
@@ -1,305 +1,332
1 #include "FuzzingDefs.h"
1 #include "FuzzingDefs.h"
2 #include "FuzzingOperations.h"
2 #include "FuzzingOperations.h"
3 #include "FuzzingUtils.h"
3 #include "FuzzingUtils.h"
4 #include "FuzzingValidators.h"
4 #include "FuzzingValidators.h"
5
5
6 #include "AmdaProvider.h"
6 #include "AmdaProvider.h"
7
7
8 #include <Network/NetworkController.h>
8 #include <Network/NetworkController.h>
9 #include <Settings/SqpSettingsDefs.h>
9 #include <Settings/SqpSettingsDefs.h>
10 #include <SqpApplication.h>
10 #include <SqpApplication.h>
11 #include <Time/TimeController.h>
11 #include <Time/TimeController.h>
12 #include <Variable/Variable.h>
12 #include <Variable/Variable.h>
13 #include <Variable/VariableController.h>
13 #include <Variable/VariableController.h>
14
14
15 #include <QLoggingCategory>
15 #include <QLoggingCategory>
16 #include <QObject>
16 #include <QObject>
17 #include <QtTest>
17 #include <QtTest>
18
18
19 #include <memory>
19 #include <memory>
20
20
21 Q_LOGGING_CATEGORY(LOG_TestAmdaFuzzing, "TestAmdaFuzzing")
21 Q_LOGGING_CATEGORY(LOG_TestAmdaFuzzing, "TestAmdaFuzzing")
22
22
23 namespace {
23 namespace {
24
24
25 // /////// //
25 // /////// //
26 // Aliases //
26 // Aliases //
27 // /////// //
27 // /////// //
28
28
29 using VariableId = int;
29 using VariableId = int;
30 using Weight = double;
30 using Weight = double;
31 using Weights = std::vector<Weight>;
31 using Weights = std::vector<Weight>;
32
32
33 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
33 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
34 using VariablesOperations = std::vector<VariableOperation>;
34 using VariablesOperations = std::vector<VariableOperation>;
35
35
36 using WeightedOperationsPool = std::map<std::shared_ptr<IFuzzingOperation>, Weight>;
36 using WeightedOperationsPool = std::map<std::shared_ptr<IFuzzingOperation>, Weight>;
37 using VariablesPool = std::map<VariableId, VariableState>;
37 using VariablesPool = std::map<VariableId, VariableState>;
38 using Validators = std::vector<std::shared_ptr<IFuzzingValidator> >;
38 using Validators = std::vector<std::shared_ptr<IFuzzingValidator> >;
39
39
40 // ///////// //
40 // ///////// //
41 // Constants //
41 // Constants //
42 // ///////// //
42 // ///////// //
43
43
44 // Defaults values used when the associated properties have not been set for the test
44 // Defaults values used when the associated properties have not been set for the test
45 const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
45 const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
46 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
46 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
47 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE = QVariant::fromValue(WeightedOperationsTypes{
47 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE = QVariant::fromValue(WeightedOperationsTypes{
48 {FuzzingOperationType::CREATE, 1.},
48 {FuzzingOperationType::CREATE, 1.},
49 {FuzzingOperationType::DELETE, 0.1}, // Delete operation is less frequent
49 {FuzzingOperationType::DELETE, 0.1}, // Delete operation is less frequent
50 {FuzzingOperationType::PAN_LEFT, 1.},
50 {FuzzingOperationType::PAN_LEFT, 1.},
51 {FuzzingOperationType::PAN_RIGHT, 1.},
51 {FuzzingOperationType::PAN_RIGHT, 1.},
52 {FuzzingOperationType::ZOOM_IN, 1.},
52 {FuzzingOperationType::ZOOM_IN, 1.},
53 {FuzzingOperationType::ZOOM_OUT, 1.}});
53 {FuzzingOperationType::ZOOM_OUT, 1.}});
54 const auto CACHE_TOLERANCE_DEFAULT_VALUE = 0.2;
54 const auto CACHE_TOLERANCE_DEFAULT_VALUE = 0.2;
55
55
56 /// Delay between each operation (in ms)
56 /// Delay between each operation (in ms)
57 const auto OPERATION_DELAY_DEFAULT_VALUE = 3000;
57 const auto OPERATION_DELAY_DEFAULT_VALUE = 3000;
58
58
59 /// Validators for the tests (executed in the order in which they're defined)
59 /// Validators for the tests (executed in the order in which they're defined)
60 const auto VALIDATORS_DEFAULT_VALUE = QVariant::fromValue(
60 const auto VALIDATORS_DEFAULT_VALUE = QVariant::fromValue(
61 ValidatorsTypes{{FuzzingValidatorType::RANGE, FuzzingValidatorType::DATA}});
61 ValidatorsTypes{{FuzzingValidatorType::RANGE, FuzzingValidatorType::DATA}});
62
62
63 // /////// //
63 // /////// //
64 // Methods //
64 // Methods //
65 // /////// //
65 // /////// //
66
66
67 /// Goes through the variables pool and operations pool to determine the set of {variable/operation}
67 /// Goes through the variables pool and operations pool to determine the set of {variable/operation}
68 /// pairs that are valid (i.e. operation that can be executed on variable)
68 /// pairs that are valid (i.e. operation that can be executed on variable)
69 std::pair<VariablesOperations, Weights>
69 std::pair<VariablesOperations, Weights>
70 availableOperations(const VariablesPool &variablesPool,
70 availableOperations(const VariablesPool &variablesPool,
71 const WeightedOperationsPool &operationsPool)
71 const WeightedOperationsPool &operationsPool)
72 {
72 {
73 VariablesOperations result{};
73 VariablesOperations result{};
74 Weights weights{};
74 Weights weights{};
75
75
76 for (const auto &variablesPoolEntry : variablesPool) {
76 for (const auto &variablesPoolEntry : variablesPool) {
77 auto variableId = variablesPoolEntry.first;
77 auto variableId = variablesPoolEntry.first;
78 const auto &variableState = variablesPoolEntry.second;
78 const auto &variableState = variablesPoolEntry.second;
79
79
80 for (const auto &operationsPoolEntry : operationsPool) {
80 for (const auto &operationsPoolEntry : operationsPool) {
81 auto operation = operationsPoolEntry.first;
81 auto operation = operationsPoolEntry.first;
82 auto weight = operationsPoolEntry.second;
82 auto weight = operationsPoolEntry.second;
83
83
84 // A pair is valid if the current operation can be executed on the current variable
84 // A pair is valid if the current operation can be executed on the current variable
85 if (operation->canExecute(variableState)) {
85 if (operation->canExecute(variableState)) {
86 result.push_back({variableId, operation});
86 result.push_back({variableId, operation});
87 weights.push_back(weight);
87 weights.push_back(weight);
88 }
88 }
89 }
89 }
90 }
90 }
91
91
92 return {result, weights};
92 return {result, weights};
93 }
93 }
94
94
95 WeightedOperationsPool createOperationsPool(const WeightedOperationsTypes &types)
95 WeightedOperationsPool createOperationsPool(const WeightedOperationsTypes &types)
96 {
96 {
97 WeightedOperationsPool result{};
97 WeightedOperationsPool result{};
98
98
99 std::transform(
99 std::transform(
100 types.cbegin(), types.cend(), std::inserter(result, result.end()), [](const auto &type) {
100 types.cbegin(), types.cend(), std::inserter(result, result.end()), [](const auto &type) {
101 return std::make_pair(FuzzingOperationFactory::create(type.first), type.second);
101 return std::make_pair(FuzzingOperationFactory::create(type.first), type.second);
102 });
102 });
103
103
104 return result;
104 return result;
105 }
105 }
106
106
107 Validators createValidators(const ValidatorsTypes &types)
107 Validators createValidators(const ValidatorsTypes &types)
108 {
108 {
109 Validators result{};
109 Validators result{};
110
110
111 std::transform(types.cbegin(), types.cend(), std::inserter(result, result.end()),
111 std::transform(types.cbegin(), types.cend(), std::inserter(result, result.end()),
112 [](const auto &type) { return FuzzingValidatorFactory::create(type); });
112 [](const auto &type) { return FuzzingValidatorFactory::create(type); });
113
113
114 return result;
114 return result;
115 }
115 }
116
116
117 /**
117 /**
118 * Validates all the variables' states passed in parameter, according to a set of validators
119 * @param variablesPool the variables' states
120 * @param validators the validators used for validation
121 */
122 void validate(const VariablesPool &variablesPool, const Validators &validators)
123 {
124 for (const auto &variablesPoolEntry : variablesPool) {
125 auto variableId = variablesPoolEntry.first;
126 const auto &variableState = variablesPoolEntry.second;
127
128 auto variableMessage = variableState.m_Variable ? variableState.m_Variable->name()
129 : QStringLiteral("null variable");
130 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validating state of variable at index"
131 << variableId << "(" << variableMessage << ")...";
132
133 for (const auto &validator : validators) {
134 validator->validate(VariableState{variableState});
135 }
136
137 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validation completed.";
138 }
139 }
140
141 /**
118 * Class to run random tests
142 * Class to run random tests
119 */
143 */
120 class FuzzingTest {
144 class FuzzingTest {
121 public:
145 public:
122 explicit FuzzingTest(VariableController &variableController, Properties properties)
146 explicit FuzzingTest(VariableController &variableController, Properties properties)
123 : m_VariableController{variableController},
147 : m_VariableController{variableController},
124 m_Properties{std::move(properties)},
148 m_Properties{std::move(properties)},
125 m_VariablesPool{}
149 m_VariablesPool{}
126 {
150 {
127 // Inits variables pool: at init, all variables are null
151 // Inits variables pool: at init, all variables are null
128 for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
152 for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
129 m_VariablesPool[variableId] = VariableState{};
153 m_VariablesPool[variableId] = VariableState{};
130 }
154 }
131 }
155 }
132
156
133 void execute()
157 void execute()
134 {
158 {
135 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Running" << nbMaxOperations() << "operations on"
159 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Running" << nbMaxOperations() << "operations on"
136 << nbMaxVariables() << "variable(s)...";
160 << nbMaxVariables() << "variable(s)...";
137
161
138 auto canExecute = true;
162 auto canExecute = true;
139 for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
163 for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
140 // Retrieves all operations that can be executed in the current context
164 // Retrieves all operations that can be executed in the current context
141 VariablesOperations variableOperations{};
165 VariablesOperations variableOperations{};
142 Weights weights{};
166 Weights weights{};
143 std::tie(variableOperations, weights)
167 std::tie(variableOperations, weights)
144 = availableOperations(m_VariablesPool, operationsPool());
168 = availableOperations(m_VariablesPool, operationsPool());
145
169
146 canExecute = !variableOperations.empty();
170 canExecute = !variableOperations.empty();
147 if (canExecute) {
171 if (canExecute) {
148 // Of the operations available, chooses a random operation and executes it
172 // Of the operations available, chooses a random operation and executes it
149 auto variableOperation
173 auto variableOperation
150 = RandomGenerator::instance().randomChoice(variableOperations, weights);
174 = RandomGenerator::instance().randomChoice(variableOperations, weights);
151
175
152 auto variableId = variableOperation.first;
176 auto variableId = variableOperation.first;
153 auto &variableState = m_VariablesPool.at(variableId);
177 auto &variableState = m_VariablesPool.at(variableId);
154 auto fuzzingOperation = variableOperation.second;
178 auto fuzzingOperation = variableOperation.second;
155
179
156 fuzzingOperation->execute(variableState, m_VariableController, m_Properties);
180 fuzzingOperation->execute(variableState, m_VariableController, m_Properties);
157 QTest::qWait(operationDelay());
181 QTest::qWait(operationDelay());
182
183 // Validates variables
184 validate(m_VariablesPool, validators());
158 }
185 }
159 else {
186 else {
160 qCInfo(LOG_TestAmdaFuzzing()).noquote()
187 qCInfo(LOG_TestAmdaFuzzing()).noquote()
161 << "No more operations are available, the execution of the test will stop...";
188 << "No more operations are available, the execution of the test will stop...";
162 }
189 }
163 }
190 }
164
191
165 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Execution of the test completed.";
192 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Execution of the test completed.";
166 }
193 }
167
194
168 private:
195 private:
169 int nbMaxOperations() const
196 int nbMaxOperations() const
170 {
197 {
171 static auto result
198 static auto result
172 = m_Properties.value(NB_MAX_OPERATIONS_PROPERTY, NB_MAX_OPERATIONS_DEFAULT_VALUE)
199 = m_Properties.value(NB_MAX_OPERATIONS_PROPERTY, NB_MAX_OPERATIONS_DEFAULT_VALUE)
173 .toInt();
200 .toInt();
174 return result;
201 return result;
175 }
202 }
176
203
177 int nbMaxVariables() const
204 int nbMaxVariables() const
178 {
205 {
179 static auto result
206 static auto result
180 = m_Properties.value(NB_MAX_VARIABLES_PROPERTY, NB_MAX_VARIABLES_DEFAULT_VALUE).toInt();
207 = m_Properties.value(NB_MAX_VARIABLES_PROPERTY, NB_MAX_VARIABLES_DEFAULT_VALUE).toInt();
181 return result;
208 return result;
182 }
209 }
183
210
184 int operationDelay() const
211 int operationDelay() const
185 {
212 {
186 static auto result
213 static auto result
187 = m_Properties.value(OPERATION_DELAY_PROPERTY, OPERATION_DELAY_DEFAULT_VALUE).toInt();
214 = m_Properties.value(OPERATION_DELAY_PROPERTY, OPERATION_DELAY_DEFAULT_VALUE).toInt();
188 return result;
215 return result;
189 }
216 }
190
217
191 WeightedOperationsPool operationsPool() const
218 WeightedOperationsPool operationsPool() const
192 {
219 {
193 static auto result = createOperationsPool(
220 static auto result = createOperationsPool(
194 m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
221 m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
195 .value<WeightedOperationsTypes>());
222 .value<WeightedOperationsTypes>());
196 return result;
223 return result;
197 }
224 }
198
225
199 Validators validators() const
226 Validators validators() const
200 {
227 {
201 static auto result
228 static auto result
202 = createValidators(m_Properties.value(VALIDATORS_PROPERTY, VALIDATORS_DEFAULT_VALUE)
229 = createValidators(m_Properties.value(VALIDATORS_PROPERTY, VALIDATORS_DEFAULT_VALUE)
203 .value<ValidatorsTypes>());
230 .value<ValidatorsTypes>());
204 return result;
231 return result;
205 }
232 }
206
233
207 VariableController &m_VariableController;
234 VariableController &m_VariableController;
208 Properties m_Properties;
235 Properties m_Properties;
209 VariablesPool m_VariablesPool;
236 VariablesPool m_VariablesPool;
210 };
237 };
211
238
212 } // namespace
239 } // namespace
213
240
214 class TestAmdaFuzzing : public QObject {
241 class TestAmdaFuzzing : public QObject {
215 Q_OBJECT
242 Q_OBJECT
216
243
217 private slots:
244 private slots:
218 /// Input data for @sa testFuzzing()
245 /// Input data for @sa testFuzzing()
219 void testFuzzing_data();
246 void testFuzzing_data();
220 void testFuzzing();
247 void testFuzzing();
221 };
248 };
222
249
223 void TestAmdaFuzzing::testFuzzing_data()
250 void TestAmdaFuzzing::testFuzzing_data()
224 {
251 {
225 // ////////////// //
252 // ////////////// //
226 // Test structure //
253 // Test structure //
227 // ////////////// //
254 // ////////////// //
228
255
229 QTest::addColumn<Properties>("properties"); // Properties for random test
256 QTest::addColumn<Properties>("properties"); // Properties for random test
230
257
231 // ////////// //
258 // ////////// //
232 // Test cases //
259 // Test cases //
233 // ////////// //
260 // ////////// //
234
261
235 auto maxRange = SqpRange::fromDateTime({2017, 1, 1}, {0, 0}, {2017, 1, 5}, {0, 0});
262 auto maxRange = SqpRange::fromDateTime({2017, 1, 1}, {0, 0}, {2017, 1, 5}, {0, 0});
236 MetadataPool metadataPool{{{"dataType", "vector"}, {"xml:id", "imf"}}};
263 MetadataPool metadataPool{{{"dataType", "vector"}, {"xml:id", "imf"}}};
237
264
238 // Note: we don't use auto here as we want to pass std::shared_ptr<IDataProvider> as is in the
265 // Note: we don't use auto here as we want to pass std::shared_ptr<IDataProvider> as is in the
239 // QVariant
266 // QVariant
240 std::shared_ptr<IDataProvider> provider = std::make_shared<AmdaProvider>();
267 std::shared_ptr<IDataProvider> provider = std::make_shared<AmdaProvider>();
241
268
242 QTest::newRow("fuzzingTest") << Properties{
269 QTest::newRow("fuzzingTest") << Properties{
243 {MAX_RANGE_PROPERTY, QVariant::fromValue(maxRange)},
270 {MAX_RANGE_PROPERTY, QVariant::fromValue(maxRange)},
244 {METADATA_POOL_PROPERTY, QVariant::fromValue(metadataPool)},
271 {METADATA_POOL_PROPERTY, QVariant::fromValue(metadataPool)},
245 {PROVIDER_PROPERTY, QVariant::fromValue(provider)}};
272 {PROVIDER_PROPERTY, QVariant::fromValue(provider)}};
246 }
273 }
247
274
248 void TestAmdaFuzzing::testFuzzing()
275 void TestAmdaFuzzing::testFuzzing()
249 {
276 {
250 QFETCH(Properties, properties);
277 QFETCH(Properties, properties);
251
278
252 // Sets cache property
279 // Sets cache property
253 QSettings settings{};
280 QSettings settings{};
254 auto cacheTolerance = properties.value(CACHE_TOLERANCE_PROPERTY, CACHE_TOLERANCE_DEFAULT_VALUE);
281 auto cacheTolerance = properties.value(CACHE_TOLERANCE_PROPERTY, CACHE_TOLERANCE_DEFAULT_VALUE);
255 settings.setValue(GENERAL_TOLERANCE_AT_INIT_KEY, cacheTolerance);
282 settings.setValue(GENERAL_TOLERANCE_AT_INIT_KEY, cacheTolerance);
256 settings.setValue(GENERAL_TOLERANCE_AT_UPDATE_KEY, cacheTolerance);
283 settings.setValue(GENERAL_TOLERANCE_AT_UPDATE_KEY, cacheTolerance);
257
284
258 auto &variableController = sqpApp->variableController();
285 auto &variableController = sqpApp->variableController();
259 auto &timeController = sqpApp->timeController();
286 auto &timeController = sqpApp->timeController();
260
287
261 // Generates random initial range (bounded to max range)
288 // Generates random initial range (bounded to max range)
262 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
289 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
263 .value<SqpRange>();
290 .value<SqpRange>();
264
291
265 QVERIFY(maxRange != INVALID_RANGE);
292 QVERIFY(maxRange != INVALID_RANGE);
266
293
267 auto initialRangeStart
294 auto initialRangeStart
268 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
295 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
269 auto initialRangeEnd
296 auto initialRangeEnd
270 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
297 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
271 if (initialRangeStart > initialRangeEnd) {
298 if (initialRangeStart > initialRangeEnd) {
272 std::swap(initialRangeStart, initialRangeEnd);
299 std::swap(initialRangeStart, initialRangeEnd);
273 }
300 }
274
301
275 // Sets initial range on time controller
302 // Sets initial range on time controller
276 SqpRange initialRange{initialRangeStart, initialRangeEnd};
303 SqpRange initialRange{initialRangeStart, initialRangeEnd};
277 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Setting initial range to" << initialRange << "...";
304 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Setting initial range to" << initialRange << "...";
278 timeController.onTimeToUpdate(initialRange);
305 timeController.onTimeToUpdate(initialRange);
279 properties.insert(INITIAL_RANGE_PROPERTY, QVariant::fromValue(initialRange));
306 properties.insert(INITIAL_RANGE_PROPERTY, QVariant::fromValue(initialRange));
280
307
281 FuzzingTest test{variableController, properties};
308 FuzzingTest test{variableController, properties};
282 test.execute();
309 test.execute();
283 }
310 }
284
311
285 int main(int argc, char *argv[])
312 int main(int argc, char *argv[])
286 {
313 {
287 QLoggingCategory::setFilterRules(
314 QLoggingCategory::setFilterRules(
288 "*.warning=false\n"
315 "*.warning=false\n"
289 "*.info=false\n"
316 "*.info=false\n"
290 "*.debug=false\n"
317 "*.debug=false\n"
291 "FuzzingOperations.info=true\n"
318 "FuzzingOperations.info=true\n"
292 "FuzzingValidators.info=true\n"
319 "FuzzingValidators.info=true\n"
293 "TestAmdaFuzzing.info=true\n");
320 "TestAmdaFuzzing.info=true\n");
294
321
295 SqpApplication app{argc, argv};
322 SqpApplication app{argc, argv};
296 SqpApplication::setOrganizationName("LPP");
323 SqpApplication::setOrganizationName("LPP");
297 SqpApplication::setOrganizationDomain("lpp.fr");
324 SqpApplication::setOrganizationDomain("lpp.fr");
298 SqpApplication::setApplicationName("SciQLop-TestFuzzing");
325 SqpApplication::setApplicationName("SciQLop-TestFuzzing");
299 app.setAttribute(Qt::AA_Use96Dpi, true);
326 app.setAttribute(Qt::AA_Use96Dpi, true);
300 TestAmdaFuzzing testObject{};
327 TestAmdaFuzzing testObject{};
301 QTEST_SET_MAIN_SOURCE_PATH
328 QTEST_SET_MAIN_SOURCE_PATH
302 return QTest::qExec(&testObject, argc, argv);
329 return QTest::qExec(&testObject, argc, argv);
303 }
330 }
304
331
305 #include "TestAmdaFuzzing.moc"
332 #include "TestAmdaFuzzing.moc"
General Comments 0
You need to be logged in to leave comments. Login now