email/pop3andsmtpmtm/servermtmutils/test/src/T_IMSK02.cpp
changeset 0 72b543305e3a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/email/pop3andsmtpmtm/servermtmutils/test/src/T_IMSK02.cpp	Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,399 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// The purpose of this test harness is to test a fix for INC37442.
+// In order to test this, it is necessary to start 2 connections to the same IAP off and then
+// cancel one of them. This must be done before the CImConnect has finished connecting.
+// 
+//
+
+
+#include "TESTENV.h"
+#include <nd_err.h>
+
+#include <imsk.h>
+
+#include <s32mem.h>
+#include <s32file.h>
+#include <iapprefs.h>
+#include "emailtestutils.h"
+#include <commdb.h>
+
+
+LOCAL_D RTest test(_L("IMSK Multiple CImTextServerSessions Test"));
+
+LOCAL_D CTrapCleanup* theCleanup;
+LOCAL_D RFs theFs;
+LOCAL_D CActiveScheduler* scheduler;
+LOCAL_D CEmailTestUtils* testUtils;
+
+// Test Harness Prototypes
+LOCAL_C void DoTestThreadWorkL();
+static TInt DoTestThreadStart(TAny*);
+
+// Foward declare
+class CMsgConnect;
+CMsgConnect* gConnect;
+
+
+// we use a freeserve account;
+// this will need to be set up as COMMDB_ID 1 in the cdbv3.dat file
+_LIT(KServerAddressConn0, "pop.freeserve.net");
+_LIT(KServerAddressConn1, "www.guardian.co.uk");
+const TInt KPortNumber = 110;
+
+const TInt KConnectingProgressValue = 2500;
+const TInt KConnectionMadeProgressValue = 7000;
+
+
+// create an active object to connect
+class CMsgConnect : public CActive
+	{
+	public:
+		static CMsgConnect* NewLC(TInt aConn);
+		~CMsgConnect();
+
+	public:		// CActive
+		void RunL();
+		void DoCancel();
+
+	public:
+		void RequestConnectL();
+		void CancelConnectL();
+		TInt ConnectProgress();
+		TInt GetIAPValue(TUint32 &aIAP);
+		TInt GetIAPBearer(TUint32 &aBearer);
+
+	private:
+		CMsgConnect(TInt aConn);
+		void ConstructL();
+
+	private:
+		CImTextServerSession*	iImSocket;
+		CImIAPPreferences*		iIAPPreferences;
+		TInt					iConn;
+	};
+
+
+CMsgConnect::CMsgConnect(TInt aConn)
+:CActive(EPriorityNormal),
+ iConn(aConn)
+	{
+	}
+
+CMsgConnect* CMsgConnect::NewLC(TInt aConn)
+	{
+	CMsgConnect* self = new (ELeave) CMsgConnect(aConn);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+void CMsgConnect::ConstructL()
+	{
+	CActiveScheduler::Add(this); // add to active scheduler
+	iImSocket = CImTextServerSession::NewL();
+	testUtils->WriteComment(_L("CMsgConnect::ConstructL() OK"));
+	}
+
+CMsgConnect::~CMsgConnect()
+	{
+	Cancel();
+	delete iImSocket;
+	delete iIAPPreferences;
+	}
+
+void CMsgConnect::DoCancel()
+	{
+	iImSocket->Cancel();
+	}
+
+void CMsgConnect::RunL()
+	{
+	testUtils->WriteComment(_L("CMsgConnect::RunL() start"));
+
+	// if we have cancelled the connection, then the value here will be KErrCancel
+	if(iStatus.Int() == KErrCancel)
+		{
+		testUtils->WriteComment(_L("CMsgConnect - connection cancelled"));
+		test.Printf(_L("cancelled"));
+		return;
+		}
+
+	testUtils->WriteComment(_L("CMsgConnect - connection made"));
+	// if we've connected, then say so
+	test.Printf(_L("connected"));
+	CActiveScheduler::Stop();
+	}
+
+void CMsgConnect::RequestConnectL()
+	{
+	testUtils->WriteComment(_L("CMsgConnect::RequestConnectL() start"));
+	test.Next(_L("connecting"));
+
+	iIAPPreferences = CImIAPPreferences::NewLC();		// PUSH		(there is not a NewL() function)
+	CleanupStack::Pop(iIAPPreferences);					// POP
+
+	TImIAPChoice iap;
+	iap.iIAP = 1;		// COMMDB_ID 1
+	iap.iDialogPref = ECommDbDialogPrefDoNotPrompt;
+	iIAPPreferences->AddIAPL(iap);
+
+	TBuf<32> serverAddress;
+	if(iConn == 0)
+		serverAddress = KServerAddressConn0;
+	else
+		serverAddress = KServerAddressConn1;
+
+	testUtils->WriteComment(_L("CMsgConnect - queuing connect with CImTextServerSesison"));
+	iImSocket->QueueConnectL(iStatus, serverAddress, KPortNumber, *iIAPPreferences);
+	SetActive();
+	}
+
+void CMsgConnect::CancelConnectL()
+	{
+	testUtils->WriteComment(_L("CMsgConnect cancelling connection"));
+	test.Next(_L("Cancel connecting"));
+	iImSocket->Disconnect();
+	}
+
+TInt CMsgConnect::ConnectProgress()
+	{
+	return iImSocket->GetConnectionStage();
+	}
+
+TInt CMsgConnect::GetIAPValue(TUint32 &aIAP)
+	{
+	return iImSocket->GetIAPValue(aIAP);
+	}
+
+TInt CMsgConnect::GetIAPBearer(TUint32 &aBearer)
+	{
+	return iImSocket->GetIAPBearer(aBearer);
+	}
+
+//
+
+LOCAL_C void Init()
+	{
+	scheduler = new (ELeave) CActiveScheduler;
+	CActiveScheduler::Install(scheduler);
+
+	User::LeaveIfError(theFs.Connect());
+
+	// set up the log file
+	testUtils = CEmailTestUtils::NewLC(test);
+	testUtils->TestStart(0);
+	testUtils->SetLogToFile(ETrue);
+	testUtils->WriteComment(_L("This tests a change to CImConnect so that it no longer calls iConn.Stop()"));
+	testUtils->WriteComment(_L("in its DoCancel(), but iConn.Close() instead."));
+	testUtils->WriteComment(_L("This should not cancel other connections to the internet using that IAP."));
+	testUtils->WriteComment(_L("\n"));
+	}
+
+LOCAL_C void Closedown()
+	{
+	testUtils->TestHarnessCompleted();
+	CleanupStack::PopAndDestroy(testUtils);
+
+	theFs.Close();
+	delete scheduler;
+	}
+// This tests the change made for "INC040630 - Panic while disconnecting a 
+// service". Calling CImTextServerSession::GetConnectionStage with a cancelled
+// RConnection caused a panic.
+LOCAL_C void TestCancelWithProgress()
+	{
+	_LIT(KTestThreadName, "CancelWithProgress Test Thread");
+	const TInt KMinTestHeapSize = 0x10000;
+    const TInt KMaxTestHeapSize = 0x100000;
+
+	TRequestStatus requestStatus;
+	RThread testThread;
+
+	gConnect = CMsgConnect::NewLC(0);	// PUSH	
+
+	User::SetJustInTime(EFalse);
+
+	// Set up the conditions which cause the panic. I.e. request a connection
+	// then cancel it.
+	gConnect->RequestConnectL();
+
+	// Call GetConnectionStage, GetIAPValue, and GetIAPBearer to ensure they
+	// return the correct results.
+	TUint32 bearer = 1;
+	TUint32 iap = 1;
+	TInt returnValue;
+	
+	// Test normal behaviour in this state with a valid but unconnected connection.
+	returnValue = gConnect->GetIAPBearer(bearer);
+	(*testUtils)(returnValue == KErrNotReady);
+	returnValue = gConnect->GetIAPValue(iap);
+	(*testUtils)(returnValue == KErrNone || returnValue == KErrNotReady);
+	(*testUtils)(iap == 1);
+	returnValue = gConnect->ConnectProgress();
+	(*testUtils)(returnValue != KErrBadHandle);
+
+	// Cancel the CImTextServerSession 
+	gConnect->CancelConnectL();
+
+	// Test after cancel.
+	returnValue = gConnect->GetIAPBearer(bearer);
+	// GetIAPBearer now returns KErrBadHandle. 
+	(*testUtils)(returnValue == KErrBadHandle);
+
+	returnValue = gConnect->GetIAPValue(iap);
+	// GetIAPValue now returns KErrBadHandle.
+	(*testUtils)(returnValue == KErrBadHandle);
+
+	// CImConnect::Progress now returns KErrBadHandle.
+	returnValue = gConnect->ConnectProgress();
+	(*testUtils)(returnValue == KErrBadHandle);
+
+	// Create a separate thread to call GetConnectionStage
+	testThread.Create(
+		KTestThreadName, 
+		DoTestThreadStart, // replace
+		KDefaultStackSize, 
+		KMinTestHeapSize, 
+		KMaxTestHeapSize, 
+		NULL, 
+		EOwnerThread);
+	testThread.Logon(requestStatus);
+
+    // Let the thread run
+    testThread.Resume();
+    User::WaitForRequest(requestStatus);
+
+	// Test whether the thread exitied with a panic.
+	TInt result = (testThread.ExitType() == EExitPanic);
+	if (result)
+		testUtils->WriteComment(
+			_L("GetConnectionStage caused panic after Cancel"));
+	// Pass or fail the test based on whether the thread stopped because of a
+	// panic.
+	(*testUtils)(!result);
+    testThread.Close();
+	User::SetJustInTime(ETrue);
+
+	CleanupStack::PopAndDestroy(gConnect);
+	}
+
+LOCAL_C void DoTestThreadWorkL()
+    {
+    CActiveScheduler* scheduler = new (ELeave) CActiveScheduler;
+    CActiveScheduler::Install(scheduler);
+    CleanupStack::PushL(scheduler);
+	// ConnectProgress calls GetConnectionStage in CImTextServerSession.
+	gConnect->ConnectProgress();
+	CleanupStack::PopAndDestroy(scheduler);
+	}
+
+static TInt DoTestThreadStart(TAny*)
+    {
+    // Entry function for the child thread which is created then killed.
+    CTrapCleanup* cleanup = CTrapCleanup::New();
+    test(cleanup != NULL);
+
+    TRAPD(ret, DoTestThreadWorkL());
+    delete cleanup;
+    return 0;
+    }
+
+
+//
+
+LOCAL_C void doMainL()
+	{
+	Init();
+
+	TInt testNo = 1;
+	testUtils->TestStart(testNo);
+	testUtils->WriteComment(
+		_L("Testing calls to CImTextServerSession Cancel then GetConnectionStage"));
+	TestCancelWithProgress();
+	testUtils->TestFinish(testNo);
+	testNo += 1;
+
+	CMsgConnect* connect1 = CMsgConnect::NewLC(0);	// PUSH
+	CMsgConnect* connect2 = CMsgConnect::NewLC(1);	// PUSH
+
+	testUtils->WriteComment(_L("1st connect object connecting"));
+	connect1->RequestConnectL();
+	// wait a while before starting the next connection
+	testUtils->WriteComment(_L("waiting a little while before starting the 2nd connection"));
+	User::After(1000000);
+
+	testUtils->WriteComment(_L("2nd connect object connecting"));
+	connect2->RequestConnectL();
+
+	// we wait until the connect2 is actually connecting,
+	// this is when the progress value = 2500
+	testUtils->WriteComment(_L("we should only cancel the connection when it is connecting"));
+
+	for(TInt a = 0; a < 100; a++)
+		{	
+		// if connect2 has got so far as connecting, then we should fail the test because
+		// this test relies on us cancelling the connection when it is connecting
+		if(connect2->ConnectProgress() == KConnectionMadeProgressValue)
+			{
+			testUtils->WriteComment(_L("connection made before we can cancel it"));
+			testUtils->WriteComment(_L("TEST FAILED"));
+			CleanupStack::PopAndDestroy(2);			// connect2 & connect1
+			Closedown();
+			return;
+			}
+
+		// note that the connect progress could have skipped past the connecting value, whilst we
+		// are waiting for the 1second to pass, so if the progress is higher than the connecting
+		// value, then we should cancel it as well
+		if(connect2->ConnectProgress() > KConnectingProgressValue)
+			{
+			testUtils->WriteComment(_L("cancelling the 2nd connection"));
+			connect2->CancelConnectL();
+			break;
+			}
+		
+		User::After(1000000);
+		}
+	
+	// wait until the 1st one has connected correctly
+	testUtils->WriteComment(_L("wait for the 1st connection object to connect"));
+	CActiveScheduler::Start();
+
+	// cancel the connection of the connection that is up and running
+	testUtils->WriteComment(_L("cancel the 1st connection object"));
+	connect1->CancelConnectL();
+
+	CleanupStack::PopAndDestroy(2);					// connect2 & connect1
+	Closedown();
+	}
+
+
+GLDEF_C TInt E32Main()
+	{
+	test.SetLogged(ETrue);
+	test.Title();
+	test.Start(_L("Testing Multiple connections on one IAP using CImTextServerSession"));
+	__UHEAP_MARK;
+
+	theCleanup=CTrapCleanup::New();
+	test (theCleanup!=NULL);
+	TRAPD(ret,doMainL());
+	test (ret==KErrNone);
+	delete theCleanup;
+
+	__UHEAP_MARKEND;
+	test.End();
+	return 0;
+	}