tests/auto/qhostinfo/tst_qhostinfo.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 // When using WinSock2 on Windows, it's the first thing that can be included
       
    44 // (except qglobal.h), or else you'll get tons of compile errors
       
    45 #include <qglobal.h>
       
    46 
       
    47 // MinGW doesn't provide getaddrinfo(), so we test for Q_OS_WIN
       
    48 // and Q_CC_GNU, which indirectly tells us whether we're using MinGW.
       
    49 #if defined(Q_OS_WIN) && defined(Q_CC_GNU)
       
    50 # define QT_NO_GETADDRINFO
       
    51 #endif
       
    52 
       
    53 #if defined(Q_OS_WIN) && !defined(QT_NO_GETADDRINFO)
       
    54 # include <winsock2.h>
       
    55 # include <ws2tcpip.h>
       
    56 #endif
       
    57 
       
    58 #include <QtTest/QtTest>
       
    59 #include <qcoreapplication.h>
       
    60 #include <QDebug>
       
    61 #include <QTcpSocket>
       
    62 #include <private/qthread_p.h>
       
    63 #include <QTcpServer>
       
    64 
       
    65 #include <time.h>
       
    66 #include <qlibrary.h>
       
    67 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
       
    68 #include <windows.h>
       
    69 #else
       
    70 #include <unistd.h>
       
    71 #include <signal.h>
       
    72 #endif
       
    73 
       
    74 #include <qhostinfo.h>
       
    75 
       
    76 #if !defined(QT_NO_GETADDRINFO)
       
    77 # if !defined(Q_OS_WINCE)
       
    78 #  include <sys/types.h>
       
    79 # else
       
    80 #  include <types.h>
       
    81 # endif
       
    82 # if defined(Q_OS_UNIX)
       
    83 #  include <sys/socket.h>
       
    84 # endif
       
    85 # if !defined(Q_OS_WIN)
       
    86 #  include <netdb.h>
       
    87 # endif
       
    88 #endif
       
    89 
       
    90 #include "../network-settings.h"
       
    91 
       
    92 //TESTED_CLASS=
       
    93 //TESTED_FILES=
       
    94 
       
    95 const char * const lupinellaIp = "10.3.4.6";
       
    96 
       
    97 
       
    98 class tst_QHostInfo : public QObject
       
    99 {
       
   100     Q_OBJECT
       
   101 
       
   102 public:
       
   103     tst_QHostInfo();
       
   104     virtual ~tst_QHostInfo();
       
   105 
       
   106 
       
   107 public slots:
       
   108     void init();
       
   109     void cleanup();
       
   110 private slots:
       
   111     void getSetCheck();
       
   112     void staticInformation();
       
   113     void initTestCase();
       
   114     void lookupIPv4_data();
       
   115     void lookupIPv4();
       
   116     void lookupIPv6_data();
       
   117     void lookupIPv6();
       
   118     void reverseLookup_data();
       
   119     void reverseLookup();
       
   120 
       
   121     void blockingLookup_data();
       
   122     void blockingLookup();
       
   123 
       
   124     void raceCondition();
       
   125     void threadSafety();
       
   126 
       
   127 protected slots:
       
   128     void resultsReady(const QHostInfo &);
       
   129 
       
   130 private:
       
   131     bool ipv6LookupsAvailable;
       
   132     bool ipv6Available;
       
   133     bool lookupDone;
       
   134     QHostInfo lookupResults;
       
   135 };
       
   136 
       
   137 // Testing get/set functions
       
   138 void tst_QHostInfo::getSetCheck()
       
   139 {
       
   140     QHostInfo obj1;
       
   141     // HostInfoError QHostInfo::error()
       
   142     // void QHostInfo::setError(HostInfoError)
       
   143     obj1.setError(QHostInfo::HostInfoError(0));
       
   144     QCOMPARE(QHostInfo::HostInfoError(0), obj1.error());
       
   145     obj1.setError(QHostInfo::HostInfoError(1));
       
   146     QCOMPARE(QHostInfo::HostInfoError(1), obj1.error());
       
   147 
       
   148     // int QHostInfo::lookupId()
       
   149     // void QHostInfo::setLookupId(int)
       
   150     obj1.setLookupId(0);
       
   151     QCOMPARE(0, obj1.lookupId());
       
   152     obj1.setLookupId(INT_MIN);
       
   153     QCOMPARE(INT_MIN, obj1.lookupId());
       
   154     obj1.setLookupId(INT_MAX);
       
   155     QCOMPARE(INT_MAX, obj1.lookupId());
       
   156 }
       
   157 
       
   158 void tst_QHostInfo::staticInformation()
       
   159 {
       
   160     qDebug() << "Hostname:" << QHostInfo::localHostName();
       
   161     qDebug() << "Domain name:" << QHostInfo::localDomainName();
       
   162 }
       
   163 
       
   164 tst_QHostInfo::tst_QHostInfo()
       
   165 {
       
   166     Q_SET_DEFAULT_IAP
       
   167 }
       
   168 
       
   169 tst_QHostInfo::~tst_QHostInfo()
       
   170 {
       
   171 }
       
   172 
       
   173 void tst_QHostInfo::initTestCase()
       
   174 {
       
   175     ipv6Available = false;
       
   176     ipv6LookupsAvailable = false;
       
   177 #if !defined(QT_NO_GETADDRINFO)
       
   178     // check if the system getaddrinfo can do IPv6 lookups
       
   179     struct addrinfo hint, *result = 0;
       
   180     memset(&hint, 0, sizeof hint);
       
   181     hint.ai_family = AF_UNSPEC;
       
   182 # ifdef AI_ADDRCONFIG
       
   183     hint.ai_flags = AI_ADDRCONFIG;
       
   184 # endif
       
   185 
       
   186     int res = getaddrinfo("::1", "80", &hint, &result);
       
   187     if (res == 0) {
       
   188         // this test worked
       
   189         freeaddrinfo(result);
       
   190         res = getaddrinfo("ipv6-test.dev.troll.no", "80", &hint, &result);
       
   191         if (res == 0 && result != 0 && result->ai_family != AF_INET) {
       
   192             freeaddrinfo(result);
       
   193             ipv6LookupsAvailable = true;
       
   194         }
       
   195     }
       
   196 #endif
       
   197 
       
   198     QTcpServer server;
       
   199     if (server.listen(QHostAddress("::1"))) {
       
   200         // We have IPv6 support
       
   201         ipv6Available = true;
       
   202     }
       
   203 }
       
   204 
       
   205 void tst_QHostInfo::init()
       
   206 {
       
   207 }
       
   208 
       
   209 void tst_QHostInfo::cleanup()
       
   210 {
       
   211 }
       
   212 
       
   213 void tst_QHostInfo::lookupIPv4_data()
       
   214 {
       
   215     QTest::addColumn<QString>("hostname");
       
   216     QTest::addColumn<QString>("addresses");
       
   217     QTest::addColumn<int>("err");
       
   218 
       
   219 #ifdef Q_OS_SYMBIAN
       
   220     // Test server lookup
       
   221     QTest::newRow("lookup_01") << QtNetworkSettings::serverName() << QtNetworkSettings::serverIP().toString() << int(QHostInfo::NoError);
       
   222     QTest::newRow("literal_ip4") << QtNetworkSettings::serverIP().toString() << QtNetworkSettings::serverIP().toString() << int(QHostInfo::NoError);
       
   223     QTest::newRow("multiple_ip4") << "multi.dev.troll.no" << "1.2.3.4 1.2.3.5 10.3.3.31" << int(QHostInfo::NoError);
       
   224 #else
       
   225     QTest::newRow("empty") << "" << "" << int(QHostInfo::HostNotFound);
       
   226 
       
   227     QTest::newRow("single_ip4") << "lupinella.troll.no" << lupinellaIp << int(QHostInfo::NoError);
       
   228     QTest::newRow("multiple_ip4") << "multi.dev.troll.no" << "1.2.3.4 1.2.3.5 10.3.3.31" << int(QHostInfo::NoError);
       
   229     QTest::newRow("literal_ip4") << lupinellaIp << lupinellaIp << int(QHostInfo::NoError);
       
   230 #endif
       
   231     QTest::newRow("notfound") << "this-name-does-not-exist-hopefully." << "" << int(QHostInfo::HostNotFound);
       
   232 
       
   233     QTest::newRow("idn-ace") << "xn--alqualond-34a.troll.no" << "10.3.3.55" << int(QHostInfo::NoError);
       
   234     QTest::newRow("idn-unicode") << QString::fromLatin1("alqualond\353.troll.no") << "10.3.3.55" << int(QHostInfo::NoError);
       
   235 }
       
   236 
       
   237 void tst_QHostInfo::lookupIPv4()
       
   238 {
       
   239     QFETCH(QString, hostname);
       
   240     QFETCH(int, err);
       
   241     QFETCH(QString, addresses);
       
   242 
       
   243     lookupDone = false;
       
   244     QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(const QHostInfo&)));
       
   245 
       
   246     QTestEventLoop::instance().enterLoop(10);
       
   247     QVERIFY(!QTestEventLoop::instance().timeout());
       
   248     QVERIFY(lookupDone);
       
   249 
       
   250     if ((int)lookupResults.error() != (int)err) {
       
   251         qWarning() << hostname << "=>" << lookupResults.errorString();
       
   252     }
       
   253     QCOMPARE((int)lookupResults.error(), (int)err);
       
   254 
       
   255     QStringList tmp;
       
   256     for (int i = 0; i < lookupResults.addresses().count(); ++i)
       
   257         tmp.append(lookupResults.addresses().at(i).toString());
       
   258     tmp.sort();
       
   259 
       
   260     QStringList expected = addresses.split(' ');
       
   261     expected.sort();
       
   262 
       
   263     QCOMPARE(tmp.join(" "), expected.join(" "));
       
   264 }
       
   265 
       
   266 void tst_QHostInfo::lookupIPv6_data()
       
   267 {
       
   268     QTest::addColumn<QString>("hostname");
       
   269     QTest::addColumn<QString>("addresses");
       
   270     QTest::addColumn<int>("err");
       
   271 
       
   272     QTest::newRow("ip6") << "www.ipv6-net.org" << "62.93.217.177 2001:618:1401:0:0:0:0:4" << int(QHostInfo::NoError);
       
   273 
       
   274     // avoid using real IPv6 addresses here because this will do a DNS query
       
   275     // real addresses are between 2000:: and 3fff:ffff:ffff:ffff:ffff:ffff:ffff
       
   276     QTest::newRow("literal_ip6") << "f001:6b0:1:ea:202:a5ff:fecd:13a6" << "f001:6b0:1:ea:202:a5ff:fecd:13a6" << int(QHostInfo::NoError);
       
   277     QTest::newRow("literal_shortip6") << "f001:618:1401::4" << "f001:618:1401:0:0:0:0:4" << int(QHostInfo::NoError);
       
   278 }
       
   279 
       
   280 void tst_QHostInfo::lookupIPv6()
       
   281 {
       
   282     QFETCH(QString, hostname);
       
   283     QFETCH(int, err);
       
   284     QFETCH(QString, addresses);
       
   285 
       
   286     if (!ipv6LookupsAvailable)
       
   287         QSKIP("This platform does not support IPv6 lookups", SkipAll);
       
   288 
       
   289     lookupDone = false;
       
   290     QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(const QHostInfo&)));
       
   291 
       
   292     QTestEventLoop::instance().enterLoop(3);
       
   293     QVERIFY(!QTestEventLoop::instance().timeout());
       
   294     QVERIFY(lookupDone);
       
   295 
       
   296     QCOMPARE((int)lookupResults.error(), (int)err);
       
   297 
       
   298     QStringList tmp;
       
   299     for (int i = 0; i < lookupResults.addresses().count(); ++i)
       
   300         tmp.append(lookupResults.addresses().at(i).toString());
       
   301     tmp.sort();
       
   302 
       
   303     QStringList expected = addresses.split(' ');
       
   304     expected.sort();
       
   305 
       
   306     QCOMPARE(tmp.join(" ").toLower(), expected.join(" ").toLower());
       
   307 }
       
   308 
       
   309 void tst_QHostInfo::reverseLookup_data()
       
   310 {
       
   311     QTest::addColumn<QString>("address");
       
   312     QTest::addColumn<QStringList>("hostNames");
       
   313     QTest::addColumn<int>("err");
       
   314 
       
   315     QTest::newRow("trolltech.com") << QString("62.70.27.69") << QStringList(QString("diverse.troll.no")) << 0;
       
   316 
       
   317     // ### Use internal DNS instead. Discussed with Andreas.
       
   318     //QTest::newRow("classical.hexago.com") << QString("2001:5c0:0:2::24") << QStringList(QString("classical.hexago.com")) << 0;
       
   319     QTest::newRow("origin.cisco.com") << QString("12.159.148.94") << QStringList(QString("origin.cisco.com")) << 0;
       
   320     QTest::newRow("bogus-name") << QString("1::2::3::4") << QStringList() << 1;
       
   321 }
       
   322 
       
   323 void tst_QHostInfo::reverseLookup()
       
   324 {
       
   325     QFETCH(QString, address);
       
   326     QFETCH(QStringList, hostNames);
       
   327     QFETCH(int, err);
       
   328 
       
   329     if (!ipv6LookupsAvailable && hostNames.contains("classical.hexago.com")) {
       
   330         QSKIP("IPv6 lookups are not supported on this platform", SkipSingle);
       
   331     }
       
   332 #if defined(Q_OS_HPUX) && defined(__ia64)
       
   333     if (hostNames.contains("classical.hexago.com"))
       
   334         QSKIP("HP-UX 11i does not support IPv6 reverse lookups.", SkipSingle);
       
   335 #endif
       
   336 
       
   337     QHostInfo info = QHostInfo::fromName(address);
       
   338 
       
   339     if (err == 0) {
       
   340         QVERIFY(hostNames.contains(info.hostName()));
       
   341         QCOMPARE(info.addresses().first(), QHostAddress(address));
       
   342     } else {
       
   343         QCOMPARE(info.hostName(), address);
       
   344         QCOMPARE(info.error(), QHostInfo::HostNotFound);
       
   345     }
       
   346 
       
   347 }
       
   348 
       
   349 void tst_QHostInfo::blockingLookup_data()
       
   350 {
       
   351     lookupIPv4_data();
       
   352     if (ipv6LookupsAvailable)
       
   353         lookupIPv6_data();
       
   354 }
       
   355 
       
   356 void tst_QHostInfo::blockingLookup()
       
   357 {
       
   358     QFETCH(QString, hostname);
       
   359     QFETCH(int, err);
       
   360     QFETCH(QString, addresses);
       
   361 
       
   362     QHostInfo hostInfo = QHostInfo::fromName(hostname);
       
   363     QStringList tmp;
       
   364     for (int i = 0; i < hostInfo.addresses().count(); ++i)
       
   365         tmp.append(hostInfo.addresses().at(i).toString());
       
   366     tmp.sort();
       
   367 
       
   368     if ((int)hostInfo.error() != (int)err) {
       
   369         qWarning() << hostname << "=>" << lookupResults.errorString();
       
   370     }
       
   371     QCOMPARE((int)hostInfo.error(), (int)err);
       
   372 
       
   373     QStringList expected = addresses.split(' ');
       
   374     expected.sort();
       
   375 
       
   376     QCOMPARE(tmp.join(" ").toUpper(), expected.join(" ").toUpper());
       
   377 }
       
   378 
       
   379 void tst_QHostInfo::raceCondition()
       
   380 {
       
   381     for (int i = 0; i < 1000; ++i) {
       
   382         QTcpSocket socket;
       
   383         socket.connectToHost("notavalidname.troll.no", 80);
       
   384     }
       
   385 }
       
   386 
       
   387 class LookupThread : public QThread
       
   388 {
       
   389 protected:
       
   390     inline void run()
       
   391     {
       
   392          QHostInfo info = QHostInfo::fromName("qt.nokia.com");
       
   393          QCOMPARE(info.addresses().at(0).toString(), QString("87.238.50.178"));
       
   394     }
       
   395 };
       
   396 
       
   397 void tst_QHostInfo::threadSafety()
       
   398 {
       
   399     const int nattempts = 5;
       
   400 #if defined(Q_OS_WINCE)
       
   401     const int runs = 10;
       
   402 #else
       
   403     const int runs = 100;
       
   404 #endif
       
   405     LookupThread thr[nattempts];
       
   406     for (int j = 0; j < runs; ++j) {
       
   407         for (int i = 0; i < nattempts; ++i)
       
   408             thr[i].start();
       
   409         for (int k = nattempts - 1; k >= 0; --k)
       
   410             thr[k].wait();
       
   411     }
       
   412 }
       
   413 
       
   414 void tst_QHostInfo::resultsReady(const QHostInfo &hi)
       
   415 {
       
   416     lookupDone = true;
       
   417     lookupResults = hi;
       
   418 
       
   419     QTestEventLoop::instance().exitLoop();
       
   420 }
       
   421 
       
   422 QTEST_MAIN(tst_QHostInfo)
       
   423 #include "tst_qhostinfo.moc"