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 "devicetest.h"
8#include "autotests.h"
9#include "initmanagerjob.h"
10#include "pendingcall.h"
11
12#include <QSignalSpy>
13#include <QTest>
14
15namespace BluezQt
16{
17extern void bluezqt_initFakeBluezTestRun();
18}
19
20using namespace BluezQt;
21
22DeviceTest::DeviceTest()
23 : m_manager(nullptr)
24{
25 Autotests::registerMetatypes();
26}
27
28void DeviceTest::initTestCase()
29{
30 QDBusConnection connection = QDBusConnection::sessionBus();
31 QString service = QStringLiteral("org.kde.bluezqt.fakebluez");
32
33 bluezqt_initFakeBluezTestRun();
34
35 FakeBluez::start();
36 FakeBluez::runTest(QStringLiteral("bluez-standard"));
37
38 // Create adapters
39 QDBusObjectPath adapter1 = QDBusObjectPath(QStringLiteral("/org/bluez/hci0"));
40 QVariantMap adapterProps;
41 adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter1);
42 adapterProps[QStringLiteral("Address")] = QStringLiteral("1C:E5:C3:BC:94:7E");
43 adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter");
44 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps);
45
46 QDBusObjectPath adapter2 = QDBusObjectPath(QStringLiteral("/org/bluez/hci1"));
47 adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter2);
48 adapterProps[QStringLiteral("Address")] = QStringLiteral("2E:3A:C3:BC:85:7C");
49 adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter2");
50 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps);
51
52 // Create devices
53 QVariantMap deviceProps;
54 deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75"));
55 deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0"));
56 deviceProps[QStringLiteral("Address")] = QStringLiteral("40:79:6A:0C:39:75");
57 deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice");
58 deviceProps[QStringLiteral("Alias")] = QStringLiteral("TestAlias");
59 deviceProps[QStringLiteral("Icon")] = QStringLiteral("phone");
60 deviceProps[QStringLiteral("Class")] = QVariant::fromValue(quint32(101));
61 deviceProps[QStringLiteral("Appearance")] = QVariant::fromValue(quint16(25));
62 deviceProps[QStringLiteral("UUIDs")] = QStringList();
63 deviceProps[QStringLiteral("Paired")] = false;
64 deviceProps[QStringLiteral("Connected")] = false;
65 deviceProps[QStringLiteral("Trusted")] = false;
66 deviceProps[QStringLiteral("Blocked")] = false;
67 deviceProps[QStringLiteral("LegacyPairing")] = false;
68 deviceProps[QStringLiteral("RSSI")] = QVariant::fromValue(qint16(20));
69 deviceProps[QStringLiteral("Modalias")] = QStringLiteral("bluetooth:v001Dp1200d1236");
70 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps);
71
72 deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_50_79_6A_0C_39_75"));
73 deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1"));
74 deviceProps[QStringLiteral("Address")] = QStringLiteral("50:79:6A:0C:39:75");
75 deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice2");
76 deviceProps[QStringLiteral("Alias")] = QStringLiteral("TestAlias2");
77 deviceProps[QStringLiteral("Icon")] = QStringLiteral("joypad");
78 deviceProps[QStringLiteral("Class")] = QVariant::fromValue(quint32(201));
79 deviceProps[QStringLiteral("Appearance")] = QVariant::fromValue(quint16(32));
80 deviceProps[QStringLiteral("UUIDs")] = QStringList();
81 deviceProps[QStringLiteral("Paired")] = true;
82 deviceProps[QStringLiteral("Connected")] = false;
83 deviceProps[QStringLiteral("Trusted")] = true;
84 deviceProps[QStringLiteral("Blocked")] = false;
85 deviceProps[QStringLiteral("LegacyPairing")] = false;
86 deviceProps[QStringLiteral("RSSI")] = QVariant::fromValue(qint16(-15));
87 deviceProps[QStringLiteral("Modalias")] = QStringLiteral("bluetooth:v001Dp1100d1236");
88 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps);
89
90 m_manager = new Manager();
91 InitManagerJob *initJob = m_manager->init();
92 initJob->exec();
93 QVERIFY(!initJob->error());
94
95 for (const AdapterPtr &adapter : m_manager->adapters()) {
96 QVERIFY(!adapter->ubi().isEmpty());
97
98 for (const DevicePtr &device : adapter->devices()) {
99 QVERIFY(!device->ubi().isEmpty());
100
101 DeviceUnit u;
102 u.device = device;
103 u.dbusDevice = new org::bluez::Device1(service, device->ubi(), connection, this);
104 u.dbusProperties = new org::freedesktop::DBus::Properties(service, device->ubi(), connection, this);
105 m_units.append(u);
106 }
107 }
108
109 QCOMPARE(m_manager->adapters().count(), 2);
110 QCOMPARE(m_manager->devices().count(), 2);
111}
112
113void DeviceTest::cleanupTestCase()
114{
115 for (const DeviceUnit &unit : m_units) {
116 delete unit.dbusDevice;
117 delete unit.dbusProperties;
118 }
119
120 delete m_manager;
121
122 FakeBluez::stop();
123}
124
125static void compareUuids(const QStringList &actual, const QStringList &expected)
126{
127 QCOMPARE(actual.size(), expected.size());
128
129 for (int i = 0; i < actual.size(); ++i) {
130 QCOMPARE(actual.at(i).toUpper(), expected.at(i).toUpper());
131 }
132}
133
134void DeviceTest::getPropertiesTest()
135{
136 for (const DeviceUnit &unit : m_units) {
137 QCOMPARE(unit.device->ubi(), unit.dbusDevice->path());
138 QCOMPARE(unit.device->address(), unit.dbusDevice->address());
139 QCOMPARE(unit.device->name(), unit.dbusDevice->alias());
140 QCOMPARE(unit.device->remoteName(), unit.dbusDevice->name());
141 QCOMPARE(unit.device->deviceClass(), unit.dbusDevice->deviceClass());
142 QCOMPARE(unit.device->appearance(), unit.dbusDevice->appearance());
143 QCOMPARE(unit.device->icon(), deviceIcon(unit.dbusDevice));
144 QCOMPARE(unit.device->isPaired(), unit.dbusDevice->paired());
145 QCOMPARE(unit.device->isTrusted(), unit.dbusDevice->trusted());
146 QCOMPARE(unit.device->isBlocked(), unit.dbusDevice->blocked());
147 QCOMPARE(unit.device->hasLegacyPairing(), unit.dbusDevice->legacyPairing());
148 QCOMPARE(unit.device->rssi(), deviceRssi(unit.dbusDevice));
149 QCOMPARE(unit.device->isConnected(), unit.dbusDevice->connected());
150 QCOMPARE(unit.device->modalias(), unit.dbusDevice->modalias());
151 QCOMPARE(unit.device->adapter()->ubi(), unit.dbusDevice->adapter().path());
152
153 compareUuids(unit.device->uuids(), unit.dbusDevice->uUIDs());
154 }
155}
156
157void DeviceTest::setAliasTest()
158{
159 for (const DeviceUnit &unit : m_units) {
160 QSignalSpy deviceSpy(unit.device.data(), SIGNAL(nameChanged(QString)));
161 QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
162
163 QString value = unit.device->name() + QLatin1String("_tst_alias");
164
165 unit.device->setName(value);
166 QTRY_COMPARE(deviceSpy.count(), 1);
167
168 QList<QVariant> arguments = deviceSpy.takeFirst();
169 QCOMPARE(arguments.at(0).toString(), value);
170 Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Alias"), value);
171
172 QCOMPARE(unit.device->name(), value);
173 QCOMPARE(unit.dbusDevice->alias(), value);
174 }
175}
176
177void DeviceTest::setTrustedTest()
178{
179 for (const DeviceUnit &unit : m_units) {
180 QSignalSpy deviceSpy(unit.device.data(), SIGNAL(trustedChanged(bool)));
181 QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
182
183 bool value = !unit.device->isTrusted();
184
185 unit.device->setTrusted(value);
186 QTRY_COMPARE(deviceSpy.count(), 1);
187
188 QList<QVariant> arguments = deviceSpy.takeFirst();
189 QCOMPARE(arguments.at(0).toBool(), value);
190 Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Trusted"), value);
191
192 QCOMPARE(unit.device->isTrusted(), value);
193 QCOMPARE(unit.dbusDevice->trusted(), value);
194 }
195}
196
197void DeviceTest::setBlockedTest()
198{
199 for (const DeviceUnit &unit : m_units) {
200 QSignalSpy deviceSpy(unit.device.data(), SIGNAL(blockedChanged(bool)));
201 QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
202
203 bool value = !unit.device->isBlocked();
204
205 unit.device->setBlocked(value);
206 QTRY_COMPARE(deviceSpy.count(), 1);
207
208 QList<QVariant> arguments = deviceSpy.takeFirst();
209 QCOMPARE(arguments.at(0).toBool(), value);
210 Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Blocked"), value);
211
212 QCOMPARE(unit.device->isBlocked(), value);
213 QCOMPARE(unit.dbusDevice->blocked(), value);
214 }
215}
216
217void DeviceTest::deviceRemovedTest()
218{
219 for (const DeviceUnit &unit : m_units) {
220 QSignalSpy managerSpy(m_manager, SIGNAL(deviceRemoved(DevicePtr)));
221 QSignalSpy adapterSpy(unit.device->adapter().data(), SIGNAL(deviceRemoved(DevicePtr)));
222 QSignalSpy deviceSpy(unit.device.data(), SIGNAL(deviceRemoved(DevicePtr)));
223
224 QVariantMap properties;
225 properties[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(unit.device->ubi()));
226 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("remove-device"), properties);
227
228 QTRY_COMPARE(managerSpy.count(), 1);
229 QTRY_COMPARE(adapterSpy.count(), 1);
230 QTRY_COMPARE(deviceSpy.count(), 1);
231
232 QCOMPARE(managerSpy.at(0).at(0).value<DevicePtr>(), unit.device);
233 QCOMPARE(adapterSpy.at(0).at(0).value<DevicePtr>(), unit.device);
234 QCOMPARE(deviceSpy.at(0).at(0).value<DevicePtr>(), unit.device);
235 }
236}
237
238QString DeviceTest::deviceIcon(org::bluez::Device1 *device) const
239{
240 quint32 classNum = device->deviceClass();
241 switch ((classNum & 0x1f00) >> 8) {
242 case 0x04:
243 switch ((classNum & 0xfc) >> 2) {
244 case 0x01:
245 case 0x02:
246 return QStringLiteral("audio-headset");
247 case 0x06:
248 return QStringLiteral("audio-headphones");
249 }
250 }
251 return device->icon();
252}
253
254qint16 DeviceTest::deviceRssi(org::bluez::Device1 *device) const
255{
256 qint16 rssi = device->rSSI();
257 if (!rssi) {
258 rssi = -32768;
259 }
260 return rssi;
261}
262
263QTEST_MAIN(DeviceTest)
264
265#include "moc_devicetest.cpp"
266

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