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"