qtmobility/tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.cpp
branchRCL_3
changeset 9 5d007b20cfd0
parent 8 885c2596c964
child 10 cd2778e5acfe
equal deleted inserted replaced
8:885c2596c964 9:5d007b20cfd0
     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 Qt Mobility Components.
       
     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 #include <QtTest/QtTest>
       
    43 #include <QLocalServer>
       
    44 #include <QLocalSocket>
       
    45 #include <QTimer>
       
    46 #include "../../qbearertestcommon.h"
       
    47 #include "../../../../src/bearer/qnetworkconfigmanager.h"
       
    48 #include "../../../../src/bearer/qnetworksession.h"
       
    49 
       
    50 #if defined(Q_WS_MAEMO_6) || defined(Q_WS_MAEMO_5)
       
    51 #include <stdio.h>
       
    52 #include <iapconf.h>
       
    53 #endif
       
    54 
       
    55 QTM_USE_NAMESPACE
       
    56 
       
    57 // Can be used to configure tests that require manual attention (such as roaming)
       
    58 //#define QNETWORKSESSION_MANUAL_TESTS 1
       
    59 
       
    60 Q_DECLARE_METATYPE(QNetworkConfiguration)
       
    61 Q_DECLARE_METATYPE(QNetworkConfiguration::Type);
       
    62 Q_DECLARE_METATYPE(QNetworkSession::State);
       
    63 Q_DECLARE_METATYPE(QNetworkSession::SessionError);
       
    64 
       
    65 class tst_QNetworkSession : public QObject
       
    66 {
       
    67     Q_OBJECT
       
    68 
       
    69 public slots:
       
    70     void initTestCase();
       
    71     void cleanupTestCase();
       
    72 
       
    73 private slots:
       
    74 
       
    75     void robustnessBombing();
       
    76 
       
    77     void sessionClosing_data();
       
    78     void sessionClosing();
       
    79 
       
    80     void outOfProcessSession();
       
    81     void invalidSession();
       
    82 
       
    83     void repeatedOpenClose_data();
       
    84     void repeatedOpenClose();
       
    85 
       
    86     void sessionStop_data();
       
    87     void sessionStop();
       
    88 
       
    89     void roamingErrorCodes();
       
    90 
       
    91     void sessionProperties_data();
       
    92     void sessionProperties();
       
    93 
       
    94     void userChoiceSession_data();
       
    95     void userChoiceSession();
       
    96 
       
    97     void sessionOpenCloseStop_data();
       
    98     void sessionOpenCloseStop();
       
    99 
       
   100 private:
       
   101     QNetworkConfigurationManager manager;
       
   102     QMap<QString, bool> testsToRun;
       
   103 
       
   104     uint inProcessSessionManagementCount;
       
   105 
       
   106 #if defined(Q_WS_MAEMO_6) || defined(Q_WS_MAEMO_5)
       
   107     Maemo::IAPConf *iapconf;
       
   108     Maemo::IAPConf *iapconf2;
       
   109     Maemo::IAPConf *gprsiap;
       
   110 #define MAX_IAPS 10
       
   111     Maemo::IAPConf *iaps[MAX_IAPS];
       
   112     QProcess *icd_stub;
       
   113 #endif
       
   114 };
       
   115 
       
   116 // Helper functions
       
   117 bool openSession(QNetworkSession *session);
       
   118 bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration = true);
       
   119 void updateConfigurations();
       
   120 void printConfigurations();
       
   121 QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfiguration::Type configType);
       
   122 
       
   123 void tst_QNetworkSession::initTestCase()
       
   124 {
       
   125     qRegisterMetaType<QNetworkSession::State>("QNetworkSession::State");
       
   126     qRegisterMetaType<QNetworkSession::SessionError>("QNetworkSession::SessionError");
       
   127     qRegisterMetaType<QNetworkConfiguration>("QNetworkConfiguration");
       
   128     qRegisterMetaType<QNetworkConfiguration::Type>("QNetworkConfiguration::Type");
       
   129 	
       
   130     // If you wish to skip tests, set value as false. This is often very convinient because tests are so lengthy.
       
   131     // Better way still would be to make this readable from a file.
       
   132     testsToRun["robustnessBombing"] = true;
       
   133     testsToRun["sessionClosing"] = true;
       
   134     testsToRun["outOfProcessSession"] = true;
       
   135     testsToRun["invalidSession"] = true;
       
   136     testsToRun["repeatedOpenClose"] = true;
       
   137     testsToRun["roamingErrorCodes"] = true;
       
   138     testsToRun["sessionStop"] = true;
       
   139     testsToRun["sessionProperties"] = true;
       
   140     testsToRun["userChoiceSession"] = true;
       
   141     testsToRun["sessionOpenCloseStop"] = true;
       
   142 	
       
   143 #if defined(Q_WS_MAEMO_6) || defined(Q_WS_MAEMO_5)
       
   144     iapconf = new Maemo::IAPConf("007");
       
   145     iapconf->setValue("ipv4_type", "AUTO");
       
   146     iapconf->setValue("wlan_wepkey1", "connt");
       
   147     iapconf->setValue("wlan_wepdefkey", 1);
       
   148     iapconf->setValue("wlan_ssid", QByteArray("JamesBond"));
       
   149     iapconf->setValue("name", "James Bond");
       
   150     iapconf->setValue("type", "WLAN_INFRA");
       
   151 
       
   152     gprsiap = new Maemo::IAPConf("This-is-GPRS-IAP");
       
   153     gprsiap->setValue("ask_password", false);
       
   154     gprsiap->setValue("gprs_accesspointname", "internet");
       
   155     gprsiap->setValue("gprs_password", "");
       
   156     gprsiap->setValue("gprs_username", "");
       
   157     gprsiap->setValue("ipv4_autodns", true);
       
   158     gprsiap->setValue("ipv4_type", "AUTO");
       
   159     gprsiap->setValue("sim_imsi", "244070123456789");
       
   160     gprsiap->setValue("name", "MI6");
       
   161     gprsiap->setValue("type", "GPRS");
       
   162 
       
   163     iapconf2 = new Maemo::IAPConf("osso.net");
       
   164     iapconf2->setValue("ipv4_type", "AUTO");
       
   165     iapconf2->setValue("wlan_wepkey1", "osso.net");
       
   166     iapconf2->setValue("wlan_wepdefkey", 1);
       
   167     iapconf2->setValue("wlan_ssid", QByteArray("osso.net"));
       
   168     iapconf2->setValue("name", "osso.net");
       
   169     iapconf2->setValue("type", "WLAN_INFRA");
       
   170     iapconf2->setValue("wlan_security", "WEP");
       
   171 
       
   172     /* Create large number of IAPs in the gconf and see what happens */
       
   173     fflush(stdout);
       
   174     printf("Creating %d IAPS: ", MAX_IAPS);
       
   175     for (int i=0; i<MAX_IAPS; i++) {
       
   176 	QString num = QString().sprintf("%d", i);
       
   177 	QString iap = "iap-" + num;
       
   178 	iaps[i] = new Maemo::IAPConf(iap);
       
   179 	iaps[i]->setValue("name", QString("test-iap-")+num);
       
   180 	iaps[i]->setValue("type", "WLAN_INFRA");
       
   181 	iaps[i]->setValue("wlan_ssid", QString(QString("test-ssid-")+num).toAscii());
       
   182 	iaps[i]->setValue("wlan_security", "WPA_PSK");
       
   183 	iaps[i]->setValue("EAP_wpa_preshared_passphrase", QString("test-passphrase-")+num);
       
   184 	printf(".");
       
   185 	fflush(stdout);
       
   186     }
       
   187     printf("\n");
       
   188     fflush(stdout);
       
   189 
       
   190     icd_stub = new QProcess(this);
       
   191     icd_stub->start("/usr/bin/icd2_stub.py");
       
   192     QTest::qWait(1000);
       
   193 
       
   194     // Add a known network to scan list that icd2 stub returns
       
   195     QProcess dbus_send;
       
   196     // 007 network
       
   197     dbus_send.start("dbus-send --type=method_call --system "
       
   198 		    "--dest=com.nokia.icd2 /com/nokia/icd2 "
       
   199 		    "com.nokia.icd2.testing.add_available_network "
       
   200 		    "string:'' uint32:0 string:'' "
       
   201 		    "string:WLAN_INFRA uint32:5000011 array:byte:48,48,55");
       
   202     dbus_send.waitForFinished();
       
   203 
       
   204     // osso.net network
       
   205     dbus_send.start("dbus-send --type=method_call --system "
       
   206 		    "--dest=com.nokia.icd2 /com/nokia/icd2 "
       
   207 		    "com.nokia.icd2.testing.add_available_network "
       
   208 		    "string:'' uint32:0 string:'' "
       
   209 		    "string:WLAN_INFRA uint32:83886097 array:byte:111,115,115,111,46,110,101,116");
       
   210     dbus_send.waitForFinished();
       
   211 #endif
       
   212 
       
   213     inProcessSessionManagementCount = 0;
       
   214 
       
   215     QSignalSpy spy(&manager, SIGNAL(updateCompleted()));
       
   216     manager.updateConfigurations();
       
   217     QTRY_VERIFY(spy.count() == 1);
       
   218 }
       
   219 
       
   220 void tst_QNetworkSession::cleanupTestCase()
       
   221 {
       
   222     if (!(manager.capabilities() & QNetworkConfigurationManager::SystemSessionSupport) &&
       
   223         (manager.capabilities() & QNetworkConfigurationManager::CanStartAndStopInterfaces) &&
       
   224         inProcessSessionManagementCount == 0) {
       
   225         QFAIL("No usable configurations found to complete all possible "
       
   226               "tests in inProcessSessionManagement()");
       
   227     }
       
   228 
       
   229 #if defined(Q_WS_MAEMO_6) || defined(Q_WS_MAEMO_5)
       
   230     iapconf->clear();
       
   231     delete iapconf;
       
   232     iapconf2->clear();
       
   233     delete iapconf2;
       
   234     gprsiap->clear();
       
   235     delete gprsiap;
       
   236 
       
   237     printf("Deleting %d IAPS : ", MAX_IAPS);
       
   238     for (int i=0; i<MAX_IAPS; i++) {
       
   239 	iaps[i]->clear();
       
   240 	delete iaps[i];
       
   241 	printf(".");
       
   242 	fflush(stdout);
       
   243     }
       
   244     printf("\n");
       
   245     qDebug() << "Deleted" << MAX_IAPS << "IAPs";
       
   246 
       
   247     icd_stub->terminate();
       
   248     icd_stub->waitForFinished();
       
   249 #endif
       
   250 }
       
   251 
       
   252 // Robustness test for calling interfaces in nonsense order / with nonsense parameters
       
   253 void tst_QNetworkSession::robustnessBombing() 
       
   254 {
       
   255     if (!testsToRun["robustnessBombing"]) {
       
   256 	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
       
   257     }
       
   258     
       
   259     QNetworkConfigurationManager mgr;
       
   260     QNetworkSession testSession(mgr.defaultConfiguration());
       
   261     // Should not reset even session is not opened
       
   262     testSession.migrate();
       
   263     testSession.accept();
       
   264     testSession.ignore();
       
   265     testSession.reject();
       
   266 }
       
   267 
       
   268 void tst_QNetworkSession::sessionClosing_data() {
       
   269     QTest::addColumn<QString>("bearerType");
       
   270     QTest::addColumn<QNetworkConfiguration::Type>("configurationType");
       
   271 
       
   272     QTest::newRow("WLAN_IAP") << "WLAN" << QNetworkConfiguration::InternetAccessPoint;
       
   273     QTest::newRow("Cellular_IAP") << "cellular" << QNetworkConfiguration::InternetAccessPoint;
       
   274     QTest::newRow("SNAP") << "bearer_type_not_relevant_with_SNAPs" << QNetworkConfiguration::ServiceNetwork;
       
   275 }
       
   276 
       
   277 // Testcase for closing the session at unexpected times
       
   278 void tst_QNetworkSession::sessionClosing()
       
   279 {
       
   280     if (!testsToRun["sessionClosing"]) {
       
   281         QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);
       
   282     }
       
   283     QFETCH(QString, bearerType);
       
   284     QFETCH(QNetworkConfiguration::Type, configurationType);
       
   285 
       
   286     // Update configurations so that WLANs are discovered too.
       
   287     updateConfigurations();
       
   288 
       
   289     // First check that opening once succeeds and determine if test is doable
       
   290     QNetworkConfiguration config = suitableConfiguration(bearerType, configurationType);
       
   291     if (!config.isValid()) {
       
   292         QSKIP("No suitable configurations, skipping this round of repeated open-close test.", SkipSingle);
       
   293     }
       
   294     qDebug() << "Using following configuration to bomb with close(): " << config.name();
       
   295     QNetworkSession session(config);
       
   296     if (!openSession(&session) ||
       
   297         !closeSession(&session)) {
       
   298         QSKIP("Unable to open/close session, skipping this round of close() bombing.", SkipSingle);
       
   299     }
       
   300 
       
   301     qDebug() << "Closing without issuing open()";
       
   302     session.close();
       
   303 
       
   304     for (int i = 0; i < 25; i++) {
       
   305         qDebug() << "Opening and then waiting: " << i * 100 << " ms before closing.";
       
   306         session.open();
       
   307         QTest::qWait(i*100);
       
   308         session.close();
       
   309         // Sooner or later session must end in Disconnected state,
       
   310         // no matter what the phase was.
       
   311         QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
       
   312         QTest::qWait(200); // Give platform a breathe, otherwise we'll be catching other errors
       
   313     }
       
   314 }
       
   315 
       
   316 void tst_QNetworkSession::invalidSession()
       
   317 { 
       
   318     if (!testsToRun["invalidSession"]) {
       
   319 	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
       
   320     }
       
   321     // 1. Verify that session created with invalid configuration remains in invalid state
       
   322     QNetworkSession session(QNetworkConfiguration(), 0);
       
   323     QVERIFY(!session.isOpen());
       
   324     QVERIFY(session.state() == QNetworkSession::Invalid);
       
   325     
       
   326     // 2. Verify that opening session with invalid configuration both 1) emits invalidconfigurationerror and 2) sets session's state as invalid.
       
   327     QSignalSpy errorSpy(&session, SIGNAL(error(QNetworkSession::SessionError)));
       
   328     session.open();
       
   329     session.waitForOpened(1000); // Should bail out right away
       
   330     QVERIFY(errorSpy.count() == 1); 
       
   331     QNetworkSession::SessionError error =
       
   332            qvariant_cast<QNetworkSession::SessionError> (errorSpy.first().at(0));
       
   333     QVERIFY(error == QNetworkSession::InvalidConfigurationError);
       
   334     QVERIFY(session.state() == QNetworkSession::Invalid);
       
   335     	
       
   336 #ifdef QNETWORKSESSION_MANUAL_TESTS
       
   337 
       
   338     QNetworkConfiguration invalidatedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint);
       
   339     if (invalidatedConfig.isValid()) {
       
   340         // 3. Verify that invalidating a session after its successfully configured works
       
   341         QNetworkSession invalidatedSession(invalidatedConfig);
       
   342         qDebug() << "Delete the WLAN IAP from phone now (waiting 60 seconds): " << invalidatedConfig.name();
       
   343         QTest::qWait(60000);
       
   344         QVERIFY(!invalidatedConfig.isValid());
       
   345         QVERIFY(invalidatedSession.state() == QNetworkSession::Invalid);
       
   346         qDebug() << "Add the WLAN IAP back (waiting 60 seconds): " << invalidatedConfig.name();
       
   347         QTest::qWait(60000);
       
   348     }
       
   349     
       
   350     QNetworkConfiguration definedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint);
       
   351     if (definedConfig.isValid()) {
       
   352         // 4. Verify that opening a session with defined configuration emits error and enters notavailable-state
       
   353         // TODO these timer waits should be changed to waiting appropriate signals, now these wait excessively
       
   354         qDebug() << "Shutdown WLAN IAP (waiting 60 seconds): " << definedConfig.name();
       
   355         QTest::qWait(60000);
       
   356         // Shutting down WLAN should bring back to defined -state.
       
   357         QVERIFY((definedConfig.state() & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined);
       
   358         QNetworkSession definedSession(definedConfig);
       
   359         QSignalSpy errorSpy(&definedSession, SIGNAL(error(QNetworkSession::SessionError)));
       
   360         QNetworkSession::SessionError sessionError;
       
   361         updateConfigurations();
       
   362 
       
   363         definedSession.open();
       
   364 #ifdef Q_OS_SYMBIAN
       
   365         // On symbian, the connection opening is tried even with defined state.
       
   366         qDebug("Waiting for 10 seconds to all signals to propagate.");
       
   367         QTest::qWait(10000);
       
   368 #endif
       
   369         updateConfigurations();
       
   370 
       
   371         QVERIFY(definedConfig.isValid()); // Session remains valid
       
   372         QVERIFY(definedSession.state() == QNetworkSession::NotAvailable); // State is not available because WLAN is not in coverage
       
   373         QVERIFY(!errorSpy.isEmpty()); // Session tells with error about invalidated configuration
       
   374         sessionError = qvariant_cast<QNetworkSession::SessionError> (errorSpy.first().at(0));
       
   375         QVERIFY(sessionError == QNetworkSession::InvalidConfigurationError);
       
   376         qDebug() << "Turn the WLAN IAP back on (waiting 60 seconds): " << definedConfig.name();
       
   377         QTest::qWait(60000);
       
   378         updateConfigurations();        
       
   379         QVERIFY(definedConfig.state() == QNetworkConfiguration::Discovered);
       
   380     }
       
   381 
       
   382 #endif
       
   383 }
       
   384 
       
   385 void tst_QNetworkSession::sessionProperties_data()
       
   386 {
       
   387     QTest::addColumn<QNetworkConfiguration>("configuration");
       
   388 
       
   389     QTest::newRow("invalid configuration") << QNetworkConfiguration();
       
   390 
       
   391     foreach (const QNetworkConfiguration &config, manager.allConfigurations()) {
       
   392         const QString name = config.name().isEmpty() ? QString("<Hidden>") : config.name();
       
   393         QTest::newRow(name.toLocal8Bit().constData()) << config;
       
   394     }
       
   395 }
       
   396 
       
   397 void tst_QNetworkSession::sessionProperties()
       
   398 {
       
   399     if (!testsToRun["sessionProperties"]) {
       
   400 	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
       
   401     }
       
   402     QFETCH(QNetworkConfiguration, configuration);
       
   403     QNetworkSession session(configuration);
       
   404     QVERIFY(session.configuration() == configuration);
       
   405     QStringList validBearerNames = QStringList() << QLatin1String("Unknown")
       
   406                                                  << QLatin1String("Ethernet")
       
   407                                                  << QLatin1String("WLAN")
       
   408                                                  << QLatin1String("2G")
       
   409                                                  << QLatin1String("CDMA2000")
       
   410                                                  << QLatin1String("WCDMA")
       
   411                                                  << QLatin1String("HSPA")
       
   412                                                  << QLatin1String("Bluetooth")
       
   413                                                  << QLatin1String("WiMAX");
       
   414 
       
   415     if (!configuration.isValid()) {
       
   416         QVERIFY(configuration.bearerName().isEmpty());
       
   417     } else {
       
   418         switch (configuration.type())
       
   419         {
       
   420             case QNetworkConfiguration::ServiceNetwork:
       
   421             case QNetworkConfiguration::UserChoice:
       
   422             default:
       
   423                 QVERIFY(configuration.bearerName().isEmpty());
       
   424                 break;
       
   425             case QNetworkConfiguration::InternetAccessPoint:
       
   426                 QVERIFY(validBearerNames.contains(configuration.bearerName()));
       
   427                 break;
       
   428         }
       
   429     }
       
   430 
       
   431     // QNetworkSession::interface() should return an invalid interface unless
       
   432     // session is in the connected state.
       
   433 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
       
   434     // On Symbian emulator, the support for data bearers is limited
       
   435     QCOMPARE(session.state() == QNetworkSession::Connected, session.interface().isValid());
       
   436 #endif
       
   437 
       
   438     if (!configuration.isValid()) {
       
   439         QVERIFY(configuration.state() == QNetworkConfiguration::Undefined &&
       
   440                 session.state() == QNetworkSession::Invalid);
       
   441     } else {
       
   442         switch (configuration.state()) {
       
   443         case QNetworkConfiguration::Undefined:
       
   444             QVERIFY(session.state() == QNetworkSession::NotAvailable);
       
   445             break;
       
   446         case QNetworkConfiguration::Defined:
       
   447             QVERIFY(session.state() == QNetworkSession::NotAvailable);
       
   448             break;
       
   449         case QNetworkConfiguration::Discovered:
       
   450             QVERIFY(session.state() == QNetworkSession::Connecting ||
       
   451                     session.state() == QNetworkSession::Disconnected);
       
   452             break;
       
   453         case QNetworkConfiguration::Active:
       
   454             QVERIFY(session.state() == QNetworkSession::Connected ||
       
   455                     session.state() == QNetworkSession::Closing ||
       
   456                     session.state() == QNetworkSession::Roaming);
       
   457             break;
       
   458         default:
       
   459             QFAIL("Invalid configuration state");
       
   460         };
       
   461     }
       
   462 }
       
   463 
       
   464 void tst_QNetworkSession::repeatedOpenClose_data() {
       
   465     QTest::addColumn<QString>("bearerType");
       
   466     QTest::addColumn<QNetworkConfiguration::Type>("configurationType");
       
   467     QTest::addColumn<int>("repeatTimes");
       
   468 
       
   469     QTest::newRow("WLAN_IAP") << "WLAN" << QNetworkConfiguration::InternetAccessPoint << 3;
       
   470     // QTest::newRow("Cellular_IAP") << "cellular" << QNetworkConfiguration::InternetAccessPoint << 3;
       
   471     // QTest::newRow("SNAP") << "bearer_type_not_relevant_with_SNAPs" << QNetworkConfiguration::ServiceNetwork << 3;
       
   472 }
       
   473 
       
   474 // Tests repeated-open close.
       
   475 void tst_QNetworkSession::repeatedOpenClose() 
       
   476 {	
       
   477     if (!testsToRun["repeatedOpenClose"]) {
       
   478 	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
       
   479     }
       
   480 	
       
   481     QFETCH(QString, bearerType);
       
   482     QFETCH(QNetworkConfiguration::Type, configurationType);
       
   483     QFETCH(int, repeatTimes);
       
   484 
       
   485     // First check that opening once succeeds and determine if repeatable testing is doable
       
   486     QNetworkConfiguration config = suitableConfiguration(bearerType, configurationType);
       
   487     if (!config.isValid()) {
       
   488         QSKIP("No suitable configurations, skipping this round of repeated open-close test.", SkipSingle);
       
   489     }
       
   490     qDebug() << "Using following configuratio to repeatedly open and close: " << config.name();
       
   491     QNetworkSession permanentSession(config);
       
   492     if (!openSession(&permanentSession) || 
       
   493         !closeSession(&permanentSession)) {
       
   494         QSKIP("Unable to open/close session, skipping this round of repeated open-close test.", SkipSingle); 
       
   495     }
       
   496     for (int i = 0; i < repeatTimes; i++) { 
       
   497        qDebug() << "Opening, loop number " << i;
       
   498        QVERIFY(openSession(&permanentSession));
       
   499        qDebug() << "Closing, loop number, then waiting 5 seconds: " << i;
       
   500        QVERIFY(closeSession(&permanentSession));
       
   501        QTest::qWait(5000);
       
   502     }
       
   503 }
       
   504 
       
   505 void tst_QNetworkSession::roamingErrorCodes() 
       
   506 {
       
   507     if (!testsToRun["roamingErrorCodes"]) {
       
   508 	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
       
   509     }    
       
   510 #ifndef Q_OS_SYMBIAN
       
   511     QSKIP("Roaming supported on Symbian.", SkipAll);
       
   512 #else 
       
   513     QNetworkConfiguration wlanIapConfig = suitableConfiguration("WLAN", QNetworkConfiguration::InternetAccessPoint);
       
   514     if (!wlanIapConfig.isValid()) {
       
   515         QSKIP("No WLAN IAP accessible, skipping test.", SkipAll);
       
   516     }
       
   517     // Check that opening and closing two sessions on same config work gracefully:
       
   518     QNetworkSession iapSession(wlanIapConfig);
       
   519     QVERIFY(openSession(&iapSession));
       
   520     QNetworkSession adminIapSession(wlanIapConfig);
       
   521     QVERIFY(openSession(&adminIapSession));
       
   522     QVERIFY(closeSession(&iapSession, false)); // false == not a last session based on the configuration
       
   523     QVERIFY(closeSession(&adminIapSession));
       
   524     
       
   525     // Open configurations again, force close bearer and check that errors are emitted correctly
       
   526     // on the other session
       
   527     QVERIFY(openSession(&iapSession));
       
   528     QVERIFY(openSession(&adminIapSession));
       
   529     QSignalSpy errorSpy(&iapSession, SIGNAL(error(QNetworkSession::SessionError)));   
       
   530     adminIapSession.stop(); // requires NetworkControl capabilities
       
   531     QTRY_VERIFY(!errorSpy.isEmpty()); // wait for error signals
       
   532     QNetworkSession::SessionError error = qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
       
   533     QTest::qWait(2000); // Wait for a moment to all platform signals to propagate
       
   534     QVERIFY(error == QNetworkSession::SessionAbortedError);
       
   535     QVERIFY(iapSession.state() == QNetworkSession::Disconnected);
       
   536     QVERIFY(adminIapSession.state() == QNetworkSession::Disconnected);
       
   537 #endif // Q_OS_SYMBIAN
       
   538 }
       
   539 
       
   540 
       
   541 void tst_QNetworkSession::sessionStop_data() {
       
   542     QTest::addColumn<QString>("bearerType");
       
   543     QTest::addColumn<QNetworkConfiguration::Type>("configurationType");
       
   544 
       
   545     QTest::newRow("SNAP") << "bearer_type_not_relevant_with_SNAPs" << QNetworkConfiguration::ServiceNetwork;
       
   546     QTest::newRow("WLAN_IAP") << "WLAN" << QNetworkConfiguration::InternetAccessPoint;
       
   547     QTest::newRow("Cellular_IAP") << "cellular" << QNetworkConfiguration::InternetAccessPoint;
       
   548 }
       
   549 
       
   550 void tst_QNetworkSession::sessionStop() 
       
   551 {
       
   552     if (!testsToRun["sessionStop"]) {
       
   553 	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
       
   554     }
       
   555 #ifndef Q_OS_SYMBIAN
       
   556     QSKIP("Testcase contains mainly Symbian specific checks, because it is only platform to really support interface (IAP-level) Stop.", SkipAll);
       
   557 #endif 
       
   558     QFETCH(QString, bearerType);
       
   559     QFETCH(QNetworkConfiguration::Type, configurationType);
       
   560     
       
   561     int configWaitdelayInMs = 2000;
       
   562 	
       
   563     updateConfigurations();
       
   564     printConfigurations();
       
   565     
       
   566     QNetworkConfiguration config = suitableConfiguration(bearerType, configurationType);
       
   567     if (!config.isValid()) {
       
   568         QSKIP("No suitable configurations, skipping this round of session stop test.", SkipSingle);
       
   569     }
       
   570     qDebug() << "Using following configuration to open and stop a session: " << config.name();
       
   571 
       
   572     QNetworkSession openedSession(config);
       
   573     QNetworkSession closedSession(config);
       
   574     QNetworkSession innocentSession(config);
       
   575     QNetworkConfigurationManager mgr;
       
   576     
       
   577     QSignalSpy closedSessionOpenedSpy(&closedSession, SIGNAL(opened()));
       
   578     QSignalSpy closedSessionClosedSpy(&closedSession, SIGNAL(closed()));
       
   579     QSignalSpy closedSessionStateChangedSpy(&closedSession, SIGNAL(stateChanged(QNetworkSession::State)));
       
   580     QSignalSpy closedErrorSpy(&closedSession, SIGNAL(error(QNetworkSession::SessionError)));
       
   581     
       
   582     QSignalSpy openedSessionClosedSpy(&openedSession, SIGNAL(closed()));
       
   583     QSignalSpy openedSessionStateChangedSpy(&openedSession, SIGNAL(stateChanged(QNetworkSession::State)));
       
   584     
       
   585     QSignalSpy innocentSessionClosedSpy(&innocentSession, SIGNAL(closed()));
       
   586     QSignalSpy innocentSessionStateChangedSpy(&innocentSession, SIGNAL(stateChanged(QNetworkSession::State)));
       
   587     QSignalSpy innocentErrorSpy(&innocentSession, SIGNAL(error(QNetworkSession::SessionError)));
       
   588     QNetworkSession::SessionError sessionError;
       
   589     
       
   590     // 1. Verify that stopping an opened session works (the simplest usecase).
       
   591     qDebug("----------1. Verify that stopping an opened session works (the simplest usecase)");
       
   592     QSignalSpy configChangeSpy(&mgr, SIGNAL(configurationChanged(QNetworkConfiguration)));
       
   593     QVERIFY(openSession(&openedSession));
       
   594     qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs);
       
   595     // Clear signals caused by opening
       
   596     closedSessionOpenedSpy.clear();
       
   597     closedSessionClosedSpy.clear();
       
   598     closedSessionStateChangedSpy.clear();
       
   599     closedErrorSpy.clear();
       
   600     openedSessionStateChangedSpy.clear();
       
   601     openedSessionClosedSpy.clear();
       
   602     
       
   603     openedSession.stop();
       
   604 
       
   605     qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs);
       
   606     QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
       
   607     
       
   608     // First to closing, then to disconnected
       
   609     QVERIFY(openedSessionStateChangedSpy.count() == 2);
       
   610     QVERIFY(!openedSessionClosedSpy.isEmpty());
       
   611     QVERIFY(openedSession.state() == QNetworkSession::Disconnected);
       
   612     QVERIFY(config.state() != QNetworkConfiguration::Active);
       
   613     
       
   614     // 2. Verify that stopping a session based on non-connected configuration does nothing
       
   615     qDebug("----------2. Verify that stopping a session based on non-connected configuration does nothing");
       
   616     QNetworkSession::State closedSessionOriginalState = closedSession.state();
       
   617     // Clear all possible signals
       
   618     configChangeSpy.clear();
       
   619     closedSessionOpenedSpy.clear();
       
   620     closedSessionClosedSpy.clear();
       
   621     closedSessionStateChangedSpy.clear();
       
   622     closedErrorSpy.clear();
       
   623     
       
   624     closedSession.stop();
       
   625     qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs);
       
   626     QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
       
   627     
       
   628     QVERIFY(closedSessionOpenedSpy.isEmpty());
       
   629     QVERIFY(closedSessionClosedSpy.isEmpty());
       
   630     QVERIFY(closedSessionStateChangedSpy.isEmpty());
       
   631     QVERIFY(closedErrorSpy.isEmpty());
       
   632     QVERIFY(closedSession.state() == closedSessionOriginalState); // State remains
       
   633     
       
   634     // 3. Check that stopping a opened session affects also other opened session based on the same configuration.
       
   635     if (config.type() == QNetworkConfiguration::InternetAccessPoint) {
       
   636         qDebug("----------3. Check that stopping a opened session affects also other opened session based on the same configuration.");
       
   637 	
       
   638         QVERIFY(openSession(&openedSession));
       
   639         QVERIFY(openSession(&innocentSession));
       
   640 	    
       
   641         configChangeSpy.clear();
       
   642         innocentSessionClosedSpy.clear();
       
   643         innocentSessionStateChangedSpy.clear();
       
   644         innocentErrorSpy.clear();
       
   645         
       
   646         openedSession.stop();    
       
   647         qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs);
       
   648         QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
       
   649 	QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
       
   650 	    
       
   651         QVERIFY(!innocentSessionClosedSpy.isEmpty());
       
   652         QVERIFY(!innocentSessionStateChangedSpy.isEmpty());
       
   653         QVERIFY(!innocentErrorSpy.isEmpty());
       
   654         QVERIFY(innocentSession.state() == QNetworkSession::Disconnected);
       
   655         QVERIFY(openedSession.state() == QNetworkSession::Disconnected);
       
   656         sessionError = qvariant_cast<QNetworkSession::SessionError>(innocentErrorSpy.first().at(0));
       
   657         QVERIFY(sessionError == QNetworkSession::SessionAbortedError);
       
   658 
       
   659         innocentSessionClosedSpy.clear();
       
   660         innocentSessionStateChangedSpy.clear();
       
   661         innocentErrorSpy.clear();
       
   662     } else {
       
   663         qDebug("----------3. Skip for SNAP configuration.");
       
   664     }
       
   665     // 4. Check that stopping a non-opened session stops the other session based on the 
       
   666     // same configuration if configuration is IAP. Stopping closed SNAP session has no impact on other opened SNAP session.
       
   667     if (config.type() == QNetworkConfiguration::ServiceNetwork) {
       
   668         qDebug("----------4. Skip for SNAP configuration.");
       
   669     } else if (config.type() == QNetworkConfiguration::InternetAccessPoint) {
       
   670         qDebug("----------4.   Check that stopping a non-opened session stops the other session based on the same configuration");
       
   671 	qDebug("----------4.1 Opening innocent session");
       
   672         QVERIFY(openSession(&innocentSession));    
       
   673         qDebug("Waiting for %d ms after open to make sure all platform indications are propagated", configWaitdelayInMs);
       
   674         QTest::qWait(configWaitdelayInMs);
       
   675         qDebug("----------4.2 Calling closedSession.stop()");
       
   676         closedSession.stop();
       
   677         qDebug("Waiting for %d ms to get all configurationChange signals from platform..", configWaitdelayInMs);
       
   678         QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
       
   679     
       
   680 	    QTest::qWait(configWaitdelayInMs);
       
   681 	    QTest::qWait(configWaitdelayInMs);
       
   682 	    
       
   683         QVERIFY(!innocentSessionClosedSpy.isEmpty());
       
   684         QVERIFY(!innocentSessionStateChangedSpy.isEmpty());
       
   685         QVERIFY(!innocentErrorSpy.isEmpty());
       
   686         QVERIFY(innocentSession.state() == QNetworkSession::Disconnected);
       
   687         QVERIFY(closedSession.state() == QNetworkSession::Disconnected);
       
   688         sessionError = qvariant_cast<QNetworkSession::SessionError>(innocentErrorSpy.first().at(0));
       
   689         QVERIFY(sessionError == QNetworkSession::SessionAbortedError);
       
   690         QVERIFY(config.state() == QNetworkConfiguration::Discovered);
       
   691     }
       
   692     
       
   693     // 5. Sanity check that stopping invalid session does not crash
       
   694     qDebug("----------5. Sanity check that stopping invalid session does not crash");
       
   695     QNetworkSession invalidSession(QNetworkConfiguration(), 0);
       
   696     QVERIFY(invalidSession.state() == QNetworkSession::Invalid);
       
   697     invalidSession.stop();
       
   698     QVERIFY(invalidSession.state() == QNetworkSession::Invalid);
       
   699 }
       
   700 
       
   701 void tst_QNetworkSession::userChoiceSession_data()
       
   702 {
       
   703     QTest::addColumn<QNetworkConfiguration>("configuration");
       
   704 
       
   705     QNetworkConfiguration config = manager.defaultConfiguration();
       
   706     if (config.type() == QNetworkConfiguration::UserChoice)
       
   707         QTest::newRow("UserChoice") << config;
       
   708     else
       
   709         QSKIP("Default configuration is not a UserChoice configuration.", SkipAll);
       
   710 }
       
   711 
       
   712 void tst_QNetworkSession::userChoiceSession()
       
   713 {
       
   714     if (!testsToRun["userChoiceSession"]) {
       
   715 	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
       
   716     }
       
   717     QFETCH(QNetworkConfiguration, configuration);
       
   718 
       
   719     QVERIFY(configuration.type() == QNetworkConfiguration::UserChoice);
       
   720 
       
   721     QNetworkSession session(configuration);
       
   722 
       
   723     // Check that configuration was really set
       
   724     QVERIFY(session.configuration() == configuration);
       
   725 
       
   726     QVERIFY(!session.isOpen());
       
   727 
       
   728     // Check that session is not active
       
   729     QVERIFY(session.sessionProperty("ActiveConfiguration").toString().isEmpty());
       
   730 
       
   731     // The remaining tests require the session to be not NotAvailable.
       
   732     if (session.state() == QNetworkSession::NotAvailable)
       
   733         QSKIP("Network is not available.", SkipSingle);
       
   734 
       
   735     QSignalSpy sessionOpenedSpy(&session, SIGNAL(opened()));
       
   736     QSignalSpy sessionClosedSpy(&session, SIGNAL(closed()));
       
   737     QSignalSpy stateChangedSpy(&session, SIGNAL(stateChanged(QNetworkSession::State)));
       
   738     QSignalSpy errorSpy(&session, SIGNAL(error(QNetworkSession::SessionError)));
       
   739 
       
   740     // Test opening the session.
       
   741     {
       
   742         bool expectStateChange = session.state() != QNetworkSession::Connected;
       
   743 
       
   744         session.open();
       
   745 
       
   746 #if defined(Q_OS_SYMBIAN)
       
   747         // Opening & closing multiple connections in a row sometimes
       
   748         // results hanging of connection opening on Symbian devices
       
   749         // => If first open fails, wait a moment and try again.
       
   750         if (!session.waitForOpened()) {
       
   751             qDebug("**** Session open Timeout - Wait 5 seconds and try once again ****");        
       
   752             session.close();
       
   753             QTest::qWait(5000); // Wait a while before trying to open session again
       
   754             session.open();
       
   755             session.waitForOpened();
       
   756         }
       
   757 #else        
       
   758         session.waitForOpened();
       
   759 #endif        
       
   760 
       
   761         if (session.isOpen())
       
   762             QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty());
       
   763         if (!errorSpy.isEmpty()) {
       
   764             QNetworkSession::SessionError error =
       
   765                 qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
       
   766             if (error == QNetworkSession::OperationNotSupportedError) {
       
   767                 // The session needed to bring up the interface,
       
   768                 // but the operation is not supported.
       
   769                 QSKIP("Configuration does not support open().", SkipSingle);
       
   770             } else if (error == QNetworkSession::InvalidConfigurationError) {
       
   771                 // The session needed to bring up the interface, but it is not possible for the
       
   772                 // specified configuration.
       
   773                 if ((session.configuration().state() & QNetworkConfiguration::Discovered) ==
       
   774                     QNetworkConfiguration::Discovered) {
       
   775                     QFAIL("Failed to open session for Discovered configuration.");
       
   776                 } else {
       
   777                     QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle);
       
   778                 }
       
   779             } else if (error == QNetworkSession::UnknownSessionError) {
       
   780                     QSKIP("Unknown session error.", SkipSingle);
       
   781             } else {
       
   782                 QFAIL("Error opening session.");
       
   783             }
       
   784         } else if (!sessionOpenedSpy.isEmpty()) {
       
   785             QCOMPARE(sessionOpenedSpy.count(), 1);
       
   786             QVERIFY(sessionClosedSpy.isEmpty());
       
   787             QVERIFY(errorSpy.isEmpty());
       
   788 
       
   789             if (expectStateChange)
       
   790                 QTRY_VERIFY(!stateChangedSpy.isEmpty());
       
   791 
       
   792             QVERIFY(session.state() == QNetworkSession::Connected);
       
   793 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
       
   794             // On Symbian emulator, the support for data bearers is limited
       
   795             QVERIFY(session.interface().isValid());
       
   796 #endif
       
   797 
       
   798             const QString userChoiceIdentifier =
       
   799                 session.sessionProperty("UserChoiceConfiguration").toString();
       
   800 
       
   801             QVERIFY(!userChoiceIdentifier.isEmpty());
       
   802             QVERIFY(userChoiceIdentifier != configuration.identifier());
       
   803 
       
   804             QNetworkConfiguration userChoiceConfiguration =
       
   805                 manager.configurationFromIdentifier(userChoiceIdentifier);
       
   806 
       
   807             QVERIFY(userChoiceConfiguration.isValid());
       
   808             QVERIFY(userChoiceConfiguration.type() != QNetworkConfiguration::UserChoice);
       
   809 
       
   810             const QString testIdentifier("abc");
       
   811             //resetting UserChoiceConfiguration is ignored (read only property)
       
   812             session.setSessionProperty("UserChoiceConfiguration", testIdentifier);
       
   813             QVERIFY(session.sessionProperty("UserChoiceConfiguration").toString() != testIdentifier);
       
   814 
       
   815             const QString activeIdentifier =
       
   816                 session.sessionProperty("ActiveConfiguration").toString();
       
   817 
       
   818             QVERIFY(!activeIdentifier.isEmpty());
       
   819             QVERIFY(activeIdentifier != configuration.identifier());
       
   820 
       
   821             QNetworkConfiguration activeConfiguration =
       
   822                 manager.configurationFromIdentifier(activeIdentifier);
       
   823 
       
   824             QVERIFY(activeConfiguration.isValid());
       
   825             QVERIFY(activeConfiguration.type() == QNetworkConfiguration::InternetAccessPoint);
       
   826             
       
   827             //resetting ActiveConfiguration is ignored (read only property)
       
   828             session.setSessionProperty("ActiveConfiguration", testIdentifier);
       
   829             QVERIFY(session.sessionProperty("ActiveConfiguration").toString() != testIdentifier);
       
   830 
       
   831             if (userChoiceConfiguration.type() == QNetworkConfiguration::InternetAccessPoint) {
       
   832                 QVERIFY(userChoiceConfiguration == activeConfiguration);
       
   833             } else {
       
   834                 QVERIFY(userChoiceConfiguration.type() == QNetworkConfiguration::ServiceNetwork);
       
   835                 QVERIFY(userChoiceConfiguration.children().contains(activeConfiguration));
       
   836             }
       
   837         } else {
       
   838             QFAIL("Timeout waiting for session to open.");
       
   839         }
       
   840     }
       
   841 }
       
   842 
       
   843 void tst_QNetworkSession::sessionOpenCloseStop_data()
       
   844 {
       
   845     QTest::addColumn<QNetworkConfiguration>("configuration");
       
   846     QTest::addColumn<bool>("forceSessionStop");
       
   847 
       
   848     foreach (const QNetworkConfiguration &config, manager.allConfigurations()) {
       
   849         const QString name = config.name().isEmpty() ? QString("<Hidden>") : config.name();
       
   850         QTest::newRow((name + QLatin1String(" close")).toLocal8Bit().constData())
       
   851             << config << false;
       
   852         QTest::newRow((name + QLatin1String(" stop")).toLocal8Bit().constData())
       
   853             << config << true;
       
   854     }
       
   855 }
       
   856 
       
   857 void tst_QNetworkSession::sessionOpenCloseStop()
       
   858 {
       
   859     if (!testsToRun["sessionOpenCloseStop"]) {
       
   860 	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
       
   861     }
       
   862     QFETCH(QNetworkConfiguration, configuration);
       
   863     QFETCH(bool, forceSessionStop);
       
   864 
       
   865     QNetworkSession session(configuration);
       
   866 
       
   867     // Test initial state of the session.
       
   868     {
       
   869         QVERIFY(session.configuration() == configuration);
       
   870         QVERIFY(!session.isOpen());
       
   871         // session may be invalid if configuration is removed between when
       
   872         // sessionOpenCloseStop_data() is called and here.
       
   873         QVERIFY((configuration.isValid() && (session.state() != QNetworkSession::Invalid)) ||
       
   874                 (!configuration.isValid() && (session.state() == QNetworkSession::Invalid)));
       
   875         QVERIFY(session.error() == QNetworkSession::UnknownSessionError);
       
   876     }
       
   877 
       
   878     // The remaining tests require the session to be not NotAvailable.
       
   879     if (session.state() == QNetworkSession::NotAvailable)
       
   880         QSKIP("Network is not available.", SkipSingle);
       
   881         
       
   882     QSignalSpy sessionOpenedSpy(&session, SIGNAL(opened()));
       
   883     QSignalSpy sessionClosedSpy(&session, SIGNAL(closed()));
       
   884     QSignalSpy stateChangedSpy(&session, SIGNAL(stateChanged(QNetworkSession::State)));
       
   885     QSignalSpy errorSpy(&session, SIGNAL(error(QNetworkSession::SessionError)));
       
   886 
       
   887     // Test opening the session.
       
   888     {
       
   889         QNetworkSession::State previousState = session.state();
       
   890         bool expectStateChange = previousState != QNetworkSession::Connected;
       
   891 
       
   892         session.open();
       
   893 
       
   894 #if defined(Q_OS_SYMBIAN)
       
   895         // Opening & closing multiple connections in a row sometimes
       
   896         // results hanging of connection opening on Symbian devices
       
   897         // => If first open fails, wait a moment and try again.
       
   898         if (!session.waitForOpened()) {
       
   899             qDebug("**** Session open Timeout - Wait 5 seconds and try once again ****");        
       
   900             session.close();
       
   901             QTest::qWait(5000); // Wait a while before trying to open session again
       
   902             session.open();
       
   903             session.waitForOpened();
       
   904         }
       
   905 #else        
       
   906         session.waitForOpened();
       
   907 #endif        
       
   908 
       
   909          // Wait until the configuration is uptodate as well, it may be signaled 'connected' 
       
   910          // bit later than the session
       
   911          QTRY_VERIFY(configuration.state() == QNetworkConfiguration::Active);
       
   912 
       
   913         if (session.isOpen())
       
   914             QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty());
       
   915         if (!errorSpy.isEmpty()) {
       
   916         
       
   917             QNetworkSession::SessionError error =
       
   918                 qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
       
   919 
       
   920             QVERIFY(session.state() == previousState);
       
   921 
       
   922             if (error == QNetworkSession::OperationNotSupportedError) {
       
   923                 // The session needed to bring up the interface,
       
   924                 // but the operation is not supported.
       
   925                 QSKIP("Configuration does not support open().", SkipSingle);
       
   926             } else if (error == QNetworkSession::InvalidConfigurationError) {
       
   927                 // The session needed to bring up the interface, but it is not possible for the
       
   928                 // specified configuration.
       
   929                 if ((session.configuration().state() & QNetworkConfiguration::Discovered) ==
       
   930                     QNetworkConfiguration::Discovered) {
       
   931                     QFAIL("Failed to open session for Discovered configuration.");
       
   932                 } else {
       
   933                     QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle);
       
   934                 }
       
   935             } else if (error == QNetworkSession::UnknownSessionError) {
       
   936                     QSKIP("Unknown Session error.", SkipSingle);
       
   937             } else {
       
   938                 QFAIL("Error opening session.");
       
   939             }
       
   940         } else if (!sessionOpenedSpy.isEmpty()) {
       
   941             QCOMPARE(sessionOpenedSpy.count(), 1);
       
   942             QVERIFY(sessionClosedSpy.isEmpty());
       
   943             QVERIFY(errorSpy.isEmpty());
       
   944 
       
   945             if (expectStateChange) {
       
   946                 QTRY_VERIFY(stateChangedSpy.count() >= 2);
       
   947 
       
   948                 QNetworkSession::State state =
       
   949                     qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(0).at(0));
       
   950                 QVERIFY(state == QNetworkSession::Connecting);
       
   951 
       
   952                 state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(1).at(0));
       
   953                 QVERIFY(state == QNetworkSession::Connected);
       
   954             }
       
   955 
       
   956             QVERIFY(session.state() == QNetworkSession::Connected);
       
   957 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
       
   958             // On Symbian emulator, the support for data bearers is limited
       
   959             QVERIFY(session.interface().isValid());
       
   960 #endif
       
   961         } else {
       
   962             QFAIL("Timeout waiting for session to open.");
       
   963         }
       
   964     }
       
   965 
       
   966     sessionOpenedSpy.clear();
       
   967     sessionClosedSpy.clear();
       
   968     stateChangedSpy.clear();
       
   969     errorSpy.clear();
       
   970 
       
   971     QNetworkSession session2(configuration);
       
   972 
       
   973     QSignalSpy sessionOpenedSpy2(&session2, SIGNAL(opened()));
       
   974     QSignalSpy sessionClosedSpy2(&session2, SIGNAL(closed()));
       
   975     QSignalSpy stateChangedSpy2(&session2, SIGNAL(stateChanged(QNetworkSession::State)));
       
   976     QSignalSpy errorSpy2(&session2, SIGNAL(error(QNetworkSession::SessionError)));
       
   977 
       
   978     // Test opening a second session.
       
   979     {
       
   980         QVERIFY(session2.configuration() == configuration);
       
   981         QVERIFY(!session2.isOpen());
       
   982         QVERIFY(session2.state() == QNetworkSession::Connected);
       
   983         QVERIFY(session.error() == QNetworkSession::UnknownSessionError);
       
   984 
       
   985         session2.open();
       
   986 	    
       
   987         QTRY_VERIFY(!sessionOpenedSpy2.isEmpty() || !errorSpy2.isEmpty());
       
   988 
       
   989         if (errorSpy2.isEmpty()) {
       
   990             QVERIFY(session2.isOpen());
       
   991             QVERIFY(session2.state() == QNetworkSession::Connected);
       
   992         }
       
   993         QVERIFY(session.isOpen());
       
   994         QVERIFY(session.state() == QNetworkSession::Connected);
       
   995 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
       
   996         // On Symbian emulator, the support for data bearers is limited
       
   997         QVERIFY(session.interface().isValid());
       
   998 #endif
       
   999         if (errorSpy2.isEmpty()) {
       
  1000             QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress());
       
  1001             QCOMPARE(session.interface().index(), session2.interface().index());
       
  1002         }
       
  1003     }
       
  1004 
       
  1005     sessionOpenedSpy2.clear();
       
  1006 
       
  1007     if (forceSessionStop && session2.isOpen()) {
       
  1008         // Test forcing the second session to stop the interface.
       
  1009         QNetworkSession::State previousState = session.state();
       
  1010 #ifdef Q_CC_NOKIAX86
       
  1011         // For S60 emulator builds: RConnection::Stop does not work on all Emulators
       
  1012         bool expectStateChange = false;
       
  1013 #else
       
  1014         bool expectStateChange = previousState != QNetworkSession::Disconnected;
       
  1015 #endif
       
  1016         session2.stop();
       
  1017 
       
  1018         // QNetworkSession::stop() must result either closed() signal
       
  1019         // or error() signal
       
  1020         QTRY_VERIFY(!sessionClosedSpy2.isEmpty() || !errorSpy2.isEmpty());
       
  1021         QVERIFY(!session2.isOpen());
       
  1022 
       
  1023         if (!errorSpy2.isEmpty()) {
       
  1024             // QNetworkSession::stop() resulted error() signal for session2
       
  1025             // => also session should emit error() signal
       
  1026             QTRY_VERIFY(!errorSpy.isEmpty());
       
  1027 
       
  1028             // check for SessionAbortedError
       
  1029             QNetworkSession::SessionError error =
       
  1030                 qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
       
  1031             QNetworkSession::SessionError error2 =
       
  1032                 qvariant_cast<QNetworkSession::SessionError>(errorSpy2.first().at(0));
       
  1033 
       
  1034             QVERIFY(error == QNetworkSession::SessionAbortedError);
       
  1035             QVERIFY(error2 == QNetworkSession::SessionAbortedError);
       
  1036 
       
  1037             QCOMPARE(errorSpy.count(), 1);
       
  1038             QCOMPARE(errorSpy2.count(), 1);
       
  1039 
       
  1040             errorSpy.clear();
       
  1041             errorSpy2.clear();
       
  1042         }
       
  1043 
       
  1044         QVERIFY(errorSpy.isEmpty());
       
  1045         QVERIFY(errorSpy2.isEmpty());
       
  1046         
       
  1047         // Wait for Disconnected state 
       
  1048         QTRY_NOOP(session2.state() == QNetworkSession::Disconnected);
       
  1049 	
       
  1050         if (expectStateChange)
       
  1051             QTRY_VERIFY(stateChangedSpy2.count() >= 1 || !errorSpy2.isEmpty());
       
  1052 
       
  1053         if (!errorSpy2.isEmpty()) {
       
  1054             QVERIFY(session2.state() == previousState);
       
  1055             QVERIFY(session.state() == previousState);
       
  1056 
       
  1057             QNetworkSession::SessionError error =
       
  1058                 qvariant_cast<QNetworkSession::SessionError>(errorSpy2.first().at(0));
       
  1059             if (error == QNetworkSession::OperationNotSupportedError) {
       
  1060                 // The session needed to bring down the interface,
       
  1061                 // but the operation is not supported.
       
  1062                 QSKIP("Configuration does not support stop().", SkipSingle);
       
  1063             } else if (error == QNetworkSession::InvalidConfigurationError) {
       
  1064                 // The session needed to bring down the interface, but it is not possible for the
       
  1065                 // specified configuration.
       
  1066                 if ((session.configuration().state() & QNetworkConfiguration::Discovered) ==
       
  1067                     QNetworkConfiguration::Discovered) {
       
  1068                     QFAIL("Failed to stop session for Discovered configuration.");
       
  1069                 } else {
       
  1070                     QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle);
       
  1071                 }
       
  1072             } else {
       
  1073                 QFAIL("Error stopping session.");
       
  1074             }
       
  1075         } else if (!sessionClosedSpy2.isEmpty()) {
       
  1076             if (expectStateChange) {
       
  1077                 if (configuration.type() == QNetworkConfiguration::ServiceNetwork) {
       
  1078                     bool roamedSuccessfully = false;
       
  1079 
       
  1080                     QNetworkSession::State state;
       
  1081                     if (stateChangedSpy2.count() == 4) {
       
  1082                         state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(0).at(0));
       
  1083                         QVERIFY(state == QNetworkSession::Connecting);
       
  1084 
       
  1085                         state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(1).at(0));
       
  1086                         QVERIFY(state == QNetworkSession::Connected);
       
  1087 
       
  1088                         state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(2).at(0));
       
  1089                         QVERIFY(state == QNetworkSession::Closing);
       
  1090 
       
  1091                         state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(3).at(0));
       
  1092                         QVERIFY(state == QNetworkSession::Disconnected);
       
  1093                     } else if (stateChangedSpy2.count() == 2) {
       
  1094                         state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(0).at(0));
       
  1095                         QVERIFY(state == QNetworkSession::Closing);
       
  1096 
       
  1097                         state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(1).at(0));
       
  1098                         QVERIFY(state == QNetworkSession::Disconnected);
       
  1099                     } else {
       
  1100                         QFAIL("Unexpected amount of state changes when roaming.");
       
  1101                     }
       
  1102 			
       
  1103                     QTRY_VERIFY(session.state() == QNetworkSession::Roaming ||
       
  1104                                 session.state() == QNetworkSession::Connected ||
       
  1105                                 session.state() == QNetworkSession::Disconnected);
       
  1106                     
       
  1107                     QTRY_VERIFY(stateChangedSpy.count() > 0);
       
  1108                     state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(stateChangedSpy.count() - 1).at(0));                    
       
  1109                     
       
  1110                     for (int i = 0; i < stateChangedSpy.count(); i++) {
       
  1111                         QNetworkSession::State state_temp =
       
  1112                                 qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(i).at(0));
       
  1113                         // Extra debug because a fragile point in testcase because statuses vary.
       
  1114                         qDebug() << "------- Statechange spy at: " << i << " is " << state_temp;
       
  1115                     }
       
  1116 
       
  1117                     if (state == QNetworkSession::Roaming) {
       
  1118                         QTRY_VERIFY(session.state() == QNetworkSession::Connected);
       
  1119                         QTRY_VERIFY(session2.state() == QNetworkSession::Connected);
       
  1120                         roamedSuccessfully = true;
       
  1121                     } else if (state == QNetworkSession::Closing) {
       
  1122                         QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected);
       
  1123                         QTRY_VERIFY(session.state() == QNetworkSession::Connected || 
       
  1124                         	session.state() == QNetworkSession::Disconnected);
       
  1125                         roamedSuccessfully = false;
       
  1126                     } else if (state == QNetworkSession::Disconnected) {
       
  1127                         QTRY_VERIFY(!errorSpy.isEmpty());
       
  1128                         QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected);
       
  1129                   	} else if (state == QNetworkSession::Connected) {
       
  1130                         QTRY_VERIFY(errorSpy.isEmpty());
       
  1131 
       
  1132                         if (stateChangedSpy.count() > 1) {
       
  1133                             state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(stateChangedSpy.count() - 2).at(0));                        
       
  1134                             QVERIFY(state == QNetworkSession::Roaming);
       
  1135                         }
       
  1136                         roamedSuccessfully = true;
       
  1137                     }
       
  1138 
       
  1139                     if (roamedSuccessfully) {
       
  1140                         // Verify that you can open session based on the disconnected configuration
       
  1141                         QString configId = session.sessionProperty("ActiveConfiguration").toString();
       
  1142                         QNetworkConfiguration config = manager.configurationFromIdentifier(configId);
       
  1143                         QNetworkSession session3(config);
       
  1144                         QSignalSpy errorSpy3(&session3, SIGNAL(error(QNetworkSession::SessionError)));
       
  1145                         QSignalSpy sessionOpenedSpy3(&session3, SIGNAL(opened()));
       
  1146                         session3.open();
       
  1147                         session3.waitForOpened();
       
  1148                         QTest::qWait(1000); // Wait awhile to get all signals from platform
       
  1149                         if (session.isOpen())
       
  1150                             QVERIFY(!sessionOpenedSpy3.isEmpty() || !errorSpy3.isEmpty());
       
  1151                         session.stop();
       
  1152                         QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
       
  1153                     }
       
  1154 #ifndef Q_CC_NOKIAX86
       
  1155                     if (!roamedSuccessfully)
       
  1156                         QVERIFY(!errorSpy.isEmpty());
       
  1157 #endif
       
  1158                 } else {
       
  1159                     QTest::qWait(2000); // Wait awhile to get all signals from platform
       
  1160         
       
  1161                     if (stateChangedSpy2.count() == 2)  {
       
  1162                         QNetworkSession::State state =
       
  1163                             qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(0).at(0));
       
  1164                         QVERIFY(state == QNetworkSession::Closing);
       
  1165                         state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(1).at(0));
       
  1166                         QVERIFY(state == QNetworkSession::Disconnected);
       
  1167                     } else {
       
  1168                         QVERIFY(stateChangedSpy2.count() >= 1);
       
  1169 
       
  1170                         for (int i = 0; i < stateChangedSpy2.count(); i++) {
       
  1171                             QNetworkSession::State state_temp =
       
  1172                                     qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(i).at(0));
       
  1173                             // Extra debug because a fragile point in testcase.
       
  1174                             qDebug() << "+++++ Statechange spy at: " << i << " is " << state_temp;
       
  1175                         }
       
  1176 
       
  1177                         QNetworkSession::State state =
       
  1178                                 qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(stateChangedSpy2.count() - 1).at(0));
       
  1179                          // Symbian version dependant.
       
  1180                         QVERIFY(state == QNetworkSession::Disconnected);	
       
  1181                     }
       
  1182                 }
       
  1183 
       
  1184                 QTRY_VERIFY(!sessionClosedSpy.isEmpty());
       
  1185                 QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
       
  1186             }
       
  1187 
       
  1188             QVERIFY(errorSpy2.isEmpty());
       
  1189 
       
  1190             ++inProcessSessionManagementCount;
       
  1191         } else {
       
  1192             QFAIL("Timeout waiting for session to stop.");
       
  1193         }
       
  1194 
       
  1195 #ifndef Q_CC_NOKIAX86
       
  1196         QVERIFY(!sessionClosedSpy.isEmpty());
       
  1197 #endif
       
  1198         QVERIFY(!sessionClosedSpy2.isEmpty());
       
  1199 
       
  1200 #ifndef Q_CC_NOKIAX86
       
  1201         QVERIFY(!session.isOpen());
       
  1202 #endif
       
  1203         QVERIFY(!session2.isOpen());
       
  1204     } else if (session2.isOpen()) {
       
  1205         // Test closing the second session.
       
  1206         {
       
  1207             int stateChangedCountBeforeClose = stateChangedSpy2.count();
       
  1208             session2.close();
       
  1209 
       
  1210             QTRY_VERIFY(!sessionClosedSpy2.isEmpty());
       
  1211 #ifndef Q_CC_NOKIAX86        
       
  1212             QVERIFY(stateChangedSpy2.count() == stateChangedCountBeforeClose);
       
  1213 #endif        
       
  1214 
       
  1215             QVERIFY(sessionClosedSpy.isEmpty());
       
  1216 
       
  1217             QVERIFY(session.isOpen());
       
  1218             QVERIFY(!session2.isOpen());
       
  1219             QVERIFY(session.state() == QNetworkSession::Connected);
       
  1220             QVERIFY(session2.state() == QNetworkSession::Connected);
       
  1221 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
       
  1222             // On Symbian emulator, the support for data bearers is limited
       
  1223             QVERIFY(session.interface().isValid());
       
  1224 #endif
       
  1225             QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress());
       
  1226             QCOMPARE(session.interface().index(), session2.interface().index());
       
  1227         }
       
  1228 
       
  1229         sessionClosedSpy2.clear();
       
  1230 
       
  1231         // Test closing the first session.
       
  1232         {
       
  1233 #ifdef Q_CC_NOKIAX86
       
  1234             // For S60 emulator builds: RConnection::Close does not actually
       
  1235             //                          close network connection on all Emulators
       
  1236             bool expectStateChange = false;
       
  1237 #else
       
  1238             bool expectStateChange = session.state() != QNetworkSession::Disconnected &&
       
  1239                                      manager.capabilities() & QNetworkConfigurationManager::SystemSessionSupport;
       
  1240 #endif
       
  1241 
       
  1242             session.close();
       
  1243 
       
  1244             QTRY_VERIFY(!sessionClosedSpy.isEmpty() || !errorSpy.isEmpty());
       
  1245 
       
  1246             QVERIFY(!session.isOpen());
       
  1247 
       
  1248             if (expectStateChange)
       
  1249                 QTRY_VERIFY(!stateChangedSpy.isEmpty() || !errorSpy.isEmpty());
       
  1250 
       
  1251             if (!errorSpy.isEmpty()) {
       
  1252                 QNetworkSession::SessionError error =
       
  1253                     qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
       
  1254                 if (error == QNetworkSession::OperationNotSupportedError) {
       
  1255                     // The session needed to bring down the interface,
       
  1256                     // but the operation is not supported.
       
  1257                     QSKIP("Configuration does not support close().", SkipSingle);
       
  1258                 } else if (error == QNetworkSession::InvalidConfigurationError) {
       
  1259                     // The session needed to bring down the interface, but it is not possible for the
       
  1260                     // specified configuration.
       
  1261                     if ((session.configuration().state() & QNetworkConfiguration::Discovered) ==
       
  1262                         QNetworkConfiguration::Discovered) {
       
  1263                         QFAIL("Failed to close session for Discovered configuration.");
       
  1264                     } else {
       
  1265                         QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle);
       
  1266                     }
       
  1267                 } else {
       
  1268                     QFAIL("Error closing session.");
       
  1269                 }
       
  1270             } else if (!sessionClosedSpy.isEmpty()) {
       
  1271                 QVERIFY(sessionOpenedSpy.isEmpty());
       
  1272                 QCOMPARE(sessionClosedSpy.count(), 1);
       
  1273                 if (expectStateChange)
       
  1274                     QVERIFY(!stateChangedSpy.isEmpty());
       
  1275                 QVERIFY(errorSpy.isEmpty());
       
  1276 
       
  1277                 if (expectStateChange)
       
  1278                     QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
       
  1279 
       
  1280                 ++inProcessSessionManagementCount;
       
  1281             } else {
       
  1282                 QFAIL("Timeout waiting for session to close.");
       
  1283             }
       
  1284         }
       
  1285     }
       
  1286 }
       
  1287 
       
  1288 QDebug operator<<(QDebug debug, const QList<QNetworkConfiguration> &list)
       
  1289 {
       
  1290     debug.nospace() << "( ";
       
  1291     foreach (const QNetworkConfiguration &config, list)
       
  1292         debug.nospace() << config.identifier() << ", ";
       
  1293     debug.nospace() << ")\n";
       
  1294     return debug;
       
  1295 }
       
  1296 
       
  1297 // Note: outOfProcessSession requires that at least one configuration is
       
  1298 // at Discovered -state.
       
  1299 void tst_QNetworkSession::outOfProcessSession()
       
  1300 {
       
  1301     if (!testsToRun["outOfProcessSession"]) {
       
  1302 	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
       
  1303     }
       
  1304 #if defined(Q_OS_SYMBIAN) && defined(__WINS__)
       
  1305     QSKIP("Symbian emulator does not support two [QR]PRocesses linking a dll (QtBearer.dll) with global writeable static data.", SkipAll);
       
  1306 #endif
       
  1307 	updateConfigurations();	   
       
  1308 	QTest::qWait(2000);
       
  1309 	
       
  1310     QNetworkConfigurationManager manager;
       
  1311     // Create a QNetworkConfigurationManager to detect configuration changes made in Lackey. This
       
  1312     // is actually the essence of this testcase - to check that platform mediates/reflects changes
       
  1313     // regardless of process boundaries. The interprocess communication is more like a way to get
       
  1314     // this test-case act correctly and timely.
       
  1315     QList<QNetworkConfiguration> before = manager.allConfigurations(QNetworkConfiguration::Active);
       
  1316     QSignalSpy spy(&manager, SIGNAL(configurationChanged(QNetworkConfiguration)));
       
  1317 
       
  1318     // Cannot read/write to processes on WinCE or Symbian.
       
  1319     // Easiest alternative is to use sockets for IPC.
       
  1320     QLocalServer oopServer;
       
  1321     // First remove possible earlier listening address which would cause listen to fail 
       
  1322     // (e.g. previously abruptly ended unit test might cause this)
       
  1323     QLocalServer::removeServer("tst_qnetworksession");
       
  1324     oopServer.listen("tst_qnetworksession");
       
  1325 
       
  1326     QProcess lackey;
       
  1327     lackey.start("qnetworksessionlackey");
       
  1328     QVERIFY(lackey.waitForStarted());
       
  1329 
       
  1330 
       
  1331     QVERIFY(oopServer.waitForNewConnection(-1));
       
  1332     QLocalSocket *oopSocket = oopServer.nextPendingConnection();
       
  1333 
       
  1334     do {
       
  1335         QByteArray output;
       
  1336 
       
  1337         if(oopSocket->waitForReadyRead()) {
       
  1338             output = oopSocket->readLine().trimmed();
       
  1339         }
       
  1340 
       
  1341         if (output.startsWith("Started session ")) {
       
  1342             QString identifier = QString::fromLocal8Bit(output.mid(20).constData());
       
  1343             QNetworkConfiguration changed;
       
  1344 
       
  1345             do {
       
  1346                 QTRY_VERIFY(!spy.isEmpty());
       
  1347                 changed = qvariant_cast<QNetworkConfiguration>(spy.takeFirst().at(0));
       
  1348             } while (changed.identifier() != identifier);
       
  1349 
       
  1350             QVERIFY((changed.state() & QNetworkConfiguration::Active) ==
       
  1351                     QNetworkConfiguration::Active);
       
  1352 
       
  1353             QVERIFY(!before.contains(changed));
       
  1354 
       
  1355             QList<QNetworkConfiguration> after =
       
  1356                 manager.allConfigurations(QNetworkConfiguration::Active);
       
  1357 
       
  1358             QVERIFY(after.contains(changed));
       
  1359 
       
  1360             spy.clear();
       
  1361 
       
  1362             oopSocket->write("stop\n");
       
  1363             oopSocket->waitForBytesWritten();
       
  1364 
       
  1365             do {
       
  1366                 QTRY_VERIFY(!spy.isEmpty());
       
  1367 
       
  1368                 changed = qvariant_cast<QNetworkConfiguration>(spy.takeFirst().at(0));
       
  1369             } while (changed.identifier() != identifier);
       
  1370 
       
  1371             QVERIFY((changed.state() & QNetworkConfiguration::Active) !=
       
  1372                     QNetworkConfiguration::Active);
       
  1373 
       
  1374             QList<QNetworkConfiguration> afterStop =
       
  1375                     manager.allConfigurations(QNetworkConfiguration::Active);
       
  1376 
       
  1377             QVERIFY(!afterStop.contains(changed));
       
  1378 
       
  1379             oopSocket->disconnectFromServer();
       
  1380             oopSocket->waitForDisconnected(-1);
       
  1381 
       
  1382             lackey.waitForFinished();
       
  1383         }
       
  1384     // This is effected by QTBUG-4903, process will always report as running
       
  1385     //} while (lackey.state() == QProcess::Running);
       
  1386 
       
  1387     // Workaround: the socket in the lackey will disconnect on exit
       
  1388     } while (oopSocket->state() == QLocalSocket::ConnectedState);
       
  1389 
       
  1390     switch (lackey.exitCode()) {
       
  1391     case 0:
       
  1392         qDebug("Lackey returned exit success (0)");
       
  1393         break;
       
  1394     case 1:
       
  1395         QSKIP("No discovered configurations found.", SkipAll);
       
  1396     case 2:
       
  1397         QSKIP("Lackey could not start session.", SkipAll);
       
  1398     default:
       
  1399         QSKIP("Lackey failed", SkipAll);
       
  1400     }
       
  1401 }
       
  1402 
       
  1403 // A convinience / helper function for testcases. Return the first matching configuration.
       
  1404 // Ignores configurations in other than 'discovered' -state. Returns invalid (QNetworkConfiguration())
       
  1405 // if none found.
       
  1406 QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfiguration::Type configType) {
       
  1407     
       
  1408     // Refresh configurations and derive configurations matching given parameters.
       
  1409     QNetworkConfigurationManager mgr;
       
  1410     QSignalSpy updateSpy(&mgr, SIGNAL(updateCompleted()));
       
  1411     
       
  1412     mgr.updateConfigurations();
       
  1413     QTRY_NOOP(updateSpy.count() == 1);
       
  1414     if (updateSpy.count() != 1) {
       
  1415         qDebug("tst_QNetworkSession::suitableConfiguration() failure: unable to update configurations");
       
  1416         return QNetworkConfiguration();
       
  1417     }
       
  1418     QList<QNetworkConfiguration> discoveredConfigs = mgr.allConfigurations(QNetworkConfiguration::Discovered);
       
  1419     foreach(QNetworkConfiguration config, discoveredConfigs) {
       
  1420         if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {        
       
  1421             discoveredConfigs.removeOne(config);
       
  1422         } else if (config.type() != configType) {
       
  1423             // qDebug() << "Dumping config because type (IAP/SNAP) mismatches: " << config.name();
       
  1424             discoveredConfigs.removeOne(config);
       
  1425         } else if ((config.type() == QNetworkConfiguration::InternetAccessPoint) &&
       
  1426                     bearerType == "cellular") { // 'cellular' bearertype is for convinience
       
  1427             if (config.bearerName() != "2G" &&
       
  1428                 config.bearerName() != "CDMA2000" &&
       
  1429                 config.bearerName() != "WCDMA" &&
       
  1430                 config.bearerName() != "HSPA") {
       
  1431                 // qDebug() << "Dumping config because bearer mismatches (cellular): " << config.name();
       
  1432                 discoveredConfigs.removeOne(config);
       
  1433             }
       
  1434         } else if ((config.type() == QNetworkConfiguration::InternetAccessPoint) && 
       
  1435                     bearerType != config.bearerName()) {
       
  1436             // qDebug() << "Dumping config because bearer mismatches (WLAN): " << config.name();
       
  1437             discoveredConfigs.removeOne(config);
       
  1438         }
       
  1439     }
       
  1440     if (discoveredConfigs.isEmpty()) {
       
  1441         qDebug("tst_QNetworkSession::suitableConfiguration() failure: no suitable configurations present.");
       
  1442         return QNetworkConfiguration();
       
  1443     } else {
       
  1444         return discoveredConfigs.first();
       
  1445     }
       
  1446 }
       
  1447 
       
  1448 // A convinience-function: updates configurations and waits that they are updated.
       
  1449 void updateConfigurations() 
       
  1450 {
       
  1451     QNetworkConfigurationManager mgr;
       
  1452     QSignalSpy updateSpy(&mgr, SIGNAL(updateCompleted()));
       
  1453     mgr.updateConfigurations();
       
  1454     QTRY_NOOP(updateSpy.count() == 1);
       
  1455 }
       
  1456 
       
  1457 // A convinience-function: updates and prints all available confiurations and their states
       
  1458 void printConfigurations()
       
  1459 {
       
  1460     QNetworkConfigurationManager manager;
       
  1461     QList<QNetworkConfiguration> allConfigs =
       
  1462     manager.allConfigurations();
       
  1463     qDebug("tst_QNetworkSession::printConfigurations QNetworkConfigurationManager gives following configurations: ");
       
  1464     foreach(QNetworkConfiguration config, allConfigs) {
       
  1465         qDebug() << "Name of the configuration: " << config.name();
       
  1466         qDebug() << "State of the configuration: " << config.state();
       
  1467     }
       
  1468 }
       
  1469 
       
  1470 // A convinience function for test-cases: opens the given configuration and return
       
  1471 // true if it was done gracefully.
       
  1472 bool openSession(QNetworkSession *session) {
       
  1473     bool result = true;
       
  1474     QNetworkConfigurationManager mgr;
       
  1475     QSignalSpy openedSpy(session, SIGNAL(opened()));
       
  1476     QSignalSpy stateChangeSpy(session, SIGNAL(stateChanged(QNetworkSession::State)));
       
  1477     QSignalSpy errorSpy(session, SIGNAL(error(QNetworkSession::SessionError)));
       
  1478     QSignalSpy configChangeSpy(&mgr, SIGNAL(configurationChanged(QNetworkConfiguration)));
       
  1479     // Store some initial statuses, because expected signals differ if the config is already
       
  1480     // active by some other session
       
  1481     QNetworkConfiguration::StateFlags configInitState = session->configuration().state();
       
  1482     QNetworkSession::State sessionInitState = session->state();
       
  1483     qDebug() << "tst_QNetworkSession::openSession() name of the configuration to be opened:  " << session->configuration().name();
       
  1484     qDebug() << "tst_QNetworkSession::openSession() state of the configuration to be opened:  " << session->configuration().state();
       
  1485     qDebug() << "tst_QNetworkSession::openSession() state of the session to be opened:  " << session->state();
       
  1486 
       
  1487     if (session->isOpen() ||
       
  1488         !session->sessionProperty("ActiveConfiguration").toString().isEmpty()) {
       
  1489         qDebug("tst_QNetworkSession::openSession() failure: session was already open / active.");
       
  1490         result = false;
       
  1491     } else {
       
  1492         session->open();
       
  1493         session->waitForOpened(120000); // Bringing interfaces up and down may take time at platform
       
  1494     }
       
  1495     QTest::qWait(5000); // Wait a moment to ensure all signals are propagated
       
  1496     // Check that connection opening went by the book. Add checks here if more strictness needed.
       
  1497     if (!session->isOpen()) {
       
  1498         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::open() failed.");
       
  1499         result =  false;
       
  1500     }
       
  1501     if (openedSpy.count() != 1) {
       
  1502         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::opened() - signal not received.");
       
  1503         result =  false;
       
  1504     }
       
  1505     if (!errorSpy.isEmpty()) {
       
  1506         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::error() - signal was detected.");
       
  1507         result = false;
       
  1508     }
       
  1509     if (sessionInitState != QNetworkSession::Connected && 
       
  1510         stateChangeSpy.isEmpty()) {
       
  1511         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::stateChanged() - signals not detected.");
       
  1512         result =  false;
       
  1513     }
       
  1514     if (configInitState != QNetworkConfiguration::Active && 
       
  1515         configChangeSpy.isEmpty()) {
       
  1516         qDebug("tst_QNetworkSession::openSession() failure: QNetworkConfigurationManager::configurationChanged() - signals not detected.");
       
  1517         result =  false;
       
  1518     }
       
  1519     if (session->configuration().state() != QNetworkConfiguration::Active) {
       
  1520         qDebug("tst_QNetworkSession::openSession() failure: session's configuration is not in 'Active' -state.");
       
  1521 	qDebug() << "tst_QNetworkSession::openSession() state is:  " << session->configuration().state();
       
  1522         result =  false;
       
  1523     }
       
  1524     if (result == false) {
       
  1525 	    qDebug() << "tst_QNetworkSession::openSession() opening session failed.";
       
  1526     } else {
       
  1527 	    qDebug() << "tst_QNetworkSession::openSession() opening session succeeded.";
       
  1528     }
       
  1529     qDebug() << "tst_QNetworkSession::openSession() name of the configuration is:  " << session->configuration().name();
       
  1530     qDebug() << "tst_QNetworkSession::openSession() configuration state is:  " << session->configuration().state();
       
  1531     qDebug() << "tst_QNetworkSession::openSession() session state is:  " << session->state();
       
  1532 	    
       
  1533     return result;
       
  1534 }
       
  1535 
       
  1536 // Helper function for closing opened session. Performs checks that 
       
  1537 // session is closed gradefully (e.g. signals). Function does not delete
       
  1538 // the session. The lastSessionOnConfiguration (true by default) is used to
       
  1539 // tell if there are more sessions open, basing on same configration. This 
       
  1540 // impacts the checks made.
       
  1541 bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration) {
       
  1542     if (!session) {
       
  1543         qDebug("tst_QNetworkSession::closeSession() failure: NULL session given");
       
  1544         return false;
       
  1545     }
       
  1546     
       
  1547     qDebug() << "tst_QNetworkSession::closeSession() name of the configuration to be closed:  " << session->configuration().name();
       
  1548     qDebug() << "tst_QNetworkSession::closeSession() state of the configuration to be closed:  " << session->configuration().state();
       
  1549     qDebug() << "tst_QNetworkSession::closeSession() state of the session to be closed:  " << session->state();
       
  1550     
       
  1551     if (session->state() != QNetworkSession::Connected || 
       
  1552         !session->isOpen()) {
       
  1553         qDebug("tst_QNetworkSession::closeSession() failure: session is not opened.");
       
  1554         return false;
       
  1555     }    
       
  1556     QNetworkConfigurationManager mgr;
       
  1557     QSignalSpy sessionClosedSpy(session, SIGNAL(closed()));
       
  1558     QSignalSpy sessionStateChangedSpy(session, SIGNAL(stateChanged(QNetworkSession::State)));
       
  1559     QSignalSpy sessionErrorSpy(session, SIGNAL(error(QNetworkSession::SessionError)));
       
  1560     QSignalSpy configChangeSpy(&mgr, SIGNAL(configurationChanged(QNetworkConfiguration)));
       
  1561     
       
  1562     bool result = true;
       
  1563     session->close();
       
  1564     QTest::qWait(5000); // Wait a moment so that all signals are propagated
       
  1565     
       
  1566     if (!sessionErrorSpy.isEmpty()) {
       
  1567         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::error() received.");
       
  1568         result = false;
       
  1569     }
       
  1570     if (sessionClosedSpy.count() != 1) {
       
  1571         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::closed() signal not received.");
       
  1572         result = false;
       
  1573     }
       
  1574     if (lastSessionOnConfiguration && 
       
  1575         sessionStateChangedSpy.isEmpty()) {
       
  1576         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::stateChanged() signals not received.");
       
  1577         result = false;
       
  1578     }
       
  1579     if (lastSessionOnConfiguration &&
       
  1580         session->state() != QNetworkSession::Disconnected) {
       
  1581         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession is not in Disconnected -state");
       
  1582         result = false;
       
  1583     }
       
  1584     QTRY_NOOP(!configChangeSpy.isEmpty());
       
  1585     if (lastSessionOnConfiguration &&
       
  1586         configChangeSpy.isEmpty()) {
       
  1587         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkConfigurationManager::configurationChanged() - signal not detected.");
       
  1588         result = false;
       
  1589     }
       
  1590     if (lastSessionOnConfiguration &&
       
  1591         session->configuration().state() == QNetworkConfiguration::Active) {
       
  1592          qDebug("tst_QNetworkSession::closeSession() failure: session's configuration is still in active state.");
       
  1593          result = false;
       
  1594     }
       
  1595     if (result == false) {
       
  1596 	    qDebug() << "tst_QNetworkSession::closeSession() closing session failed.";
       
  1597     } else {
       
  1598 	    qDebug() << "tst_QNetworkSession::closeSession() closing session succeeded.";
       
  1599     } 
       
  1600     qDebug() << "tst_QNetworkSession::closeSession() name of the configuration is:  " << session->configuration().name();
       
  1601     qDebug() << "tst_QNetworkSession::closeSession() configuration state is:  " << session->configuration().state();
       
  1602     qDebug() << "tst_QNetworkSession::closeSession() session state is:  " << session->state();
       
  1603     return result;
       
  1604 }
       
  1605 
       
  1606 QTEST_MAIN(tst_QNetworkSession)
       
  1607 
       
  1608 #include "tst_qnetworksession.moc"