85136496bc
Adds support for binding "dual stack" sockets (via QUdpSocket or QTcpServer). A dual stack socket will accept incoming connections on either IPv4 or IPv6 interfaces. QHostAddress::Any - use this to bind a dual stack socket QHostAddress::AnyIPv6 - use this to bind a socket for IPv6 only QHostAddress::AnyIPv4 - use this to bind a socket for IPv4 only Binding to a specific address rather than one of the "any" addresses is restricting you to a protocol anyway so no behaviour change there. IPv6 sockets were previously dual stack on some OS and v6 only on others Any previously meant IPv4 only This commit implemented & tested on Windows 7, Linux (Ubuntu 10.04) and Mac OS 10.6.7. Windows XP and server 2003 do not support dual stack sockets, even though they can support IPv6. On those versions, QHostAddress::Any will still bind to IPv4 0.0.0.0 (which is also the behaviour anywhere QT_NO_IPV6 is defined) Autotests run: qudpsocket (includes a new test case) qtcpserver (includes a new test case) qtcpsocket qnetworkreply qhostaddress Task-number: QTBUG-17080 Change-Id: Id486677c4f832e18dc0ff1a86c5f5fc422c9eb4f Reviewed-on: http://codereview.qt.nokia.com/421 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Thiago Macieira <thiago.macieira@nokia.com> Reviewed-by: Markus Goetz
612 lines
32 KiB
C++
612 lines
32 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
|
** All rights reserved.
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
**
|
|
** This file is part of the test suite of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** GNU Lesser General Public License Usage
|
|
** This file may be used under the terms of the GNU Lesser General Public
|
|
** License version 2.1 as published by the Free Software Foundation and
|
|
** appearing in the file LICENSE.LGPL included in the packaging of this
|
|
** file. Please review the following information to ensure the GNU Lesser
|
|
** General Public License version 2.1 requirements will be met:
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU General
|
|
** Public License version 3.0 as published by the Free Software Foundation
|
|
** and appearing in the file LICENSE.GPL included in the packaging of this
|
|
** file. Please review the following information to ensure the GNU General
|
|
** Public License version 3.0 requirements will be met:
|
|
** http://www.gnu.org/copyleft/gpl.html.
|
|
**
|
|
** Other Usage
|
|
** Alternatively, this file may be used in accordance with the terms and
|
|
** conditions contained in a signed written agreement between you and Nokia.
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
|
|
#include <qcoreapplication.h>
|
|
#include <QtTest/QtTest>
|
|
#include <qhostaddress.h>
|
|
#include <qplatformdefs.h>
|
|
#include <qdebug.h>
|
|
#include <qhash.h>
|
|
#include <qbytearray.h>
|
|
#include <qdatastream.h>
|
|
|
|
//TESTED_CLASS=
|
|
//TESTED_FILES=
|
|
|
|
class tst_QHostAddress : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
tst_QHostAddress();
|
|
virtual ~tst_QHostAddress();
|
|
|
|
|
|
public slots:
|
|
void init();
|
|
void cleanup();
|
|
private slots:
|
|
void constructor_QString_data();
|
|
void constructor_QString();
|
|
void setAddress_QString_data();
|
|
void setAddress_QString();
|
|
void specialAddresses_data();
|
|
void specialAddresses();
|
|
void compare_data();
|
|
void compare();
|
|
void assignment();
|
|
void scopeId();
|
|
void hashKey();
|
|
void streaming_data();
|
|
void streaming();
|
|
void parseSubnet_data();
|
|
void parseSubnet();
|
|
void isInSubnet_data();
|
|
void isInSubnet();
|
|
};
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
namespace QTest {
|
|
template<>
|
|
char *toString(const QHostAddress &addr)
|
|
{
|
|
if (addr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol)
|
|
return qstrdup("<invalid>");
|
|
return qstrdup(addr.toString().toLatin1());
|
|
}
|
|
}
|
|
QT_END_NAMESPACE
|
|
|
|
tst_QHostAddress::tst_QHostAddress()
|
|
{
|
|
}
|
|
|
|
tst_QHostAddress::~tst_QHostAddress()
|
|
{
|
|
}
|
|
|
|
Q_DECLARE_METATYPE(QHostAddress)
|
|
|
|
void tst_QHostAddress::init()
|
|
{
|
|
qRegisterMetaType<QHostAddress>("QHostAddress");
|
|
}
|
|
|
|
void tst_QHostAddress::cleanup()
|
|
{
|
|
// No cleanup is required.
|
|
}
|
|
|
|
void tst_QHostAddress::constructor_QString_data()
|
|
{
|
|
setAddress_QString_data();
|
|
}
|
|
|
|
void tst_QHostAddress::constructor_QString()
|
|
{
|
|
QFETCH(QString, address);
|
|
QFETCH(bool, ok);
|
|
QFETCH(int, protocol);
|
|
|
|
QHostAddress hostAddr(address);
|
|
|
|
if (address == "0.0.0.0" || address == "::") {
|
|
QVERIFY(ok);
|
|
} else {
|
|
QVERIFY(hostAddr.isNull() != ok);
|
|
}
|
|
|
|
if (ok)
|
|
QTEST(hostAddr.toString(), "resAddr");
|
|
|
|
if ( protocol == 4 ) {
|
|
QVERIFY( hostAddr.protocol() == QAbstractSocket::IPv4Protocol || hostAddr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol );
|
|
QVERIFY( hostAddr.protocol() != QAbstractSocket::IPv6Protocol );
|
|
} else if ( protocol == 6 ) {
|
|
QVERIFY( hostAddr.protocol() != QAbstractSocket::IPv4Protocol && hostAddr.protocol() != QAbstractSocket::UnknownNetworkLayerProtocol );
|
|
QVERIFY( hostAddr.protocol() == QAbstractSocket::IPv6Protocol );
|
|
} else {
|
|
QVERIFY( hostAddr.isNull() );
|
|
QVERIFY( hostAddr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol );
|
|
}
|
|
}
|
|
|
|
void tst_QHostAddress::setAddress_QString_data()
|
|
{
|
|
QTest::addColumn<QString>("address");
|
|
QTest::addColumn<bool>("ok");
|
|
QTest::addColumn<QString>("resAddr");
|
|
QTest::addColumn<int>("protocol"); // 4: IPv4, 6: IPv6, other: undefined
|
|
|
|
//next we fill it with data
|
|
QTest::newRow("ip4_00") << QString("127.0.0.1") << (bool)TRUE << QString("127.0.0.1") << 4;
|
|
QTest::newRow("ip4_01") << QString("255.3.2.1") << (bool)TRUE << QString("255.3.2.1") << 4;
|
|
QTest::newRow("ip4_03") << QString(" 255.3.2.1") << (bool)TRUE << QString("255.3.2.1") << 4;
|
|
QTest::newRow("ip4_04") << QString("255.3.2.1\r ") << (bool)TRUE << QString("255.3.2.1") << 4;
|
|
QTest::newRow("ip4_05") << QString("0.0.0.0") << (bool)TRUE << QString("0.0.0.0") << 4;
|
|
|
|
// for the format of IPv6 addresses see also RFC 5952
|
|
QTest::newRow("ip6_00") << QString("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210") << (bool)TRUE << QString("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210") << 6;
|
|
QTest::newRow("ip6_01") << QString("1080:0000:0000:0000:0008:0800:200C:417A") << (bool)TRUE << QString("1080::8:800:200C:417A") << 6;
|
|
QTest::newRow("ip6_02") << QString("1080:0:0:0:8:800:200C:417A") << (bool)TRUE << QString("1080::8:800:200C:417A") << 6;
|
|
QTest::newRow("ip6_03") << QString("1080::8:800:200C:417A") << (bool)TRUE << QString("1080::8:800:200C:417A") << 6;
|
|
QTest::newRow("ip6_04") << QString("FF01::43") << (bool)TRUE << QString("FF01::43") << 6;
|
|
QTest::newRow("ip6_05") << QString("::1") << (bool)TRUE << QString("::1") << 6;
|
|
QTest::newRow("ip6_06") << QString("1::") << (bool)TRUE << QString("1::") << 6;
|
|
QTest::newRow("ip6_07") << QString("::") << (bool)TRUE << QString("::") << 6;
|
|
QTest::newRow("ip6_08") << QString("0:0:0:0:0:0:13.1.68.3") << (bool)TRUE << QString("::D01:4403") << 6;
|
|
QTest::newRow("ip6_09") << QString("::13.1.68.3") << (bool)TRUE << QString("::D01:4403") << 6;
|
|
QTest::newRow("ip6_10") << QString("0:0:0:0:0:FFFF:129.144.52.38") << (bool)TRUE << QString("::FFFF:8190:3426") << 6;
|
|
QTest::newRow("ip6_11") << QString("::FFFF:129.144.52.38") << (bool)TRUE << QString("::FFFF:8190:3426") << 6;
|
|
QTest::newRow("ip6_12") << QString("1::FFFF:129.144.52.38") << (bool)TRUE << QString("1::FFFF:8190:3426") << 6;
|
|
QTest::newRow("ip6_13") << QString("A:B::D:E") << (bool)TRUE << QString("A:B::D:E") << 6;
|
|
QTest::newRow("ip6_14") << QString("1080:0:1:0:8:800:200C:417A") << (bool)TRUE << QString("1080:0:1:0:8:800:200C:417A") << 6;
|
|
QTest::newRow("ip6_15") << QString("1080:0:1:0:8:800:200C:0") << (bool)TRUE << QString("1080:0:1:0:8:800:200C:0") << 6;
|
|
QTest::newRow("ip6_16") << QString("1080:0:1:0:8:800:0:0") << (bool)TRUE << QString("1080:0:1:0:8:800::") << 6;
|
|
QTest::newRow("ip6_17") << QString("1080:0:0:0:8:800:0:0") << (bool)TRUE << QString("1080::8:800:0:0") << 6;
|
|
QTest::newRow("ip6_18") << QString("0:1:1:1:8:800:0:0") << (bool)TRUE << QString("0:1:1:1:8:800::") << 6;
|
|
QTest::newRow("ip6_19") << QString("0:1:1:1:8:800:0:1") << (bool)TRUE << QString("0:1:1:1:8:800:0:1") << 6;
|
|
|
|
QTest::newRow("error_00") << QString("foobarcom") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_01") << QString("foo.bar.com") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_02") << QString("") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_03") << QString() << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_04") << QString(" \t\r") << (bool)FALSE << QString() << 0;
|
|
|
|
QTest::newRow("error_ip4_00") << QString("256.9.9.9") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip4_01") << QString("-1.9.9.9") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip4_02") << QString("123.0.0") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip4_03") << QString("123.0.0.0.0") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip4_04") << QString("255.2 3.2.1") << (bool)FALSE << QString() << 0;
|
|
|
|
QTest::newRow("error_ip6_00") << QString(":") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_01") << QString(":::") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_02") << QString("::AAAA:") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_03") << QString(":AAAA::") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_04") << QString("FFFF:::129.144.52.38") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_05") << QString("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210:1234") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_06") << QString("129.144.52.38::") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_07") << QString("::129.144.52.38:129.144.52.38") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_08") << QString(":::129.144.52.38") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_09") << QString("1FEDC:BA98:7654:3210:FEDC:BA98:7654:3210") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_10") << QString("::FFFFFFFF") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_11") << QString("::EFGH") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_12") << QString("ABCD:ABCD:ABCD") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_13") << QString("::ABCD:ABCD::") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_14") << QString("1::2::3") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_15") << QString("1:2:::") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_16") << QString(":::1:2") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_17") << QString("1:::2") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_18") << QString("FEDC::7654:3210:FEDC:BA98::3210") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_19") << QString("ABCD:ABCD:ABCD:1.2.3.4") << (bool)FALSE << QString() << 0;
|
|
QTest::newRow("error_ip6_20") << QString("ABCD::ABCD::ABCD:1.2.3.4") << (bool)FALSE << QString() << 0;
|
|
|
|
}
|
|
|
|
void tst_QHostAddress::setAddress_QString()
|
|
{
|
|
QFETCH(QString, address);
|
|
QFETCH(bool, ok);
|
|
QFETCH(int, protocol);
|
|
|
|
QHostAddress hostAddr;
|
|
QVERIFY(hostAddr.setAddress(address) == ok);
|
|
|
|
if (ok)
|
|
QTEST(hostAddr.toString(), "resAddr");
|
|
|
|
if ( protocol == 4 ) {
|
|
QVERIFY( hostAddr.protocol() == QAbstractSocket::IPv4Protocol || hostAddr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol );
|
|
QVERIFY( hostAddr.protocol() != QAbstractSocket::IPv6Protocol );
|
|
} else if ( protocol == 6 ) {
|
|
QVERIFY( hostAddr.protocol() != QAbstractSocket::IPv4Protocol && hostAddr.protocol() != QAbstractSocket::UnknownNetworkLayerProtocol );
|
|
QVERIFY( hostAddr.protocol() == QAbstractSocket::IPv6Protocol );
|
|
} else {
|
|
QVERIFY( hostAddr.isNull() );
|
|
QVERIFY( hostAddr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol );
|
|
}
|
|
}
|
|
|
|
void tst_QHostAddress::specialAddresses_data()
|
|
{
|
|
QTest::addColumn<QString>("text");
|
|
QTest::addColumn<int>("address");
|
|
QTest::addColumn<bool>("result");
|
|
|
|
QTest::newRow("localhost_1") << QString("127.0.0.1") << (int)QHostAddress::LocalHost << true;
|
|
QTest::newRow("localhost_2") << QString("127.0.0.2") << (int)QHostAddress::LocalHost << false;
|
|
QTest::newRow("localhost_3") << QString("127.0.0.2") << (int)QHostAddress::LocalHostIPv6 << false;
|
|
|
|
QTest::newRow("localhost_ipv6_4") << QString("::1") << (int)QHostAddress::LocalHostIPv6 << true;
|
|
QTest::newRow("localhost_ipv6_5") << QString("::2") << (int)QHostAddress::LocalHostIPv6 << false;
|
|
QTest::newRow("localhost_ipv6_6") << QString("::1") << (int)QHostAddress::LocalHost << false;
|
|
|
|
QTest::newRow("null_1") << QString("") << (int)QHostAddress::Null << true;
|
|
QTest::newRow("null_2") << QString("bjarne") << (int)QHostAddress::Null << true;
|
|
|
|
QTest::newRow("compare_from_null") << QString("") << (int)QHostAddress::Broadcast << false;
|
|
|
|
QTest::newRow("broadcast_1") << QString("255.255.255.255") << (int)QHostAddress::Any << false;
|
|
QTest::newRow("broadcast_2") << QString("255.255.255.255") << (int)QHostAddress::Broadcast << true;
|
|
|
|
QTest::newRow("any_ipv6") << QString("::") << (int)QHostAddress::AnyIPv6 << true;
|
|
QTest::newRow("any_ipv4") << QString("0.0.0.0") << (int)QHostAddress::AnyIPv4 << true;
|
|
|
|
QTest::newRow("dual_not_ipv6") << QString("::") << (int)QHostAddress::Any << false;
|
|
QTest::newRow("dual_not_ipv4") << QString("0.0.0.0") << (int)QHostAddress::Any << false;
|
|
}
|
|
|
|
|
|
void tst_QHostAddress::specialAddresses()
|
|
{
|
|
QFETCH(QString, text);
|
|
QFETCH(int, address);
|
|
QFETCH(bool, result);
|
|
QVERIFY((QHostAddress(text) == (QHostAddress::SpecialAddress)address) == result);
|
|
|
|
QHostAddress setter;
|
|
setter.setAddress(text);
|
|
if (result) {
|
|
QVERIFY(setter == (QHostAddress::SpecialAddress) address);
|
|
} else {
|
|
QVERIFY(!((QHostAddress::SpecialAddress) address == setter));
|
|
}
|
|
}
|
|
|
|
|
|
void tst_QHostAddress::compare_data()
|
|
{
|
|
QTest::addColumn<QHostAddress>("first");
|
|
QTest::addColumn<QHostAddress>("second");
|
|
QTest::addColumn<bool>("result");
|
|
|
|
QTest::newRow("1") << QHostAddress() << QHostAddress() << true;
|
|
QTest::newRow("2") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::Any) << true;
|
|
QTest::newRow("3") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv6) << true;
|
|
QTest::newRow("4") << QHostAddress(QHostAddress::Broadcast) << QHostAddress(QHostAddress::Broadcast) << true;
|
|
QTest::newRow("5") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::Broadcast) << false;
|
|
QTest::newRow("6") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHostIPv6) << false;
|
|
QTest::newRow("7") << QHostAddress() << QHostAddress(QHostAddress::LocalHostIPv6) << false;
|
|
}
|
|
|
|
void tst_QHostAddress::compare()
|
|
{
|
|
QFETCH(QHostAddress, first);
|
|
QFETCH(QHostAddress, second);
|
|
QFETCH(bool, result);
|
|
|
|
QCOMPARE(first == second, result);
|
|
}
|
|
|
|
void tst_QHostAddress::assignment()
|
|
{
|
|
QHostAddress address;
|
|
address = "127.0.0.1";
|
|
QCOMPARE(address, QHostAddress("127.0.0.1"));
|
|
|
|
address = "::1";
|
|
QCOMPARE(address, QHostAddress("::1"));
|
|
|
|
QHostAddress addr("4.2.2.1");
|
|
sockaddr_in sockAddr;
|
|
sockAddr.sin_family = AF_INET;
|
|
sockAddr.sin_addr.s_addr = htonl(addr.toIPv4Address());
|
|
address.setAddress((sockaddr *)&sockAddr);
|
|
QCOMPARE(address, addr);
|
|
}
|
|
|
|
void tst_QHostAddress::scopeId()
|
|
{
|
|
QHostAddress address("fe80::2e0:4cff:fefb:662a%eth0");
|
|
QCOMPARE(address.scopeId(), QString("eth0"));
|
|
QCOMPARE(address.toString().toLower(), QString("fe80::2e0:4cff:fefb:662a%eth0"));
|
|
|
|
QHostAddress address2("fe80::2e0:4cff:fefb:662a");
|
|
QCOMPARE(address2.scopeId(), QString());
|
|
address2.setScopeId(QString("en0"));
|
|
QCOMPARE(address2.toString().toLower(), QString("fe80::2e0:4cff:fefb:662a%en0"));
|
|
|
|
address2 = address;
|
|
QCOMPARE(address2.scopeId(), QString("eth0"));
|
|
QCOMPARE(address2.toString().toLower(), QString("fe80::2e0:4cff:fefb:662a%eth0"));
|
|
}
|
|
|
|
void tst_QHostAddress::hashKey()
|
|
{
|
|
QHash<QHostAddress, QString> hostHash;
|
|
hostHash.insert(QHostAddress(), "ole");
|
|
}
|
|
|
|
void tst_QHostAddress::streaming_data()
|
|
{
|
|
QTest::addColumn<QHostAddress>("address");
|
|
QTest::newRow("1") << QHostAddress();
|
|
QTest::newRow("2") << QHostAddress(0xDEADBEEF);
|
|
QTest::newRow("3") << QHostAddress("127.128.129.130");
|
|
QTest::newRow("4") << QHostAddress("1080:0000:0000:0000:0008:0800:200C:417A");
|
|
QTest::newRow("5") << QHostAddress("fe80::2e0:4cff:fefb:662a%eth0");
|
|
QTest::newRow("6") << QHostAddress(QHostAddress::Null);
|
|
QTest::newRow("7") << QHostAddress(QHostAddress::LocalHost);
|
|
QTest::newRow("8") << QHostAddress(QHostAddress::LocalHostIPv6);
|
|
QTest::newRow("9") << QHostAddress(QHostAddress::Broadcast);
|
|
QTest::newRow("10") << QHostAddress(QHostAddress::Any);
|
|
QTest::newRow("11") << QHostAddress(QHostAddress::AnyIPv4);
|
|
QTest::newRow("12") << QHostAddress(QHostAddress::AnyIPv6);
|
|
QTest::newRow("13") << QHostAddress("foo.bar.com");
|
|
}
|
|
|
|
void tst_QHostAddress::streaming()
|
|
{
|
|
QFETCH(QHostAddress, address);
|
|
QByteArray ba;
|
|
QDataStream ds1(&ba, QIODevice::WriteOnly);
|
|
ds1 << address;
|
|
QVERIFY(ds1.status() == QDataStream::Ok);
|
|
QDataStream ds2(&ba, QIODevice::ReadOnly);
|
|
QHostAddress address2;
|
|
ds2 >> address2;
|
|
QVERIFY(ds2.status() == QDataStream::Ok);
|
|
QCOMPARE(address, address2);
|
|
}
|
|
|
|
void tst_QHostAddress::parseSubnet_data()
|
|
{
|
|
QTest::addColumn<QString>("subnet");
|
|
QTest::addColumn<QHostAddress>("prefix");
|
|
QTest::addColumn<int>("prefixLength");
|
|
|
|
// invalid/error values
|
|
QTest::newRow("empty") << QString() << QHostAddress() << -1;
|
|
QTest::newRow("invalid_01") << "foobar" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_02") << " " << QHostAddress() << -1;
|
|
QTest::newRow("invalid_03") << "1.2.3.a" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_04") << "1.2.3.4.5" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_05") << "1.2.3.4:80" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_06") << "1.2.3.4/33" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_07") << "1.2.3.4/-1" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_08") << "1.2.3.4/256.0.0.0" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_09") << "1.2.3.4/255.253.0.0" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_10") << "1.2.3.4/255.0.0.255" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_11") << "1.2.3.4." << QHostAddress() << -1;
|
|
QTest::newRow("invalid_20") << "ffff::/-1" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_21") << "ffff::/129" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_22") << "ffff::/255.255.0.0" << QHostAddress() << -1;
|
|
QTest::newRow("invalid_23") << "ffff::/ff00::" << QHostAddress() << -1;
|
|
|
|
// correct IPv4 with netmask
|
|
QTest::newRow("netmask_0") << "0.0.0.0/0.0.0.0" << QHostAddress(QHostAddress::AnyIPv4) << 0;
|
|
QTest::newRow("netmask_1") << "0.0.0.0/255.128.0.0" << QHostAddress(QHostAddress::AnyIPv4) << 9;
|
|
QTest::newRow("netmask_2") << "0.0.0.0/255.192.0.0" << QHostAddress(QHostAddress::AnyIPv4) << 10;
|
|
QTest::newRow("netmask_3") << "0.0.0.0/255.224.0.0" << QHostAddress(QHostAddress::AnyIPv4) << 11;
|
|
QTest::newRow("netmask_4") << "0.0.0.0/255.240.0.0" << QHostAddress(QHostAddress::AnyIPv4) << 12;
|
|
QTest::newRow("netmask_5") << "0.0.0.0/255.248.0.0" << QHostAddress(QHostAddress::AnyIPv4) << 13;
|
|
QTest::newRow("netmask_6") << "0.0.0.0/255.252.0.0" << QHostAddress(QHostAddress::AnyIPv4) << 14;
|
|
QTest::newRow("netmask_7") << "0.0.0.0/255.254.0.0" << QHostAddress(QHostAddress::AnyIPv4) << 15;
|
|
QTest::newRow("netmask_8") << "0.0.0.0/255.255.0.0" << QHostAddress(QHostAddress::AnyIPv4) << 16;
|
|
QTest::newRow("netmask_16") << "0.0.0.0/255.255.0.0" << QHostAddress(QHostAddress::AnyIPv4) << 16;
|
|
QTest::newRow("netmask_24") << "0.0.0.0/255.255.255.0" << QHostAddress(QHostAddress::AnyIPv4) << 24;
|
|
QTest::newRow("netmask_31") << "0.0.0.0/255.255.255.254" << QHostAddress(QHostAddress::AnyIPv4) << 31;
|
|
QTest::newRow("netmask_32") << "0.0.0.0/255.255.255.255" << QHostAddress(QHostAddress::AnyIPv4) << 32;
|
|
|
|
// correct IPv4 with prefix
|
|
QTest::newRow("prefix_0") << "0.0.0.0/0" << QHostAddress(QHostAddress::AnyIPv4) << 0;
|
|
QTest::newRow("prefix_1") << "0.0.0.0/1" << QHostAddress(QHostAddress::AnyIPv4) << 1;
|
|
QTest::newRow("prefix_9") << "0.0.0.0/9" << QHostAddress(QHostAddress::AnyIPv4) << 9;
|
|
QTest::newRow("prefix_31") << "0.0.0.0/31" << QHostAddress(QHostAddress::AnyIPv4) << 31;
|
|
QTest::newRow("prefix_32") << "0.0.0.0/32" << QHostAddress(QHostAddress::AnyIPv4) << 32;
|
|
|
|
// correct IPv4 without prefix or netmask
|
|
QTest::newRow("classA") << "10" << QHostAddress("10.0.0.0") << 8;
|
|
QTest::newRow("classA+dot") << "10." << QHostAddress("10.0.0.0") << 8;
|
|
QTest::newRow("classB") << "172.16" << QHostAddress("172.16.0.0") << 16;
|
|
QTest::newRow("classB+dot") << "172.16." << QHostAddress("172.16.0.0") << 16;
|
|
QTest::newRow("classC") << "192.168.0" << QHostAddress("192.168.0.0") << 24;
|
|
QTest::newRow("classC+dot") << "192.168.0" << QHostAddress("192.168.0.0") << 24;
|
|
QTest::newRow("full-ipv4") << "192.168.0.1" << QHostAddress("192.168.0.1") << 32;
|
|
|
|
// correct IPv6 with prefix
|
|
QTest::newRow("ipv6_01") << "::/0" << QHostAddress(QHostAddress::AnyIPv6) << 0;
|
|
QTest::newRow("ipv6_03") << "::/3" << QHostAddress(QHostAddress::AnyIPv6) << 3;
|
|
QTest::newRow("ipv6_16") << "::/16" << QHostAddress(QHostAddress::AnyIPv6) << 16;
|
|
QTest::newRow("ipv6_48") << "::/48" << QHostAddress(QHostAddress::AnyIPv6) << 48;
|
|
QTest::newRow("ipv6_127") << "::/127" << QHostAddress(QHostAddress::AnyIPv6) << 127;
|
|
QTest::newRow("ipv6_128") << "::/128" << QHostAddress(QHostAddress::AnyIPv6) << 128;
|
|
|
|
// tail bit clearing:
|
|
QTest::newRow("clear_01") << "255.255.255.255/31" << QHostAddress("255.255.255.254") << 31;
|
|
QTest::newRow("clear_08") << "255.255.255.255/24" << QHostAddress("255.255.255.0") << 24;
|
|
QTest::newRow("clear_09") << "255.255.255.255/23" << QHostAddress("255.255.254.0") << 23;
|
|
QTest::newRow("clear_10") << "255.255.255.255/22" << QHostAddress("255.255.252.0") << 22;
|
|
QTest::newRow("clear_11") << "255.255.255.255/21" << QHostAddress("255.255.248.0") << 21;
|
|
QTest::newRow("clear_12") << "255.255.255.255/20" << QHostAddress("255.255.240.0") << 20;
|
|
QTest::newRow("clear_13") << "255.255.255.255/19" << QHostAddress("255.255.224.0") << 19;
|
|
QTest::newRow("clear_14") << "255.255.255.255/18" << QHostAddress("255.255.192.0") << 18;
|
|
QTest::newRow("clear_15") << "255.255.255.255/17" << QHostAddress("255.255.128.0") << 17;
|
|
QTest::newRow("clear_16") << "255.255.255.255/16" << QHostAddress("255.255.0.0") << 16;
|
|
QTest::newRow("clear_24") << "255.255.255.255/8" << QHostAddress("255.0.0.0") << 8;
|
|
QTest::newRow("clear_31") << "255.255.255.255/1" << QHostAddress("128.0.0.0") << 1;
|
|
QTest::newRow("clear_32") << "255.255.255.255/0" << QHostAddress("0.0.0.0") << 0;
|
|
|
|
// same for IPv6:
|
|
QTest::newRow("ipv6_clear_01") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/127"
|
|
<< QHostAddress("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe")
|
|
<< 127;
|
|
QTest::newRow("ipv6_clear_07") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/121"
|
|
<< QHostAddress("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff80")
|
|
<< 121;
|
|
QTest::newRow("ipv6_clear_08") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/120"
|
|
<< QHostAddress("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00")
|
|
<< 120;
|
|
QTest::newRow("ipv6_clear_16") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/112"
|
|
<< QHostAddress("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0")
|
|
<< 112;
|
|
QTest::newRow("ipv6_clear_80") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/48"
|
|
<< QHostAddress("ffff:ffff:ffff::")
|
|
<< 48;
|
|
QTest::newRow("ipv6_clear_81") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/47"
|
|
<< QHostAddress("ffff:ffff:fffe::")
|
|
<< 47;
|
|
QTest::newRow("ipv6_clear_82") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/46"
|
|
<< QHostAddress("ffff:ffff:fffc::")
|
|
<< 46;
|
|
QTest::newRow("ipv6_clear_83") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/45"
|
|
<< QHostAddress("ffff:ffff:fff8::")
|
|
<< 45;
|
|
QTest::newRow("ipv6_clear_84") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/44"
|
|
<< QHostAddress("ffff:ffff:fff0::")
|
|
<< 44;
|
|
QTest::newRow("ipv6_clear_85") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/43"
|
|
<< QHostAddress("ffff:ffff:ffe0::")
|
|
<< 43;
|
|
QTest::newRow("ipv6_clear_86") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/42"
|
|
<< QHostAddress("ffff:ffff:ffc0::")
|
|
<< 42;
|
|
QTest::newRow("ipv6_clear_87") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/41"
|
|
<< QHostAddress("ffff:ffff:ff80::")
|
|
<< 41;
|
|
QTest::newRow("ipv6_clear_88") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/40"
|
|
<< QHostAddress("ffff:ffff:ff00::")
|
|
<< 40;
|
|
QTest::newRow("ipv6_clear_125") << "3fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/3"
|
|
<< QHostAddress("2000::")
|
|
<< 3;
|
|
QTest::newRow("ipv6_clear_127") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/1"
|
|
<< QHostAddress("8000::")
|
|
<< 1;
|
|
QTest::newRow("ipv6_clear_128") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/0"
|
|
<< QHostAddress(QHostAddress::AnyIPv6)
|
|
<< 0;
|
|
}
|
|
|
|
void tst_QHostAddress::parseSubnet()
|
|
{
|
|
QFETCH(QString, subnet);
|
|
QFETCH(QHostAddress, prefix);
|
|
QFETCH(int, prefixLength);
|
|
|
|
QPair<QHostAddress, int> result = QHostAddress::parseSubnet(subnet);
|
|
QCOMPARE(result.first, prefix);
|
|
QCOMPARE(result.second, prefixLength);
|
|
}
|
|
|
|
void tst_QHostAddress::isInSubnet_data()
|
|
{
|
|
QTest::addColumn<QHostAddress>("address");
|
|
QTest::addColumn<QHostAddress>("prefix");
|
|
QTest::addColumn<int>("prefixLength");
|
|
QTest::addColumn<bool>("result");
|
|
|
|
// invalid QHostAddresses are never in any subnets
|
|
QTest::newRow("invalid_01") << QHostAddress() << QHostAddress() << 32 << false;
|
|
QTest::newRow("invalid_02") << QHostAddress() << QHostAddress(QHostAddress::AnyIPv4) << 32 << false;
|
|
QTest::newRow("invalid_03") << QHostAddress() << QHostAddress(QHostAddress::AnyIPv4) << 8 << false;
|
|
QTest::newRow("invalid_04") << QHostAddress() << QHostAddress(QHostAddress::AnyIPv4) << 0 << false;
|
|
QTest::newRow("invalid_05") << QHostAddress() << QHostAddress("255.255.255.0") << 24 << false;
|
|
QTest::newRow("invalid_06") << QHostAddress() << QHostAddress(QHostAddress::AnyIPv6) << 0 << false;
|
|
QTest::newRow("invalid_07") << QHostAddress() << QHostAddress(QHostAddress::AnyIPv6) << 32 << false;
|
|
QTest::newRow("invalid_08") << QHostAddress() << QHostAddress(QHostAddress::AnyIPv6) << 128<< false;
|
|
|
|
// and no host address can be in a subnet whose prefix is invalid
|
|
QTest::newRow("invalid_20") << QHostAddress(QHostAddress::AnyIPv4) << QHostAddress() << 16 << false;
|
|
QTest::newRow("invalid_21") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress() << 16 << false;
|
|
QTest::newRow("invalid_22") << QHostAddress(QHostAddress::LocalHost) << QHostAddress() << 16 << false;
|
|
QTest::newRow("invalid_23") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress() << 16 << false;
|
|
|
|
// negative netmasks don't make sense:
|
|
QTest::newRow("invalid_30") << QHostAddress(QHostAddress::AnyIPv4) << QHostAddress(QHostAddress::Any) << -1 << false;
|
|
QTest::newRow("invalid_31") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv6) << -1 << false;
|
|
|
|
// we don't support IPv4 belonging in an IPv6 netmask and vice-versa
|
|
QTest::newRow("v4-in-v6") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::AnyIPv6) << 0 << false;
|
|
QTest::newRow("v6-in-v4") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::Any) << 0 << false;
|
|
QTest::newRow("v4-in-v6mapped") << QHostAddress(QHostAddress::LocalHost) << QHostAddress("ffff:ffff:ffff:ffff:ffff:ffff:255.0.0.0") << 113 << false;
|
|
QTest::newRow("v4-in-v6mapped2") << QHostAddress(QHostAddress::LocalHost) << QHostAddress("::ffff:255.0.0.0") << 113 << false;
|
|
|
|
// IPv4 correct ones
|
|
QTest::newRow("netmask_0") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::AnyIPv4) << 0 << true;
|
|
QTest::newRow("netmask_0bis") << QHostAddress(QHostAddress::LocalHost) << QHostAddress("255.255.0.0") << 0 << true;
|
|
QTest::newRow("netmask_0ter") << QHostAddress(QHostAddress::LocalHost) << QHostAddress("1.2.3.4") << 0 << true;
|
|
QTest::newRow("netmask_1") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::AnyIPv4) << 1 << true;
|
|
QTest::newRow("~netmask_1") << QHostAddress(QHostAddress::LocalHost) << QHostAddress("128.0.0.0") << 1 << false;
|
|
QTest::newRow("netmask_1bis") << QHostAddress("224.0.0.1") << QHostAddress("128.0.0.0") << 1 << true;
|
|
QTest::newRow("~netmask_1bis") << QHostAddress("224.0.0.1") << QHostAddress("0.0.0.0") << 1 << false;
|
|
QTest::newRow("netmask_8") << QHostAddress(QHostAddress::LocalHost) << QHostAddress("127.0.0.0") << 8 << true;
|
|
QTest::newRow("~netmask_8") << QHostAddress(QHostAddress::LocalHost) << QHostAddress("126.0.0.0") << 8 << false;
|
|
QTest::newRow("netmask_15") << QHostAddress("10.0.1.255") << QHostAddress("10.0.0.0") << 15 << true;
|
|
QTest::newRow("netmask_16") << QHostAddress("172.16.0.1") << QHostAddress("172.16.0.0") << 16 << true;
|
|
|
|
// the address is always in the subnet containing its address, regardless of length:
|
|
QTest::newRow("same_01") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHost) << 1 << true;
|
|
QTest::newRow("same_07") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHost) << 7 << true;
|
|
QTest::newRow("same_8") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHost) << 8 << true;
|
|
QTest::newRow("same_24") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHost) << 23 << true;
|
|
QTest::newRow("same_31") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHost) << 31 << true;
|
|
QTest::newRow("same_32") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHost) << 32 << true;
|
|
|
|
// IPv6 correct ones:
|
|
QTest::newRow("ipv6_netmask_0") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::AnyIPv6) << 0 << true;
|
|
QTest::newRow("ipv6_netmask_0bis") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::LocalHostIPv6) << 0 << true;
|
|
QTest::newRow("ipv6_netmask_0ter") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress("ffff::") << 0 << true;
|
|
QTest::newRow("ipv6_netmask_1") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::AnyIPv6) << 1 << true;
|
|
QTest::newRow("ipv6_netmask_1bis") << QHostAddress("fec0::1") << QHostAddress("8000::") << 1 << true;
|
|
QTest::newRow("~ipv6_netmask_1") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress("8000::") << 1 << false;
|
|
QTest::newRow("~ipv6_netmask_1bis") << QHostAddress("fec0::1") << QHostAddress("::") << 1 << false;
|
|
QTest::newRow("ipv6_netmask_47") << QHostAddress("2:3:5::1") << QHostAddress("2:3:4::") << 47 << true;
|
|
QTest::newRow("ipv6_netmask_48") << QHostAddress("2:3:4::1") << QHostAddress("2:3:4::") << 48 << true;
|
|
QTest::newRow("~ipv6_netmask_48") << QHostAddress("2:3:5::1") << QHostAddress("2:3:4::") << 48 << false;
|
|
QTest::newRow("ipv6_netmask_127") << QHostAddress("2:3:4:5::1") << QHostAddress("2:3:4:5::") << 127 << true;
|
|
QTest::newRow("ipv6_netmask_128") << QHostAddress("2:3:4:5::1") << QHostAddress("2:3:4:5::1") << 128 << true;
|
|
QTest::newRow("~ipv6_netmask_128") << QHostAddress("2:3:4:5::1") << QHostAddress("2:3:4:5::0") << 128 << false;
|
|
}
|
|
|
|
void tst_QHostAddress::isInSubnet()
|
|
{
|
|
QFETCH(QHostAddress, address);
|
|
QFETCH(QHostAddress, prefix);
|
|
QFETCH(int, prefixLength);
|
|
|
|
QTEST(address.isInSubnet(prefix, prefixLength), "result");
|
|
}
|
|
|
|
QTEST_MAIN(tst_QHostAddress)
|
|
#include "tst_qhostaddress.moc"
|