File indexing completed on 2023-09-24 11:37:32

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