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"