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 test suite 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 | //TESTED_COMPONENT=src/multimedia |
30 | |
31 | #include <QtTest/QtTest> |
32 | |
33 | #include <QtCore/qtimer.h> |
34 | |
35 | #include <QtMultimedia/qmediametadata.h> |
36 | #include <qmediaobject.h> |
37 | #include <qmediaservice.h> |
38 | #include <qmetadatareadercontrol.h> |
39 | #include <qaudioinputselectorcontrol.h> |
40 | |
41 | #include "mockmediarecorderservice.h" |
42 | #include "mockmediaserviceprovider.h" |
43 | #include "mockmetadatareadercontrol.h" |
44 | #include "mockavailabilitycontrol.h" |
45 | |
46 | class QtTestMediaObjectService : public QMediaService |
47 | { |
48 | Q_OBJECT |
49 | public: |
50 | QtTestMediaObjectService(QObject *parent = 0, MockAvailabilityControl *availability = 0) |
51 | : QMediaService(parent) |
52 | , availabilityControl(availability) |
53 | , metaDataRef(0) |
54 | , hasMetaData(true) |
55 | { |
56 | } |
57 | |
58 | QMediaControl *requestControl(const char *iid) |
59 | { |
60 | if (hasMetaData && qstrcmp(str1: iid, QMetaDataReaderControl_iid) == 0) |
61 | return &metaData; |
62 | else if (qstrcmp(str1: iid, QMediaAvailabilityControl_iid) == 0) |
63 | return availabilityControl; |
64 | else |
65 | return 0; |
66 | } |
67 | |
68 | void releaseControl(QMediaControl *) |
69 | { |
70 | } |
71 | |
72 | MockMetaDataReaderControl metaData; |
73 | MockAvailabilityControl *availabilityControl; |
74 | int metaDataRef; |
75 | bool hasMetaData; |
76 | }; |
77 | |
78 | QT_USE_NAMESPACE |
79 | |
80 | class tst_QMediaObject : public QObject |
81 | { |
82 | Q_OBJECT |
83 | |
84 | private slots: |
85 | void propertyWatch(); |
86 | void notifySignals_data(); |
87 | void notifySignals(); |
88 | void notifyInterval_data(); |
89 | void notifyInterval(); |
90 | |
91 | void nullMetaDataControl(); |
92 | void isMetaDataAvailable(); |
93 | void metaDataChanged(); |
94 | void metaData_data(); |
95 | void metaData(); |
96 | void availability(); |
97 | |
98 | void service(); |
99 | |
100 | private: |
101 | void setupNotifyTests(); |
102 | }; |
103 | |
104 | class QtTestMediaObject : public QMediaObject |
105 | { |
106 | Q_OBJECT |
107 | Q_PROPERTY(int a READ a WRITE setA NOTIFY aChanged) |
108 | Q_PROPERTY(int b READ b WRITE setB NOTIFY bChanged) |
109 | Q_PROPERTY(int c READ c WRITE setC NOTIFY cChanged) |
110 | Q_PROPERTY(int d READ d WRITE setD) |
111 | public: |
112 | QtTestMediaObject(QMediaService *service = 0): QMediaObject(0, service), m_a(0), m_b(0), m_c(0), m_d(0) {} |
113 | |
114 | using QMediaObject::addPropertyWatch; |
115 | using QMediaObject::removePropertyWatch; |
116 | |
117 | int a() const { return m_a; } |
118 | void setA(int a) { m_a = a; } |
119 | |
120 | int b() const { return m_b; } |
121 | void setB(int b) { m_b = b; } |
122 | |
123 | int c() const { return m_c; } |
124 | void setC(int c) { m_c = c; } |
125 | |
126 | int d() const { return m_d; } |
127 | void setD(int d) { m_d = d; } |
128 | |
129 | Q_SIGNALS: |
130 | void aChanged(int a); |
131 | void bChanged(int b); |
132 | void cChanged(int c); |
133 | |
134 | private: |
135 | int m_a; |
136 | int m_b; |
137 | int m_c; |
138 | int m_d; |
139 | }; |
140 | |
141 | void tst_QMediaObject::propertyWatch() |
142 | { |
143 | QtTestMediaObject object; |
144 | object.setNotifyInterval(0); |
145 | |
146 | QEventLoop loop; |
147 | connect(sender: &object, SIGNAL(aChanged(int)), receiver: &QTestEventLoop::instance(), SLOT(exitLoop())); |
148 | connect(sender: &object, SIGNAL(bChanged(int)), receiver: &QTestEventLoop::instance(), SLOT(exitLoop())); |
149 | connect(sender: &object, SIGNAL(cChanged(int)), receiver: &QTestEventLoop::instance(), SLOT(exitLoop())); |
150 | |
151 | QSignalSpy aSpy(&object, SIGNAL(aChanged(int))); |
152 | QSignalSpy bSpy(&object, SIGNAL(bChanged(int))); |
153 | QSignalSpy cSpy(&object, SIGNAL(cChanged(int))); |
154 | |
155 | QTestEventLoop::instance().enterLoop(secs: 1); |
156 | |
157 | QCOMPARE(aSpy.count(), 0); |
158 | QCOMPARE(bSpy.count(), 0); |
159 | QCOMPARE(cSpy.count(), 0); |
160 | |
161 | int aCount = 0; |
162 | int bCount = 0; |
163 | int cCount = 0; |
164 | |
165 | object.addPropertyWatch(name: "a" ); |
166 | |
167 | QTestEventLoop::instance().enterLoop(secs: 1); |
168 | |
169 | QVERIFY(aSpy.count() > aCount); |
170 | QCOMPARE(bSpy.count(), 0); |
171 | QCOMPARE(cSpy.count(), 0); |
172 | QCOMPARE(aSpy.last().value(0).toInt(), 0); |
173 | |
174 | aCount = aSpy.count(); |
175 | |
176 | object.setA(54); |
177 | object.setB(342); |
178 | object.setC(233); |
179 | |
180 | QTestEventLoop::instance().enterLoop(secs: 1); |
181 | |
182 | QVERIFY(aSpy.count() > aCount); |
183 | QCOMPARE(bSpy.count(), 0); |
184 | QCOMPARE(cSpy.count(), 0); |
185 | QCOMPARE(aSpy.last().value(0).toInt(), 54); |
186 | |
187 | aCount = aSpy.count(); |
188 | |
189 | object.addPropertyWatch(name: "b" ); |
190 | object.addPropertyWatch(name: "d" ); |
191 | object.removePropertyWatch(name: "e" ); |
192 | object.setA(43); |
193 | object.setB(235); |
194 | object.setC(90); |
195 | |
196 | QTestEventLoop::instance().enterLoop(secs: 1); |
197 | |
198 | QVERIFY(aSpy.count() > aCount); |
199 | QVERIFY(bSpy.count() > bCount); |
200 | QCOMPARE(cSpy.count(), 0); |
201 | QCOMPARE(aSpy.last().value(0).toInt(), 43); |
202 | QCOMPARE(bSpy.last().value(0).toInt(), 235); |
203 | |
204 | aCount = aSpy.count(); |
205 | bCount = bSpy.count(); |
206 | |
207 | object.removePropertyWatch(name: "a" ); |
208 | object.addPropertyWatch(name: "c" ); |
209 | object.addPropertyWatch(name: "e" ); |
210 | |
211 | QTestEventLoop::instance().enterLoop(secs: 1); |
212 | |
213 | QCOMPARE(aSpy.count(), aCount); |
214 | QVERIFY(bSpy.count() > bCount); |
215 | QVERIFY(cSpy.count() > cCount); |
216 | QCOMPARE(bSpy.last().value(0).toInt(), 235); |
217 | QCOMPARE(cSpy.last().value(0).toInt(), 90); |
218 | |
219 | bCount = bSpy.count(); |
220 | cCount = cSpy.count(); |
221 | |
222 | object.setA(435); |
223 | object.setC(9845); |
224 | |
225 | QTestEventLoop::instance().enterLoop(secs: 1); |
226 | |
227 | QCOMPARE(aSpy.count(), aCount); |
228 | QVERIFY(bSpy.count() > bCount); |
229 | QVERIFY(cSpy.count() > cCount); |
230 | QCOMPARE(bSpy.last().value(0).toInt(), 235); |
231 | QCOMPARE(cSpy.last().value(0).toInt(), 9845); |
232 | |
233 | bCount = bSpy.count(); |
234 | cCount = cSpy.count(); |
235 | |
236 | object.setA(8432); |
237 | object.setB(324); |
238 | object.setC(443); |
239 | object.removePropertyWatch(name: "c" ); |
240 | object.removePropertyWatch(name: "d" ); |
241 | |
242 | QTestEventLoop::instance().enterLoop(secs: 1); |
243 | |
244 | QCOMPARE(aSpy.count(), aCount); |
245 | QVERIFY(bSpy.count() > bCount); |
246 | QCOMPARE(cSpy.count(), cCount); |
247 | QCOMPARE(bSpy.last().value(0).toInt(), 324); |
248 | QCOMPARE(cSpy.last().value(0).toInt(), 9845); |
249 | |
250 | bCount = bSpy.count(); |
251 | |
252 | object.removePropertyWatch(name: "b" ); |
253 | |
254 | QTestEventLoop::instance().enterLoop(secs: 1); |
255 | |
256 | QCOMPARE(aSpy.count(), aCount); |
257 | QCOMPARE(bSpy.count(), bCount); |
258 | QCOMPARE(cSpy.count(), cCount); |
259 | } |
260 | |
261 | void tst_QMediaObject::setupNotifyTests() |
262 | { |
263 | QTest::addColumn<int>(name: "interval" ); |
264 | QTest::addColumn<int>(name: "count" ); |
265 | |
266 | QTest::newRow(dataTag: "single 750ms" ) |
267 | << 750 |
268 | << 1; |
269 | QTest::newRow(dataTag: "single 600ms" ) |
270 | << 600 |
271 | << 1; |
272 | QTest::newRow(dataTag: "x3 300ms" ) |
273 | << 300 |
274 | << 3; |
275 | QTest::newRow(dataTag: "x5 180ms" ) |
276 | << 180 |
277 | << 5; |
278 | } |
279 | |
280 | void tst_QMediaObject::notifySignals_data() |
281 | { |
282 | setupNotifyTests(); |
283 | } |
284 | |
285 | void tst_QMediaObject::notifySignals() |
286 | { |
287 | QFETCH(int, interval); |
288 | QFETCH(int, count); |
289 | |
290 | QtTestMediaObject object; |
291 | QSignalSpy spy(&object, SIGNAL(aChanged(int))); |
292 | |
293 | object.setNotifyInterval(interval); |
294 | object.addPropertyWatch(name: "a" ); |
295 | |
296 | QElapsedTimer timer; |
297 | timer.start(); |
298 | |
299 | QTRY_COMPARE(spy.count(), count); |
300 | } |
301 | |
302 | void tst_QMediaObject::notifyInterval_data() |
303 | { |
304 | setupNotifyTests(); |
305 | } |
306 | |
307 | void tst_QMediaObject::notifyInterval() |
308 | { |
309 | QFETCH(int, interval); |
310 | |
311 | QtTestMediaObject object; |
312 | QSignalSpy spy(&object, SIGNAL(notifyIntervalChanged(int))); |
313 | |
314 | object.setNotifyInterval(interval); |
315 | QCOMPARE(object.notifyInterval(), interval); |
316 | QCOMPARE(spy.count(), 1); |
317 | QCOMPARE(spy.last().value(0).toInt(), interval); |
318 | |
319 | object.setNotifyInterval(interval); |
320 | QCOMPARE(object.notifyInterval(), interval); |
321 | QCOMPARE(spy.count(), 1); |
322 | } |
323 | |
324 | void tst_QMediaObject::nullMetaDataControl() |
325 | { |
326 | const QString titleKey(QLatin1String("Title" )); |
327 | const QString title(QLatin1String("Host of Seraphim" )); |
328 | |
329 | QtTestMediaObjectService service; |
330 | service.hasMetaData = false; |
331 | |
332 | QtTestMediaObject object(&service); |
333 | |
334 | QSignalSpy spy(&object, SIGNAL(metaDataChanged())); |
335 | |
336 | QCOMPARE(object.isMetaDataAvailable(), false); |
337 | |
338 | QCOMPARE(object.metaData(QMediaMetaData::Title).toString(), QString()); |
339 | QCOMPARE(object.availableMetaData(), QStringList()); |
340 | QCOMPARE(spy.count(), 0); |
341 | } |
342 | |
343 | void tst_QMediaObject::isMetaDataAvailable() |
344 | { |
345 | QtTestMediaObjectService service; |
346 | service.metaData.setMetaDataAvailable(false); |
347 | |
348 | QtTestMediaObject object(&service); |
349 | QCOMPARE(object.isMetaDataAvailable(), false); |
350 | |
351 | QSignalSpy spy(&object, SIGNAL(metaDataAvailableChanged(bool))); |
352 | service.metaData.setMetaDataAvailable(true); |
353 | |
354 | QCOMPARE(object.isMetaDataAvailable(), true); |
355 | QCOMPARE(spy.count(), 1); |
356 | QCOMPARE(spy.at(0).at(0).toBool(), true); |
357 | |
358 | service.metaData.setMetaDataAvailable(false); |
359 | |
360 | QCOMPARE(object.isMetaDataAvailable(), false); |
361 | QCOMPARE(spy.count(), 2); |
362 | QCOMPARE(spy.at(1).at(0).toBool(), false); |
363 | } |
364 | |
365 | void tst_QMediaObject::metaDataChanged() |
366 | { |
367 | QtTestMediaObjectService service; |
368 | QtTestMediaObject object(&service); |
369 | |
370 | QSignalSpy changedSpy(&object, SIGNAL(metaDataChanged())); |
371 | QSignalSpy changedWithValueSpy(&object, SIGNAL(metaDataChanged(QString,QVariant))); |
372 | |
373 | service.metaData.setMetaData(key: "key" , value: "Value" ); |
374 | QCOMPARE(changedSpy.count(), 1); |
375 | QCOMPARE(changedWithValueSpy.count(), 1); |
376 | QCOMPARE(changedWithValueSpy.last()[0], QVariant("key" )); |
377 | QCOMPARE(changedWithValueSpy.last()[1].value<QVariant>(), QVariant("Value" )); |
378 | |
379 | service.metaData.setMetaData(key: "key" , value: "Value" ); |
380 | QCOMPARE(changedSpy.count(), 1); |
381 | QCOMPARE(changedWithValueSpy.count(), 1); |
382 | |
383 | service.metaData.setMetaData(key: "key2" , value: "Value" ); |
384 | QCOMPARE(changedSpy.count(), 2); |
385 | QCOMPARE(changedWithValueSpy.count(), 2); |
386 | QCOMPARE(changedWithValueSpy.last()[0], QVariant("key2" )); |
387 | QCOMPARE(changedWithValueSpy.last()[1].value<QVariant>(), QVariant("Value" )); |
388 | } |
389 | |
390 | void tst_QMediaObject::metaData_data() |
391 | { |
392 | QTest::addColumn<QString>(name: "artist" ); |
393 | QTest::addColumn<QString>(name: "title" ); |
394 | QTest::addColumn<QString>(name: "genre" ); |
395 | |
396 | QTest::newRow(dataTag: "" ) |
397 | << QString::fromLatin1(str: "Dead Can Dance" ) |
398 | << QString::fromLatin1(str: "Host of Seraphim" ) |
399 | << QString::fromLatin1(str: "Awesome" ); |
400 | } |
401 | |
402 | void tst_QMediaObject::metaData() |
403 | { |
404 | QFETCH(QString, artist); |
405 | QFETCH(QString, title); |
406 | QFETCH(QString, genre); |
407 | |
408 | QtTestMediaObjectService service; |
409 | service.metaData.populateMetaData(); |
410 | |
411 | QtTestMediaObject object(&service); |
412 | QVERIFY(object.availableMetaData().isEmpty()); |
413 | |
414 | service.metaData.m_data.insert(key: QMediaMetaData::AlbumArtist, value: artist); |
415 | service.metaData.m_data.insert(key: QMediaMetaData::Title, value: title); |
416 | service.metaData.m_data.insert(key: QMediaMetaData::Genre, value: genre); |
417 | |
418 | QCOMPARE(object.metaData(QMediaMetaData::AlbumArtist).toString(), artist); |
419 | QCOMPARE(object.metaData(QMediaMetaData::Title).toString(), title); |
420 | |
421 | QStringList metaDataKeys = object.availableMetaData(); |
422 | QCOMPARE(metaDataKeys.size(), 3); |
423 | QVERIFY(metaDataKeys.contains(QMediaMetaData::AlbumArtist)); |
424 | QVERIFY(metaDataKeys.contains(QMediaMetaData::Title)); |
425 | QVERIFY(metaDataKeys.contains(QMediaMetaData::Genre)); |
426 | } |
427 | |
428 | void tst_QMediaObject::availability() |
429 | { |
430 | { |
431 | QtTestMediaObject nullObject(0); |
432 | QCOMPARE(nullObject.isAvailable(), false); |
433 | QCOMPARE(nullObject.availability(), QMultimedia::ServiceMissing); |
434 | } |
435 | |
436 | { |
437 | QtTestMediaObjectService service; |
438 | QtTestMediaObject object(&service); |
439 | QCOMPARE(object.isAvailable(), true); |
440 | QCOMPARE(object.availability(), QMultimedia::Available); |
441 | } |
442 | |
443 | { |
444 | MockAvailabilityControl available(QMultimedia::Available); |
445 | QtTestMediaObjectService service(0, &available); |
446 | QtTestMediaObject object(&service); |
447 | QSignalSpy availabilitySpy(&object, SIGNAL(availabilityChanged(bool))); |
448 | QSignalSpy availabilityStatusSpy(&object, SIGNAL(availabilityChanged(QMultimedia::AvailabilityStatus))); |
449 | |
450 | QCOMPARE(object.isAvailable(), true); |
451 | QCOMPARE(object.availability(), QMultimedia::Available); |
452 | |
453 | available.setAvailability(QMultimedia::Busy); |
454 | QCOMPARE(object.isAvailable(), false); |
455 | QCOMPARE(object.availability(), QMultimedia::Busy); |
456 | QCOMPARE(availabilitySpy.count(), 1); |
457 | QCOMPARE(availabilityStatusSpy.count(), 1); |
458 | |
459 | available.setAvailability(QMultimedia::Available); |
460 | QCOMPARE(object.isAvailable(), true); |
461 | QCOMPARE(object.availability(), QMultimedia::Available); |
462 | QCOMPARE(availabilitySpy.count(), 2); |
463 | QCOMPARE(availabilityStatusSpy.count(), 2); |
464 | } |
465 | |
466 | { |
467 | MockAvailabilityControl available(QMultimedia::Busy); |
468 | QtTestMediaObjectService service(0, &available); |
469 | QtTestMediaObject object(&service); |
470 | QSignalSpy availabilitySpy(&object, SIGNAL(availabilityChanged(bool))); |
471 | QSignalSpy availabilityStatusSpy(&object, SIGNAL(availabilityChanged(QMultimedia::AvailabilityStatus))); |
472 | |
473 | QCOMPARE(object.isAvailable(), false); |
474 | QCOMPARE(object.availability(), QMultimedia::Busy); |
475 | |
476 | available.setAvailability(QMultimedia::Available); |
477 | QCOMPARE(object.isAvailable(), true); |
478 | QCOMPARE(object.availability(), QMultimedia::Available); |
479 | QCOMPARE(availabilitySpy.count(), 1); |
480 | QCOMPARE(availabilityStatusSpy.count(), 1); |
481 | } |
482 | } |
483 | |
484 | void tst_QMediaObject::service() |
485 | { |
486 | // Create the mediaobject with service. |
487 | QtTestMediaObjectService service; |
488 | QtTestMediaObject mediaObject1(&service); |
489 | |
490 | // Get service and Compare if it equal to the service passed as an argument in mediaObject1. |
491 | QMediaService *service1 = mediaObject1.service(); |
492 | QVERIFY(service1 != NULL); |
493 | QCOMPARE(service1,&service); |
494 | |
495 | // Create the mediaobject with empty service and verify that service() returns NULL. |
496 | QtTestMediaObject mediaObject2; |
497 | QMediaService *service2 = mediaObject2.service(); |
498 | QVERIFY(service2 == NULL); |
499 | } |
500 | |
501 | QTEST_GUILESS_MAIN(tst_QMediaObject) |
502 | #include "tst_qmediaobject.moc" |
503 | |