##// END OF EJS Templates
Creates sync and desync operations and adds them to the fuzzing tests
Alexandre Leroux -
r1238:b0db13ba024e
parent child
Show More
@@ -1,206 +1,229
1 #include "FuzzingOperations.h"
1 #include "FuzzingOperations.h"
2 #include "FuzzingUtils.h"
2 #include "FuzzingUtils.h"
3
3
4 #include <Data/IDataProvider.h>
4 #include <Data/IDataProvider.h>
5
5
6 #include <Variable/Variable.h>
6 #include <Variable/Variable.h>
7 #include <Variable/VariableController.h>
7 #include <Variable/VariableController.h>
8
8
9 #include <QUuid>
9 #include <QUuid>
10
10
11 #include <functional>
11 #include <functional>
12
12
13 Q_LOGGING_CATEGORY(LOG_FuzzingOperations, "FuzzingOperations")
13 Q_LOGGING_CATEGORY(LOG_FuzzingOperations, "FuzzingOperations")
14
14
15 namespace {
15 namespace {
16
16
17 struct CreateOperation : public IFuzzingOperation {
17 struct CreateOperation : public IFuzzingOperation {
18 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
18 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
19 {
19 {
20 // A variable can be created only if it doesn't exist yet
20 // A variable can be created only if it doesn't exist yet
21 return fuzzingState.variableState(variableId).m_Variable == nullptr;
21 return fuzzingState.variableState(variableId).m_Variable == nullptr;
22 }
22 }
23
23
24 void execute(VariableId variableId, FuzzingState &fuzzingState,
24 void execute(VariableId variableId, FuzzingState &fuzzingState,
25 VariableController &variableController,
25 VariableController &variableController,
26 const Properties &properties) const override
26 const Properties &properties) const override
27 {
27 {
28 // Retrieves metadata pool from properties, and choose one of the metadata entries to
28 // Retrieves metadata pool from properties, and choose one of the metadata entries to
29 // associate it with the variable
29 // associate it with the variable
30 auto metaDataPool = properties.value(METADATA_POOL_PROPERTY).value<MetadataPool>();
30 auto metaDataPool = properties.value(METADATA_POOL_PROPERTY).value<MetadataPool>();
31 auto variableMetadata = RandomGenerator::instance().randomChoice(metaDataPool);
31 auto variableMetadata = RandomGenerator::instance().randomChoice(metaDataPool);
32
32
33 // Retrieves provider
33 // Retrieves provider
34 auto variableProvider
34 auto variableProvider
35 = properties.value(PROVIDER_PROPERTY).value<std::shared_ptr<IDataProvider> >();
35 = properties.value(PROVIDER_PROPERTY).value<std::shared_ptr<IDataProvider> >();
36
36
37 auto variableName = QString{"Var_%1"}.arg(QUuid::createUuid().toString());
37 auto variableName = QString{"Var_%1"}.arg(QUuid::createUuid().toString());
38 qCInfo(LOG_FuzzingOperations()).noquote()
38 qCInfo(LOG_FuzzingOperations()).noquote()
39 << "Creating variable" << variableName << "(metadata:" << variableMetadata << ")...";
39 << "Creating variable" << variableName << "(metadata:" << variableMetadata << ")...";
40
40
41 auto newVariable
41 auto newVariable
42 = variableController.createVariable(variableName, variableMetadata, variableProvider);
42 = variableController.createVariable(variableName, variableMetadata, variableProvider);
43
43
44 // Updates variable's state
44 // Updates variable's state
45 auto &variableState = fuzzingState.variableState(variableId);
45 auto &variableState = fuzzingState.variableState(variableId);
46 variableState.m_Range = properties.value(INITIAL_RANGE_PROPERTY).value<SqpRange>();
46 variableState.m_Range = properties.value(INITIAL_RANGE_PROPERTY).value<SqpRange>();
47 std::swap(variableState.m_Variable, newVariable);
47 std::swap(variableState.m_Variable, newVariable);
48 }
48 }
49 };
49 };
50
50
51 struct DeleteOperation : public IFuzzingOperation {
51 struct DeleteOperation : public IFuzzingOperation {
52 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
52 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
53 {
53 {
54 // A variable can be delete only if it exists
54 // A variable can be delete only if it exists
55 return fuzzingState.variableState(variableId).m_Variable != nullptr;
55 return fuzzingState.variableState(variableId).m_Variable != nullptr;
56 }
56 }
57
57
58 void execute(VariableId variableId, FuzzingState &fuzzingState,
58 void execute(VariableId variableId, FuzzingState &fuzzingState,
59 VariableController &variableController, const Properties &) const override
59 VariableController &variableController, const Properties &) const override
60 {
60 {
61 auto &variableState = fuzzingState.variableState(variableId);
61 auto &variableState = fuzzingState.variableState(variableId);
62
62
63 qCInfo(LOG_FuzzingOperations()).noquote()
63 qCInfo(LOG_FuzzingOperations()).noquote()
64 << "Deleting variable" << variableState.m_Variable->name() << "...";
64 << "Deleting variable" << variableState.m_Variable->name() << "...";
65 variableController.deleteVariable(variableState.m_Variable);
65 variableController.deleteVariable(variableState.m_Variable);
66
66
67 // Updates variable's state
67 // Updates variable's state
68 variableState.m_Range = INVALID_RANGE;
68 variableState.m_Range = INVALID_RANGE;
69 variableState.m_Variable = nullptr;
69 variableState.m_Variable = nullptr;
70 }
70 }
71 };
71 };
72
72
73 /**
73 /**
74 * Defines a move operation through a range.
74 * Defines a move operation through a range.
75 *
75 *
76 * A move operation is determined by three functions:
76 * A move operation is determined by three functions:
77 * - Two 'move' functions, used to indicate in which direction the beginning and the end of a range
77 * - Two 'move' functions, used to indicate in which direction the beginning and the end of a range
78 * are going during the operation. These functions will be:
78 * are going during the operation. These functions will be:
79 * -- {<- / <-} for pan left
79 * -- {<- / <-} for pan left
80 * -- {-> / ->} for pan right
80 * -- {-> / ->} for pan right
81 * -- {-> / <-} for zoom in
81 * -- {-> / <-} for zoom in
82 * -- {<- / ->} for zoom out
82 * -- {<- / ->} for zoom out
83 * - One 'max move' functions, used to compute the max delta at which the operation can move a
83 * - One 'max move' functions, used to compute the max delta at which the operation can move a
84 * range, according to a max range. For exemple, for a range of {1, 5} and a max range of {0, 10},
84 * range, according to a max range. For exemple, for a range of {1, 5} and a max range of {0, 10},
85 * max deltas will be:
85 * max deltas will be:
86 * -- {0, 4} for pan left
86 * -- {0, 4} for pan left
87 * -- {6, 10} for pan right
87 * -- {6, 10} for pan right
88 * -- {3, 3} for zoom in
88 * -- {3, 3} for zoom in
89 * -- {0, 6} for zoom out (same spacing left and right)
89 * -- {0, 6} for zoom out (same spacing left and right)
90 */
90 */
91 struct MoveOperation : public IFuzzingOperation {
91 struct MoveOperation : public IFuzzingOperation {
92 using MoveFunction = std::function<double(double currentValue, double maxValue)>;
92 using MoveFunction = std::function<double(double currentValue, double maxValue)>;
93 using MaxMoveFunction = std::function<double(const SqpRange &range, const SqpRange &maxRange)>;
93 using MaxMoveFunction = std::function<double(const SqpRange &range, const SqpRange &maxRange)>;
94
94
95 explicit MoveOperation(MoveFunction rangeStartMoveFun, MoveFunction rangeEndMoveFun,
95 explicit MoveOperation(MoveFunction rangeStartMoveFun, MoveFunction rangeEndMoveFun,
96 MaxMoveFunction maxMoveFun,
96 MaxMoveFunction maxMoveFun,
97 const QString &label = QStringLiteral("Move operation"))
97 const QString &label = QStringLiteral("Move operation"))
98 : m_RangeStartMoveFun{std::move(rangeStartMoveFun)},
98 : m_RangeStartMoveFun{std::move(rangeStartMoveFun)},
99 m_RangeEndMoveFun{std::move(rangeEndMoveFun)},
99 m_RangeEndMoveFun{std::move(rangeEndMoveFun)},
100 m_MaxMoveFun{std::move(maxMoveFun)},
100 m_MaxMoveFun{std::move(maxMoveFun)},
101 m_Label{label}
101 m_Label{label}
102 {
102 {
103 }
103 }
104
104
105 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
105 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
106 {
106 {
107 return fuzzingState.variableState(variableId).m_Variable != nullptr;
107 return fuzzingState.variableState(variableId).m_Variable != nullptr;
108 }
108 }
109
109
110 void execute(VariableId variableId, FuzzingState &fuzzingState,
110 void execute(VariableId variableId, FuzzingState &fuzzingState,
111 VariableController &variableController,
111 VariableController &variableController,
112 const Properties &properties) const override
112 const Properties &properties) const override
113 {
113 {
114 auto &variableState = fuzzingState.variableState(variableId);
114 auto &variableState = fuzzingState.variableState(variableId);
115 auto variable = variableState.m_Variable;
115 auto variable = variableState.m_Variable;
116
116
117 // Gets the max range defined
117 // Gets the max range defined
118 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
118 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
119 .value<SqpRange>();
119 .value<SqpRange>();
120 auto variableRange = variable->range();
120 auto variableRange = variable->range();
121
121
122 if (maxRange == INVALID_RANGE || variableRange.m_TStart < maxRange.m_TStart
122 if (maxRange == INVALID_RANGE || variableRange.m_TStart < maxRange.m_TStart
123 || variableRange.m_TEnd > maxRange.m_TEnd) {
123 || variableRange.m_TEnd > maxRange.m_TEnd) {
124 qCWarning(LOG_FuzzingOperations()) << "Can't execute operation: invalid max range";
124 qCWarning(LOG_FuzzingOperations()) << "Can't execute operation: invalid max range";
125 return;
125 return;
126 }
126 }
127
127
128 // Computes the max delta at which the variable can move, up to the limits of the max range
128 // Computes the max delta at which the variable can move, up to the limits of the max range
129 auto deltaMax = m_MaxMoveFun(variable->range(), maxRange);
129 auto deltaMax = m_MaxMoveFun(variable->range(), maxRange);
130
130
131 // Generates random delta that will be used to move variable
131 // Generates random delta that will be used to move variable
132 auto delta = RandomGenerator::instance().generateDouble(0, deltaMax);
132 auto delta = RandomGenerator::instance().generateDouble(0, deltaMax);
133
133
134 // Moves variable to its new range
134 // Moves variable to its new range
135 auto newVariableRange = SqpRange{m_RangeStartMoveFun(variableRange.m_TStart, delta),
135 auto newVariableRange = SqpRange{m_RangeStartMoveFun(variableRange.m_TStart, delta),
136 m_RangeEndMoveFun(variableRange.m_TEnd, delta)};
136 m_RangeEndMoveFun(variableRange.m_TEnd, delta)};
137 qCInfo(LOG_FuzzingOperations()).noquote()
137 qCInfo(LOG_FuzzingOperations()).noquote()
138 << "Performing" << m_Label << "on" << variable->name() << "(from" << variableRange
138 << "Performing" << m_Label << "on" << variable->name() << "(from" << variableRange
139 << "to" << newVariableRange << ")...";
139 << "to" << newVariableRange << ")...";
140 variableController.onRequestDataLoading({variable}, newVariableRange, false);
140 variableController.onRequestDataLoading({variable}, newVariableRange, false);
141
141
142 // Updates variable's state
142 // Updates variable's state
143 variableState.m_Range = newVariableRange;
143 variableState.m_Range = newVariableRange;
144 }
144 }
145
145
146 MoveFunction m_RangeStartMoveFun;
146 MoveFunction m_RangeStartMoveFun;
147 MoveFunction m_RangeEndMoveFun;
147 MoveFunction m_RangeEndMoveFun;
148 MaxMoveFunction m_MaxMoveFun;
148 MaxMoveFunction m_MaxMoveFun;
149 QString m_Label;
149 QString m_Label;
150 };
150 };
151
151
152 struct SynchronizeOperation : public IFuzzingOperation {
153 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
154 {
155 }
156
157 void execute(VariableId variableId, FuzzingState &fuzzingState,
158 VariableController &variableController, const Properties &) const override
159 {
160 }
161 };
162
163 struct DesynchronizeOperation : public IFuzzingOperation {
164 bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const override
165 {
166 }
167
168 void execute(VariableId variableId, FuzzingState &fuzzingState,
169 VariableController &variableController, const Properties &) const override
170 {
152 struct UnknownOperation : public IFuzzingOperation {
171 struct UnknownOperation : public IFuzzingOperation {
153 bool canExecute(VariableId, const FuzzingState &) const override { return false; }
172 bool canExecute(VariableId, const FuzzingState &) const override { return false; }
154
173
155 void execute(VariableId, FuzzingState &, VariableController &,
174 void execute(VariableId, FuzzingState &, VariableController &,
156 const Properties &) const override
175 const Properties &) const override
157 {
176 {
158 }
177 }
159 };
178 };
160
179
161 } // namespace
180 } // namespace
162
181
163 std::unique_ptr<IFuzzingOperation> FuzzingOperationFactory::create(FuzzingOperationType type)
182 std::unique_ptr<IFuzzingOperation> FuzzingOperationFactory::create(FuzzingOperationType type)
164 {
183 {
165 switch (type) {
184 switch (type) {
166 case FuzzingOperationType::CREATE:
185 case FuzzingOperationType::CREATE:
167 return std::make_unique<CreateOperation>();
186 return std::make_unique<CreateOperation>();
168 case FuzzingOperationType::DELETE:
187 case FuzzingOperationType::DELETE:
169 return std::make_unique<DeleteOperation>();
188 return std::make_unique<DeleteOperation>();
170 case FuzzingOperationType::PAN_LEFT:
189 case FuzzingOperationType::PAN_LEFT:
171 return std::make_unique<MoveOperation>(
190 return std::make_unique<MoveOperation>(
172 std::minus<double>(), std::minus<double>(),
191 std::minus<double>(), std::minus<double>(),
173 [](const SqpRange &range, const SqpRange &maxRange) {
192 [](const SqpRange &range, const SqpRange &maxRange) {
174 return range.m_TStart - maxRange.m_TStart;
193 return range.m_TStart - maxRange.m_TStart;
175 },
194 },
176 QStringLiteral("Pan left operation"));
195 QStringLiteral("Pan left operation"));
177 case FuzzingOperationType::PAN_RIGHT:
196 case FuzzingOperationType::PAN_RIGHT:
178 return std::make_unique<MoveOperation>(
197 return std::make_unique<MoveOperation>(
179 std::plus<double>(), std::plus<double>(),
198 std::plus<double>(), std::plus<double>(),
180 [](const SqpRange &range, const SqpRange &maxRange) {
199 [](const SqpRange &range, const SqpRange &maxRange) {
181 return maxRange.m_TEnd - range.m_TEnd;
200 return maxRange.m_TEnd - range.m_TEnd;
182 },
201 },
183 QStringLiteral("Pan right operation"));
202 QStringLiteral("Pan right operation"));
184 case FuzzingOperationType::ZOOM_IN:
203 case FuzzingOperationType::ZOOM_IN:
185 return std::make_unique<MoveOperation>(
204 return std::make_unique<MoveOperation>(
186 std::plus<double>(), std::minus<double>(),
205 std::plus<double>(), std::minus<double>(),
187 [](const SqpRange &range, const SqpRange &maxRange) {
206 [](const SqpRange &range, const SqpRange &maxRange) {
188 Q_UNUSED(maxRange)
207 Q_UNUSED(maxRange)
189 return range.m_TEnd - (range.m_TStart + range.m_TEnd) / 2.;
208 return range.m_TEnd - (range.m_TStart + range.m_TEnd) / 2.;
190 },
209 },
191 QStringLiteral("Zoom in operation"));
210 QStringLiteral("Zoom in operation"));
192 case FuzzingOperationType::ZOOM_OUT:
211 case FuzzingOperationType::ZOOM_OUT:
193 return std::make_unique<MoveOperation>(
212 return std::make_unique<MoveOperation>(
194 std::minus<double>(), std::plus<double>(),
213 std::minus<double>(), std::plus<double>(),
195 [](const SqpRange &range, const SqpRange &maxRange) {
214 [](const SqpRange &range, const SqpRange &maxRange) {
196 return std::min(range.m_TStart - maxRange.m_TStart,
215 return std::min(range.m_TStart - maxRange.m_TStart,
197 maxRange.m_TEnd - range.m_TEnd);
216 maxRange.m_TEnd - range.m_TEnd);
198 },
217 },
199 QStringLiteral("Zoom out operation"));
218 QStringLiteral("Zoom out operation"));
219 case FuzzingOperationType::SYNCHRONIZE:
220 return std::make_unique<SynchronizeOperation>();
221 case FuzzingOperationType::DESYNCHRONIZE:
222 return std::make_unique<DesynchronizeOperation>();
200 default:
223 default:
201 // Default case returns unknown operation
224 // Default case returns unknown operation
202 break;
225 break;
203 }
226 }
204
227
205 return std::make_unique<UnknownOperation>();
228 return std::make_unique<UnknownOperation>();
206 }
229 }
@@ -1,50 +1,59
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 VariableController;
14 class VariableController;
15
15
16 /**
16 /**
17 * Enumeration of types of existing fuzzing operations
17 * Enumeration of types of existing fuzzing operations
18 */
18 */
19 enum class FuzzingOperationType { CREATE, DELETE, PAN_LEFT, PAN_RIGHT, ZOOM_IN, ZOOM_OUT };
19 enum class FuzzingOperationType {
20 CREATE,
21 DELETE,
22 PAN_LEFT,
23 PAN_RIGHT,
24 ZOOM_IN,
25 ZOOM_OUT,
26 SYNCHRONIZE,
27 DESYNCHRONIZE
28 };
20
29
21 /// Interface that represents an operation that can be executed during a fuzzing test
30 /// Interface that represents an operation that can be executed during a fuzzing test
22 struct IFuzzingOperation {
31 struct IFuzzingOperation {
23 virtual ~IFuzzingOperation() noexcept = default;
32 virtual ~IFuzzingOperation() noexcept = default;
24
33
25 /// Checks if the operation can be executed according to the current test's state for the
34 /// Checks if the operation can be executed according to the current test's state for the
26 /// variable passed in parameter
35 /// variable passed in parameter
27 virtual bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const = 0;
36 virtual bool canExecute(VariableId variableId, const FuzzingState &fuzzingState) const = 0;
28 /// Executes the operation on the variable for which its identifier is passed in parameter
37 /// Executes the operation on the variable for which its identifier is passed in parameter
29 /// @param variableId the variable identifier
38 /// @param variableId the variable identifier
30 /// @param fuzzingState the current test's state on which to find the variable and execute the
39 /// @param fuzzingState the current test's state on which to find the variable and execute the
31 /// operation
40 /// operation
32 /// @param variableController the controller associated to the operation
41 /// @param variableController the controller associated to the operation
33 /// @param properties properties that can be used to configure the operation
42 /// @param properties properties that can be used to configure the operation
34 /// @remarks fuzzingState is passed as a reference because, according to the operation, it can
43 /// @remarks fuzzingState is passed as a reference because, according to the operation, it can
35 /// be modified (in/out parameter)
44 /// be modified (in/out parameter)
36 virtual void execute(VariableId variableId, FuzzingState &fuzzingState,
45 virtual void execute(VariableId variableId, FuzzingState &fuzzingState,
37 VariableController &variableController,
46 VariableController &variableController,
38 const Properties &properties = {}) const = 0;
47 const Properties &properties = {}) const = 0;
39 };
48 };
40
49
41 /// Factory of @sa IFuzzingOperation
50 /// Factory of @sa IFuzzingOperation
42 struct FuzzingOperationFactory {
51 struct FuzzingOperationFactory {
43 /// Creates a fuzzing operation from a type
52 /// Creates a fuzzing operation from a type
44 static std::unique_ptr<IFuzzingOperation> create(FuzzingOperationType type);
53 static std::unique_ptr<IFuzzingOperation> create(FuzzingOperationType type);
45 };
54 };
46
55
47 using WeightedOperationsTypes = std::map<FuzzingOperationType, double>;
56 using WeightedOperationsTypes = std::map<FuzzingOperationType, double>;
48 Q_DECLARE_METATYPE(WeightedOperationsTypes)
57 Q_DECLARE_METATYPE(WeightedOperationsTypes)
49
58
50 #endif // SCIQLOP_FUZZINGOPERATIONS_H
59 #endif // SCIQLOP_FUZZINGOPERATIONS_H
@@ -1,344 +1,346
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 Weight = double;
29 using Weight = double;
30 using Weights = std::vector<Weight>;
30 using Weights = std::vector<Weight>;
31
31
32 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
32 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
33 using VariablesOperations = std::vector<VariableOperation>;
33 using VariablesOperations = std::vector<VariableOperation>;
34
34
35 using WeightedOperationsPool = std::map<std::shared_ptr<IFuzzingOperation>, Weight>;
35 using WeightedOperationsPool = std::map<std::shared_ptr<IFuzzingOperation>, Weight>;
36 using Validators = std::vector<std::shared_ptr<IFuzzingValidator> >;
36 using Validators = std::vector<std::shared_ptr<IFuzzingValidator> >;
37
37
38 // ///////// //
38 // ///////// //
39 // Constants //
39 // Constants //
40 // ///////// //
40 // ///////// //
41
41
42 // Defaults values used when the associated properties have not been set for the test
42 // Defaults values used when the associated properties have not been set for the test
43 const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
43 const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
44 const auto NB_MAX_SYNC_GROUPS_DEFAULT_VALUE = 1;
44 const auto NB_MAX_SYNC_GROUPS_DEFAULT_VALUE = 1;
45 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
45 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
46 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE = QVariant::fromValue(WeightedOperationsTypes{
46 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE = QVariant::fromValue(WeightedOperationsTypes{
47 {FuzzingOperationType::CREATE, 1.},
47 {FuzzingOperationType::CREATE, 1.},
48 {FuzzingOperationType::DELETE, 0.1}, // Delete operation is less frequent
48 {FuzzingOperationType::DELETE, 0.1}, // Delete operation is less frequent
49 {FuzzingOperationType::PAN_LEFT, 1.},
49 {FuzzingOperationType::PAN_LEFT, 1.},
50 {FuzzingOperationType::PAN_RIGHT, 1.},
50 {FuzzingOperationType::PAN_RIGHT, 1.},
51 {FuzzingOperationType::ZOOM_IN, 1.},
51 {FuzzingOperationType::ZOOM_IN, 1.},
52 {FuzzingOperationType::ZOOM_OUT, 1.}});
52 {FuzzingOperationType::ZOOM_OUT, 1.},
53 {FuzzingOperationType::SYNCHRONIZE, 0.8},
54 {FuzzingOperationType::DESYNCHRONIZE, 0.4}});
53 const auto CACHE_TOLERANCE_DEFAULT_VALUE = 0.2;
55 const auto CACHE_TOLERANCE_DEFAULT_VALUE = 0.2;
54
56
55 /// Delay between each operation (in ms)
57 /// Delay between each operation (in ms)
56 const auto OPERATION_DELAY_DEFAULT_VALUE = 3000;
58 const auto OPERATION_DELAY_DEFAULT_VALUE = 3000;
57
59
58 /// Validators for the tests (executed in the order in which they're defined)
60 /// Validators for the tests (executed in the order in which they're defined)
59 const auto VALIDATORS_DEFAULT_VALUE = QVariant::fromValue(
61 const auto VALIDATORS_DEFAULT_VALUE = QVariant::fromValue(
60 ValidatorsTypes{{FuzzingValidatorType::RANGE, FuzzingValidatorType::DATA}});
62 ValidatorsTypes{{FuzzingValidatorType::RANGE, FuzzingValidatorType::DATA}});
61
63
62 // /////// //
64 // /////// //
63 // Methods //
65 // Methods //
64 // /////// //
66 // /////// //
65
67
66 /// Goes through the variables pool and operations pool to determine the set of {variable/operation}
68 /// Goes through the variables pool and operations pool to determine the set of {variable/operation}
67 /// pairs that are valid (i.e. operation that can be executed on variable)
69 /// pairs that are valid (i.e. operation that can be executed on variable)
68 std::pair<VariablesOperations, Weights>
70 std::pair<VariablesOperations, Weights>
69 availableOperations(const FuzzingState &fuzzingState, const WeightedOperationsPool &operationsPool)
71 availableOperations(const FuzzingState &fuzzingState, const WeightedOperationsPool &operationsPool)
70 {
72 {
71 VariablesOperations result{};
73 VariablesOperations result{};
72 Weights weights{};
74 Weights weights{};
73
75
74 for (const auto &variablesPoolEntry : fuzzingState.m_VariablesPool) {
76 for (const auto &variablesPoolEntry : fuzzingState.m_VariablesPool) {
75 auto variableId = variablesPoolEntry.first;
77 auto variableId = variablesPoolEntry.first;
76
78
77 for (const auto &operationsPoolEntry : operationsPool) {
79 for (const auto &operationsPoolEntry : operationsPool) {
78 auto operation = operationsPoolEntry.first;
80 auto operation = operationsPoolEntry.first;
79 auto weight = operationsPoolEntry.second;
81 auto weight = operationsPoolEntry.second;
80
82
81 // A pair is valid if the current operation can be executed on the current variable
83 // A pair is valid if the current operation can be executed on the current variable
82 if (operation->canExecute(variableId, fuzzingState)) {
84 if (operation->canExecute(variableId, fuzzingState)) {
83 result.push_back({variableId, operation});
85 result.push_back({variableId, operation});
84 weights.push_back(weight);
86 weights.push_back(weight);
85 }
87 }
86 }
88 }
87 }
89 }
88
90
89 return {result, weights};
91 return {result, weights};
90 }
92 }
91
93
92 WeightedOperationsPool createOperationsPool(const WeightedOperationsTypes &types)
94 WeightedOperationsPool createOperationsPool(const WeightedOperationsTypes &types)
93 {
95 {
94 WeightedOperationsPool result{};
96 WeightedOperationsPool result{};
95
97
96 std::transform(
98 std::transform(
97 types.cbegin(), types.cend(), std::inserter(result, result.end()), [](const auto &type) {
99 types.cbegin(), types.cend(), std::inserter(result, result.end()), [](const auto &type) {
98 return std::make_pair(FuzzingOperationFactory::create(type.first), type.second);
100 return std::make_pair(FuzzingOperationFactory::create(type.first), type.second);
99 });
101 });
100
102
101 return result;
103 return result;
102 }
104 }
103
105
104 Validators createValidators(const ValidatorsTypes &types)
106 Validators createValidators(const ValidatorsTypes &types)
105 {
107 {
106 Validators result{};
108 Validators result{};
107
109
108 std::transform(types.cbegin(), types.cend(), std::inserter(result, result.end()),
110 std::transform(types.cbegin(), types.cend(), std::inserter(result, result.end()),
109 [](const auto &type) { return FuzzingValidatorFactory::create(type); });
111 [](const auto &type) { return FuzzingValidatorFactory::create(type); });
110
112
111 return result;
113 return result;
112 }
114 }
113
115
114 /**
116 /**
115 * Validates all the variables' states passed in parameter, according to a set of validators
117 * Validates all the variables' states passed in parameter, according to a set of validators
116 * @param variablesPool the variables' states
118 * @param variablesPool the variables' states
117 * @param validators the validators used for validation
119 * @param validators the validators used for validation
118 */
120 */
119 void validate(const VariablesPool &variablesPool, const Validators &validators)
121 void validate(const VariablesPool &variablesPool, const Validators &validators)
120 {
122 {
121 for (const auto &variablesPoolEntry : variablesPool) {
123 for (const auto &variablesPoolEntry : variablesPool) {
122 auto variableId = variablesPoolEntry.first;
124 auto variableId = variablesPoolEntry.first;
123 const auto &variableState = variablesPoolEntry.second;
125 const auto &variableState = variablesPoolEntry.second;
124
126
125 auto variableMessage = variableState.m_Variable ? variableState.m_Variable->name()
127 auto variableMessage = variableState.m_Variable ? variableState.m_Variable->name()
126 : QStringLiteral("null variable");
128 : QStringLiteral("null variable");
127 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validating state of variable at index"
129 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validating state of variable at index"
128 << variableId << "(" << variableMessage << ")...";
130 << variableId << "(" << variableMessage << ")...";
129
131
130 for (const auto &validator : validators) {
132 for (const auto &validator : validators) {
131 validator->validate(VariableState{variableState});
133 validator->validate(VariableState{variableState});
132 }
134 }
133
135
134 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validation completed.";
136 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validation completed.";
135 }
137 }
136 }
138 }
137
139
138 /**
140 /**
139 * Class to run random tests
141 * Class to run random tests
140 */
142 */
141 class FuzzingTest {
143 class FuzzingTest {
142 public:
144 public:
143 explicit FuzzingTest(VariableController &variableController, Properties properties)
145 explicit FuzzingTest(VariableController &variableController, Properties properties)
144 : m_VariableController{variableController},
146 : m_VariableController{variableController},
145 m_Properties{std::move(properties)},
147 m_Properties{std::move(properties)},
146 m_FuzzingState{}
148 m_FuzzingState{}
147 {
149 {
148 // Inits variables pool: at init, all variables are null
150 // Inits variables pool: at init, all variables are null
149 for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
151 for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
150 m_FuzzingState.m_VariablesPool[variableId] = VariableState{};
152 m_FuzzingState.m_VariablesPool[variableId] = VariableState{};
151 }
153 }
152
154
153 // Inits sync groups and registers them into the variable controller
155 // Inits sync groups and registers them into the variable controller
154 for (auto i = 0; i < nbMaxSyncGroups(); ++i) {
156 for (auto i = 0; i < nbMaxSyncGroups(); ++i) {
155 auto syncGroupId = SyncGroupId::createUuid();
157 auto syncGroupId = SyncGroupId::createUuid();
156 variableController.onAddSynchronizationGroupId(syncGroupId);
158 variableController.onAddSynchronizationGroupId(syncGroupId);
157 m_FuzzingState.m_SyncGroupsPool[syncGroupId] = SyncGroup{};
159 m_FuzzingState.m_SyncGroupsPool[syncGroupId] = SyncGroup{};
158 }
160 }
159 }
161 }
160
162
161 void execute()
163 void execute()
162 {
164 {
163 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Running" << nbMaxOperations() << "operations on"
165 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Running" << nbMaxOperations() << "operations on"
164 << nbMaxVariables() << "variable(s)...";
166 << nbMaxVariables() << "variable(s)...";
165
167
166 auto canExecute = true;
168 auto canExecute = true;
167 for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
169 for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
168 // Retrieves all operations that can be executed in the current context
170 // Retrieves all operations that can be executed in the current context
169 VariablesOperations variableOperations{};
171 VariablesOperations variableOperations{};
170 Weights weights{};
172 Weights weights{};
171 std::tie(variableOperations, weights)
173 std::tie(variableOperations, weights)
172 = availableOperations(m_FuzzingState, operationsPool());
174 = availableOperations(m_FuzzingState, operationsPool());
173
175
174 canExecute = !variableOperations.empty();
176 canExecute = !variableOperations.empty();
175 if (canExecute) {
177 if (canExecute) {
176 // Of the operations available, chooses a random operation and executes it
178 // Of the operations available, chooses a random operation and executes it
177 auto variableOperation
179 auto variableOperation
178 = RandomGenerator::instance().randomChoice(variableOperations, weights);
180 = RandomGenerator::instance().randomChoice(variableOperations, weights);
179
181
180 auto variableId = variableOperation.first;
182 auto variableId = variableOperation.first;
181 auto fuzzingOperation = variableOperation.second;
183 auto fuzzingOperation = variableOperation.second;
182
184
183 fuzzingOperation->execute(variableId, m_FuzzingState, m_VariableController,
185 fuzzingOperation->execute(variableId, m_FuzzingState, m_VariableController,
184 m_Properties);
186 m_Properties);
185 QTest::qWait(operationDelay());
187 QTest::qWait(operationDelay());
186
188
187 // Validates variables
189 // Validates variables
188 validate(m_FuzzingState.m_VariablesPool, validators());
190 validate(m_FuzzingState.m_VariablesPool, validators());
189 }
191 }
190 else {
192 else {
191 qCInfo(LOG_TestAmdaFuzzing()).noquote()
193 qCInfo(LOG_TestAmdaFuzzing()).noquote()
192 << "No more operations are available, the execution of the test will stop...";
194 << "No more operations are available, the execution of the test will stop...";
193 }
195 }
194 }
196 }
195
197
196 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Execution of the test completed.";
198 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Execution of the test completed.";
197 }
199 }
198
200
199 private:
201 private:
200 int nbMaxOperations() const
202 int nbMaxOperations() const
201 {
203 {
202 static auto result
204 static auto result
203 = m_Properties.value(NB_MAX_OPERATIONS_PROPERTY, NB_MAX_OPERATIONS_DEFAULT_VALUE)
205 = m_Properties.value(NB_MAX_OPERATIONS_PROPERTY, NB_MAX_OPERATIONS_DEFAULT_VALUE)
204 .toInt();
206 .toInt();
205 return result;
207 return result;
206 }
208 }
207
209
208 int nbMaxSyncGroups() const
210 int nbMaxSyncGroups() const
209 {
211 {
210 static auto result
212 static auto result
211 = m_Properties.value(NB_MAX_SYNC_GROUPS_PROPERTY, NB_MAX_SYNC_GROUPS_DEFAULT_VALUE)
213 = m_Properties.value(NB_MAX_SYNC_GROUPS_PROPERTY, NB_MAX_SYNC_GROUPS_DEFAULT_VALUE)
212 .toInt();
214 .toInt();
213 return result;
215 return result;
214 }
216 }
215
217
216 int nbMaxVariables() const
218 int nbMaxVariables() const
217 {
219 {
218 static auto result
220 static auto result
219 = m_Properties.value(NB_MAX_VARIABLES_PROPERTY, NB_MAX_VARIABLES_DEFAULT_VALUE).toInt();
221 = m_Properties.value(NB_MAX_VARIABLES_PROPERTY, NB_MAX_VARIABLES_DEFAULT_VALUE).toInt();
220 return result;
222 return result;
221 }
223 }
222
224
223 int operationDelay() const
225 int operationDelay() const
224 {
226 {
225 static auto result
227 static auto result
226 = m_Properties.value(OPERATION_DELAY_PROPERTY, OPERATION_DELAY_DEFAULT_VALUE).toInt();
228 = m_Properties.value(OPERATION_DELAY_PROPERTY, OPERATION_DELAY_DEFAULT_VALUE).toInt();
227 return result;
229 return result;
228 }
230 }
229
231
230 WeightedOperationsPool operationsPool() const
232 WeightedOperationsPool operationsPool() const
231 {
233 {
232 static auto result = createOperationsPool(
234 static auto result = createOperationsPool(
233 m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
235 m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
234 .value<WeightedOperationsTypes>());
236 .value<WeightedOperationsTypes>());
235 return result;
237 return result;
236 }
238 }
237
239
238 Validators validators() const
240 Validators validators() const
239 {
241 {
240 static auto result
242 static auto result
241 = createValidators(m_Properties.value(VALIDATORS_PROPERTY, VALIDATORS_DEFAULT_VALUE)
243 = createValidators(m_Properties.value(VALIDATORS_PROPERTY, VALIDATORS_DEFAULT_VALUE)
242 .value<ValidatorsTypes>());
244 .value<ValidatorsTypes>());
243 return result;
245 return result;
244 }
246 }
245
247
246 VariableController &m_VariableController;
248 VariableController &m_VariableController;
247 Properties m_Properties;
249 Properties m_Properties;
248 FuzzingState m_FuzzingState;
250 FuzzingState m_FuzzingState;
249 };
251 };
250
252
251 } // namespace
253 } // namespace
252
254
253 class TestAmdaFuzzing : public QObject {
255 class TestAmdaFuzzing : public QObject {
254 Q_OBJECT
256 Q_OBJECT
255
257
256 private slots:
258 private slots:
257 /// Input data for @sa testFuzzing()
259 /// Input data for @sa testFuzzing()
258 void testFuzzing_data();
260 void testFuzzing_data();
259 void testFuzzing();
261 void testFuzzing();
260 };
262 };
261
263
262 void TestAmdaFuzzing::testFuzzing_data()
264 void TestAmdaFuzzing::testFuzzing_data()
263 {
265 {
264 // ////////////// //
266 // ////////////// //
265 // Test structure //
267 // Test structure //
266 // ////////////// //
268 // ////////////// //
267
269
268 QTest::addColumn<Properties>("properties"); // Properties for random test
270 QTest::addColumn<Properties>("properties"); // Properties for random test
269
271
270 // ////////// //
272 // ////////// //
271 // Test cases //
273 // Test cases //
272 // ////////// //
274 // ////////// //
273
275
274 auto maxRange = SqpRange::fromDateTime({2017, 1, 1}, {0, 0}, {2017, 1, 5}, {0, 0});
276 auto maxRange = SqpRange::fromDateTime({2017, 1, 1}, {0, 0}, {2017, 1, 5}, {0, 0});
275 MetadataPool metadataPool{{{"dataType", "vector"}, {"xml:id", "imf"}}};
277 MetadataPool metadataPool{{{"dataType", "vector"}, {"xml:id", "imf"}}};
276
278
277 // Note: we don't use auto here as we want to pass std::shared_ptr<IDataProvider> as is in the
279 // Note: we don't use auto here as we want to pass std::shared_ptr<IDataProvider> as is in the
278 // QVariant
280 // QVariant
279 std::shared_ptr<IDataProvider> provider = std::make_shared<AmdaProvider>();
281 std::shared_ptr<IDataProvider> provider = std::make_shared<AmdaProvider>();
280
282
281 QTest::newRow("fuzzingTest") << Properties{
283 QTest::newRow("fuzzingTest") << Properties{
282 {MAX_RANGE_PROPERTY, QVariant::fromValue(maxRange)},
284 {MAX_RANGE_PROPERTY, QVariant::fromValue(maxRange)},
283 {METADATA_POOL_PROPERTY, QVariant::fromValue(metadataPool)},
285 {METADATA_POOL_PROPERTY, QVariant::fromValue(metadataPool)},
284 {PROVIDER_PROPERTY, QVariant::fromValue(provider)}};
286 {PROVIDER_PROPERTY, QVariant::fromValue(provider)}};
285 }
287 }
286
288
287 void TestAmdaFuzzing::testFuzzing()
289 void TestAmdaFuzzing::testFuzzing()
288 {
290 {
289 QFETCH(Properties, properties);
291 QFETCH(Properties, properties);
290
292
291 // Sets cache property
293 // Sets cache property
292 QSettings settings{};
294 QSettings settings{};
293 auto cacheTolerance = properties.value(CACHE_TOLERANCE_PROPERTY, CACHE_TOLERANCE_DEFAULT_VALUE);
295 auto cacheTolerance = properties.value(CACHE_TOLERANCE_PROPERTY, CACHE_TOLERANCE_DEFAULT_VALUE);
294 settings.setValue(GENERAL_TOLERANCE_AT_INIT_KEY, cacheTolerance);
296 settings.setValue(GENERAL_TOLERANCE_AT_INIT_KEY, cacheTolerance);
295 settings.setValue(GENERAL_TOLERANCE_AT_UPDATE_KEY, cacheTolerance);
297 settings.setValue(GENERAL_TOLERANCE_AT_UPDATE_KEY, cacheTolerance);
296
298
297 auto &variableController = sqpApp->variableController();
299 auto &variableController = sqpApp->variableController();
298 auto &timeController = sqpApp->timeController();
300 auto &timeController = sqpApp->timeController();
299
301
300 // Generates random initial range (bounded to max range)
302 // Generates random initial range (bounded to max range)
301 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
303 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
302 .value<SqpRange>();
304 .value<SqpRange>();
303
305
304 QVERIFY(maxRange != INVALID_RANGE);
306 QVERIFY(maxRange != INVALID_RANGE);
305
307
306 auto initialRangeStart
308 auto initialRangeStart
307 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
309 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
308 auto initialRangeEnd
310 auto initialRangeEnd
309 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
311 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
310 if (initialRangeStart > initialRangeEnd) {
312 if (initialRangeStart > initialRangeEnd) {
311 std::swap(initialRangeStart, initialRangeEnd);
313 std::swap(initialRangeStart, initialRangeEnd);
312 }
314 }
313
315
314 // Sets initial range on time controller
316 // Sets initial range on time controller
315 SqpRange initialRange{initialRangeStart, initialRangeEnd};
317 SqpRange initialRange{initialRangeStart, initialRangeEnd};
316 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Setting initial range to" << initialRange << "...";
318 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Setting initial range to" << initialRange << "...";
317 timeController.onTimeToUpdate(initialRange);
319 timeController.onTimeToUpdate(initialRange);
318 properties.insert(INITIAL_RANGE_PROPERTY, QVariant::fromValue(initialRange));
320 properties.insert(INITIAL_RANGE_PROPERTY, QVariant::fromValue(initialRange));
319
321
320 FuzzingTest test{variableController, properties};
322 FuzzingTest test{variableController, properties};
321 test.execute();
323 test.execute();
322 }
324 }
323
325
324 int main(int argc, char *argv[])
326 int main(int argc, char *argv[])
325 {
327 {
326 QLoggingCategory::setFilterRules(
328 QLoggingCategory::setFilterRules(
327 "*.warning=false\n"
329 "*.warning=false\n"
328 "*.info=false\n"
330 "*.info=false\n"
329 "*.debug=false\n"
331 "*.debug=false\n"
330 "FuzzingOperations.info=true\n"
332 "FuzzingOperations.info=true\n"
331 "FuzzingValidators.info=true\n"
333 "FuzzingValidators.info=true\n"
332 "TestAmdaFuzzing.info=true\n");
334 "TestAmdaFuzzing.info=true\n");
333
335
334 SqpApplication app{argc, argv};
336 SqpApplication app{argc, argv};
335 SqpApplication::setOrganizationName("LPP");
337 SqpApplication::setOrganizationName("LPP");
336 SqpApplication::setOrganizationDomain("lpp.fr");
338 SqpApplication::setOrganizationDomain("lpp.fr");
337 SqpApplication::setApplicationName("SciQLop-TestFuzzing");
339 SqpApplication::setApplicationName("SciQLop-TestFuzzing");
338 app.setAttribute(Qt::AA_Use96Dpi, true);
340 app.setAttribute(Qt::AA_Use96Dpi, true);
339 TestAmdaFuzzing testObject{};
341 TestAmdaFuzzing testObject{};
340 QTEST_SET_MAIN_SOURCE_PATH
342 QTEST_SET_MAIN_SOURCE_PATH
341 return QTest::qExec(&testObject, argc, argv);
343 return QTest::qExec(&testObject, argc, argv);
342 }
344 }
343
345
344 #include "TestAmdaFuzzing.moc"
346 #include "TestAmdaFuzzing.moc"
General Comments 0
You need to be logged in to leave comments. Login now