##// END OF EJS Templates
Randomizes the time to wait between each operations (defines min/max delays)
Randomizes the time to wait between each operations (defines min/max delays)

File last commit:

r1243:99981a2cca28
r1243:99981a2cca28
Show More
TestAmdaFuzzing.cpp
354 lines | 12.2 KiB | text/x-c | CppLexer
/ plugins / amda / tests / TestAmdaFuzzing.cpp
Alexandre Leroux
Adds "number of operations" and "number of variables" properties for the tests
r1201 #include "FuzzingDefs.h"
Alexandre Leroux
Defines fuzzing operations...
r1202 #include "FuzzingOperations.h"
Alexandre Leroux
Adds utility class to get random values
r1206 #include "FuzzingUtils.h"
Alexandre Leroux
Adds validators to the fuzzing test...
r1228 #include "FuzzingValidators.h"
Alexandre Leroux
Adds utility class to get random values
r1206
Alexandre Leroux
Adds initial test case
r1210 #include "AmdaProvider.h"
Alexandre Leroux
Inits test structure
r1199 #include <Network/NetworkController.h>
Alexandre Leroux
Adds the ability to set cache tolerance for tests
r1224 #include <Settings/SqpSettingsDefs.h>
Alexandre Leroux
Inits test structure
r1199 #include <SqpApplication.h>
#include <Time/TimeController.h>
Alexandre Leroux
Defines VariableState struct (3)...
r1222 #include <Variable/Variable.h>
Alexandre Leroux
Inits test structure
r1199 #include <Variable/VariableController.h>
#include <QLoggingCategory>
#include <QObject>
#include <QtTest>
#include <memory>
Q_LOGGING_CATEGORY(LOG_TestAmdaFuzzing, "TestAmdaFuzzing")
namespace {
Alexandre Leroux
Defines fuzzing operations...
r1202 // /////// //
// Aliases //
// /////// //
Alexandre Leroux
Adds weights to operations (2)...
r1216 using Weight = double;
using Weights = std::vector<Weight>;
Alexandre Leroux
Defines variable pool...
r1203
Alexandre Leroux
Implements test execute() method...
r1205 using VariableOperation = std::pair<VariableId, std::shared_ptr<IFuzzingOperation> >;
using VariablesOperations = std::vector<VariableOperation>;
Alexandre Leroux
Adds weights to operations (2)...
r1216 using WeightedOperationsPool = std::map<std::shared_ptr<IFuzzingOperation>, Weight>;
Alexandre Leroux
Adds validators to the fuzzing test...
r1228 using Validators = std::vector<std::shared_ptr<IFuzzingValidator> >;
Alexandre Leroux
Defines variable pool...
r1203
Alexandre Leroux
Adds "number of operations" and "number of variables" properties for the tests
r1201 // ///////// //
// Constants //
// ///////// //
// Defaults values used when the associated properties have not been set for the test
const auto NB_MAX_OPERATIONS_DEFAULT_VALUE = 100;
Alexandre Leroux
Sets the number of sync groups to create for fuzzing tests
r1237 const auto NB_MAX_SYNC_GROUPS_DEFAULT_VALUE = 1;
Alexandre Leroux
Adds "number of operations" and "number of variables" properties for the tests
r1201 const auto NB_MAX_VARIABLES_DEFAULT_VALUE = 1;
Alexandre Leroux
Adds delete operation
r1225 const auto AVAILABLE_OPERATIONS_DEFAULT_VALUE = QVariant::fromValue(WeightedOperationsTypes{
{FuzzingOperationType::CREATE, 1.},
{FuzzingOperationType::DELETE, 0.1}, // Delete operation is less frequent
{FuzzingOperationType::PAN_LEFT, 1.},
{FuzzingOperationType::PAN_RIGHT, 1.},
{FuzzingOperationType::ZOOM_IN, 1.},
Alexandre Leroux
Creates sync and desync operations and adds them to the fuzzing tests
r1238 {FuzzingOperationType::ZOOM_OUT, 1.},
{FuzzingOperationType::SYNCHRONIZE, 0.8},
{FuzzingOperationType::DESYNCHRONIZE, 0.4}});
Alexandre Leroux
Adds the ability to set cache tolerance for tests
r1224 const auto CACHE_TOLERANCE_DEFAULT_VALUE = 0.2;
Alexandre Leroux
Implements move operations (3)...
r1219
Alexandre Leroux
Randomizes the time to wait between each operations (defines min/max delays)
r1243 /// Min/max delays between each operation (in ms)
const auto OPERATION_DELAY_BOUNDS_DEFAULT_VALUE = QVariant::fromValue(std::make_pair(100, 3000));
Alexandre Leroux
Completes fuzzing test structure by setting initial range for the time controller
r1209
Alexandre Leroux
Adds validators to the fuzzing test...
r1228 /// Validators for the tests (executed in the order in which they're defined)
const auto VALIDATORS_DEFAULT_VALUE = QVariant::fromValue(
ValidatorsTypes{{FuzzingValidatorType::RANGE, FuzzingValidatorType::DATA}});
Alexandre Leroux
Implements test execute() method...
r1205 // /////// //
// Methods //
// /////// //
/// Goes through the variables pool and operations pool to determine the set of {variable/operation}
/// pairs that are valid (i.e. operation that can be executed on variable)
Alexandre Leroux
Adds weights to operations (2)...
r1216 std::pair<VariablesOperations, Weights>
Alexandre Leroux
Passes FuzzingState and variable id instead VariableState to the methods of operations
r1236 availableOperations(const FuzzingState &fuzzingState, const WeightedOperationsPool &operationsPool)
Alexandre Leroux
Implements test execute() method...
r1205 {
VariablesOperations result{};
Alexandre Leroux
Adds weights to operations (2)...
r1216 Weights weights{};
Alexandre Leroux
Implements test execute() method...
r1205
Alexandre Leroux
Passes FuzzingState and variable id instead VariableState to the methods of operations
r1236 for (const auto &variablesPoolEntry : fuzzingState.m_VariablesPool) {
Alexandre Leroux
Implements test execute() method...
r1205 auto variableId = variablesPoolEntry.first;
Alexandre Leroux
Adds weights to operations (2)...
r1216 for (const auto &operationsPoolEntry : operationsPool) {
auto operation = operationsPoolEntry.first;
auto weight = operationsPoolEntry.second;
Alexandre Leroux
Implements test execute() method...
r1205 // A pair is valid if the current operation can be executed on the current variable
Alexandre Leroux
Passes FuzzingState and variable id instead VariableState to the methods of operations
r1236 if (operation->canExecute(variableId, fuzzingState)) {
Alexandre Leroux
Implements test execute() method...
r1205 result.push_back({variableId, operation});
Alexandre Leroux
Adds weights to operations (2)...
r1216 weights.push_back(weight);
Alexandre Leroux
Implements test execute() method...
r1205 }
}
}
Alexandre Leroux
Adds weights to operations (2)...
r1216 return {result, weights};
Alexandre Leroux
Implements test execute() method...
r1205 }
Alexandre Leroux
Adds weights to operations (2)...
r1216 WeightedOperationsPool createOperationsPool(const WeightedOperationsTypes &types)
Alexandre Leroux
Defines operations pool...
r1204 {
Alexandre Leroux
Adds weights to operations (2)...
r1216 WeightedOperationsPool result{};
Alexandre Leroux
Defines operations pool...
r1204
Alexandre Leroux
Adds weights to operations (2)...
r1216 std::transform(
types.cbegin(), types.cend(), std::inserter(result, result.end()), [](const auto &type) {
return std::make_pair(FuzzingOperationFactory::create(type.first), type.second);
});
Alexandre Leroux
Defines operations pool...
r1204
return result;
}
Alexandre Leroux
Adds validators to the fuzzing test...
r1228 Validators createValidators(const ValidatorsTypes &types)
{
Validators result{};
std::transform(types.cbegin(), types.cend(), std::inserter(result, result.end()),
[](const auto &type) { return FuzzingValidatorFactory::create(type); });
return result;
}
Alexandre Leroux
Calls validation after each operation
r1229 /**
* Validates all the variables' states passed in parameter, according to a set of validators
* @param variablesPool the variables' states
* @param validators the validators used for validation
*/
void validate(const VariablesPool &variablesPool, const Validators &validators)
{
for (const auto &variablesPoolEntry : variablesPool) {
auto variableId = variablesPoolEntry.first;
const auto &variableState = variablesPoolEntry.second;
auto variableMessage = variableState.m_Variable ? variableState.m_Variable->name()
: QStringLiteral("null variable");
qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validating state of variable at index"
<< variableId << "(" << variableMessage << ")...";
for (const auto &validator : validators) {
validator->validate(VariableState{variableState});
}
qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Validation completed.";
}
}
Alexandre Leroux
Inits test structure
r1199 /**
* Class to run random tests
*/
class FuzzingTest {
public:
Alexandre Leroux
Adds variable controller and properties to test structure...
r1200 explicit FuzzingTest(VariableController &variableController, Properties properties)
: m_VariableController{variableController},
m_Properties{std::move(properties)},
Alexandre Leroux
Passes FuzzingState and variable id instead VariableState to the methods of operations
r1236 m_FuzzingState{}
Alexandre Leroux
Adds variable controller and properties to test structure...
r1200 {
Alexandre Leroux
Defines variable pool...
r1203 // Inits variables pool: at init, all variables are null
for (auto variableId = 0; variableId < nbMaxVariables(); ++variableId) {
Alexandre Leroux
Passes FuzzingState and variable id instead VariableState to the methods of operations
r1236 m_FuzzingState.m_VariablesPool[variableId] = VariableState{};
Alexandre Leroux
Defines variable pool...
r1203 }
Alexandre Leroux
Sets the number of sync groups to create for fuzzing tests
r1237
// Inits sync groups and registers them into the variable controller
for (auto i = 0; i < nbMaxSyncGroups(); ++i) {
auto syncGroupId = SyncGroupId::createUuid();
variableController.onAddSynchronizationGroupId(syncGroupId);
m_FuzzingState.m_SyncGroupsPool[syncGroupId] = SyncGroup{};
}
Alexandre Leroux
Adds variable controller and properties to test structure...
r1200 }
Alexandre Leroux
Inits test structure
r1199 void execute()
{
Alexandre Leroux
Some fixes...
r1223 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Running" << nbMaxOperations() << "operations on"
<< nbMaxVariables() << "variable(s)...";
Alexandre Leroux
Adds "number of operations" and "number of variables" properties for the tests
r1201
Alexandre Leroux
Implements test execute() method...
r1205 auto canExecute = true;
for (auto i = 0; i < nbMaxOperations() && canExecute; ++i) {
// Retrieves all operations that can be executed in the current context
Alexandre Leroux
Adds weights to operations (2)...
r1216 VariablesOperations variableOperations{};
Weights weights{};
std::tie(variableOperations, weights)
Alexandre Leroux
Passes FuzzingState and variable id instead VariableState to the methods of operations
r1236 = availableOperations(m_FuzzingState, operationsPool());
Alexandre Leroux
Implements test execute() method...
r1205
canExecute = !variableOperations.empty();
if (canExecute) {
// Of the operations available, chooses a random operation and executes it
auto variableOperation
Alexandre Leroux
Adds weights to operations (2)...
r1216 = RandomGenerator::instance().randomChoice(variableOperations, weights);
Alexandre Leroux
Implements test execute() method...
r1205
auto variableId = variableOperation.first;
auto fuzzingOperation = variableOperation.second;
Alexandre Leroux
Passes FuzzingState and variable id instead VariableState to the methods of operations
r1236 fuzzingOperation->execute(variableId, m_FuzzingState, m_VariableController,
m_Properties);
Alexandre Leroux
Randomizes the time to wait between each operations (defines min/max delays)
r1243
// Delays the next operation with a randomly generated time
auto delay = RandomGenerator::instance().generateInt(operationDelays().first,
operationDelays().second);
qCDebug(LOG_TestAmdaFuzzing())
<< "Waiting " << delay << "ms before the next operation...";
QTest::qWait(delay);
Alexandre Leroux
Calls validation after each operation
r1229
// Validates variables
Alexandre Leroux
Passes FuzzingState and variable id instead VariableState to the methods of operations
r1236 validate(m_FuzzingState.m_VariablesPool, validators());
Alexandre Leroux
Implements test execute() method...
r1205 }
else {
Alexandre Leroux
Some fixes...
r1223 qCInfo(LOG_TestAmdaFuzzing()).noquote()
Alexandre Leroux
Implements test execute() method...
r1205 << "No more operations are available, the execution of the test will stop...";
}
}
Alexandre Leroux
Some fixes...
r1223 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Execution of the test completed.";
Alexandre Leroux
Inits test structure
r1199 }
Alexandre Leroux
Adds variable controller and properties to test structure...
r1200
private:
Alexandre Leroux
Adds "number of operations" and "number of variables" properties for the tests
r1201 int nbMaxOperations() const
{
static auto result
= m_Properties.value(NB_MAX_OPERATIONS_PROPERTY, NB_MAX_OPERATIONS_DEFAULT_VALUE)
.toInt();
return result;
}
Alexandre Leroux
Sets the number of sync groups to create for fuzzing tests
r1237 int nbMaxSyncGroups() const
{
static auto result
= m_Properties.value(NB_MAX_SYNC_GROUPS_PROPERTY, NB_MAX_SYNC_GROUPS_DEFAULT_VALUE)
.toInt();
return result;
}
Alexandre Leroux
Adds "number of operations" and "number of variables" properties for the tests
r1201 int nbMaxVariables() const
{
static auto result
= m_Properties.value(NB_MAX_VARIABLES_PROPERTY, NB_MAX_VARIABLES_DEFAULT_VALUE).toInt();
return result;
}
Alexandre Leroux
Randomizes the time to wait between each operations (defines min/max delays)
r1243 std::pair<int, int> operationDelays() const
Alexandre Leroux
Implements move operations (3)...
r1219 {
static auto result
Alexandre Leroux
Randomizes the time to wait between each operations (defines min/max delays)
r1243 = m_Properties
.value(OPERATION_DELAY_BOUNDS_PROPERTY, OPERATION_DELAY_BOUNDS_DEFAULT_VALUE)
.value<std::pair<int, int> >();
Alexandre Leroux
Implements move operations (3)...
r1219 return result;
}
Alexandre Leroux
Adds weights to operations (2)...
r1216 WeightedOperationsPool operationsPool() const
Alexandre Leroux
Defines operations pool...
r1204 {
static auto result = createOperationsPool(
m_Properties.value(AVAILABLE_OPERATIONS_PROPERTY, AVAILABLE_OPERATIONS_DEFAULT_VALUE)
Alexandre Leroux
Adds weights to operations (2)...
r1216 .value<WeightedOperationsTypes>());
Alexandre Leroux
Defines operations pool...
r1204 return result;
}
Alexandre Leroux
Adds validators to the fuzzing test...
r1228 Validators validators() const
{
static auto result
= createValidators(m_Properties.value(VALIDATORS_PROPERTY, VALIDATORS_DEFAULT_VALUE)
.value<ValidatorsTypes>());
return result;
}
Alexandre Leroux
Adds variable controller and properties to test structure...
r1200 VariableController &m_VariableController;
Properties m_Properties;
Alexandre Leroux
Passes FuzzingState and variable id instead VariableState to the methods of operations
r1236 FuzzingState m_FuzzingState;
Alexandre Leroux
Inits test structure
r1199 };
} // namespace
class TestAmdaFuzzing : public QObject {
Q_OBJECT
private slots:
/// Input data for @sa testFuzzing()
void testFuzzing_data();
void testFuzzing();
};
void TestAmdaFuzzing::testFuzzing_data()
{
// ////////////// //
// Test structure //
// ////////////// //
Alexandre Leroux
Adds variable controller and properties to test structure...
r1200 QTest::addColumn<Properties>("properties"); // Properties for random test
Alexandre Leroux
Inits test structure
r1199
// ////////// //
// Test cases //
// ////////// //
Alexandre Leroux
Adds initial test case
r1210 auto maxRange = SqpRange::fromDateTime({2017, 1, 1}, {0, 0}, {2017, 1, 5}, {0, 0});
MetadataPool metadataPool{{{"dataType", "vector"}, {"xml:id", "imf"}}};
// Note: we don't use auto here as we want to pass std::shared_ptr<IDataProvider> as is in the
// QVariant
std::shared_ptr<IDataProvider> provider = std::make_shared<AmdaProvider>();
QTest::newRow("fuzzingTest") << Properties{
{MAX_RANGE_PROPERTY, QVariant::fromValue(maxRange)},
{METADATA_POOL_PROPERTY, QVariant::fromValue(metadataPool)},
{PROVIDER_PROPERTY, QVariant::fromValue(provider)}};
Alexandre Leroux
Inits test structure
r1199 }
void TestAmdaFuzzing::testFuzzing()
{
Alexandre Leroux
Adds variable controller and properties to test structure...
r1200 QFETCH(Properties, properties);
Alexandre Leroux
Adds the ability to set cache tolerance for tests
r1224 // Sets cache property
QSettings settings{};
auto cacheTolerance = properties.value(CACHE_TOLERANCE_PROPERTY, CACHE_TOLERANCE_DEFAULT_VALUE);
settings.setValue(GENERAL_TOLERANCE_AT_INIT_KEY, cacheTolerance);
settings.setValue(GENERAL_TOLERANCE_AT_UPDATE_KEY, cacheTolerance);
Alexandre Leroux
Inits test structure
r1199 auto &variableController = sqpApp->variableController();
auto &timeController = sqpApp->timeController();
Alexandre Leroux
Completes fuzzing test structure by setting initial range for the time controller
r1209 // Generates random initial range (bounded to max range)
auto maxRange = properties.value(MAX_RANGE_PROPERTY, QVariant::fromValue(INVALID_RANGE))
.value<SqpRange>();
QVERIFY(maxRange != INVALID_RANGE);
auto initialRangeStart
= RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
auto initialRangeEnd
= RandomGenerator::instance().generateDouble(maxRange.m_TStart, maxRange.m_TEnd);
if (initialRangeStart > initialRangeEnd) {
std::swap(initialRangeStart, initialRangeEnd);
}
// Sets initial range on time controller
SqpRange initialRange{initialRangeStart, initialRangeEnd};
Alexandre Leroux
Some fixes...
r1223 qCInfo(LOG_TestAmdaFuzzing()).noquote() << "Setting initial range to" << initialRange << "...";
Alexandre Leroux
Completes fuzzing test structure by setting initial range for the time controller
r1209 timeController.onTimeToUpdate(initialRange);
Alexandre Leroux
Some fixes...
r1223 properties.insert(INITIAL_RANGE_PROPERTY, QVariant::fromValue(initialRange));
Alexandre Leroux
Completes fuzzing test structure by setting initial range for the time controller
r1209
Alexandre Leroux
Adds variable controller and properties to test structure...
r1200 FuzzingTest test{variableController, properties};
Alexandre Leroux
Inits test structure
r1199 test.execute();
}
int main(int argc, char *argv[])
{
QLoggingCategory::setFilterRules(
"*.warning=false\n"
"*.info=false\n"
"*.debug=false\n"
"FuzzingOperations.info=true\n"
Alexandre Leroux
Adds validators to the fuzzing test...
r1228 "FuzzingValidators.info=true\n"
Alexandre Leroux
Inits test structure
r1199 "TestAmdaFuzzing.info=true\n");
SqpApplication app{argc, argv};
Alexandre Leroux
Adds the ability to set cache tolerance for tests
r1224 SqpApplication::setOrganizationName("LPP");
SqpApplication::setOrganizationDomain("lpp.fr");
SqpApplication::setApplicationName("SciQLop-TestFuzzing");
Alexandre Leroux
Inits test structure
r1199 app.setAttribute(Qt::AA_Use96Dpi, true);
TestAmdaFuzzing testObject{};
QTEST_SET_MAIN_SOURCE_PATH
return QTest::qExec(&testObject, argc, argv);
}
#include "TestAmdaFuzzing.moc"