// Copyright (c) 2002-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:
// This contains ESock Test cases from section 1
// 
//

// EPOC includes
#include <e32base.h>
#include <ss_std.h>

// Test system includes
#include "SocketTestSection1.h"


_LIT(KDummyProtocol1Name,"Dummy Protocol 1"); // corresponds to KDummyOneName in pdummy

// Test step 1.1
const TDesC& CSocketTest1_1::GetTestName()
	{
	_LIT(ret,"Test1.1");
	return ret;
	}

enum TVerdict CSocketTest1_1::InternalDoTestStepL( void )
	{
	TVerdict verdict = EPass;

	Logger().WriteFormat(_L("Test Purpose: Connect and Disconnect"));

	// connect to esock
	Logger().WriteFormat(_L("Attempting to connect to socket server"));
    RSocketServ ss1;
	TInt ret = OptimalConnect(ss1);
	CleanupClosePushL(ss1);
	Logger().WriteFormat(_L("Connect returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);

	Logger().WriteFormat(_L("Closing Session"));
	CleanupStack::Pop(&ss1);
	ss1.Close();

	Logger().WriteFormat(_L("Re-connecting to socket server"));
    RSocketServ ss;
	ret = OptimalConnect(ss);
	CleanupClosePushL(ss);
	Logger().WriteFormat(_L("Connect returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);

	CleanupStack::Pop();
	ss.Close();
 
 	SetTestStepResult(verdict);   
	return verdict;
	}


// Test step 1.2
const TDesC& CSocketTest1_2::GetTestName()
	{
	_LIT(ret,"Test1.2");
	return ret;
	}
	
enum TVerdict CSocketTest1_2::InternalDoTestStepL( void )
	{
	TVerdict verdict = EPass;

	Logger().WriteFormat(_L("Test Purpose: Open and Close Sockets"));

	// connect to esock
	Logger().WriteFormat(_L("Attempting to connect to socket server"));
    RSocketServ ss;
	TInt ret = OptimalConnect(ss);
	CleanupClosePushL(ss);
	Logger().WriteFormat(_L("Connect returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);

	// NumProtocols and GetProtocolInfo
	Logger().WriteFormat(_L("Try NumProtocols"));
//	ss.__DbgMarkHeap();		// in ESOCKMT leak checking is best done by shutting down the server
	TUint numProtocols;
	ret = ss.NumProtocols(numProtocols);
	Logger().WriteFormat(_L("NumProtocols returned %S, number %d"), 
			&EpocErrorToText(ret), numProtocols);
	TESTL(KErrNone == ret);

	TProtocolDesc protoInfo;
	TUint aIndex;
	TBool aFound = false;
	RSocket sock1;
	TInt pdummyIndex = -1;
 	Logger().WriteFormat(_L("Trying GetProtocolInfo until Dummy Protocol 1 is found"));
	for (aIndex=1;aIndex<=numProtocols;aIndex++) 
		{
		ret = ss.GetProtocolInfo(aIndex, protoInfo);
		Logger().WriteFormat(_L("GetProtocolInfo returned %S"), &EpocErrorToText(ret));	
		TESTL(KErrNone == ret || KErrCannotFindProtocol == ret);
		Logger().WriteFormat(_L("Protocol Index %d corresponds to %S"), aIndex, &protoInfo.iName);
		if (protoInfo.iName == KDummyProtocol1Name())
			{
			pdummyIndex = aIndex;
			aFound = true;
			}
		}

	if (!aFound) {
		Logger().WriteFormat(_L("Could not find Dummy Protocol 1"));
		CleanupStack::PopAndDestroy();
		return EFail;
	}

	Logger().WriteFormat(_L("Opening Socket for Family: %d, Sock: %d, protocol: %d"),
			protoInfo.iAddrFamily, protoInfo.iSockType, protoInfo.iProtocol);
		
	ret=sock1.Open(ss, protoInfo.iAddrFamily, protoInfo.iSockType, protoInfo.iProtocol);
	Logger().WriteFormat(_L("Open returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);
	Logger().WriteFormat(_L("Opened %S socket OK"), &protoInfo.iName);

	Logger().WriteFormat(_L("Getting protocol info for index %d again"),pdummyIndex);
	ret = ss.GetProtocolInfo(pdummyIndex, protoInfo);
	Logger().WriteFormat(_L("GetProtocolInfo returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);


	Logger().WriteFormat(_L("Opening another socket"));
	RSocket sock2;
	ret = sock2.Open(ss, protoInfo.iAddrFamily, protoInfo.iSockType, protoInfo.iProtocol);
	Logger().WriteFormat(_L("Open returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);
	Logger().WriteFormat(_L("Opened %S socket OK"), &protoInfo.iName);

	Logger().WriteFormat(_L("Closing sockets"));
	sock2.Close();
	sock1.Close();

	Logger().WriteFormat(_L("Opening another socket"));
	RSocket sock3;
	ret = sock3.Open(ss, protoInfo.iAddrFamily, protoInfo.iSockType, protoInfo.iProtocol);
	Logger().WriteFormat(_L("Open returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);
	Logger().WriteFormat(_L("Opened %S socket OK"), &protoInfo.iName);

	Logger().WriteFormat(_L("Closing socket"));
	sock3.Close();

	Logger().WriteFormat(_L("Opening a socket by name on dummy protocol 1"));
	RSocket sock4;
	ret = sock4.Open(ss, KDummyProtocol1Name());
	Logger().WriteFormat(_L("Open returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);
	Logger().WriteFormat(_L("Opened %S socket OK"), &protoInfo.iName);

	Logger().WriteFormat(_L("Closing socket"));
	sock4.Close();

	CleanupStack::Pop(&ss);
	ss.Close();

	SetTestStepResult(verdict);
	return verdict;
	}

// Test step 1.3
const TDesC& CSocketTest1_3::GetTestName()
	{
	_LIT(ret,"Test1.3");
	return ret;
	}


enum TVerdict CSocketTest1_3::InternalDoTestStepL( void )
	{
	TVerdict verdict = EPass;

	Logger().WriteFormat(_L("Test Purpose: Open Bad Socket Type"));

	// connect to esock
	Logger().WriteFormat(_L("Attempting to connect to socket server"));
    RSocketServ ss;
	TInt ret = OptimalConnect(ss);
	CleanupClosePushL(ss);
	Logger().WriteFormat(_L("Connect returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);

	Logger().WriteFormat(_L("Attempting to create bad socket type"));
	RSocket sock;
	ret = sock.Open(ss, 0, 0, 0); 
	Logger().WriteFormat(_L("Open returned %S"), &EpocErrorToText(ret));
	TESTL(KErrBadName == ret);

	sock.Close();
	CleanupStack::Pop(&ss);
	ss.Close();
	SetTestStepResult(verdict);
	return verdict;
	}

// Test step 1.4
const TDesC& CSocketTest1_4::GetTestName()
	{
	_LIT(ret,"Test1.4");
	return ret;
	}
	
enum TVerdict CSocketTest1_4::InternalDoTestStepL( void )
	{
	TVerdict verdict = EPass;

	Logger().WriteFormat(_L("Test Purpose: Find Protocols"));

	// connect to esock
	Logger().WriteFormat(_L("Attempting to connect to socket server"));
    RSocketServ ss;
	TInt ret = OptimalConnect(ss);
	CleanupClosePushL(ss);
	Logger().WriteFormat(_L("Connect returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);

    Logger().WriteFormat(_L("Try to find non-existent protocol"));
	TProtocolDesc protoInfo;
	ret = ss.FindProtocol(_L("Not a Protocol Name"), protoInfo);
	Logger().WriteFormat(_L("FindProtocol returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNotFound == ret);

    Logger().WriteFormat(_L("Try to find dummy protocol 1"));
	ret = ss.FindProtocol(KDummyProtocol1Name(), protoInfo);
	Logger().WriteFormat(_L("FindProtocol returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);
	
	CleanupStack::Pop(&ss);
	ss.Close();
	SetTestStepResult(verdict);
	return verdict;
	}

// Test step 1.5
const TDesC& CSocketTest1_5::GetTestName()
	{
	_LIT(ret,"Test1.5");
	return ret;
	}

enum TVerdict CSocketTest1_5::InternalDoTestStepL( void )
	{
	TVerdict verdict = EPass;

	Logger().WriteFormat(_L("Test Purpose: Tidy Up Sockets on Thread Death"));

	Logger().WriteFormat(_L("Main thread : Creating sub thread"));
	RSemaphore s;
	s.CreateLocal(0);
	RThread t;
	TSocketThreadArg a;
	a.iHandle = this;
	a.iSem=&s;
	a.iNumSockets = KNumTestSockets;
	//Need to share logger across different threads
	Logger().ShareAuto();
	t.Create(_L("SocketThread1"), SocketThread, 
			 KDefaultStackSize, KDefaultHeapSize, KDefaultHeapSize, &a);
	t.Resume();
	s.Wait();

	Logger().WriteFormat(_L("Main thread : Killing Sub thread"));
	t.Kill(KErrNone);
	t.Close();

	SetTestStepResult(verdict);
	return verdict;
	}

// Test step 1.6
const TDesC& CSocketTest1_6::GetTestName()
	{
	_LIT(ret,"Test1.6");
	return ret;
	}
	
enum TVerdict CSocketTest1_6::InternalDoTestStepL( void )
	{
	TVerdict verdict = EPass;

	Logger().WriteFormat(_L("Test Purpose: Close Uninitialised Socket"));

	Logger().WriteFormat(_L("Attempting to close socket"));
	RSocket s;
	s.Close();
	s.Close();

	return verdict;
	}

// Test step 1.7
const TDesC& CSocketTest1_7::GetTestName()
	{
	_LIT(ret,"Test1.7");
	return ret;
	}
	
enum TVerdict CSocketTest1_7::InternalDoTestStepL( void )
	{
	TVerdict verdict = EPass;
	
	TInt numExhaustiveSockets = iNormalTest ? KNumExhaustiveSockets : 10;
	iNormalTest = EFalse; // normal test is only run once, the rest are OOM tests

	Logger().WriteFormat(_L("Test Purpose: Exhaustive Socket Open"));

	// connect to esock
	Logger().WriteFormat(_L("Attempting to connect to socket server"));
    RSocketServ ss;
	TInt ret = OptimalConnect(ss);
	CleanupClosePushL(ss);
	Logger().WriteFormat(_L("Connect returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);

    Logger().WriteFormat(_L("Finding dummy protocol 1"));
	TProtocolDesc protoInfo;
	ret = ss.FindProtocol(KDummyProtocol1Name(), protoInfo);
	Logger().WriteFormat(_L("FindProtocol returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);

    Logger().WriteFormat(_L("Opening socket"));
	RSocket sock;
	ret = sock.Open(ss,protoInfo.iAddrFamily,protoInfo.iSockType,protoInfo.iProtocol);
	Logger().WriteFormat(_L("Open returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);

    Logger().WriteFormat(_L("Closing socket"));
	sock.Close();

    Logger().WriteFormat(_L("Creating array of %d sockets"), numExhaustiveSockets);
	RSocket* socks = new (ELeave) RSocket[numExhaustiveSockets];
	CleanupArrayDeletePushL(socks);

	Logger().WriteFormat(_L("Attempting to Open %d sockets"), numExhaustiveSockets);
	TInt sockNum=0;
	ret = KErrNone;
	while (KErrNone==ret && sockNum<numExhaustiveSockets)
		{
		ret = socks[sockNum].Open(ss, protoInfo.iAddrFamily, 
								  protoInfo.iSockType, protoInfo.iProtocol);
		sockNum++;
		}
	if (ret != KErrNone)
		{
		sockNum--;
		}
	Logger().WriteFormat(_L("Created %d sockets"), sockNum);
	
	Logger().WriteFormat(_L("Freeing sockets in creation order"));
	TInt i;
	for (i=0; i<sockNum; i++)
		{
		socks[i].Close();
		}
		

#if defined (_DEBUG_SOCKET_FUNCTIONS)

	Logger().WriteFormat(_L("Attempting to Open %d sockets"), numExhaustiveSockets);
	TInt sockCount1 = sockNum;
	ret = KErrNone;
	sockNum = 0;
	while (ret==KErrNone && sockNum<numExhaustiveSockets)
		{
		ret=socks[sockNum].Open(ss, protoInfo.iAddrFamily, 
								protoInfo.iSockType,protoInfo.iProtocol);
		sockNum++;
		}
	if (ret != KErrNone)
		{
		sockNum--;
		}
	Logger().WriteFormat(_L("Created %d sockets, expected %d sockets"), sockNum, sockCount1);
	TESTL(sockCount1 == sockNum);

	Logger().WriteFormat(_L("Freeing sockets in creation order"));
	for (i=0; i<sockNum; i++)
		{
		socks[i].Close();
		}

#endif	// (_DEBUG) }

	CleanupStack::PopAndDestroy(socks);

	CleanupStack::Pop(&ss);
	ss.Close();
	SetTestStepResult(verdict);
	return verdict;
	}
	
// Test step 1.8
const TDesC& CSocketTest1_8::GetTestName()
	{
	_LIT(ret,"Test1.8");
	return ret;
	}
	
enum TVerdict CSocketTest1_8::InternalDoTestStepL( void )
	{
	TVerdict verdict = EPass;

	Logger().WriteFormat(_L("Test Purpose: Exhaustively enumerate all the protocols"));

	// connect to esock
	Logger().WriteFormat(_L("Attempting to connect to socket server"));
    RSocketServ ss;
	TInt ret = ss.Connect();
	Logger().WriteFormat(_L("Connect returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);
	CleanupClosePushL(ss);
	// NumProtocols and GetProtocolInfo
	Logger().WriteFormat(_L("Try NumProtocols"));
	TUint numProtocols;
	ret = ss.NumProtocols(numProtocols);
	Logger().WriteFormat(_L("NumProtocols returned %S, number %d"), 
			&EpocErrorToText(ret), numProtocols);
	TESTL(KErrNone == ret);

	TProtocolDesc protoInfo;
	TUint aIndex;
	TInt pdummyIndex = -1;
 	Logger().WriteFormat(_L("Trying GetProtocolInfo on each protocol"));
	for (aIndex=1;aIndex<=numProtocols;aIndex++) 
		{
		ret = ss.GetProtocolInfo(aIndex, protoInfo);
		Logger().WriteFormat(_L("GetProtocolInfo returned %S"), &EpocErrorToText(ret));	
		TESTL(KErrNone == ret);
		Logger().WriteFormat(_L("Protocol Index %d corresponds to %S"), aIndex, &protoInfo.iName);
		if (protoInfo.iName ==KDummyProtocol1Name())
			{
			pdummyIndex = aIndex;
			}
		}
	CleanupStack::Pop(&ss);
	ss.Close();
	if (pdummyIndex < 0)
		{
		Logger().WriteFormat(_L("Could not find Dummy Protocol 1"));
		verdict = EFail;
		}
	verdict = EPass;
	
	SetTestStepResult(verdict);
	return verdict;
	}







// Test step 1.9
const TDesC& CSocketTest1_9::GetTestName()
	{
	_LIT(ret,"Test1.9");
	return ret;
	}
	
	
enum TVerdict CSocketTest1_9::InternalDoTestStepL( void )
	{

	// Create socket, shutdown socket then connect 
	TVerdict verdict = EPass;
	Logger().WriteFormat(_L("Test Purpose: Connect Socket, then Shutdown"));

	// Connect to esock
	Logger().WriteFormat(_L("Attempting to connect to socket server"));
    RSocketServ ss;
	TInt ret = ss.Connect();
	Logger().WriteFormat(_L("Connect returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);
	CleanupClosePushL(ss); 

	// Create and open RConnection
	Logger().WriteFormat(_L("Creating RConnection"));
	RConnection conn; 
	ret = conn.Open(ss);
	Logger().WriteFormat(_L("Connection Open returned %S"), &EpocErrorToText(ret));
	TESTL(KErrNone == ret);
	CleanupClosePushL(conn);

	// Create and open socket on TCP protocol
	RSocket socket1;
	
	
	TProtocolDesc protoInfo;
	
	TUint numProtocols;
	ret = ss.NumProtocols(numProtocols);
	Logger().WriteFormat(_L("NumProtocols returned %S, number %d"), 
			&EpocErrorToText(ret), numProtocols);
	TESTL(KErrNone == ret);

	
	for (TInt index=1;index<=numProtocols;index++) 
		{
		ret = ss.GetProtocolInfo(index, protoInfo);
		Logger().WriteFormat(_L("GetProtocolInfo returned %S"), &EpocErrorToText(ret));	
		TESTL(KErrNone == ret || KErrCannotFindProtocol == ret);
		Logger().WriteFormat(_L("Protocol Index %d corresponds to %S"), index, &protoInfo.iName);
		if (protoInfo.iName == KDummyProtocol1Name())
			{
			break;
			}
		}
	
	
	
	Logger().WriteFormat(_L("Opening Socket 1"));
	ret = socket1.Open(ss, protoInfo.iAddrFamily, protoInfo.iSockType, protoInfo.iProtocol /*KAfInet, KSockStream, KProtocolInetTcp, conn*/);
	Logger().WriteFormat(_L("Socket 1 Open returned %S"), &EpocErrorToText(ret)); 
	TESTL(KErrNone == ret);
	CleanupClosePushL(socket1); 

	// Create Ports for Socket and socket to connect to
	const TInt KSocket1Port = 3441;
	const TInt KSocket2Port = 3881;
	_LIT(KLoopback, "127.0.0.1");
	_LIT(KLocal, "0.0.0.0");

	// Set the local address of Socket1
	TInetAddr socket1Addr;
	socket1Addr.SetPort(KSocket1Port);
	socket1Addr.Input(KLocal);
	ret = socket1.Bind(socket1Addr);

	// Set remote address for socket 
	TInetAddr socket2Addr;
	socket2Addr.SetPort(KSocket2Port);
	socket2Addr.Input(KLoopback);

	// Shutdown the Socket
	Logger().WriteFormat(_L("Shutting down Connection on Socket1"));
	TRequestStatus shutdownStatus;
	_LIT8(desOut, "Some test stuff to send to protocol");
	
	TBuf8<50> desIn;
	
	socket1.Shutdown(RSocket::EImmediate,desOut,desIn, shutdownStatus);
	User::WaitForRequest(shutdownStatus);
	Logger().WriteFormat(_L("Socket 1 shutdown returned %S"), &EpocErrorToText(shutdownStatus.Int()));

	// Connect socket1 to remote address
	TRequestStatus connectSocket1Status;
	Logger().WriteFormat(_L("Connecting Socket1 "));

	socket1.Connect(socket2Addr, connectSocket1Status);   // used to cause server to panic
	User::WaitForRequest(connectSocket1Status);

	if(connectSocket1Status != KErrBadHandle)
		{
		verdict = EFail;
		}
	
	CleanupStack::PopAndDestroy(); //socket
	CleanupStack::PopAndDestroy(); //conn
	CleanupStack::PopAndDestroy(); //ss

	return verdict;


	}





