diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index 1133a80820..9a604e5d04 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -52,6 +52,13 @@ #include #endif +#if defined(Q_OS_LINUX) +#define SHOULD_CHECK_SYSCALL_SUPPORT +#include +#include +#include +#endif + Q_DECLARE_METATYPE(QHostAddress) QT_FORWARD_DECLARE_CLASS(QUdpSocket) @@ -115,6 +122,12 @@ protected slots: void async_readDatagramSlot(); private: + bool shouldSkipIpv6TestsForBrokenSetsockopt(); +#ifdef SHOULD_CHECK_SYSCALL_SUPPORT + bool ipv6SetsockoptionMissing(int level, int optname); +#endif + + bool m_skipUnsupportedIPv6Tests; QList allAddresses; #ifndef QT_NO_BEARERMANAGEMENT QNetworkConfigurationManager *netConfMan; @@ -125,6 +138,43 @@ private: QUdpSocket *m_asyncReceiver; }; +#ifdef SHOULD_CHECK_SYSCALL_SUPPORT +bool tst_QUdpSocket::ipv6SetsockoptionMissing(int level, int optname) +{ + int testSocket; + + testSocket = socket(PF_INET6, SOCK_DGRAM, 0); + + // If we can't test here, assume it's not missing + if (testSocket == -1) + return false; + + bool result = false; + if (setsockopt(testSocket, level, optname, nullptr, 0) == -1) + if (errno == ENOPROTOOPT) + result = true; + + close(testSocket); + return result; +} +#endif //SHOULD_CHECK_SYSCALL_SUPPORT + +bool tst_QUdpSocket::shouldSkipIpv6TestsForBrokenSetsockopt() +{ +#ifdef SHOULD_CHECK_SYSCALL_SUPPORT + // Following parameters for setsockopt are not supported by all QEMU versions: + if (ipv6SetsockoptionMissing(SOL_IPV6, IPV6_JOIN_GROUP) + || ipv6SetsockoptionMissing(SOL_IPV6, IPV6_MULTICAST_HOPS) + || ipv6SetsockoptionMissing(SOL_IPV6, IPV6_MULTICAST_IF) + || ipv6SetsockoptionMissing(SOL_IPV6, IPV6_MULTICAST_LOOP) + || ipv6SetsockoptionMissing(SOL_IPV6, IPV6_RECVHOPLIMIT)) { + return true; + } +#endif //SHOULD_CHECK_SYSCALL_SUPPORT + + return false; +} + static QHostAddress makeNonAny(const QHostAddress &address, QHostAddress::SpecialAddress preferForAny = QHostAddress::LocalHost) { if (address == QHostAddress::Any) @@ -176,6 +226,7 @@ void tst_QUdpSocket::initTestCase() if (!QtNetworkSettings::verifyTestNetworkSettings()) QSKIP("No network test server available"); allAddresses = QNetworkInterface::allAddresses(); + m_skipUnsupportedIPv6Tests = shouldSkipIpv6TestsForBrokenSetsockopt(); } void tst_QUdpSocket::init() @@ -1140,6 +1191,13 @@ void tst_QUdpSocket::multicastTtlOption() expected = 0; } + // Some syscalls needed for ipv6 udp multicasting are not functional + if (m_skipUnsupportedIPv6Tests) { + if (bindAddress.protocol() == QAbstractSocket::IPv6Protocol) { + QSKIP("Syscalls needed for ipv6 udp multicasting missing functionality"); + } + } + QUdpSocket udpSocket; #ifdef FORCE_SESSION udpSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); @@ -1186,6 +1244,13 @@ void tst_QUdpSocket::multicastLoopbackOption() expected = 0; } + // Some syscalls needed for ipv6 udp multicasting are not functional + if (m_skipUnsupportedIPv6Tests) { + if (bindAddress.protocol() == QAbstractSocket::IPv6Protocol) { + QSKIP("Syscalls needed for ipv6 udp multicasting missing functionality"); + } + } + QUdpSocket udpSocket; #ifdef FORCE_SESSION udpSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); @@ -1240,6 +1305,13 @@ void tst_QUdpSocket::multicastLeaveAfterClose() if (!QtNetworkSettings::hasIPv6() && groupAddress.protocol() == QAbstractSocket::IPv6Protocol) QSKIP("system doesn't support ipv6!"); + // Some syscalls needed for ipv6 udp multicasting are not functional + if (m_skipUnsupportedIPv6Tests) { + if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) { + QSKIP("Syscalls needed for ipv6 udp multicasting missing functionality"); + } + } + QUdpSocket udpSocket; #ifdef FORCE_SESSION udpSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); @@ -1280,6 +1352,11 @@ void tst_QUdpSocket::setMulticastInterface() QFETCH(QNetworkInterface, iface); QFETCH(QHostAddress, address); + // Some syscalls needed for udp multicasting are not functional + if (m_skipUnsupportedIPv6Tests) { + QSKIP("Syscalls needed for udp multicasting missing functionality"); + } + QUdpSocket udpSocket; // bind initializes the socket bool bound = udpSocket.bind((address.protocol() == QAbstractSocket::IPv6Protocol @@ -1339,6 +1416,13 @@ void tst_QUdpSocket::multicast() return; } + // Some syscalls needed for ipv6 udp multicasting are not functional + if (m_skipUnsupportedIPv6Tests) { + if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) { + QSKIP("Syscalls needed for ipv6 udp multicasting missing functionality"); + } + } + QUdpSocket receiver; #ifdef FORCE_SESSION receiver.setProperty("_q_networksession", QVariant::fromValue(networkSession));