##// END OF EJS Templates
Changes plugin products to integrate parametric frequencies
Alexandre Leroux -
r781:958cef2901c0
parent child
Show More
@@ -1,81 +1,91
1 1 #include "MockPlugin.h"
2 2 #include "CosinusProvider.h"
3 3 #include "MockDefs.h"
4 4
5 5 #include <DataSource/DataSourceController.h>
6 6 #include <DataSource/DataSourceItem.h>
7 7 #include <DataSource/DataSourceItemAction.h>
8 8
9 9 #include <SqpApplication.h>
10 10
11 11 Q_LOGGING_CATEGORY(LOG_MockPlugin, "MockPlugin")
12 12
13 13 namespace {
14 14
15 15 /// Name of the data source
16 16 const auto DATA_SOURCE_NAME = QStringLiteral("MMS");
17 17
18 18 /// Creates the data provider relative to the plugin
19 19 std::unique_ptr<IDataProvider> createDataProvider() noexcept
20 20 {
21 21 return std::make_unique<CosinusProvider>();
22 22 }
23 23
24 24 std::unique_ptr<DataSourceItem> createProductItem(const QVariantHash &data,
25 25 const QUuid &dataSourceUid)
26 26 {
27 27 auto result = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, data);
28 28 auto productName = data.value(DataSourceItem::NAME_DATA_KEY).toString();
29 29
30 30 // Add action to load product from DataSourceController
31 31 result->addAction(std::make_unique<DataSourceItemAction>(
32 32 QObject::tr("Load %1 product").arg(productName),
33 33 [productName, dataSourceUid](DataSourceItem &item) {
34 34 if (auto app = sqpApp) {
35 35 app->dataSourceController().loadProductItem(dataSourceUid, item);
36 36 }
37 37 }));
38 38
39 39 return result;
40 40 }
41 41
42 42 /// Creates the data source item relative to the plugin
43 43 std::unique_ptr<DataSourceItem> createDataSourceItem(const QUuid &dataSourceUid) noexcept
44 44 {
45 45 // Magnetic field products
46 46 auto magneticFieldFolder = std::make_unique<DataSourceItem>(DataSourceItemType::NODE,
47 47 QStringLiteral("Magnetic field"));
48 magneticFieldFolder->appendChild(createProductItem(QStringLiteral("FGM"), dataSourceUid));
49 magneticFieldFolder->appendChild(createProductItem(QStringLiteral("SC"), dataSourceUid));
48 magneticFieldFolder->appendChild(
49 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 10 Hz")},
50 {COSINUS_FREQUENCY_KEY, 10.}},
51 dataSourceUid));
52 magneticFieldFolder->appendChild(
53 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 60 Hz")},
54 {COSINUS_FREQUENCY_KEY, 60.}},
55 dataSourceUid));
56 magneticFieldFolder->appendChild(
57 createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 100 Hz")},
58 {COSINUS_FREQUENCY_KEY, 100.}},
59 dataSourceUid));
50 60
51 61 // Electric field products
52 62 auto electricFieldFolder = std::make_unique<DataSourceItem>(DataSourceItemType::NODE,
53 63 QStringLiteral("Electric field"));
54 64
55 65 // Root
56 66 auto root = std::make_unique<DataSourceItem>(DataSourceItemType::NODE, DATA_SOURCE_NAME);
57 67 root->appendChild(std::move(magneticFieldFolder));
58 68 root->appendChild(std::move(electricFieldFolder));
59 69
60 70 return root;
61 71 }
62 72
63 73 } // namespace
64 74
65 75 void MockPlugin::initialize()
66 76 {
67 77 if (auto app = sqpApp) {
68 78 // Registers to the data source controller
69 79 auto &dataSourceController = app->dataSourceController();
70 80 auto dataSourceUid = dataSourceController.registerDataSource(DATA_SOURCE_NAME);
71 81
72 82 // Sets data source tree
73 83 dataSourceController.setDataSourceItem(dataSourceUid, createDataSourceItem(dataSourceUid));
74 84
75 85 // Sets data provider
76 86 dataSourceController.setDataProvider(dataSourceUid, createDataProvider());
77 87 }
78 88 else {
79 89 qCWarning(LOG_MockPlugin()) << tr("Can't access to SciQlop application");
80 90 }
81 91 }
@@ -1,191 +1,193
1 1 #include "CosinusProvider.h"
2 #include "MockDefs.h"
2 3
3 4 #include <Data/DataProviderParameters.h>
4 5 #include <Data/ScalarSeries.h>
5 6 #include <SqpApplication.h>
6 7 #include <Time/TimeController.h>
7 8 #include <Variable/Variable.h>
8 9 #include <Variable/VariableController.h>
9 10
10 11 #include <QObject>
11 12 #include <QtTest>
12 13
13 14 #include <cmath>
14 15 #include <memory>
15 16
16 17 namespace {
17 18
18 19 /// Path for the tests
19 20 const auto TESTS_RESOURCES_PATH = QFileInfo{
20 21 QString{MOCKPLUGIN_TESTS_RESOURCES_DIR},
21 22 "TestCosinusAcquisition"}.absoluteFilePath();
22 23
23 24 /// Format of dates in data files
24 25 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
25 26
26 27 /// Delay after each operation on the variable before validating it (in ms)
27 28 const auto OPERATION_DELAY = 250;
28 29
29 30 /**
30 31 * Verifies that the data in the candidate series are identical to the data in the reference series
31 32 * in a specific range
32 33 * @param candidate the candidate data series
33 34 * @param range the range to check
34 35 * @param reference the reference data series
35 36 * @return true if the data of the candidate series and the reference series are identical in the
36 37 * range, false otherwise
37 38 */
38 39 bool checkDataSeries(std::shared_ptr<IDataSeries> candidate, const SqpRange &range,
39 40 std::shared_ptr<IDataSeries> reference)
40 41 {
41 42 if (candidate == nullptr || reference == nullptr) {
42 43 return candidate == reference;
43 44 }
44 45
45 46 auto referenceIt = reference->xAxisRange(range.m_TStart, range.m_TEnd);
46 47
47 48 return std::equal(candidate->cbegin(), candidate->cend(), referenceIt.first, referenceIt.second,
48 49 [](const auto &it1, const auto &it2) {
49 50 // - milliseconds precision for time
50 51 // - 1e-6 precision for value
51 52 return std::abs(it1.x() - it2.x()) < 1e-3
52 53 && std::abs(it1.value() - it2.value()) < 1e-6;
53 54 });
54 55 }
55 56
56 57 /// Generates the data series from the reading of a data stream
57 58 std::shared_ptr<IDataSeries> readDataStream(QTextStream &stream)
58 59 {
59 60 std::vector<double> xAxisData, valuesData;
60 61
61 62 QString line{};
62 63 while (stream.readLineInto(&line)) {
63 64 // Separates date (x-axis data) to value data
64 65 auto splitLine = line.split('\t');
65 66 if (splitLine.size() == 2) {
66 67 // Converts datetime to double
67 68 auto dateTime = QDateTime::fromString(splitLine[0], DATETIME_FORMAT);
68 69 dateTime.setTimeSpec(Qt::UTC);
69 70 xAxisData.push_back(DateUtils::secondsSinceEpoch(dateTime));
70 71
71 72 valuesData.push_back(splitLine[1].toDouble());
72 73 }
73 74 }
74 75
75 76 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
76 77 Unit{{}, true}, Unit{});
77 78 }
78 79
79 80 } // namespace
80 81
81 82 /**
82 83 * @brief The TestCosinusAcquisition class tests acquisition in SciQlop (operations like zooms in,
83 84 * zooms out, pans) of data from CosinusProvider
84 85 * @sa CosinusProvider
85 86 */
86 87 class TestCosinusAcquisition : public QObject {
87 88 Q_OBJECT
88 89
89 90 private slots:
90 91 /// Input data for @sa testAcquisition()
91 92 void testAcquisition_data();
92 93 void testAcquisition();
93 94 };
94 95
95 96 void TestCosinusAcquisition::testAcquisition_data()
96 97 {
97 98 // ////////////// //
98 99 // Test structure //
99 100 // ////////////// //
100 101
101 102 QTest::addColumn<QString>("dataFilename"); // File containing expected data of acquisitions
102 103 QTest::addColumn<SqpRange>("initialRange"); // First acquisition
103 104 QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
104 105
105 106 // ////////// //
106 107 // Test cases //
107 108 // ////////// //
108 109
109 110 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
110 111 return DateUtils::secondsSinceEpoch(
111 112 QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC});
112 113 };
113 114
114 115 QTest::newRow("cosinus")
115 116 << "Cosinus_100Hz_20170101_1200_20170101_1300.txt"
116 117 << SqpRange{dateTime(2017, 1, 1, 12, 30, 0), dateTime(2017, 1, 1, 12, 35, 1)}
117 118 << std::vector<SqpRange>{
118 119 // Pan (jump) left
119 120 SqpRange{dateTime(2017, 1, 1, 12, 45, 0), dateTime(2017, 1, 1, 12, 50, 0)},
120 121 // Pan (jump) right
121 122 SqpRange{dateTime(2017, 1, 1, 12, 15, 0), dateTime(2017, 1, 1, 12, 20, 0)},
122 123 // Pan (overlay) right
123 124 SqpRange{dateTime(2017, 1, 1, 12, 14, 0), dateTime(2017, 1, 1, 12, 19, 0)},
124 125 // Pan (overlay) left
125 126 SqpRange{dateTime(2017, 1, 1, 12, 15, 0), dateTime(2017, 1, 1, 12, 20, 0)},
126 127 // Pan (overlay) left
127 128 SqpRange{dateTime(2017, 1, 1, 12, 16, 0), dateTime(2017, 1, 1, 12, 21, 0)},
128 129 // Zoom in
129 130 SqpRange{dateTime(2017, 1, 1, 12, 17, 30), dateTime(2017, 1, 1, 12, 19, 30)},
130 131 // Zoom out
131 132 SqpRange{dateTime(2017, 1, 1, 12, 12, 30), dateTime(2017, 1, 1, 12, 24, 30)}};
132 133 }
133 134
134 135 void TestCosinusAcquisition::testAcquisition()
135 136 {
136 137 // Retrieves data file
137 138 QFETCH(QString, dataFilename);
138 139
139 140 auto dataFilePath = QFileInfo{TESTS_RESOURCES_PATH, dataFilename}.absoluteFilePath();
140 141 QFile dataFile{dataFilePath};
141 142
142 143 if (dataFile.open(QFile::ReadOnly)) {
143 144 // Generates data series to compare with
144 145 QTextStream dataStream{&dataFile};
145 146 auto dataSeries = readDataStream(dataStream);
146 147
147 148 /// Lambda used to validate a variable at each step
148 149 auto validateVariable = [dataSeries](std::shared_ptr<Variable> variable,
149 150 const SqpRange &range) {
150 151 // Checks that the variable's range has changed
151 152 QCOMPARE(variable->range(), range);
152 153
153 154 // Checks the variable's data series
154 155 QVERIFY(checkDataSeries(variable->dataSeries(), variable->cacheRange(), dataSeries));
155 156 };
156 157
157 158 // Creates variable
158 159 QFETCH(SqpRange, initialRange);
159 160 sqpApp->timeController().onTimeToUpdate(initialRange);
160 161 auto provider = std::make_shared<CosinusProvider>();
161 auto variable = sqpApp->variableController().createVariable("MMS", {}, provider);
162 auto variable = sqpApp->variableController().createVariable(
163 "MMS", {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 100.}}, provider);
162 164
163 165 QTest::qWait(OPERATION_DELAY);
164 166 validateVariable(variable, initialRange);
165 167
166 168 // Makes operations on the variable
167 169 QFETCH(std::vector<SqpRange>, operations);
168 170 for (const auto &operation : operations) {
169 171 // Asks request on the variable and waits during its execution
170 172 sqpApp->variableController().onRequestDataLoading({variable}, operation,
171 173 variable->range(), true);
172 174
173 175 QTest::qWait(OPERATION_DELAY);
174 176 validateVariable(variable, operation);
175 177 }
176 178 }
177 179 else {
178 180 QFAIL("Can't read input data file");
179 181 }
180 182 }
181 183
182 184 int main(int argc, char *argv[])
183 185 {
184 186 SqpApplication app{argc, argv};
185 187 app.setAttribute(Qt::AA_Use96Dpi, true);
186 188 TestCosinusAcquisition testObject{};
187 189 QTEST_SET_MAIN_SOURCE_PATH
188 190 return QTest::qExec(&testObject, argc, argv);
189 191 }
190 192
191 193 #include "TestCosinusAcquisition.moc"
General Comments 0
You need to be logged in to leave comments. Login now