##// END OF EJS Templates
Implements unit test (3)...
Alexandre Leroux -
r689:e4699d579435
parent child
Show More
@@ -1,109 +1,110
1 1 #include "CosinusProvider.h"
2 2
3 3 #include <Data/DataProviderParameters.h>
4 4 #include <Data/ScalarSeries.h>
5 5
6 6 #include <cmath>
7 7
8 8 #include <QFuture>
9 9 #include <QThread>
10 10 #include <QtConcurrent/QtConcurrent>
11 11
12 12 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
13 13
14 14 std::shared_ptr<IDataProvider> CosinusProvider::clone() const
15 15 {
16 16 // No copy is made in clone
17 17 return std::make_shared<CosinusProvider>();
18 18 }
19 19
20 20 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid acqIdentifier,
21 21 const SqpRange &dataRangeRequested)
22 22 {
23 23 // TODO: Add Mutex
24 24 auto dataIndex = 0;
25 25
26 26 // Gets the timerange from the parameters
27 27 double freq = 100.0;
28 28 double start = std::ceil(dataRangeRequested.m_TStart * freq); // 100 htz
29 29 double end = std::floor(dataRangeRequested.m_TEnd * freq); // 100 htz
30 30
31 31 // We assure that timerange is valid
32 32 if (end < start) {
33 33 std::swap(start, end);
34 34 }
35 35
36 // Generates scalar series containing cosinus values (one value per second)
37 auto dataCount = end - start;
36 // Generates scalar series containing cosinus values (one value per second, end value is
37 // included)
38 auto dataCount = end - start + 1;
38 39
39 40 auto xAxisData = std::vector<double>{};
40 41 xAxisData.resize(dataCount);
41 42
42 43 auto valuesData = std::vector<double>{};
43 44 valuesData.resize(dataCount);
44 45
45 46 int progress = 0;
46 47 auto progressEnd = dataCount;
47 for (auto time = start; time < end; ++time, ++dataIndex) {
48 for (auto time = start; time <= end; ++time, ++dataIndex) {
48 49 auto it = m_VariableToEnableProvider.find(acqIdentifier);
49 50 if (it != m_VariableToEnableProvider.end() && it.value()) {
50 51 const auto timeOnFreq = time / freq;
51 52
52 53 xAxisData[dataIndex] = timeOnFreq;
53 54 valuesData[dataIndex] = std::cos(timeOnFreq);
54 55
55 56 // progression
56 57 int currentProgress = (time - start) * 100.0 / progressEnd;
57 58 if (currentProgress != progress) {
58 59 progress = currentProgress;
59 60
60 61 emit dataProvidedProgress(acqIdentifier, progress);
61 62 }
62 63 }
63 64 else {
64 65 if (!it.value()) {
65 66 qCDebug(LOG_CosinusProvider())
66 67 << "CosinusProvider::retrieveData: ARRET De l'acquisition detectΓ©"
67 68 << end - time;
68 69 }
69 70 }
70 71 }
71 72 emit dataProvidedProgress(acqIdentifier, 0.0);
72 73
73 74 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
74 75 Unit{QStringLiteral("t"), true}, Unit{});
75 76 }
76 77
77 78 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
78 79 const DataProviderParameters &parameters)
79 80 {
80 81 // TODO: Add Mutex
81 82 m_VariableToEnableProvider[acqIdentifier] = true;
82 83 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::requestDataLoading"
83 84 << QThread::currentThread()->objectName();
84 85 // NOTE: Try to use multithread if possible
85 86 const auto times = parameters.m_Times;
86 87
87 88 for (const auto &dateTime : qAsConst(times)) {
88 89 if (m_VariableToEnableProvider[acqIdentifier]) {
89 90 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime);
90 91 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::dataProvided";
91 92 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
92 93 }
93 94 }
94 95 }
95 96
96 97 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
97 98 {
98 99 // TODO: Add Mutex
99 100 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
100 101 << QThread::currentThread()->objectName();
101 102 auto it = m_VariableToEnableProvider.find(acqIdentifier);
102 103 if (it != m_VariableToEnableProvider.end()) {
103 104 it.value() = false;
104 105 }
105 106 else {
106 107 qCWarning(LOG_CosinusProvider())
107 108 << tr("Aborting progression of inexistant identifier detected !!!");
108 109 }
109 110 }
@@ -1,123 +1,163
1 1 #include "CosinusProvider.h"
2 2
3 3 #include <Data/DataProviderParameters.h>
4 4 #include <Data/ScalarSeries.h>
5 5 #include <SqpApplication.h>
6 6 #include <Time/TimeController.h>
7 7 #include <Variable/Variable.h>
8 8 #include <Variable/VariableController.h>
9 9
10 10 #include <QObject>
11 11 #include <QtTest>
12 12
13 13 #include <cmath>
14 14 #include <memory>
15 15
16 16 namespace {
17 17
18 18 /// Path for the tests
19 19 const auto TESTS_RESOURCES_PATH = QFileInfo{
20 20 QString{MOCKPLUGIN_TESTS_RESOURCES_DIR},
21 21 "TestCosinusAcquisition"}.absoluteFilePath();
22 22
23 23 /// Format of dates in data files
24 24 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
25 25
26 26 /// Delay after each operation on the variable before validating it (in ms)
27 27 const auto OPERATION_DELAY = 250;
28 28
29 /**
30 * Verifies that the data in the candidate series are identical to the data in the reference series
31 * in a specific range
32 * @param candidate the candidate data series
33 * @param range the range to check
34 * @param reference the reference data series
35 * @return true if the data of the candidate series and the reference series are identical in the
36 * range, false otherwise
37 */
38 bool checkDataSeries(std::shared_ptr<IDataSeries> candidate, const SqpRange &range,
39 std::shared_ptr<IDataSeries> reference)
40 {
41 if (candidate == nullptr || reference == nullptr) {
42 return candidate == reference;
43 }
44
45 auto referenceIt = reference->xAxisRange(range.m_TStart, range.m_TEnd);
46
47 return std::equal(candidate->cbegin(), candidate->cend(), referenceIt.first, referenceIt.second,
48 [](const auto &it1, const auto &it2) {
49 // - milliseconds precision for time
50 // - 1e-6 precision for value
51 return std::abs(it1.x() - it2.x()) < 1e-3
52 && std::abs(it1.value() - it2.value()) < 1e-6;
53 });
54 }
55
29 56 /// Generates the data series from the reading of a data stream
30 57 std::shared_ptr<IDataSeries> readDataStream(QTextStream &stream)
31 58 {
32 59 std::vector<double> xAxisData, valuesData;
33 60
34 61 QString line{};
35 62 while (stream.readLineInto(&line)) {
36 63 // Separates date (x-axis data) to value data
37 64 auto splitLine = line.split('\t');
38 65 if (splitLine.size() == 2) {
39 66 // Converts datetime to double
40 67 auto dateTime = QDateTime::fromString(splitLine[0], DATETIME_FORMAT);
41 68 dateTime.setTimeSpec(Qt::UTC);
42 69 xAxisData.push_back(DateUtils::secondsSinceEpoch(dateTime));
43 70
44 71 valuesData.push_back(splitLine[1].toDouble());
45 72 }
46 73 }
47 74
48 75 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
49 76 Unit{{}, true}, Unit{});
50 77 }
51 78
52 79 } // namespace
53 80
54 81 /**
55 82 * @brief The TestCosinusAcquisition class tests acquisition in SciQlop (operations like zooms in,
56 83 * zooms out, pans) of data from CosinusProvider
57 84 * @sa CosinusProvider
58 85 */
59 86 class TestCosinusAcquisition : public QObject {
60 87 Q_OBJECT
61 88
62 89 private slots:
63 90 /// Input data for @sa testAcquisition()
64 91 void testAcquisition_data();
65 92 void testAcquisition();
66 93 };
67 94
68 95 void TestCosinusAcquisition::testAcquisition_data()
69 96 {
70 97 // ////////////// //
71 98 // Test structure //
72 99 // ////////////// //
73 100
74 101 QTest::addColumn<QString>("dataFilename"); // File containing expected data of acquisitions
75 102 QTest::addColumn<SqpRange>("initialRange"); // First acquisition
76 103 QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
77 104 }
78 105
79 106 void TestCosinusAcquisition::testAcquisition()
80 107 {
81 108 // Retrieves data file
82 109 QFETCH(QString, dataFilename);
83 110
84 111 auto dataFilePath = QFileInfo{TESTS_RESOURCES_PATH, dataFilename}.absoluteFilePath();
85 112 QFile dataFile{dataFilePath};
86 113
87 114 if (dataFile.open(QFile::ReadOnly)) {
88 115 // Generates data series to compare with
89 116 QTextStream dataStream{&dataFile};
90 117 auto dataSeries = readDataStream(dataStream);
91 118
119 /// Lambda used to validate a variable at each step
120 auto validateVariable = [dataSeries](std::shared_ptr<Variable> variable,
121 const SqpRange &range) {
122 // Checks that the variable's range has changed
123 QCOMPARE(variable->range(), range);
124
125 // Checks the variable's data series
126 QVERIFY(checkDataSeries(variable->dataSeries(), variable->cacheRange(), dataSeries));
127 };
128
92 129 // Creates variable
93 130 QFETCH(SqpRange, initialRange);
94 131 sqpApp->timeController().onTimeToUpdate(initialRange);
95 132 auto provider = std::make_shared<CosinusProvider>();
96 133 auto variable = sqpApp->variableController().createVariable("MMS", {}, provider);
97 134
98 135 QTest::qWait(OPERATION_DELAY);
136 validateVariable(variable, initialRange);
137
99 138 // Makes operations on the variable
100 139 QFETCH(std::vector<SqpRange>, operations);
101 140 for (const auto &operation : operations) {
102 141 // Asks request on the variable and waits during its execution
103 142 sqpApp->variableController().onRequestDataLoading({variable}, operation,
104 143 variable->range(), true);
105 144
106 145 QTest::qWait(OPERATION_DELAY);
146 validateVariable(variable, operation);
107 147 }
108 148 }
109 149 else {
110 150 QFAIL("Can't read input data file");
111 151 }
112 152 }
113 153
114 154 int main(int argc, char *argv[])
115 155 {
116 156 SqpApplication app{argc, argv};
117 157 app.setAttribute(Qt::AA_Use96Dpi, true);
118 158 TestCosinusAcquisition testObject{};
119 159 QTEST_SET_MAIN_SOURCE_PATH
120 160 return QTest::qExec(&testObject, argc, argv);
121 161 }
122 162
123 163 #include "TestCosinusAcquisition.moc"
General Comments 0
You need to be logged in to leave comments. Login now