File indexing completed on 2024-04-21 03:51:52

0001 /*
0002  * SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@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 "adaptertest.h"
0008 #include "autotests.h"
0009 #include "device.h"
0010 #include "initmanagerjob.h"
0011 #include "pendingcall.h"
0012 
0013 #include <QSignalSpy>
0014 #include <QTest>
0015 
0016 namespace BluezQt
0017 {
0018 extern void bluezqt_initFakeBluezTestRun();
0019 }
0020 
0021 using namespace BluezQt;
0022 
0023 AdapterTest::AdapterTest()
0024     : m_manager(nullptr)
0025 {
0026     Autotests::registerMetatypes();
0027 }
0028 
0029 void AdapterTest::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 adapter1path = QDBusObjectPath(QStringLiteral("/org/bluez/hci0"));
0041     QVariantMap adapterProps;
0042     adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter1path);
0043     adapterProps[QStringLiteral("Address")] = QStringLiteral("1C:E5:C3:BC:94:7E");
0044     adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter");
0045     adapterProps[QStringLiteral("Alias")] = QStringLiteral("TestAlias");
0046     adapterProps[QStringLiteral("Class")] = QVariant::fromValue(quint32(101));
0047     adapterProps[QStringLiteral("Powered")] = false;
0048     adapterProps[QStringLiteral("Discoverable")] = false;
0049     adapterProps[QStringLiteral("Pairable")] = false;
0050     adapterProps[QStringLiteral("PairableTimeout")] = QVariant::fromValue(quint32(0));
0051     adapterProps[QStringLiteral("DiscoverableTimeout")] = QVariant::fromValue(quint32(0));
0052     adapterProps[QStringLiteral("Discovering")] = false;
0053     adapterProps[QStringLiteral("UUIDs")] = QStringList(QStringLiteral("00001200-0000-1000-8000-00805f9b34fb"));
0054     adapterProps[QStringLiteral("Modalias")] = QStringLiteral("usb:v2D6Bp1236d0215");
0055     FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps);
0056 
0057     QDBusObjectPath adapter2path = QDBusObjectPath(QStringLiteral("/org/bluez/hci1"));
0058     adapterProps[QStringLiteral("Path")] = QVariant::fromValue(adapter2path);
0059     adapterProps[QStringLiteral("Address")] = QStringLiteral("2E:3A:C3:BC:85:7C");
0060     adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter2");
0061     adapterProps[QStringLiteral("Alias")] = QStringLiteral("TestAlias2");
0062     adapterProps[QStringLiteral("Class")] = QVariant::fromValue(quint32(201));
0063     adapterProps[QStringLiteral("Powered")] = true;
0064     adapterProps[QStringLiteral("Discoverable")] = true;
0065     adapterProps[QStringLiteral("Pairable")] = true;
0066     adapterProps[QStringLiteral("PairableTimeout")] = QVariant::fromValue(quint32(150));
0067     adapterProps[QStringLiteral("DiscoverableTimeout")] = QVariant::fromValue(quint32(120));
0068     adapterProps[QStringLiteral("Discovering")] = false;
0069     adapterProps[QStringLiteral("UUIDs")] = QStringList(QStringLiteral("0000110c-0000-1000-8000-00805f9b34fb"));
0070     adapterProps[QStringLiteral("Modalias")] = QStringLiteral("usb:v1D3Bp1134d0214");
0071     FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps);
0072 
0073     // Create devices
0074     QVariantMap deviceProps;
0075     deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci0/dev_40_79_6A_0C_39_75"));
0076     deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(adapter1path);
0077     deviceProps[QStringLiteral("Address")] = QStringLiteral("40:79:6A:0C:39:75");
0078     deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice");
0079     FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps);
0080 
0081     deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath("/org/bluez/hci1/dev_50_79_6A_0C_39_75"));
0082     deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(adapter2path);
0083     deviceProps[QStringLiteral("Address")] = QStringLiteral("50:79:6A:0C:39:75");
0084     deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice2");
0085     FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps);
0086 
0087     m_manager = new Manager();
0088     InitManagerJob *initJob = m_manager->init();
0089     initJob->exec();
0090     QVERIFY(!initJob->error());
0091 
0092     for (AdapterPtr adapter : m_manager->adapters()) {
0093         QVERIFY(!adapter->ubi().isEmpty());
0094 
0095         AdapterUnit u;
0096         u.adapter = adapter;
0097         u.dbusAdapter = new org::bluez::Adapter1(service, adapter->ubi(), connection, this);
0098         u.dbusProperties = new org::freedesktop::DBus::Properties(service, adapter->ubi(), connection, this);
0099         m_units.append(u);
0100     }
0101 
0102     QCOMPARE(m_manager->adapters().count(), 2);
0103 }
0104 
0105 void AdapterTest::cleanupTestCase()
0106 {
0107     for (const AdapterUnit &unit : m_units) {
0108         delete unit.dbusAdapter;
0109         delete unit.dbusProperties;
0110     }
0111 
0112     delete m_manager;
0113 
0114     FakeBluez::stop();
0115 }
0116 
0117 static void compareUuids(const QStringList &actual, const QStringList &expected)
0118 {
0119     QCOMPARE(actual.size(), expected.size());
0120 
0121     for (int i = 0; i < actual.size(); ++i) {
0122         QCOMPARE(actual.at(i).toUpper(), expected.at(i).toUpper());
0123     }
0124 }
0125 
0126 void AdapterTest::getPropertiesTest()
0127 {
0128     for (const AdapterUnit &unit : m_units) {
0129         QCOMPARE(unit.adapter->ubi(), unit.dbusAdapter->path());
0130         QCOMPARE(unit.adapter->address(), unit.dbusAdapter->address());
0131         QCOMPARE(unit.adapter->name(), unit.dbusAdapter->alias());
0132         QCOMPARE(unit.adapter->systemName(), unit.dbusAdapter->name());
0133         QCOMPARE(unit.adapter->adapterClass(), unit.dbusAdapter->adapterClass());
0134         QCOMPARE(unit.adapter->isPowered(), unit.dbusAdapter->powered());
0135         QCOMPARE(unit.adapter->isDiscoverable(), unit.dbusAdapter->discoverable());
0136         QCOMPARE(unit.adapter->discoverableTimeout(), unit.dbusAdapter->discoverableTimeout());
0137         QCOMPARE(unit.adapter->isPairable(), unit.dbusAdapter->pairable());
0138         QCOMPARE(unit.adapter->pairableTimeout(), unit.dbusAdapter->pairableTimeout());
0139         QCOMPARE(unit.adapter->isDiscovering(), unit.dbusAdapter->discovering());
0140         QCOMPARE(unit.adapter->modalias(), unit.dbusAdapter->modalias());
0141 
0142         compareUuids(unit.adapter->uuids(), unit.dbusAdapter->uUIDs());
0143     }
0144 }
0145 
0146 void AdapterTest::setAliasTest()
0147 {
0148     for (const AdapterUnit &unit : m_units) {
0149         QSignalSpy adapterSpy(unit.adapter.data(), SIGNAL(nameChanged(QString)));
0150         QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
0151 
0152         QString value = unit.adapter->name() + QLatin1String("_tst_alias");
0153 
0154         unit.adapter->setName(value);
0155         QTRY_COMPARE(adapterSpy.count(), 1);
0156 
0157         QList<QVariant> adapterArguments = adapterSpy.takeFirst();
0158         QCOMPARE(adapterArguments.at(0).toString(), value);
0159         Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Alias"), value);
0160 
0161         QCOMPARE(unit.adapter->name(), value);
0162         QCOMPARE(unit.dbusAdapter->alias(), value);
0163     }
0164 }
0165 
0166 void AdapterTest::setPoweredTest()
0167 {
0168     for (const AdapterUnit &unit : m_units) {
0169         QSignalSpy adapterSpy(unit.adapter.data(), SIGNAL(poweredChanged(bool)));
0170         QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
0171 
0172         bool value = !unit.adapter->isPowered();
0173 
0174         unit.adapter->setPowered(value);
0175         QTRY_COMPARE(adapterSpy.count(), 1);
0176 
0177         QVERIFY(dbusSpy.count() >= 1);
0178         Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Powered"), value);
0179 
0180         QList<QVariant> adapterArguments = adapterSpy.takeFirst();
0181         QCOMPARE(adapterArguments.at(0).toBool(), value);
0182 
0183         QCOMPARE(unit.adapter->isPowered(), value);
0184         QCOMPARE(unit.dbusAdapter->powered(), value);
0185     }
0186 }
0187 
0188 void AdapterTest::setDiscoverableTest()
0189 {
0190     // Discoverable cannot be changed when Adapter is off
0191 
0192     for (const AdapterUnit &unit : m_units) {
0193         unit.adapter->setPowered(true)->waitForFinished();
0194 
0195         QSignalSpy adapterSpy(unit.adapter.data(), SIGNAL(discoverableChanged(bool)));
0196         QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
0197 
0198         bool value = !unit.adapter->isDiscoverable();
0199 
0200         unit.adapter->setDiscoverable(value);
0201         QTRY_COMPARE(adapterSpy.count(), 1);
0202 
0203         QList<QVariant> adapterArguments = adapterSpy.takeFirst();
0204         QCOMPARE(adapterArguments.at(0).toBool(), value);
0205         Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Discoverable"), value);
0206 
0207         QCOMPARE(unit.adapter->isDiscoverable(), value);
0208         QCOMPARE(unit.dbusAdapter->discoverable(), value);
0209     }
0210 }
0211 
0212 void AdapterTest::setDiscoverableTimeoutTest()
0213 {
0214     for (const AdapterUnit &unit : m_units) {
0215         QSignalSpy adapterSpy(unit.adapter.data(), SIGNAL(discoverableTimeoutChanged(quint32)));
0216         QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
0217 
0218         quint32 value = unit.adapter->discoverableTimeout() + 1;
0219 
0220         unit.adapter->setDiscoverableTimeout(value);
0221         QTRY_COMPARE(adapterSpy.count(), 1);
0222 
0223         QVERIFY(dbusSpy.count() >= 1);
0224         Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("DiscoverableTimeout"), value);
0225 
0226         QList<QVariant> adapterArguments = adapterSpy.takeFirst();
0227         QCOMPARE(adapterArguments.at(0).toUInt(), value);
0228 
0229         QCOMPARE(unit.adapter->discoverableTimeout(), value);
0230         QCOMPARE(unit.dbusAdapter->discoverableTimeout(), value);
0231     }
0232 }
0233 
0234 void AdapterTest::setPairableTest()
0235 {
0236     for (const AdapterUnit &unit : m_units) {
0237         QSignalSpy adapterSpy(unit.adapter.data(), SIGNAL(pairableChanged(bool)));
0238         QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
0239 
0240         bool value = !unit.adapter->isPairable();
0241 
0242         unit.adapter->setPairable(value);
0243         QTRY_COMPARE(adapterSpy.count(), 1);
0244 
0245         QList<QVariant> adapterArguments = adapterSpy.takeFirst();
0246         QCOMPARE(adapterArguments.at(0).toBool(), value);
0247         Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Pairable"), value);
0248 
0249         QCOMPARE(unit.adapter->isPairable(), value);
0250         QCOMPARE(unit.dbusAdapter->pairable(), value);
0251     }
0252 }
0253 
0254 void AdapterTest::setPairableTimeoutTest()
0255 {
0256     for (const AdapterUnit &unit : m_units) {
0257         QSignalSpy adapterSpy(unit.adapter.data(), SIGNAL(pairableTimeoutChanged(quint32)));
0258         QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
0259 
0260         quint32 value = unit.adapter->pairableTimeout() + 1;
0261 
0262         unit.adapter->setPairableTimeout(value);
0263         QTRY_COMPARE(adapterSpy.count(), 1);
0264 
0265         QVERIFY(dbusSpy.count() >= 1);
0266         Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("PairableTimeout"), value);
0267 
0268         QList<QVariant> adapterArguments = adapterSpy.takeFirst();
0269         QCOMPARE(adapterArguments.at(0).toUInt(), value);
0270 
0271         QCOMPARE(unit.adapter->pairableTimeout(), value);
0272         QCOMPARE(unit.dbusAdapter->pairableTimeout(), value);
0273     }
0274 }
0275 
0276 void AdapterTest::discoveryTest()
0277 {
0278     // Discovery needs Adapter powered on
0279 
0280     for (const AdapterUnit &unit : m_units) {
0281         // Make sure the Adapter is powered on and not discovering
0282         unit.adapter->setPowered(true)->waitForFinished();
0283         if (unit.adapter->isDiscovering()) {
0284             unit.adapter->stopDiscovery()->waitForFinished();
0285         }
0286 
0287         QSignalSpy adapterSpy(unit.adapter.data(), SIGNAL(discoveringChanged(bool)));
0288         QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
0289 
0290         // Start Discovery
0291         unit.adapter->startDiscovery();
0292         QTRY_COMPARE(adapterSpy.count(), 1);
0293 
0294         QVERIFY(dbusSpy.count() >= 1);
0295         Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Discovering"), true);
0296 
0297         QList<QVariant> adapterArguments = adapterSpy.takeFirst();
0298         QCOMPARE(adapterArguments.at(0).toBool(), true);
0299 
0300         QCOMPARE(unit.adapter->isDiscovering(), true);
0301         QCOMPARE(unit.dbusAdapter->discovering(), true);
0302 
0303         adapterSpy.clear();
0304         dbusSpy.clear();
0305 
0306         // Stop Discovery
0307         unit.adapter->stopDiscovery();
0308         QTRY_COMPARE(adapterSpy.count(), 1);
0309 
0310         QVERIFY(dbusSpy.count() >= 1);
0311         Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Discovering"), false);
0312 
0313         adapterArguments = adapterSpy.takeFirst();
0314         QCOMPARE(adapterArguments.at(0).toBool(), false);
0315 
0316         QCOMPARE(unit.adapter->isDiscovering(), false);
0317         QCOMPARE(unit.dbusAdapter->discovering(), false);
0318     }
0319 }
0320 
0321 void AdapterTest::removeDeviceTest()
0322 {
0323     for (const AdapterUnit &unit : m_units) {
0324         while (!unit.adapter->devices().isEmpty()) {
0325             DevicePtr device = unit.adapter->devices().first();
0326 
0327             QSignalSpy managerSpy(m_manager, SIGNAL(deviceRemoved(DevicePtr)));
0328             QSignalSpy adapterSpy(unit.adapter.data(), SIGNAL(deviceRemoved(DevicePtr)));
0329             QSignalSpy deviceSpy(device.data(), SIGNAL(deviceRemoved(DevicePtr)));
0330 
0331             unit.adapter->removeDevice(device);
0332 
0333             QTRY_COMPARE(managerSpy.count(), 1);
0334             QTRY_COMPARE(adapterSpy.count(), 1);
0335             QTRY_COMPARE(deviceSpy.count(), 1);
0336 
0337             QCOMPARE(managerSpy.at(0).at(0).value<DevicePtr>(), device);
0338             QCOMPARE(adapterSpy.at(0).at(0).value<DevicePtr>(), device);
0339             QCOMPARE(deviceSpy.at(0).at(0).value<DevicePtr>(), device);
0340         }
0341     }
0342 }
0343 
0344 static bool isFilterValid(const QStringList &filters, const QVariantMap &filter)
0345 {
0346     auto i = filter.constBegin();
0347     while (i != filter.constEnd()) {
0348         if (!filters.contains(i.key())) {
0349             return false;
0350         }
0351         i++;
0352     }
0353     return true;
0354 }
0355 
0356 void AdapterTest::discoveryFilterTest_data() {
0357     QTest::addColumn<QVariantMap>("filter");
0358     QTest::addColumn<bool>("isValid");
0359     QTest::addColumn<bool>("shouldBeDiscoverable");
0360 
0361 
0362     QTest::newRow("valid-non-discoverable") << QVariantMap({
0363         { QStringLiteral("UUIDs"), QStringList() },
0364         { QStringLiteral("RSSI"), QVariant::fromValue(qint16(-100)) },
0365         { QStringLiteral("Transport"), QStringLiteral("auto") },
0366         { QStringLiteral("DuplicateData"), true },
0367         { QStringLiteral("Discoverable"), false },
0368         { QStringLiteral("Pattern"), QLatin1String("")}
0369     }) << true << false;
0370 
0371     QTest::newRow("valid-discoverable") << QVariantMap({
0372         { QStringLiteral("UUIDs"), QStringList() },
0373         { QStringLiteral("RSSI"), QVariant::fromValue(qint16(-100)) },
0374         { QStringLiteral("Transport"), QStringLiteral("auto") },
0375         { QStringLiteral("DuplicateData"), true },
0376         { QStringLiteral("Discoverable"), true },
0377         { QStringLiteral("Pattern"), QLatin1String("")}
0378     }) << true << true;
0379 
0380     QTest::newRow("invalid") << QVariantMap({
0381         { QStringLiteral("SomeKey"), QStringList() }
0382     }) << false << false;
0383 }
0384 
0385 void AdapterTest::discoveryFilterTest()
0386 {
0387     QFETCH(QVariantMap, filter);
0388     QFETCH(bool, isValid);
0389     QFETCH(bool, shouldBeDiscoverable);
0390 
0391     for (const AdapterUnit &unit : m_units) {
0392 
0393         // Get available discovery filters
0394         PendingCall* p = unit.adapter->getDiscoveryFilters(); p->waitForFinished();
0395         Q_ASSERT(p->isFinished());
0396         QCOMPARE(p->error(), PendingCall::NoError);
0397         const QStringList filters = p->value().toStringList();
0398 
0399         // Verify filter
0400         QCOMPARE(isFilterValid(filters, filter), isValid);
0401 
0402         // Make sure adapter is powered and not discoverable
0403         unit.adapter->setPowered(true)->waitForFinished();
0404         unit.adapter->setDiscoverable(false);
0405         QTRY_COMPARE(unit.adapter->isDiscoverable(), false);
0406         QTRY_COMPARE(unit.dbusAdapter->discoverable(), false);
0407 
0408         QSignalSpy adapterSpy(unit.adapter.data(), SIGNAL(discoverableChanged(bool)));
0409         QSignalSpy dbusSpy(unit.dbusProperties, SIGNAL(PropertiesChanged(QString, QVariantMap, QStringList)));
0410 
0411         // Set discovery filter
0412         unit.adapter->setDiscoveryFilter(filter);
0413 
0414         if (shouldBeDiscoverable) {
0415             // Check if adapter became discoverable
0416             QTRY_COMPARE(adapterSpy.count(), 1);
0417 
0418             const QList<QVariant> adapterArguments = adapterSpy.takeFirst();
0419             QCOMPARE(adapterArguments.at(0).toBool(), true);
0420             Autotests::verifyPropertiesChangedSignal(dbusSpy, QStringLiteral("Discoverable"), true);
0421 
0422             QCOMPARE(unit.adapter->isDiscoverable(), true);
0423             QCOMPARE(unit.dbusAdapter->discoverable(), true);
0424         }
0425     }
0426 }
0427 
0428 void AdapterTest::adapterRemovedTest()
0429 {
0430     for (const AdapterUnit &unit : m_units) {
0431         QSignalSpy managerSpy(m_manager, SIGNAL(adapterRemoved(AdapterPtr)));
0432         QSignalSpy adapterSpy(unit.adapter.data(), SIGNAL(adapterRemoved(AdapterPtr)));
0433 
0434         QVariantMap properties;
0435         properties[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(unit.adapter->ubi()));
0436         FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("remove-adapter"), properties);
0437 
0438         QTRY_COMPARE(managerSpy.count(), 1);
0439         QTRY_COMPARE(adapterSpy.count(), 1);
0440 
0441         QCOMPARE(managerSpy.at(0).at(0).value<AdapterPtr>(), unit.adapter);
0442         QCOMPARE(adapterSpy.at(0).at(0).value<AdapterPtr>(), unit.adapter);
0443     }
0444 }
0445 
0446 QTEST_MAIN(AdapterTest)
0447 
0448 #include "moc_adaptertest.cpp"