##// END OF EJS Templates
Setups test (4)...
Alexandre Leroux -
r716:c3e161f3c70a
parent child
Show More
@@ -1,192 +1,241
1 1 #include <QObject>
2 2 #include <QtTest>
3 3
4 4 #include <memory>
5 5
6 6 #include <Data/DataProviderParameters.h>
7 7 #include <Data/IDataProvider.h>
8 8 #include <Data/ScalarSeries.h>
9 #include <Time/TimeController.h>
9 10 #include <Variable/Variable.h>
10 11 #include <Variable/VariableController.h>
11 12 #include <Variable/VariableModel.h>
12 13
13 14 namespace {
14 15
16 /// Delay after each operation on the variable before validating it (in ms)
17 const auto OPERATION_DELAY = 100;
18
15 19 /**
16 20 * Generates values according to a range. The value generated for a time t is the number of seconds
17 21 * of difference between t and a reference value (which is midnight -> 00:00:00)
18 22 *
19 23 * Example: For a range between 00:00:10 and 00:00:20, the generated values are
20 24 * {10,11,12,13,14,15,16,17,18,19,20}
21 25 */
22 26 std::vector<double> values(const SqpRange &range)
23 27 {
24 28 QTime referenceTime{0, 0};
25 29
26 30 std::vector<double> result{};
27 31
28 32 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
29 33 auto time = DateUtils::dateTime(i).time();
30 34 result.push_back(referenceTime.secsTo(time));
31 35 }
32 36
33 37 return result;
34 38 }
35 39
36 40 /// Provider used for the tests
37 41 class TestProvider : public IDataProvider {
38 42 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
39 43
40 44 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
41 45 {
42 46 const auto &ranges = parameters.m_Times;
43 47
44 48 for (const auto &range : ranges) {
45 49 // Generates data series
46 50 auto valuesData = values(range);
47 51
48 52 std::vector<double> xAxisData{};
49 53 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
50 54 xAxisData.push_back(i);
51 55 }
52 56
53 57 auto dataSeries = std::make_shared<ScalarSeries>(
54 58 std::move(xAxisData), std::move(valuesData), Unit{"t", true}, Unit{});
55 59
56 60 emit dataProvided(acqIdentifier, dataSeries, range);
57 61 }
58 62 }
59 63
60 64 void requestDataAborting(QUuid acqIdentifier) override
61 65 {
62 66 // Does nothing
63 67 }
64 68 };
65 69
66 70 /**
67 71 * Interface representing an operation performed on a variable controller.
68 72 * This interface is used in tests to apply a set of operations and check the status of the
69 73 * controller after each operation
70 74 */
71 75 struct IOperation {
72 76 virtual ~IOperation() = default;
73 77 /// Executes the operation on the variable controller
74 78 virtual void exec(VariableController &variableController) const = 0;
75 79 };
76 80
77 81 /**
78 82 *Variable creation operation in the controller
79 83 */
80 84 struct Create : public IOperation {
81 85 explicit Create(int index) : m_Index{index} {}
82 86
83 87 void exec(VariableController &variableController) const override
84 88 {
85 89 auto variable = variableController.createVariable(QString::number(m_Index), {},
86 90 std::make_unique<TestProvider>());
87 91 }
88 92
89 93 int m_Index; ///< The index of the variable to create in the controller
90 94 };
91 95
92 96 /**
93 97 * Variable move/shift operation in the controller
94 98 */
95 99 struct Move : public IOperation {
96 100 explicit Move(int index, const SqpRange &newRange, bool shift = false)
97 101 : m_Index{index}, m_NewRange{newRange}, m_Shift{shift}
98 102 {
99 103 }
100 104
101 105 void exec(VariableController &variableController) const override
102 106 {
103 107 if (auto variable = variableController.variableModel()->variable(m_Index)) {
104 108 variableController.onRequestDataLoading({variable}, m_NewRange, variable->range(),
105 109 !m_Shift);
106 110 }
107 111 }
108 112
109 113 int m_Index; ///< The index of the variable to move
110 114 SqpRange m_NewRange; ///< The new range of the variable
111 115 bool m_Shift; ///< Performs a shift (
112 116 };
113 117
114 118 /**
115 119 * Variable synchronization/desynchronization operation in the controller
116 120 */
117 121 struct Synchronize : public IOperation {
118 122 explicit Synchronize(int index, QUuid syncId, bool synchronize = true)
119 123 : m_Index{index}, m_SyncId{syncId}, m_Synchronize{synchronize}
120 124 {
121 125 }
122 126
123 127 void exec(VariableController &variableController) const override
124 128 {
125 129 if (auto variable = variableController.variableModel()->variable(m_Index)) {
126 130 if (m_Synchronize) {
127 131 variableController.onAddSynchronized(variable, m_SyncId);
128 132 }
129 133 else {
130 134 variableController.desynchronize(variable, m_SyncId);
131 135 }
132 136 }
133 137 }
134 138
135 139 int m_Index; ///< The index of the variable to sync/desync
136 140 QUuid m_SyncId; ///< The synchronization group of the variable
137 141 bool m_Synchronize; ///< Performs sync or desync operation
138 142 };
139 143
140 144 /**
141 145 * Test Iteration
142 146 *
143 147 * A test iteration includes an operation to be performed, and a set of expected ranges after each
144 148 * operation. Each range is tested after the operation to ensure that:
145 149 * - the range of the variable is the expected range
146 150 * - the data of the variable are those generated for the expected range
147 151 */
148 152 struct Iteration {
149 153 std::shared_ptr<IOperation> m_Operation; ///< Operation to perform
150 154 std::map<int, SqpRange> m_ExpectedRanges; ///< Expected ranges (by variable index)
151 155 };
152 156
153 157 using Iterations = std::vector<Iteration>;
154 158
155 159 } // namespace
156 160
157 161 Q_DECLARE_METATYPE(Iterations)
158 162
159 163 class TestVariableSync : public QObject {
160 164 Q_OBJECT
161 165
162 166 private slots:
163 167 /// Input data for @sa testSync()
164 168 void testSync_data();
165 169
166 170 /// Tests synchronization between variables through several operations
167 171 void testSync();
168 172 };
169 173
170 174 void TestVariableSync::testSync_data()
171 175 {
172 176 // ////////////// //
173 177 // Test structure //
174 178 // ////////////// //
175 179
176 /// @todo
180 QTest::addColumn<QUuid>("syncId");
181 QTest::addColumn<SqpRange>("initialRange");
182 QTest::addColumn<Iterations>("iterations");
177 183
178 184 // ////////// //
179 185 // Test cases //
180 186 // ////////// //
181 187
182 188 /// @todo
183 189 }
184 190
185 191 void TestVariableSync::testSync()
186 192 {
187 /// @todo
193 // Inits controllers
194 TimeController timeController{};
195 VariableController variableController{};
196 variableController.setTimeController(&timeController);
197
198 QFETCH(QUuid, syncId);
199 QFETCH(SqpRange, initialRange);
200 timeController.onTimeToUpdate(initialRange);
201
202 // Synchronization group used
203 variableController.onAddSynchronizationGroupId(syncId);
204
205 // For each iteration:
206 // - execute operation
207 // - compare the variables' state to the expected states
208 QFETCH(Iterations, iterations);
209 for (const auto &iteration : iterations) {
210 iteration.m_Operation->exec(variableController);
211 QTest::qWait(OPERATION_DELAY);
212
213 for (const auto &expectedRangeEntry : iteration.m_ExpectedRanges) {
214 auto variableIndex = expectedRangeEntry.first;
215 auto expectedRange = expectedRangeEntry.second;
216
217 // Gets the variable in the controller
218 auto variable = variableController.variableModel()->variable(variableIndex);
219
220 // Compares variable's range to the expected range
221 QVERIFY(variable != nullptr);
222 auto range = variable->range();
223 QCOMPARE(range, expectedRange);
224
225 // Compares variable's data with values expected for its range
226 auto dataSeries = variable->dataSeries();
227 QVERIFY(dataSeries != nullptr);
228
229 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
230 auto expectedValues = values(range);
231 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
232 [](const auto &dataSeriesIt, const auto &expectedValue) {
233 return dataSeriesIt.value() == expectedValue;
234 }));
235 }
236 }
188 237 }
189 238
190 239 QTEST_MAIN(TestVariableSync)
191 240
192 241 #include "TestVariableSync.moc"
General Comments 0
You need to be logged in to leave comments. Login now