summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorTimur Pocheptsov <timur.pocheptsov@qt.io>2023-01-03 10:37:21 +0100
committerTimur Pocheptsov <timur.pocheptsov@qt.io>2023-02-24 13:59:28 +0100
commitae1a1f5efce291f613a13757ff6f744fcca2d2ce (patch)
tree4d0b562d220783e75d4aa2cc3c5cae1d28fcd4e0 /tests
parent935ec099758487b57970732f0ecfe7021b655968 (diff)
QtBluetooth: port the code to the new permissions API (CoreBluetooth)
We only _check_ if permissions were granted, leaving it up to an application to _request_ permissions. If permission status is not 'Granted', we bail out ealy setting MissionPermissionsError. QLowEnergyController::init is now a no-op for Darwin, because it's OK to create a peripheral/central and no need to set any error yet. Autotests require minor adjustments - they were already passing if BT is off, as it is on CI (checking Bluetooth local device and its status), but if BT is somewhere on, tests can try to scan or connect not having permissions granted - for this we adjust the tests, using permission API. [ChangeLog][Important Behavior Changes][QtBluetooth][Darwin] Do not request permissions implicitly, only check them and leave it to applications to request permissions explicitly. Task-number: QTBUG-109964 Change-Id: I95c04744e979614ffb6d992da2e279e86b272679 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qbluetoothdevicediscoveryagent/tst_qbluetoothdevicediscoveryagent.cpp58
-rw-r--r--tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp37
-rw-r--r--tests/auto/qlowenergydescriptor/tst_qlowenergydescriptor.cpp28
3 files changed, 115 insertions, 8 deletions
diff --git a/tests/auto/qbluetoothdevicediscoveryagent/tst_qbluetoothdevicediscoveryagent.cpp b/tests/auto/qbluetoothdevicediscoveryagent/tst_qbluetoothdevicediscoveryagent.cpp
index daa14e45..b192e120 100644
--- a/tests/auto/qbluetoothdevicediscoveryagent/tst_qbluetoothdevicediscoveryagent.cpp
+++ b/tests/auto/qbluetoothdevicediscoveryagent/tst_qbluetoothdevicediscoveryagent.cpp
@@ -14,6 +14,14 @@
#include <qbluetoothdevicediscoveryagent.h>
#include <qbluetoothlocaldevice.h>
+#if QT_CONFIG(permissions)
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qpermissions.h>
+#include <QtCore/qnamespace.h>
+#endif // permissions
+
+#include <memory>
+
QT_USE_NAMESPACE
/*
@@ -62,12 +70,28 @@ private slots:
void tst_discoveryMethods();
private:
qsizetype noOfLocalDevices;
+ using DiscoveryAgentPtr = std::unique_ptr<QBluetoothDeviceDiscoveryAgent>;
+#if QT_CONFIG(permissions)
+ Qt::PermissionStatus permissionStatus = Qt::PermissionStatus::Undetermined;
+#endif
};
tst_QBluetoothDeviceDiscoveryAgent::tst_QBluetoothDeviceDiscoveryAgent()
{
QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
qRegisterMetaType<QBluetoothDeviceDiscoveryAgent::Error>();
+#if QT_CONFIG(permissions)
+ permissionStatus = qApp->checkPermission(QBluetoothPermission{});
+ if (permissionStatus == Qt::PermissionStatus::Undetermined) {
+ QTestEventLoop loop;
+ qApp->requestPermission(QBluetoothPermission{}, [this, &loop](const QPermission &permission){
+ permissionStatus = permission.status();
+ loop.exitLoop();
+ });
+ if (permissionStatus == Qt::PermissionStatus::Undetermined) // Did not return immediately?
+ loop.enterLoopMSecs(30000);
+ }
+#endif
}
tst_QBluetoothDeviceDiscoveryAgent::~tst_QBluetoothDeviceDiscoveryAgent()
@@ -105,21 +129,24 @@ void tst_QBluetoothDeviceDiscoveryAgent::initTestCase()
void tst_QBluetoothDeviceDiscoveryAgent::tst_invalidBtAddress()
{
- QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(
- QBluetoothAddress(QStringLiteral("11:11:11:11:11:11")));
+ DiscoveryAgentPtr discoveryAgent(new QBluetoothDeviceDiscoveryAgent(
+ QBluetoothAddress(QStringLiteral("11:11:11:11:11:11"))));
QCOMPARE(discoveryAgent->error(), QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError);
discoveryAgent->start();
QCOMPARE(discoveryAgent->isActive(), false);
- delete discoveryAgent;
- discoveryAgent = new QBluetoothDeviceDiscoveryAgent(QBluetoothAddress());
+#if QT_CONFIG(permissions)
+ if (permissionStatus != Qt::PermissionStatus::Granted)
+ return;
+#endif
+
+ discoveryAgent.reset(new QBluetoothDeviceDiscoveryAgent(QBluetoothAddress()));
QCOMPARE(discoveryAgent->error(), QBluetoothDeviceDiscoveryAgent::NoError);
if (!QBluetoothLocalDevice::allDevices().isEmpty()) {
discoveryAgent->start();
QCOMPARE(discoveryAgent->isActive(), true);
}
- delete discoveryAgent;
}
void tst_QBluetoothDeviceDiscoveryAgent::deviceDiscoveryDebug(const QBluetoothDeviceInfo &info)
@@ -131,6 +158,7 @@ void tst_QBluetoothDeviceDiscoveryAgent::tst_startStopDeviceDiscoveries()
{
if (androidBluetoothEmulator())
QSKIP("Skipping test on Android 12+ emulator, CI can timeout waiting for user input");
+
QBluetoothDeviceDiscoveryAgent discoveryAgent;
QVERIFY(discoveryAgent.error() == discoveryAgent.NoError);
@@ -148,6 +176,14 @@ void tst_QBluetoothDeviceDiscoveryAgent::tst_startStopDeviceDiscoveries()
QVERIFY(errorSpy.isEmpty());
discoveryAgent.start();
+#if QT_CONFIG(permissions)
+ if (permissionStatus != Qt::PermissionStatus::Granted) {
+ // If bluetooth is OFF, the permission does not get checked (e.g. on Darwin),
+ // but not to depend on the order in which errors generated, we
+ // do not compare error value with MissionPermissionsError here.
+ return;
+ }
+#endif
if (errorSpy.isEmpty()) {
QVERIFY(discoveryAgent.isActive());
@@ -327,7 +363,12 @@ void tst_QBluetoothDeviceDiscoveryAgent::tst_deviceDiscovery()
// this, SLOT(deviceDiscoveryDebug(QBluetoothDeviceInfo)));
discoveryAgent.start();
+
if (!errorSpy.isEmpty()) {
+#if QT_CONFIG(permissions)
+ if (permissionStatus == Qt::PermissionStatus::Granted)
+#endif
+
QCOMPARE(noOfLocalDevices, 0);
QVERIFY(!discoveryAgent.isActive());
QSKIP("No local Bluetooth device available. Skipping remaining part of test.");
@@ -457,10 +498,15 @@ void tst_QBluetoothDeviceDiscoveryAgent::tst_discoveryMethods()
// Start discovery, probably both Classic and LE methods:
agent.start(supportedMethods);
+#if QT_CONFIG(permissions)
+ if (permissionStatus != Qt::PermissionStatus::Granted) {
+ QCOMPARE(agent.error(), QBluetoothDeviceDiscoveryAgent::MissingPermissionsError);
+ QSKIP("The remaining test requires the Bluetooth permission granted");
+ }
+#endif
QVERIFY(agent.isActive());
QVERIFY(errorSpy.isEmpty());
-
#define RUN_DISCOVERY(maxTimeout, step, condition) \
for (int scanTime = maxTimeout; (condition) && scanTime > 0; scanTime -= step) \
QTest::qWait(step);
diff --git a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
index c83f4bc5..ed4a86bb 100644
--- a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
+++ b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
@@ -14,6 +14,13 @@
#include <QLowEnergyController>
#include <QLowEnergyCharacteristic>
+#if QT_CONFIG(permissions)
+#include <QCoreApplication>
+#include <QPermissions>
+
+#include <QtCore/qnamespace.h>
+#endif
+
#include <QDebug>
/*!
@@ -59,6 +66,9 @@ private:
QBluetoothDeviceInfo remoteDeviceInfo;
QList<QBluetoothUuid> foundServices;
bool isBluezDbusLE = false;
+#if QT_CONFIG(permissions)
+ Qt::PermissionStatus permissionStatus = Qt::PermissionStatus::Undetermined;
+#endif
};
tst_QLowEnergyController::tst_QLowEnergyController()
@@ -81,6 +91,24 @@ tst_QLowEnergyController::tst_QLowEnergyController()
isBluezDbusLE = (bluetoothdVersion() >= QVersionNumber(5, 42));
qDebug() << "isDBusBluez:" << isBluezDbusLE;
#endif
+
+#if QT_CONFIG(permissions)
+ // FIXME: for Android, set additional parameters for scan and connect
+ // permissions.
+ permissionStatus = qApp->checkPermission(QBluetoothPermission{});
+ if (permissionStatus == Qt::PermissionStatus::Undetermined) {
+ QTestEventLoop eventLoop;
+ qApp->requestPermission(QBluetoothPermission{}, [this, &eventLoop](const QPermission &permission){
+ permissionStatus = permission.status();
+ eventLoop.exitLoop();
+ });
+ if (permissionStatus == Qt::PermissionStatus::Undetermined)
+ eventLoop.enterLoop(30000);
+ }
+ // Note: even with missing Bluetooth permission, we still can run tests on
+ // LE controller to test its logic/errors it emits, even if we cannot scan
+ // and cannot connect.
+#endif // permission
}
tst_QLowEnergyController::~tst_QLowEnergyController()
@@ -109,7 +137,6 @@ void tst_QLowEnergyController::initTestCase()
#endif
// QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
-
devAgent = new QBluetoothDeviceDiscoveryAgent(this);
devAgent->setLowEnergyDiscoveryTimeout(5000);
@@ -120,6 +147,12 @@ void tst_QLowEnergyController::initTestCase()
bool deviceFound = false;
devAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
+#if QT_CONFIG(permissions)
+ if (permissionStatus != Qt::PermissionStatus::Granted) {
+ QCOMPARE(devAgent->error(), QBluetoothDeviceDiscoveryAgent::MissingPermissionsError);
+ return;
+ }
+#endif
QTRY_VERIFY_WITH_TIMEOUT(!finishedSpy.isEmpty(), 30000);
const QList<QBluetoothDeviceInfo> infos = devAgent->discoveredDevices();
for (const QBluetoothDeviceInfo &info : infos) {
@@ -223,6 +256,7 @@ void tst_QLowEnergyController::tst_emptyCtor()
#else
QCOMPARE(control->error(), QLowEnergyController::NoError);
#endif
+
control->connectToDevice();
QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 10000);
@@ -234,7 +268,6 @@ void tst_QLowEnergyController::tst_emptyCtor()
QVERIFY(lastError == QLowEnergyController::UnknownRemoteDeviceError // if local device on platform found
|| lastError == QLowEnergyController::InvalidBluetoothAdapterError); // otherwise, e.g. fallback backend
}
-
}
void tst_QLowEnergyController::tst_connect()
diff --git a/tests/auto/qlowenergydescriptor/tst_qlowenergydescriptor.cpp b/tests/auto/qlowenergydescriptor/tst_qlowenergydescriptor.cpp
index b3046a52..80ad9938 100644
--- a/tests/auto/qlowenergydescriptor/tst_qlowenergydescriptor.cpp
+++ b/tests/auto/qlowenergydescriptor/tst_qlowenergydescriptor.cpp
@@ -12,6 +12,12 @@
#include <QLowEnergyController>
#include <QBluetoothLocalDevice>
+#if QT_CONFIG(permissions)
+#include <QCoreApplication>
+#include <QPermissions>
+#include <QtCore/qnamespace.h>
+#endif
+
QT_USE_NAMESPACE
class tst_QLowEnergyDescriptor : public QObject
@@ -35,12 +41,27 @@ private:
QList<QBluetoothDeviceInfo> remoteLeDeviceInfos;
QLowEnergyController *globalControl;
QLowEnergyService *globalService;
+#if QT_CONFIG(permissions)
+ Qt::PermissionStatus permissionStatus = Qt::PermissionStatus::Undetermined;
+#endif
};
tst_QLowEnergyDescriptor::tst_QLowEnergyDescriptor() :
globalControl(nullptr), globalService(nullptr)
{
QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+#if QT_CONFIG(permissions)
+ permissionStatus = qApp->checkPermission(QBluetoothPermission{});
+ if (permissionStatus == Qt::PermissionStatus::Undetermined) {
+ QTestEventLoop loop;
+ qApp->requestPermission(QBluetoothPermission{}, [this, &loop](const QPermission &permission){
+ permissionStatus = permission.status();
+ loop.exitLoop();
+ });
+ if (permissionStatus == Qt::PermissionStatus::Undetermined)
+ loop.enterLoopMSecs(30000);
+ }
+#endif
}
tst_QLowEnergyDescriptor::~tst_QLowEnergyDescriptor()
@@ -65,6 +86,13 @@ void tst_QLowEnergyDescriptor::initTestCase()
}
}
+#if QT_CONFIG(permissions)
+ if (permissionStatus != Qt::PermissionStatus::Granted) {
+ qWarning("Use of BLuetooth LE requires the Bluetooth permission granted");
+ return;
+ }
+#endif
+
// find an arbitrary low energy device in vicinity
// find an arbitrary service with descriptor