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