1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtSensors module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include <QtTest/QtTest> |
30 | #include <QtTest/QSignalSpy> |
31 | #include <QtCore/QDebug> |
32 | |
33 | #include "../../../src/imports/sensors/qmlsensor.h" |
34 | #include "../../../src/imports/sensors/qmlsensorgesture.h" |
35 | |
36 | #include "qtemplategestureplugin.h" |
37 | #include "qtemplaterecognizer.h" |
38 | #include <qsensorgesturemanager.h> |
39 | #include <qsensorbackend.h> |
40 | #include "qsensormanager.h" |
41 | |
42 | QT_USE_NAMESPACE |
43 | |
44 | QT_BEGIN_NAMESPACE |
45 | |
46 | class tst_Sensors2QMLAPI : public QObject |
47 | { |
48 | Q_OBJECT |
49 | |
50 | private slots: |
51 | void initTestCase(); |
52 | void testGesture(); |
53 | void testSensorRanges(); |
54 | }; |
55 | |
56 | void tst_Sensors2QMLAPI::initTestCase() |
57 | { |
58 | qputenv(varName: "QT_SENSORS_LOAD_PLUGINS" , value: "0" ); // Do not load plugins |
59 | } |
60 | |
61 | void tst_Sensors2QMLAPI::testGesture() |
62 | { |
63 | QTemplateGesturePlugin* plugin = new QTemplateGesturePlugin(); |
64 | QList <QSensorGestureRecognizer *> recognizers = plugin->createRecognizers(); |
65 | QSensorGestureManager manager; |
66 | |
67 | QmlSensorGesture* gs = new QmlSensorGesture(this); |
68 | gs->componentComplete(); |
69 | QSignalSpy spy_availableGesturesChanged(gs, SIGNAL(availableGesturesChanged())); |
70 | QSignalSpy spy_detected(gs, SIGNAL(detected(QString))); |
71 | QSignalSpy spy_gesturesChanged(gs, SIGNAL(gesturesChanged())); |
72 | QSignalSpy spy_validGesturesChanged(gs, SIGNAL(validGesturesChanged())); |
73 | QSignalSpy spy_invalidGesturesChanged(gs, SIGNAL(invalidGesturesChanged())); |
74 | QSignalSpy spy_enabledChanged(gs, SIGNAL(enabledChanged())); |
75 | |
76 | //This flag is needed if you run this unit test with an alread installed template plugin |
77 | bool registered = false; |
78 | for (int i = 0; i < recognizers.count(); i++){ |
79 | registered = manager.registerSensorGestureRecognizer(recognizer: recognizers[i]); |
80 | } |
81 | if (registered) { |
82 | QCOMPARE(spy_availableGesturesChanged.count(), 2); |
83 | } |
84 | |
85 | //check creation of a not known plugin |
86 | QCOMPARE(spy_invalidGesturesChanged.count(), 0); |
87 | QCOMPARE(spy_gesturesChanged.count(), 0); |
88 | gs->setGestures(QStringList() << "lollipop" ); |
89 | QCOMPARE(spy_gesturesChanged.count(), 1); |
90 | QCOMPARE(spy_invalidGesturesChanged.count(), 1); |
91 | |
92 | //check creation of a known plugin |
93 | QCOMPARE(spy_validGesturesChanged.count(), 0); |
94 | QCOMPARE(spy_gesturesChanged.count(), 1); |
95 | spy_invalidGesturesChanged.clear(); |
96 | spy_validGesturesChanged.clear(); |
97 | gs->setGestures(QStringList() << "QtSensors.template" ); |
98 | QCOMPARE(spy_gesturesChanged.count(), 2); |
99 | QCOMPARE(spy_invalidGesturesChanged.count(), 1); |
100 | QCOMPARE(spy_validGesturesChanged.count(), 1); |
101 | |
102 | //enable "QtSensors.template" |
103 | QCOMPARE(spy_enabledChanged.count(), 0); |
104 | QCOMPARE(spy_detected.count(), 0); |
105 | gs->setEnabled(true); |
106 | QCOMPARE(spy_enabledChanged.count(), 1); |
107 | QCOMPARE(spy_detected.count(), 1); |
108 | |
109 | //set gesture during running sensor should not emit gesture changed |
110 | spy_gesturesChanged.clear(); |
111 | gs->setGestures(QStringList() << "QtSensors.template2" ); |
112 | QCOMPARE(spy_gesturesChanged.count(), 0); |
113 | |
114 | gs->setEnabled(false); |
115 | |
116 | QmlSensorGesture* gs1 = new QmlSensorGesture(this); |
117 | QSignalSpy spy1_detected(gs1, SIGNAL(detected(QString))); |
118 | QSignalSpy spy1_gesturesChanged(gs1, SIGNAL(gesturesChanged())); |
119 | QSignalSpy spy1_validGesturesChanged(gs1, SIGNAL(validGesturesChanged())); |
120 | QSignalSpy spy1_invalidGesturesChanged(gs1, SIGNAL(invalidGesturesChanged())); |
121 | QSignalSpy spy1_enabledChanged(gs1, SIGNAL(enabledChanged())); |
122 | gs1->componentComplete(); |
123 | |
124 | //set enable = true without gesture should |
125 | gs1->setEnabled(true); |
126 | QCOMPARE(spy1_enabledChanged.count(), 1); |
127 | gs1->setEnabled(false); |
128 | spy1_enabledChanged.clear(); |
129 | |
130 | //reding gestures check if we get back an empty string list |
131 | QStringList gestures = gs1->gestures(); |
132 | QCOMPARE(gestures.count(), 0); |
133 | QStringList validgestures = gs1->validGestures(); |
134 | QCOMPARE(validgestures.count(), 0); |
135 | QStringList invalidgestures = gs1->invalidGestures(); |
136 | QCOMPARE(invalidgestures.count(), 0); |
137 | |
138 | //check types "QtSensors.template" "QtSensors.template1" "lollipop" |
139 | //expect valid 2 not available 1 |
140 | gestures << "QtSensors.template" << "QtSensors.template1" << "lollipop" ; |
141 | gs1->setGestures(gestures); |
142 | gestures = gs1->gestures(); |
143 | QCOMPARE(gestures.count(), 3); |
144 | QCOMPARE(spy1_validGesturesChanged.count(), 1); |
145 | QCOMPARE(spy1_invalidGesturesChanged.count(), 1); |
146 | QCOMPARE(spy1_gesturesChanged.count(), 1); |
147 | //set same gesture again should not emit gesture changed |
148 | gs1->setGestures(gestures); |
149 | QCOMPARE(spy1_gesturesChanged.count(), 1); |
150 | |
151 | spy1_gesturesChanged.clear(); |
152 | gestures.clear(); |
153 | gs1->setGestures(gestures); |
154 | QCOMPARE(spy1_gesturesChanged.count(), 1); |
155 | |
156 | //enable "QtSensors.template" and "QtSensors.template1" |
157 | gestures << "QtSensors.template" << "QtSensors.template1" ; |
158 | gs1->setEnabled(false); |
159 | gs1->setGestures(gestures); |
160 | spy1_enabledChanged.clear(); |
161 | spy1_detected.clear(); |
162 | gs1->setEnabled(true); |
163 | QCOMPARE(spy1_enabledChanged.count(), 1); |
164 | QCOMPARE(spy1_detected.count(), 2); |
165 | gs1->setEnabled(false); |
166 | |
167 | //check sensor shouldn't run until the componentComplete gets called |
168 | QmlSensorGesture* gs2 = new QmlSensorGesture(this); |
169 | QSignalSpy spy2_detected(gs2, SIGNAL(detected(QString))); |
170 | gs2->setGestures(QStringList() << "QtSensors.template" ); |
171 | gs2->setEnabled(true); |
172 | QCOMPARE(spy2_detected.count(), 0); |
173 | gs2->componentComplete(); |
174 | QCOMPARE(spy2_detected.count(), 1); |
175 | } |
176 | |
177 | class QDummySensorBackend : public QSensorBackend |
178 | { |
179 | Q_OBJECT |
180 | public: |
181 | QDummySensorBackend(QSensor *sensor) : QSensorBackend(sensor) |
182 | { |
183 | addDataRate(min: 2, max: 3); |
184 | addDataRate(min: 5, max: 7); |
185 | addOutputRange(min: 100, max: 200, accuracy: 1); |
186 | addOutputRange(min: 600, max: 700, accuracy: 10); |
187 | addOutputRange(min: 0, max: 1, accuracy: 2); |
188 | } |
189 | |
190 | void start() override {} |
191 | void stop() override {} |
192 | }; |
193 | |
194 | class QDummySensorReading : public QSensorReading |
195 | { |
196 | Q_OBJECT |
197 | public: |
198 | QDummySensorReading(QObject *parent) : QSensorReading(parent, nullptr) {} |
199 | }; |
200 | |
201 | class QmlDummySensorReading : public QmlSensorReading |
202 | { |
203 | Q_OBJECT |
204 | public: |
205 | QmlDummySensorReading(QSensor *sensor) : |
206 | QmlSensorReading(sensor), |
207 | m_reading(new QDummySensorReading(this)) |
208 | {} |
209 | |
210 | QSensorReading *reading() const override { return m_reading; } |
211 | void readingUpdate() override {} |
212 | |
213 | private: |
214 | QSensorReading *m_reading = nullptr; |
215 | }; |
216 | |
217 | class QmlDummySensor : public QmlSensor |
218 | { |
219 | Q_OBJECT |
220 | public: |
221 | QmlDummySensor(QObject *parent = nullptr) : |
222 | QmlSensor(parent), |
223 | m_sensor(new QSensor("dummy" , this)) |
224 | { |
225 | QDummySensorBackend b(m_sensor); |
226 | Q_UNUSED(b); |
227 | } |
228 | |
229 | QSensor *sensor() const override { return m_sensor; } |
230 | QmlSensorReading *createReading() const override { return new QmlDummySensorReading(m_sensor); } |
231 | |
232 | void componentComplete() override { QmlSensor::componentComplete(); } |
233 | |
234 | private: |
235 | QSensor *m_sensor = nullptr; |
236 | }; |
237 | |
238 | void tst_Sensors2QMLAPI::testSensorRanges() |
239 | { |
240 | QScopedPointer<QmlDummySensor> qmlSensor(new QmlDummySensor); |
241 | qmlSensor->componentComplete(); |
242 | |
243 | auto ranges = qmlSensor->availableDataRates(); |
244 | QCOMPARE(ranges.count(&ranges), 2); |
245 | |
246 | const auto range0 = ranges.at(&ranges, 0); |
247 | QCOMPARE(range0->minimum(), 2); |
248 | QCOMPARE(range0->maximum(), 3); |
249 | QSignalSpy range0Spy(range0, SIGNAL(destroyed())); |
250 | |
251 | const auto range1 = ranges.at(&ranges, 1); |
252 | QCOMPARE(range1->minimum(), 5); |
253 | QCOMPARE(range1->maximum(), 7); |
254 | QSignalSpy range1Spy(range1, SIGNAL(destroyed())); |
255 | |
256 | auto outputs = qmlSensor->outputRanges(); |
257 | QCOMPARE(outputs.count(&outputs), 3); |
258 | |
259 | const auto output0 = outputs.at(&outputs, 0); |
260 | QCOMPARE(output0->minimum(), 100); |
261 | QCOMPARE(output0->maximum(), 200); |
262 | QCOMPARE(output0->accuracy(), 1); |
263 | QSignalSpy output0Spy(output0, SIGNAL(destroyed())); |
264 | |
265 | const auto output1 = outputs.at(&outputs, 1); |
266 | QCOMPARE(output1->minimum(), 600); |
267 | QCOMPARE(output1->maximum(), 700); |
268 | QCOMPARE(output1->accuracy(), 10); |
269 | QSignalSpy output1Spy(output1, SIGNAL(destroyed())); |
270 | |
271 | const auto output2 = outputs.at(&outputs, 2); |
272 | QCOMPARE(output2->minimum(), 0); |
273 | QCOMPARE(output2->maximum(), 1); |
274 | QCOMPARE(output2->accuracy(), 2); |
275 | QSignalSpy output2Spy(output2, SIGNAL(destroyed())); |
276 | |
277 | qmlSensor.reset(); |
278 | QCOMPARE(range0Spy.count(), 1); |
279 | QCOMPARE(range1Spy.count(), 1); |
280 | QCOMPARE(output0Spy.count(), 1); |
281 | QCOMPARE(output1Spy.count(), 1); |
282 | QCOMPARE(output2Spy.count(), 1); |
283 | } |
284 | |
285 | QT_END_NAMESPACE |
286 | |
287 | QTEST_MAIN(tst_Sensors2QMLAPI) |
288 | #include "tst_sensors2qmlapi.moc" |
289 | |