##// END OF EJS Templates
Wait for the end of an acquisition to validate an operation (1)...
Alexandre Leroux -
r1246:2785fa3e9772
parent child
Show More
@@ -0,0 +1,38
1 #ifndef SCIQLOP_SIGNALWAITER_H
2 #define SCIQLOP_SIGNALWAITER_H
3
4 #include "CoreGlobal.h"
5
6 #include <QEventLoop>
7
8 /**
9 * Class for synchronously waiting for the reception of a signal. The signal to wait is passed to
10 * the construction of the object. When starting the wait, a timeout can be set to exit if the
11 * signal has not been sent
12 */
13 class SCIQLOP_CORE_EXPORT SignalWaiter : public QObject {
14 Q_OBJECT
15 public:
16 /**
17 * Ctor
18 * @param object the sender of the signal
19 * @param signal the signal to listen
20 */
21 explicit SignalWaiter(QObject &sender, const char *signal);
22
23 /**
24 * Starts the signal and leaves after the signal has been received, or after the timeout
25 * @param timeout the timeout set (if 0, uses a default timeout)
26 * @return true if the signal was sent, false if the timeout occured
27 */
28 bool wait(int timeout);
29
30 private:
31 bool m_Timeout;
32 QEventLoop m_EventLoop;
33
34 private slots:
35 void timeout();
36 };
37
38 #endif // SCIQLOP_SIGNALWAITER_H
@@ -0,0 +1,36
1 #include "Common/SignalWaiter.h"
2
3 #include <QTimer>
4
5 namespace {
6
7 const auto DEFAULT_TIMEOUT = 30000;
8
9 } // namespace
10
11 SignalWaiter::SignalWaiter(QObject &sender, const char *signal) : m_Timeout{false}
12 {
13 connect(&sender, signal, &m_EventLoop, SLOT(quit()));
14 }
15
16 bool SignalWaiter::wait(int timeout)
17 {
18 if (timeout == 0) {
19 timeout = DEFAULT_TIMEOUT;
20 }
21
22 QTimer timer{};
23 timer.setInterval(timeout);
24 timer.start();
25 connect(&timer, &QTimer::timeout, this, &SignalWaiter::timeout);
26
27 m_EventLoop.exec();
28
29 return !m_Timeout;
30 }
31
32 void SignalWaiter::timeout()
33 {
34 m_Timeout = true;
35 m_EventLoop.quit();
36 }
@@ -1,73 +1,75
1
1
2 qxorm_dep = dependency('QxOrm', required : true, fallback:['QxOrm','qxorm_dep'])
2 qxorm_dep = dependency('QxOrm', required : true, fallback:['QxOrm','qxorm_dep'])
3 catalogueapi_dep = dependency('CatalogueAPI', required : true, fallback:['CatalogueAPI','CatalogueAPI_dep'])
3 catalogueapi_dep = dependency('CatalogueAPI', required : true, fallback:['CatalogueAPI','CatalogueAPI_dep'])
4
4
5
5
6 core_moc_headers = [
6 core_moc_headers = [
7 'include/Catalogue/CatalogueController.h',
7 'include/Catalogue/CatalogueController.h',
8 'include/Common/SignalWaiter.h',
8 'include/Data/IDataProvider.h',
9 'include/Data/IDataProvider.h',
9 'include/DataSource/DataSourceController.h',
10 'include/DataSource/DataSourceController.h',
10 'include/DataSource/DataSourceItemAction.h',
11 'include/DataSource/DataSourceItemAction.h',
11 'include/Network/NetworkController.h',
12 'include/Network/NetworkController.h',
12 'include/Time/TimeController.h',
13 'include/Time/TimeController.h',
13 'include/Variable/Variable.h',
14 'include/Variable/Variable.h',
14 'include/Variable/VariableCacheController.h',
15 'include/Variable/VariableCacheController.h',
15 'include/Variable/VariableController.h',
16 'include/Variable/VariableController.h',
16 'include/Variable/VariableAcquisitionWorker.h',
17 'include/Variable/VariableAcquisitionWorker.h',
17 'include/Variable/VariableSynchronizationGroup.h',
18 'include/Variable/VariableSynchronizationGroup.h',
18 'include/Variable/VariableModel.h',
19 'include/Variable/VariableModel.h',
19 'include/Visualization/VisualizationController.h'
20 'include/Visualization/VisualizationController.h'
20 ]
21 ]
21
22
22
23
23 core_moc_files = qt5.preprocess(moc_headers : core_moc_headers)
24 core_moc_files = qt5.preprocess(moc_headers : core_moc_headers)
24
25
25 core_sources = [
26 core_sources = [
26 'src/Common/DateUtils.cpp',
27 'src/Common/DateUtils.cpp',
28 'src/Common/SignalWaiter.cpp',
27 'src/Common/StringUtils.cpp',
29 'src/Common/StringUtils.cpp',
28 'src/Common/MimeTypesDef.cpp',
30 'src/Common/MimeTypesDef.cpp',
29 'src/Catalogue/CatalogueController.cpp',
31 'src/Catalogue/CatalogueController.cpp',
30 'src/Data/ScalarSeries.cpp',
32 'src/Data/ScalarSeries.cpp',
31 'src/Data/SpectrogramSeries.cpp',
33 'src/Data/SpectrogramSeries.cpp',
32 'src/Data/DataSeriesIterator.cpp',
34 'src/Data/DataSeriesIterator.cpp',
33 'src/Data/ArrayDataIterator.cpp',
35 'src/Data/ArrayDataIterator.cpp',
34 'src/Data/VectorSeries.cpp',
36 'src/Data/VectorSeries.cpp',
35 'src/Data/OptionalAxis.cpp',
37 'src/Data/OptionalAxis.cpp',
36 'src/Data/DataSeriesUtils.cpp',
38 'src/Data/DataSeriesUtils.cpp',
37 'src/DataSource/DataSourceController.cpp',
39 'src/DataSource/DataSourceController.cpp',
38 'src/DataSource/DataSourceItem.cpp',
40 'src/DataSource/DataSourceItem.cpp',
39 'src/DataSource/DataSourceItemAction.cpp',
41 'src/DataSource/DataSourceItemAction.cpp',
40 'src/DataSource/DataSourceItemMergeHelper.cpp',
42 'src/DataSource/DataSourceItemMergeHelper.cpp',
41 'src/Network/NetworkController.cpp',
43 'src/Network/NetworkController.cpp',
42 'src/Plugin/PluginManager.cpp',
44 'src/Plugin/PluginManager.cpp',
43 'src/Settings/SqpSettingsDefs.cpp',
45 'src/Settings/SqpSettingsDefs.cpp',
44 'src/Time/TimeController.cpp',
46 'src/Time/TimeController.cpp',
45 'src/Variable/Variable.cpp',
47 'src/Variable/Variable.cpp',
46 'src/Variable/VariableCacheController.cpp',
48 'src/Variable/VariableCacheController.cpp',
47 'src/Variable/VariableController.cpp',
49 'src/Variable/VariableController.cpp',
48 'src/Variable/VariableAcquisitionWorker.cpp',
50 'src/Variable/VariableAcquisitionWorker.cpp',
49 'src/Variable/VariableSynchronizationGroup.cpp',
51 'src/Variable/VariableSynchronizationGroup.cpp',
50 'src/Variable/VariableModel.cpp',
52 'src/Variable/VariableModel.cpp',
51 'src/Visualization/VisualizationController.cpp'
53 'src/Visualization/VisualizationController.cpp'
52 ]
54 ]
53
55
54 core_inc = include_directories(['include', '../plugin/include'])
56 core_inc = include_directories(['include', '../plugin/include'])
55
57
56 sciqlop_core_lib = library('sciqlopcore',
58 sciqlop_core_lib = library('sciqlopcore',
57 core_sources,
59 core_sources,
58 core_moc_files,
60 core_moc_files,
59 cpp_args : '-DCORE_LIB',
61 cpp_args : '-DCORE_LIB',
60 include_directories : core_inc,
62 include_directories : core_inc,
61 dependencies : [qt5core, qt5network, catalogueapi_dep],
63 dependencies : [qt5core, qt5network, catalogueapi_dep],
62 install : true
64 install : true
63 )
65 )
64
66
65
67
66 sciqlop_core = declare_dependency(link_with : sciqlop_core_lib,
68 sciqlop_core = declare_dependency(link_with : sciqlop_core_lib,
67 include_directories : core_inc,
69 include_directories : core_inc,
68 dependencies : [qt5core, qt5network, catalogueapi_dep])
70 dependencies : [qt5core, qt5network, catalogueapi_dep])
69
71
70
72
71
73
72 subdir('tests')
74 subdir('tests')
73
75
@@ -1,368 +1,369
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 <Common/SignalWaiter.h>
8 #include <Network/NetworkController.h>
9 #include <Network/NetworkController.h>
9 #include <Settings/SqpSettingsDefs.h>
10 #include <Settings/SqpSettingsDefs.h>
10 #include <SqpApplication.h>
11 #include <SqpApplication.h>
11 #include <Time/TimeController.h>
12 #include <Time/TimeController.h>
12 #include <Variable/Variable.h>
13 #include <Variable/Variable.h>
13 #include <Variable/VariableController.h>
14 #include <Variable/VariableController.h>
14
15
15 #include <QLoggingCategory>
16 #include <QLoggingCategory>
16 #include <QObject>
17 #include <QObject>
17 #include <QtTest>
18 #include <QtTest>
18
19
19 #include <memory>
20 #include <memory>
20
21
21 Q_LOGGING_CATEGORY(LOG_TestAmdaFuzzing, "TestAmdaFuzzing")
22 Q_LOGGING_CATEGORY(LOG_TestAmdaFuzzing, "TestAmdaFuzzing")
22
23
23 /**
24 /**
24 * Macro used to generate a getter for a property in @sa FuzzingTest. The macro generates a static
25 * Macro used to generate a getter for a property in @sa FuzzingTest. The macro generates a static
25 * attribute that is initialized by searching in properties the property and use a default value if
26 * attribute that is initialized by searching in properties the property and use a default value if
26 * it's not present. Macro arguments are:
27 * it's not present. Macro arguments are:
27 * - GETTER_NAME : name of the getter
28 * - GETTER_NAME : name of the getter
28 * - PROPERTY_NAME: used to generate constants for property's name ({PROPERTY_NAME}_PROPERTY) and
29 * - PROPERTY_NAME: used to generate constants for property's name ({PROPERTY_NAME}_PROPERTY) and
29 * default value ({PROPERTY_NAME}_DEFAULT_VALUE)
30 * default value ({PROPERTY_NAME}_DEFAULT_VALUE)
30 * - TYPE : return type of the getter
31 * - TYPE : return type of the getter
31 */
32 */
32 // clang-format off
33 // clang-format off
33 #define DECLARE_PROPERTY_GETTER(GETTER_NAME, PROPERTY_NAME, TYPE) \
34 #define DECLARE_PROPERTY_GETTER(GETTER_NAME, PROPERTY_NAME, TYPE) \
34 TYPE GETTER_NAME() const \
35 TYPE GETTER_NAME() const \
35 { \
36 { \
36 static auto result = m_Properties.value(PROPERTY_NAME##_PROPERTY, PROPERTY_NAME##_DEFAULT_VALUE).value<TYPE>(); \
37 static auto result = m_Properties.value(PROPERTY_NAME##_PROPERTY, PROPERTY_NAME##_DEFAULT_VALUE).value<TYPE>(); \
37 return result; \
38 return result; \
38 } \
39 } \
39 // clang-format on
40 // clang-format on
40
41
41 namespace {
42 namespace {
42
43
43 // /////// //
44 // /////// //
44 // Aliases //
45 // Aliases //
45 // /////// //
46 // /////// //
46
47
47 using IntPair = std::pair<int, int>;
48 using IntPair = std::pair<int, int>;
48 using Weight = double;
49 using Weight = double;
49 using Weights = std::vector<Weight>;
50 using Weights = std::vector<Weight>;
50
51
51 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
52 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
52 using VariablesOperations = std::vector<VariableOperation>;
53 using VariablesOperations = std::vector<VariableOperation>;
53
54
54 using WeightedOperationsPool = std::map<std::shared_ptr<IFuzzingOperation>, Weight>;
55 using WeightedOperationsPool = std::map<std::shared_ptr<IFuzzingOperation>, Weight>;
55 using Validators = std::vector<std::shared_ptr<IFuzzingValidator> >;
56 using Validators = std::vector<std::shared_ptr<IFuzzingValidator> >;
56
57
57 // ///////// //
58 // ///////// //
58 // Constants //
59 // Constants //
59 // ///////// //
60 // ///////// //
60
61
61 // Defaults values used when the associated properties have not been set for the test
62 // Defaults values used when the associated properties have not been set for the test
62 const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
63 const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
63 const auto NB_MAX_SYNC_GROUPS_DEFAULT_VALUE = 1;
64 const auto NB_MAX_SYNC_GROUPS_DEFAULT_VALUE = 1;
64 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
65 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
65 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE = QVariant::fromValue(WeightedOperationsTypes{
66 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE = QVariant::fromValue(WeightedOperationsTypes{
66 {FuzzingOperationType::CREATE, 1.},
67 {FuzzingOperationType::CREATE, 1.},
67 {FuzzingOperationType::DELETE, 0.1}, // Delete operation is less frequent
68 {FuzzingOperationType::DELETE, 0.1}, // Delete operation is less frequent
68 {FuzzingOperationType::PAN_LEFT, 1.},
69 {FuzzingOperationType::PAN_LEFT, 1.},
69 {FuzzingOperationType::PAN_RIGHT, 1.},
70 {FuzzingOperationType::PAN_RIGHT, 1.},
70 {FuzzingOperationType::ZOOM_IN, 1.},
71 {FuzzingOperationType::ZOOM_IN, 1.},
71 {FuzzingOperationType::ZOOM_OUT, 1.},
72 {FuzzingOperationType::ZOOM_OUT, 1.},
72 {FuzzingOperationType::SYNCHRONIZE, 0.8},
73 {FuzzingOperationType::SYNCHRONIZE, 0.8},
73 {FuzzingOperationType::DESYNCHRONIZE, 0.4}});
74 {FuzzingOperationType::DESYNCHRONIZE, 0.4}});
74 const auto CACHE_TOLERANCE_DEFAULT_VALUE = 0.2;
75 const auto CACHE_TOLERANCE_DEFAULT_VALUE = 0.2;
75
76
76 /// Min/max delays between each operation (in ms)
77 /// Min/max delays between each operation (in ms)
77 const auto OPERATION_DELAY_BOUNDS_DEFAULT_VALUE = QVariant::fromValue(std::make_pair(100, 3000));
78 const auto OPERATION_DELAY_BOUNDS_DEFAULT_VALUE = QVariant::fromValue(std::make_pair(100, 3000));
78
79
79 /// Validators for the tests (executed in the order in which they're defined)
80 /// Validators for the tests (executed in the order in which they're defined)
80 const auto VALIDATORS_DEFAULT_VALUE = QVariant::fromValue(
81 const auto VALIDATORS_DEFAULT_VALUE = QVariant::fromValue(
81 ValidatorsTypes{{FuzzingValidatorType::RANGE, FuzzingValidatorType::DATA}});
82 ValidatorsTypes{{FuzzingValidatorType::RANGE, FuzzingValidatorType::DATA}});
82
83
83 /// Min/max number of operations to execute before calling validation
84 /// Min/max number of operations to execute before calling validation
84 const auto VALIDATION_FREQUENCY_BOUNDS_DEFAULT_VALUE = QVariant::fromValue(std::make_pair(1, 10));
85 const auto VALIDATION_FREQUENCY_BOUNDS_DEFAULT_VALUE = QVariant::fromValue(std::make_pair(1, 10));
85
86
86 // /////// //
87 // /////// //
87 // Methods //
88 // Methods //
88 // /////// //
89 // /////// //
89
90
90 /// Goes through the variables pool and operations pool to determine the set of {variable/operation}
91 /// Goes through the variables pool and operations pool to determine the set of {variable/operation}
91 /// pairs that are valid (i.e. operation that can be executed on variable)
92 /// pairs that are valid (i.e. operation that can be executed on variable)
92 std::pair<VariablesOperations, Weights>
93 std::pair<VariablesOperations, Weights>
93 availableOperations(const FuzzingState &fuzzingState, const WeightedOperationsPool &operationsPool)
94 availableOperations(const FuzzingState &fuzzingState, const WeightedOperationsPool &operationsPool)
94 {
95 {
95 VariablesOperations result{};
96 VariablesOperations result{};
96 Weights weights{};
97 Weights weights{};
97
98
98 for (const auto &variablesPoolEntry : fuzzingState.m_VariablesPool) {
99 for (const auto &variablesPoolEntry : fuzzingState.m_VariablesPool) {
99 auto variableId = variablesPoolEntry.first;
100 auto variableId = variablesPoolEntry.first;
100
101
101 for (const auto &operationsPoolEntry : operationsPool) {
102 for (const auto &operationsPoolEntry : operationsPool) {
102 auto operation = operationsPoolEntry.first;
103 auto operation = operationsPoolEntry.first;
103 auto weight = operationsPoolEntry.second;
104 auto weight = operationsPoolEntry.second;
104
105
105 // A pair is valid if the current operation can be executed on the current variable
106 // A pair is valid if the current operation can be executed on the current variable
106 if (operation->canExecute(variableId, fuzzingState)) {
107 if (operation->canExecute(variableId, fuzzingState)) {
107 result.push_back({variableId, operation});
108 result.push_back({variableId, operation});
108 weights.push_back(weight);
109 weights.push_back(weight);
109 }
110 }
110 }
111 }
111 }
112 }
112
113
113 return {result, weights};
114 return {result, weights};
114 }
115 }
115
116
116 WeightedOperationsPool createOperationsPool(const WeightedOperationsTypes &types)
117 WeightedOperationsPool createOperationsPool(const WeightedOperationsTypes &types)
117 {
118 {
118 WeightedOperationsPool result{};
119 WeightedOperationsPool result{};
119
120
120 std::transform(
121 std::transform(
121 types.cbegin(), types.cend(), std::inserter(result, result.end()), [](const auto &type) {
122 types.cbegin(), types.cend(), std::inserter(result, result.end()), [](const auto &type) {
122 return std::make_pair(FuzzingOperationFactory::create(type.first), type.second);
123 return std::make_pair(FuzzingOperationFactory::create(type.first), type.second);
123 });
124 });
124
125
125 return result;
126 return result;
126 }
127 }
127
128
128 Validators createValidators(const ValidatorsTypes &types)
129 Validators createValidators(const ValidatorsTypes &types)
129 {
130 {
130 Validators result{};
131 Validators result{};
131
132
132 std::transform(types.cbegin(), types.cend(), std::inserter(result, result.end()),
133 std::transform(types.cbegin(), types.cend(), std::inserter(result, result.end()),
133 [](const auto &type) { return FuzzingValidatorFactory::create(type); });
134 [](const auto &type) { return FuzzingValidatorFactory::create(type); });
134
135
135 return result;
136 return result;
136 }
137 }
137
138
138 /**
139 /**
139 * Validates all the variables' states passed in parameter, according to a set of validators
140 * Validates all the variables' states passed in parameter, according to a set of validators
140 * @param variablesPool the variables' states
141 * @param variablesPool the variables' states
141 * @param validators the validators used for validation
142 * @param validators the validators used for validation
142 */
143 */
143 void validate(const VariablesPool &variablesPool, const Validators &validators)
144 void validate(const VariablesPool &variablesPool, const Validators &validators)
144 {
145 {
145 for (const auto &variablesPoolEntry : variablesPool) {
146 for (const auto &variablesPoolEntry : variablesPool) {
146 auto variableId = variablesPoolEntry.first;
147 auto variableId = variablesPoolEntry.first;
147 const auto &variableState = variablesPoolEntry.second;
148 const auto &variableState = variablesPoolEntry.second;
148
149
149 auto variableMessage = variableState.m_Variable ? variableState.m_Variable->name()
150 auto variableMessage = variableState.m_Variable ? variableState.m_Variable->name()
150 : QStringLiteral("null variable");
151 : QStringLiteral("null variable");
151 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validating state of variable at index"
152 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validating state of variable at index"
152 << variableId << "(" << variableMessage << ")...";
153 << variableId << "(" << variableMessage << ")...";
153
154
154 for (const auto &validator : validators) {
155 for (const auto &validator : validators) {
155 validator->validate(VariableState{variableState});
156 validator->validate(VariableState{variableState});
156 }
157 }
157
158
158 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validation completed.";
159 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validation completed.";
159 }
160 }
160 }
161 }
161
162
162 /**
163 /**
163 * Class to run random tests
164 * Class to run random tests
164 */
165 */
165 class FuzzingTest {
166 class FuzzingTest {
166 public:
167 public:
167 explicit FuzzingTest(VariableController &variableController, Properties properties)
168 explicit FuzzingTest(VariableController &variableController, Properties properties)
168 : m_VariableController{variableController},
169 : m_VariableController{variableController},
169 m_Properties{std::move(properties)},
170 m_Properties{std::move(properties)},
170 m_FuzzingState{}
171 m_FuzzingState{}
171 {
172 {
172 // Inits variables pool: at init, all variables are null
173 // Inits variables pool: at init, all variables are null
173 for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
174 for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
174 m_FuzzingState.m_VariablesPool[variableId] = VariableState{};
175 m_FuzzingState.m_VariablesPool[variableId] = VariableState{};
175 }
176 }
176
177
177 // Inits sync groups and registers them into the variable controller
178 // Inits sync groups and registers them into the variable controller
178 for (auto i = 0; i < nbMaxSyncGroups(); ++i) {
179 for (auto i = 0; i < nbMaxSyncGroups(); ++i) {
179 auto syncGroupId = SyncGroupId::createUuid();
180 auto syncGroupId = SyncGroupId::createUuid();
180 variableController.onAddSynchronizationGroupId(syncGroupId);
181 variableController.onAddSynchronizationGroupId(syncGroupId);
181 m_FuzzingState.m_SyncGroupsPool[syncGroupId] = SyncGroup{};
182 m_FuzzingState.m_SyncGroupsPool[syncGroupId] = SyncGroup{};
182 }
183 }
183 }
184 }
184
185
185 void execute()
186 void execute()
186 {
187 {
187 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Running" << nbMaxOperations() << "operations on"
188 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Running" << nbMaxOperations() << "operations on"
188 << nbMaxVariables() << "variable(s)...";
189 << nbMaxVariables() << "variable(s)...";
189
190
190
191
191 // Inits the count of the number of operations before the next validation
192 // Inits the count of the number of operations before the next validation
192 int nextValidationCounter = 0;
193 int nextValidationCounter = 0;
193 auto updateValidationCounter = [this, &nextValidationCounter]() {
194 auto updateValidationCounter = [this, &nextValidationCounter]() {
194 nextValidationCounter = RandomGenerator::instance().generateInt(
195 nextValidationCounter = RandomGenerator::instance().generateInt(
195 validationFrequencies().first, validationFrequencies().second);
196 validationFrequencies().first, validationFrequencies().second);
196 qCInfo(LOG_TestAmdaFuzzing()).noquote()
197 qCInfo(LOG_TestAmdaFuzzing()).noquote()
197 << "Next validation in " << nextValidationCounter << "operations...";
198 << "Next validation in " << nextValidationCounter << "operations...";
198 };
199 };
199 updateValidationCounter();
200 updateValidationCounter();
200
201
201 auto canExecute = true;
202 auto canExecute = true;
202 for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
203 for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
203 // Retrieves all operations that can be executed in the current context
204 // Retrieves all operations that can be executed in the current context
204 VariablesOperations variableOperations{};
205 VariablesOperations variableOperations{};
205 Weights weights{};
206 Weights weights{};
206 std::tie(variableOperations, weights)
207 std::tie(variableOperations, weights)
207 = availableOperations(m_FuzzingState, operationsPool());
208 = availableOperations(m_FuzzingState, operationsPool());
208
209
209 canExecute = !variableOperations.empty();
210 canExecute = !variableOperations.empty();
210 if (canExecute) {
211 if (canExecute) {
211 --nextValidationCounter;
212 --nextValidationCounter;
212
213
213 // Of the operations available, chooses a random operation and executes it
214 // Of the operations available, chooses a random operation and executes it
214 auto variableOperation
215 auto variableOperation
215 = RandomGenerator::instance().randomChoice(variableOperations, weights);
216 = RandomGenerator::instance().randomChoice(variableOperations, weights);
216
217
217 auto variableId = variableOperation.first;
218 auto variableId = variableOperation.first;
218 auto fuzzingOperation = variableOperation.second;
219 auto fuzzingOperation = variableOperation.second;
219
220
220 fuzzingOperation->execute(variableId, m_FuzzingState, m_VariableController,
221 fuzzingOperation->execute(variableId, m_FuzzingState, m_VariableController,
221 m_Properties);
222 m_Properties);
222
223
223 // Delays the next operation with a randomly generated time
224 // Delays the next operation with a randomly generated time
224 auto delay = RandomGenerator::instance().generateInt(operationDelays().first,
225 auto delay = RandomGenerator::instance().generateInt(operationDelays().first,
225 operationDelays().second);
226 operationDelays().second);
226 qCDebug(LOG_TestAmdaFuzzing())
227 qCDebug(LOG_TestAmdaFuzzing())
227 << "Waiting " << delay << "ms before the next operation...";
228 << "Waiting " << delay << "ms before the next operation...";
228 QTest::qWait(delay);
229 QTest::qWait(delay);
229
230
230 // Validates variables
231 // Validates variables
231 if (nextValidationCounter == 0) {
232 if (nextValidationCounter == 0) {
232 validate(m_FuzzingState.m_VariablesPool, validators());
233 validate(m_FuzzingState.m_VariablesPool, validators());
233 updateValidationCounter();
234 updateValidationCounter();
234 }
235 }
235 }
236 }
236 else {
237 else {
237 qCInfo(LOG_TestAmdaFuzzing()).noquote()
238 qCInfo(LOG_TestAmdaFuzzing()).noquote()
238 << "No more operations are available, the execution of the test will stop...";
239 << "No more operations are available, the execution of the test will stop...";
239 }
240 }
240 }
241 }
241
242
242 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Execution of the test completed.";
243 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Execution of the test completed.";
243 }
244 }
244
245
245 private:
246 private:
246
247
247 WeightedOperationsPool operationsPool() const
248 WeightedOperationsPool operationsPool() const
248 {
249 {
249 static auto result = createOperationsPool(
250 static auto result = createOperationsPool(
250 m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
251 m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
251 .value<WeightedOperationsTypes>());
252 .value<WeightedOperationsTypes>());
252 return result;
253 return result;
253 }
254 }
254
255
255 Validators validators() const
256 Validators validators() const
256 {
257 {
257 static auto result
258 static auto result
258 = createValidators(m_Properties.value(VALIDATORS_PROPERTY, VALIDATORS_DEFAULT_VALUE)
259 = createValidators(m_Properties.value(VALIDATORS_PROPERTY, VALIDATORS_DEFAULT_VALUE)
259 .value<ValidatorsTypes>());
260 .value<ValidatorsTypes>());
260 return result;
261 return result;
261 }
262 }
262
263
263 DECLARE_PROPERTY_GETTER(nbMaxOperations, NB_MAX_OPERATIONS, int)
264 DECLARE_PROPERTY_GETTER(nbMaxOperations, NB_MAX_OPERATIONS, int)
264 DECLARE_PROPERTY_GETTER(nbMaxSyncGroups, NB_MAX_SYNC_GROUPS, int)
265 DECLARE_PROPERTY_GETTER(nbMaxSyncGroups, NB_MAX_SYNC_GROUPS, int)
265 DECLARE_PROPERTY_GETTER(nbMaxVariables, NB_MAX_VARIABLES, int)
266 DECLARE_PROPERTY_GETTER(nbMaxVariables, NB_MAX_VARIABLES, int)
266 DECLARE_PROPERTY_GETTER(operationDelays, OPERATION_DELAY_BOUNDS, IntPair)
267 DECLARE_PROPERTY_GETTER(operationDelays, OPERATION_DELAY_BOUNDS, IntPair)
267 DECLARE_PROPERTY_GETTER(validationFrequencies, VALIDATION_FREQUENCY_BOUNDS, IntPair)
268 DECLARE_PROPERTY_GETTER(validationFrequencies, VALIDATION_FREQUENCY_BOUNDS, IntPair)
268 DECLARE_PROPERTY_GETTER(acquisitionTimeout, ACQUISITION_TIMEOUT, int)
269 DECLARE_PROPERTY_GETTER(acquisitionTimeout, ACQUISITION_TIMEOUT, int)
269
270
270 VariableController &m_VariableController;
271 VariableController &m_VariableController;
271 Properties m_Properties;
272 Properties m_Properties;
272 FuzzingState m_FuzzingState;
273 FuzzingState m_FuzzingState;
273 };
274 };
274
275
275 } // namespace
276 } // namespace
276
277
277 class TestAmdaFuzzing : public QObject {
278 class TestAmdaFuzzing : public QObject {
278 Q_OBJECT
279 Q_OBJECT
279
280
280 private slots:
281 private slots:
281 /// Input data for @sa testFuzzing()
282 /// Input data for @sa testFuzzing()
282 void testFuzzing_data();
283 void testFuzzing_data();
283 void testFuzzing();
284 void testFuzzing();
284 };
285 };
285
286
286 void TestAmdaFuzzing::testFuzzing_data()
287 void TestAmdaFuzzing::testFuzzing_data()
287 {
288 {
288 // ////////////// //
289 // ////////////// //
289 // Test structure //
290 // Test structure //
290 // ////////////// //
291 // ////////////// //
291
292
292 QTest::addColumn<Properties>("properties"); // Properties for random test
293 QTest::addColumn<Properties>("properties"); // Properties for random test
293
294
294 // ////////// //
295 // ////////// //
295 // Test cases //
296 // Test cases //
296 // ////////// //
297 // ////////// //
297
298
298 auto maxRange = SqpRange::fromDateTime({2017, 1, 1}, {0, 0}, {2017, 1, 5}, {0, 0});
299 auto maxRange = SqpRange::fromDateTime({2017, 1, 1}, {0, 0}, {2017, 1, 5}, {0, 0});
299 MetadataPool metadataPool{{{"dataType", "vector"}, {"xml:id", "imf"}}};
300 MetadataPool metadataPool{{{"dataType", "vector"}, {"xml:id", "imf"}}};
300
301
301 // Note: we don't use auto here as we want to pass std::shared_ptr<IDataProvider> as is in the
302 // Note: we don't use auto here as we want to pass std::shared_ptr<IDataProvider> as is in the
302 // QVariant
303 // QVariant
303 std::shared_ptr<IDataProvider> provider = std::make_shared<AmdaProvider>();
304 std::shared_ptr<IDataProvider> provider = std::make_shared<AmdaProvider>();
304
305
305 QTest::newRow("fuzzingTest") << Properties{
306 QTest::newRow("fuzzingTest") << Properties{
306 {MAX_RANGE_PROPERTY, QVariant::fromValue(maxRange)},
307 {MAX_RANGE_PROPERTY, QVariant::fromValue(maxRange)},
307 {METADATA_POOL_PROPERTY, QVariant::fromValue(metadataPool)},
308 {METADATA_POOL_PROPERTY, QVariant::fromValue(metadataPool)},
308 {PROVIDER_PROPERTY, QVariant::fromValue(provider)}};
309 {PROVIDER_PROPERTY, QVariant::fromValue(provider)}};
309 }
310 }
310
311
311 void TestAmdaFuzzing::testFuzzing()
312 void TestAmdaFuzzing::testFuzzing()
312 {
313 {
313 QFETCH(Properties, properties);
314 QFETCH(Properties, properties);
314
315
315 // Sets cache property
316 // Sets cache property
316 QSettings settings{};
317 QSettings settings{};
317 auto cacheTolerance = properties.value(CACHE_TOLERANCE_PROPERTY, CACHE_TOLERANCE_DEFAULT_VALUE);
318 auto cacheTolerance = properties.value(CACHE_TOLERANCE_PROPERTY, CACHE_TOLERANCE_DEFAULT_VALUE);
318 settings.setValue(GENERAL_TOLERANCE_AT_INIT_KEY, cacheTolerance);
319 settings.setValue(GENERAL_TOLERANCE_AT_INIT_KEY, cacheTolerance);
319 settings.setValue(GENERAL_TOLERANCE_AT_UPDATE_KEY, cacheTolerance);
320 settings.setValue(GENERAL_TOLERANCE_AT_UPDATE_KEY, cacheTolerance);
320
321
321 auto &variableController = sqpApp->variableController();
322 auto &variableController = sqpApp->variableController();
322 auto &timeController = sqpApp->timeController();
323 auto &timeController = sqpApp->timeController();
323
324
324 // Generates random initial range (bounded to max range)
325 // Generates random initial range (bounded to max range)
325 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
326 auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
326 .value<SqpRange>();
327 .value<SqpRange>();
327
328
328 QVERIFY(maxRange != INVALID_RANGE);
329 QVERIFY(maxRange != INVALID_RANGE);
329
330
330 auto initialRangeStart
331 auto initialRangeStart
331 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
332 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
332 auto initialRangeEnd
333 auto initialRangeEnd
333 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
334 = RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
334 if (initialRangeStart > initialRangeEnd) {
335 if (initialRangeStart > initialRangeEnd) {
335 std::swap(initialRangeStart, initialRangeEnd);
336 std::swap(initialRangeStart, initialRangeEnd);
336 }
337 }
337
338
338 // Sets initial range on time controller
339 // Sets initial range on time controller
339 SqpRange initialRange{initialRangeStart, initialRangeEnd};
340 SqpRange initialRange{initialRangeStart, initialRangeEnd};
340 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Setting initial range to" << initialRange << "...";
341 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Setting initial range to" << initialRange << "...";
341 timeController.onTimeToUpdate(initialRange);
342 timeController.onTimeToUpdate(initialRange);
342 properties.insert(INITIAL_RANGE_PROPERTY, QVariant::fromValue(initialRange));
343 properties.insert(INITIAL_RANGE_PROPERTY, QVariant::fromValue(initialRange));
343
344
344 FuzzingTest test{variableController, properties};
345 FuzzingTest test{variableController, properties};
345 test.execute();
346 test.execute();
346 }
347 }
347
348
348 int main(int argc, char *argv[])
349 int main(int argc, char *argv[])
349 {
350 {
350 QLoggingCategory::setFilterRules(
351 QLoggingCategory::setFilterRules(
351 "*.warning=false\n"
352 "*.warning=false\n"
352 "*.info=false\n"
353 "*.info=false\n"
353 "*.debug=false\n"
354 "*.debug=false\n"
354 "FuzzingOperations.info=true\n"
355 "FuzzingOperations.info=true\n"
355 "FuzzingValidators.info=true\n"
356 "FuzzingValidators.info=true\n"
356 "TestAmdaFuzzing.info=true\n");
357 "TestAmdaFuzzing.info=true\n");
357
358
358 SqpApplication app{argc, argv};
359 SqpApplication app{argc, argv};
359 SqpApplication::setOrganizationName("LPP");
360 SqpApplication::setOrganizationName("LPP");
360 SqpApplication::setOrganizationDomain("lpp.fr");
361 SqpApplication::setOrganizationDomain("lpp.fr");
361 SqpApplication::setApplicationName("SciQLop-TestFuzzing");
362 SqpApplication::setApplicationName("SciQLop-TestFuzzing");
362 app.setAttribute(Qt::AA_Use96Dpi, true);
363 app.setAttribute(Qt::AA_Use96Dpi, true);
363 TestAmdaFuzzing testObject{};
364 TestAmdaFuzzing testObject{};
364 QTEST_SET_MAIN_SOURCE_PATH
365 QTEST_SET_MAIN_SOURCE_PATH
365 return QTest::qExec(&testObject, argc, argv);
366 return QTest::qExec(&testObject, argc, argv);
366 }
367 }
367
368
368 #include "TestAmdaFuzzing.moc"
369 #include "TestAmdaFuzzing.moc"
General Comments 0
You need to be logged in to leave comments. Login now