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