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