File indexing completed on 2024-04-21 14:52: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 "gattdescriptorremotetest.h"
0008 #include "autotests.h"
0009 #include "initmanagerjob.h"
0010 #include "pendingcall.h"
0011 #include "gattserviceremote.h"
0012 #include "gattcharacteristicremote.h"
0013 
0014 #include <QSignalSpy>
0015 #include <QTest>
0016 #include <QDebug>
0017 
0018 namespace BluezQt
0019 {
0020 extern void bluezqt_initFakeBluezTestRun();
0021 }
0022 
0023 using namespace BluezQt;
0024 
0025 GattDescriptorRemoteTest::GattDescriptorRemoteTest()
0026     : m_manager(nullptr)
0027 {
0028     Autotests::registerMetatypes();
0029     qRegisterMetaType<BluezQt::GattDescriptorRemotePtr>("GattDescriptorRemotePtr");
0030 }
0031 
0032 void GattDescriptorRemoteTest::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     // Create descriptors
0135     QVariantMap descrProps;
0136     descrProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75/service0/char0/descriptor0"));
0137     descrProps[QStringLiteral("UUID")] = QStringLiteral("04FA28C0-2D0C-11EC-8D3D-0242AC130005");
0138     descrProps[QStringLiteral("Characteristic")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75/service0/char0"));
0139     descrProps[QStringLiteral("Value")] = QVariant::fromValue(QByteArray());
0140     descrProps[QStringLiteral("Flags")] = QStringList({QStringLiteral("read"), QStringLiteral("write")});
0141     descrProps[QStringLiteral("Handle")] = QVariant::fromValue(qint16(5));
0142     FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-gatt-descriptor"), descrProps);
0143 
0144     descrProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_50_79_6A_0C_39_75/service0/char0/descriptor0"));
0145     descrProps[QStringLiteral("UUID")] = QStringLiteral("0663A394-9A76-4361-9DE6-82577B82AC9C");
0146     descrProps[QStringLiteral("Characteristic")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_50_79_6A_0C_39_75/service0/char0"));
0147     descrProps[QStringLiteral("Value")] = QVariant::fromValue(QByteArray());
0148     descrProps[QStringLiteral("Flags")] = QStringList({QStringLiteral("read"), QStringLiteral("write")});
0149     descrProps[QStringLiteral("Handle")] = QVariant::fromValue(qint16(6));
0150     FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-gatt-descriptor"), descrProps);
0151 
0152 
0153     m_manager = new Manager();
0154     InitManagerJob *initJob = m_manager->init();
0155     initJob->exec();
0156     QVERIFY(!initJob->error());
0157 
0158     for (const AdapterPtr &adapter : m_manager->adapters()) {
0159         QVERIFY(!adapter->ubi().isEmpty());
0160 
0161         for (const DevicePtr &device : adapter->devices()) {
0162             QVERIFY(!device->ubi().isEmpty());
0163 
0164             for (const GattServiceRemotePtr &gattService : device->gattServices()) {
0165                 QVERIFY(!gattService->ubi().isEmpty());
0166 
0167                 for (const GattCharacteristicRemotePtr &gattCharacteristic : gattService->characteristics()) {
0168                     QVERIFY(!gattCharacteristic->ubi().isEmpty());
0169 
0170                     for (const GattDescriptorRemotePtr &gattDescriptor : gattCharacteristic->descriptors()) {
0171                         QVERIFY(!gattDescriptor->ubi().isEmpty());
0172 
0173                         GattDescriptorRemoteUnit u;
0174                         u.descriptor = gattDescriptor;
0175                         u.dbusDescriptor = new org::bluez::GattDescriptor1(service, gattDescriptor->ubi(), connection, this);
0176                         u.dbusProperties = new org::freedesktop::DBus::Properties(service, gattDescriptor->ubi(), connection, this);
0177                         m_units.append(u);
0178                     }
0179 
0180                     QCOMPARE(gattCharacteristic->descriptors().count(), 1);
0181                 }
0182 
0183                 QCOMPARE(gattService->characteristics().count(), 1);
0184             }
0185 
0186             QCOMPARE(device->gattServices().count(), 1);
0187         }
0188     }
0189 
0190     QCOMPARE(m_manager->adapters().count(), 2);
0191     QCOMPARE(m_manager->devices().count(), 2);
0192 }
0193 
0194 void GattDescriptorRemoteTest::cleanupTestCase()
0195 {
0196     for (const GattDescriptorRemoteUnit &unit : std::as_const(m_units)) {
0197         delete unit.dbusDescriptor;
0198         delete unit.dbusProperties;
0199     }
0200 
0201     delete m_manager;
0202 
0203     FakeBluez::stop();
0204 }
0205 
0206 void GattDescriptorRemoteTest::getPropertiesTest()
0207 {
0208     for (const GattDescriptorRemoteUnit &unit : std::as_const(m_units)) {
0209         QCOMPARE(unit.descriptor->ubi(), unit.dbusDescriptor->path());
0210         QCOMPARE(unit.descriptor->uuid(), unit.dbusDescriptor->uUID());
0211         QCOMPARE(unit.descriptor->characteristic()->ubi(), unit.dbusDescriptor->characteristic().path());
0212         QCOMPARE(unit.descriptor->value(), unit.dbusDescriptor->value());
0213         QCOMPARE(unit.descriptor->flags(), unit.dbusDescriptor->flags());
0214         QCOMPARE(unit.descriptor->handle(), unit.dbusDescriptor->handle());
0215     }
0216 }
0217 
0218 void GattDescriptorRemoteTest::setHandleTest()
0219 {
0220     for (const GattDescriptorRemoteUnit &unit : std::as_const(m_units)) {
0221         QSignalSpy descriptorSpy(unit.descriptor.data(), SIGNAL(handleChanged(quint16)));
0222         QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
0223 
0224         quint16 value = unit.descriptor->handle() + 3;
0225 
0226         unit.descriptor->setHandle(value);
0227         QTRY_COMPARE(descriptorSpy.count(), 1);
0228 
0229         QList<QVariant> arguments = descriptorSpy.takeFirst();
0230         QCOMPARE(arguments.at(0).toUInt(), value);
0231         Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Handle"), value);
0232 
0233         QCOMPARE(unit.descriptor->handle(), value);
0234         QCOMPARE(unit.dbusDescriptor->handle(), value);
0235     }
0236 }
0237 
0238 void GattDescriptorRemoteTest::readValueTest()
0239 {
0240     for (const GattDescriptorRemoteUnit &unit : std::as_const(m_units)) {
0241         QSignalSpy descriptorSpy(unit.descriptor.data(), SIGNAL(valueChanged(const QByteArray)));
0242         QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
0243 
0244 
0245         // Test initial value
0246         QByteArray value = QByteArray();
0247         QCOMPARE(unit.descriptor->value(), value);
0248         QCOMPARE(unit.dbusDescriptor->value(), value);
0249 
0250 
0251         // Test read
0252         value = QByteArray("TEST");
0253         unit.descriptor->readValue({});
0254         QTRY_COMPARE(descriptorSpy.count(), 1);
0255 
0256         QList<QVariant> arguments = descriptorSpy.takeFirst();
0257         QCOMPARE(arguments.at(0).value<QByteArray>(), value);
0258         Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Value"), value);
0259 
0260         QCOMPARE(unit.descriptor->value(), value);
0261         QCOMPARE(unit.dbusDescriptor->value(), value);
0262     }
0263 }
0264 
0265 void GattDescriptorRemoteTest::writeValueTest()
0266 {
0267     for (const GattDescriptorRemoteUnit &unit : std::as_const(m_units)) {
0268         QSignalSpy descriptorSpy(unit.descriptor.data(), SIGNAL(valueChanged(const QByteArray)));
0269         QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
0270 
0271         // Test write
0272         QByteArray value = QByteArray("WRITE");
0273         unit.descriptor->writeValue(value, {});
0274         QTRY_COMPARE(descriptorSpy.count(), 1);
0275 
0276         QList<QVariant> arguments = descriptorSpy.takeFirst();
0277         QCOMPARE(arguments.at(0).value<QByteArray>(), value);
0278         Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Value"), value);
0279 
0280         QCOMPARE(unit.descriptor->value(), value);
0281         QCOMPARE(unit.dbusDescriptor->value(), value);
0282     }
0283 }
0284 
0285 void GattDescriptorRemoteTest::descriptorRemovedTest()
0286 {
0287     for (const GattDescriptorRemoteUnit &unit : std::as_const(m_units)) {
0288         QSignalSpy characteristicSpy(unit.descriptor->characteristic().data(), SIGNAL(gattDescriptorRemoved(GattDescriptorRemotePtr)));
0289 
0290         QVariantMap properties;
0291         properties[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(unit.descriptor->ubi()));
0292         FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("remove-gatt-descriptor"), properties);
0293 
0294         QTRY_COMPARE(characteristicSpy.count(), 1);
0295 
0296         QCOMPARE(characteristicSpy.at(0).at(0).value<GattDescriptorRemotePtr>(), unit.descriptor);
0297     }
0298 }
0299 
0300 QTEST_MAIN(GattDescriptorRemoteTest)
0301 
0302 #include "moc_gattdescriptorremotetest.cpp"