diff options
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp | 120 |
1 files changed, 98 insertions, 22 deletions
diff --git a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp index 58510952..1d1997e0 100644 --- a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp +++ b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp @@ -29,6 +29,9 @@ #include <QtTest/QtTest> #include <private/qtbluetoothglobal_p.h> +#if QT_CONFIG(bluez) +#include <QtBluetooth/private/bluez5_helper_p.h> +#endif #include <QBluetoothAddress> #include <QBluetoothLocalDevice> #include <QBluetoothDeviceDiscoveryAgent> @@ -58,7 +61,10 @@ QT_USE_NAMESPACE #endif #ifdef HANDLES_PROVIDED_BY_PLATFORM -#define HANDLE_COMPARE(actual,expected) QCOMPARE(actual,expected) +#define HANDLE_COMPARE(actual,expected) \ + if (!isBluezDbusLE) {\ + QCOMPARE(actual, expected);\ + }; #else #define HANDLE_COMPARE(actual,expected) #endif @@ -91,6 +97,7 @@ private: QBluetoothAddress remoteDevice; QBluetoothDeviceInfo remoteDeviceInfo; QList<QBluetoothUuid> foundServices; + bool isBluezDbusLE = false; }; tst_QLowEnergyController::tst_QLowEnergyController() @@ -107,6 +114,12 @@ tst_QLowEnergyController::tst_QLowEnergyController() qWarning() << "Not using any remote device for testing. Set BT_TEST_DEVICE env to run manual tests involving a remote device"; } #endif + +#if QT_CONFIG(bluez) + // This debug is needed to determine runtime configuration in the Qt CI. + isBluezDbusLE = (bluetoothdVersion() >= QVersionNumber(5, 42)); + qDebug() << "isDBusBluez:" << isBluezDbusLE; +#endif } tst_QLowEnergyController::~tst_QLowEnergyController() @@ -135,6 +148,7 @@ void tst_QLowEnergyController::initTestCase() #endif devAgent = new QBluetoothDeviceDiscoveryAgent(this); + devAgent->setLowEnergyDiscoveryTimeout(5000); QSignalSpy finishedSpy(devAgent, SIGNAL(finished())); // there should be no changes yet @@ -163,7 +177,8 @@ void tst_QLowEnergyController::initTestCase() // These are the services exported by the TI SensorTag #ifndef Q_OS_MAC // Core Bluetooth somehow ignores/hides/fails to discover these services. - foundServices << QBluetoothUuid(QString("00001800-0000-1000-8000-00805f9b34fb")); + if (!isBluezDbusLE) // Bluez LE Dbus intentionally hides 0x1800 service + foundServices << QBluetoothUuid(QString("00001800-0000-1000-8000-00805f9b34fb")); foundServices << QBluetoothUuid(QString("00001801-0000-1000-8000-00805f9b34fb")); #endif foundServices << QBluetoothUuid(QString("0000180a-0000-1000-8000-00805f9b34fb")); @@ -449,9 +464,38 @@ void tst_QLowEnergyController::tst_concurrentDiscovery() QCOMPARE(control.state(), QLowEnergyController::ConnectedState); QCOMPARE(control2.state(), QLowEnergyController::UnconnectedState); #else - // see QTBUG-42519 - // Linux cannot maintain two controller connections at the same time - QVERIFY(control2.error() != QLowEnergyController::NoError); + if (!isBluezDbusLE) { + // see QTBUG-42519 + // Linux non-DBus GATT cannot maintain two controller connections at the same time + QCOMPARE(control.state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control2.state(), QLowEnergyController::ConnectedState); + control2.disconnectFromDevice(); + QTRY_COMPARE(control2.state(), QLowEnergyController::UnconnectedState); + QTRY_COMPARE(control2.error(), QLowEnergyController::NoError); + + // reconnect control + control.connectToDevice(); + { + QTRY_VERIFY_WITH_TIMEOUT(control.state() != QLowEnergyController::ConnectingState, + 30000); + } + QCOMPARE(control.state(), QLowEnergyController::ConnectedState); + } else { + QCOMPARE(control.state(), QLowEnergyController::ConnectedState); + QCOMPARE(control2.state(), QLowEnergyController::ConnectedState); + control2.disconnectFromDevice(); + QTRY_COMPARE(control2.state(), QLowEnergyController::UnconnectedState); + QTRY_COMPARE(control2.error(), QLowEnergyController::NoError); + QTRY_COMPARE(control.state(), QLowEnergyController::UnconnectedState); + + // reconnect control + control.connectToDevice(); + { + QTRY_VERIFY_WITH_TIMEOUT(control.state() != QLowEnergyController::ConnectingState, + 30000); + } + QCOMPARE(control.state(), QLowEnergyController::ConnectedState); + } #endif } @@ -1981,12 +2025,30 @@ void tst_QLowEnergyController::tst_readWriteDescriptor() QVERIFY(notification == signalDesc); descWrittenSpy.clear(); + // The series of wait calls below is required because toggling CCC via the notifying + // property consistently crashes BlueZ 5.47. BlueZ 5.48 does not crash but + // an error is thrown. For details see QTBUG-65729 + if (isBluezDbusLE) + QTest::qWait(1000); + // test concurrent writeRequests // they need to be queued up service->writeDescriptor(notification,QByteArray::fromHex("0100")); + if (isBluezDbusLE) + QTest::qWait(1000); + service->writeDescriptor(notification, QByteArray::fromHex("0000")); + if (isBluezDbusLE) + QTest::qWait(1000); + service->writeDescriptor(notification, QByteArray::fromHex("0100")); + if (isBluezDbusLE) + QTest::qWait(1000); + service->writeDescriptor(notification, QByteArray::fromHex("0000")); + if (isBluezDbusLE) + QTest::qWait(1000); + QTRY_VERIFY_WITH_TIMEOUT(descWrittenSpy.count() == 4, 10000); QCOMPARE(notification.value(), QByteArray::fromHex("0000")); @@ -2520,10 +2582,14 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() QVERIFY(imageBlockChar.isValid()); // 2. Get "Image Identity" notification descriptor - const QLowEnergyDescriptor notification = imageIdentityChar.descriptor( + const QLowEnergyDescriptor identityNotification = imageIdentityChar.descriptor( + QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); + const QLowEnergyDescriptor blockNotification = imageBlockChar.descriptor( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); - if (!notification.isValid() || !imageIdentityChar.isValid()) { + if (!identityNotification.isValid() + || !blockNotification.isValid() + || !imageIdentityChar.isValid()) { delete service; control.disconnectFromDevice(); QSKIP("Cannot find OAD char/notification"); @@ -2541,19 +2607,28 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() QSignalSpy errorSpy(service, SIGNAL(error(QLowEnergyService::ServiceError))); + //enable notifications on both characteristics + if (identityNotification.value() != QByteArray::fromHex("0100")) { + service->writeDescriptor(identityNotification, QByteArray::fromHex("0100")); + QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000); + QCOMPARE(identityNotification.value(), QByteArray::fromHex("0100")); + QList<QVariant> firstSignalData = descWrittenSpy.first(); + QLowEnergyDescriptor signalDesc = firstSignalData[0].value<QLowEnergyDescriptor>(); + QByteArray signalValue = firstSignalData[1].toByteArray(); + QCOMPARE(signalValue, QByteArray::fromHex("0100")); + QVERIFY(identityNotification == signalDesc); + descWrittenSpy.clear(); + } - // by default the device enables the notification bit already - // no need to enable it. If notifications fail to arrive the - // platform must check default enabled notifications. - if (notification.value() != QByteArray::fromHex("0100")) { - service->writeDescriptor(notification, QByteArray::fromHex("0100")); + if (blockNotification.value() != QByteArray::fromHex("0100")) { + service->writeDescriptor(blockNotification, QByteArray::fromHex("0100")); QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000); - QCOMPARE(notification.value(), QByteArray::fromHex("0100")); + QCOMPARE(blockNotification.value(), QByteArray::fromHex("0100")); QList<QVariant> firstSignalData = descWrittenSpy.first(); QLowEnergyDescriptor signalDesc = firstSignalData[0].value<QLowEnergyDescriptor>(); QByteArray signalValue = firstSignalData[1].toByteArray(); QCOMPARE(signalValue, QByteArray::fromHex("0100")); - QVERIFY(notification == signalDesc); + QVERIFY(blockNotification == signalDesc); descWrittenSpy.clear(); } @@ -2577,8 +2652,8 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() // Write triggers a notification and write confirmation service->writeCharacteristic(imageIdentityChar, QByteArray::fromHex("0")); QTest::qWait(1000); - QTRY_VERIFY_WITH_TIMEOUT(charChangedSpy.count() == 1, 5000); - QTRY_VERIFY_WITH_TIMEOUT(charWrittenSpy.count() == 1, 5000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.count(), 1, 5000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.count(), 1, 5000); // This is very SensorTag specific logic. // If the image block is empty the current firmware @@ -2592,8 +2667,7 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() QCOMPARE(imageIdentityChar, first); foundOneImage = true; } else { - // we received a notification for imageBlockChar without explicitly - // enabling them. This is caused by the device's default settings. + // we received a notification for imageBlockChar QCOMPARE(imageBlockChar, first); qWarning() << "Invalid image A ident info"; } @@ -2614,8 +2688,8 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() // Image B service->writeCharacteristic(imageIdentityChar, QByteArray::fromHex("1")); QTest::qWait(1000); - QTRY_VERIFY_WITH_TIMEOUT(charChangedSpy.count() == 1, 5000); - QTRY_VERIFY_WITH_TIMEOUT(charWrittenSpy.count() == 1, 5000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.count(), 1, 5000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.count(), 1, 5000);; entry = charChangedSpy[0]; first = entry[0].value<QLowEnergyCharacteristic>(); @@ -2660,7 +2734,8 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() // we only expect one signal (the notification but not the write confirmation) // Wait at least a second for a potential second signals QTest::qWait(1000); - QTRY_VERIFY_WITH_TIMEOUT(charChangedSpy.count() == 1, 10000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.count(), 1, 10000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.count(), 0, 10000); entry = charChangedSpy[0]; first = entry[0].value<QLowEnergyCharacteristic>(); @@ -2695,7 +2770,8 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() // we only expect one signal (the notification but not the write confirmation) // Wait at least a second for a potential second signals QTest::qWait(1000); - QTRY_VERIFY_WITH_TIMEOUT(charChangedSpy.count() == 1, 10000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.count(), 0, 10000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.count(), 1, 10000); entry = charChangedSpy[0]; first = entry[0].value<QLowEnergyCharacteristic>(); |