1/*
2 * SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6
7#include "managertest.h"
8#include "adapter.h"
9#include "autotests.h"
10#include "device.h"
11#include "initmanagerjob.h"
12#include "manager.h"
13
14#include <QDBusObjectPath>
15#include <QSignalSpy>
16#include <QTest>
17
18namespace BluezQt
19{
20extern void bluezqt_initFakeBluezTestRun();
21}
22
23using namespace BluezQt;
24
25void ManagerTest::initTestCase()
26{
27 bluezqt_initFakeBluezTestRun();
28 FakeBluez::start(); // to check that it works
29 Autotests::registerMetatypes();
30}
31
32void ManagerTest::cleanup()
33{
34 FakeBluez::stop();
35}
36
37void ManagerTest::bluezNotRunningTest()
38{
39 // org.bluez is not running at all
40 // expected: init successful
41 auto manager = std::make_unique<Manager>();
42 InitManagerJob *job = manager->init();
43 job->exec();
44
45 QVERIFY(!job->error());
46 QVERIFY(manager->isInitialized());
47 QVERIFY(!manager->isOperational());
48 QVERIFY(!manager->isBluetoothOperational());
49}
50
51void ManagerTest::bluezNotExportingInterfacesTest()
52{
53 // org.bluez is running, but it does not export any interfaces
54 // expected: init error
55 FakeBluez::start();
56 FakeBluez::runTest(QStringLiteral("bluez-not-exporting-interfaces"));
57
58 auto manager = std::make_unique<Manager>();
59 InitManagerJob *job = manager->init();
60 job->exec();
61
62 QVERIFY(job->error());
63 QVERIFY(!manager->isInitialized());
64 QVERIFY(!manager->isOperational());
65 QVERIFY(!manager->isBluetoothOperational());
66}
67
68void ManagerTest::bluezEmptyManagedObjectsTest()
69{
70 // org.bluez exports ObjectManager, but there is no AgentManager1
71 // expected: init error
72 FakeBluez::start();
73 FakeBluez::runTest(QStringLiteral("bluez-empty-managed-objects"));
74
75 auto manager = std::make_unique<Manager>();
76 InitManagerJob *job = manager->init();
77 job->exec();
78
79 QVERIFY(job->error());
80 QVERIFY(!manager->isInitialized());
81 QVERIFY(!manager->isOperational());
82 QVERIFY(!manager->isBluetoothOperational());
83}
84
85void ManagerTest::bluezNoAdaptersTest()
86{
87 // org.bluez exports ObjectManager with AgentManager1, but there are no adapters
88 // expected: init successful
89 FakeBluez::start();
90 FakeBluez::runTest(QStringLiteral("bluez-no-adapters"));
91
92 auto manager = std::make_unique<Manager>();
93 InitManagerJob *job = manager->init();
94 job->exec();
95
96 QVERIFY(!job->error());
97 QVERIFY(manager->isInitialized());
98 QVERIFY(manager->isOperational());
99 QVERIFY(!manager->isBluetoothOperational());
100}
101
102void ManagerTest::bluezShutdownTest()
103{
104 // tests whether the adapter/device removed signals work correctly
105
106 FakeBluez::start();
107 FakeBluez::runTest(QStringLiteral("bluez-standard"));
108
109 // Create adapters
110 QDBusObjectPath adapter1path = QDBusObjectPath(QStringLiteral("/org/bluez/hci0"));
111 QVariantMap adapterProps;
112 adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter1path);
113 adapterProps[QStringLiteral("Address")] = QStringLiteral("1C:E5:C3:BC:94:7E");
114 adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter");
115 adapterProps[QStringLiteral("Powered")] = true;
116 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps);
117
118 QDBusObjectPath adapter2path = QDBusObjectPath(QStringLiteral("/org/bluez/hci1"));
119 adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter2path);
120 adapterProps[QStringLiteral("Address")] = QStringLiteral("2E:3A:C3:BC:85:7C");
121 adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter2");
122 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps);
123
124 // Create devices
125 QVariantMap deviceProps;
126 deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75"));
127 deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(adapter1path);
128 deviceProps[QStringLiteral("Address")] = QStringLiteral("40:79:6A:0C:39:75");
129 deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice");
130 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps);
131
132 deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_50_79_6A_0C_39_75"));
133 deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(adapter2path);
134 deviceProps[QStringLiteral("Address")] = QStringLiteral("50:79:6A:0C:39:75");
135 deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice2");
136 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps);
137
138 auto manager = std::make_unique<Manager>();
139
140 QSignalSpy btOperationalChangedSpy(manager.get(), SIGNAL(bluetoothOperationalChanged(bool)));
141
142 InitManagerJob *job = manager->init();
143 job->exec();
144
145 QVERIFY(!job->error());
146 QVERIFY(manager->isInitialized());
147 QVERIFY(manager->isOperational());
148 QVERIFY(manager->isBluetoothOperational());
149 QCOMPARE(manager->adapters().count(), 2);
150 QCOMPARE(manager->devices().count(), 2);
151
152 QCOMPARE(btOperationalChangedSpy.count(), 1);
153 QCOMPARE(btOperationalChangedSpy.first().first().toBool(), true);
154
155 AdapterPtr adapter1 = manager->adapterForAddress(QStringLiteral("1C:E5:C3:BC:94:7E"));
156 AdapterPtr adapter2 = manager->adapterForAddress(QStringLiteral("2E:3A:C3:BC:85:7C"));
157 DevicePtr device1 = manager->deviceForAddress(QStringLiteral("40:79:6A:0C:39:75"));
158 DevicePtr device2 = manager->deviceForAddress(QStringLiteral("50:79:6A:0C:39:75"));
159
160 QVERIFY(adapter1);
161 QVERIFY(adapter2);
162 QVERIFY(device1);
163 QVERIFY(device2);
164
165 QSignalSpy allAdaptersRemovedSpy(manager.get(), SIGNAL(allAdaptersRemoved()));
166 QSignalSpy adapterRemovedSpy(manager.get(), SIGNAL(adapterRemoved(AdapterPtr)));
167 QSignalSpy device1RemovedSpy(adapter1.data(), SIGNAL(deviceRemoved(DevicePtr)));
168 QSignalSpy device2RemovedSpy(adapter2.data(), SIGNAL(deviceRemoved(DevicePtr)));
169
170 btOperationalChangedSpy.clear();
171 FakeBluez::stop();
172
173 // allAdaptersRemoved will be last signal
174 QTRY_COMPARE(allAdaptersRemovedSpy.count(), 1);
175
176 QCOMPARE(adapterRemovedSpy.count(), 2);
177 QCOMPARE(device1RemovedSpy.count(), 1);
178 QCOMPARE(device2RemovedSpy.count(), 1);
179
180 QCOMPARE(btOperationalChangedSpy.count(), 1);
181 QCOMPARE(btOperationalChangedSpy.first().first().toBool(), false);
182}
183
184void ManagerTest::usableAdapterTest()
185{
186 FakeBluez::start();
187 FakeBluez::runTest(QStringLiteral("bluez-standard"));
188
189 // Create adapters
190 QDBusObjectPath adapter1path = QDBusObjectPath(QStringLiteral("/org/bluez/hci0"));
191 QVariantMap adapterProps;
192 adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter1path);
193 adapterProps[QStringLiteral("Address")] = QStringLiteral("1C:E5:C3:BC:94:7E");
194 adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter");
195 adapterProps[QStringLiteral("Powered")] = false;
196 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps);
197
198 QDBusObjectPath adapter2path = QDBusObjectPath(QStringLiteral("/org/bluez/hci1"));
199 adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter2path);
200 adapterProps[QStringLiteral("Address")] = QStringLiteral("2E:3A:C3:BC:85:7C");
201 adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter2");
202 adapterProps[QStringLiteral("Powered")] = false;
203 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps);
204
205 auto manager = std::make_unique<Manager>();
206
207 QSignalSpy usableAdapterChangedSpy(manager.get(), SIGNAL(usableAdapterChanged(AdapterPtr)));
208
209 InitManagerJob *job = manager->init();
210 job->exec();
211
212 QVERIFY(!job->error());
213 QVERIFY(manager->isInitialized());
214 QVERIFY(manager->isOperational());
215 QVERIFY(!manager->isBluetoothOperational());
216 QCOMPARE(usableAdapterChangedSpy.count(), 0);
217 QCOMPARE(manager->adapters().count(), 2);
218 QCOMPARE(manager->devices().count(), 0);
219
220 QVariantMap properties;
221 properties[QStringLiteral("Path")] = QVariant::fromValue(adapter1path);
222 properties[QStringLiteral("Name")] = QStringLiteral("Powered");
223 properties[QStringLiteral("Value")] = true;
224 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("change-adapter-property"), properties);
225
226 QTRY_COMPARE(usableAdapterChangedSpy.count(), 1);
227 QCOMPARE(manager->usableAdapter()->ubi(), adapter1path.path());
228
229 usableAdapterChangedSpy.clear();
230
231 properties[QStringLiteral("Value")] = false;
232 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("change-adapter-property"), properties);
233
234 QTRY_COMPARE(usableAdapterChangedSpy.count(), 1);
235 QVERIFY(manager->usableAdapter().isNull());
236
237 usableAdapterChangedSpy.clear();
238
239 properties[QStringLiteral("Path")] = QVariant::fromValue(adapter2path);
240 properties[QStringLiteral("Value")] = true;
241 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("change-adapter-property"), properties);
242
243 QTRY_COMPARE(usableAdapterChangedSpy.count(), 1);
244 QCOMPARE(manager->usableAdapter()->ubi(), adapter2path.path());
245}
246
247void ManagerTest::deviceForAddressTest()
248{
249 // tests whether the deviceForAddress correctly prefer powered adapters
250
251 FakeBluez::start();
252 FakeBluez::runTest(QStringLiteral("bluez-standard"));
253
254 // Create adapters
255 QDBusObjectPath adapter1path = QDBusObjectPath(QStringLiteral("/org/bluez/hci0"));
256 QVariantMap adapterProps;
257 adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter1path);
258 adapterProps[QStringLiteral("Address")] = QStringLiteral("1C:E5:C3:BC:94:7E");
259 adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter");
260 adapterProps[QStringLiteral("Powered")] = false;
261 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps);
262
263 QDBusObjectPath adapter2path = QDBusObjectPath(QStringLiteral("/org/bluez/hci1"));
264 adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter2path);
265 adapterProps[QStringLiteral("Address")] = QStringLiteral("2E:3A:C3:BC:85:7C");
266 adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter2");
267 adapterProps[QStringLiteral("Powered")] = true;
268 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps);
269
270 // Create devices
271 QVariantMap deviceProps;
272 deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75"));
273 deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(adapter1path);
274 deviceProps[QStringLiteral("Address")] = QStringLiteral("40:79:6A:0C:39:75");
275 deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice");
276 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps);
277
278 deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_40_79_6A_0C_39_75"));
279 deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(adapter2path);
280 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps);
281
282 auto manager = std::make_unique<Manager>();
283
284 InitManagerJob *job = manager->init();
285 job->exec();
286
287 QVERIFY(!job->error());
288
289 QString address(QStringLiteral("40:79:6A:0C:39:75"));
290 AdapterPtr adapter1 = manager->adapterForUbi(QStringLiteral("/org/bluez/hci0"));
291 AdapterPtr adapter2 = manager->adapterForUbi(QStringLiteral("/org/bluez/hci1"));
292
293 QVERIFY(adapter1);
294 QVERIFY(adapter2);
295
296 QSignalSpy adapter1Spy(adapter1.data(), SIGNAL(poweredChanged(bool)));
297 QSignalSpy adapter2Spy(adapter2.data(), SIGNAL(poweredChanged(bool)));
298
299 QCOMPARE(manager->deviceForAddress(address)->adapter(), adapter2);
300
301 QVariantMap properties;
302 properties[QStringLiteral("Path")] = QVariant::fromValue(adapter1path);
303 properties[QStringLiteral("Name")] = QStringLiteral("Powered");
304 properties[QStringLiteral("Value")] = true;
305 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("change-adapter-property"), properties);
306
307 properties[QStringLiteral("Path")] = QVariant::fromValue(adapter2path);
308 properties[QStringLiteral("Value")] = false;
309 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("change-adapter-property"), properties);
310
311 QTRY_COMPARE(adapter1Spy.count(), 1);
312 QTRY_COMPARE(adapter2Spy.count(), 1);
313
314 QCOMPARE(manager->deviceForAddress(address)->adapter(), adapter1);
315
316 properties[QStringLiteral("Path")] = QVariant::fromValue(adapter1path);
317 properties[QStringLiteral("Value")] = false;
318 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("change-adapter-property"), properties);
319
320 QTRY_COMPARE(adapter1Spy.count(), 2);
321 QVERIFY(manager->deviceForAddress(address));
322}
323
324void ManagerTest::adapterWithDevicesRemovedTest()
325{
326 // tests whether the devices are always removed from the adapter before removing adapter
327
328 FakeBluez::start();
329 FakeBluez::runTest(QStringLiteral("bluez-standard"));
330
331 // Create adapters
332 QDBusObjectPath adapter1path = QDBusObjectPath(QStringLiteral("/org/bluez/hci0"));
333 QVariantMap adapterProps;
334 adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter1path);
335 adapterProps[QStringLiteral("Address")] = QStringLiteral("1C:E5:C3:BC:94:7E");
336 adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter");
337 adapterProps[QStringLiteral("Powered")] = false;
338 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps);
339
340 // Create devices
341 QVariantMap deviceProps;
342 deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75"));
343 deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(adapter1path);
344 deviceProps[QStringLiteral("Address")] = QStringLiteral("40:79:6A:0C:39:75");
345 deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice");
346 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps);
347
348 deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_50_79_6A_0C_39_75"));
349 deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(adapter1path);
350 deviceProps[QStringLiteral("Address")] = QStringLiteral("50:79:6A:0C:39:75");
351 deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice2");
352 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps);
353
354 auto manager = std::make_unique<Manager>();
355
356 InitManagerJob *job = manager->init();
357 job->exec();
358
359 QVERIFY(!job->error());
360
361 AdapterPtr adapter = manager->adapterForAddress(QStringLiteral("1C:E5:C3:BC:94:7E"));
362 DevicePtr device1 = manager->deviceForAddress(QStringLiteral("40:79:6A:0C:39:75"));
363 DevicePtr device2 = manager->deviceForAddress(QStringLiteral("50:79:6A:0C:39:75"));
364
365 QVERIFY(adapter);
366 QVERIFY(device1);
367 QVERIFY(device2);
368
369 QSignalSpy adapterRemovedSpy(manager.get(), SIGNAL(adapterRemoved(AdapterPtr)));
370 QSignalSpy deviceRemovedSpy(manager.get(), SIGNAL(deviceRemoved(DevicePtr)));
371
372 QVariantMap properties;
373 properties[QStringLiteral("Path")] = QVariant::fromValue(adapter1path);
374 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("remove-adapter"), properties);
375
376 QTRY_COMPARE(adapterRemovedSpy.count(), 1);
377 QTRY_COMPARE(deviceRemovedSpy.count(), 2);
378 QCOMPARE(manager->adapters().count(), 0);
379 QCOMPARE(manager->devices().count(), 0);
380 QCOMPARE(adapter->devices().count(), 0);
381}
382
383void ManagerTest::bug364416()
384{
385 // Bug 364416: Crash when device is added with adapter that is unknown to Manager
386
387 FakeBluez::start();
388 FakeBluez::runTest(QStringLiteral("bluez-standard"));
389
390 auto manager = std::make_unique<Manager>();
391
392 InitManagerJob *job = manager->init();
393 job->exec();
394
395 QVERIFY(!job->error());
396
397 // Add device to invalid adapter
398 QVariantMap deviceProps;
399 deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75"));
400 deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath(QStringLiteral("/org/bluez/hci0")));
401 deviceProps[QStringLiteral("Address")] = QStringLiteral("40:79:6A:0C:39:75");
402 deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice");
403 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps);
404
405 // Wait for Manager to receive the interfacesAdded signal
406 QTest::qWait(100);
407}
408
409void ManagerTest::bug377405()
410{
411 // Bug 377405: Property changes immediately after adapter is added are lost
412
413 FakeBluez::start();
414 FakeBluez::runTest(QStringLiteral("bluez-standard"));
415
416 auto manager = std::make_unique<Manager>();
417
418 InitManagerJob *job = manager->init();
419 job->exec();
420
421 QVERIFY(!job->error());
422
423 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("bug377405"));
424
425 // Adapter property Powered is changed to true immediately after being added
426 QTRY_COMPARE(manager->isBluetoothOperational(), true);
427}
428
429QTEST_MAIN(ManagerTest)
430
431#include "moc_managertest.cpp"
432

source code of bluez-qt/autotests/managertest.cpp