##// END OF EJS Templates
Adds utility class to get random values
Alexandre Leroux -
r1175:9f9ab053f00b
parent child
Show More
@@ -0,0 +1,25
1 #include "FuzzingUtils.h"
2
3 RandomGenerator &RandomGenerator::instance()
4 {
5 static auto instance = RandomGenerator();
6 return instance;
7 }
8
9 double RandomGenerator::generateDouble(double min, double max)
10 {
11 std::uniform_real_distribution<double> dist{min, max};
12 return dist(m_Mt);
13 }
14
15 int RandomGenerator::generateInt(int min, int max)
16 {
17 std::uniform_int_distribution<int> dist{min, max};
18 return dist(m_Mt);
19 }
20
21 RandomGenerator::RandomGenerator()
22 {
23 std::random_device rd{};
24 m_Mt = std::mt19937{rd()};
25 }
@@ -0,0 +1,41
1 #ifndef SCIQLOP_FUZZINGUTILS_H
2 #define SCIQLOP_FUZZINGUTILS_H
3
4 #include <random>
5
6 /**
7 * Class that proposes random utility methods
8 */
9 class RandomGenerator {
10 public:
11 /// @return the unique instance of the random generator
12 static RandomGenerator &instance();
13
14 /// Generates a random double between [min, max]
15 double generateDouble(double min, double max);
16 /// Generates a random int between [min, max]
17 int generateInt(int min, int max);
18
19 /// Returns a random element among the elements of a container. If the container is empty, returns an element built by default
20 template <typename T, typename ValueType = typename T::value_type>
21 ValueType randomChoice(const T& container);
22
23 private:
24 std::mt19937 m_Mt;
25
26 explicit RandomGenerator();
27 };
28
29 template<typename T, typename ValueType>
30 ValueType RandomGenerator::randomChoice(const T &container)
31 {
32 if(container.empty()){
33 return ValueType{};
34 }
35
36 auto randomIndex = generateInt(0, container.size() - 1);
37 return container.at(randomIndex);
38 }
39
40 #endif // SCIQLOP_FUZZINGUTILS
41
@@ -1,85 +1,87
1 1
2 2 amdaplugin_moc_headers = [
3 3 'include/AmdaPlugin.h',
4 4 'include/AmdaProvider.h'
5 5 ]
6 6
7 7 amdaplugin_sources = [
8 8 'src/AmdaDefs.cpp',
9 9 'src/AmdaParser.cpp',
10 10 'src/AmdaPlugin.cpp',
11 11 'src/AmdaProvider.cpp',
12 12 'src/AmdaResultParser.cpp',
13 13 'src/AmdaResultParserDefs.cpp',
14 14 'src/AmdaResultParserHelper.cpp',
15 15 'src/AmdaServer.cpp'
16 16 ]
17 17
18 18 amdaplugin_ui_files = []
19 19 amdaplugin_resources_files = [
20 20 'resources/amdaresources.qrc'
21 21 ]
22 22
23 23 amdaplugin_inc = include_directories(['include', '../../plugin/include'])
24 24
25 25 moc_gen = generator(moc,
26 26 output : 'moc_@BASENAME@.cpp',
27 27 arguments : ['@INPUT@',
28 28 '-DSCIQLOP_PLUGIN_JSON_FILE_PATH="'+meson.source_root()+'/plugins/amda/resources/amda.json"',
29 29 '-I', meson.current_source_dir()+'/include',
30 30 '-I', meson.current_source_dir()+'/../../plugin/include',
31 31 '-o', '@OUTPUT@'])
32 32
33 33 rcc_gen = generator(rcc,
34 34 output : 'qrc_@BASENAME@.cpp',
35 35 arguments : ['--name=@BASENAME@"',
36 36 '--output',
37 37 '@OUTPUT@',
38 38 '@INPUT@'])
39 39
40 40 amdaplugin_moc_plugin_files = moc_gen.process(amdaplugin_moc_headers)
41 41
42 42 amdaplugin_rcc_plugin_files = rcc_gen.process(amdaplugin_resources_files)
43 43
44 44 #amdaplugin_rcc_plugin_files = qt5.preprocess(
45 45 # qresources : amdaplugin_resources_files)
46 46
47 47 amdaplugin_moc_files = qt5.preprocess(
48 48 ui_files : amdaplugin_ui_files)
49 49
50 50 sciqlop_amdaplugin = library('amdaplugin',
51 51 amdaplugin_sources,
52 52 amdaplugin_moc_files,
53 53 amdaplugin_rcc_plugin_files,
54 54 amdaplugin_moc_plugin_files,
55 55 cpp_args : ['-DAMDA_LIB','-DQT_PLUGIN'],
56 56 include_directories : [amdaplugin_inc],
57 57 dependencies : [sciqlop_core, sciqlop_gui],
58 58 install : true
59 59 )
60 60
61 61
62 62 tests = [
63 63 [['tests/TestAmdaParser.cpp'],'test_amda_parser','AMDA parser test'],
64 64 [['tests/TestAmdaResultParser.cpp'],'test_amda_result_parser','AMDA result parser test'],
65 65 [['tests/TestAmdaAcquisition.cpp'],'test_amda_acquisition','AMDA Acquisition test'],
66 66 [['tests/TestAmdaFuzzing.cpp'],'test_amda_fuzzing','AMDA fuzzing test']
67 67 ]
68 68
69 69 tests_sources = [
70 70 'tests/FuzzingDefs.h',
71 71 'tests/FuzzingDefs.cpp',
72 72 'tests/FuzzingOperations.h',
73 73 'tests/FuzzingOperations.cpp',
74 'tests/FuzzingUtils.h',
75 'tests/FuzzingUtils.cpp'
74 76 ]
75 77
76 78 foreach unit_test : tests
77 79 test_moc_files = qt5.preprocess(moc_sources : unit_test[0])
78 80 test_exe = executable(unit_test[1],unit_test[0] , test_moc_files,
79 81 link_with : [sciqlop_amdaplugin],
80 82 include_directories : [amdaplugin_inc],
81 83 cpp_args : ['-DAMDA_TESTS_RESOURCES_DIR="'+meson.current_source_dir()+'/tests-resources"'],
82 84 sources : [tests_sources],
83 85 dependencies : [sciqlop_core, sciqlop_gui, qt5test])
84 86 test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])], timeout: 3 * 60)
85 87 endforeach
@@ -1,207 +1,209
1 1 #include "FuzzingDefs.h"
2 2 #include "FuzzingOperations.h"
3 #include "FuzzingUtils.h"
4
3 5 #include <Network/NetworkController.h>
4 6 #include <SqpApplication.h>
5 7 #include <Time/TimeController.h>
6 8 #include <Variable/VariableController.h>
7 9
8 10 #include <QLoggingCategory>
9 11 #include <QObject>
10 12 #include <QtTest>
11 13
12 14 #include <memory>
13 15
14 16 Q_LOGGING_CATEGORY(LOG_TestAmdaFuzzing, "TestAmdaFuzzing")
15 17
16 18 namespace {
17 19
18 20 // /////// //
19 21 // Aliases //
20 22 // /////// //
21 23
22 24 using VariableId = int;
23 25
24 26 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
25 27 using VariablesOperations = std::vector<VariableOperation>;
26 28
27 29 using OperationsPool = std::set<std::shared_ptr<IFuzzingOperation> >;
28 30 using VariablesPool = std::map<VariableId, std::shared_ptr<Variable> >;
29 31
30 32 // ///////// //
31 33 // Constants //
32 34 // ///////// //
33 35
34 36 // Defaults values used when the associated properties have not been set for the test
35 37 const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
36 38 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
37 39 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE
38 40 = QVariant::fromValue(OperationsTypes{FuzzingOperationType::CREATE});
39 41 // /////// //
40 42 // Methods //
41 43 // /////// //
42 44
43 45 /// Goes through the variables pool and operations pool to determine the set of {variable/operation}
44 46 /// pairs that are valid (i.e. operation that can be executed on variable)
45 47 VariablesOperations availableOperations(const VariablesPool &variablesPool,
46 48 const OperationsPool &operationsPool)
47 49 {
48 50 VariablesOperations result{};
49 51
50 52 for (const auto &variablesPoolEntry : variablesPool) {
51 53 auto variableId = variablesPoolEntry.first;
52 54 auto variable = variablesPoolEntry.second;
53 55
54 56 for (const auto &operation : operationsPool) {
55 57 // A pair is valid if the current operation can be executed on the current variable
56 58 if (operation->canExecute(variable)) {
57 59 result.push_back({variableId, operation});
58 60 }
59 61 }
60 62 }
61 63
62 64 return result;
63 65 }
64 66
65 67 OperationsPool createOperationsPool(const OperationsTypes &types)
66 68 {
67 69 OperationsPool result{};
68 70
69 71 std::transform(types.cbegin(), types.cend(), std::inserter(result, result.end()),
70 72 [](const auto &type) { return FuzzingOperationFactory::create(type); });
71 73
72 74 return result;
73 75 }
74 76
75 77 /**
76 78 * Class to run random tests
77 79 */
78 80 class FuzzingTest {
79 81 public:
80 82 explicit FuzzingTest(VariableController &variableController, Properties properties)
81 83 : m_VariableController{variableController},
82 84 m_Properties{std::move(properties)},
83 85 m_VariablesPool{}
84 86 {
85 87 // Inits variables pool: at init, all variables are null
86 88 for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
87 89 m_VariablesPool[variableId] = nullptr;
88 90 }
89 91 }
90 92
91 93 void execute()
92 94 {
93 95 qCInfo(LOG_TestAmdaFuzzing()) << "Running" << nbMaxOperations() << "operations on"
94 96 << nbMaxVariables() << "variables...";
95 97
96 98 auto canExecute = true;
97 99 for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
98 100 // Retrieves all operations that can be executed in the current context
99 101 auto variableOperations = availableOperations(m_VariablesPool, operationsPool());
100 102
101 103 canExecute = !variableOperations.empty();
102 104 if (canExecute) {
103 105 // Of the operations available, chooses a random operation and executes it
104 106 auto variableOperation
105 = /* TODO: gets a random operation */;
107 = RandomGenerator::instance().randomChoice(variableOperations);
106 108
107 109 auto variableId = variableOperation.first;
108 110 auto variable = m_VariablesPool.at(variableId);
109 111 auto fuzzingOperation = variableOperation.second;
110 112
111 113 fuzzingOperation->execute(variable, m_VariableController, m_Properties);
112 114
113 115 // Updates variable pool with the new state of the variable after operation
114 116 m_VariablesPool[variableId] = variable;
115 117 }
116 118 else {
117 119 qCInfo(LOG_TestAmdaFuzzing())
118 120 << "No more operations are available, the execution of the test will stop...";
119 121 }
120 122 }
121 123
122 124 qCInfo(LOG_TestAmdaFuzzing()) << "Execution of the test completed.";
123 125 }
124 126
125 127 private:
126 128 int nbMaxOperations() const
127 129 {
128 130 static auto result
129 131 = m_Properties.value(NB_MAX_OPERATIONS_PROPERTY, NB_MAX_OPERATIONS_DEFAULT_VALUE)
130 132 .toInt();
131 133 return result;
132 134 }
133 135
134 136 int nbMaxVariables() const
135 137 {
136 138 static auto result
137 139 = m_Properties.value(NB_MAX_VARIABLES_PROPERTY, NB_MAX_VARIABLES_DEFAULT_VALUE).toInt();
138 140 return result;
139 141 }
140 142
141 143 OperationsPool operationsPool() const
142 144 {
143 145 static auto result = createOperationsPool(
144 146 m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
145 147 .value<OperationsTypes>());
146 148 return result;
147 149 }
148 150
149 151 VariableController &m_VariableController;
150 152 Properties m_Properties;
151 153 VariablesPool m_VariablesPool;
152 154 };
153 155
154 156 } // namespace
155 157
156 158 class TestAmdaFuzzing : public QObject {
157 159 Q_OBJECT
158 160
159 161 private slots:
160 162 /// Input data for @sa testFuzzing()
161 163 void testFuzzing_data();
162 164 void testFuzzing();
163 165 };
164 166
165 167 void TestAmdaFuzzing::testFuzzing_data()
166 168 {
167 169 // ////////////// //
168 170 // Test structure //
169 171 // ////////////// //
170 172
171 173 QTest::addColumn<Properties>("properties"); // Properties for random test
172 174
173 175 // ////////// //
174 176 // Test cases //
175 177 // ////////// //
176 178
177 179 ///@todo: complete
178 180 }
179 181
180 182 void TestAmdaFuzzing::testFuzzing()
181 183 {
182 184 QFETCH(Properties, properties);
183 185
184 186 auto &variableController = sqpApp->variableController();
185 187 auto &timeController = sqpApp->timeController();
186 188
187 189 FuzzingTest test{variableController, properties};
188 190 test.execute();
189 191 }
190 192
191 193 int main(int argc, char *argv[])
192 194 {
193 195 QLoggingCategory::setFilterRules(
194 196 "*.warning=false\n"
195 197 "*.info=false\n"
196 198 "*.debug=false\n"
197 199 "FuzzingOperations.info=true\n"
198 200 "TestAmdaFuzzing.info=true\n");
199 201
200 202 SqpApplication app{argc, argv};
201 203 app.setAttribute(Qt::AA_Use96Dpi, true);
202 204 TestAmdaFuzzing testObject{};
203 205 QTEST_SET_MAIN_SOURCE_PATH
204 206 return QTest::qExec(&testObject, argc, argv);
205 207 }
206 208
207 209 #include "TestAmdaFuzzing.moc"
General Comments 0
You need to be logged in to leave comments. Login now