##// END OF EJS Templates
Fixes data loss in some cases of data recovery from the CosiunusProvider
Fixes data loss in some cases of data recovery from the CosiunusProvider

File last commit:

r746:8ae05fa76c10
r764:6fa5f5facdaa
Show More
TestCosinusAcquisition.cpp
191 lines | 6.8 KiB | text/x-c | CppLexer
/ plugins / mockplugin / tests / TestCosinusAcquisition.cpp
Alexandre Leroux
Inits unit test
r742 #include "CosinusProvider.h"
Alexandre Leroux
Implements unit test (2)...
r744 #include <Data/DataProviderParameters.h>
Alexandre Leroux
Implements unit test (1)...
r743 #include <Data/ScalarSeries.h>
Alexandre Leroux
Inits unit test
r742 #include <SqpApplication.h>
Alexandre Leroux
Implements unit test (2)...
r744 #include <Time/TimeController.h>
#include <Variable/Variable.h>
#include <Variable/VariableController.h>
Alexandre Leroux
Inits unit test
r742
#include <QObject>
#include <QtTest>
Alexandre Leroux
Implements unit test (1)...
r743 #include <cmath>
#include <memory>
Alexandre Leroux
Inits unit test
r742 namespace {
/// Path for the tests
const auto TESTS_RESOURCES_PATH = QFileInfo{
QString{MOCKPLUGIN_TESTS_RESOURCES_DIR},
"TestCosinusAcquisition"}.absoluteFilePath();
Alexandre Leroux
Implements unit test (1)...
r743 /// Format of dates in data files
const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
Alexandre Leroux
Implements unit test (2)...
r744 /// Delay after each operation on the variable before validating it (in ms)
const auto OPERATION_DELAY = 250;
Alexandre Leroux
Implements unit test (3)...
r745 /**
* Verifies that the data in the candidate series are identical to the data in the reference series
* in a specific range
* @param candidate the candidate data series
* @param range the range to check
* @param reference the reference data series
* @return true if the data of the candidate series and the reference series are identical in the
* range, false otherwise
*/
bool checkDataSeries(std::shared_ptr<IDataSeries> candidate, const SqpRange &range,
std::shared_ptr<IDataSeries> reference)
{
if (candidate == nullptr || reference == nullptr) {
return candidate == reference;
}
auto referenceIt = reference->xAxisRange(range.m_TStart, range.m_TEnd);
return std::equal(candidate->cbegin(), candidate->cend(), referenceIt.first, referenceIt.second,
[](const auto &it1, const auto &it2) {
// - milliseconds precision for time
// - 1e-6 precision for value
return std::abs(it1.x() - it2.x()) < 1e-3
&& std::abs(it1.value() - it2.value()) < 1e-6;
});
}
Alexandre Leroux
Implements unit test (1)...
r743 /// Generates the data series from the reading of a data stream
std::shared_ptr<IDataSeries> readDataStream(QTextStream &stream)
{
std::vector<double> xAxisData, valuesData;
QString line{};
while (stream.readLineInto(&line)) {
// Separates date (x-axis data) to value data
auto splitLine = line.split('\t');
if (splitLine.size() == 2) {
// Converts datetime to double
auto dateTime = QDateTime::fromString(splitLine[0], DATETIME_FORMAT);
dateTime.setTimeSpec(Qt::UTC);
xAxisData.push_back(DateUtils::secondsSinceEpoch(dateTime));
valuesData.push_back(splitLine[1].toDouble());
}
}
return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
Unit{{}, true}, Unit{});
}
Alexandre Leroux
Inits unit test
r742 } // namespace
/**
* @brief The TestCosinusAcquisition class tests acquisition in SciQlop (operations like zooms in,
* zooms out, pans) of data from CosinusProvider
* @sa CosinusProvider
*/
class TestCosinusAcquisition : public QObject {
Q_OBJECT
private slots:
/// Input data for @sa testAcquisition()
void testAcquisition_data();
void testAcquisition();
};
void TestCosinusAcquisition::testAcquisition_data()
{
Alexandre Leroux
Implements unit test (1)...
r743 // ////////////// //
// Test structure //
// ////////////// //
QTest::addColumn<QString>("dataFilename"); // File containing expected data of acquisitions
QTest::addColumn<SqpRange>("initialRange"); // First acquisition
QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
Alexandre Leroux
Adds test case
r746
// ////////// //
// Test cases //
// ////////// //
auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
return DateUtils::secondsSinceEpoch(
QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC});
};
QTest::newRow("cosinus")
<< "Cosinus_100Hz_20170101_1200_20170101_1300.txt"
<< SqpRange{dateTime(2017, 1, 1, 12, 30, 0), dateTime(2017, 1, 1, 12, 35, 1)}
<< std::vector<SqpRange>{
// Pan (jump) left
SqpRange{dateTime(2017, 1, 1, 12, 45, 0), dateTime(2017, 1, 1, 12, 50, 0)},
// Pan (jump) right
SqpRange{dateTime(2017, 1, 1, 12, 15, 0), dateTime(2017, 1, 1, 12, 20, 0)},
// Pan (overlay) right
SqpRange{dateTime(2017, 1, 1, 12, 14, 0), dateTime(2017, 1, 1, 12, 19, 0)},
// Pan (overlay) left
SqpRange{dateTime(2017, 1, 1, 12, 15, 0), dateTime(2017, 1, 1, 12, 20, 0)},
// Pan (overlay) left
SqpRange{dateTime(2017, 1, 1, 12, 16, 0), dateTime(2017, 1, 1, 12, 21, 0)},
// Zoom in
SqpRange{dateTime(2017, 1, 1, 12, 17, 30), dateTime(2017, 1, 1, 12, 19, 30)},
// Zoom out
SqpRange{dateTime(2017, 1, 1, 12, 12, 30), dateTime(2017, 1, 1, 12, 24, 30)}};
Alexandre Leroux
Inits unit test
r742 }
void TestCosinusAcquisition::testAcquisition()
{
Alexandre Leroux
Implements unit test (1)...
r743 // Retrieves data file
QFETCH(QString, dataFilename);
auto dataFilePath = QFileInfo{TESTS_RESOURCES_PATH, dataFilename}.absoluteFilePath();
QFile dataFile{dataFilePath};
if (dataFile.open(QFile::ReadOnly)) {
// Generates data series to compare with
QTextStream dataStream{&dataFile};
auto dataSeries = readDataStream(dataStream);
Alexandre Leroux
Implements unit test (3)...
r745 /// Lambda used to validate a variable at each step
auto validateVariable = [dataSeries](std::shared_ptr<Variable> variable,
const SqpRange &range) {
// Checks that the variable's range has changed
QCOMPARE(variable->range(), range);
// Checks the variable's data series
QVERIFY(checkDataSeries(variable->dataSeries(), variable->cacheRange(), dataSeries));
};
Alexandre Leroux
Implements unit test (2)...
r744 // Creates variable
QFETCH(SqpRange, initialRange);
sqpApp->timeController().onTimeToUpdate(initialRange);
auto provider = std::make_shared<CosinusProvider>();
auto variable = sqpApp->variableController().createVariable("MMS", {}, provider);
QTest::qWait(OPERATION_DELAY);
Alexandre Leroux
Implements unit test (3)...
r745 validateVariable(variable, initialRange);
Alexandre Leroux
Implements unit test (2)...
r744 // Makes operations on the variable
QFETCH(std::vector<SqpRange>, operations);
for (const auto &operation : operations) {
// Asks request on the variable and waits during its execution
sqpApp->variableController().onRequestDataLoading({variable}, operation,
variable->range(), true);
QTest::qWait(OPERATION_DELAY);
Alexandre Leroux
Implements unit test (3)...
r745 validateVariable(variable, operation);
Alexandre Leroux
Implements unit test (2)...
r744 }
Alexandre Leroux
Implements unit test (1)...
r743 }
else {
QFAIL("Can't read input data file");
}
Alexandre Leroux
Inits unit test
r742 }
int main(int argc, char *argv[])
{
SqpApplication app{argc, argv};
app.setAttribute(Qt::AA_Use96Dpi, true);
TestCosinusAcquisition testObject{};
QTEST_SET_MAIN_SOURCE_PATH
return QTest::qExec(&testObject, argc, argv);
}
#include "TestCosinusAcquisition.moc"