##// END OF EJS Templates
Implements execute() method of desync operation...
Alexandre Leroux -
r1241:5f4e5de2ac36
parent child
Show More
@@ -1,77 +1,91
1 1 #include "FuzzingDefs.h"
2 2
3 3 const QString NB_MAX_OPERATIONS_PROPERTY = QStringLiteral("component");
4 4 const QString NB_MAX_SYNC_GROUPS_PROPERTY = QStringLiteral("nbSyncGroups");
5 5 const QString NB_MAX_VARIABLES_PROPERTY = QStringLiteral("nbMaxVariables");
6 6 const QString AVAILABLE_OPERATIONS_PROPERTY = QStringLiteral("availableOperations");
7 7 const QString CACHE_TOLERANCE_PROPERTY = QStringLiteral("cacheTolerance");
8 8 const QString INITIAL_RANGE_PROPERTY = QStringLiteral("initialRange");
9 9 const QString MAX_RANGE_PROPERTY = QStringLiteral("maxRange");
10 10 const QString METADATA_POOL_PROPERTY = QStringLiteral("metadataPool");
11 11 const QString PROVIDER_PROPERTY = QStringLiteral("provider");
12 12 const QString OPERATION_DELAY_PROPERTY = QStringLiteral("operationDelay");
13 13 const QString VALIDATORS_PROPERTY = QStringLiteral("validators");
14 14
15 15 // //////////// //
16 16 // FuzzingState //
17 17 // //////////// //
18 18
19 19 const SyncGroup &FuzzingState::syncGroup(SyncGroupId id) const
20 20 {
21 21 return m_SyncGroupsPool.at(id);
22 22 }
23 23
24 24 SyncGroup &FuzzingState::syncGroup(SyncGroupId id)
25 25 {
26 26 return m_SyncGroupsPool.at(id);
27 27 }
28 28
29 29 const VariableState &FuzzingState::variableState(VariableId id) const
30 30 {
31 31 return m_VariablesPool.at(id);
32 32 }
33 33
34 34 VariableState &FuzzingState::variableState(VariableId id)
35 35 {
36 36 return m_VariablesPool.at(id);
37 37 }
38 38
39 39 SyncGroupId FuzzingState::syncGroupId(VariableId variableId) const
40 40 {
41 41 auto end = m_SyncGroupsPool.cend();
42 42 auto it
43 43 = std::find_if(m_SyncGroupsPool.cbegin(), end, [&variableId](const auto &syncGroupEntry) {
44 44 const auto &syncGroup = syncGroupEntry.second;
45 45 return syncGroup.m_Variables.find(variableId) != syncGroup.m_Variables.end();
46 46 });
47 47
48 48 return it != end ? it->first : SyncGroupId{};
49 49 }
50 50
51 51 std::vector<SyncGroupId> FuzzingState::syncGroupsIds() const
52 52 {
53 53 std::vector<SyncGroupId> result{};
54 54
55 55 for (const auto &entry : m_SyncGroupsPool) {
56 56 result.push_back(entry.first);
57 57 }
58 58
59 59 return result;
60 60 }
61 61
62 62 void FuzzingState::synchronizeVariable(VariableId variableId, SyncGroupId syncGroupId)
63 63 {
64 64 if (syncGroupId.isNull()) {
65 65 return;
66 66 }
67 67
68 68 // Registers variable into sync group: if it's the first variable, sets the variable range as
69 69 // the sync group range
70 70 auto &syncGroup = m_SyncGroupsPool.at(syncGroupId);
71 71 syncGroup.m_Variables.insert(variableId);
72 72 if (syncGroup.m_Variables.size() == 1) {
73 73 auto &variableState = m_VariablesPool.at(variableId);
74 74 syncGroup.m_Range = variableState.m_Range;
75 75 }
76 76 }
77 77
78 void FuzzingState::desynchronizeVariable(VariableId variableId, SyncGroupId syncGroupId)
79 {
80 if (syncGroupId.isNull()) {
81 return;
82 }
83
84 // Unregisters variable from sync group: if there is no more variable in the group, resets the range
85 auto &syncGroup = m_SyncGroupsPool.at(syncGroupId);
86 syncGroup.m_Variables.erase(variableId);
87 if (syncGroup.m_Variables.empty()) {
88 syncGroup.m_Range = INVALID_RANGE;
89 }
90 }
91
@@ -1,113 +1,118
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 <QUuid>
8 8 #include <QVariantHash>
9 9
10 10 #include <memory>
11 11 #include <set>
12 12
13 13 // /////// //
14 14 // Aliases //
15 15 // /////// //
16 16
17 17 using MetadataPool = std::vector<QVariantHash>;
18 18 Q_DECLARE_METATYPE(MetadataPool)
19 19
20 20 using Properties = QVariantHash;
21 21
22 22 // ///////// //
23 23 // Constants //
24 24 // ///////// //
25 25
26 26 /// Max number of operations to generate
27 27 extern const QString NB_MAX_OPERATIONS_PROPERTY;
28 28
29 29 /// Max number of sync groups to create through operations
30 30 extern const QString NB_MAX_SYNC_GROUPS_PROPERTY;
31 31
32 32 /// Max number of variables to manipulate through operations
33 33 extern const QString NB_MAX_VARIABLES_PROPERTY;
34 34
35 35 /// Set of operations available for the test
36 36 extern const QString AVAILABLE_OPERATIONS_PROPERTY;
37 37
38 38 /// Tolerance used for variable's cache (in ratio)
39 39 extern const QString CACHE_TOLERANCE_PROPERTY;
40 40
41 41 /// Range with which the timecontroller is initialized
42 42 extern const QString INITIAL_RANGE_PROPERTY;
43 43
44 44 /// Max range that an operation can reach
45 45 extern const QString MAX_RANGE_PROPERTY;
46 46
47 47 /// Set of metadata that can be associated to a variable
48 48 extern const QString METADATA_POOL_PROPERTY;
49 49
50 50 /// Provider used to retrieve data
51 51 extern const QString PROVIDER_PROPERTY;
52 52
53 53 /// Time left for an operation to execute
54 54 extern const QString OPERATION_DELAY_PROPERTY;
55 55
56 56 /// Validators used to validate an operation
57 57 extern const QString VALIDATORS_PROPERTY;
58 58
59 59 // /////// //
60 60 // Structs //
61 61 // /////// //
62 62
63 63 class Variable;
64 64 struct VariableState {
65 65 std::shared_ptr<Variable> m_Variable{nullptr};
66 66 SqpRange m_Range{INVALID_RANGE};
67 67 };
68 68
69 69 using VariableId = int;
70 70 using VariablesPool = std::map<VariableId, VariableState>;
71 71
72 72 /**
73 73 * Defines a synchronization group for a fuzzing state. A group reports the variables synchronized
74 74 * with each other, and the current range of the group (i.e. range of the last synchronized variable
75 75 * that has been moved)
76 76 */
77 77 struct SyncGroup {
78 78 std::set<VariableId> m_Variables{};
79 79 SqpRange m_Range{INVALID_RANGE};
80 80 };
81 81
82 82 using SyncGroupId = QUuid;
83 83 using SyncGroupsPool = std::map<SyncGroupId, SyncGroup>;
84 84
85 85 /**
86 86 * Defines a current state during a fuzzing state. It contains all the variables manipulated during
87 87 * the test, as well as the synchronization status of these variables.
88 88 */
89 89 struct FuzzingState {
90 90 const SyncGroup &syncGroup(SyncGroupId id) const;
91 91 SyncGroup &syncGroup(SyncGroupId id);
92 92
93 93 const VariableState &variableState(VariableId id) const;
94 94 VariableState &variableState(VariableId id);
95 95
96 96 /// @return the identifier of the synchronization group in which the variable passed in
97 97 /// parameter is located. If the variable is not in any group, returns an invalid identifier
98 98 SyncGroupId syncGroupId(VariableId variableId) const;
99 99
100 100 /// @return the set of synchronization group identifiers
101 101 std::vector<SyncGroupId> syncGroupsIds() const;
102 102
103 103 /// Updates fuzzing state according to a variable synchronization
104 104 /// @param variableId the variable that is synchronized
105 105 /// @param syncGroupId the synchronization group
106 106 void synchronizeVariable(VariableId variableId, SyncGroupId syncGroupId);
107 107
108 /// Updates fuzzing state according to a variable desynchronization
109 /// @param variableId the variable that is desynchronized
110 /// @param syncGroupId the synchronization group from which to remove the variable
111 void desynchronizeVariable(VariableId variableId, SyncGroupId syncGroupId);
112
108 113
109 114 VariablesPool m_VariablesPool;
110 115 SyncGroupsPool m_SyncGroupsPool;
111 116 };
112 117
113 118 #endif // SCIQLOP_FUZZINGDEFS_H
@@ -1,245 +1,264
1 1 #include "FuzzingOperations.h"
2 2 #include "FuzzingUtils.h"
3 3
4 4 #include <Data/IDataProvider.h>
5 5
6 6 #include <Variable/Variable.h>
7 7 #include <Variable/VariableController.h>
8 8
9 9 #include <QUuid>
10 10
11 11 #include <functional>
12 12
13 13 Q_LOGGING_CATEGORY(LOG_FuzzingOperations, "FuzzingOperations")
14 14
15 15 namespace {
16 16
17 17 struct CreateOperation : public IFuzzingOperation {
18 18 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
19 19 {
20 20 // A variable can be created only if it doesn't exist yet
21 21 return fuzzingState.variableState(variableId).m_Variable == nullptr;
22 22 }
23 23
24 24 void execute(VariableId variableId, FuzzingState &fuzzingState,
25 25 VariableController &variableController,
26 26 const Properties &properties) const override
27 27 {
28 28 // Retrieves metadata pool from properties, and choose one of the metadata entries to
29 29 // associate it with the variable
30 30 auto metaDataPool = properties.value(METADATA_POOL_PROPERTY).value<MetadataPool>();
31 31 auto variableMetadata = RandomGenerator::instance().randomChoice(metaDataPool);
32 32
33 33 // Retrieves provider
34 34 auto variableProvider
35 35 = properties.value(PROVIDER_PROPERTY).value<std::shared_ptr<IDataProvider> >();
36 36
37 37 auto variableName = QString{"Var_%1"}.arg(QUuid::createUuid().toString());
38 38 qCInfo(LOG_FuzzingOperations()).noquote()
39 39 << "Creating variable" << variableName << "(metadata:" << variableMetadata << ")...";
40 40
41 41 auto newVariable
42 42 = variableController.createVariable(variableName, variableMetadata, variableProvider);
43 43
44 44 // Updates variable's state
45 45 auto &variableState = fuzzingState.variableState(variableId);
46 46 variableState.m_Range = properties.value(INITIAL_RANGE_PROPERTY).value<SqpRange>();
47 47 std::swap(variableState.m_Variable, newVariable);
48 48 }
49 49 };
50 50
51 51 struct DeleteOperation : public IFuzzingOperation {
52 52 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
53 53 {
54 54 // A variable can be delete only if it exists
55 55 return fuzzingState.variableState(variableId).m_Variable != nullptr;
56 56 }
57 57
58 58 void execute(VariableId variableId, FuzzingState &fuzzingState,
59 59 VariableController &variableController, const Properties &) const override
60 60 {
61 61 auto &variableState = fuzzingState.variableState(variableId);
62 62
63 63 qCInfo(LOG_FuzzingOperations()).noquote()
64 64 << "Deleting variable" << variableState.m_Variable->name() << "...";
65 65 variableController.deleteVariable(variableState.m_Variable);
66 66
67 67 // Updates variable's state
68 68 variableState.m_Range = INVALID_RANGE;
69 69 variableState.m_Variable = nullptr;
70
71 // Desynchronizes the variable if it was in a sync group
72 auto syncGroupId = fuzzingState.syncGroupId(variableId);
73 fuzzingState.desynchronizeVariable(variableId, syncGroupId);
70 74 }
71 75 };
72 76
73 77 /**
74 78 * Defines a move operation through a range.
75 79 *
76 80 * A move operation is determined by three functions:
77 81 * - Two 'move' functions, used to indicate in which direction the beginning and the end of a range
78 82 * are going during the operation. These functions will be:
79 83 * -- {<- / <-} for pan left
80 84 * -- {-> / ->} for pan right
81 85 * -- {-> / <-} for zoom in
82 86 * -- {<- / ->} for zoom out
83 87 * - One 'max move' functions, used to compute the max delta at which the operation can move a
84 88 * range, according to a max range. For exemple, for a range of {1, 5} and a max range of {0, 10},
85 89 * max deltas will be:
86 90 * -- {0, 4} for pan left
87 91 * -- {6, 10} for pan right
88 92 * -- {3, 3} for zoom in
89 93 * -- {0, 6} for zoom out (same spacing left and right)
90 94 */
91 95 struct MoveOperation : public IFuzzingOperation {
92 96 using MoveFunction = std::function<double(double currentValue, double maxValue)>;
93 97 using MaxMoveFunction = std::function<double(const SqpRange &range, const SqpRange &maxRange)>;
94 98
95 99 explicit MoveOperation(MoveFunction rangeStartMoveFun, MoveFunction rangeEndMoveFun,
96 100 MaxMoveFunction maxMoveFun,
97 101 const QString &label = QStringLiteral("Move operation"))
98 102 : m_RangeStartMoveFun{std::move(rangeStartMoveFun)},
99 103 m_RangeEndMoveFun{std::move(rangeEndMoveFun)},
100 104 m_MaxMoveFun{std::move(maxMoveFun)},
101 105 m_Label{label}
102 106 {
103 107 }
104 108
105 109 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
106 110 {
107 111 return fuzzingState.variableState(variableId).m_Variable != nullptr;
108 112 }
109 113
110 114 void execute(VariableId variableId, FuzzingState &fuzzingState,
111 115 VariableController &variableController,
112 116 const Properties &properties) const override
113 117 {
114 118 auto &variableState = fuzzingState.variableState(variableId);
115 119 auto variable = variableState.m_Variable;
116 120
117 121 // Gets the max range defined
118 122 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
119 123 .value<SqpRange>();
120 124 auto variableRange = variable->range();
121 125
122 126 if (maxRange == INVALID_RANGE || variableRange.m_TStart < maxRange.m_TStart
123 127 || variableRange.m_TEnd > maxRange.m_TEnd) {
124 128 qCWarning(LOG_FuzzingOperations()) << "Can't execute operation: invalid max range";
125 129 return;
126 130 }
127 131
128 132 // Computes the max delta at which the variable can move, up to the limits of the max range
129 133 auto deltaMax = m_MaxMoveFun(variable->range(), maxRange);
130 134
131 135 // Generates random delta that will be used to move variable
132 136 auto delta = RandomGenerator::instance().generateDouble(0, deltaMax);
133 137
134 138 // Moves variable to its new range
135 139 auto newVariableRange = SqpRange{m_RangeStartMoveFun(variableRange.m_TStart, delta),
136 140 m_RangeEndMoveFun(variableRange.m_TEnd, delta)};
137 141 qCInfo(LOG_FuzzingOperations()).noquote()
138 142 << "Performing" << m_Label << "on" << variable->name() << "(from" << variableRange
139 143 << "to" << newVariableRange << ")...";
140 144 variableController.onRequestDataLoading({variable}, newVariableRange, false);
141 145
142 146 // Updates variable's state
143 147 variableState.m_Range = newVariableRange;
144 148 }
145 149
146 150 MoveFunction m_RangeStartMoveFun;
147 151 MoveFunction m_RangeEndMoveFun;
148 152 MaxMoveFunction m_MaxMoveFun;
149 153 QString m_Label;
150 154 };
151 155
152 156 struct SynchronizeOperation : public IFuzzingOperation {
153 157 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
154 158 {
155 159 auto variable = fuzzingState.variableState(variableId).m_Variable;
156 160 return variable != nullptr && !fuzzingState.m_SyncGroupsPool.empty()
157 161 && fuzzingState.syncGroupId(variableId).isNull();
158 162 }
159 163
160 164 void execute(VariableId variableId, FuzzingState &fuzzingState,
161 165 VariableController &variableController, const Properties &) const override
162 166 {
163 167 auto &variableState = fuzzingState.variableState(variableId);
164 168
165 169 // Chooses a random synchronization group and adds the variable into sync group
166 170 auto syncGroupId = RandomGenerator::instance().randomChoice(fuzzingState.syncGroupsIds());
167 171 qCInfo(LOG_FuzzingOperations()).noquote()
168 172 << "Adding" << variableState.m_Variable->name() << "into synchronization group"
169 173 << syncGroupId << "...";
170 174 variableController.onAddSynchronized(variableState.m_Variable, syncGroupId);
171 175
172 176 // Updates state
173 177 fuzzingState.synchronizeVariable(variableId, syncGroupId);
174 178 }
175 179 };
176 180
177 181 struct DesynchronizeOperation : public IFuzzingOperation {
178 182 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
179 183 {
180 184 auto variable = fuzzingState.variableState(variableId).m_Variable;
181 185 return variable != nullptr && !fuzzingState.syncGroupId(variableId).isNull();
182 186 }
183 187
184 188 void execute(VariableId variableId, FuzzingState &fuzzingState,
185 189 VariableController &variableController, const Properties &) const override
186 190 {
191 auto &variableState = fuzzingState.variableState(variableId);
192
193 // Gets the sync group of the variable
194 auto syncGroupId = fuzzingState.syncGroupId(variableId);
195
196 qCInfo(LOG_FuzzingOperations()).noquote()
197 << "Removing" << variableState.m_Variable->name() << "from synchronization group"
198 << syncGroupId << "...";
199 variableController.onAddSynchronized(variableState.m_Variable, syncGroupId);
200
201 // Updates state
202 fuzzingState.desynchronizeVariable(variableId, syncGroupId);
203 }
204 };
205
187 206 struct UnknownOperation : public IFuzzingOperation {
188 207 bool canExecute(VariableId, const FuzzingState &) const override { return false; }
189 208
190 209 void execute(VariableId, FuzzingState &, VariableController &,
191 210 const Properties &) const override
192 211 {
193 212 }
194 213 };
195 214
196 215 } // namespace
197 216
198 217 std::unique_ptr<IFuzzingOperation> FuzzingOperationFactory::create(FuzzingOperationType type)
199 218 {
200 219 switch (type) {
201 220 case FuzzingOperationType::CREATE:
202 221 return std::make_unique<CreateOperation>();
203 222 case FuzzingOperationType::DELETE:
204 223 return std::make_unique<DeleteOperation>();
205 224 case FuzzingOperationType::PAN_LEFT:
206 225 return std::make_unique<MoveOperation>(
207 226 std::minus<double>(), std::minus<double>(),
208 227 [](const SqpRange &range, const SqpRange &maxRange) {
209 228 return range.m_TStart - maxRange.m_TStart;
210 229 },
211 230 QStringLiteral("Pan left operation"));
212 231 case FuzzingOperationType::PAN_RIGHT:
213 232 return std::make_unique<MoveOperation>(
214 233 std::plus<double>(), std::plus<double>(),
215 234 [](const SqpRange &range, const SqpRange &maxRange) {
216 235 return maxRange.m_TEnd - range.m_TEnd;
217 236 },
218 237 QStringLiteral("Pan right operation"));
219 238 case FuzzingOperationType::ZOOM_IN:
220 239 return std::make_unique<MoveOperation>(
221 240 std::plus<double>(), std::minus<double>(),
222 241 [](const SqpRange &range, const SqpRange &maxRange) {
223 242 Q_UNUSED(maxRange)
224 243 return range.m_TEnd - (range.m_TStart + range.m_TEnd) / 2.;
225 244 },
226 245 QStringLiteral("Zoom in operation"));
227 246 case FuzzingOperationType::ZOOM_OUT:
228 247 return std::make_unique<MoveOperation>(
229 248 std::minus<double>(), std::plus<double>(),
230 249 [](const SqpRange &range, const SqpRange &maxRange) {
231 250 return std::min(range.m_TStart - maxRange.m_TStart,
232 251 maxRange.m_TEnd - range.m_TEnd);
233 252 },
234 253 QStringLiteral("Zoom out operation"));
235 254 case FuzzingOperationType::SYNCHRONIZE:
236 255 return std::make_unique<SynchronizeOperation>();
237 256 case FuzzingOperationType::DESYNCHRONIZE:
238 257 return std::make_unique<DesynchronizeOperation>();
239 258 default:
240 259 // Default case returns unknown operation
241 260 break;
242 261 }
243 262
244 263 return std::make_unique<UnknownOperation>();
245 264 }
General Comments 0
You need to be logged in to leave comments. Login now