diff options
Diffstat (limited to 'tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp')
-rw-r--r-- | tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp | 834 |
1 files changed, 714 insertions, 120 deletions
diff --git a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp index 3cb57e3f..5faf5fee 100644 --- a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp +++ b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** @@ -10,9 +10,9 @@ ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -23,8 +23,8 @@ ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ @@ -53,6 +53,19 @@ QT_USE_NAMESPACE +// This define must be set if the platform provides access to GATT handles +// otherwise it must not be defined. As of now the two supported platforms +// (Android and Bluez/Linux) provide access or some notion of it. +#ifndef Q_OS_MAC +#define HANDLES_PROVIDED_BY_PLATFORM +#endif + +#ifdef HANDLES_PROVIDED_BY_PLATFORM +#define HANDLE_COMPARE(actual,expected) QCOMPARE(actual,expected) +#else +#define HANDLE_COMPARE(actual,expected) +#endif + class tst_QLowEnergyController : public QObject { Q_OBJECT @@ -63,6 +76,7 @@ public: private slots: void initTestCase(); + void init(); void cleanupTestCase(); void tst_emptyCtor(); void tst_connect(); @@ -70,19 +84,20 @@ private slots: void tst_defaultBehavior(); void tst_writeCharacteristic(); void tst_writeCharacteristicNoResponse(); - void tst_writeDescriptor(); - void tst_encryption(); + void tst_readWriteDescriptor(); + void tst_customProgrammableDevice(); + void tst_errorCases(); private: void verifyServiceProperties(const QLowEnergyService *info); QBluetoothDeviceDiscoveryAgent *devAgent; QBluetoothAddress remoteDevice; + QBluetoothDeviceInfo remoteDeviceInfo; QList<QBluetoothUuid> foundServices; }; Q_DECLARE_METATYPE(QLowEnergyCharacteristic) Q_DECLARE_METATYPE(QLowEnergyDescriptor) -Q_DECLARE_METATYPE(QLowEnergyService::ServiceError) tst_QLowEnergyController::tst_QLowEnergyController() { @@ -90,6 +105,9 @@ tst_QLowEnergyController::tst_QLowEnergyController() qRegisterMetaType<QLowEnergyDescriptor>(); //QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); +#ifndef Q_OS_MAC + // Core Bluetooth (OS X and iOS) does not work with addresses, + // making the code below useless. const QString remote = qgetenv("BT_TEST_DEVICE"); if (!remote.isEmpty()) { remoteDevice = QBluetoothAddress(remote); @@ -97,6 +115,7 @@ tst_QLowEnergyController::tst_QLowEnergyController() } else { qWarning() << "Not using any remote device for testing. Set BT_TEST_DEVICE env to run manual tests involving a remote device"; } +#endif } tst_QLowEnergyController::~tst_QLowEnergyController() @@ -106,12 +125,19 @@ tst_QLowEnergyController::~tst_QLowEnergyController() void tst_QLowEnergyController::initTestCase() { +#ifndef Q_OS_MAC if (remoteDevice.isNull() || QBluetoothLocalDevice::allDevices().isEmpty()) { qWarning("No remote device or local adapter found."); return; } - +#elif defined(Q_OS_OSX) + // allDevices is always empty on iOS: + if (QBluetoothLocalDevice::allDevices().isEmpty()) { + qWarning("No local adapter found."); + return; + } +#endif devAgent = new QBluetoothDeviceDiscoveryAgent(this); @@ -124,7 +150,14 @@ void tst_QLowEnergyController::initTestCase() devAgent->start(); QTRY_VERIFY_WITH_TIMEOUT(finishedSpy.count() > 0, 30000); foreach (const QBluetoothDeviceInfo &info, devAgent->discoveredDevices()) { +#ifndef Q_OS_MAC if (info.address() == remoteDevice) { +#else + // On OS X/iOS the only way to find the device we are + // interested in - is to use device's name. + if (info.name().contains("Sensor") && info.name().contains("Tag")) { + remoteDeviceInfo = info; +#endif deviceFound = true; break; } @@ -133,8 +166,11 @@ void tst_QLowEnergyController::initTestCase() QVERIFY2(deviceFound, "Cannot find remote device."); // 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")); foundServices << QBluetoothUuid(QString("00001801-0000-1000-8000-00805f9b34fb")); +#endif foundServices << QBluetoothUuid(QString("0000180a-0000-1000-8000-00805f9b34fb")); foundServices << QBluetoothUuid(QString("0000ffe0-0000-1000-8000-00805f9b34fb")); foundServices << QBluetoothUuid(QString("f000aa00-0451-4000-b000-000000000000")); @@ -148,6 +184,20 @@ void tst_QLowEnergyController::initTestCase() foundServices << QBluetoothUuid(QString("f000ffc0-0451-4000-b000-000000000000")); } +/* + * Executed in between each test function call. + */ +void tst_QLowEnergyController::init() +{ +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + /* + * Add a delay to give Android/iOS stack time to catch up in between + * the multiple connect/disconnects within each test function. + */ + QTest::qWait(2000); +#endif +} + void tst_QLowEnergyController::cleanupTestCase() { @@ -198,17 +248,38 @@ void tst_QLowEnergyController::tst_emptyCtor() void tst_QLowEnergyController::tst_connect() { QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices(); + +#ifndef Q_OS_MAC if (localAdapters.isEmpty() || remoteDevice.isNull()) +#elif defined(Q_OS_OSX) + if (localAdapters.isEmpty() || remoteDeviceInfo.deviceUuid().isNull()) +#elif defined (Q_OS_IOS) + if (remoteDeviceInfo.deviceUuid().isNull()) +#endif QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); +#ifndef Q_OS_IOS const QBluetoothAddress localAdapter = localAdapters.at(0).address(); +#endif + +#ifndef Q_OS_MAC QLowEnergyController control(remoteDevice); +#else + // Create a low energy controller using Apple's + // uuid (NSUUID). + QLowEnergyController control(remoteDeviceInfo); +#endif + QSignalSpy connectedSpy(&control, SIGNAL(connected())); QSignalSpy disconnectedSpy(&control, SIGNAL(disconnected())); +#ifndef Q_OS_IOS QCOMPARE(control.localAddress(), localAdapter); QVERIFY(!control.localAddress().isNull()); +#endif +#ifndef Q_OS_MAC QCOMPARE(control.remoteAddress(), remoteDevice); +#endif QCOMPARE(control.state(), QLowEnergyController::UnconnectedState); QCOMPARE(control.error(), QLowEnergyController::NoError); QVERIFY(control.errorString().isEmpty()); @@ -251,7 +322,7 @@ void tst_QLowEnergyController::tst_connect() QSignalSpy serviceFoundSpy(&control, SIGNAL(serviceDiscovered(QBluetoothUuid))); QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState))); control.discoverServices(); - QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000); QCOMPARE(stateSpy.count(), 2); QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(), QLowEnergyController::DiscoveringState); @@ -344,12 +415,19 @@ void tst_QLowEnergyController::tst_connect() void tst_QLowEnergyController::tst_concurrentDiscovery() { +#ifndef Q_OS_MAC QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices(); if (localAdapters.isEmpty() || remoteDevice.isNull()) QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); // quick setup - more elaborate test is done by connectNew() QLowEnergyController control(remoteDevice); +#else + if (remoteDeviceInfo.deviceUuid().isNull()) + QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); + QLowEnergyController control(remoteDeviceInfo); +#endif + QCOMPARE(control.state(), QLowEnergyController::UnconnectedState); QCOMPARE(control.error(), QLowEnergyController::NoError); @@ -376,7 +454,18 @@ void tst_QLowEnergyController::tst_concurrentDiscovery() 30000); } +#ifdef Q_OS_ANDROID + QCOMPARE(control.state(), QLowEnergyController::ConnectedState); + QCOMPARE(control2.state(), QLowEnergyController::ConnectedState); + control2.disconnectFromDevice(); + QTest::qWait(3000); + 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); +#endif } /* We are testing that we can run service discovery on the same device @@ -386,7 +475,7 @@ void tst_QLowEnergyController::tst_concurrentDiscovery() QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished())); QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState))); control.discoverServices(); - QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000); QCOMPARE(stateSpy.count(), 2); QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(), QLowEnergyController::DiscoveringState); @@ -444,7 +533,7 @@ void tst_QLowEnergyController::tst_concurrentDiscovery() QCOMPARE(control.state(), QLowEnergyController::ConnectedState); stateSpy.clear(); control.discoverServices(); - QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000); QCOMPARE(stateSpy.count(), 2); QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(), QLowEnergyController::DiscoveringState); @@ -515,7 +604,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Device Name QString temp("00002a00-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x3)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x3)); QCOMPARE(chars[0].properties(), QLowEnergyCharacteristic::Read); QCOMPARE(chars[0].value(), QByteArray::fromHex("544920424c452053656e736f7220546167")); QVERIFY(chars[0].isValid()); @@ -525,7 +614,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Appearance temp = QString("00002a01-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x5)); + HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x5)); QCOMPARE(chars[1].properties(), QLowEnergyCharacteristic::Read); QCOMPARE(chars[1].value(), QByteArray::fromHex("0000")); QVERIFY(chars[1].isValid()); @@ -535,7 +624,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Peripheral Privacy Flag temp = QString("00002a02-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x7)); + HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x7)); QCOMPARE(chars[2].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[2].value(), QByteArray::fromHex("00")); @@ -546,7 +635,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Reconnection Address temp = QString("00002a03-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[3].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[3].handle(), QLowEnergyHandle(0x9)); + HANDLE_COMPARE(chars[3].handle(), QLowEnergyHandle(0x9)); //Early firmware version had this characteristic as Read|Write and may fail QCOMPARE(chars[3].properties(), QLowEnergyCharacteristic::Write); if (chars[3].properties() & QLowEnergyCharacteristic::Read) @@ -560,7 +649,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Peripheral Preferred Connection Parameters temp = QString("00002a04-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[4].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[4].handle(), QLowEnergyHandle(0xb)); + HANDLE_COMPARE(chars[4].handle(), QLowEnergyHandle(0xb)); QCOMPARE(chars[4].properties(), QLowEnergyCharacteristic::Read); QCOMPARE(chars[4].value(), QByteArray::fromHex("5000a0000000e803")); QVERIFY(chars[4].isValid()); @@ -576,7 +665,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QString temp("00002a05-0000-1000-8000-00805f9b34fb"); //this should really be readable according to GATT Service spec QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0xe)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0xe)); QCOMPARE(chars[0].properties(), QLowEnergyCharacteristic::Indicate); QCOMPARE(chars[0].value(), QByteArray()); QVERIFY(chars[0].isValid()); @@ -584,7 +673,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().count(), 1); QCOMPARE(chars[0].descriptors().at(0).isValid(), true); - QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0xf)); + HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0xf)); QCOMPARE(chars[0].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), @@ -601,9 +690,11 @@ void tst_QLowEnergyController::verifyServiceProperties( QString temp("00002a23-0000-1000-8000-00805f9b34fb"); //this should really be readable according to GATT Service spec QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x12)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x12)); QCOMPARE(chars[0].properties(), QLowEnergyCharacteristic::Read); - QCOMPARE(chars[0].value(), QByteArray::fromHex("6e41ab0000296abc")); +// Do not read the System ID as it is different for every device +// QEXPECT_FAIL("", "The value is different on different devices", Continue); +// QCOMPARE(chars[0].value(), QByteArray::fromHex("6e41ab0000296abc")); QVERIFY(chars[0].isValid()); QVERIFY(info->contains(chars[0])); QCOMPARE(chars[0].descriptors().count(), 0); @@ -611,7 +702,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Model Number temp = QString("00002a24-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x14)); + HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x14)); QCOMPARE(chars[1].properties(), QLowEnergyCharacteristic::Read); QCOMPARE(chars[1].value(), QByteArray::fromHex("4e2e412e00")); QVERIFY(chars[1].isValid()); @@ -621,7 +712,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Serial Number temp = QString("00002a25-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x16)); + HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x16)); QCOMPARE(chars[2].properties(), (QLowEnergyCharacteristic::Read)); QCOMPARE(chars[2].value(), QByteArray::fromHex("4e2e412e00")); @@ -632,7 +723,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Firmware Revision temp = QString("00002a26-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[3].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[3].handle(), QLowEnergyHandle(0x18)); + HANDLE_COMPARE(chars[3].handle(), QLowEnergyHandle(0x18)); QCOMPARE(chars[3].properties(), (QLowEnergyCharacteristic::Read)); //FW rev. : 1.5 (Oct 23 2013) @@ -645,7 +736,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Hardware Revision temp = QString("00002a27-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[4].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[4].handle(), QLowEnergyHandle(0x1a)); + HANDLE_COMPARE(chars[4].handle(), QLowEnergyHandle(0x1a)); QCOMPARE(chars[4].properties(), (QLowEnergyCharacteristic::Read)); QCOMPARE(chars[4].value(), QByteArray::fromHex("4e2e412e00")); @@ -656,7 +747,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Software Revision temp = QString("00002a28-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[5].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[5].handle(), QLowEnergyHandle(0x1c)); + HANDLE_COMPARE(chars[5].handle(), QLowEnergyHandle(0x1c)); QCOMPARE(chars[5].properties(), (QLowEnergyCharacteristic::Read)); QCOMPARE(chars[5].value(), QByteArray::fromHex("4e2e412e00")); @@ -667,7 +758,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Manufacturer Name temp = QString("00002a29-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[6].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[6].handle(), QLowEnergyHandle(0x1e)); + HANDLE_COMPARE(chars[6].handle(), QLowEnergyHandle(0x1e)); QCOMPARE(chars[6].properties(), (QLowEnergyCharacteristic::Read)); QCOMPARE(chars[6].value(), QByteArray::fromHex("546578617320496e737472756d656e747300")); @@ -678,7 +769,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // IEEE temp = QString("00002a2a-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[7].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[7].handle(), QLowEnergyHandle(0x20)); + HANDLE_COMPARE(chars[7].handle(), QLowEnergyHandle(0x20)); QCOMPARE(chars[7].properties(), (QLowEnergyCharacteristic::Read)); QCOMPARE(chars[7].value(), QByteArray::fromHex("fe006578706572696d656e74616c")); @@ -689,7 +780,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // PnP ID temp = QString("00002a50-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[8].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[8].handle(), QLowEnergyHandle(0x22)); + HANDLE_COMPARE(chars[8].handle(), QLowEnergyHandle(0x22)); QCOMPARE(chars[8].properties(), (QLowEnergyCharacteristic::Read)); QCOMPARE(chars[8].value(), QByteArray::fromHex("010d0000001001")); @@ -705,7 +796,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Temp Data QString temp("f000aa01-0451-4000-b000-000000000000"); QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x25)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x25)); QCOMPARE(chars[0].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); QCOMPARE(chars[0].value(), QByteArray::fromHex("00000000")); @@ -715,7 +806,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().count(), 2); //descriptor checks QCOMPARE(chars[0].descriptors().at(0).isValid(), true); - QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x26)); + HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x26)); QCOMPARE(chars[0].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), @@ -724,7 +815,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QVERIFY(info->contains(chars[0].descriptors().at(0))); QCOMPARE(chars[0].descriptors().at(1).isValid(), true); - QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x27)); + HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x27)); QCOMPARE(chars[0].descriptors().at(1).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[0].descriptors().at(1).type(), @@ -737,7 +828,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Temp Config temp = QString("f000aa02-0451-4000-b000-000000000000"); QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x29)); + HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x29)); QCOMPARE(chars[1].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); @@ -747,7 +838,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[1].descriptors().count(), 1); //descriptor checks QCOMPARE(chars[1].descriptors().at(0).isValid(), true); - QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x2a)); + HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x2a)); QCOMPARE(chars[1].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[1].descriptors().at(0).type(), @@ -762,7 +853,7 @@ void tst_QLowEnergyController::verifyServiceProperties( if (chars.count() > 2) { temp = QString("f000aa03-0451-4000-b000-000000000000"); QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x2c)); + HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x2c)); QCOMPARE(chars[2].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[2].value(), QByteArray::fromHex("64")); @@ -772,7 +863,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[2].descriptors().count(), 1); //descriptor checks QCOMPARE(chars[2].descriptors().at(0).isValid(), true); - QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x2d)); + HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x2d)); QCOMPARE(chars[2].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[2].descriptors().at(0).type(), @@ -791,7 +882,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QString temp("0000ffe1-0000-1000-8000-00805f9b34fb"); QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x6b)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x6b)); QCOMPARE(chars[0].properties(), (QLowEnergyCharacteristic::Notify)); QCOMPARE(chars[0].value(), QByteArray()); @@ -802,7 +893,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //descriptor checks QCOMPARE(chars[0].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x6c)); + HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x6c)); QCOMPARE(chars[0].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), @@ -812,7 +903,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().at(1).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x6d)); + HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x6d)); QCOMPARE(chars[0].descriptors().at(1).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[0].descriptors().at(1).type(), @@ -831,7 +922,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QString temp("f000aa11-0451-4000-b000-000000000000"); QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x30)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x30)); QCOMPARE(chars[0].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); QCOMPARE(chars[0].value(), QByteArray::fromHex("000000")); @@ -842,7 +933,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x31)); + HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x31)); QCOMPARE(chars[0].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), @@ -852,7 +943,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().at(1).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x32)); + HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x32)); QCOMPARE(chars[0].descriptors().at(1).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[0].descriptors().at(1).type(), @@ -865,7 +956,7 @@ void tst_QLowEnergyController::verifyServiceProperties( temp = QString("f000aa12-0451-4000-b000-000000000000"); QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x34)); + HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x34)); QCOMPARE(chars[1].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); @@ -875,7 +966,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[1].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x35)); + HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x35)); QCOMPARE(chars[1].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[1].descriptors().at(0).type(), @@ -888,7 +979,7 @@ void tst_QLowEnergyController::verifyServiceProperties( temp = QString("f000aa13-0451-4000-b000-000000000000"); QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x37)); + HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x37)); QCOMPARE(chars[2].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[2].value(), QByteArray::fromHex("64")); // don't change it or set it to 0x64 @@ -899,7 +990,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //descriptor checks QCOMPARE(chars[2].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x38)); + HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x38)); QCOMPARE(chars[2].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[2].descriptors().at(0).type(), @@ -918,7 +1009,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QString temp("f000aa21-0451-4000-b000-000000000000"); QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x3b)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x3b)); QCOMPARE(chars[0].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); QCOMPARE(chars[0].value(), QByteArray::fromHex("00000000")); @@ -929,7 +1020,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //descriptor checks QCOMPARE(chars[0].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x3c)); + HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x3c)); QCOMPARE(chars[0].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), @@ -939,7 +1030,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().at(1).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x3d)); + HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x3d)); QCOMPARE(chars[0].descriptors().at(1).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[0].descriptors().at(1).type(), @@ -952,7 +1043,7 @@ void tst_QLowEnergyController::verifyServiceProperties( temp = QString("f000aa22-0451-4000-b000-000000000000"); QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x3f)); + HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x3f)); QCOMPARE(chars[1].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); @@ -963,7 +1054,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //descriptor checks QCOMPARE(chars[1].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x40)); + HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x40)); QCOMPARE(chars[1].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[1].descriptors().at(0).type(), @@ -977,7 +1068,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Humidity Period temp = QString("f000aa23-0451-4000-b000-000000000000"); QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x42)); + HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x42)); QCOMPARE(chars[2].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[2].value(), QByteArray::fromHex("64")); @@ -987,7 +1078,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[2].descriptors().count(), 1); //descriptor checks QCOMPARE(chars[2].descriptors().at(0).isValid(), true); - QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x43)); + HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x43)); QCOMPARE(chars[2].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[2].descriptors().at(0).type(), @@ -1006,7 +1097,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QString temp("f000aa31-0451-4000-b000-000000000000"); QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x46)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x46)); QCOMPARE(chars[0].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); QCOMPARE(chars[0].value(), QByteArray::fromHex("000000000000")); @@ -1017,7 +1108,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x47)); + HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x47)); QCOMPARE(chars[0].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), @@ -1027,7 +1118,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().at(1).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x48)); + HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x48)); QCOMPARE(chars[0].descriptors().at(1).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[0].descriptors().at(1).type(), @@ -1040,7 +1131,7 @@ void tst_QLowEnergyController::verifyServiceProperties( temp = QString("f000aa32-0451-4000-b000-000000000000"); QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x4a)); + HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x4a)); QCOMPARE(chars[1].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); @@ -1050,7 +1141,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[1].descriptors().count(), 1); QCOMPARE(chars[1].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x4b)); + HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x4b)); QCOMPARE(chars[1].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[1].descriptors().at(0).type(), @@ -1064,7 +1155,7 @@ void tst_QLowEnergyController::verifyServiceProperties( temp = QString("f000aa33-0451-4000-b000-000000000000"); QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x4d)); + HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x4d)); QCOMPARE(chars[2].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[2].value(), QByteArray::fromHex("c8")); // don't change it or set it to 0xc8 @@ -1074,7 +1165,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[2].descriptors().count(), 1); QCOMPARE(chars[2].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x4e)); + HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x4e)); QCOMPARE(chars[2].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[2].descriptors().at(0).type(), @@ -1093,7 +1184,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QString temp("f000aa41-0451-4000-b000-000000000000"); QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x51)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x51)); QCOMPARE(chars[0].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); QCOMPARE(chars[0].value(), QByteArray::fromHex("00000000")); @@ -1104,7 +1195,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //descriptor checks QCOMPARE(chars[0].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x52)); + HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x52)); QCOMPARE(chars[0].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), @@ -1114,7 +1205,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().at(1).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x53)); + HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x53)); QCOMPARE(chars[0].descriptors().at(1).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[0].descriptors().at(1).type(), @@ -1128,7 +1219,7 @@ void tst_QLowEnergyController::verifyServiceProperties( temp = QString("f000aa42-0451-4000-b000-000000000000"); QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x55)); + HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x55)); QCOMPARE(chars[1].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); @@ -1138,7 +1229,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[1].descriptors().count(), 1); QCOMPARE(chars[1].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x56)); + HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x56)); QCOMPARE(chars[1].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[1].descriptors().at(0).type(), @@ -1162,7 +1253,7 @@ void tst_QLowEnergyController::verifyServiceProperties( temp = QString("f000aa43-0451-4000-b000-000000000000"); QCOMPARE(calibration.uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(calibration.handle(), QLowEnergyHandle(0x5b)); + HANDLE_COMPARE(calibration.handle(), QLowEnergyHandle(0x5b)); QCOMPARE(calibration.properties(), (QLowEnergyCharacteristic::Read)); QCOMPARE(calibration.value(), QByteArray::fromHex("00000000000000000000000000000000")); // don't change it @@ -1173,7 +1264,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //descriptor checks QCOMPARE(calibration.descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(calibration.descriptors().at(0).handle(), QLowEnergyHandle(0x5c)); + HANDLE_COMPARE(calibration.descriptors().at(0).handle(), QLowEnergyHandle(0x5c)); QCOMPARE(calibration.descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(calibration.descriptors().at(0).type(), @@ -1183,7 +1274,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(calibration.descriptors().at(1).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(calibration.descriptors().at(1).handle(), QLowEnergyHandle(0x5d)); + HANDLE_COMPARE(calibration.descriptors().at(1).handle(), QLowEnergyHandle(0x5d)); QCOMPARE(calibration.descriptors().at(1).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(calibration.descriptors().at(1).type(), @@ -1198,7 +1289,7 @@ void tst_QLowEnergyController::verifyServiceProperties( temp = QString("f000aa44-0451-4000-b000-000000000000"); QCOMPARE(period.uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(period.handle(), QLowEnergyHandle(0x58)); + HANDLE_COMPARE(period.handle(), QLowEnergyHandle(0x58)); QCOMPARE(period.properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(period.value(), QByteArray::fromHex("64")); @@ -1209,7 +1300,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //descriptor checks QCOMPARE(period.descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(period.descriptors().at(0).handle(), QLowEnergyHandle(0x59)); + HANDLE_COMPARE(period.descriptors().at(0).handle(), QLowEnergyHandle(0x59)); QCOMPARE(period.descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(period.descriptors().at(0).type(), @@ -1228,7 +1319,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QString temp("f000aa51-0451-4000-b000-000000000000"); QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x60)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x60)); QCOMPARE(chars[0].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Notify)); QCOMPARE(chars[0].value(), QByteArray::fromHex("000000000000")); @@ -1239,7 +1330,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //descriptor checks QCOMPARE(chars[0].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x61)); + HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x61)); QCOMPARE(chars[0].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), @@ -1249,7 +1340,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().at(1).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x62)); + HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x62)); QCOMPARE(chars[0].descriptors().at(1).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[0].descriptors().at(1).type(), @@ -1263,7 +1354,7 @@ void tst_QLowEnergyController::verifyServiceProperties( temp = QString("f000aa52-0451-4000-b000-000000000000"); QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x64)); + HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x64)); QCOMPARE(chars[1].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); @@ -1274,7 +1365,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //descriptor checks QCOMPARE(chars[1].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x65)); + HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x65)); QCOMPARE(chars[1].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[1].descriptors().at(0).type(), @@ -1287,7 +1378,7 @@ void tst_QLowEnergyController::verifyServiceProperties( temp = QString("f000aa53-0451-4000-b000-000000000000"); QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x67)); + HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x67)); QCOMPARE(chars[2].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[2].value(), QByteArray::fromHex("64")); @@ -1297,7 +1388,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[2].descriptors().count(), 1); //descriptor checks QCOMPARE(chars[2].descriptors().at(0).isValid(), true); - QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x68)); + HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x68)); QCOMPARE(chars[2].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[2].descriptors().at(0).type(), @@ -1315,7 +1406,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QString temp("f000aa61-0451-4000-b000-000000000000"); QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x70)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x70)); QCOMPARE(chars[0].properties(), (QLowEnergyCharacteristic::Read)); QCOMPARE(chars[0].value(), QByteArray::fromHex("3f00")); @@ -1325,7 +1416,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().count(), 1); QCOMPARE(chars[0].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x71)); + HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x71)); QCOMPARE(chars[0].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[0].descriptors().at(0).type(), @@ -1337,7 +1428,7 @@ void tst_QLowEnergyController::verifyServiceProperties( // Test Config temp = QString("f000aa62-0451-4000-b000-000000000000"); QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x73)); + HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x73)); QCOMPARE(chars[1].properties(), (QLowEnergyCharacteristic::Read|QLowEnergyCharacteristic::Write)); QCOMPARE(chars[1].value(), QByteArray::fromHex("00")); @@ -1348,7 +1439,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //descriptor checks QCOMPARE(chars[1].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x74)); + HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x74)); QCOMPARE(chars[1].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[1].descriptors().at(0).type(), @@ -1365,7 +1456,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //first characteristic QString temp("f000ccc1-0451-4000-b000-000000000000"); QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x77)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x77)); QCOMPARE(chars[0].properties(), (QLowEnergyCharacteristic::Notify|QLowEnergyCharacteristic::Read)); // the connection control parameter change from platform to platform @@ -1377,7 +1468,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().count(), 2); //descriptor checks QCOMPARE(chars[0].descriptors().at(0).isValid(), true); - QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x78)); + HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x78)); QCOMPARE(chars[0].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), @@ -1388,7 +1479,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().at(1).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x79)); + HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x79)); QCOMPARE(chars[0].descriptors().at(1).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[0].descriptors().at(1).type(), @@ -1400,7 +1491,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //second characteristic temp = QString("f000ccc2-0451-4000-b000-000000000000"); QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x7b)); + HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x7b)); QCOMPARE(chars[1].properties(), QLowEnergyCharacteristic::Write); QCOMPARE(chars[1].value(), QByteArray()); QVERIFY(chars[1].isValid()); @@ -1408,7 +1499,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[1].descriptors().count(), 1); QCOMPARE(chars[1].descriptors().at(0).isValid(), true); - QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x7c)); + HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x7c)); QCOMPARE(chars[1].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[1].descriptors().at(0).type(), @@ -1420,7 +1511,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //third characteristic temp = QString("f000ccc3-0451-4000-b000-000000000000"); QCOMPARE(chars[2].uuid(), QBluetoothUuid(temp)); - QCOMPARE(chars[2].handle(), QLowEnergyHandle(0x7e)); + HANDLE_COMPARE(chars[2].handle(), QLowEnergyHandle(0x7e)); QCOMPARE(chars[2].properties(), QLowEnergyCharacteristic::Write); QCOMPARE(chars[2].value(), QByteArray()); QVERIFY(chars[2].isValid()); @@ -1428,7 +1519,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[2].descriptors().count(), 1); QCOMPARE(chars[2].descriptors().at(0).isValid(), true); - QCOMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x7f)); + HANDLE_COMPARE(chars[2].descriptors().at(0).handle(), QLowEnergyHandle(0x7f)); QCOMPARE(chars[2].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[2].descriptors().at(0).type(), @@ -1446,7 +1537,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QString temp("f000ffc1-0451-4000-b000-000000000000"); QCOMPARE(chars[0].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[0].handle(), QLowEnergyHandle(0x82)); + HANDLE_COMPARE(chars[0].handle(), QLowEnergyHandle(0x82)); QCOMPARE(chars[0].properties(), (QLowEnergyCharacteristic::Notify|QLowEnergyCharacteristic::Write|QLowEnergyCharacteristic::WriteNoResponse)); QCOMPARE(chars[0].value(), QByteArray()); @@ -1456,7 +1547,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().count(), 2); //descriptor checks QCOMPARE(chars[0].descriptors().at(0).isValid(), true); - QCOMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x83)); + HANDLE_COMPARE(chars[0].descriptors().at(0).handle(), QLowEnergyHandle(0x83)); QCOMPARE(chars[0].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), @@ -1467,7 +1558,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[0].descriptors().at(1).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x84)); + HANDLE_COMPARE(chars[0].descriptors().at(1).handle(), QLowEnergyHandle(0x84)); QCOMPARE(chars[0].descriptors().at(1).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[0].descriptors().at(1).type(), @@ -1480,7 +1571,7 @@ void tst_QLowEnergyController::verifyServiceProperties( temp = QString("f000ffc2-0451-4000-b000-000000000000"); QCOMPARE(chars[1].uuid(), QBluetoothUuid(temp)); // value different in other revisions and test may fail - QCOMPARE(chars[1].handle(), QLowEnergyHandle(0x86)); + HANDLE_COMPARE(chars[1].handle(), QLowEnergyHandle(0x86)); QCOMPARE(chars[1].properties(), (QLowEnergyCharacteristic::Notify|QLowEnergyCharacteristic::Write|QLowEnergyCharacteristic::WriteNoResponse)); QCOMPARE(chars[1].value(), QByteArray()); @@ -1491,7 +1582,7 @@ void tst_QLowEnergyController::verifyServiceProperties( //descriptor checks QCOMPARE(chars[1].descriptors().at(0).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x87)); + HANDLE_COMPARE(chars[1].descriptors().at(0).handle(), QLowEnergyHandle(0x87)); QCOMPARE(chars[1].descriptors().at(0).uuid(), QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[1].descriptors().at(0).type(), @@ -1502,7 +1593,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QCOMPARE(chars[1].descriptors().at(1).isValid(), true); // value different in other revisions and test may fail - QCOMPARE(chars[1].descriptors().at(1).handle(), QLowEnergyHandle(0x88)); + HANDLE_COMPARE(chars[1].descriptors().at(1).handle(), QLowEnergyHandle(0x88)); QCOMPARE(chars[1].descriptors().at(1).uuid(), QBluetoothUuid(QBluetoothUuid::CharacteristicUserDescription)); QCOMPARE(chars[1].descriptors().at(1).type(), @@ -1566,12 +1657,19 @@ void tst_QLowEnergyController::tst_defaultBehavior() void tst_QLowEnergyController::tst_writeCharacteristic() { +#ifndef Q_OS_MAC QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices(); if (localAdapters.isEmpty() || remoteDevice.isNull()) QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); // quick setup - more elaborate test is done by connect() QLowEnergyController control(remoteDevice); +#else + if (remoteDeviceInfo.deviceUuid().isNull()) + QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); + QLowEnergyController control(remoteDeviceInfo); +#endif + QCOMPARE(control.error(), QLowEnergyController::NoError); control.connectToDevice(); @@ -1590,7 +1688,7 @@ void tst_QLowEnergyController::tst_writeCharacteristic() QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished())); QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState))); control.discoverServices(); - QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000); QCOMPARE(stateSpy.count(), 2); QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(), QLowEnergyController::DiscoveringState); @@ -1624,6 +1722,7 @@ void tst_QLowEnergyController::tst_writeCharacteristic() QVERIFY(service->contains(dataChar)); QVERIFY(configChar.isValid()); QVERIFY(configChar.properties() & QLowEnergyCharacteristic::Write); + QVERIFY(configChar.properties() & QLowEnergyCharacteristic::Read); QVERIFY(service->contains(configChar)); QCOMPARE(dataChar.value(), QByteArray::fromHex("3f00")); @@ -1632,11 +1731,13 @@ void tst_QLowEnergyController::tst_writeCharacteristic() QSignalSpy writeSpy(service, SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy readSpy(service, + SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray))); // ******************************************* // test writing of characteristic // enable Blinking LED if not already enabled - if (configChar.value() != QByteArray("81")) { + if (configChar.value() != QByteArray::fromHex("81")) { service->writeCharacteristic(configChar, QByteArray::fromHex("81")); //0x81 blink LED D1 QTRY_VERIFY_WITH_TIMEOUT(!writeSpy.isEmpty(), 10000); QCOMPARE(configChar.value(), QByteArray::fromHex("81")); @@ -1648,9 +1749,27 @@ void tst_QLowEnergyController::tst_writeCharacteristic() QVERIFY(signalChar == configChar); writeSpy.clear(); + } - service->writeCharacteristic(configChar, QByteArray::fromHex("00")); //0x81 blink LED D1 + // test direct read of configChar + QVERIFY(readSpy.isEmpty()); + service->readCharacteristic(configChar); + QTRY_VERIFY_WITH_TIMEOUT(!readSpy.isEmpty(), 10000); + QCOMPARE(configChar.value(), QByteArray::fromHex("81")); + QCOMPARE(readSpy.count(), 1); //expect one characteristicRead signal + { + //verify the readCharacteristic() + QList<QVariant> firstSignalData = readSpy.first(); + QLowEnergyCharacteristic signalChar = firstSignalData[0].value<QLowEnergyCharacteristic>(); + QByteArray signalValue = firstSignalData[1].toByteArray(); + + QCOMPARE(signalValue, QByteArray::fromHex("81")); + QCOMPARE(signalValue, configChar.value()); + QVERIFY(signalChar == configChar); + } + + service->writeCharacteristic(configChar, QByteArray::fromHex("00")); //turn LED D1 off QTRY_VERIFY_WITH_TIMEOUT(!writeSpy.isEmpty(), 10000); QCOMPARE(configChar.value(), QByteArray::fromHex("00")); QList<QVariant> firstSignalData = writeSpy.first(); @@ -1684,8 +1803,8 @@ void tst_QLowEnergyController::tst_writeCharacteristic() QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 10000); QCOMPARE(errorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), - QLowEnergyService::OperationError); - QCOMPARE(service->error(), QLowEnergyService::OperationError); + QLowEnergyService::CharacteristicWriteError); + QCOMPARE(service->error(), QLowEnergyService::CharacteristicWriteError); QCOMPARE(writeSpy.count(), 0); QCOMPARE(dataChar.value(), QByteArray::fromHex("3f00")); @@ -1713,14 +1832,19 @@ void tst_QLowEnergyController::tst_writeCharacteristic() delete service; } -void tst_QLowEnergyController::tst_writeDescriptor() +void tst_QLowEnergyController::tst_readWriteDescriptor() { +#ifndef Q_OS_MAC QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices(); if (localAdapters.isEmpty() || remoteDevice.isNull()) QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); - - // quick setup - more elaborate test is done by connect() QLowEnergyController control(remoteDevice); +#else + if (remoteDeviceInfo.deviceUuid().isNull()) + QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); + QLowEnergyController control(remoteDeviceInfo); +#endif + // quick setup - more elaborate test is done by connect() control.connectToDevice(); { QTRY_IMPL(control.state() != QLowEnergyController::ConnectingState, @@ -1737,7 +1861,7 @@ void tst_QLowEnergyController::tst_writeDescriptor() QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished())); QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState))); control.discoverServices(); - QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000); QCOMPARE(stateSpy.count(), 2); QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(), QLowEnergyController::DiscoveringState); @@ -1787,9 +1911,11 @@ void tst_QLowEnergyController::tst_writeDescriptor() QCOMPARE(tempConfig.value(), QByteArray::fromHex("00")); } - // 3. Test writing to descriptor -> activate notifications + // 3. Test reading and writing to descriptor -> activate notifications QSignalSpy descWrittenSpy(service, SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray))); + QSignalSpy descReadSpy(service, + SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray))); QSignalSpy charWrittenSpy(service, SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray))); QSignalSpy charChangedSpy(service, @@ -1836,12 +1962,31 @@ void tst_QLowEnergyController::tst_writeDescriptor() const QLowEnergyCharacteristic ch = entry[0].value<QLowEnergyCharacteristic>(); QCOMPARE(tempData, ch); + + //check last characteristic changed value matches the characteristics current value + if (i == (charChangedSpy.count() - 1)) { + writtenValue = entry[1].toByteArray(); + QCOMPARE(ch.value(), writtenValue); + QCOMPARE(tempData.value(), writtenValue); + } } service->writeCharacteristic(tempConfig, QByteArray::fromHex("00")); } - // 5. Test writing to descriptor -> deactivate notifications + // 5. Test reading and writing of/to descriptor -> deactivate notifications + + service->readDescriptor(notification); + QTRY_VERIFY_WITH_TIMEOUT(!descReadSpy.isEmpty(), 3000); + QCOMPARE(descReadSpy.count(), 1); + firstSignalData = descReadSpy.first(); + signalDesc = firstSignalData[0].value<QLowEnergyDescriptor>(); + signalValue = firstSignalData[1].toByteArray(); + QCOMPARE(signalValue, notification.value()); + QCOMPARE(notification.value(), QByteArray::fromHex("0100")); + descReadSpy.clear(); + + service->writeDescriptor(notification, QByteArray::fromHex("0000")); // verify QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000); @@ -1853,6 +1998,41 @@ void tst_QLowEnergyController::tst_writeDescriptor() QVERIFY(notification == signalDesc); descWrittenSpy.clear(); + // test concurrent writeRequests + // they need to be queued up + service->writeDescriptor(notification,QByteArray::fromHex("0100")); + service->writeDescriptor(notification, QByteArray::fromHex("0000")); + service->writeDescriptor(notification, QByteArray::fromHex("0100")); + service->writeDescriptor(notification, QByteArray::fromHex("0000")); + QTRY_VERIFY_WITH_TIMEOUT(descWrittenSpy.count() == 4, 10000); + + QCOMPARE(notification.value(), QByteArray::fromHex("0000")); + for (int i = 0; i < descWrittenSpy.count(); i++) { + firstSignalData = descWrittenSpy.at(i); + signalDesc = firstSignalData[0].value<QLowEnergyDescriptor>(); + signalValue = firstSignalData[1].toByteArray(); + if (i & 0x1) // odd + QCOMPARE(signalValue, QByteArray::fromHex("0000")); + else // even + QCOMPARE(signalValue, QByteArray::fromHex("0100")); + QVERIFY(notification == signalDesc); + + } + + // 5. Test reading and writing of/to descriptor -> deactivate notifications + + service->readDescriptor(notification); + QTRY_VERIFY_WITH_TIMEOUT(!descReadSpy.isEmpty(), 3000); + QCOMPARE(descReadSpy.count(), 1); + firstSignalData = descReadSpy.first(); + signalDesc = firstSignalData[0].value<QLowEnergyDescriptor>(); + signalValue = firstSignalData[1].toByteArray(); + QCOMPARE(signalValue, notification.value()); + QCOMPARE(notification.value(), QByteArray::fromHex("0000")); + descReadSpy.clear(); + + descWrittenSpy.clear(); + // ******************************************* // write wrong value -> error response required QSignalSpy errorSpy(service, SIGNAL(error(QLowEnergyService::ServiceError))); @@ -1862,7 +2042,15 @@ void tst_QLowEnergyController::tst_writeDescriptor() // write 4 byte value to 2 byte characteristic service->writeDescriptor(notification, QByteArray::fromHex("11112222")); +#ifdef Q_OS_MAC + // On OS X/iOS we have a special method to set notify value, + // it accepts only false/true and not + // writing descriptors, there is only one way to find this error - + // immediately intercept in LE controller and set the error. + QVERIFY(!errorSpy.isEmpty()); +#else QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 30000); +#endif QCOMPARE(errorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), QLowEnergyService::DescriptorWriteError); QCOMPARE(service->error(), QLowEnergyService::DescriptorWriteError); @@ -1886,12 +2074,32 @@ void tst_QLowEnergyController::tst_writeDescriptor() } /* - * Tests encrypted read/write. + * By default this test is skipped. + * + * Following tests are performed: + * - encrypted read and discovery + * - readCharacteristic() of values longer than MTU + * - readCharacteristic() if values equal to MTU + * * This test is semi manual as the test device environment is very specific. - * Adjust the various uuids and addresses at the top to cater for the current - * situation. By default this test is skipped. + * A programmable BTLE device is required. Currently, the test requires + * the CSR Dev Kit using the hr_sensor example. + * + * The following changes must be done to example to be able to fully + * utilise the test: + * 1.) gap_service_db.db -> UUID_DEVICE_NAME char - add FLAG_ENCR_R + * => tests encrypted read/discovery + * 2.) dev_info_service_db.db -> UUID_DEVICE_INFO_MANUFACTURER_NAME + * => The default name "Cambridge Silicon Radio" must be changed + * to "Cambridge Silicon Radi" (new length 22) + * 3.) revert change 1 above and redo test. This attempts to write a + * char that is readable w/o encryption but writeable with encryption + * => tests encryption code lines in writeCharacteristic() + * => otherwise the read encryption would have increased security level already + * => programmable CSR device must be reset before each run of this test + * (to undo the previous write) */ -void tst_QLowEnergyController::tst_encryption() +void tst_QLowEnergyController::tst_customProgrammableDevice() { QSKIP("Skipping encryption"); @@ -1922,7 +2130,7 @@ void tst_QLowEnergyController::tst_encryption() QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished())); QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState))); control.discoverServices(); - QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000); QCOMPARE(stateSpy.count(), 2); QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(), QLowEnergyController::DiscoveringState); @@ -1934,33 +2142,360 @@ void tst_QLowEnergyController::tst_encryption() QLowEnergyService *service = control.createServiceObject(serviceUuid, this); QVERIFY(service); + + // 1.) discovery triggers read of device name char which is encrypted service->discoverDetails(); QTRY_VERIFY_WITH_TIMEOUT( service->state() == QLowEnergyService::ServiceDiscovered, 30000); - QLowEnergyCharacteristic characteristic = service->characteristic( + QLowEnergyCharacteristic encryptedChar = service->characteristic( characterristicUuid); + const QByteArray encryptedReference("CSR HR Sensor"); + QVERIFY(encryptedChar.isValid()); + QCOMPARE(encryptedChar.value(), encryptedReference); + + // 2.) read of encrypted characteristic + // => the discovery of the encrypted char above will have switched to + // encryption already. + QSignalSpy encryptedReadSpy(service, + SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy encryptedErrorSpy(service, + SIGNAL(error(QLowEnergyService::ServiceError))); + service->readCharacteristic(encryptedChar); + QTRY_VERIFY_WITH_TIMEOUT(!encryptedReadSpy.isEmpty(), 10000); + QVERIFY(encryptedErrorSpy.isEmpty()); + QCOMPARE(encryptedReadSpy.count(), 1); + QList<QVariant> entry = encryptedReadSpy[0]; + QVERIFY(entry[0].value<QLowEnergyCharacteristic>() == encryptedChar); + QCOMPARE(entry[1].toByteArray(), encryptedReference); + QCOMPARE(encryptedChar.value(), encryptedReference); + + // 3.) write to encrypted characteristic + QSignalSpy encryptedWriteSpy(service, + SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray))); + encryptedReadSpy.clear(); + encryptedErrorSpy.clear(); + const QByteArray newValue("ZZZ HR Sensor"); + service->writeCharacteristic(encryptedChar, newValue); + QTRY_VERIFY_WITH_TIMEOUT(!encryptedWriteSpy.isEmpty(), 10000); + QVERIFY(encryptedErrorSpy.isEmpty()); + QVERIFY(encryptedReadSpy.isEmpty()); + QCOMPARE(encryptedWriteSpy.count(), 1); + entry = encryptedWriteSpy[0]; + QVERIFY(entry[0].value<QLowEnergyCharacteristic>() == encryptedChar); + QCOMPARE(entry[1].toByteArray(), newValue); + QCOMPARE(encryptedChar.value(), newValue); + + delete service; - QVERIFY(characteristic.isValid()); - qDebug() << "Encrypted char value:" << characteristic.value().toHex() << characteristic.value(); - QVERIFY(!characteristic.value().isEmpty()); + //change to Device Information service + QVERIFY(uuids.contains(QBluetoothUuid::DeviceInformation)); + service = control.createServiceObject(QBluetoothUuid::DeviceInformation); + QVERIFY(service); + + service->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + service->state() == QLowEnergyService::ServiceDiscovered, 30000); + + // 4.) read of software revision string which is longer than mtu + // tests readCharacteristic() including blob reads + QSignalSpy readSpy(service, + SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy errorSpy(service, + SIGNAL(error(QLowEnergyService::ServiceError))); + + const QByteArray expectedSoftRev("Application version 2.3.0.0"); + QLowEnergyCharacteristic softwareRevChar + = service->characteristic(QBluetoothUuid::SoftwareRevisionString); + QVERIFY(softwareRevChar.isValid()); + QCOMPARE(softwareRevChar.value(), expectedSoftRev); + + service->readCharacteristic(softwareRevChar); + QTRY_VERIFY_WITH_TIMEOUT(!readSpy.isEmpty(), 10000); + QVERIFY(errorSpy.isEmpty()); + QCOMPARE(readSpy.count(), 1); + entry = readSpy[0]; + QVERIFY(entry[0].value<QLowEnergyCharacteristic>() == softwareRevChar); + QCOMPARE(entry[1].toByteArray(), expectedSoftRev); + QCOMPARE(softwareRevChar.value(), expectedSoftRev); + + + // 5.) read of manufacturer string which is exactly as long as single + // MTU size (assuming negotiated MTU is 23) + // => blob read test without blob being required + // => the read blob answer will have zero length + + readSpy.clear(); + + // This assumes the manufacturer string was mondified via CSR SDK + // see function description above + const QByteArray expectedManufacturer("Cambridge Silicon Radi"); + QLowEnergyCharacteristic manufacturerChar = service->characteristic( + QBluetoothUuid::ManufacturerNameString); + QVERIFY(manufacturerChar.isValid()); + QCOMPARE(manufacturerChar.value(), expectedManufacturer); + + service->readCharacteristic(manufacturerChar); + QTRY_VERIFY_WITH_TIMEOUT(!readSpy.isEmpty(), 10000); + QVERIFY(errorSpy.isEmpty()); + QCOMPARE(readSpy.count(), 1); + entry = readSpy[0]; + QVERIFY(entry[0].value<QLowEnergyCharacteristic>() == manufacturerChar); + QCOMPARE(entry[1].toByteArray(), expectedManufacturer); + QCOMPARE(manufacturerChar.value(), expectedManufacturer); delete service; control.disconnectFromDevice(); } + +/* 1.) Test with undiscovered devices + - read and write invalid char + 2.) Test with discovered devices + - read non-readable char + - write non-writable char + */ +void tst_QLowEnergyController::tst_errorCases() +{ +#ifndef Q_OS_MAC + QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices(); + if (localAdapters.isEmpty() || remoteDevice.isNull()) + QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); + + // quick setup - more elaborate test is done by connect() + QLowEnergyController control(remoteDevice); +#else + if (remoteDeviceInfo.deviceUuid().isNull()) + QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); + + QLowEnergyController control(remoteDeviceInfo); +#endif + QCOMPARE(control.error(), QLowEnergyController::NoError); + + control.connectToDevice(); + { + QTRY_IMPL(control.state() != QLowEnergyController::ConnectingState, + 30000); + } + + if (control.state() == QLowEnergyController::ConnectingState + || control.error() != QLowEnergyController::NoError) { + // default BTLE backend forever hangs in ConnectingState + QSKIP("Cannot connect to remote device"); + } + + QCOMPARE(control.state(), QLowEnergyController::ConnectedState); + QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished())); + QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState))); + control.discoverServices(); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000); + QCOMPARE(stateSpy.count(), 2); + QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(), + QLowEnergyController::DiscoveringState); + QCOMPARE(stateSpy.at(1).at(0).value<QLowEnergyController::ControllerState>(), + QLowEnergyController::DiscoveredState); + + + // Setup required uuids + const QBluetoothUuid irTemperaturServiceUuid(QStringLiteral("f000aa00-0451-4000-b000-000000000000")); + const QBluetoothUuid irCharUuid(QString("f000aa01-0451-4000-b000-000000000000")); + const QBluetoothUuid oadServiceUuid(QStringLiteral("f000ffc0-0451-4000-b000-000000000000")); + const QBluetoothUuid oadCharUuid(QString("f000ffc1-0451-4000-b000-000000000000")); + + QVERIFY(control.services().contains(irTemperaturServiceUuid)); + QVERIFY(control.services().contains(oadServiceUuid)); + + // Create service objects and basic tests + QLowEnergyService *irService = control.createServiceObject(irTemperaturServiceUuid); + QVERIFY(irService); + QCOMPARE(irService->state(), QLowEnergyService::DiscoveryRequired); + QVERIFY(irService->characteristics().isEmpty()); + QLowEnergyService *oadService = control.createServiceObject(oadServiceUuid); + QVERIFY(oadService); + QCOMPARE(oadService->state(), QLowEnergyService::DiscoveryRequired); + QVERIFY(oadService->characteristics().isEmpty()); + + QLowEnergyCharacteristic invalidChar; + QLowEnergyDescriptor invalidDesc; + + QVERIFY(!irService->contains(invalidChar)); + QVERIFY(!irService->contains(invalidDesc)); + + QSignalSpy irErrorSpy(irService, SIGNAL(error(QLowEnergyService::ServiceError))); + QSignalSpy oadErrorSpy(oadService, SIGNAL(error(QLowEnergyService::ServiceError))); + + QSignalSpy irReadSpy(irService, SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy irWrittenSpy(irService, SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy irDescReadSpy(irService, SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray))); + QSignalSpy irDescWrittenSpy(irService, SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray))); + + QSignalSpy oadCharReadSpy(oadService, SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray))); + + // ******************************************************** + // Test read/write to discovered service + // with invalid characteristic & descriptor + + // discover IR Service + irService->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + irService->state() == QLowEnergyService::ServiceDiscovered, 30000); + QVERIFY(!irService->contains(invalidChar)); + QVERIFY(!irService->contains(invalidDesc)); + irErrorSpy.clear(); + + // read invalid characteristic + irService->readCharacteristic(invalidChar); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QCOMPARE(irErrorSpy.count(), 1); + QVERIFY(irWrittenSpy.isEmpty()); + QVERIFY(irReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), + QLowEnergyService::OperationError); + irErrorSpy.clear(); + + // read invalid descriptor + irService->readDescriptor(invalidDesc); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QCOMPARE(irErrorSpy.count(), 1); + QVERIFY(irDescWrittenSpy.isEmpty()); + QVERIFY(irDescReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), + QLowEnergyService::OperationError); + irErrorSpy.clear(); + + // write invalid characteristic + irService->writeCharacteristic(invalidChar, QByteArray("foo")); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QCOMPARE(irErrorSpy.count(), 1); + QVERIFY(irWrittenSpy.isEmpty()); + QVERIFY(irReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), + QLowEnergyService::OperationError); + irErrorSpy.clear(); + + // write invalid descriptor + irService->readDescriptor(invalidDesc); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QCOMPARE(irErrorSpy.count(), 1); + QVERIFY(irDescWrittenSpy.isEmpty()); + QVERIFY(irDescReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), + QLowEnergyService::OperationError); + irErrorSpy.clear(); + + // ******************************************************** + // Test read/write to undiscovered service + // with invalid characteristic & descriptor + + // read invalid characteristic + oadService->readCharacteristic(invalidChar); + QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000); + QCOMPARE(oadErrorSpy.count(), 1); + QCOMPARE(oadErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), + QLowEnergyService::OperationError); + oadErrorSpy.clear(); + + // read invalid descriptor + oadService->readDescriptor(invalidDesc); + QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000); + QCOMPARE(oadErrorSpy.count(), 1); + QCOMPARE(oadErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), + QLowEnergyService::OperationError); + oadErrorSpy.clear(); + + // write invalid characteristic + oadService->writeCharacteristic(invalidChar, QByteArray("foo")); + QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000); + QCOMPARE(oadErrorSpy.count(), 1); + QCOMPARE(oadErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), + QLowEnergyService::OperationError); + oadErrorSpy.clear(); + + // write invalid descriptor + oadService->readDescriptor(invalidDesc); + QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000); + QCOMPARE(oadErrorSpy.count(), 1); + QCOMPARE(oadErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), + QLowEnergyService::OperationError); + oadErrorSpy.clear(); + + // ******************************************************** + // Write to non-writable char + + QLowEnergyCharacteristic nonWritableChar = irService->characteristic(irCharUuid); + QVERIFY(nonWritableChar.isValid()); + // not writeable in any form + QVERIFY(!(nonWritableChar.properties() + & (QLowEnergyCharacteristic::Write|QLowEnergyCharacteristic::WriteNoResponse + |QLowEnergyCharacteristic::WriteSigned))); + irService->writeCharacteristic(nonWritableChar, QByteArray("ABCD")); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QVERIFY(irWrittenSpy.isEmpty()); + QVERIFY(irReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), + QLowEnergyService::CharacteristicWriteError); + irErrorSpy.clear(); + + // ******************************************************** + // Write to non-writable desc + // CharacteristicUserDescription is not writable + + QLowEnergyDescriptor nonWritableDesc = nonWritableChar.descriptor( + QBluetoothUuid::CharacteristicUserDescription); + QVERIFY(nonWritableDesc.isValid()); + irService->writeDescriptor(nonWritableDesc, QByteArray("ABCD")); + QTRY_VERIFY_WITH_TIMEOUT(!irErrorSpy.isEmpty(), 5000); + QVERIFY(irWrittenSpy.isEmpty()); + QVERIFY(irReadSpy.isEmpty()); + QCOMPARE(irErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), + QLowEnergyService::DescriptorWriteError); + irErrorSpy.clear(); + + + // ******************************************************** + // Read non-readable char + + // discover OAD Service + oadService->discoverDetails(); + QTRY_VERIFY_WITH_TIMEOUT( + oadService->state() == QLowEnergyService::ServiceDiscovered, 30000); + oadErrorSpy.clear(); + + // Test reading + QLowEnergyCharacteristic oadChar = oadService->characteristic(oadCharUuid); + QVERIFY(oadChar.isValid()); + oadService->readCharacteristic(oadChar); + QTRY_VERIFY_WITH_TIMEOUT(!oadErrorSpy.isEmpty(), 5000); + QCOMPARE(oadErrorSpy.count(), 1); + QVERIFY(oadCharReadSpy.isEmpty()); + QCOMPARE(oadErrorSpy[0].at(0).value<QLowEnergyService::ServiceError>(), + QLowEnergyService::CharacteristicReadError); + oadErrorSpy.clear(); + + delete irService; + delete oadService; + control.disconnectFromDevice(); +} + /* Tests write without responses. We utilize the Over-The-Air image update service of the SensorTag. */ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() { +#ifndef Q_OS_MAC QList<QBluetoothHostInfo> localAdapters = QBluetoothLocalDevice::allDevices(); if (localAdapters.isEmpty() || remoteDevice.isNull()) QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); // quick setup - more elaborate test is done by connect() QLowEnergyController control(remoteDevice); +#else + if (remoteDeviceInfo.deviceUuid().isNull()) + QSKIP("No local Bluetooth or remote BTLE device found. Skipping test."); + + QLowEnergyController control(remoteDeviceInfo); +#endif QCOMPARE(control.error(), QLowEnergyController::NoError); control.connectToDevice(); @@ -1979,7 +2514,7 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() QSignalSpy discoveryFinishedSpy(&control, SIGNAL(discoveryFinished())); QSignalSpy stateSpy(&control, SIGNAL(stateChanged(QLowEnergyController::ControllerState))); control.discoverServices(); - QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 10000); + QTRY_VERIFY_WITH_TIMEOUT(discoveryFinishedSpy.count() == 1, 20000); QCOMPARE(stateSpy.count(), 2); QCOMPARE(stateSpy.at(0).at(0).value<QLowEnergyController::ControllerState>(), QLowEnergyController::DiscoveringState); @@ -2005,6 +2540,7 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() QVERIFY(imageIdentityChar.isValid()); QVERIFY(imageIdentityChar.properties() & QLowEnergyCharacteristic::Write); QVERIFY(imageIdentityChar.properties() & QLowEnergyCharacteristic::WriteNoResponse); + QVERIFY(!(imageIdentityChar.properties() & QLowEnergyCharacteristic::Read)); //not readable QVERIFY(imageBlockChar.isValid()); // 2. Get "Image Identity" notification descriptor @@ -2024,7 +2560,15 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray))); QSignalSpy charWrittenSpy(service, SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy charReadSpy(service, + SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray))); + QSignalSpy errorSpy(service, + SIGNAL(error(QLowEnergyService::ServiceError))); + + // 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")); QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000); @@ -2037,8 +2581,20 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() descWrittenSpy.clear(); } - // 4. Trigger image identity announcement (using traditional write) QList<QVariant> entry; + + // Test direct read of non-readable characteristic + QVERIFY(errorSpy.isEmpty()); + QVERIFY(charReadSpy.isEmpty()); + service->readCharacteristic(imageIdentityChar); + QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 10000); + QCOMPARE(errorSpy.count(), 1); // should throw CharacteristicReadError + QVERIFY(charReadSpy.isEmpty()); + entry = errorSpy[0]; + QCOMPARE(entry[0].value<QLowEnergyService::ServiceError>(), + QLowEnergyService::CharacteristicReadError); + + // 4. Trigger image identity announcement (using traditional write) bool foundOneImage = false; // Image A @@ -2060,6 +2616,8 @@ 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. QCOMPARE(imageBlockChar, first); qWarning() << "Invalid image A ident info"; } @@ -2068,7 +2626,11 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() QLowEnergyCharacteristic second = entry[0].value<QLowEnergyCharacteristic>(); QByteArray val2 = entry[1].toByteArray(); QCOMPARE(imageIdentityChar, second); - QCOMPARE(val2, QByteArray::fromHex("0")); + QVERIFY(val2 == QByteArray::fromHex("0") || val2 == val1); + + // notifications on non-readable characteristics do not update cache + QVERIFY(imageIdentityChar.value().isEmpty()); + QVERIFY(imageBlockChar.value().isEmpty()); charChangedSpy.clear(); charWrittenSpy.clear(); @@ -2086,6 +2648,8 @@ 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. QCOMPARE(imageBlockChar, first); qWarning() << "Invalid image B ident info"; } @@ -2094,7 +2658,16 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() second = entry[0].value<QLowEnergyCharacteristic>(); val2 = entry[1].toByteArray(); QCOMPARE(imageIdentityChar, second); - QCOMPARE(val2, QByteArray::fromHex("1")); + + // notifications on non-readable characteristics do not update cache + QVERIFY(imageIdentityChar.value().isEmpty()); + QVERIFY(imageBlockChar.value().isEmpty()); + + /* Bluez resends the last confirmed write value, other platforms + * send the value received by the change notification value. + */ + qDebug() << "Image B(1):" << val1.toHex() << val2.toHex(); + QVERIFY(val2 == QByteArray::fromHex("1") || val2 == val1); QVERIFY2(foundOneImage, "The SensorTag doesn't have a valid image? (1)"); @@ -2117,15 +2690,25 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() first = entry[0].value<QLowEnergyCharacteristic>(); val1 = entry[1].toByteArray(); +#ifdef Q_OS_ANDROID + QEXPECT_FAIL("", "Android sends write confirmation when using WriteWithoutResponse", + Continue); +#endif QVERIFY(charWrittenSpy.isEmpty()); if (val1.size() == 8) { QCOMPARE(first, imageIdentityChar); foundOneImage = true; } else { + // we received a notification for imageBlockChar without explicitly + // enabling them. This is caused by the device's default settings. QCOMPARE(imageBlockChar, first); qWarning() << "Image A not set?"; } + // notifications on non-readable characteristics do not update cache + QVERIFY(imageIdentityChar.value().isEmpty()); + QVERIFY(imageBlockChar.value().isEmpty()); + charChangedSpy.clear(); // Image B @@ -2142,15 +2725,26 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() first = entry[0].value<QLowEnergyCharacteristic>(); val1 = entry[1].toByteArray(); +#ifdef Q_OS_ANDROID + QEXPECT_FAIL("", "Android sends write confirmation when using WriteWithoutResponse", + Continue); +#endif QVERIFY(charWrittenSpy.isEmpty()); if (val1.size() == 8) { QCOMPARE(first, imageIdentityChar); foundOneImage = true; } else { + // we received a notification for imageBlockChar without explicitly + // enabling them. This is caused by the device's default settings. QCOMPARE(imageBlockChar, first); qWarning() << "Image B not set?"; } + // notifications on non-readable characteristics do not update cache + QVERIFY(imageIdentityChar.value().isEmpty()); + QVERIFY(imageBlockChar.value().isEmpty()); + + QVERIFY2(foundOneImage, "The SensorTag doesn't have a valid image? (2)"); delete service; |