summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <[email protected]>2025-10-17 10:34:13 -0700
committerThiago Macieira <[email protected]>2025-10-21 16:56:19 -0700
commit30985c1fabb7281f2ac86cf576a092b7d48aeb3b (patch)
tree440fd9c9714969b630d61c1c480f751aa86092f6
parent6ec878ccab1b86b46f9dff8d42677f7b260110b2 (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.cpp48
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());