// Copyright (c) 2007-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 declaration of the CTSY integration test suite base class.
// 
//

/**
 @internalTechnology
*/

#ifndef __CCTSYINTEGRATIONTESTSUITEBASE_H__
#define __CCTSYINTEGRATIONTESTSUITEBASE_H__

#include <test/testexecutestepbase.h>

#include <etelmm.h>
#include <etelpckt.h>

#include "tetelrequeststatus.h"
#include "rpsownnumbers.h"
#include "townnumbersmanager.h"
#include "rpsasciirqstdefs.h"

class CEtelSessionMgr;

/**
Test result allocation:

EInconclusive: (INCONCLUSIVE)
-	The test can't be run because the HW, LTSY, SIM or Network 
	doesn't support a require functionality or capability. 
	Example: Call waiting indicator test and the SIM doesn't 
	support call waiting.
-	The test setup can't be completed due to an expected error. 
	Example: the test setup requires to have a active call but 
	this call can't be connected because the network is too busy.
No actions require, the test is correct and may pass on others 
condition/configuration.

ETestSuiteError: (UNKNOWN)
-	The test setup can't be completed due to an unexpected error
	or leave. Example: the test setup requires to have a line 
	status change notification active but the call to activate 
	this notification returned an error.
There is a problem with the test setup that must be investigated.

EIgnore: (UNEXECUTED)
-	The test fails for a known reason, but it cannot be fixed in 
	the near future. Example: there is a known problem with the 
	baseband that makes the test fail.

EAbort: (ABORT)
-	Generated by TEF when a test timeout
*/

/*************************************************************************************
INSTRUCTIONS on good use of MACROS!

1) Only use CHECK_XXX macros between SET UP and SET UP END sections of doTestStepL.
2) Only use ASSERT_XXXX macros in procedure section of doTestStepL I.e. Between TEST START and TEST END.
3) Use ASSERT_EQUALS_XX where possible as this will automatically log out actual and expected values on failure.
4) Do not use ASSERT_TRUE for testing equality of simple types.  This is because on failure it will not data. Prefer ASSERT_EQUALS_XX instead.
5) Comparison of complex types (e.g. TMobileCallInfoV1) can either be compared on each field (so would use ASSERT_EQUALS_XX) or a comparator obect can be created
   and ASSERT_TRUE used.  E.g  ASSERT_TRUE(cmpObj.IsEqual(ELogError), _L("Failed kkk"));
6) If comparator object is used the IsEquals() should be passed ELogError to ensure data is logged on failure.
*************************************************************************************/



/**
description: ASSERT_EQUALS may be used to test equality of two values.  <result> argument may also be an expression returning a simple type.
usage: For testing equality of simple types, e.g. TInt, TBool, TReal, caps, enums.
exceptions: Not for use for testing equality of complex types e.g TMobileCallInfoV1.  Use ASSERT_TRUE with a TCmpBase derived comparator class
exceptions: Not for use for testing equality of descriptors.  See ASSERT_EQUALS_DES8 and ASSERT_EQUALS_DES16.
logging: when comparison fails macro will log out the actual and expected values that have been compared. 
		 E.g. "FAILURE: Got 0, Expected 3 : my error22."
example: ASSERT_EQUALS(RMobileCall::EMulticallNotSupported, RMobileCall::EMulticallNotSupported, _L("my error4."));
example: ASSERT_EQUALS(DoSomething(), 3, _L("my error22."));
example: ASSERT_EQUALS(-5, KErrNotSupported, _L("my error4."));

@param result. simple value to compare
@param expected. expected value to test against
@param msg. string to print out if comaprison fails.
*/
#define ASSERT_EQUALS(result, expected, msg)														\
    {																								\
    if(!assert_equals(Logger(),((TText8*)__FILE__), __LINE__, ESevrErr, result, expected, msg)) 	\
	    { 																							\
	    SetAssertResult();				 															\
        } 																							\
    }


/**
description: ASSERT_EQUALS_DES8 may be used to test equality of two 8-bit descriptors.  <result> argument may also be an expression returning a 8-bit descriptor.
usage: For testing equality of 8-bit descriptors e.g. TDes8, TDesC8, TBuf8. 
exception: Not for use for testing equality of complex types e.g TMobileCallInfoV1.  Use ASSERT_TRUE with a TCmpBase derived comparator class
exception: Not for use for testing equality simple types.  See ASSERT_EQUALS.
exception: Not for use for testing equality of 16-bit descriptors.  See ASSERT_EQUALS_DES16.
logging: when comparison fails macro will log out the actual and expected values that have been compared. 
		 E.g. "FAILURE: Got bbbbbbbbbbbbbbbbbbbb, Expected cccccccccccccccccccc : my error44."
		 Logging will truncate logged strings to length KMaxLogCharLength.
example: ASSERT_EQUALS_DES8(buf1, buf2, _L("my error4."));

@param result. TDes8 value to compare
@param expected. expected value to test against
@param msg. string to print out if comaprison fails.
*/    		
#define ASSERT_EQUALS_DES8(result, expected, msg)																\
    {																											\
    if(!assert_equals_des8(Logger(),((TText8*)__FILE__), __LINE__, ESevrErr, result, expected, msg)) 	\
	    { 																										\
	    SetAssertResult();				 																		\
        }																										\
    }

    
/**
description: ASSERT_EQUALS_DES16 may be used to test equality of two 16-bit descriptors.  <result> argument may also be an expression returning a 16-bit descriptor.
usage: For testing equality of 16-bit descriptors e.g. TDes16, TDesC16, TBuf16. 
exception: Not for use for testing equality of complex types e.g TMobileCallInfoV1.  Use ASSERT_TRUE with a TCmpBase derived comparator class
exception: Not for use for testing equality simple types.  See ASSERT_EQUALS.
exception: Not for use for testing equality of 8-bit descriptors.  See ASSERT_EQUALS_DES8.
logging: when comparison fails macro will log out the actual and expected values that have been compared. 
		 E.g. "FAILURE: Got bbbbbbbbbbbbbbbbbbbb, Expected cccccccccccccccccccc : my error44."
		 Logging will truncate logged strings to length KMaxLogCharLength.
example: ASSERT_EQUALS_DES16(buf1, buf2, _L("my error4."));

@param result. TDes16 value to compare
@param expected. expected value to test against
@param msg. string to print out if comaprison fails.
*/ 
#define ASSERT_EQUALS_DES16(result, expected, msg)															\
    {																										\
    if(!assert_equals_des16(Logger(),((TText8*)__FILE__), __LINE__, ESevrErr, result, expected, msg)) 		\
	    { 																									\
	    SetAssertResult();																					\
	    }																									\
	}

/**
description: ASSERT_TRUE may be used to test for true statements.  <value> argument may also be an expression returning a bool.
			 This macro should be used for testing inequality statements holding true e.g. >,<,>=, <=
usage: For testing boolean true.  This macro should be used when checking for equality in TCmpBase and TCapsCmpBase derived classes for complex types.
exception: Not for use for testing equality of simple types or descriptor types. Use one of ASSERT_EQUALS_XXX macros.
logging: Does not log input values.  Will only log message below concatonated with <msg>
		 E.g. "FAILURE: Expected true : <msg>."
example: ASSERT_TRUE(5>3, _L("my error4."));
example: ASSERT_TRUE(cmpObj.IsEqual(ELogError), _L("Failed kkk"));

@param value. to check for boolean true.
@param msg. string to print out if check fails.
*/
_LIT(KAssertTrueText, "FAILURE: Expected true : %S");

#define ASSERT_TRUE(value, msg)														\
	{																				\
	TBool result = value;															\
	if (!result)																	\
	    {																			\
	    TPtrC m = (msg);															\
	    ERR_PRINTF2(KAssertTrueText, &m);											\
	    SetAssertResult();															\
	    }																			\
	}						


/**
description: ASSERT_BITS_SET may be used to test correct capbilities set in a bitmask.  
usage: For comparison of actual bitmask with expected bitmask. Comparison is based on matching wanted and unwanted bits.  All other bits are ignored.
logging: when check fails macro will logs out actual bit mask and wanted and unwanted bitmasks.
		 E.g. "FAILURE: Wrong bits set : Got 0x19 , required 0x10, unwanted 0x2 : <msg>"
example: ASSERT_BITS_SET(dynCaps, expectedCaps, unwantedCaps, _L("Wrong dynamic caps"))

@param value. bitmaks to check.
@param wantedBits. wanted bits in value mask
@param unwantedBits. Unwanted bits in value mask.
@param msg. string to print out if check fails.
*/

/**
 * Use this in the ASSERT_BITS_SET macro setting wantedBits to this value if
 * there are no wanted bits.
 */
const TUint KNoWantedBits = 0;
/**
 * Use this in the ASSERT_BITS_SET macro setting wantedBits to this value if
 * there are no unwanted bits.
 */
const TUint KNoUnwantedBits = 0;

_LIT(KAssertBitsSet, "FAILURE: Wrong bits set : Got 0x%x , required 0x%x, unwanted 0x%x : %S");

#define ASSERT_BITS_SET(value, wantedBits, unwantedBits, msg)						\
    {																				\
	if( (((value) & (wantedBits))  != (wantedBits)) ||								\
		(((value) & (unwantedBits)) != 0) )											\
		{																			\
		TPtrC m = (msg);															\
		ERR_PRINTF5(KAssertBitsSet, value, wantedBits, unwantedBits, &m);			\
		SetAssertResult();															\
		}																			\
    }

/**
 * Causes the test to leave if it has failed at this point.
 * When the test leaves, message msg is logged to the log file.
 * 
 * This macro should be used at a point in the test to cause
 * it to leave if there is no point in proceeding with the
 * test if it has already failed. Use sparingly!
 * 
 * Example: TEST_CHECK_POINT_L(_L("Could not dial a call."));
 */
_LIT(KTestCheckPointText, "TEST CHECK POINT FAILURE: %S");
#define TEST_CHECK_POINT_L(msg)					\
	{											\
	if (TestStepResult() != EPass)				\
		{										\
		TPtrC m = (msg);						\
		ERR_PRINTF2(KTestCheckPointText, &m);	\
		User::Leave(KErrGeneral);				\
		}										\
	};


// NOTE: These CHECK_XXX macros for test setup only, 
// to check a test pre-condidion. 
// To be used between SET UP and SET UP END in test step.

_LIT(KCheckText, "SET UP FAILURE: %S");

#define CHECK_TRUE_L(cond, msg)														\
    if(!(cond)) 																	\
	    { 																			\
		TPtrC m = (msg);															\
	    WARN_PRINTF2(KCheckText, &m); 												\
	    SetCheckResultL();															\
        } 		


#define CHECK_EQUALS_L(result, expected, msg)														\
    {																								\
    if(!assert_equals(Logger(),((TText8*)__FILE__), __LINE__, ESevrErr, result, expected, msg)) 		\
	    { 																							\
	    SetCheckResultL();				 															\
        } 																							\
    }


_LIT(KCheckBitsSetText, "SET UP FAILURE: Got 0x%x , required 0x%x, unwanted 0x%x : %S");

#define CHECK_BITS_SET_L(value, wantedBits, unwantedBits, msg)						\
    {																				\
	if ((((value) & wantedBits) != wantedBits) ||									\
		(((value) & unwantedBits) != 0))											\
		{																			\
		TPtrC m = (msg);															\
		WARN_PRINTF5(KCheckBitsSetText, value, wantedBits, unwantedBits, &m);		\
		SetCheckResultL();															\
		}																			\
    }	


/*
 * Debug logging macros.
 * 
 * These macros wrap around the regular INFO_PRINTFX macros defined in TestExecute
 * but allow logging to be turned on or off depending on whether
 * the ENABLE_DEBUG_LOGGING macro is defined in the mmp file. 
 */
#ifdef ENABLE_DEBUG_LOGGING

	#ifndef ENABLE_COMMS_DEBUG_UTIL_LOGGING // Route logging to TEF script
		#define DEBUG_PRINTF1(p1)				INFO_PRINTF1(p1)
		#define DEBUG_PRINTF2(p1, p2)			INFO_PRINTF2(p1, p2)
		#define DEBUG_PRINTF3(p1, p2, p3)		INFO_PRINTF3(p1, p2, p3)
		#define DEBUG_PRINTF4(p1, p2, p3, p4)	INFO_PRINTF4(p1, p2, p3, p4)
	#else // Route logging to CommsDebugUtil and to TEF log file

		#include <comms-infras/commsdebugutility.h>

		_LIT8(KTSYSubSystem, "tsy");
		_LIT8(KTSYCompnt, "ctsytest");

		#define DEBUG_PRINTF1(AAA)             { __FLOG_STATIC0(KTSYSubSystem, KTSYCompnt, (AAA)); INFO_PRINTF1(AAA); }
		#define DEBUG_PRINTF2(AAA,BBB)         { __FLOG_STATIC1(KTSYSubSystem, KTSYCompnt, (AAA), (BBB)); INFO_PRINTF2(AAA, BBB); }
		#define DEBUG_PRINTF3(AAA,BBB,CCC)     { __FLOG_STATIC2(KTSYSubSystem, KTSYCompnt, (AAA), (BBB), (CCC)); INFO_PRINTF3(AAA, BBB, CCC); }
		#define DEBUG_PRINTF4(AAA,BBB,CCC,DDD) { __FLOG_STATIC3(KTSYSubSystem, KTSYCompnt, (AAA), (BBB), (CCC), (DDD)); INFO_PRINTF4(AAA, BBB, CCC, DDD); }
		
		#define DEBUG_HEX_PRINTF2(AAA)	   {RFileLogger::HexDump(KTSYSubSystem, KTSYCompnt, (AAA)); }	

	#endif // ENABLE_COMMS_DEBUG_UTIL_LOGGING

#else
	#define DEBUG_PRINTF1(p1)		
	#define DEBUG_PRINTF2(p1, p2)	
	#define DEBUG_PRINTF3(p1, p2, p3)
	#define DEBUG_PRINTF4(p1, p2, p3, p4)
#endif // ENABLE_DEBUG_LOGGING


/**
test helper functions
*/

_LIT(KAssertErrorEqualsText,"FAILURE: Got %d, Expected %d : %S"); 
_LIT(KAssertErrorEqualsTextDes,"FAILURE: Got %S, Expected %S : %S");
const TInt KMaxLogCharLength = 20;

template<class T>
inline TBool assert_equals(CTestExecuteLogger& aLogger, const TText8* aFile, TInt aLine, TInt aSeverity, T aRes, T aExp, TPtrC aMsg)
	{
	if(aRes != aExp)
		{
		aLogger.LogExtra(aFile, aLine, aSeverity, KAssertErrorEqualsText, aRes, aExp, &aMsg);
		return EFalse;
		}
	return ETrue;
	}
	

TBool assert_equals_des16(CTestExecuteLogger& aLogger, const TText8* aFile, TInt aLine, 
	TInt aSeverity, const TDesC& aRes, const TDesC& aExp, const TDesC& aMsg);

TBool assert_equals_des8(CTestExecuteLogger& aLogger, const TText8* aFile, 
	TInt aLine, TInt aSeverity, const TDesC8& aRes, const TDesC8& aExp, const TDesC& aMsg);


// Time constants
const TInt KOneSecond = 1000000;

/**
 * Timeouts
 */
enum TTimeDuration
	{
	ETimeShort = 5*KOneSecond, 		// Simple LTSY transaction
	ETimeMedium = 20*KOneSecond,	// Simple SIM access
	ETimeLong = 60*KOneSecond,		// When sending something to the network
	ETimeVeryLong = 120*KOneSecond	// Multiple network transactions or SIM access
	};

const TInt KTwentySeconds = 20*1000000;//deliberately not using KOneSecond in case it gets reduced to speed up tests.  Do not want to reduce time for user interaction.
class CRPSMaster;
class MRpsFunctorBase;
class CCTSYIntegrationTestSuiteStepBase : public CTestStep
/**
 * Base test step class from which all test steps inherit.
 */
	{
public:

	virtual ~CCTSYIntegrationTestSuiteStepBase();
	CCTSYIntegrationTestSuiteStepBase(CEtelSessionMgr& aEtelSessionMgr);

	virtual TVerdict doTestStepPreambleL(); 
	virtual TVerdict doTestStepPostambleL();

	void SetAssertResult();
	void SetCheckResultL();
	TInt WaitForRequestWithTimeOut(TEtelRequestBase& aRequestStatus,  TTimeDuration aTimeOut);
	
	void ConsolePrintL(const TDesC& aText );
	
	void DisplayUserInteractionPromptL(const TDesC& aText, TTimeDuration aTimeOut = ETimeMedium);
	
	inline void SetRpsHandle(CRPSMaster* aRPS) 
		{
		iRPS = aRPS;
		};
		
	inline void SetOwnNumbersManager(TOwnNumbersManager* aOwnNumbers)
		{
		iOwnNumbersCache.SetOwnNumbersManager(aOwnNumbers);
		};
		
	inline TBool UsingRps() const
		{
		// if the pointer to RPS is null, return false, else return true
		return ((iRPS==NULL)?EFalse:ETrue);
		}
	void GetRPSNumber(TEtelLine aLine, TPtrC& aNumber);
		
	//RPS dispatch requests
	TInt RPSDialNumberL(const TDesC& aNumToDial, TEtelLine aLine);
	TInt RPSRequestIncomingCallL(TEtelLine aLine);
	TInt RPSRequestIncomingCancelBeforeConnectL(TEtelLine aLine, TInt aDelay);
	TInt RPSRequestIncomingHangupAfterConnectL(TEtelLine aLine, TInt aDelay);
	TInt RPSAnswerNextCallThenHangupL(TEtelLine aLine, TInt aDelay);
	TInt RPSAnswerNextCallL(TEtelLine aLine);
	TInt RPSAnswerNextCallThenHoldL(TEtelLine aLine, TInt aDelay);
	TInt RPSIgnoreNextCallL(TEtelLine aLine);	
	TInt RPSHoldL(TEtelLine aLine, TInt aDelay);
	TInt RPSResumeL(TEtelLine aLine, TInt aDelay);
	TInt RPSHangupL(TEtelLine aLine, TInt aDelay);
	TInt RPSHangUpNextCallBeforeConnectL(TEtelLine aLine);
	TInt RPSEchoDataL(const TDesC& aDataToSend);
	TInt RPSRejectNextCallL(TEtelLine aLine);
	
	void AsyncExec(CThreadExec::MFunctor* aFunction);
	void SyncExec(CThreadExec::MFunctor* aFunction);
protected:
	void StartSetup();
	void StartTest();
	void StartCleanup();
	void RPSCleanupL();
	TInt ExecuteRemoteRequestL(MRpsFunctorBase& aRpsFunctor, const TDesC& aRpsCallMsg);
	TInt DoPauseL(const TDesC& aText, TTimeDuration aTimeout = ETimeMedium );
	TPtrC Number(TEtelLine aLine);

protected:
	CEtelSessionMgr& iEtelSessionMgr;

	TVerdict		iAssertResult;
	TVerdict		iCheckResult;
	CRPSMaster* iRPS;
	
	// Own Number Info
	TOwnNumbersCache iOwnNumbersCache;

	}; // class CCTSYIntegrationTestSuiteStepBase

#endif // __CCTSYINTEGRATIONTESTSUITEBASE_H__
