Introduce QSocketNotifier::activate(QSocketDescriptor, QSN::Type)

The pre-existing overload passes an int, but this can mean the
descriptor gets truncated in compilations where the descriptor
is 64-bit.

The old overload with int is visible when querying the metaobject system
so string-based connects still work as before, and connecting to it will
produce a deprecation warning in the output.
At the same time the PMF-based connect will, on recompile, pick the
QSocketDescriptor overload. As an added improvement it also comes with
the notification type, removing the need for separate slots where the
code would be mostly shared anyway.

The QSocketDescriptor type can be implicitly converted to and from
qintptr to ensure existing code still compiles. It can also be
constructed from Qt::HANDLE on Windows.

In this same patch I also update the existing string-based connects in
this module, which then includes updating the parameters for some slots
as well.

[ChangeLog][QtCore][QSocketNotifier] Added
QSocketNotifier::activated(QSocketDescriptor, QSocketNotifier::Type).
This replaces the activated(int) signal which in 64-bit environments
could truncate the socket descriptor. If you use "activated" with the
string-based connect() then you need to update the parameter type of the
signal and slot if it had one. If you use it with the pointer to member
function based connect() then all you need to do is update your slot's
parameter type if it has one. If you need to compile your source code
with multiple versions of Qt then connect() to this function using
pointer to member function and update the slot's parameter type if
needed.

Task-number: QTBUG-70441
Change-Id: Ic43d6bc4c5bcb4040867b2ffad8d36fb01eed8af
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Mårten Nordheim 2020-03-24 09:40:10 +01:00
parent b34158d7a1
commit 487dd80bce
18 changed files with 234 additions and 38 deletions

View File

@ -253,7 +253,7 @@ QInotifyFileSystemWatcherEngine::QInotifyFileSystemWatcherEngine(int fd, QObject
notifier(fd, QSocketNotifier::Read, this)
{
fcntl(inotifyFd, F_SETFD, FD_CLOEXEC);
connect(&notifier, SIGNAL(activated(int)), SLOT(readFromInotify()));
connect(&notifier, SIGNAL(activated(QSocketDescriptor)), SLOT(readFromInotify()));
}
QInotifyFileSystemWatcherEngine::~QInotifyFileSystemWatcherEngine()

View File

@ -77,7 +77,7 @@ QKqueueFileSystemWatcherEngine::QKqueueFileSystemWatcherEngine(int kqfd, QObject
kqfd(kqfd),
notifier(kqfd, QSocketNotifier::Read, this)
{
connect(&notifier, SIGNAL(activated(int)), SLOT(readFromKqueue()));
connect(&notifier, SIGNAL(activated(QSocketDescriptor)), SLOT(readFromKqueue()));
fcntl(kqfd, F_SETFD, FD_CLOEXEC);
}

View File

@ -251,7 +251,7 @@ bool QProcessPrivate::openChannel(Channel &channel)
channel.notifier = new QSocketNotifier(channel.pipe[1],
QSocketNotifier::Write, q);
channel.notifier->setEnabled(false);
QObject::connect(channel.notifier, SIGNAL(activated(int)),
QObject::connect(channel.notifier, SIGNAL(activated(QSocketDescriptor)),
q, SLOT(_q_canWrite()));
} else {
channel.notifier = new QSocketNotifier(channel.pipe[0],
@ -261,7 +261,7 @@ bool QProcessPrivate::openChannel(Channel &channel)
receiver = SLOT(_q_canReadStandardOutput());
else
receiver = SLOT(_q_canReadStandardError());
QObject::connect(channel.notifier, SIGNAL(activated(int)),
QObject::connect(channel.notifier, SIGNAL(activated(QSocketDescriptor)),
q, receiver);
}
}
@ -380,7 +380,7 @@ void QProcessPrivate::startProcess()
if (threadData.loadRelaxed()->hasEventDispatcher()) {
startupSocketNotifier = new QSocketNotifier(childStartedPipe[0],
QSocketNotifier::Read, q);
QObject::connect(startupSocketNotifier, SIGNAL(activated(int)),
QObject::connect(startupSocketNotifier, SIGNAL(activated(QSocketDescriptor)),
q, SLOT(_q_startupNotification()));
}
@ -531,7 +531,7 @@ void QProcessPrivate::startProcess()
if (threadData.loadRelaxed()->eventDispatcher.loadAcquire()) {
deathNotifier = new QSocketNotifier(forkfd, QSocketNotifier::Read, q);
QObject::connect(deathNotifier, SIGNAL(activated(int)),
QObject::connect(deathNotifier, SIGNAL(activated(QSocketDescriptor)),
q, SLOT(_q_processDied()));
}
}

View File

@ -37,23 +37,32 @@
**
****************************************************************************/
#define BUILDING_QSOCKETNOTIFIER
#include "qsocketnotifier.h"
#undef BUILDING_QSOCKETNOTIFIER
#include "qplatformdefs.h"
#include "qabstracteventdispatcher.h"
#include "qcoreapplication.h"
#include "qmetatype.h"
#include "qobject_p.h"
#include <private/qthread_p.h>
#include <QtCore/QLoggingCategory>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcSocketNotifierDeprecation)
Q_LOGGING_CATEGORY(lcSocketNotifierDeprecation, "qt.core.socketnotifier_deprecation");
class QSocketNotifierPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QSocketNotifier)
public:
qintptr sockfd;
QSocketDescriptor sockfd;
QSocketNotifier::Type sntype;
bool snenabled;
};
@ -143,13 +152,17 @@ QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent)
: QObject(*new QSocketNotifierPrivate, parent)
{
Q_D(QSocketNotifier);
qRegisterMetaType<QSocketDescriptor>();
qRegisterMetaType<QSocketNotifier::Type>();
d->sockfd = socket;
d->sntype = type;
d->snenabled = true;
auto thisThreadData = d->threadData.loadRelaxed();
if (socket < 0)
if (!d->sockfd.isValid())
qWarning("QSocketNotifier: Invalid socket specified");
else if (!thisThreadData->hasEventDispatcher())
qWarning("QSocketNotifier: Can only be used with threads started with QThread");
@ -169,6 +182,11 @@ QSocketNotifier::~QSocketNotifier()
/*!
\fn void QSocketNotifier::activated(int socket)
\obsolete To avoid unintended truncation of the descriptor, use
the QSocketDescriptor overload of this function. If you need
compatibility with versions older than 5.15 you need to change
the slot to accept qintptr if it currently accepts an int, and
then connect using Functor-Based Connection.
This signal is emitted whenever the socket notifier is enabled and
a socket event corresponding to its \l {Type}{type} occurs.
@ -178,6 +196,18 @@ QSocketNotifier::~QSocketNotifier()
\sa type(), socket()
*/
/*!
\fn void QSocketNotifier::activated(QSocketDescriptor socket, QSocketNotifier::Type type)
\since 5.15
This signal is emitted whenever the socket notifier is enabled and
a socket event corresponding to its \a type occurs.
The socket identifier is passed in the \a socket parameter.
\sa type(), socket()
*/
/*!
Returns the socket identifier specified to the constructor.
@ -187,7 +217,7 @@ QSocketNotifier::~QSocketNotifier()
qintptr QSocketNotifier::socket() const
{
Q_D(const QSocketNotifier);
return d->sockfd;
return qintptr(d->sockfd);
}
/*!
@ -230,7 +260,7 @@ bool QSocketNotifier::isEnabled() const
void QSocketNotifier::setEnabled(bool enable)
{
Q_D(QSocketNotifier);
if (d->sockfd < 0)
if (!d->sockfd.isValid())
return;
if (d->snenabled == enable) // no change
return;
@ -268,12 +298,57 @@ bool QSocketNotifier::event(QEvent *e)
}
QObject::event(e); // will activate filters
if ((e->type() == QEvent::SockAct) || (e->type() == QEvent::SockClose)) {
emit activated(d->sockfd, QPrivateSignal());
QPointer<QSocketNotifier> alive(this);
emit activated(d->sockfd, d->sntype, QPrivateSignal());
// ### Qt7: Remove emission if the activated(int) signal is removed
if (alive)
emit activated(int(qintptr(d->sockfd)), QPrivateSignal());
return true;
}
return false;
}
/*!
\class QSocketDescriptor
\inmodule QtCore
\brief A class which holds a native socket descriptor.
\ingroup network
\ingroup io
\since 5.15
QSocketDescriptor makes it easier to handle native socket
descriptors in cross-platform code.
On Windows it holds a \c {Qt::HANDLE} and on Unix it holds an \c int.
The class will implicitly convert between the class and the
native descriptor type.
*/
/*!
\fn QSocketDescriptor::QSocketDescriptor(DescriptorType descriptor)
Construct a QSocketDescriptor from a native socket \a descriptor.
*/
/*!
\fn QSocketDescriptor::QSocketDescriptor(qintptr descriptor)
Construct a QSocketDescriptor from a native socket \a descriptor.
\note This constructor is only available on Windows.
*/
/*!
\fn Qt::HANDLE QSocketDescriptor::winHandle() const noexcept
Returns the internal handle.
\note This function is only available on Windows.
*/
QT_END_NAMESPACE
#include "moc_qsocketnotifier.cpp"

View File

@ -44,6 +44,7 @@
QT_BEGIN_NAMESPACE
class QSocketDescriptor;
class QSocketNotifierPrivate;
class Q_CORE_EXPORT QSocketNotifier : public QObject
{
@ -65,7 +66,23 @@ public Q_SLOTS:
void setEnabled(bool);
Q_SIGNALS:
#if defined(Q_MOC_RUN)
// Add default arguments during Q_MOC_RUN which makes moc generate "signals" which takes less
// parameters, but we won't actually allow emitting without all 3. This lets users use the
// string-based connect without specifying QSocketNotifier::Type as one of the parameters.
void activated(QSocketDescriptor socket, QSocketNotifier::Type activationEvent = Read,
QPrivateSignal = {});
#else
void activated(QSocketDescriptor socket, QSocketNotifier::Type activationEvent, QPrivateSignal);
#endif
// ### Qt7: consider removing it.
// The old signal is compiled internally, but hidden outside of this class.
// This means the PMF-based connect(..) will automatically, on recompile, pick up the new
// version while the old-style connect(..) can query the metaobject system for this version.
#if defined(Q_MOC_RUN) || defined(BUILDING_QSOCKETNOTIFIER) || defined(Q_QDOC)
void activated(int socket, QPrivateSignal);
#endif
protected:
bool event(QEvent *) override;
@ -74,6 +91,50 @@ private:
Q_DISABLE_COPY(QSocketNotifier)
};
class QSocketDescriptor
{
public:
#if defined(Q_OS_WIN)
using DescriptorType = Qt::HANDLE;
#define Q_DECL_CONSTEXPR_NOT_WIN
#else
using DescriptorType = int;
#define Q_DECL_CONSTEXPR_NOT_WIN Q_DECL_CONSTEXPR
#endif
/* implicit */ Q_DECL_CONSTEXPR_NOT_WIN
QSocketDescriptor(DescriptorType descriptor = DescriptorType(-1)) noexcept : sockfd(descriptor)
{
}
#if defined(Q_OS_WIN) || defined(Q_QDOC)
/* implicit */ QSocketDescriptor(qintptr desc) noexcept : sockfd(DescriptorType(desc)) {}
operator qintptr() const noexcept { return qintptr(sockfd); }
Q_DECL_CONSTEXPR Qt::HANDLE winHandle() const noexcept { return sockfd; }
#endif
Q_DECL_CONSTEXPR operator DescriptorType() const noexcept { return sockfd; }
Q_DECL_CONSTEXPR_NOT_WIN bool isValid() const noexcept { return *this != QSocketDescriptor(); }
friend Q_DECL_CONSTEXPR_NOT_WIN bool operator==(QSocketDescriptor lhs,
QSocketDescriptor rhs) noexcept
{
return lhs.sockfd == rhs.sockfd;
}
friend Q_DECL_CONSTEXPR_NOT_WIN bool operator!=(QSocketDescriptor lhs,
QSocketDescriptor rhs) noexcept
{
return lhs.sockfd != rhs.sockfd;
}
#undef Q_DECL_CONSTEXPR_NOT_WIN
private:
DescriptorType sockfd;
};
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QSocketNotifier::Type)
Q_DECLARE_METATYPE(QSocketDescriptor)
#endif // QSOCKETNOTIFIER_H

View File

@ -173,7 +173,7 @@ public:
public:
// typedefs
typedef QMultiHash<int, Watcher> WatcherHash;
typedef QMultiHash<qintptr, Watcher> WatcherHash;
typedef QHash<int, DBusTimeout *> TimeoutHash;
typedef QVector<QDBusMessage> PendingMessageList;
@ -283,8 +283,8 @@ public slots:
// public slots
void setDispatchEnabled(bool enable);
void doDispatch();
void socketRead(int);
void socketWrite(int);
void socketRead(qintptr);
void socketWrite(qintptr);
void objectDestroyed(QObject *o);
void relaySignal(QObject *obj, const QMetaObject *, int signalId, const QVariantList &args);
bool addSignalHook(const QString &key, const SignalHook &hook);

View File

@ -1205,7 +1205,7 @@ void QDBusConnectionPrivate::doDispatch()
}
}
void QDBusConnectionPrivate::socketRead(int fd)
void QDBusConnectionPrivate::socketRead(qintptr fd)
{
WatcherHash::ConstIterator it = watchers.constFind(fd);
while (it != watchers.constEnd() && it.key() == fd) {
@ -1219,7 +1219,7 @@ void QDBusConnectionPrivate::socketRead(int fd)
doDispatch();
}
void QDBusConnectionPrivate::socketWrite(int fd)
void QDBusConnectionPrivate::socketWrite(qintptr fd)
{
WatcherHash::ConstIterator it = watchers.constFind(fd);
while (it != watchers.constEnd() && it.key() == fd) {

View File

@ -185,7 +185,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
Q_ASSERT(!socketNotifier);
socketNotifier = new QSocketNotifier(listenSocket,
QSocketNotifier::Read, q);
q->connect(socketNotifier, SIGNAL(activated(int)),
q->connect(socketNotifier, SIGNAL(activated(QSocketDescriptor)),
q, SLOT(_q_onNewConnection()));
socketNotifier->setEnabled(maxPendingConnections > 0);
return true;
@ -227,7 +227,7 @@ bool QLocalServerPrivate::listen(qintptr socketDescriptor)
Q_ASSERT(!socketNotifier);
socketNotifier = new QSocketNotifier(listenSocket,
QSocketNotifier::Read, q);
q->connect(socketNotifier, SIGNAL(activated(int)),
q->connect(socketNotifier, SIGNAL(activated(QSocketDescriptor)),
q, SLOT(_q_onNewConnection()));
socketNotifier->setEnabled(maxPendingConnections > 0);
return true;

View File

@ -308,7 +308,7 @@ void QLocalSocketPrivate::_q_connectToSocket()
// Try again later, all of the sockets listening are full
if (!delayConnect) {
delayConnect = new QSocketNotifier(connectingSocket, QSocketNotifier::Write, q);
q->connect(delayConnect, SIGNAL(activated(int)), q, SLOT(_q_connectToSocket()));
q->connect(delayConnect, SIGNAL(activated(QSocketDescriptor)), q, SLOT(_q_connectToSocket()));
}
if (!connectTimer) {
connectTimer = new QTimer(q);

View File

@ -92,7 +92,7 @@ QDeviceDiscoveryUDev::QDeviceDiscoveryUDev(QDeviceTypes types, struct udev *udev
m_udevMonitorFileDescriptor = udev_monitor_get_fd(m_udevMonitor);
m_udevSocketNotifier = new QSocketNotifier(m_udevMonitorFileDescriptor, QSocketNotifier::Read, this);
connect(m_udevSocketNotifier, SIGNAL(activated(int)), this, SLOT(handleUDevNotification()));
connect(m_udevSocketNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(handleUDevNotification()));
}
QDeviceDiscoveryUDev::~QDeviceDiscoveryUDev()

View File

@ -83,7 +83,7 @@ QOpenWFDDevice::QOpenWFDDevice(QOpenWFDIntegration *integration, WFDint device_e
int fd = wfdDeviceEventGetFD(mDevice,mEvent);
mEventSocketNotifier = new QSocketNotifier(fd,QSocketNotifier::Read,this);
connect(mEventSocketNotifier,SIGNAL(activated(int)),SLOT(readEvents()));
connect(mEventSocketNotifier,SIGNAL(activated(QSocketDescriptor)),SLOT(readEvents()));
mCommitedDevice = true;
commit(WFD_COMMIT_ENTIRE_DEVICE, handle());

View File

@ -96,7 +96,7 @@ void QQnxButtonEventNotifier::start()
}
m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read);
QObject::connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(updateButtonStates()));
QObject::connect(m_readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(updateButtonStates()));
qButtonDebug("successfully connected to Navigator. fd = %d", m_fd);
}

View File

@ -96,7 +96,7 @@ void QQnxNavigatorEventNotifier::start()
}
m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read);
connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(readData()));
connect(m_readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(readData()));
}
void QQnxNavigatorEventNotifier::parsePPS(const QByteArray &ppsData, QByteArray &msg, QByteArray &dat, QByteArray &id)

View File

@ -143,7 +143,7 @@ bool QQnxVirtualKeyboardPps::connect()
return false;
m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read);
QObject::connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(ppsDataReady()));
QObject::connect(m_readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(ppsDataReady()));
return true;
}

View File

@ -61,11 +61,11 @@ public:
QSmSocketReceiver(int socket)
{
QSocketNotifier* sn = new QSocketNotifier(socket, QSocketNotifier::Read, this);
connect(sn, SIGNAL(activated(int)), this, SLOT(socketActivated(int)));
connect(sn, SIGNAL(activated(QSocketDescriptor)), this, SLOT(socketActivated()));
}
public Q_SLOTS:
void socketActivated(int);
void socketActivated();
};
@ -327,7 +327,7 @@ static void sm_saveYourselfPhase2Callback(SmcConn smcConn, SmPointer clientData)
}
void QSmSocketReceiver::socketActivated(int)
void QSmSocketReceiver::socketActivated()
{
IceProcessMessages(SmcGetIceConnection(smcConnection), nullptr, nullptr);
}

View File

@ -279,7 +279,7 @@ void QPSQLDriverPrivate::checkPendingNotifications() const
Q_Q(const QPSQLDriver);
if (seid.size() && !pendingNotifyCheck) {
pendingNotifyCheck = true;
QMetaObject::invokeMethod(const_cast<QPSQLDriver*>(q), "_q_handleNotification", Qt::QueuedConnection, Q_ARG(int,0));
QMetaObject::invokeMethod(const_cast<QPSQLDriver*>(q), "_q_handleNotification", Qt::QueuedConnection);
}
}
@ -1246,7 +1246,7 @@ void QPSQLDriver::close()
d->seid.clear();
if (d->sn) {
disconnect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int)));
disconnect(d->sn, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_handleNotification()));
delete d->sn;
d->sn = nullptr;
}
@ -1603,7 +1603,7 @@ bool QPSQLDriver::subscribeToNotification(const QString &name)
if (!d->sn) {
d->sn = new QSocketNotifier(socket, QSocketNotifier::Read);
connect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int)));
connect(d->sn, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_handleNotification()));
}
} else {
qWarning("QPSQLDriver::subscribeToNotificationImplementation: PQsocket didn't return a valid socket to listen on");
@ -1639,7 +1639,7 @@ bool QPSQLDriver::unsubscribeFromNotification(const QString &name)
d->seid.removeAll(name);
if (d->seid.isEmpty()) {
disconnect(d->sn, SIGNAL(activated(int)), this, SLOT(_q_handleNotification(int)));
disconnect(d->sn, SIGNAL(activated(QSocketDescriptor)), this, SLOT(_q_handleNotification()));
delete d->sn;
d->sn = nullptr;
}
@ -1653,7 +1653,7 @@ QStringList QPSQLDriver::subscribedToNotifications() const
return d->seid;
}
void QPSQLDriver::_q_handleNotification(int)
void QPSQLDriver::_q_handleNotification()
{
Q_D(QPSQLDriver);
d->pendingNotifyCheck = false;

View File

@ -130,7 +130,7 @@ protected:
bool rollbackTransaction() override;
private Q_SLOTS:
void _q_handleNotification(int);
void _q_handleNotification();
};
QT_END_NAMESPACE

View File

@ -53,6 +53,7 @@
# undef min
#endif // Q_CC_MSVC
class tst_QSocketNotifier : public QObject
{
Q_OBJECT
@ -63,6 +64,9 @@ private slots:
void posixSockets();
#endif
void asyncMultipleDatagram();
void activationReason_data();
void activationReason();
void legacyConnect();
protected slots:
void async_readDatagramSlot();
@ -97,10 +101,10 @@ public:
{
QSocketNotifier *notifier1 =
new QSocketNotifier(readEnd1->socketDescriptor(), QSocketNotifier::Read, this);
connect(notifier1, SIGNAL(activated(int)), SLOT(handleActivated()));
connect(notifier1, SIGNAL(activated(QSocketDescriptor)), SLOT(handleActivated()));
QSocketNotifier *notifier2 =
new QSocketNotifier(readEnd2->socketDescriptor(), QSocketNotifier::Read, this);
connect(notifier2, SIGNAL(activated(int)), SLOT(handleActivated()));
connect(notifier2, SIGNAL(activated(QSocketDescriptor)), SLOT(handleActivated()));
}
public slots:
@ -284,12 +288,12 @@ void tst_QSocketNotifier::posixSockets()
{
QSocketNotifier rn(posixSocket, QSocketNotifier::Read);
connect(&rn, SIGNAL(activated(int)), &QTestEventLoop::instance(), SLOT(exitLoop()));
connect(&rn, SIGNAL(activated(QSocketDescriptor)), &QTestEventLoop::instance(), SLOT(exitLoop()));
QSignalSpy readSpy(&rn, &QSocketNotifier::activated);
QVERIFY(readSpy.isValid());
// No write notifier, some systems trigger write notification on socket creation, but not all
QSocketNotifier en(posixSocket, QSocketNotifier::Exception);
connect(&en, SIGNAL(activated(int)), &QTestEventLoop::instance(), SLOT(exitLoop()));
connect(&en, SIGNAL(activated(QSocketDescriptor)), &QTestEventLoop::instance(), SLOT(exitLoop()));
QSignalSpy errorSpy(&en, &QSocketNotifier::activated);
QVERIFY(errorSpy.isValid());
@ -306,7 +310,7 @@ void tst_QSocketNotifier::posixSockets()
QCOMPARE(buffer, "hello");
QSocketNotifier wn(posixSocket, QSocketNotifier::Write);
connect(&wn, SIGNAL(activated(int)), &QTestEventLoop::instance(), SLOT(exitLoop()));
connect(&wn, SIGNAL(activated(QSocketDescriptor)), &QTestEventLoop::instance(), SLOT(exitLoop()));
QSignalSpy writeSpy(&wn, &QSocketNotifier::activated);
QVERIFY(writeSpy.isValid());
qt_safe_write(posixSocket, "goodbye", 8);
@ -385,5 +389,61 @@ void tst_QSocketNotifier::asyncMultipleDatagram()
#endif // !Q_OS_WINRT
}
void tst_QSocketNotifier::activationReason_data()
{
QTest::addColumn<QSocketNotifier::Type>("type");
QTest::addRow("read") << QSocketNotifier::Read;
QTest::addRow("write") << QSocketNotifier::Write;
QTest::addRow("exception") << QSocketNotifier::Exception;
}
void tst_QSocketNotifier::activationReason()
{
QSocketDescriptor fd = 15;
QFETCH(QSocketNotifier::Type, type);
QSocketNotifier notifier(fd, type);
auto activation = new QEvent(QEvent::SockAct);
QCoreApplication::postEvent(&notifier, activation);
QSocketNotifier::Type notifierType;
connect(&notifier, &QSocketNotifier::activated, this,
[&notifierType, fd](QSocketDescriptor sockfd, QSocketNotifier::Type sntype) {
if (sockfd == fd)
notifierType = sntype;
else
qWarning() << "Got an unexpected socket file descriptor:" << qintptr(sockfd);
});
QCoreApplication::processEvents();
QCOMPARE(notifierType, type);
}
// This test ensures that we can connect QSocketNotifier::activated to a slot taking an integer
// or qintptr.
void tst_QSocketNotifier::legacyConnect()
{
qintptr fd = 15;
QSocketNotifier notifier(fd, QSocketNotifier::Read);
auto activation = new QEvent(QEvent::SockAct);
QCoreApplication::postEvent(&notifier, activation);
bool receivedQIntPtr = false;
connect(&notifier, &QSocketNotifier::activated, this, [&receivedQIntPtr, fd](qintptr q){
if (q == fd)
receivedQIntPtr = true;
});
bool receivedInt = false;
connect(&notifier, &QSocketNotifier::activated, this, [&receivedInt, fd](int q){
if (q == fd)
receivedInt = true;
});
QCoreApplication::processEvents();
QVERIFY(receivedQIntPtr);
QVERIFY(receivedInt);
}
QTEST_MAIN(tst_QSocketNotifier)
#include <tst_qsocketnotifier.moc>