From c59f9ad7768a007ca7a49ea11b16617529e86d52 Mon Sep 17 00:00:00 2001 From: Jo Asplin Date: Tue, 6 Sep 2011 13:46:40 +0200 Subject: Moved network autotests into new directory structure Task-number: QTBUG-21223 Change-Id: I55dbf5c42a1c5d938b9e0c9bf7d90457a6c26bbc Reviewed-on: http://codereview.qt-project.org/4259 Reviewed-by: Qt Sanity Bot Reviewed-by: Sergio Ahumada Reviewed-by: Rohan McGovern --- .../network/kernel/qhostinfo/tst_qhostinfo.cpp | 665 +++++++++++++++++++++ 1 file changed, 665 insertions(+) create mode 100644 tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp (limited to 'tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp') diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp new file mode 100644 index 0000000000..58b51bcb69 --- /dev/null +++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp @@ -0,0 +1,665 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +// When using WinSock2 on Windows, it's the first thing that can be included +// (except qglobal.h), or else you'll get tons of compile errors +#include + +// MinGW doesn't provide getaddrinfo(), so we test for Q_OS_WIN +// and Q_CC_GNU, which indirectly tells us whether we're using MinGW. +#if defined(Q_OS_WIN) && defined(Q_CC_GNU) +# define QT_NO_GETADDRINFO +#endif + +#if defined(Q_OS_WIN) && !defined(QT_NO_GETADDRINFO) +# include +# include +#endif + +#include +#include +#include +#include +#include +#include + +#ifndef QT_NO_BEARERMANAGEMENT +#include +#include +#include +#endif + +#include +#include +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +#include +#else +#include +#include +#endif + +#include +#include "private/qhostinfo_p.h" + +#if !defined(QT_NO_GETADDRINFO) +# if !defined(Q_OS_WINCE) +# include +# else +# include +# endif +# if defined(Q_OS_UNIX) +# include +# endif +# if !defined(Q_OS_WIN) +# include +# endif +#endif + +#include "../../../network-settings.h" +#include "../../../../shared/util.h" + +//TESTED_CLASS= +//TESTED_FILES= + +const char * const lupinellaIp = "10.3.4.6"; + + +class tst_QHostInfo : public QObject +{ + Q_OBJECT + +public: + tst_QHostInfo(); + virtual ~tst_QHostInfo(); + + +public slots: + void init(); + void cleanup(); + void initTestCase(); + +private slots: + void getSetCheck(); + void staticInformation(); + void lookupIPv4_data(); + void lookupIPv4(); + void lookupIPv6_data(); + void lookupIPv6(); + void reverseLookup_data(); + void reverseLookup(); + + void blockingLookup_data(); + void blockingLookup(); + + void raceCondition(); + void threadSafety(); + void threadSafetyAsynchronousAPI(); + + void multipleSameLookups(); + void multipleDifferentLookups_data(); + void multipleDifferentLookups(); + + void cache(); + + void abortHostLookup(); + void abortHostLookupInDifferentThread(); +protected slots: + void resultsReady(const QHostInfo &); + +private: + bool ipv6LookupsAvailable; + bool ipv6Available; + bool lookupDone; + int lookupsDoneCounter; + QHostInfo lookupResults; +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer networkSession; +#endif +}; + +// Testing get/set functions +void tst_QHostInfo::getSetCheck() +{ + QHostInfo obj1; + // HostInfoError QHostInfo::error() + // void QHostInfo::setError(HostInfoError) + obj1.setError(QHostInfo::HostInfoError(0)); + QCOMPARE(QHostInfo::HostInfoError(0), obj1.error()); + obj1.setError(QHostInfo::HostInfoError(1)); + QCOMPARE(QHostInfo::HostInfoError(1), obj1.error()); + + // int QHostInfo::lookupId() + // void QHostInfo::setLookupId(int) + obj1.setLookupId(0); + QCOMPARE(0, obj1.lookupId()); + obj1.setLookupId(INT_MIN); + QCOMPARE(INT_MIN, obj1.lookupId()); + obj1.setLookupId(INT_MAX); + QCOMPARE(INT_MAX, obj1.lookupId()); +} + +void tst_QHostInfo::staticInformation() +{ + qDebug() << "Hostname:" << QHostInfo::localHostName(); + qDebug() << "Domain name:" << QHostInfo::localDomainName(); +} + +tst_QHostInfo::tst_QHostInfo() +{ + Q_SET_DEFAULT_IAP +} + +tst_QHostInfo::~tst_QHostInfo() +{ +} + +void tst_QHostInfo::initTestCase() +{ +#ifndef QT_NO_BEARERMANAGEMENT + //start the default network + netConfMan = new QNetworkConfigurationManager(this); + networkConfiguration = netConfMan->defaultConfiguration(); + networkSession.reset(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + QVERIFY(networkSession->waitForOpened(30000)); + } +#endif + +#ifdef Q_OS_SYMBIAN + ipv6Available = true; + ipv6LookupsAvailable = true; +#else + ipv6Available = false; + ipv6LookupsAvailable = false; + + QTcpServer server; + if (server.listen(QHostAddress("::1"))) { + // We have IPv6 support + ipv6Available = true; + } + +#if !defined(QT_NO_GETADDRINFO) + // check if the system getaddrinfo can do IPv6 lookups + struct addrinfo hint, *result = 0; + memset(&hint, 0, sizeof hint); + hint.ai_family = AF_UNSPEC; +# ifdef AI_ADDRCONFIG + hint.ai_flags = AI_ADDRCONFIG; +# endif + + int res = getaddrinfo("::1", "80", &hint, &result); + if (res == 0) { + // this test worked + freeaddrinfo(result); + res = getaddrinfo("ipv6-test.dev.troll.no", "80", &hint, &result); + if (res == 0 && result != 0 && result->ai_family != AF_INET) { + freeaddrinfo(result); + ipv6LookupsAvailable = true; + } + } +#endif +#endif + + // run each testcase with and without test enabled + QTest::addColumn("cache"); + QTest::newRow("WithCache") << true; + QTest::newRow("WithoutCache") << false; +} + +void tst_QHostInfo::init() +{ + // delete the cache so inidividual testcase results are independent from each other + qt_qhostinfo_clear_cache(); + + QFETCH_GLOBAL(bool, cache); + qt_qhostinfo_enable_cache(cache); +} + +void tst_QHostInfo::cleanup() +{ +} + +void tst_QHostInfo::lookupIPv4_data() +{ + QTest::addColumn("hostname"); + QTest::addColumn("addresses"); + QTest::addColumn("err"); + + // Test server lookup + QTest::newRow("lookup_01") << QtNetworkSettings::serverName() << QtNetworkSettings::serverIP().toString() << int(QHostInfo::NoError); + QTest::newRow("empty") << "" << "" << int(QHostInfo::HostNotFound); + + QTest::newRow("single_ip4") << "lupinella.troll.no" << lupinellaIp << int(QHostInfo::NoError); + QTest::newRow("multiple_ip4") << "multi.dev.troll.no" << "1.2.3.4 1.2.3.5 10.3.3.31" << int(QHostInfo::NoError); + QTest::newRow("literal_ip4") << lupinellaIp << lupinellaIp << int(QHostInfo::NoError); + + QTest::newRow("notfound") << "this-name-does-not-exist-hopefully." << "" << int(QHostInfo::HostNotFound); + + QTest::newRow("idn-ace") << "xn--alqualond-34a.troll.no" << "10.3.3.55" << int(QHostInfo::NoError); + QTest::newRow("idn-unicode") << QString::fromLatin1("alqualond\353.troll.no") << "10.3.3.55" << int(QHostInfo::NoError); +} + +void tst_QHostInfo::lookupIPv4() +{ + QFETCH(QString, hostname); + QFETCH(int, err); + QFETCH(QString, addresses); + + lookupDone = false; + QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(const QHostInfo&))); + + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(lookupDone); + + if ((int)lookupResults.error() != (int)err) { + qWarning() << hostname << "=>" << lookupResults.errorString(); + } + QCOMPARE((int)lookupResults.error(), (int)err); + + QStringList tmp; + for (int i = 0; i < lookupResults.addresses().count(); ++i) + tmp.append(lookupResults.addresses().at(i).toString()); + tmp.sort(); + + QStringList expected = addresses.split(' '); + expected.sort(); + + QCOMPARE(tmp.join(" "), expected.join(" ")); +} + +void tst_QHostInfo::lookupIPv6_data() +{ + QTest::addColumn("hostname"); + QTest::addColumn("addresses"); + QTest::addColumn("err"); + + QTest::newRow("ipv6-net") << "www.ipv6-net.org" << "62.93.217.177 2001:618:1401::4" << int(QHostInfo::NoError); + QTest::newRow("ipv6-test") << "ipv6-test.dev.troll.no" << "2001:638:a00:2::2" << int(QHostInfo::NoError); + QTest::newRow("dns6-test") << "dns6-test-dev.troll.no" << "2001:470:1f01:115::10" << int(QHostInfo::NoError); + QTest::newRow("multi-dns6") << "multi-dns6-test-dev.troll.no" << "2001:470:1f01:115::11 2001:470:1f01:115::12" << int(QHostInfo::NoError); + QTest::newRow("dns46-test") << "dns46-test-dev.troll.no" << "10.3.4.90 2001:470:1f01:115::13" << int(QHostInfo::NoError); + + // avoid using real IPv6 addresses here because this will do a DNS query + // real addresses are between 2000:: and 3fff:ffff:ffff:ffff:ffff:ffff:ffff + QTest::newRow("literal_ip6") << "f001:6b0:1:ea:202:a5ff:fecd:13a6" << "f001:6b0:1:ea:202:a5ff:fecd:13a6" << int(QHostInfo::NoError); + QTest::newRow("literal_shortip6") << "f001:618:1401::4" << "f001:618:1401::4" << int(QHostInfo::NoError); +} + +void tst_QHostInfo::lookupIPv6() +{ + QFETCH(QString, hostname); + QFETCH(int, err); + QFETCH(QString, addresses); + + if (!ipv6LookupsAvailable) + QSKIP("This platform does not support IPv6 lookups", SkipAll); + + lookupDone = false; + QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(const QHostInfo&))); + + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(lookupDone); + + QCOMPARE((int)lookupResults.error(), (int)err); + + QStringList tmp; + for (int i = 0; i < lookupResults.addresses().count(); ++i) + tmp.append(lookupResults.addresses().at(i).toString()); + tmp.sort(); + + QStringList expected = addresses.split(' '); + expected.sort(); + + QCOMPARE(tmp.join(" ").toLower(), expected.join(" ").toLower()); +} + +void tst_QHostInfo::reverseLookup_data() +{ + QTest::addColumn("address"); + QTest::addColumn("hostNames"); + QTest::addColumn("err"); + + QTest::newRow("trolltech.com") << QString("62.70.27.69") << QStringList(QString("diverse.troll.no")) << 0; + + // ### Use internal DNS instead. Discussed with Andreas. + //QTest::newRow("classical.hexago.com") << QString("2001:5c0:0:2::24") << QStringList(QString("classical.hexago.com")) << 0; + QTest::newRow("gitorious.org") << QString("87.238.52.168") << QStringList(QString("gitorious.org")) << 0; + QTest::newRow("bogus-name") << QString("1::2::3::4") << QStringList() << 1; +} + +void tst_QHostInfo::reverseLookup() +{ + QFETCH(QString, address); + QFETCH(QStringList, hostNames); + QFETCH(int, err); + + if (!ipv6LookupsAvailable && hostNames.contains("classical.hexago.com")) { + QSKIP("IPv6 lookups are not supported on this platform", SkipSingle); + } +#if defined(Q_OS_HPUX) && defined(__ia64) + if (hostNames.contains("classical.hexago.com")) + QSKIP("HP-UX 11i does not support IPv6 reverse lookups.", SkipSingle); +#endif + + QHostInfo info = QHostInfo::fromName(address); + + if (err == 0) { + QVERIFY(hostNames.contains(info.hostName())); + QCOMPARE(info.addresses().first(), QHostAddress(address)); + } else { + QCOMPARE(info.hostName(), address); + QCOMPARE(info.error(), QHostInfo::HostNotFound); + } + +} + +void tst_QHostInfo::blockingLookup_data() +{ + lookupIPv4_data(); + if (ipv6LookupsAvailable) + lookupIPv6_data(); +} + +void tst_QHostInfo::blockingLookup() +{ + QFETCH(QString, hostname); + QFETCH(int, err); + QFETCH(QString, addresses); + + QHostInfo hostInfo = QHostInfo::fromName(hostname); + QStringList tmp; + for (int i = 0; i < hostInfo.addresses().count(); ++i) + tmp.append(hostInfo.addresses().at(i).toString()); + tmp.sort(); + + if ((int)hostInfo.error() != (int)err) { + qWarning() << hostname << "=>" << lookupResults.errorString(); + } + QCOMPARE((int)hostInfo.error(), (int)err); + + QStringList expected = addresses.split(' '); + expected.sort(); + + QCOMPARE(tmp.join(" ").toUpper(), expected.join(" ").toUpper()); +} + +void tst_QHostInfo::raceCondition() +{ + for (int i = 0; i < 1000; ++i) { + QTcpSocket socket; + socket.connectToHost("notavalidname.troll.no", 80); + } +} + +class LookupThread : public QThread +{ +protected: + inline void run() + { + QHostInfo info = QHostInfo::fromName("qt.nokia.com"); + QCOMPARE(info.error(), QHostInfo::NoError); + QVERIFY(info.addresses().count() > 0); + QCOMPARE(info.addresses().at(0).toString(), QString("87.238.50.178")); + } +}; + +void tst_QHostInfo::threadSafety() +{ + const int nattempts = 5; +#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) + const int runs = 10; +#else + const int runs = 100; +#endif + LookupThread thr[nattempts]; + for (int j = 0; j < runs; ++j) { + for (int i = 0; i < nattempts; ++i) + thr[i].start(); + for (int k = nattempts - 1; k >= 0; --k) + thr[k].wait(); + } +} + +class LookupReceiver : public QObject +{ + Q_OBJECT +public slots: + void start(); + void resultsReady(const QHostInfo&); +public: + QHostInfo result; + int numrequests; +}; + +void LookupReceiver::start() +{ + for (int i=0;iquit(); +} + +void tst_QHostInfo::threadSafetyAsynchronousAPI() +{ + const int nattempts = 10; + const int lookupsperthread = 10; + QList threads; + QList receivers; + for (int i = 0; i < nattempts; ++i) { + QThread* thread = new QThread; + LookupReceiver* receiver = new LookupReceiver; + receiver->numrequests = lookupsperthread; + receivers.append(receiver); + receiver->moveToThread(thread); + connect(thread, SIGNAL(started()), receiver, SLOT(start())); + thread->start(); + threads.append(thread); + } + for (int k = threads.count() - 1; k >= 0; --k) + QVERIFY(threads.at(k)->wait(60000)); + foreach (LookupReceiver* receiver, receivers) { + QCOMPARE(receiver->result.error(), QHostInfo::NoError); + QCOMPARE(receiver->result.addresses().at(0).toString(), QString("87.238.50.178")); + QCOMPARE(receiver->numrequests, 0); + } +} + +// this test is for the multi-threaded QHostInfo rewrite. It is about getting results at all, +// not about getting correct IPs +void tst_QHostInfo::multipleSameLookups() +{ + const int COUNT = 10; + lookupsDoneCounter = 0; + + for (int i = 0; i < COUNT; i++) + QHostInfo::lookupHost("localhost", this, SLOT(resultsReady(const QHostInfo))); + + QElapsedTimer timer; + timer.start(); + while (timer.elapsed() < 10000 && lookupsDoneCounter < COUNT) { + QTestEventLoop::instance().enterLoop(2); + } + QCOMPARE(lookupsDoneCounter, COUNT); +} + +// this test is for the multi-threaded QHostInfo rewrite. It is about getting results at all, +// not about getting correct IPs +void tst_QHostInfo::multipleDifferentLookups_data() +{ + QTest::addColumn("repeats"); + QTest::newRow("1") << 1; + QTest::newRow("2") << 2; + QTest::newRow("5") << 5; + QTest::newRow("10") << 10; +} + +void tst_QHostInfo::multipleDifferentLookups() +{ + QStringList hostnameList; + hostnameList << "www.ovi.com" << "www.nokia.com" << "qt.nokia.com" << "www.trolltech.com" << "troll.no" + << "www.qtcentre.org" << "forum.nokia.com" << "www.nokia.com" << "wiki.forum.nokia.com" + << "www.nokia.com" << "nokia.de" << "127.0.0.1" << "----"; + + QFETCH(int, repeats); + const int COUNT = hostnameList.size(); + lookupsDoneCounter = 0; + + for (int i = 0; i < hostnameList.size(); i++) + for (int j = 0; j < repeats; ++j) + QHostInfo::lookupHost(hostnameList.at(i), this, SLOT(resultsReady(const QHostInfo))); + + QElapsedTimer timer; + timer.start(); + while (timer.elapsed() < 60000 && lookupsDoneCounter < repeats*COUNT) { + QTestEventLoop::instance().enterLoop(2); + //qDebug() << "t:" << timer.elapsed(); + } + QCOMPARE(lookupsDoneCounter, repeats*COUNT); +} + +void tst_QHostInfo::cache() +{ + QFETCH_GLOBAL(bool, cache); + if (!cache) + return; // test makes only sense when cache enabled + + // reset slot counter + lookupsDoneCounter = 0; + + // lookup once, wait in event loop, result should not come directly. + bool valid = true; + int id = -1; + QHostInfo result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id); + QTestEventLoop::instance().enterLoop(5); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(valid == false); + QVERIFY(result.addresses().isEmpty()); + + // loopkup second time, result should come directly + valid = false; + result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id); + QVERIFY(valid == true); + QVERIFY(!result.addresses().isEmpty()); + + // clear the cache + qt_qhostinfo_clear_cache(); + + // lookup third time, result should not come directly. + valid = true; + result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id); + QTestEventLoop::instance().enterLoop(5); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(valid == false); + QVERIFY(result.addresses().isEmpty()); + + // the slot should have been called 2 times. + QCOMPARE(lookupsDoneCounter, 2); +} + +void tst_QHostInfo::resultsReady(const QHostInfo &hi) +{ + lookupDone = true; + lookupResults = hi; + lookupsDoneCounter++; + QTestEventLoop::instance().exitLoop(); +} + +void tst_QHostInfo::abortHostLookup() +{ + //reset counter + lookupsDoneCounter = 0; + bool valid = false; + int id = -1; + QHostInfo result = qt_qhostinfo_lookup("qt.nokia.com", this, SLOT(resultsReady(QHostInfo)), &valid, &id); + QVERIFY(!valid); + //it is assumed that the DNS request/response in the backend is slower than it takes to call abort + QHostInfo::abortHostLookup(id); + QTestEventLoop::instance().enterLoop(5); + QCOMPARE(lookupsDoneCounter, 0); +} + +class LookupAborter : public QObject +{ + Q_OBJECT +public slots: + void abort() + { + QHostInfo::abortHostLookup(id); + QThread::currentThread()->quit(); + } +public: + int id; +}; + +void tst_QHostInfo::abortHostLookupInDifferentThread() +{ + //reset counter + lookupsDoneCounter = 0; + bool valid = false; + int id = -1; + QHostInfo result = qt_qhostinfo_lookup("qt.nokia.com", this, SLOT(resultsReady(QHostInfo)), &valid, &id); + QVERIFY(!valid); + QThread thread; + LookupAborter aborter; + aborter.id = id; + aborter.moveToThread(&thread); + connect(&thread, SIGNAL(started()), &aborter, SLOT(abort())); + //it is assumed that the DNS request/response in the backend is slower than it takes to schedule the thread and call abort + thread.start(); + QVERIFY(thread.wait(5000)); + QTestEventLoop::instance().enterLoop(5); + QCOMPARE(lookupsDoneCounter, 0); +} + +QTEST_MAIN(tst_QHostInfo) +#include "tst_qhostinfo.moc" -- cgit v1.2.3