qtmobility/tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.cpp
changeset 0 cfcbf08528c4
child 2 5822d84012fb
child 4 90517678cc4f
equal deleted inserted replaced
-1:000000000000 0:cfcbf08528c4
       
     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 "../../qbearertestcommon.h"
       
    46 #include <qnetworkconfigmanager.h>
       
    47 #include <qnetworksession.h>
       
    48 
       
    49 #ifdef Q_WS_MAEMO_6
       
    50 #include <stdio.h>
       
    51 #include <iapconf.h>
       
    52 #endif
       
    53 
       
    54 QTM_USE_NAMESPACE
       
    55 
       
    56 Q_DECLARE_METATYPE(QNetworkConfiguration)
       
    57 Q_DECLARE_METATYPE(QNetworkConfiguration::Type);
       
    58 Q_DECLARE_METATYPE(QNetworkSession::State);
       
    59 Q_DECLARE_METATYPE(QNetworkSession::SessionError);
       
    60 
       
    61 class tst_QNetworkSession : public QObject
       
    62 {
       
    63     Q_OBJECT
       
    64 
       
    65 public slots:
       
    66     void initTestCase();
       
    67     void cleanupTestCase();
       
    68 
       
    69 private slots:
       
    70 
       
    71     void outOfProcessSession();
       
    72     void invalidSession();
       
    73 
       
    74     void repeatedOpenClose_data();
       
    75     void repeatedOpenClose();
       
    76     
       
    77     void roamingErrorCodes();
       
    78 
       
    79     void sessionProperties_data();
       
    80     void sessionProperties();
       
    81 
       
    82     void userChoiceSession_data();
       
    83     void userChoiceSession();
       
    84 
       
    85     void sessionOpenCloseStop_data();
       
    86     void sessionOpenCloseStop();
       
    87 
       
    88 private:
       
    89     QNetworkConfigurationManager manager;
       
    90 
       
    91     uint inProcessSessionManagementCount;
       
    92 
       
    93 #ifdef Q_WS_MAEMO_6
       
    94     Maemo::IAPConf *iapconf;
       
    95     Maemo::IAPConf *iapconf2;
       
    96     Maemo::IAPConf *gprsiap;
       
    97 #define MAX_IAPS 10
       
    98     Maemo::IAPConf *iaps[MAX_IAPS];
       
    99     QProcess *icd_stub;
       
   100 #endif
       
   101 };
       
   102 
       
   103 // Helper functions
       
   104 bool openSession(QNetworkSession *session);
       
   105 bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration = true);
       
   106 QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfiguration::Type configType);
       
   107 
       
   108 void tst_QNetworkSession::initTestCase()
       
   109 {
       
   110     qRegisterMetaType<QNetworkSession::State>("QNetworkSession::State");
       
   111     qRegisterMetaType<QNetworkSession::SessionError>("QNetworkSession::SessionError");
       
   112     qRegisterMetaType<QNetworkConfiguration>("QNetworkConfiguration");
       
   113     qRegisterMetaType<QNetworkConfiguration::Type>("QNetworkConfiguration::Type");
       
   114 
       
   115 #ifdef Q_WS_MAEMO_6
       
   116     iapconf = new Maemo::IAPConf("007");
       
   117     iapconf->setValue("ipv4_type", "AUTO");
       
   118     iapconf->setValue("wlan_wepkey1", "connt");
       
   119     iapconf->setValue("wlan_wepdefkey", 1);
       
   120     iapconf->setValue("wlan_ssid", QByteArray("JamesBond"));
       
   121     iapconf->setValue("name", "James Bond");
       
   122     iapconf->setValue("type", "WLAN_INFRA");
       
   123 
       
   124     gprsiap = new Maemo::IAPConf("This-is-GPRS-IAP");
       
   125     gprsiap->setValue("ask_password", false);
       
   126     gprsiap->setValue("gprs_accesspointname", "internet");
       
   127     gprsiap->setValue("gprs_password", "");
       
   128     gprsiap->setValue("gprs_username", "");
       
   129     gprsiap->setValue("ipv4_autodns", true);
       
   130     gprsiap->setValue("ipv4_type", "AUTO");
       
   131     gprsiap->setValue("sim_imsi", "244070123456789");
       
   132     gprsiap->setValue("name", "MI6");
       
   133     gprsiap->setValue("type", "GPRS");
       
   134 
       
   135     iapconf2 = new Maemo::IAPConf("osso.net");
       
   136     iapconf2->setValue("ipv4_type", "AUTO");
       
   137     iapconf2->setValue("wlan_wepkey1", "osso.net");
       
   138     iapconf2->setValue("wlan_wepdefkey", 1);
       
   139     iapconf2->setValue("wlan_ssid", QByteArray("osso.net"));
       
   140     iapconf2->setValue("name", "osso.net");
       
   141     iapconf2->setValue("type", "WLAN_INFRA");
       
   142     iapconf2->setValue("wlan_security", "WEP");
       
   143 
       
   144     /* Create large number of IAPs in the gconf and see what happens */
       
   145     fflush(stdout);
       
   146     printf("Creating %d IAPS: ", MAX_IAPS);
       
   147     for (int i=0; i<MAX_IAPS; i++) {
       
   148 	QString num = QString().sprintf("%d", i);
       
   149 	QString iap = "iap-" + num;
       
   150 	iaps[i] = new Maemo::IAPConf(iap);
       
   151 	iaps[i]->setValue("name", QString("test-iap-")+num);
       
   152 	iaps[i]->setValue("type", "WLAN_INFRA");
       
   153 	iaps[i]->setValue("wlan_ssid", QString(QString("test-ssid-")+num).toAscii());
       
   154 	iaps[i]->setValue("wlan_security", "WPA_PSK");
       
   155 	iaps[i]->setValue("EAP_wpa_preshared_passphrase", QString("test-passphrase-")+num);
       
   156 	printf(".");
       
   157 	fflush(stdout);
       
   158     }
       
   159     printf("\n");
       
   160     fflush(stdout);
       
   161 
       
   162     icd_stub = new QProcess(this);
       
   163     icd_stub->start("/usr/bin/icd2_stub.py");
       
   164     QTest::qWait(1000);
       
   165 
       
   166     // Add a known network to scan list that icd2 stub returns
       
   167     QProcess dbus_send;
       
   168     // 007 network
       
   169     dbus_send.start("dbus-send --type=method_call --system "
       
   170 		    "--dest=com.nokia.icd2 /com/nokia/icd2 "
       
   171 		    "com.nokia.icd2.testing.add_available_network "
       
   172 		    "string:'' uint32:0 string:'' "
       
   173 		    "string:WLAN_INFRA uint32:5000011 array:byte:48,48,55");
       
   174     dbus_send.waitForFinished();
       
   175 
       
   176     // osso.net network
       
   177     dbus_send.start("dbus-send --type=method_call --system "
       
   178 		    "--dest=com.nokia.icd2 /com/nokia/icd2 "
       
   179 		    "com.nokia.icd2.testing.add_available_network "
       
   180 		    "string:'' uint32:0 string:'' "
       
   181 		    "string:WLAN_INFRA uint32:83886097 array:byte:111,115,115,111,46,110,101,116");
       
   182     dbus_send.waitForFinished();
       
   183 #endif
       
   184 
       
   185     inProcessSessionManagementCount = 0;
       
   186 
       
   187     QSignalSpy spy(&manager, SIGNAL(updateCompleted()));
       
   188     manager.updateConfigurations();
       
   189     QTRY_VERIFY(spy.count() == 1);
       
   190 }
       
   191 
       
   192 void tst_QNetworkSession::cleanupTestCase()
       
   193 {
       
   194     if (!(manager.capabilities() & QNetworkConfigurationManager::SystemSessionSupport) &&
       
   195         (manager.capabilities() & QNetworkConfigurationManager::CanStartAndStopInterfaces) &&
       
   196         inProcessSessionManagementCount == 0) {
       
   197         QFAIL("No usable configurations found to complete all possible "
       
   198               "tests in inProcessSessionManagement()");
       
   199     }
       
   200 
       
   201 #ifdef Q_WS_MAEMO_6
       
   202     iapconf->clear();
       
   203     delete iapconf;
       
   204     iapconf2->clear();
       
   205     delete iapconf2;
       
   206     gprsiap->clear();
       
   207     delete gprsiap;
       
   208 
       
   209     printf("Deleting %d IAPS : ", MAX_IAPS);
       
   210     for (int i=0; i<MAX_IAPS; i++) {
       
   211 	iaps[i]->clear();
       
   212 	delete iaps[i];
       
   213 	printf(".");
       
   214 	fflush(stdout);
       
   215     }
       
   216     printf("\n");
       
   217     qDebug() << "Deleted" << MAX_IAPS << "IAPs";
       
   218 
       
   219     icd_stub->terminate();
       
   220     icd_stub->waitForFinished();
       
   221 #endif
       
   222 }
       
   223 
       
   224 void tst_QNetworkSession::invalidSession()
       
   225 {
       
   226     // Verify that session created with invalid configuration remains in invalid state
       
   227     QNetworkSession session(QNetworkConfiguration(), 0);
       
   228     QVERIFY(!session.isOpen());
       
   229     QVERIFY(session.state() == QNetworkSession::Invalid);
       
   230     
       
   231     // Verify that opening session with invalid configuration both 1) emits invalidconfigurationerror
       
   232     // and 2) sets session's state as invalid.
       
   233     QSignalSpy errorSpy(&session, SIGNAL(error(QNetworkSession::SessionError)));
       
   234     session.open();
       
   235     session.waitForOpened(1000); // Should bail out right away
       
   236     QVERIFY(errorSpy.count() == 1); 
       
   237     QNetworkSession::SessionError error =
       
   238            qvariant_cast<QNetworkSession::SessionError> (errorSpy.first().at(0));
       
   239     QVERIFY(error == QNetworkSession::InvalidConfigurationError);
       
   240     QVERIFY(session.state() == QNetworkSession::Invalid);
       
   241 
       
   242     // Check same thing with a config from platform (there are subtle differences
       
   243     // because emtpy configuration does not have private pointer). Test with config 
       
   244     // in '(un)defined' state
       
   245     QList<QNetworkConfiguration> allConfigs = manager.allConfigurations();
       
   246     foreach(QNetworkConfiguration config, allConfigs) {
       
   247         if ((config.state() & QNetworkConfiguration::Discovered) != QNetworkConfiguration::Discovered) {
       
   248             QNetworkSession session2(config);
       
   249             QSignalSpy errorSpy2(&session2, SIGNAL(error(QNetworkSession::SessionError)));
       
   250             session2.open();
       
   251             session2.waitForOpened(1000); // Should bail out right away
       
   252             QVERIFY(errorSpy2.count() == 1); 
       
   253             QNetworkSession::SessionError error2 =
       
   254                        qvariant_cast<QNetworkSession::SessionError> (errorSpy2.first().at(0));
       
   255             QVERIFY(error2 == QNetworkSession::InvalidConfigurationError);
       
   256             QVERIFY(session2.state() == QNetworkSession::Invalid);
       
   257             break; // Once is enough
       
   258         }
       
   259     }
       
   260 }
       
   261 
       
   262 void tst_QNetworkSession::sessionProperties_data()
       
   263 {
       
   264     QTest::addColumn<QNetworkConfiguration>("configuration");
       
   265 
       
   266     QTest::newRow("invalid configuration") << QNetworkConfiguration();
       
   267 
       
   268     foreach (const QNetworkConfiguration &config, manager.allConfigurations()) {
       
   269         const QString name = config.name().isEmpty() ? QString("<Hidden>") : config.name();
       
   270         QTest::newRow(name.toLocal8Bit().constData()) << config;
       
   271     }
       
   272 }
       
   273 
       
   274 void tst_QNetworkSession::sessionProperties()
       
   275 {
       
   276     QFETCH(QNetworkConfiguration, configuration);
       
   277 
       
   278     QNetworkSession session(configuration);
       
   279     
       
   280     QVERIFY(session.configuration() == configuration);
       
   281 
       
   282     QStringList validBearerNames = QStringList() << QLatin1String("Unknown")
       
   283                                                  << QLatin1String("Ethernet")
       
   284                                                  << QLatin1String("WLAN")
       
   285                                                  << QLatin1String("2G")
       
   286                                                  << QLatin1String("CDMA2000")
       
   287                                                  << QLatin1String("WCDMA")
       
   288                                                  << QLatin1String("HSPA")
       
   289                                                  << QLatin1String("Bluetooth")
       
   290                                                  << QLatin1String("WiMAX");
       
   291 
       
   292     if (!configuration.isValid()) {
       
   293         QVERIFY(configuration.bearerName().isEmpty());
       
   294     } else {
       
   295         switch (configuration.type())
       
   296         {
       
   297             case QNetworkConfiguration::ServiceNetwork:
       
   298             case QNetworkConfiguration::UserChoice:
       
   299             default:
       
   300                 QVERIFY(configuration.bearerName().isEmpty());
       
   301                 break;
       
   302             case QNetworkConfiguration::InternetAccessPoint:
       
   303                 QVERIFY(validBearerNames.contains(configuration.bearerName()));
       
   304                 break;
       
   305         }
       
   306     }
       
   307 
       
   308     // QNetworkSession::interface() should return an invalid interface unless
       
   309     // session is in the connected state.
       
   310 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
       
   311     // On Symbian emulator, the support for data bearers is limited
       
   312     QCOMPARE(session.state() == QNetworkSession::Connected, session.interface().isValid());
       
   313 #endif
       
   314 
       
   315     if (!configuration.isValid()) {
       
   316         QVERIFY(configuration.state() == QNetworkConfiguration::Undefined &&
       
   317                 session.state() == QNetworkSession::Invalid);
       
   318     } else {
       
   319         switch (configuration.state()) {
       
   320         case QNetworkConfiguration::Undefined:
       
   321             QVERIFY(session.state() == QNetworkSession::NotAvailable);
       
   322             break;
       
   323         case QNetworkConfiguration::Defined:
       
   324             QVERIFY(session.state() == QNetworkSession::NotAvailable);
       
   325             break;
       
   326         case QNetworkConfiguration::Discovered:
       
   327             QVERIFY(session.state() == QNetworkSession::Connecting ||
       
   328                     session.state() == QNetworkSession::Disconnected);
       
   329             break;
       
   330         case QNetworkConfiguration::Active:
       
   331             QVERIFY(session.state() == QNetworkSession::Connected ||
       
   332                     session.state() == QNetworkSession::Closing ||
       
   333                     session.state() == QNetworkSession::Roaming);
       
   334             break;
       
   335         default:
       
   336             QFAIL("Invalid configuration state");
       
   337         };
       
   338     }
       
   339 }
       
   340 
       
   341 void tst_QNetworkSession::repeatedOpenClose_data() {
       
   342     QTest::addColumn<QString>("bearerType");
       
   343     QTest::addColumn<QNetworkConfiguration::Type>("configurationType");
       
   344     QTest::addColumn<int>("repeatTimes");
       
   345 
       
   346     QTest::newRow("WLAN_IAP") << "WLAN" << QNetworkConfiguration::InternetAccessPoint << 3;
       
   347     // QTest::newRow("Cellular_IAP") << "cellular" << QNetworkConfiguration::InternetAccessPoint << 3;
       
   348     // QTest::newRow("SNAP") << "bearer_type_not_relevant_with_SNAPs" << QNetworkConfiguration::ServiceNetwork << 3;
       
   349 }
       
   350 
       
   351 // Tests repeated-open close.
       
   352 void tst_QNetworkSession::repeatedOpenClose() {
       
   353     QFETCH(QString, bearerType);
       
   354     QFETCH(QNetworkConfiguration::Type, configurationType);
       
   355     QFETCH(int, repeatTimes);
       
   356 
       
   357     // First check that opening once succeeds and determine if repeatable testing is doable
       
   358     QNetworkConfiguration config = suitableConfiguration(bearerType, configurationType);
       
   359     if (!config.isValid()) {
       
   360         QSKIP("No suitable configurations, skipping this round of repeated open-close test.", SkipSingle);
       
   361     }
       
   362     qDebug() << "Using following configuratio to repeatedly open and close: " << config.name();
       
   363     QNetworkSession permanentSession(config);
       
   364     if (!openSession(&permanentSession) || 
       
   365         !closeSession(&permanentSession)) {
       
   366         QSKIP("Unable to open/close session, skipping this round of repeated open-close test.", SkipSingle); 
       
   367     }
       
   368     for (int i = repeatTimes; i > 0; i--) { 
       
   369        QVERIFY(openSession(&permanentSession));
       
   370        QVERIFY(closeSession(&permanentSession));
       
   371     }
       
   372 }
       
   373 
       
   374 void tst_QNetworkSession::roamingErrorCodes() {
       
   375     
       
   376 #ifndef Q_OS_SYMBIAN
       
   377     QSKIP("Roaming supported on Symbian.", SkipAll);
       
   378 #else 
       
   379     QNetworkConfiguration wlanIapConfig = suitableConfiguration("WLAN", QNetworkConfiguration::InternetAccessPoint);
       
   380     if (!wlanIapConfig.isValid()) {
       
   381         QSKIP("No WLAN IAP accessible, skipping test.", SkipAll);
       
   382     }
       
   383     // Check that opening and closing two sessions on same config work gracefully:
       
   384     QNetworkSession iapSession(wlanIapConfig);
       
   385     QVERIFY(openSession(&iapSession));
       
   386     QNetworkSession adminIapSession(wlanIapConfig);
       
   387     QVERIFY(openSession(&adminIapSession));
       
   388     QVERIFY(closeSession(&iapSession, false)); // false == not a last session based on the configuration
       
   389     QVERIFY(closeSession(&adminIapSession));
       
   390     
       
   391     // Open configurations again, force close bearer and check that errors are emitted correctly
       
   392     // on the other session
       
   393     QVERIFY(openSession(&iapSession));
       
   394     QVERIFY(openSession(&adminIapSession));
       
   395     QSignalSpy errorSpy(&iapSession, SIGNAL(error(QNetworkSession::SessionError)));   
       
   396     adminIapSession.stop(); // requires NetworkControl capabilities
       
   397     QTRY_VERIFY(!errorSpy.isEmpty()); // wait for error signals
       
   398     QNetworkSession::SessionError error = qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
       
   399     QVERIFY(error == QNetworkSession::SessionAbortedError);
       
   400     QVERIFY(iapSession.state() == QNetworkSession::Disconnected);
       
   401     QVERIFY(adminIapSession.state() == QNetworkSession::Disconnected);
       
   402 #endif // Q_OS_SYMBIAN
       
   403     /*
       
   404      // Check for roaming error. Challenging to automate, therefore commented out.
       
   405      // Case requires that you have controllable WLAN in Internet SNAP (only).
       
   406     QNetworkConfiguration snapConfig = suitableConfiguration("bearer_not_relevant_with_snaps", QNetworkConfiguration::ServiceNetwork);
       
   407     if (!snapConfig.isValid()) {
       
   408         QSKIP("No SNAP accessible, skipping test.", SkipAll);
       
   409     }
       
   410     QNetworkSession snapSession(snapConfig);
       
   411     QVERIFY(openSession(&snapSession));
       
   412     QSignalSpy errorSpySnap(&snapSession, SIGNAL(error(QNetworkSession::SessionError)));
       
   413     qDebug("Disconnect the WLAN now");
       
   414     QTRY_VERIFY(!errorSpySnap.isEmpty()); // wait for error signals
       
   415     QVERIFY(errorSpySnap.count() == 1);
       
   416     error = qvariant_cast<QNetworkSession::SessionError>(errorSpySnap.first().at(0));
       
   417     qDebug() << "Error received when turning off wlan on SNAP: " << error;
       
   418     QVERIFY(error == QNetworkSession::RoamingError);
       
   419     
       
   420     qDebug("Connect the WLAN now");
       
   421     QTest::qWait(60000); // Wait for WLAN to get up
       
   422     QNetworkConfiguration wlanIapConfig2 = suitableConfiguration("WLAN", QNetworkConfiguration::InternetAccessPoint);
       
   423     QNetworkSession iapSession2(wlanIapConfig2);
       
   424     QVERIFY(openSession(&iapSession2));
       
   425     QSignalSpy errorSpy2(&iapSession2, SIGNAL(error(QNetworkSession::SessionError)));
       
   426     qDebug("Disconnect the WLAN now");
       
   427     QTRY_VERIFY(!errorSpy2.isEmpty()); // wait for error signals
       
   428     QVERIFY(errorSpy2.count() == 1);
       
   429     error = qvariant_cast<QNetworkSession::SessionError>(errorSpy2.first().at(0));
       
   430     QVERIFY(error == QNetworkSession::SessionAbortedError);
       
   431     QVERIFY(iapSession2.state() == QNetworkSession::Disconnected);
       
   432     */
       
   433 }
       
   434 
       
   435 void tst_QNetworkSession::userChoiceSession_data()
       
   436 {
       
   437     QTest::addColumn<QNetworkConfiguration>("configuration");
       
   438 
       
   439     QNetworkConfiguration config = manager.defaultConfiguration();
       
   440     if (config.type() == QNetworkConfiguration::UserChoice)
       
   441         QTest::newRow("UserChoice") << config;
       
   442     else
       
   443         QSKIP("Default configuration is not a UserChoice configuration.", SkipAll);
       
   444 }
       
   445 
       
   446 void tst_QNetworkSession::userChoiceSession()
       
   447 {
       
   448     QFETCH(QNetworkConfiguration, configuration);
       
   449 
       
   450     QVERIFY(configuration.type() == QNetworkConfiguration::UserChoice);
       
   451 
       
   452     QNetworkSession session(configuration);
       
   453 
       
   454     // Check that configuration was really set
       
   455     QVERIFY(session.configuration() == configuration);
       
   456 
       
   457     QVERIFY(!session.isOpen());
       
   458 
       
   459     // Check that session is not active
       
   460     QVERIFY(session.sessionProperty("ActiveConfiguration").toString().isEmpty());
       
   461 
       
   462     // The remaining tests require the session to be not NotAvailable.
       
   463     if (session.state() == QNetworkSession::NotAvailable)
       
   464         QSKIP("Network is not available.", SkipSingle);
       
   465 
       
   466     QSignalSpy sessionOpenedSpy(&session, SIGNAL(opened()));
       
   467     QSignalSpy sessionClosedSpy(&session, SIGNAL(closed()));
       
   468     QSignalSpy stateChangedSpy(&session, SIGNAL(stateChanged(QNetworkSession::State)));
       
   469     QSignalSpy errorSpy(&session, SIGNAL(error(QNetworkSession::SessionError)));
       
   470 
       
   471     // Test opening the session.
       
   472     {
       
   473         bool expectStateChange = session.state() != QNetworkSession::Connected;
       
   474 
       
   475         session.open();
       
   476 
       
   477         session.waitForOpened();
       
   478 
       
   479         if (session.isOpen())
       
   480             QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty());
       
   481         if (!errorSpy.isEmpty()) {
       
   482             QNetworkSession::SessionError error =
       
   483                 qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
       
   484             if (error == QNetworkSession::OperationNotSupportedError) {
       
   485                 // The session needed to bring up the interface,
       
   486                 // but the operation is not supported.
       
   487                 QSKIP("Configuration does not support open().", SkipSingle);
       
   488             } else if (error == QNetworkSession::InvalidConfigurationError) {
       
   489                 // The session needed to bring up the interface, but it is not possible for the
       
   490                 // specified configuration.
       
   491                 if ((session.configuration().state() & QNetworkConfiguration::Discovered) ==
       
   492                     QNetworkConfiguration::Discovered) {
       
   493                     QFAIL("Failed to open session for Discovered configuration.");
       
   494                 } else {
       
   495                     QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle);
       
   496                 }
       
   497             } else if (error == QNetworkSession::UnknownSessionError) {
       
   498                     QSKIP("Unknown session error.", SkipSingle);
       
   499             } else {
       
   500                 QFAIL("Error opening session.");
       
   501             }
       
   502         } else if (!sessionOpenedSpy.isEmpty()) {
       
   503             QCOMPARE(sessionOpenedSpy.count(), 1);
       
   504             QVERIFY(sessionClosedSpy.isEmpty());
       
   505             QVERIFY(errorSpy.isEmpty());
       
   506 
       
   507             if (expectStateChange)
       
   508                 QTRY_VERIFY(!stateChangedSpy.isEmpty());
       
   509 
       
   510             QVERIFY(session.state() == QNetworkSession::Connected);
       
   511 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
       
   512             // On Symbian emulator, the support for data bearers is limited
       
   513             QVERIFY(session.interface().isValid());
       
   514 #endif
       
   515 
       
   516             const QString userChoiceIdentifier =
       
   517                 session.sessionProperty("UserChoiceConfiguration").toString();
       
   518 
       
   519             QVERIFY(!userChoiceIdentifier.isEmpty());
       
   520             QVERIFY(userChoiceIdentifier != configuration.identifier());
       
   521 
       
   522             QNetworkConfiguration userChoiceConfiguration =
       
   523                 manager.configurationFromIdentifier(userChoiceIdentifier);
       
   524 
       
   525             QVERIFY(userChoiceConfiguration.isValid());
       
   526             QVERIFY(userChoiceConfiguration.type() != QNetworkConfiguration::UserChoice);
       
   527 
       
   528             const QString testIdentifier("abc");
       
   529             //resetting UserChoiceConfiguration is ignored (read only property)
       
   530             session.setSessionProperty("UserChoiceConfiguration", testIdentifier);
       
   531             QVERIFY(session.sessionProperty("UserChoiceConfiguration").toString() != testIdentifier);
       
   532 
       
   533             const QString activeIdentifier =
       
   534                 session.sessionProperty("ActiveConfiguration").toString();
       
   535 
       
   536             QVERIFY(!activeIdentifier.isEmpty());
       
   537             QVERIFY(activeIdentifier != configuration.identifier());
       
   538 
       
   539             QNetworkConfiguration activeConfiguration =
       
   540                 manager.configurationFromIdentifier(activeIdentifier);
       
   541 
       
   542             QVERIFY(activeConfiguration.isValid());
       
   543             QVERIFY(activeConfiguration.type() == QNetworkConfiguration::InternetAccessPoint);
       
   544             
       
   545             //resetting ActiveConfiguration is ignored (read only property)
       
   546             session.setSessionProperty("ActiveConfiguration", testIdentifier);
       
   547             QVERIFY(session.sessionProperty("ActiveConfiguration").toString() != testIdentifier);
       
   548 
       
   549             if (userChoiceConfiguration.type() == QNetworkConfiguration::InternetAccessPoint) {
       
   550                 QVERIFY(userChoiceConfiguration == activeConfiguration);
       
   551             } else {
       
   552                 QVERIFY(userChoiceConfiguration.type() == QNetworkConfiguration::ServiceNetwork);
       
   553                 QVERIFY(userChoiceConfiguration.children().contains(activeConfiguration));
       
   554             }
       
   555         } else {
       
   556             QFAIL("Timeout waiting for session to open.");
       
   557         }
       
   558     }
       
   559 }
       
   560 
       
   561 void tst_QNetworkSession::sessionOpenCloseStop_data()
       
   562 {
       
   563     QTest::addColumn<QNetworkConfiguration>("configuration");
       
   564     QTest::addColumn<bool>("forceSessionStop");
       
   565 
       
   566     foreach (const QNetworkConfiguration &config, manager.allConfigurations()) {
       
   567         const QString name = config.name().isEmpty() ? QString("<Hidden>") : config.name();
       
   568         QTest::newRow((name + QLatin1String(" close")).toLocal8Bit().constData())
       
   569             << config << false;
       
   570         QTest::newRow((name + QLatin1String(" stop")).toLocal8Bit().constData())
       
   571             << config << true;
       
   572     }
       
   573 }
       
   574 
       
   575 void tst_QNetworkSession::sessionOpenCloseStop()
       
   576 {
       
   577     QFETCH(QNetworkConfiguration, configuration);
       
   578     QFETCH(bool, forceSessionStop);
       
   579 
       
   580     QNetworkSession session(configuration);
       
   581 
       
   582     // Test initial state of the session.
       
   583     {
       
   584         QVERIFY(session.configuration() == configuration);
       
   585         QVERIFY(!session.isOpen());
       
   586         // session may be invalid if configuration is removed between when
       
   587         // sessionOpenCloseStop_data() is called and here.
       
   588         QVERIFY((configuration.isValid() && (session.state() != QNetworkSession::Invalid)) ||
       
   589                 (!configuration.isValid() && (session.state() == QNetworkSession::Invalid)));
       
   590         QVERIFY(session.error() == QNetworkSession::UnknownSessionError);
       
   591     }
       
   592 
       
   593     // The remaining tests require the session to be not NotAvailable.
       
   594     if (session.state() == QNetworkSession::NotAvailable)
       
   595         QSKIP("Network is not available.", SkipSingle);
       
   596 
       
   597     QSignalSpy sessionOpenedSpy(&session, SIGNAL(opened()));
       
   598     QSignalSpy sessionClosedSpy(&session, SIGNAL(closed()));
       
   599     QSignalSpy stateChangedSpy(&session, SIGNAL(stateChanged(QNetworkSession::State)));
       
   600     QSignalSpy errorSpy(&session, SIGNAL(error(QNetworkSession::SessionError)));
       
   601 
       
   602     // Test opening the session.
       
   603     {
       
   604         QNetworkSession::State previousState = session.state();
       
   605         bool expectStateChange = previousState != QNetworkSession::Connected;
       
   606 
       
   607         session.open();
       
   608 
       
   609         session.waitForOpened();
       
   610 
       
   611         if (session.isOpen())
       
   612             QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty());
       
   613         if (!errorSpy.isEmpty()) {
       
   614             QNetworkSession::SessionError error =
       
   615                 qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
       
   616 
       
   617             QVERIFY(session.state() == previousState);
       
   618 
       
   619             if (error == QNetworkSession::OperationNotSupportedError) {
       
   620                 // The session needed to bring up the interface,
       
   621                 // but the operation is not supported.
       
   622                 QSKIP("Configuration does not support open().", SkipSingle);
       
   623             } else if (error == QNetworkSession::InvalidConfigurationError) {
       
   624                 // The session needed to bring up the interface, but it is not possible for the
       
   625                 // specified configuration.
       
   626                 if ((session.configuration().state() & QNetworkConfiguration::Discovered) ==
       
   627                     QNetworkConfiguration::Discovered) {
       
   628                     QFAIL("Failed to open session for Discovered configuration.");
       
   629                 } else {
       
   630                     QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle);
       
   631                 }
       
   632             } else if (error == QNetworkSession::UnknownSessionError) {
       
   633                     QSKIP("Unknown Session error.", SkipSingle);
       
   634             } else {
       
   635                 QFAIL("Error opening session.");
       
   636             }
       
   637         } else if (!sessionOpenedSpy.isEmpty()) {
       
   638             QCOMPARE(sessionOpenedSpy.count(), 1);
       
   639             QVERIFY(sessionClosedSpy.isEmpty());
       
   640             QVERIFY(errorSpy.isEmpty());
       
   641 
       
   642             if (expectStateChange) {
       
   643                 QTRY_VERIFY(stateChangedSpy.count() >= 2);
       
   644 
       
   645                 QNetworkSession::State state =
       
   646                     qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(0).at(0));
       
   647                 QVERIFY(state == QNetworkSession::Connecting);
       
   648 
       
   649                 state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(1).at(0));
       
   650                 QVERIFY(state == QNetworkSession::Connected);
       
   651             }
       
   652 
       
   653             QVERIFY(session.state() == QNetworkSession::Connected);
       
   654 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
       
   655             // On Symbian emulator, the support for data bearers is limited
       
   656             QVERIFY(session.interface().isValid());
       
   657 #endif
       
   658         } else {
       
   659             QFAIL("Timeout waiting for session to open.");
       
   660         }
       
   661     }
       
   662 
       
   663     sessionOpenedSpy.clear();
       
   664     sessionClosedSpy.clear();
       
   665     stateChangedSpy.clear();
       
   666     errorSpy.clear();
       
   667 
       
   668     QNetworkSession session2(configuration);
       
   669 
       
   670     QSignalSpy sessionOpenedSpy2(&session2, SIGNAL(opened()));
       
   671     QSignalSpy sessionClosedSpy2(&session2, SIGNAL(closed()));
       
   672     QSignalSpy stateChangedSpy2(&session2, SIGNAL(stateChanged(QNetworkSession::State)));
       
   673     QSignalSpy errorSpy2(&session2, SIGNAL(error(QNetworkSession::SessionError)));
       
   674 
       
   675     // Test opening a second session.
       
   676     {
       
   677         QVERIFY(session2.configuration() == configuration);
       
   678         QVERIFY(!session2.isOpen());
       
   679         QVERIFY(session2.state() == QNetworkSession::Connected);
       
   680         QVERIFY(session.error() == QNetworkSession::UnknownSessionError);
       
   681 
       
   682         session2.open();
       
   683 
       
   684         QTRY_VERIFY(!sessionOpenedSpy2.isEmpty() || !errorSpy2.isEmpty());
       
   685 
       
   686         QVERIFY(session.isOpen());
       
   687         QVERIFY(session2.isOpen());
       
   688         QVERIFY(session.state() == QNetworkSession::Connected);
       
   689         QVERIFY(session2.state() == QNetworkSession::Connected);
       
   690 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
       
   691         // On Symbian emulator, the support for data bearers is limited
       
   692         QVERIFY(session.interface().isValid());
       
   693 #endif
       
   694         QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress());
       
   695         QCOMPARE(session.interface().index(), session2.interface().index());
       
   696     }
       
   697 
       
   698     sessionOpenedSpy2.clear();
       
   699 
       
   700     if (forceSessionStop) {
       
   701         // Test forcing the second session to stop the interface.
       
   702         QNetworkSession::State previousState = session.state();
       
   703 #ifdef Q_CC_NOKIAX86
       
   704         // For S60 emulator builds: RConnection::Stop does not work on all Emulators
       
   705         bool expectStateChange = false;
       
   706 #else
       
   707         bool expectStateChange = previousState != QNetworkSession::Disconnected;
       
   708 #endif
       
   709 
       
   710         session2.stop();
       
   711 
       
   712         QTRY_VERIFY(!sessionClosedSpy2.isEmpty() || !errorSpy2.isEmpty());
       
   713 
       
   714         QVERIFY(!session2.isOpen());
       
   715 
       
   716         if (!errorSpy2.isEmpty()) {
       
   717 	    QVERIFY(!errorSpy.isEmpty());
       
   718 
       
   719             // check for SessionAbortedError
       
   720             QNetworkSession::SessionError error =
       
   721                 qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
       
   722             QNetworkSession::SessionError error2 =
       
   723                 qvariant_cast<QNetworkSession::SessionError>(errorSpy2.first().at(0));
       
   724 
       
   725             QVERIFY(error == QNetworkSession::SessionAbortedError);
       
   726             QVERIFY(error2 == QNetworkSession::SessionAbortedError);
       
   727 
       
   728             QCOMPARE(errorSpy.count(), 1);
       
   729             QCOMPARE(errorSpy2.count(), 1);
       
   730 
       
   731             errorSpy.clear();
       
   732             errorSpy2.clear();
       
   733         }
       
   734 
       
   735         QVERIFY(errorSpy.isEmpty());
       
   736         QVERIFY(errorSpy2.isEmpty());
       
   737 
       
   738         if (expectStateChange)
       
   739             QTRY_VERIFY(stateChangedSpy2.count() >= 2 || !errorSpy2.isEmpty());
       
   740 
       
   741         if (!errorSpy2.isEmpty()) {
       
   742             QVERIFY(session2.state() == previousState);
       
   743             QVERIFY(session.state() == previousState);
       
   744 
       
   745             QNetworkSession::SessionError error =
       
   746                 qvariant_cast<QNetworkSession::SessionError>(errorSpy2.first().at(0));
       
   747             if (error == QNetworkSession::OperationNotSupportedError) {
       
   748                 // The session needed to bring down the interface,
       
   749                 // but the operation is not supported.
       
   750                 QSKIP("Configuration does not support stop().", SkipSingle);
       
   751             } else if (error == QNetworkSession::InvalidConfigurationError) {
       
   752                 // The session needed to bring down the interface, but it is not possible for the
       
   753                 // specified configuration.
       
   754                 if ((session.configuration().state() & QNetworkConfiguration::Discovered) ==
       
   755                     QNetworkConfiguration::Discovered) {
       
   756                     QFAIL("Failed to stop session for Discovered configuration.");
       
   757                 } else {
       
   758                     QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle);
       
   759                 }
       
   760             } else {
       
   761                 QFAIL("Error stopping session.");
       
   762             }
       
   763         } else if (!sessionClosedSpy2.isEmpty()) {
       
   764             if (expectStateChange) {
       
   765                 if (configuration.type() == QNetworkConfiguration::ServiceNetwork) {
       
   766                     bool roamedSuccessfully = false;
       
   767 
       
   768                     QCOMPARE(stateChangedSpy2.count(), 4);
       
   769 
       
   770                     QNetworkSession::State state =
       
   771                         qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(0).at(0));
       
   772                     QVERIFY(state == QNetworkSession::Connecting);
       
   773 
       
   774                     state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(1).at(0));
       
   775                     QVERIFY(state == QNetworkSession::Connected);
       
   776 
       
   777                     state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(2).at(0));
       
   778                     QVERIFY(state == QNetworkSession::Closing);
       
   779 
       
   780                     state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(3).at(0));
       
   781                     QVERIFY(state == QNetworkSession::Disconnected);
       
   782                     
       
   783                     QTRY_VERIFY(stateChangedSpy.count() > 0);
       
   784                     state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(0).at(0));
       
   785                     if (state == QNetworkSession::Roaming) {
       
   786                         QTRY_VERIFY(!errorSpy.isEmpty() || stateChangedSpy.count() > 1);
       
   787                         if (stateChangedSpy.count() > 1) {
       
   788                             state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(1).at(0));
       
   789                             if (state == QNetworkSession::Connected) {
       
   790                                 roamedSuccessfully = true;
       
   791                                 QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected);
       
   792                             }
       
   793                         }
       
   794                     }
       
   795                     if (roamedSuccessfully) {
       
   796                         QString configId = session.sessionProperty("ActiveConfiguration").toString();
       
   797                         QNetworkConfiguration config = manager.configurationFromIdentifier(configId); 
       
   798                         QNetworkSession session3(config);
       
   799                         QSignalSpy errorSpy3(&session3, SIGNAL(error(QNetworkSession::SessionError)));
       
   800                         QSignalSpy sessionOpenedSpy3(&session3, SIGNAL(opened()));
       
   801                         
       
   802                         session3.open();
       
   803                         session3.waitForOpened();
       
   804                         
       
   805                         if (session.isOpen())
       
   806                             QVERIFY(!sessionOpenedSpy3.isEmpty() || !errorSpy3.isEmpty());
       
   807                         
       
   808                         session.stop();
       
   809 
       
   810                         QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
       
   811                         QTRY_VERIFY(session3.state() == QNetworkSession::Disconnected);
       
   812                     }
       
   813 #ifndef Q_CC_NOKIAX86
       
   814                     if (!roamedSuccessfully)
       
   815                         QVERIFY(!errorSpy.isEmpty());
       
   816 #endif
       
   817                 } else {
       
   818                     QCOMPARE(stateChangedSpy2.count(), 2);
       
   819 
       
   820                     QNetworkSession::State state =
       
   821                         qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(0).at(0));
       
   822                     QVERIFY(state == QNetworkSession::Closing);
       
   823 
       
   824                     state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(1).at(0));
       
   825                     QVERIFY(state == QNetworkSession::Disconnected);
       
   826                 }
       
   827 
       
   828                 QTRY_VERIFY(!sessionClosedSpy.isEmpty());
       
   829                 QVERIFY(session.state() == QNetworkSession::Disconnected);
       
   830                 QVERIFY(session2.state() == QNetworkSession::Disconnected);
       
   831             }
       
   832 
       
   833             QVERIFY(errorSpy2.isEmpty());
       
   834 
       
   835             ++inProcessSessionManagementCount;
       
   836         } else {
       
   837             QFAIL("Timeout waiting for session to stop.");
       
   838         }
       
   839 
       
   840 #ifndef Q_CC_NOKIAX86
       
   841         QVERIFY(!sessionClosedSpy.isEmpty());
       
   842 #endif
       
   843         QVERIFY(!sessionClosedSpy2.isEmpty());
       
   844 
       
   845 #ifndef Q_CC_NOKIAX86
       
   846         QVERIFY(!session.isOpen());
       
   847 #endif
       
   848         QVERIFY(!session2.isOpen());
       
   849     } else {
       
   850         // Test closing the second session.
       
   851         {
       
   852             int stateChangedCountBeforeClose = stateChangedSpy2.count();
       
   853             session2.close();
       
   854 
       
   855             QTRY_VERIFY(!sessionClosedSpy2.isEmpty());
       
   856 #ifndef Q_CC_NOKIAX86        
       
   857             QVERIFY(stateChangedSpy2.count() == stateChangedCountBeforeClose);
       
   858 #endif        
       
   859 
       
   860             QVERIFY(sessionClosedSpy.isEmpty());
       
   861 
       
   862             QVERIFY(session.isOpen());
       
   863             QVERIFY(!session2.isOpen());
       
   864             QVERIFY(session.state() == QNetworkSession::Connected);
       
   865             QVERIFY(session2.state() == QNetworkSession::Connected);
       
   866 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
       
   867             // On Symbian emulator, the support for data bearers is limited
       
   868             QVERIFY(session.interface().isValid());
       
   869 #endif
       
   870             QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress());
       
   871             QCOMPARE(session.interface().index(), session2.interface().index());
       
   872         }
       
   873 
       
   874         sessionClosedSpy2.clear();
       
   875 
       
   876         // Test closing the first session.
       
   877         {
       
   878 #ifdef Q_CC_NOKIAX86
       
   879             // For S60 emulator builds: RConnection::Close does not actually
       
   880             //                          close network connection on all Emulators
       
   881             bool expectStateChange = false;
       
   882 #else
       
   883             bool expectStateChange = session.state() != QNetworkSession::Disconnected &&
       
   884                                      manager.capabilities() & QNetworkConfigurationManager::SystemSessionSupport;
       
   885 #endif
       
   886 
       
   887             session.close();
       
   888 
       
   889             QTRY_VERIFY(!sessionClosedSpy.isEmpty() || !errorSpy.isEmpty());
       
   890 
       
   891             QVERIFY(!session.isOpen());
       
   892 
       
   893             if (expectStateChange)
       
   894                 QTRY_VERIFY(!stateChangedSpy.isEmpty() || !errorSpy.isEmpty());
       
   895 
       
   896             if (!errorSpy.isEmpty()) {
       
   897                 QNetworkSession::SessionError error =
       
   898                     qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
       
   899                 if (error == QNetworkSession::OperationNotSupportedError) {
       
   900                     // The session needed to bring down the interface,
       
   901                     // but the operation is not supported.
       
   902                     QSKIP("Configuration does not support close().", SkipSingle);
       
   903                 } else if (error == QNetworkSession::InvalidConfigurationError) {
       
   904                     // The session needed to bring down the interface, but it is not possible for the
       
   905                     // specified configuration.
       
   906                     if ((session.configuration().state() & QNetworkConfiguration::Discovered) ==
       
   907                         QNetworkConfiguration::Discovered) {
       
   908                         QFAIL("Failed to close session for Discovered configuration.");
       
   909                     } else {
       
   910                         QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle);
       
   911                     }
       
   912                 } else {
       
   913                     QFAIL("Error closing session.");
       
   914                 }
       
   915             } else if (!sessionClosedSpy.isEmpty()) {
       
   916                 QVERIFY(sessionOpenedSpy.isEmpty());
       
   917                 QCOMPARE(sessionClosedSpy.count(), 1);
       
   918                 if (expectStateChange)
       
   919                     QVERIFY(!stateChangedSpy.isEmpty());
       
   920                 QVERIFY(errorSpy.isEmpty());
       
   921 
       
   922                 if (expectStateChange)
       
   923                     QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
       
   924 
       
   925                 ++inProcessSessionManagementCount;
       
   926             } else {
       
   927                 QFAIL("Timeout waiting for session to close.");
       
   928             }
       
   929         }
       
   930     }
       
   931 }
       
   932 
       
   933 QDebug operator<<(QDebug debug, const QList<QNetworkConfiguration> &list)
       
   934 {
       
   935     debug.nospace() << "( ";
       
   936     foreach (const QNetworkConfiguration &config, list)
       
   937         debug.nospace() << config.identifier() << ", ";
       
   938     debug.nospace() << ")\n";
       
   939     return debug;
       
   940 }
       
   941 
       
   942 // Note: outOfProcessSession requires that at least one configuration is
       
   943 // at Discovered -state.
       
   944 void tst_QNetworkSession::outOfProcessSession()
       
   945 {
       
   946 #if defined(Q_OS_SYMBIAN) && defined(__WINS__)
       
   947     QSKIP("Symbian emulator does not support two [QR]PRocesses linking a dll (QtBearer.dll) with global writeable static data.", SkipAll);
       
   948 #endif
       
   949     QNetworkConfigurationManager manager;
       
   950     // Create a QNetworkConfigurationManager to detect configuration changes made in Lackey. This
       
   951     // is actually the essence of this testcase - to check that platform mediates/reflects changes
       
   952     // regardless of process boundaries. The interprocess communication is more like a way to get
       
   953     // this test-case act correctly and timely.
       
   954     QList<QNetworkConfiguration> before = manager.allConfigurations(QNetworkConfiguration::Active);
       
   955     QSignalSpy spy(&manager, SIGNAL(configurationChanged(QNetworkConfiguration)));
       
   956 
       
   957     // Cannot read/write to processes on WinCE or Symbian.
       
   958     // Easiest alternative is to use sockets for IPC.
       
   959     QLocalServer oopServer;
       
   960     // First remove possible earlier listening address which would cause listen to fail 
       
   961     // (e.g. previously abruptly ended unit test might cause this)
       
   962     QLocalServer::removeServer("tst_qnetworksession");
       
   963     oopServer.listen("tst_qnetworksession");
       
   964 
       
   965     QProcess lackey;
       
   966     lackey.start("qnetworksessionlackey");
       
   967     QVERIFY(lackey.waitForStarted());
       
   968 
       
   969     QVERIFY(oopServer.waitForNewConnection(-1));
       
   970     QLocalSocket *oopSocket = oopServer.nextPendingConnection();
       
   971 
       
   972     do {
       
   973         QByteArray output;
       
   974 
       
   975         if(oopSocket->waitForReadyRead()) {
       
   976             output = oopSocket->readLine().trimmed();
       
   977         }
       
   978 
       
   979         if (output.startsWith("Started session ")) {
       
   980             QString identifier = QString::fromLocal8Bit(output.mid(20).constData());
       
   981             QNetworkConfiguration changed;
       
   982 
       
   983             do {
       
   984                 QTRY_VERIFY(!spy.isEmpty());
       
   985                 changed = qvariant_cast<QNetworkConfiguration>(spy.takeFirst().at(0));
       
   986             } while (changed.identifier() != identifier);
       
   987 
       
   988             QVERIFY((changed.state() & QNetworkConfiguration::Active) ==
       
   989                     QNetworkConfiguration::Active);
       
   990 
       
   991             QVERIFY(!before.contains(changed));
       
   992 
       
   993             QList<QNetworkConfiguration> after =
       
   994                 manager.allConfigurations(QNetworkConfiguration::Active);
       
   995 
       
   996             QVERIFY(after.contains(changed));
       
   997 
       
   998             spy.clear();
       
   999 
       
  1000             oopSocket->write("stop\n");
       
  1001             oopSocket->waitForBytesWritten();
       
  1002 
       
  1003             do {
       
  1004                 QTRY_VERIFY(!spy.isEmpty());
       
  1005 
       
  1006                 changed = qvariant_cast<QNetworkConfiguration>(spy.takeFirst().at(0));
       
  1007             } while (changed.identifier() != identifier);
       
  1008 
       
  1009             QVERIFY((changed.state() & QNetworkConfiguration::Active) !=
       
  1010                     QNetworkConfiguration::Active);
       
  1011 
       
  1012             QList<QNetworkConfiguration> afterStop =
       
  1013                     manager.allConfigurations(QNetworkConfiguration::Active);
       
  1014 
       
  1015             QVERIFY(!afterStop.contains(changed));
       
  1016 
       
  1017             oopSocket->disconnectFromServer();
       
  1018             oopSocket->waitForDisconnected(-1);
       
  1019 
       
  1020             lackey.waitForFinished();
       
  1021         }
       
  1022     // This is effected by QTBUG-4903, process will always report as running
       
  1023     //} while (lackey.state() == QProcess::Running);
       
  1024 
       
  1025     // Workaround: the socket in the lackey will disconnect on exit
       
  1026     } while (oopSocket->state() == QLocalSocket::ConnectedState);
       
  1027 
       
  1028     switch (lackey.exitCode()) {
       
  1029     case 0:
       
  1030         qDebug("Lackey returned exit success (0)");
       
  1031         break;
       
  1032     case 1:
       
  1033         QSKIP("No discovered configurations found.", SkipAll);
       
  1034     case 2:
       
  1035         QSKIP("Lackey could not start session.", SkipAll);
       
  1036     default:
       
  1037         QSKIP("Lackey failed", SkipAll);
       
  1038     }
       
  1039 }
       
  1040 
       
  1041 // A convinience / helper function for testcases. Return the first matching configuration.
       
  1042 // Ignores configurations in other than 'discovered' -state. Returns invalid (QNetworkConfiguration())
       
  1043 // if none found.
       
  1044 QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfiguration::Type configType) {
       
  1045     // Refresh configurations and derive configurations matching given parameters.
       
  1046     QNetworkConfigurationManager mgr;
       
  1047     QSignalSpy updateSpy(&mgr, SIGNAL(updateCompleted()));
       
  1048     mgr.updateConfigurations();
       
  1049     QTRY_NOOP(updateSpy.count() == 1);
       
  1050     if (updateSpy.count() != 1) {
       
  1051         qDebug("tst_QNetworkSession::suitableConfiguration() failure: unable to update configurations");
       
  1052         return QNetworkConfiguration();
       
  1053     }
       
  1054     QList<QNetworkConfiguration> discoveredConfigs = mgr.allConfigurations(QNetworkConfiguration::Discovered);
       
  1055     foreach(QNetworkConfiguration config, discoveredConfigs) {
       
  1056         if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
       
  1057             // qDebug() << "Dumping config because is active: " << config.name();
       
  1058             discoveredConfigs.removeOne(config);
       
  1059         } else if (config.type() != configType) {
       
  1060             // qDebug() << "Dumping config because type (IAP/SNAP) mismatches: " << config.name();
       
  1061             discoveredConfigs.removeOne(config);
       
  1062         } else if ((config.type() == QNetworkConfiguration::InternetAccessPoint) &&
       
  1063                     bearerType == "cellular") { // 'cellular' bearertype is for convinience
       
  1064             if (config.bearerName() != "2G" &&
       
  1065                 config.bearerName() != "CDMA2000" &&
       
  1066                 config.bearerName() != "WCDMA" &&
       
  1067                 config.bearerName() != "HSPA") {
       
  1068                 // qDebug() << "Dumping config because bearer mismatches (cellular): " << config.name();
       
  1069                 discoveredConfigs.removeOne(config);
       
  1070             }
       
  1071         } else if ((config.type() == QNetworkConfiguration::InternetAccessPoint) && 
       
  1072                     bearerType != config.bearerName()) {
       
  1073             // qDebug() << "Dumping config because bearer mismatches (WLAN): " << config.name();
       
  1074             discoveredConfigs.removeOne(config);
       
  1075         }
       
  1076     }
       
  1077     if (discoveredConfigs.isEmpty()) {
       
  1078         qDebug("tst_QNetworkSession::suitableConfiguration() failure: no suitable configurations present.");
       
  1079         return QNetworkConfiguration();
       
  1080     } else {
       
  1081         return discoveredConfigs.first();
       
  1082     }
       
  1083 }
       
  1084 
       
  1085 // A convinience function for test-cases: opens the given configuration and return
       
  1086 // true if it was done gracefully.
       
  1087 bool openSession(QNetworkSession *session) {
       
  1088     QNetworkConfigurationManager mgr;
       
  1089     QSignalSpy openedSpy(session, SIGNAL(opened()));
       
  1090     QSignalSpy stateChangeSpy(session, SIGNAL(stateChanged(QNetworkSession::State)));
       
  1091     QSignalSpy errorSpy(session, SIGNAL(error(QNetworkSession::SessionError)));
       
  1092     QSignalSpy configChangeSpy(&mgr, SIGNAL(configurationChanged(QNetworkConfiguration)));
       
  1093     // Store some initial statuses, because expected signals differ if the config is already
       
  1094     // active by some other session
       
  1095     QNetworkConfiguration::StateFlags configInitState = session->configuration().state();
       
  1096     QNetworkSession::State sessionInitState = session->state();
       
  1097 
       
  1098     if (session->isOpen() ||
       
  1099         !session->sessionProperty("ActiveConfiguration").toString().isEmpty()) {
       
  1100         qDebug("tst_QNetworkSession::openSession() failure: session was already open / active.");
       
  1101         return false;
       
  1102     } else {
       
  1103         session->open();
       
  1104         session->waitForOpened(120000); // Bringing interfaces up and down may take time at platform
       
  1105     }
       
  1106     // Check that connection opening went by the book. Add checks here if more strictness needed.
       
  1107     if (!session->isOpen()) {
       
  1108         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::open() failed.");
       
  1109         return false;
       
  1110     }
       
  1111     if (openedSpy.count() != 1) {
       
  1112         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::opened() - signal not received.");
       
  1113         return false;
       
  1114     }
       
  1115     if (!errorSpy.isEmpty()) {
       
  1116         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::error() - signal was detected.");
       
  1117         return false;
       
  1118     }
       
  1119     if (sessionInitState != QNetworkSession::Connected && 
       
  1120         stateChangeSpy.isEmpty()) {
       
  1121         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::stateChanged() - signals not detected.");
       
  1122         return false;
       
  1123     }
       
  1124     if (configInitState != QNetworkConfiguration::Active && 
       
  1125         configChangeSpy.isEmpty()) {
       
  1126         qDebug("tst_QNetworkSession::openSession() failure: QNetworkConfigurationManager::configurationChanged() - signals not detected.");
       
  1127         return false;
       
  1128     }
       
  1129     if (session->configuration().state() != QNetworkConfiguration::Active) {
       
  1130         qDebug("tst_QNetworkSession::openSession() failure: session's configuration is not in 'Active' -state.");
       
  1131         return false;
       
  1132     }
       
  1133     return true;
       
  1134 }
       
  1135 
       
  1136 // Helper function for closing opened session. Performs checks that 
       
  1137 // session is closed gradefully (e.g. signals). Function does not delete
       
  1138 // the session. The lastSessionOnConfiguration (true by default) is used to
       
  1139 // tell if there are more sessions open, basing on same configration. This 
       
  1140 // impacts the checks made.
       
  1141 bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration) {
       
  1142     if (!session) {
       
  1143         qDebug("tst_QNetworkSession::closeSession() failure: NULL session given");
       
  1144         return false;
       
  1145     }
       
  1146     if (session->state() != QNetworkSession::Connected || 
       
  1147         !session->isOpen()) {
       
  1148         qDebug("tst_QNetworkSession::closeSession() failure: session is not opened.");
       
  1149         return false;
       
  1150     }    
       
  1151     QNetworkConfigurationManager mgr;
       
  1152     QSignalSpy sessionClosedSpy(session, SIGNAL(closed()));
       
  1153     QSignalSpy sessionStateChangedSpy(session, SIGNAL(stateChanged(QNetworkSession::State)));
       
  1154     QSignalSpy sessionErrorSpy(session, SIGNAL(error(QNetworkSession::SessionError)));
       
  1155     QSignalSpy configChangeSpy(&mgr, SIGNAL(configurationChanged(QNetworkConfiguration)));
       
  1156     
       
  1157     session->close();
       
  1158     
       
  1159     if (!sessionErrorSpy.isEmpty()) {
       
  1160         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::error() received.");
       
  1161         return false;
       
  1162     }
       
  1163     if (sessionClosedSpy.count() != 1) {
       
  1164         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::closed() signal not received.");
       
  1165         return false;
       
  1166     }
       
  1167     if (lastSessionOnConfiguration && 
       
  1168         sessionStateChangedSpy.isEmpty()) {
       
  1169         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::stateChanged() signals not received.");
       
  1170         return false;
       
  1171     }
       
  1172     if (lastSessionOnConfiguration &&
       
  1173         session->state() != QNetworkSession::Disconnected) {
       
  1174         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession is not in Disconnected -state");
       
  1175         return false;
       
  1176     }
       
  1177     QTRY_NOOP(!configChangeSpy.isEmpty());
       
  1178     if (lastSessionOnConfiguration &&
       
  1179         configChangeSpy.isEmpty()) {
       
  1180         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkConfigurationManager::configurationChanged() - signal not detected.");
       
  1181         return false;
       
  1182     }
       
  1183     if (lastSessionOnConfiguration &&
       
  1184         session->configuration().state() != QNetworkConfiguration::Discovered) {
       
  1185          qDebug("tst_QNetworkSession::closeSession() failure: session's configuration is not back in 'Discovered' -state.");
       
  1186          return false;
       
  1187     }
       
  1188     return true;
       
  1189 }
       
  1190 
       
  1191 
       
  1192 
       
  1193 QTEST_MAIN(tst_QNetworkSession)
       
  1194 
       
  1195 #include "tst_qnetworksession.moc"
       
  1196