##// END OF EJS Templates
Adds weights to operations (2)...
Alexandre Leroux -
r1216:0083fced54a2
parent child
Show More
@@ -1,49 +1,49
1 #ifndef SCIQLOP_FUZZINGOPERATIONS_H
1 #ifndef SCIQLOP_FUZZINGOPERATIONS_H
2 #define SCIQLOP_FUZZINGOPERATIONS_H
2 #define SCIQLOP_FUZZINGOPERATIONS_H
3
3
4 #include "FuzzingDefs.h"
4 #include "FuzzingDefs.h"
5
5
6 #include <memory>
6 #include <memory>
7 #include <set>
7 #include <set>
8
8
9 #include <QLoggingCategory>
9 #include <QLoggingCategory>
10 #include <QMetaType>
10 #include <QMetaType>
11
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_FuzzingOperations)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_FuzzingOperations)
13
13
14 class Variable;
14 class Variable;
15 class VariableController;
15 class VariableController;
16
16
17 /**
17 /**
18 * Enumeration of types of existing fuzzing operations
18 * Enumeration of types of existing fuzzing operations
19 */
19 */
20 enum class FuzzingOperationType { CREATE };
20 enum class FuzzingOperationType { CREATE };
21
21
22 /// Interface that represents an operation that can be executed during a fuzzing test
22 /// Interface that represents an operation that can be executed during a fuzzing test
23 struct IFuzzingOperation {
23 struct IFuzzingOperation {
24 virtual ~IFuzzingOperation() noexcept = default;
24 virtual ~IFuzzingOperation() noexcept = default;
25
25
26 /// Checks if the operation can be executed according to the current state of the variable
26 /// Checks if the operation can be executed according to the current state of the variable
27 /// passed in parameter
27 /// passed in parameter
28 virtual bool canExecute(std::shared_ptr<Variable> variable) const = 0;
28 virtual bool canExecute(std::shared_ptr<Variable> variable) const = 0;
29 /// Executes the operation on the variable passed in parameter
29 /// Executes the operation on the variable passed in parameter
30 /// @param variable the variable on which to execute the operation
30 /// @param variable the variable on which to execute the operation
31 /// @param variableController the controller associated to the operation
31 /// @param variableController the controller associated to the operation
32 /// @param properties properties that can be used to configure the operation
32 /// @param properties properties that can be used to configure the operation
33 /// @remarks variable is passed as a reference because, according to the operation, it can be
33 /// @remarks variable is passed as a reference because, according to the operation, it can be
34 /// modified (in/out parameter)
34 /// modified (in/out parameter)
35 virtual void execute(std::shared_ptr<Variable> &variable,
35 virtual void execute(std::shared_ptr<Variable> &variable,
36 VariableController &variableController,
36 VariableController &variableController,
37 const Properties &properties = {}) const = 0;
37 const Properties &properties = {}) const = 0;
38 };
38 };
39
39
40 /// Factory of @sa IFuzzingOperation
40 /// Factory of @sa IFuzzingOperation
41 struct FuzzingOperationFactory {
41 struct FuzzingOperationFactory {
42 /// Creates a fuzzing operation from a type
42 /// Creates a fuzzing operation from a type
43 static std::unique_ptr<IFuzzingOperation> create(FuzzingOperationType type);
43 static std::unique_ptr<IFuzzingOperation> create(FuzzingOperationType type);
44 };
44 };
45
45
46 using OperationsTypes = std::set<FuzzingOperationType>;
46 using WeightedOperationsTypes = std::map<FuzzingOperationType, double>;
47 Q_DECLARE_METATYPE(OperationsTypes)
47 Q_DECLARE_METATYPE(WeightedOperationsTypes)
48
48
49 #endif // SCIQLOP_FUZZINGOPERATIONS_H
49 #endif // SCIQLOP_FUZZINGOPERATIONS_H
@@ -1,241 +1,254
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
4
5 #include "AmdaProvider.h"
5 #include "AmdaProvider.h"
6
6
7 #include <Network/NetworkController.h>
7 #include <Network/NetworkController.h>
8 #include <SqpApplication.h>
8 #include <SqpApplication.h>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11
11
12 #include <QLoggingCategory>
12 #include <QLoggingCategory>
13 #include <QObject>
13 #include <QObject>
14 #include <QtTest>
14 #include <QtTest>
15
15
16 #include <memory>
16 #include <memory>
17
17
18 Q_LOGGING_CATEGORY(LOG_TestAmdaFuzzing, "TestAmdaFuzzing")
18 Q_LOGGING_CATEGORY(LOG_TestAmdaFuzzing, "TestAmdaFuzzing")
19
19
20 namespace {
20 namespace {
21
21
22 // /////// //
22 // /////// //
23 // Aliases //
23 // Aliases //
24 // /////// //
24 // /////// //
25
25
26 using VariableId = int;
26 using VariableId = int;
27 using Weight = double;
28 using Weights = std::vector<Weight>;
27
29
28 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
30 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
29 using VariablesOperations = std::vector<VariableOperation>;
31 using VariablesOperations = std::vector<VariableOperation>;
30
32
31 using OperationsPool = std::set<std::shared_ptr<IFuzzingOperation> >;
33 using WeightedOperationsPool = std::map<std::shared_ptr<IFuzzingOperation>, Weight>;
32 using VariablesPool = std::map<VariableId, std::shared_ptr<Variable> >;
34 using VariablesPool = std::map<VariableId, std::shared_ptr<Variable> >;
33
35
34 // ///////// //
36 // ///////// //
35 // Constants //
37 // Constants //
36 // ///////// //
38 // ///////// //
37
39
38 // Defaults values used when the associated properties have not been set for the test
40 // Defaults values used when the associated properties have not been set for the test
39 const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
41 const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
40 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
42 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
41 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE
43 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE
42 = QVariant::fromValue(OperationsTypes{FuzzingOperationType::CREATE});
44 = QVariant::fromValue(WeightedOperationsTypes{{FuzzingOperationType::CREATE, 1.}});
43
45
44 // /////// //
46 // /////// //
45 // Methods //
47 // Methods //
46 // /////// //
48 // /////// //
47
49
48 /// Goes through the variables pool and operations pool to determine the set of {variable/operation}
50 /// Goes through the variables pool and operations pool to determine the set of {variable/operation}
49 /// pairs that are valid (i.e. operation that can be executed on variable)
51 /// pairs that are valid (i.e. operation that can be executed on variable)
50 VariablesOperations availableOperations(const VariablesPool &variablesPool,
52 std::pair<VariablesOperations, Weights>
51 const OperationsPool &operationsPool)
53 availableOperations(const VariablesPool &variablesPool,
54 const WeightedOperationsPool &operationsPool)
52 {
55 {
53 VariablesOperations result{};
56 VariablesOperations result{};
57 Weights weights{};
54
58
55 for (const auto &variablesPoolEntry : variablesPool) {
59 for (const auto &variablesPoolEntry : variablesPool) {
56 auto variableId = variablesPoolEntry.first;
60 auto variableId = variablesPoolEntry.first;
57 auto variable = variablesPoolEntry.second;
61 auto variable = variablesPoolEntry.second;
58
62
59 for (const auto &operation : operationsPool) {
63 for (const auto &operationsPoolEntry : operationsPool) {
64 auto operation = operationsPoolEntry.first;
65 auto weight = operationsPoolEntry.second;
66
60 // A pair is valid if the current operation can be executed on the current variable
67 // A pair is valid if the current operation can be executed on the current variable
61 if (operation->canExecute(variable)) {
68 if (operation->canExecute(variable)) {
62 result.push_back({variableId, operation});
69 result.push_back({variableId, operation});
70 weights.push_back(weight);
63 }
71 }
64 }
72 }
65 }
73 }
66
74
67 return result;
75 return {result, weights};
68 }
76 }
69
77
70 OperationsPool createOperationsPool(const OperationsTypes &types)
78 WeightedOperationsPool createOperationsPool(const WeightedOperationsTypes &types)
71 {
79 {
72 OperationsPool result{};
80 WeightedOperationsPool result{};
73
81
74 std::transform(types.cbegin(), types.cend(), std::inserter(result, result.end()),
82 std::transform(
75 [](const auto &type) { return FuzzingOperationFactory::create(type); });
83 types.cbegin(), types.cend(), std::inserter(result, result.end()), [](const auto &type) {
84 return std::make_pair(FuzzingOperationFactory::create(type.first), type.second);
85 });
76
86
77 return result;
87 return result;
78 }
88 }
79
89
80 /**
90 /**
81 * Class to run random tests
91 * Class to run random tests
82 */
92 */
83 class FuzzingTest {
93 class FuzzingTest {
84 public:
94 public:
85 explicit FuzzingTest(VariableController &variableController, Properties properties)
95 explicit FuzzingTest(VariableController &variableController, Properties properties)
86 : m_VariableController{variableController},
96 : m_VariableController{variableController},
87 m_Properties{std::move(properties)},
97 m_Properties{std::move(properties)},
88 m_VariablesPool{}
98 m_VariablesPool{}
89 {
99 {
90 // Inits variables pool: at init, all variables are null
100 // Inits variables pool: at init, all variables are null
91 for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
101 for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
92 m_VariablesPool[variableId] = nullptr;
102 m_VariablesPool[variableId] = nullptr;
93 }
103 }
94 }
104 }
95
105
96 void execute()
106 void execute()
97 {
107 {
98 qCInfo(LOG_TestAmdaFuzzing()) << "Running" << nbMaxOperations() << "operations on"
108 qCInfo(LOG_TestAmdaFuzzing()) << "Running" << nbMaxOperations() << "operations on"
99 << nbMaxVariables() << "variable(s)...";
109 << nbMaxVariables() << "variable(s)...";
100
110
101 auto canExecute = true;
111 auto canExecute = true;
102 for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
112 for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
103 // Retrieves all operations that can be executed in the current context
113 // Retrieves all operations that can be executed in the current context
104 auto variableOperations = availableOperations(m_VariablesPool, operationsPool());
114 VariablesOperations variableOperations{};
115 Weights weights{};
116 std::tie(variableOperations, weights)
117 = availableOperations(m_VariablesPool, operationsPool());
105
118
106 canExecute = !variableOperations.empty();
119 canExecute = !variableOperations.empty();
107 if (canExecute) {
120 if (canExecute) {
108 // Of the operations available, chooses a random operation and executes it
121 // Of the operations available, chooses a random operation and executes it
109 auto variableOperation
122 auto variableOperation
110 = RandomGenerator::instance().randomChoice(variableOperations);
123 = RandomGenerator::instance().randomChoice(variableOperations, weights);
111
124
112 auto variableId = variableOperation.first;
125 auto variableId = variableOperation.first;
113 auto variable = m_VariablesPool.at(variableId);
126 auto variable = m_VariablesPool.at(variableId);
114 auto fuzzingOperation = variableOperation.second;
127 auto fuzzingOperation = variableOperation.second;
115
128
116 fuzzingOperation->execute(variable, m_VariableController, m_Properties);
129 fuzzingOperation->execute(variable, m_VariableController, m_Properties);
117
130
118 // Updates variable pool with the new state of the variable after operation
131 // Updates variable pool with the new state of the variable after operation
119 m_VariablesPool[variableId] = variable;
132 m_VariablesPool[variableId] = variable;
120 }
133 }
121 else {
134 else {
122 qCInfo(LOG_TestAmdaFuzzing())
135 qCInfo(LOG_TestAmdaFuzzing())
123 << "No more operations are available, the execution of the test will stop...";
136 << "No more operations are available, the execution of the test will stop...";
124 }
137 }
125 }
138 }
126
139
127 qCInfo(LOG_TestAmdaFuzzing()) << "Execution of the test completed.";
140 qCInfo(LOG_TestAmdaFuzzing()) << "Execution of the test completed.";
128 }
141 }
129
142
130 private:
143 private:
131 int nbMaxOperations() const
144 int nbMaxOperations() const
132 {
145 {
133 static auto result
146 static auto result
134 = m_Properties.value(NB_MAX_OPERATIONS_PROPERTY, NB_MAX_OPERATIONS_DEFAULT_VALUE)
147 = m_Properties.value(NB_MAX_OPERATIONS_PROPERTY, NB_MAX_OPERATIONS_DEFAULT_VALUE)
135 .toInt();
148 .toInt();
136 return result;
149 return result;
137 }
150 }
138
151
139 int nbMaxVariables() const
152 int nbMaxVariables() const
140 {
153 {
141 static auto result
154 static auto result
142 = m_Properties.value(NB_MAX_VARIABLES_PROPERTY, NB_MAX_VARIABLES_DEFAULT_VALUE).toInt();
155 = m_Properties.value(NB_MAX_VARIABLES_PROPERTY, NB_MAX_VARIABLES_DEFAULT_VALUE).toInt();
143 return result;
156 return result;
144 }
157 }
145
158
146 OperationsPool operationsPool() const
159 WeightedOperationsPool operationsPool() const
147 {
160 {
148 static auto result = createOperationsPool(
161 static auto result = createOperationsPool(
149 m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
162 m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
150 .value<OperationsTypes>());
163 .value<WeightedOperationsTypes>());
151 return result;
164 return result;
152 }
165 }
153
166
154 VariableController &m_VariableController;
167 VariableController &m_VariableController;
155 Properties m_Properties;
168 Properties m_Properties;
156 VariablesPool m_VariablesPool;
169 VariablesPool m_VariablesPool;
157 };
170 };
158
171
159 } // namespace
172 } // namespace
160
173
161 class TestAmdaFuzzing : public QObject {
174 class TestAmdaFuzzing : public QObject {
162 Q_OBJECT
175 Q_OBJECT
163
176
164 private slots:
177 private slots:
165 /// Input data for @sa testFuzzing()
178 /// Input data for @sa testFuzzing()
166 void testFuzzing_data();
179 void testFuzzing_data();
167 void testFuzzing();
180 void testFuzzing();
168 };
181 };
169
182
170 void TestAmdaFuzzing::testFuzzing_data()
183 void TestAmdaFuzzing::testFuzzing_data()
171 {
184 {
172 // ////////////// //
185 // ////////////// //
173 // Test structure //
186 // Test structure //
174 // ////////////// //
187 // ////////////// //
175
188
176 QTest::addColumn<Properties>("properties"); // Properties for random test
189 QTest::addColumn<Properties>("properties"); // Properties for random test
177
190
178 // ////////// //
191 // ////////// //
179 // Test cases //
192 // Test cases //
180 // ////////// //
193 // ////////// //
181
194
182 auto maxRange = SqpRange::fromDateTime({2017, 1, 1}, {0, 0}, {2017, 1, 5}, {0, 0});
195 auto maxRange = SqpRange::fromDateTime({2017, 1, 1}, {0, 0}, {2017, 1, 5}, {0, 0});
183 MetadataPool metadataPool{{{"dataType", "vector"}, {"xml:id", "imf"}}};
196 MetadataPool metadataPool{{{"dataType", "vector"}, {"xml:id", "imf"}}};
184
197
185 // Note: we don't use auto here as we want to pass std::shared_ptr<IDataProvider> as is in the
198 // Note: we don't use auto here as we want to pass std::shared_ptr<IDataProvider> as is in the
186 // QVariant
199 // QVariant
187 std::shared_ptr<IDataProvider> provider = std::make_shared<AmdaProvider>();
200 std::shared_ptr<IDataProvider> provider = std::make_shared<AmdaProvider>();
188
201
189 QTest::newRow("fuzzingTest") << Properties{
202 QTest::newRow("fuzzingTest") << Properties{
190 {MAX_RANGE_PROPERTY, QVariant::fromValue(maxRange)},
203 {MAX_RANGE_PROPERTY, QVariant::fromValue(maxRange)},
191 {METADATA_POOL_PROPERTY, QVariant::fromValue(metadataPool)},
204 {METADATA_POOL_PROPERTY, QVariant::fromValue(metadataPool)},
192 {PROVIDER_PROPERTY, QVariant::fromValue(provider)}};
205 {PROVIDER_PROPERTY, QVariant::fromValue(provider)}};
193 }
206 }
194
207
195 void TestAmdaFuzzing::testFuzzing()
208 void TestAmdaFuzzing::testFuzzing()
196 {
209 {
197 QFETCH(Properties, properties);
210 QFETCH(Properties, properties);
198
211
199 auto &variableController = sqpApp->variableController();
212 auto &variableController = sqpApp->variableController();
200 auto &timeController = sqpApp->timeController();
213 auto &timeController = sqpApp->timeController();
201
214
202 // Generates random initial range (bounded to max range)
215 // Generates random initial range (bounded to max range)
203 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
216 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
204 .value<SqpRange>();
217 .value<SqpRange>();
205
218
206 QVERIFY(maxRange != INVALID_RANGE);
219 QVERIFY(maxRange != INVALID_RANGE);
207
220
208 auto initialRangeStart
221 auto initialRangeStart
209 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
222 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
210 auto initialRangeEnd
223 auto initialRangeEnd
211 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
224 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
212 if (initialRangeStart > initialRangeEnd) {
225 if (initialRangeStart > initialRangeEnd) {
213 std::swap(initialRangeStart, initialRangeEnd);
226 std::swap(initialRangeStart, initialRangeEnd);
214 }
227 }
215
228
216 // Sets initial range on time controller
229 // Sets initial range on time controller
217 SqpRange initialRange{initialRangeStart, initialRangeEnd};
230 SqpRange initialRange{initialRangeStart, initialRangeEnd};
218 qCInfo(LOG_TestAmdaFuzzing()) << "Setting initial range to" << initialRange << "...";
231 qCInfo(LOG_TestAmdaFuzzing()) << "Setting initial range to" << initialRange << "...";
219 timeController.onTimeToUpdate(initialRange);
232 timeController.onTimeToUpdate(initialRange);
220
233
221 FuzzingTest test{variableController, properties};
234 FuzzingTest test{variableController, properties};
222 test.execute();
235 test.execute();
223 }
236 }
224
237
225 int main(int argc, char *argv[])
238 int main(int argc, char *argv[])
226 {
239 {
227 QLoggingCategory::setFilterRules(
240 QLoggingCategory::setFilterRules(
228 "*.warning=false\n"
241 "*.warning=false\n"
229 "*.info=false\n"
242 "*.info=false\n"
230 "*.debug=false\n"
243 "*.debug=false\n"
231 "FuzzingOperations.info=true\n"
244 "FuzzingOperations.info=true\n"
232 "TestAmdaFuzzing.info=true\n");
245 "TestAmdaFuzzing.info=true\n");
233
246
234 SqpApplication app{argc, argv};
247 SqpApplication app{argc, argv};
235 app.setAttribute(Qt::AA_Use96Dpi, true);
248 app.setAttribute(Qt::AA_Use96Dpi, true);
236 TestAmdaFuzzing testObject{};
249 TestAmdaFuzzing testObject{};
237 QTEST_SET_MAIN_SOURCE_PATH
250 QTEST_SET_MAIN_SOURCE_PATH
238 return QTest::qExec(&testObject, argc, argv);
251 return QTest::qExec(&testObject, argc, argv);
239 }
252 }
240
253
241 #include "TestAmdaFuzzing.moc"
254 #include "TestAmdaFuzzing.moc"
General Comments 0
You need to be logged in to leave comments. Login now