From 2faa2ff804a8ed4e0bb60a4d11cd424a0e160dc8 Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Fri, 11 Jun 2010 13:03:19 +1000 Subject: Cherry pick fix for MOBILITY-1063 from Qt Mobility. 37ad80914f7acb8d4f3364d78e75d48cd14e8e2a --- .../bearer/symbian/qnetworksession_impl.cpp | 69 +++++------------- .../qnetworksession/test/tst_qnetworksession.cpp | 84 ++++++++++++++++++++-- 2 files changed, 96 insertions(+), 57 deletions(-) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 940281c..cce8095 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -83,9 +83,6 @@ QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() delete ipConnectionNotifier; ipConnectionNotifier = NULL; - // Cancel possible RConnection::Start() - Cancel(); - #ifdef SNAP_FUNCTIONALITY_AVAILABLE if (iMobility) { delete iMobility; @@ -93,7 +90,8 @@ QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() } #endif - iConnection.Close(); + // Cancel possible RConnection::Start() + Cancel(); iSocketServ.Close(); // Close global 'Open C' RConnection @@ -366,44 +364,6 @@ void QNetworkSessionPrivateImpl::open() } if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { - // Search through existing connections. - // If there is already connection which matches to given IAP - // try to attach to existing connection. - TBool connected(EFalse); - TConnectionInfoBuf connInfo; - TUint count; - if (iConnection.EnumerateConnections(count) == KErrNone) { - for (TUint i=1; i<=count; i++) { - // Note: GetConnectionInfo expects 1-based index. - if (iConnection.GetConnectionInfo(i, connInfo) == KErrNone) { - SymbianNetworkConfigurationPrivate *symbianConfig = - toSymbianConfig(privateConfiguration(publicConfig)); - - if (connInfo().iIapId == symbianConfig->numericIdentifier()) { - if (iConnection.Attach(connInfo, RConnection::EAttachTypeNormal) == KErrNone) { - activeConfig = publicConfig; -#ifndef QT_NO_NETWORKINTERFACE - activeInterface = interface(symbianConfig->numericIdentifier()); -#endif - connected = ETrue; - startTime = QDateTime::currentDateTime(); - // Use name of the IAP to open global 'Open C' RConnection - QByteArray nameAsByteArray = publicConfig.name().toUtf8(); - ifreq ifr; - memset(&ifr, 0, sizeof(struct ifreq)); - strcpy(ifr.ifr_name, nameAsByteArray.constData()); - error = setdefaultif(&ifr); - isOpen = true; - // Make sure that state will be Connected - newState(QNetworkSession::Connected); - emit quitPendingWaitsForOpened(); - break; - } - } - } - } - } - if (!connected) { SymbianNetworkConfigurationPrivate *symbianConfig = toSymbianConfig(privateConfiguration(publicConfig)); @@ -429,7 +389,6 @@ void QNetworkSessionPrivateImpl::open() SetActive(); } newState(QNetworkSession::Connecting); - } } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { SymbianNetworkConfigurationPrivate *symbianConfig = toSymbianConfig(privateConfiguration(publicConfig)); @@ -508,15 +467,16 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) << "close() called, session state is: " << state << " and isOpen is : " << isOpen; #endif - if (!isOpen) { + + if (!isOpen && state != QNetworkSession::Connecting) { return; } // Mark this session as closed-by-user so that we are able to report // distinguish between stop() and close() state transitions // when reporting. iClosedByUser = true; - isOpen = false; + #ifndef OCC_FUNCTIONALITY_AVAILABLE // On Symbian^3 we need to keep track of active configuration longer // in case of empty-SNAP-triggered EasyWLAN. @@ -524,7 +484,6 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) #endif serviceConfig = QNetworkConfiguration(); - Cancel(); #ifdef SNAP_FUNCTIONALITY_AVAILABLE if (iMobility) { delete iMobility; @@ -538,7 +497,7 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) iHandleStateNotificationsFromManager = true; } - iConnection.Close(); + Cancel(); // closes iConnection iSocketServ.Close(); // Close global 'Open C' RConnection. If OpenC supports, @@ -551,11 +510,20 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) setdefaultif(0); } - if (publicConfig.type() == QNetworkConfiguration::UserChoice) { + // If UserChoice, go down immediately. If some other configuration, + // go down immediately if there is no reports expected from the platform; + // in practice Connection Monitor is aware of connections only after + // KFinishedSelection event, and hence reports only after that event, but + // that does not seem to be trusted on all Symbian versions --> safest + // to go down. + if (publicConfig.type() == QNetworkConfiguration::UserChoice || state == QNetworkSession::Connecting) { +#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG + qDebug() << "QNS this : " << QString::number((uint)this) << " - " + << "going Disconnected because session was Connecting."; +#endif newState(QNetworkSession::Closing); newState(QNetworkSession::Disconnected); } - if (allowSignals) { emit closed(); } @@ -755,7 +723,7 @@ void QNetworkSessionPrivateImpl::Error(TInt /*aError*/) { #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " - << "roaming Error() occured"; + << "roaming Error() occured, isOpen is: " << isOpen; #endif if (isOpen) { isOpen = false; @@ -1361,7 +1329,6 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne case KFinishedSelection: if (aError == KErrNone) { - // The user successfully selected an IAP to be used break; } else diff --git a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp index e4f2486..e4b8c14 100644 --- a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp +++ b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp @@ -75,17 +75,20 @@ private slots: void robustnessBombing(); + void sessionClosing_data(); + void sessionClosing(); + void outOfProcessSession(); void invalidSession(); void repeatedOpenClose_data(); void repeatedOpenClose(); - - void roamingErrorCodes(); - + void sessionStop_data(); void sessionStop(); + void roamingErrorCodes(); + void sessionProperties_data(); void sessionProperties(); @@ -131,6 +134,7 @@ void tst_QNetworkSession::initTestCase() // If you wish to skip tests, set value as false. This is often very convinient because tests are so lengthy. // Better way still would be to make this readable from a file. testsToRun["robustnessBombing"] = true; + testsToRun["sessionClosing"] = true; testsToRun["outOfProcessSession"] = true; testsToRun["invalidSession"] = true; testsToRun["repeatedOpenClose"] = true; @@ -265,6 +269,53 @@ void tst_QNetworkSession::robustnessBombing() testSession.reject(); } +void tst_QNetworkSession::sessionClosing_data() { + QTest::addColumn("bearerType"); + QTest::addColumn("configurationType"); + + QTest::newRow("WLAN_IAP") << "WLAN" << QNetworkConfiguration::InternetAccessPoint; + QTest::newRow("Cellular_IAP") << "cellular" << QNetworkConfiguration::InternetAccessPoint; + QTest::newRow("SNAP") << "bearer_type_not_relevant_with_SNAPs" << QNetworkConfiguration::ServiceNetwork; +} + +// Testcase for closing the session at unexpected times +void tst_QNetworkSession::sessionClosing() +{ + if (!testsToRun["sessionClosing"]) { + QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll); + } + QFETCH(QString, bearerType); + QFETCH(QNetworkConfiguration::Type, configurationType); + + // Update configurations so that WLANs are discovered too. + updateConfigurations(); + + // First check that opening once succeeds and determine if test is doable + QNetworkConfiguration config = suitableConfiguration(bearerType, configurationType); + if (!config.isValid()) { + QSKIP("No suitable configurations, skipping this round of repeated open-close test.", SkipSingle); + } + qDebug() << "Using following configuration to bomb with close(): " << config.name(); + QNetworkSession session(config); + if (!openSession(&session) || + !closeSession(&session)) { + QSKIP("Unable to open/close session, skipping this round of close() bombing.", SkipSingle); + } + + qDebug() << "Closing without issuing open()"; + session.close(); + + for (int i = 0; i < 25; i++) { + qDebug() << "Opening and then waiting: " << i * 100 << " ms before closing."; + session.open(); + QTest::qWait(i*100); + session.close(); + // Sooner or later session must end in Disconnected state, + // no matter what the phase was. + QTRY_VERIFY(session.state() == QNetworkSession::Disconnected); + QTest::qWait(200); // Give platform a breathe, otherwise we'll be catching other errors + } +} void tst_QNetworkSession::invalidSession() { @@ -1060,15 +1111,27 @@ void tst_QNetworkSession::sessionOpenCloseStop() QTRY_VERIFY(stateChangedSpy.count() > 0); state = qvariant_cast(stateChangedSpy.at(stateChangedSpy.count() - 1).at(0)); + for (int i = 0; i < stateChangedSpy.count(); i++) { + QNetworkSession::State state_temp = + qvariant_cast(stateChangedSpy.at(i).at(0)); + // Extra debug because a fragile point in testcase because statuses vary. + qDebug() << "------- Statechange spy at: " << i << " is " << state_temp; + } + if (state == QNetworkSession::Roaming) { QTRY_VERIFY(session.state() == QNetworkSession::Connected); QTRY_VERIFY(session2.state() == QNetworkSession::Connected); roamedSuccessfully = true; + } else if (state == QNetworkSession::Closing) { + QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected); + QTRY_VERIFY(session.state() == QNetworkSession::Connected); + roamedSuccessfully = true; } else if (state == QNetworkSession::Disconnected) { QTRY_VERIFY(!errorSpy.isEmpty()); QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected); } else if (state == QNetworkSession::Connected) { QTRY_VERIFY(errorSpy.isEmpty()); + if (stateChangedSpy.count() > 1) { state = qvariant_cast(stateChangedSpy.at(stateChangedSpy.count() - 2).at(0)); QVERIFY(state == QNetworkSession::Roaming); @@ -1102,9 +1165,18 @@ void tst_QNetworkSession::sessionOpenCloseStop() QVERIFY(state == QNetworkSession::Closing); state = qvariant_cast(stateChangedSpy2.at(1).at(0)); QVERIFY(state == QNetworkSession::Disconnected); - } else { // Assume .count() == 1 - QCOMPARE(stateChangedSpy2.count(), 1); - QNetworkSession::State state = qvariant_cast(stateChangedSpy2.at(0).at(0)); + } else { + QVERIFY(stateChangedSpy2.count() >= 1); + + for (int i = 0; i < stateChangedSpy2.count(); i++) { + QNetworkSession::State state_temp = + qvariant_cast(stateChangedSpy2.at(i).at(0)); + // Extra debug because a fragile point in testcase. + qDebug() << "+++++ Statechange spy at: " << i << " is " << state_temp; + } + + QNetworkSession::State state = + qvariant_cast(stateChangedSpy2.at(stateChangedSpy2.count() - 1).at(0)); // Symbian version dependant. QVERIFY(state == QNetworkSession::Disconnected); } -- cgit v0.12