blob: cbce504208846745c0b6f4b61aadfd6cfac85b6f [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <QDebug>
#include <QVariant>
#include <QList>
#include <QLoggingCategory>
#include <private/qtbluetoothglobal_p.h>
#include <qbluetoothaddress.h>
#include <qbluetoothdevicediscoveryagent.h>
#include <qbluetoothlocaldevice.h>
QT_USE_NAMESPACE
/*
* Some parts of this test require a remote and discoverable Bluetooth
* device. Setting the BT_TEST_DEVICE environment variable will
* set the test up to fail if it cannot find a remote device.
* BT_TEST_DEVICE should contain the address of the device the
* test expects to find. Ensure that the device is running
* in discovery mode.
**/
// Maximum time to for bluetooth device scan
const int MaxScanTime = 5 * 60 * 1000; // 5 minutes in ms
//Bluez needs at least 10s for a device discovery to be cancelled
const int MaxWaitForCancelTime = 15 * 1000; // 15 seconds in ms
class tst_QBluetoothDeviceDiscoveryAgent : public QObject
{
Q_OBJECT
public:
tst_QBluetoothDeviceDiscoveryAgent();
~tst_QBluetoothDeviceDiscoveryAgent();
public slots:
void deviceDiscoveryDebug(const QBluetoothDeviceInfo &info);
void finished();
private slots:
void initTestCase();
void tst_properties();
void tst_invalidBtAddress();
void tst_startStopDeviceDiscoveries();
void tst_deviceDiscovery_data();
void tst_deviceDiscovery();
void tst_discoveryTimeout();
void tst_discoveryMethods();
private:
int noOfLocalDevices;
bool isBluez5Runtime = false;
};
tst_QBluetoothDeviceDiscoveryAgent::tst_QBluetoothDeviceDiscoveryAgent()
{
QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
qRegisterMetaType<QBluetoothDeviceDiscoveryAgent::Error>();
}
tst_QBluetoothDeviceDiscoveryAgent::~tst_QBluetoothDeviceDiscoveryAgent()
{
}
#if QT_CONFIG(bluez)
// This section was adopted from tst_qloggingcategory.cpp
QString logMessage;
QByteArray qMyMessageFormatString(QtMsgType type, const QMessageLogContext &context,
const QString &str)
{
QByteArray message;
message.append(context.category);
switch (type) {
case QtDebugMsg: message.append(".debug"); break;
case QtInfoMsg: message.append(".info"); break;
case QtWarningMsg: message.append(".warning"); break;
case QtCriticalMsg:message.append(".critical"); break;
case QtFatalMsg: message.append(".fatal"); break;
}
message.append(": ");
message.append(qPrintable(str));
return message.simplified();
}
static void myCustomMessageHandler(QtMsgType type,
const QMessageLogContext &context,
const QString &msg)
{
logMessage = qMyMessageFormatString(type, context, msg);
}
#endif
void tst_QBluetoothDeviceDiscoveryAgent::initTestCase()
{
qRegisterMetaType<QBluetoothDeviceInfo>();
qRegisterMetaType<QBluetoothDeviceDiscoveryAgent::InquiryType>();
#if QT_CONFIG(bluez)
// To distinguish Bluez 4 and 5 we peek into the debug output
// of first Bluetooth ctor. It executes a runtime test and prints the result
// as logging output. This avoids more complex runtime detection logic within this unit test.
QtMessageHandler oldMessageHandler;
oldMessageHandler = qInstallMessageHandler(myCustomMessageHandler);
noOfLocalDevices = QBluetoothLocalDevice::allDevices().count();
qInstallMessageHandler(oldMessageHandler);
isBluez5Runtime = logMessage.contains(QStringLiteral("Bluez 5"));
if (isBluez5Runtime)
qDebug() << "BlueZ 5 runtime detected.";
#else
noOfLocalDevices = QBluetoothLocalDevice::allDevices().count();
#endif
if (!noOfLocalDevices)
return;
// turn on BT in case it is not on
QBluetoothLocalDevice *device = new QBluetoothLocalDevice();
if (device->hostMode() == QBluetoothLocalDevice::HostPoweredOff) {
QSignalSpy hostModeSpy(device, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)));
QVERIFY(hostModeSpy.isEmpty());
device->powerOn();
int connectTime = 5000; // ms
while (hostModeSpy.count() < 1 && connectTime > 0) {
QTest::qWait(500);
connectTime -= 500;
}
QVERIFY(hostModeSpy.count() > 0);
}
QBluetoothLocalDevice::HostMode hostMode= device->hostMode();
QVERIFY(hostMode == QBluetoothLocalDevice::HostConnectable
|| hostMode == QBluetoothLocalDevice::HostDiscoverable
|| hostMode == QBluetoothLocalDevice::HostDiscoverableLimitedInquiry);
delete device;
}
void tst_QBluetoothDeviceDiscoveryAgent::tst_properties()
{
QBluetoothDeviceDiscoveryAgent discoveryAgent;
QCOMPARE(discoveryAgent.inquiryType(), QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry);
discoveryAgent.setInquiryType(QBluetoothDeviceDiscoveryAgent::LimitedInquiry);
QCOMPARE(discoveryAgent.inquiryType(), QBluetoothDeviceDiscoveryAgent::LimitedInquiry);
discoveryAgent.setInquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry);
QCOMPARE(discoveryAgent.inquiryType(), QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry);
}
void tst_QBluetoothDeviceDiscoveryAgent::tst_invalidBtAddress()
{
QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(QBluetoothAddress("11:11:11:11:11:11"));
QCOMPARE(discoveryAgent->error(), QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError);
discoveryAgent->start();
QCOMPARE(discoveryAgent->isActive(), false);
delete discoveryAgent;
discoveryAgent = new QBluetoothDeviceDiscoveryAgent(QBluetoothAddress());
QCOMPARE(discoveryAgent->error(), QBluetoothDeviceDiscoveryAgent::NoError);
if (QBluetoothLocalDevice::allDevices().count() > 0) {
discoveryAgent->start();
QCOMPARE(discoveryAgent->isActive(), true);
}
delete discoveryAgent;
}
void tst_QBluetoothDeviceDiscoveryAgent::deviceDiscoveryDebug(const QBluetoothDeviceInfo &info)
{
qDebug() << "Discovered device:" << info.address().toString() << info.name();
}
void tst_QBluetoothDeviceDiscoveryAgent::tst_startStopDeviceDiscoveries()
{
QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType = QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry;
QBluetoothDeviceDiscoveryAgent discoveryAgent;
QVERIFY(discoveryAgent.error() == discoveryAgent.NoError);
QVERIFY(discoveryAgent.errorString().isEmpty());
QVERIFY(!discoveryAgent.isActive());
QVERIFY(discoveryAgent.discoveredDevices().isEmpty());
QSignalSpy finishedSpy(&discoveryAgent, SIGNAL(finished()));
QSignalSpy cancelSpy(&discoveryAgent, SIGNAL(canceled()));
QSignalSpy errorSpy(&discoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)));
// Starting case 1: start-stop, expecting cancel signal
discoveryAgent.setInquiryType(inquiryType);
// we should have no errors at this point.
QVERIFY(errorSpy.isEmpty());
discoveryAgent.start();
if (errorSpy.isEmpty()) {
QVERIFY(discoveryAgent.isActive());
QCOMPARE(discoveryAgent.errorString(), QString());
QCOMPARE(discoveryAgent.error(), QBluetoothDeviceDiscoveryAgent::NoError);
} else {
QCOMPARE(noOfLocalDevices, 0);
QVERIFY(!discoveryAgent.isActive());
QVERIFY(!discoveryAgent.errorString().isEmpty());
QVERIFY(discoveryAgent.error() != QBluetoothDeviceDiscoveryAgent::NoError);
QSKIP("No local Bluetooth device available. Skipping remaining part of test.");
}
// cancel current request.
discoveryAgent.stop();
// Wait for up to MaxWaitForCancelTime for the cancel to finish
int waitTime = MaxWaitForCancelTime;
while (cancelSpy.count() == 0 && waitTime > 0) {
QTest::qWait(100);
waitTime-=100;
}
// we should not be active anymore
QVERIFY(!discoveryAgent.isActive());
QVERIFY(errorSpy.isEmpty());
QCOMPARE(cancelSpy.count(), 1);
cancelSpy.clear();
// Starting case 2: start-start-stop, expecting cancel signal
discoveryAgent.start();
// we should be active now
QVERIFY(discoveryAgent.isActive());
QVERIFY(errorSpy.isEmpty());
// start again. should this be error?
discoveryAgent.start();
QVERIFY(discoveryAgent.isActive());
QVERIFY(errorSpy.isEmpty());
// stop
discoveryAgent.stop();
// Wait for up to MaxWaitForCancelTime for the cancel to finish
waitTime = MaxWaitForCancelTime;
while (cancelSpy.count() == 0 && waitTime > 0) {
QTest::qWait(100);
waitTime-=100;
}
// we should not be active anymore
QVERIFY(!discoveryAgent.isActive());
QVERIFY(errorSpy.isEmpty());
QVERIFY(cancelSpy.count() == 1);
cancelSpy.clear();
// Starting case 3: stop
discoveryAgent.stop();
QVERIFY(!discoveryAgent.isActive());
QVERIFY(errorSpy.isEmpty());
// Don't expect finished signal and no error
QVERIFY(finishedSpy.count() == 0);
QVERIFY(discoveryAgent.error() == discoveryAgent.NoError);
QVERIFY(discoveryAgent.errorString().isEmpty());
/*
Starting case 4: start-stop-start-stop:
We are testing that two subsequent stop() calls reduce total number
of cancel() signals to 1 if the true cancellation requires
asynchronous function calls (signal consolidation); otherwise we
expect 2x cancel() signal.
Examples are:
- Bluez4 (event loop needs to run for cancel)
- Bluez5 (no event loop required)
*/
bool immediateSignal = false;
discoveryAgent.start();
QVERIFY(discoveryAgent.isActive());
QVERIFY(errorSpy.isEmpty());
// cancel current request.
discoveryAgent.stop();
//should only have triggered cancel() if stop didn't involve the event loop
if (cancelSpy.count() == 1) immediateSignal = true;
// start a new one
discoveryAgent.start();
// we should be active now
QVERIFY(discoveryAgent.isActive());
QVERIFY(errorSpy.isEmpty());
// stop
discoveryAgent.stop();
if (immediateSignal)
QVERIFY(cancelSpy.count() == 2);
// Wait for up to MaxWaitForCancelTime for the cancel to finish
waitTime = MaxWaitForCancelTime;
while (cancelSpy.count() == 0 && waitTime > 0) {
QTest::qWait(100);
waitTime-=100;
}
// we should not be active anymore
QVERIFY(!discoveryAgent.isActive());
QVERIFY(errorSpy.isEmpty());
// should only have 1 cancel
if (immediateSignal)
QVERIFY(cancelSpy.count() == 2);
else
QVERIFY(cancelSpy.count() == 1);
cancelSpy.clear();
// Starting case 5: start-stop-start: expecting finished signal & no cancel
discoveryAgent.start();
QVERIFY(discoveryAgent.isActive());
QVERIFY(errorSpy.isEmpty());
// cancel current request.
discoveryAgent.stop();
// start a new one
discoveryAgent.start();
// we should be active now
QVERIFY(discoveryAgent.isActive());
QVERIFY(errorSpy.isEmpty());
// Wait for up to MaxScanTime for the cancel to finish
waitTime = MaxScanTime;
while (finishedSpy.count() == 0 && waitTime > 0) {
QTest::qWait(1000);
waitTime-=1000;
}
// we should not be active anymore
QVERIFY(!discoveryAgent.isActive());
QVERIFY(errorSpy.isEmpty());
// should only have 1 cancel
QVERIFY(finishedSpy.count() == 1);
// On OS X, stop is synchronous (signal will be emitted immediately).
if (!immediateSignal)
QVERIFY(cancelSpy.isEmpty());
}
void tst_QBluetoothDeviceDiscoveryAgent::finished()
{
qDebug() << "Finished called";
}
void tst_QBluetoothDeviceDiscoveryAgent::tst_deviceDiscovery_data()
{
QTest::addColumn<QBluetoothDeviceDiscoveryAgent::InquiryType>("inquiryType");
QTest::newRow("general unlimited inquiry") << QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry;
QTest::newRow("limited inquiry") << QBluetoothDeviceDiscoveryAgent::LimitedInquiry;
}
void tst_QBluetoothDeviceDiscoveryAgent::tst_deviceDiscovery()
{
{
QFETCH(QBluetoothDeviceDiscoveryAgent::InquiryType, inquiryType);
//Run test in case of multiple Bluetooth adapters
QBluetoothLocalDevice localDevice;
//We will use default adapter if there is no other adapter
QBluetoothAddress address = localDevice.address();
int numberOfAdapters = (localDevice.allDevices()).size();
QList<QBluetoothAddress> addresses;
if (numberOfAdapters > 1) {
for (int i=0; i < numberOfAdapters; i++) {
addresses.append(((QBluetoothHostInfo)localDevice.allDevices().at(i)).address());
}
address = (QBluetoothAddress)addresses.at(0);
}
QBluetoothDeviceDiscoveryAgent discoveryAgent(address);
QVERIFY(discoveryAgent.error() == discoveryAgent.NoError);
QVERIFY(discoveryAgent.errorString().isEmpty());
QVERIFY(!discoveryAgent.isActive());
QVERIFY(discoveryAgent.discoveredDevices().isEmpty());
QSignalSpy finishedSpy(&discoveryAgent, SIGNAL(finished()));
QSignalSpy errorSpy(&discoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)));
QSignalSpy discoveredSpy(&discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)));
// connect(&discoveryAgent, SIGNAL(finished()), this, SLOT(finished()));
// connect(&discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
// this, SLOT(deviceDiscoveryDebug(QBluetoothDeviceInfo)));
discoveryAgent.setInquiryType(inquiryType);
discoveryAgent.start();
if (!errorSpy.isEmpty()) {
QCOMPARE(noOfLocalDevices, 0);
QVERIFY(!discoveryAgent.isActive());
QSKIP("No local Bluetooth device available. Skipping remaining part of test.");
}
QVERIFY(discoveryAgent.isActive());
// Wait for up to MaxScanTime for the scan to finish
int scanTime = MaxScanTime;
while (finishedSpy.count() == 0 && scanTime > 0) {
QTest::qWait(15000);
scanTime -= 15000;
}
// verify that we are finished
QVERIFY(!discoveryAgent.isActive());
// stop
discoveryAgent.stop();
QVERIFY(!discoveryAgent.isActive());
qDebug() << "Scan time left:" << scanTime;
// Expect finished signal with no error
QVERIFY(finishedSpy.count() == 1);
QVERIFY(errorSpy.isEmpty());
QVERIFY(discoveryAgent.error() == discoveryAgent.NoError);
QVERIFY(discoveryAgent.errorString().isEmpty());
// verify that the list is as big as the signals received.
QVERIFY(discoveredSpy.count() == discoveryAgent.discoveredDevices().length());
// verify that there really was some devices in the array
const QString remote = qgetenv("BT_TEST_DEVICE");
QBluetoothAddress remoteDevice;
if (!remote.isEmpty()) {
remoteDevice = QBluetoothAddress(remote);
QVERIFY2(!remote.isNull(), "Expecting valid Bluetooth address to be passed via BT_TEST_DEVICE");
} else {
qWarning() << "Not using a remote device for testing. Set BT_TEST_DEVICE env to run extended tests involving a remote device";
}
if (!remoteDevice.isNull())
QVERIFY(discoveredSpy.count() > 0);
int counter = 0;
// All returned QBluetoothDeviceInfo should be valid.
while (!discoveredSpy.isEmpty()) {
const QBluetoothDeviceInfo info =
qvariant_cast<QBluetoothDeviceInfo>(discoveredSpy.takeFirst().at(0));
QVERIFY(info.isValid());
qDebug() << "Discovered device:" << info.address().toString() << info.name();
if (numberOfAdapters > 1) {
for (int i= 1; i < numberOfAdapters; i++) {
if (info.address().toString() == addresses[i].toString())
counter++;
}
}
}
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || QT_CONFIG(winrt_bt)
//On iOS/WinRT, we do not have access to the local device/adapter, numberOfAdapters is 0,
//so we skip this test at all.
QSKIP("iOS/WinRT: no local Bluetooth device available. Skipping remaining part of test.");
#endif
//For multiple Bluetooth adapter do the check only for GeneralUnlimitedInquiry.
if (!(inquiryType == QBluetoothDeviceDiscoveryAgent::LimitedInquiry))
QVERIFY((numberOfAdapters-1) == counter);
}
}
void tst_QBluetoothDeviceDiscoveryAgent::tst_discoveryTimeout()
{
QBluetoothDeviceDiscoveryAgent agent;
// check default values
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) || defined(Q_OS_ANDROID) || QT_CONFIG(winrt_bt)
QCOMPARE(agent.lowEnergyDiscoveryTimeout(), 25000);
agent.setLowEnergyDiscoveryTimeout(-1); // negative ignored
QCOMPARE(agent.lowEnergyDiscoveryTimeout(), 25000);
agent.setLowEnergyDiscoveryTimeout(20000);
QCOMPARE(agent.lowEnergyDiscoveryTimeout(), 20000);
#elif QT_CONFIG(bluez)
if (isBluez5Runtime) {
QCOMPARE(agent.lowEnergyDiscoveryTimeout(), 20000);
agent.setLowEnergyDiscoveryTimeout(-1); // negative ignored
QCOMPARE(agent.lowEnergyDiscoveryTimeout(), 20000);
agent.setLowEnergyDiscoveryTimeout(25000);
QCOMPARE(agent.lowEnergyDiscoveryTimeout(), 25000);
} else {
QCOMPARE(agent.lowEnergyDiscoveryTimeout(), -1);
agent.setLowEnergyDiscoveryTimeout(20000); // feature not supported -> ignored
QCOMPARE(agent.lowEnergyDiscoveryTimeout(), -1);
}
#else
QCOMPARE(agent.lowEnergyDiscoveryTimeout(), -1);
agent.setLowEnergyDiscoveryTimeout(20000); // feature not supported -> ignored
QCOMPARE(agent.lowEnergyDiscoveryTimeout(), -1);
#endif
}
void tst_QBluetoothDeviceDiscoveryAgent::tst_discoveryMethods()
{
const QBluetoothLocalDevice localDevice;
if (localDevice.allDevices().size() != 1) {
// On iOS it returns 0 but we still have working BT.
#ifndef Q_OS_IOS
QSKIP("This test expects exactly one local device working");
#endif
}
const QBluetoothDeviceDiscoveryAgent::DiscoveryMethods
supportedMethods = QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods();
QVERIFY(supportedMethods != QBluetoothDeviceDiscoveryAgent::NoMethod);
QBluetoothDeviceDiscoveryAgent::DiscoveryMethod
unsupportedMethods = QBluetoothDeviceDiscoveryAgent::NoMethod;
QBluetoothDeviceInfo::CoreConfiguration
expectedConfiguration = QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration;
if (supportedMethods == QBluetoothDeviceDiscoveryAgent::ClassicMethod) {
unsupportedMethods = QBluetoothDeviceDiscoveryAgent::LowEnergyMethod;
expectedConfiguration = QBluetoothDeviceInfo::BaseRateCoreConfiguration;
} else if (supportedMethods == QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) {
unsupportedMethods = QBluetoothDeviceDiscoveryAgent::ClassicMethod;
expectedConfiguration = QBluetoothDeviceInfo::LowEnergyCoreConfiguration;
}
QBluetoothDeviceDiscoveryAgent agent;
QSignalSpy finishedSpy(&agent, SIGNAL(finished()));
QSignalSpy errorSpy(&agent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)));
QSignalSpy discoveredSpy(&agent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)));
// NoMethod - should just immediately return:
agent.start(QBluetoothDeviceDiscoveryAgent::NoMethod);
QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::NoError);
QVERIFY(!agent.isActive());
QCOMPARE(finishedSpy.size(), 0);
QCOMPARE(errorSpy.size(), 0);
QCOMPARE(discoveredSpy.size(), 0);
if (unsupportedMethods != QBluetoothDeviceDiscoveryAgent::NoMethod) {
agent.start(unsupportedMethods);
QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod);
QVERIFY(!agent.isActive());
QVERIFY(finishedSpy.isEmpty());
QCOMPARE(errorSpy.size(), 1);
errorSpy.clear();
QVERIFY(discoveredSpy.isEmpty());
}
// Start discovery, probably both Classic and LE methods:
agent.start(supportedMethods);
QVERIFY(agent.isActive());
QVERIFY(errorSpy.isEmpty());
#define RUN_DISCOVERY(maxTimeout, step, condition) \
for (int scanTime = maxTimeout; (condition) && scanTime > 0; scanTime -= step) \
QTest::qWait(step);
// Wait for up to MaxScanTime for the scan to finish
const int timeStep = 15000;
RUN_DISCOVERY(MaxScanTime, timeStep, finishedSpy.isEmpty())
QVERIFY(!agent.isActive());
QVERIFY(errorSpy.size() <= 1);
if (errorSpy.size()) {
// For example, old iOS device could report it supports LE method,
// but it actually does not.
QVERIFY(supportedMethods == QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod);
} else {
QVERIFY(finishedSpy.count() == 1);
QVERIFY(agent.error() == QBluetoothDeviceDiscoveryAgent::NoError);
QVERIFY(agent.errorString().isEmpty());
while (!discoveredSpy.isEmpty()) {
const QBluetoothDeviceInfo info =
qvariant_cast<QBluetoothDeviceInfo>(discoveredSpy.takeFirst().at(0));
QVERIFY(info.isValid());
QVERIFY(info.coreConfigurations() & expectedConfiguration);
}
}
if (unsupportedMethods != QBluetoothDeviceDiscoveryAgent::NoMethod)
return;
// Both methods were reported as supported. We already tested them
// above, now let's test first Classic then LE.
finishedSpy.clear();
errorSpy.clear();
discoveredSpy.clear();
agent.start(QBluetoothDeviceDiscoveryAgent::ClassicMethod);
QVERIFY(agent.isActive());
QVERIFY(errorSpy.isEmpty());
QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::NoError);
RUN_DISCOVERY(MaxScanTime, timeStep, finishedSpy.isEmpty())
QVERIFY(!agent.isActive());
QVERIFY(errorSpy.isEmpty());
QCOMPARE(finishedSpy.size(), 1);
finishedSpy.clear();
discoveredSpy.clear();
agent.start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
QVERIFY(agent.isActive());
QVERIFY(errorSpy.isEmpty());
RUN_DISCOVERY(MaxScanTime, timeStep, finishedSpy.isEmpty() && errorSpy.isEmpty())
QVERIFY(!agent.isActive());
QVERIFY(errorSpy.size() <= 1);
if (errorSpy.size()) {
QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod);
qDebug() << "QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods is inaccurate"
" on your platform/with your device, LowEnergyMethod is not supported";
} else {
QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::NoError);
QCOMPARE(finishedSpy.size(), 1);
}
}
QTEST_MAIN(tst_QBluetoothDeviceDiscoveryAgent)
#include "tst_qbluetoothdevicediscoveryagent.moc"