File indexing completed on 2024-04-14 03:49:54
0001 /* 0002 * SPDX-FileCopyrightText: 2021 Ivan Podkurkov <podkiva2@gmail.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "gattcharacteristicremotetest.h" 0008 0009 #include "adapter.h" 0010 #include "autotests.h" 0011 #include "device.h" 0012 #include "initmanagerjob.h" 0013 #include "pendingcall.h" 0014 0015 #include <QSignalSpy> 0016 #include <QTest> 0017 #include <QDebug> 0018 0019 namespace BluezQt 0020 { 0021 extern void bluezqt_initFakeBluezTestRun(); 0022 } 0023 0024 using namespace BluezQt; 0025 0026 GattCharacteristicRemoteTest::GattCharacteristicRemoteTest() 0027 : m_manager(nullptr) 0028 { 0029 Autotests::registerMetatypes(); 0030 } 0031 0032 void GattCharacteristicRemoteTest::initTestCase() 0033 { 0034 QDBusConnection connection = QDBusConnection::sessionBus(); 0035 QString service = QStringLiteral("org.kde.bluezqt.fakebluez"); 0036 0037 bluezqt_initFakeBluezTestRun(); 0038 0039 FakeBluez::start(); 0040 FakeBluez::runTest(QStringLiteral("bluez-standard")); 0041 0042 // Create adapters 0043 QDBusObjectPath adapter1 = QDBusObjectPath(QStringLiteral("/org/bluez/hci0")); 0044 QVariantMap adapterProps; 0045 adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter1); 0046 adapterProps[QStringLiteral("Address")] = QStringLiteral("1C:E5:C3:BC:94:7E"); 0047 adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter"); 0048 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps); 0049 0050 QDBusObjectPath adapter2 = QDBusObjectPath(QStringLiteral("/org/bluez/hci1")); 0051 adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter2); 0052 adapterProps[QStringLiteral("Address")] = QStringLiteral("2E:3A:C3:BC:85:7C"); 0053 adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter2"); 0054 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps); 0055 0056 // Create devices 0057 QVariantMap deviceProps; 0058 deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75")); 0059 deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0")); 0060 deviceProps[QStringLiteral("Address")] = QStringLiteral("40:79:6A:0C:39:75"); 0061 deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice"); 0062 deviceProps[QStringLiteral("Alias")] = QStringLiteral("TestAlias"); 0063 deviceProps[QStringLiteral("Icon")] = QStringLiteral("phone"); 0064 deviceProps[QStringLiteral("Class")] = QVariant::fromValue(quint32(101)); 0065 deviceProps[QStringLiteral("Appearance")] = QVariant::fromValue(quint16(25)); 0066 deviceProps[QStringLiteral("UUIDs")] = QStringList(); 0067 deviceProps[QStringLiteral("Paired")] = false; 0068 deviceProps[QStringLiteral("Connected")] = false; 0069 deviceProps[QStringLiteral("Trusted")] = false; 0070 deviceProps[QStringLiteral("Blocked")] = false; 0071 deviceProps[QStringLiteral("LegacyPairing")] = false; 0072 deviceProps[QStringLiteral("RSSI")] = QVariant::fromValue(qint16(20)); 0073 deviceProps[QStringLiteral("Modalias")] = QStringLiteral("bluetooth:v001Dp1200d1236"); 0074 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); 0075 0076 deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_50_79_6A_0C_39_75")); 0077 deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1")); 0078 deviceProps[QStringLiteral("Address")] = QStringLiteral("50:79:6A:0C:39:75"); 0079 deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice2"); 0080 deviceProps[QStringLiteral("Alias")] = QStringLiteral("TestAlias2"); 0081 deviceProps[QStringLiteral("Icon")] = QStringLiteral("joypad"); 0082 deviceProps[QStringLiteral("Class")] = QVariant::fromValue(quint32(201)); 0083 deviceProps[QStringLiteral("Appearance")] = QVariant::fromValue(quint16(32)); 0084 deviceProps[QStringLiteral("UUIDs")] = QStringList(); 0085 deviceProps[QStringLiteral("Paired")] = true; 0086 deviceProps[QStringLiteral("Connected")] = false; 0087 deviceProps[QStringLiteral("Trusted")] = true; 0088 deviceProps[QStringLiteral("Blocked")] = false; 0089 deviceProps[QStringLiteral("LegacyPairing")] = false; 0090 deviceProps[QStringLiteral("RSSI")] = QVariant::fromValue(qint16(-15)); 0091 deviceProps[QStringLiteral("Modalias")] = QStringLiteral("bluetooth:v001Dp1100d1236"); 0092 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); 0093 0094 // Create services 0095 QVariantMap serviceProps; 0096 serviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75/service0")); 0097 serviceProps[QStringLiteral("UUID")] = QStringLiteral("04FA28C0-2D0C-11EC-8D3D-0242AC130003"); 0098 serviceProps[QStringLiteral("Primary")] = true; 0099 serviceProps[QStringLiteral("Device")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75")); 0100 serviceProps[QStringLiteral("Includes")] = QVariant::fromValue(QList<QDBusObjectPath>()); 0101 serviceProps[QStringLiteral("Handle")] = QVariant::fromValue(qint16(1)); 0102 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-gatt-service"), serviceProps); 0103 0104 serviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_50_79_6A_0C_39_75/service0")); 0105 serviceProps[QStringLiteral("UUID")] = QStringLiteral("0663A394-9A76-4361-9DE6-82577B82AC9A"); 0106 serviceProps[QStringLiteral("Primary")] = true; 0107 serviceProps[QStringLiteral("Device")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_50_79_6A_0C_39_75")); 0108 serviceProps[QStringLiteral("Includes")] = QVariant::fromValue(QList<QDBusObjectPath>()); 0109 serviceProps[QStringLiteral("Handle")] = QVariant::fromValue(qint16(2)); 0110 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-gatt-service"), serviceProps); 0111 0112 // Create characteristics 0113 QVariantMap charProps; 0114 charProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75/service0/char0")); 0115 charProps[QStringLiteral("UUID")] = QStringLiteral("04FA28C0-2D0C-11EC-8D3D-0242AC130004"); 0116 charProps[QStringLiteral("Service")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75/service0")); 0117 charProps[QStringLiteral("Value")] = QVariant::fromValue(QByteArray()); 0118 charProps[QStringLiteral("Notifying")] = false; 0119 charProps[QStringLiteral("Flags")] = QStringList({QStringLiteral("read"), QStringLiteral("write")}); 0120 charProps[QStringLiteral("Handle")] = QVariant::fromValue(qint16(3)); 0121 charProps[QStringLiteral("MTU")] = QVariant::fromValue(qint16(512)); 0122 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-gatt-characteristic"), charProps); 0123 0124 charProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_50_79_6A_0C_39_75/service0/char0")); 0125 charProps[QStringLiteral("UUID")] = QStringLiteral("0663A394-9A76-4361-9DE6-82577B82AC9B"); 0126 charProps[QStringLiteral("Service")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_50_79_6A_0C_39_75/service0")); 0127 charProps[QStringLiteral("Value")] = QVariant::fromValue(QByteArray()); 0128 charProps[QStringLiteral("Notifying")] = false; 0129 charProps[QStringLiteral("Flags")] = QStringList({QStringLiteral("read"), QStringLiteral("write")}); 0130 charProps[QStringLiteral("Handle")] = QVariant::fromValue(qint16(4)); 0131 charProps[QStringLiteral("MTU")] = QVariant::fromValue(qint16(512)); 0132 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-gatt-characteristic"), charProps); 0133 0134 0135 m_manager = new Manager(); 0136 InitManagerJob *initJob = m_manager->init(); 0137 initJob->exec(); 0138 QVERIFY(!initJob->error()); 0139 0140 for (const AdapterPtr &adapter : m_manager->adapters()) { 0141 QVERIFY(!adapter->ubi().isEmpty()); 0142 0143 for (const DevicePtr &device : adapter->devices()) { 0144 QVERIFY(!device->ubi().isEmpty()); 0145 0146 for (const GattServiceRemotePtr &gattService : device->gattServices()) { 0147 QVERIFY(!gattService->ubi().isEmpty()); 0148 0149 for (const GattCharacteristicRemotePtr &gattCharacteristic : gattService->characteristics()) { 0150 QVERIFY(!gattCharacteristic->ubi().isEmpty()); 0151 0152 GattCharacteristicRemoteUnit u; 0153 u.characteristic = gattCharacteristic; 0154 u.dbusCharacteristic = new org::bluez::GattCharacteristic1(service, gattCharacteristic->ubi(), connection, this); 0155 u.dbusProperties = new org::freedesktop::DBus::Properties(service, gattCharacteristic->ubi(), connection, this); 0156 m_units.append(u); 0157 } 0158 0159 QCOMPARE(gattService->characteristics().count(), 1); 0160 } 0161 0162 QCOMPARE(device->gattServices().count(), 1); 0163 } 0164 } 0165 0166 QCOMPARE(m_manager->adapters().count(), 2); 0167 QCOMPARE(m_manager->devices().count(), 2); 0168 } 0169 0170 void GattCharacteristicRemoteTest::cleanupTestCase() 0171 { 0172 for (const GattCharacteristicRemoteUnit &unit : std::as_const(m_units)) { 0173 delete unit.dbusCharacteristic; 0174 delete unit.dbusProperties; 0175 } 0176 0177 delete m_manager; 0178 0179 FakeBluez::stop(); 0180 } 0181 0182 void GattCharacteristicRemoteTest::getPropertiesTest() 0183 { 0184 for (const GattCharacteristicRemoteUnit &unit : std::as_const(m_units)) { 0185 QCOMPARE(unit.characteristic->ubi(), unit.dbusCharacteristic->path()); 0186 QCOMPARE(unit.characteristic->uuid(), unit.dbusCharacteristic->uUID()); 0187 QCOMPARE(unit.characteristic->service()->ubi(), unit.dbusCharacteristic->service().path()); 0188 QCOMPARE(unit.characteristic->value(), unit.dbusCharacteristic->value()); 0189 QCOMPARE(unit.characteristic->isNotifying(), unit.dbusCharacteristic->notifying()); 0190 QCOMPARE(unit.characteristic->flags(), unit.dbusCharacteristic->flags()); 0191 QCOMPARE(unit.characteristic->handle(), unit.dbusCharacteristic->handle()); 0192 QCOMPARE(unit.characteristic->MTU(), unit.dbusCharacteristic->mTU()); 0193 } 0194 } 0195 0196 void GattCharacteristicRemoteTest::setHandleTest() 0197 { 0198 for (const GattCharacteristicRemoteUnit &unit : std::as_const(m_units)) { 0199 QSignalSpy characteristicSpy(unit.characteristic.data(), SIGNAL(handleChanged(quint16))); 0200 QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList))); 0201 0202 quint16 value = unit.characteristic->handle() + 3; 0203 0204 unit.characteristic->setHandle(value); 0205 QTRY_COMPARE(characteristicSpy.count(), 1); 0206 0207 QList<QVariant> arguments = characteristicSpy.takeFirst(); 0208 QCOMPARE(arguments.at(0).toUInt(), value); 0209 Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Handle"), value); 0210 0211 QCOMPARE(unit.characteristic->handle(), value); 0212 QCOMPARE(unit.dbusCharacteristic->handle(), value); 0213 } 0214 } 0215 0216 void GattCharacteristicRemoteTest::readValueTest() 0217 { 0218 for (const GattCharacteristicRemoteUnit &unit : std::as_const(m_units)) { 0219 QSignalSpy characteristicSpy(unit.characteristic.data(), SIGNAL(valueChanged(const QByteArray))); 0220 QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList))); 0221 0222 0223 // Test initial value 0224 QByteArray value = QByteArray(); 0225 QCOMPARE(unit.characteristic->value(), value); 0226 QCOMPARE(unit.dbusCharacteristic->value(), value); 0227 0228 0229 // Test read 0230 value = QByteArray("TEST"); 0231 unit.characteristic->readValue({}); 0232 QTRY_COMPARE(characteristicSpy.count(), 1); 0233 0234 QList<QVariant> arguments = characteristicSpy.takeFirst(); 0235 QCOMPARE(arguments.at(0).value<QByteArray>(), value); 0236 Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Value"), value); 0237 0238 QCOMPARE(unit.characteristic->value(), value); 0239 QCOMPARE(unit.dbusCharacteristic->value(), value); 0240 } 0241 } 0242 0243 void GattCharacteristicRemoteTest::writeValueTest() 0244 { 0245 for (const GattCharacteristicRemoteUnit &unit : std::as_const(m_units)) { 0246 QSignalSpy characteristicSpy(unit.characteristic.data(), SIGNAL(valueChanged(const QByteArray))); 0247 QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList))); 0248 0249 // Test write 0250 QByteArray value = QByteArray("WRITE"); 0251 unit.characteristic->writeValue(value, {}); 0252 QTRY_COMPARE(characteristicSpy.count(), 1); 0253 0254 QList<QVariant> arguments = characteristicSpy.takeFirst(); 0255 QCOMPARE(arguments.at(0).value<QByteArray>(), value); 0256 Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Value"), value); 0257 0258 QCOMPARE(unit.characteristic->value(), value); 0259 QCOMPARE(unit.dbusCharacteristic->value(), value); 0260 } 0261 } 0262 0263 void GattCharacteristicRemoteTest::startNotifyTest() 0264 { 0265 for (const GattCharacteristicRemoteUnit &unit : std::as_const(m_units)) { 0266 QSignalSpy characteristicSpy(unit.characteristic.data(), SIGNAL(notifyingChanged(bool))); 0267 QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList))); 0268 0269 0270 // Test initial value 0271 bool value = false; 0272 QCOMPARE(unit.characteristic->isNotifying(), value); 0273 QCOMPARE(unit.dbusCharacteristic->notifying(), value); 0274 0275 0276 // Test start notifying 0277 value = true; 0278 unit.characteristic->startNotify(); 0279 QTRY_COMPARE(characteristicSpy.count(), 1); 0280 0281 QList<QVariant> arguments = characteristicSpy.takeFirst(); 0282 QCOMPARE(arguments.at(0).value<bool>(), value); 0283 Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Notifying"), value); 0284 0285 QCOMPARE(unit.characteristic->isNotifying(), value); 0286 QCOMPARE(unit.dbusCharacteristic->notifying(), value); 0287 } 0288 } 0289 0290 void GattCharacteristicRemoteTest::stopNotifyTest() 0291 { 0292 for (const GattCharacteristicRemoteUnit &unit : std::as_const(m_units)) { 0293 QSignalSpy characteristicSpy(unit.characteristic.data(), SIGNAL(notifyingChanged(bool))); 0294 QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList))); 0295 0296 0297 // Test initial value 0298 bool value = true; 0299 QCOMPARE(unit.characteristic->isNotifying(), value); 0300 QCOMPARE(unit.dbusCharacteristic->notifying(), value); 0301 0302 0303 // Test start notifying 0304 value = false; 0305 unit.characteristic->stopNotify(); 0306 QTRY_COMPARE(characteristicSpy.count(), 1); 0307 0308 QList<QVariant> arguments = characteristicSpy.takeFirst(); 0309 QCOMPARE(arguments.at(0).value<bool>(), value); 0310 Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Notifying"), value); 0311 0312 QCOMPARE(unit.characteristic->isNotifying(), value); 0313 QCOMPARE(unit.dbusCharacteristic->notifying(), value); 0314 } 0315 } 0316 0317 void GattCharacteristicRemoteTest::characteristicRemovedTest() 0318 { 0319 for (const GattCharacteristicRemoteUnit &unit : std::as_const(m_units)) { 0320 QSignalSpy serviceSpy(unit.characteristic->service().data(), SIGNAL(gattCharacteristicRemoved(GattCharacteristicRemotePtr))); 0321 0322 QVariantMap properties; 0323 properties[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(unit.characteristic->ubi())); 0324 FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("remove-gatt-characteristic"), properties); 0325 0326 QTRY_COMPARE(serviceSpy.count(), 1); 0327 0328 QCOMPARE(serviceSpy.at(0).at(0).value<GattCharacteristicRemotePtr>(), unit.characteristic); 0329 } 0330 } 0331 0332 QTEST_MAIN(GattCharacteristicRemoteTest) 0333 0334 #include "moc_gattcharacteristicremotetest.cpp"