diff options
| author | Thiago Macieira <[email protected]> | 2025-10-17 10:34:13 -0700 |
|---|---|---|
| committer | Thiago Macieira <[email protected]> | 2025-10-21 16:56:19 -0700 |
| commit | 30985c1fabb7281f2ac86cf576a092b7d48aeb3b (patch) | |
| tree | 440fd9c9714969b630d61c1c480f751aa86092f6 | |
| parent | 6ec878ccab1b86b46f9dff8d42677f7b260110b2 (diff) | |
tst_QUdpSocket: update the whitelisting of destinationAddress() support
We had hardcoded Linux, Windows, and the BSDs (which includes macOS and
FreeBSD), which are all OSes I can directly test. Instead of duplicating
the checks everywhere and often not doing it properly, let's centralize
with a static constexpr variable and a correct comment.
In addition, it turns out that all platforms in our CI support receiving
the IPv4 destination address. Indeed, QNX[1][2] and VxWorks
documentations indicate they do have IP_RECVDSTADDR.
Though, it looks like QNX fails to convey the destination address to a
dual-stack IPv6 socket when the sender is IPv4. That's probably an OS
bug. On FreeBSD, which also uses IP_RECVDSTADDR for IPv4, the
ancillary data was present.
[1] https://www.qnx.com/developers/docs/6.5.0SP1.update/com.qnx.doc.neutrino_lib_ref/i/ip_proto.html
[2] https://www.qnx.com/developers/docs/7.0.0/#com.qnx.doc.neutrino.lib_ref/topic/i/ip_proto.html
Change-Id: I6ee58e3f896e07c9eaa9fffdac51d092901ea855
Reviewed-by: MÃ¥rten Nordheim <[email protected]>
| -rw-r--r-- | tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp | 48 |
1 files changed, 21 insertions, 27 deletions
diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index 7d52c9cc01a..40292f0c44d 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -141,6 +141,16 @@ private: QUdpSocket *m_asyncReceiver; }; +// Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of obtaining +// the packet's destination addresses. This means the destinationAddress() be +// empty, so whitelist the OSes for which we know we have an implementation. +// That's currently all of them, which means there probably is code in this +// test that assumes this works without checking this variable. +// +// Note: this applies to single-stack operations; dual stack implementations +// appear to be buggy or not present at all in some OSes. +static constexpr bool HasWorkingIPv4DestinationAddress = true; + #ifdef SHOULD_CHECK_SYSCALL_SUPPORT bool tst_QUdpSocket::ipv6SetsockoptionMissing(int level, int optname) { @@ -585,12 +595,12 @@ void tst_QUdpSocket::broadcasting() QVERIFY2(allAddresses.contains(dgram.senderAddress()), dgram.senderAddress().toString().toLatin1()); QCOMPARE(dgram.senderPort(), int(broadcastSocket.localPort())); - if (!dgram.destinationAddress().isNull()) { + if (HasWorkingIPv4DestinationAddress) { QVERIFY2(dgram.destinationAddress() == QHostAddress::Broadcast || broadcastAddresses.contains(dgram.destinationAddress()), dgram.destinationAddress().toString().toLatin1()); - QCOMPARE(dgram.destinationPort(), int(serverSocket.localPort())); } + QCOMPARE(dgram.destinationPort(), int(serverSocket.localPort())); int ttl = dgram.hopLimit(); if (ttl != -1) @@ -755,15 +765,7 @@ void tst_QUdpSocket::loop() QCOMPARE(paulDatagram.senderPort(), int(peter.localPort())); QCOMPARE(peterDatagram.senderPort(), int(paul.localPort())); - // Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of - // obtaining the packet's destination addresses. The destinationAddress and - // destinationPort calls could fail, so whitelist the OSes for which we - // know we have an implementation. -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN) - QVERIFY(peterDatagram.destinationPort() != -1); - QVERIFY(paulDatagram.destinationPort() != -1); -#endif - if (peterDatagram.destinationPort() == -1) { + if (!HasWorkingIPv4DestinationAddress) { QCOMPARE(peterDatagram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol); QCOMPARE(paulDatagram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol); } else { @@ -877,6 +879,8 @@ void tst_QUdpSocket::dualStack() QCOMPARE(dgram.destinationPort(), int(dualSock.localPort())); QVERIFY(dgram.destinationAddress().isEqual(makeNonAny(dualSock.localAddress(), QHostAddress::LocalHost))); } else { + // Observed on QNX: the IPV6_PKTINFO ancillary data appears to be + // missing if the sender is IPv4. qInfo("Getting IPv4 destination address failed."); } @@ -916,11 +920,8 @@ void tst_QUdpSocket::dualStack() QCOMPARE(dgram.data(), dualData); QCOMPARE(dgram.senderPort(), int(dualSock.localPort())); QCOMPARE(dgram.senderAddress(), makeNonAny(dualSock.localAddress(), QHostAddress::LocalHost)); -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN) - QVERIFY(dgram.destinationPort() != -1); -#endif - if (dgram.destinationPort() != -1) { - QCOMPARE(dgram.destinationPort(), int(v4Sock.localPort())); + QCOMPARE(dgram.destinationPort(), int(v4Sock.localPort())); + if (HasWorkingIPv4DestinationAddress) { QCOMPARE(dgram.destinationAddress(), makeNonAny(v4Sock.localAddress(), QHostAddress::LocalHost)); if (loopbackInterface) QCOMPARE(dgram.interfaceIndex(), loopbackInterface); @@ -1777,10 +1778,10 @@ void tst_QUdpSocket::multicast() QVERIFY2(allAddresses.contains(dgram.senderAddress()), dgram.senderAddress().toString().toLatin1()); QCOMPARE(dgram.senderPort(), int(sender.localPort())); - if (!dgram.destinationAddress().isNull()) { + if (HasWorkingIPv4DestinationAddress) { QCOMPARE(dgram.destinationAddress(), groupAddress); - QCOMPARE(dgram.destinationPort(), int(receiver.localPort())); } + QCOMPARE(dgram.destinationPort(), int(receiver.localPort())); int ttl = dgram.hopLimit(); if (ttl != -1) @@ -1991,19 +1992,12 @@ void tst_QUdpSocket::linkLocalIPv4() QCOMPARE(dgram.data().size(), testData.size()); QCOMPARE(dgram.data(), testData); - // Unlike for IPv6 with IPV6_PKTINFO, IPv4 has no standardized way of - // obtaining the packet's destination addresses. The destinationAddress - // and destinationPort calls could fail, so whitelist the OSes we know - // we have an implementation. -#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) || defined(Q_OS_WIN) - QVERIFY(dgram.destinationPort() != -1); -#endif - if (dgram.destinationPort() == -1) { + if (!HasWorkingIPv4DestinationAddress) { QCOMPARE(dgram.destinationAddress().protocol(), QAbstractSocket::UnknownNetworkLayerProtocol); } else { QCOMPARE(dgram.destinationAddress(), s->localAddress()); - QCOMPARE(dgram.destinationPort(), int(neutral.localPort())); } + QCOMPARE(dgram.destinationPort(), int(neutral.localPort())); QVERIFY(neutral.writeDatagram(dgram.makeReply(testData))); QVERIFY2(s->waitForReadyRead(10000), QtNetworkSettings::msgSocketError(*s).constData()); |
