/*******************************************************************

Copyright (c) 2004 Open Mobile Alliance, Ltd.  All Rights Reserved.

This software is made available under the usage and distribution terms 
covered by the Common Public License 1.0 and by using this software you
are bound by the terms and conditions of the same.

EXCEPT AS EXPRESSLY SET FORTH IN THE COMMON PUBLIC LICENSE,
THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, 
ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
   
Each recipient is solely responsible for determining the 
appropriateness of using and distributing this program and assumes 
all risks associated with its exercise of rights under the Common 
Public License, including but not limited to the risks and 
costs of program errors, compliance with applicable laws, 
damage to or loss of data, programs or equipment, and 
unavailability or interruption of operations.

********************************************************************/

#ifndef _SCTS_DEVMAN_TESTENGINE_H
#define _SCTS_DEVMAN_TESTENGINE_H

#define __SCTS_TESTCASE_VER__	"1.0"
#include "SctsPlatformLib.h"
#include "SctsCommandElements.h"
#include "SctsThread.h"
#include "SctsDevManT&D.h"
#include "SctsTransport.h"
#ifdef __SCTS_USING_SCTS__
#include "map"
#include "list"

class SctsDMDevice;
class SctsDMSession;
class SctsDMTestGroup;
class SctsDMTestCase;

/* Stage 1 : Checks the Test Object's Tree and Starts a session to updated the Test Objects's Tree, to bring it to the required state 
   Stage 2 : Starts the test session
   Stage 3 : Checks the test session to see if all test cases have passed
*/


typedef enum
{
	TE_IDLE=0,
	TE_TERMINATE,
	TE_STAGE_CHECK,
	TE_STAGE_TEST,
} SctsDMTestEngineState;


/* 
CommandRef structure to store information pertaining to received status.
Note : The itemID member denotes the position of the item in the outgoing command's
item list
*/
typedef struct
{
	int msgID;
	int cmdID;
	int itemID;
	int status;
	SctsDMNode *node;
} SctsDMTestCommandRef;

/* 
Test case/group prerequisites, a test groups prerequisite is the logical sum of all
its test cases.

id				: used by test cases to denote their static test case id
preReqState     : State of the Test case Pre-req.
shortDesc		: Short desciption
desc			: Long desciption
passCriteria	: Pass criteria string
preReqStr		: Additional preReq string
*/

typedef struct
{
	int id;
	const char *shortDesc/*[30]*/;
	const char *desc/*[200]*/;
	const char *passCriteria/*[130]*/;
	const char *preReqStr/*[512]*/;
	bool optional;
} SctsDMTestPreReq;


/* Static test case requirements */
extern SctsDMTestPreReq sctsClientTestCasePreReqs[];
extern SctsDMTestPreReq sctsServerTestCasePreReqs[];

/* Test case/group state */
typedef enum
{
	NOT_TESTED=0,
	TEST_PASSED,
	TEST_FAILED,
	TEST_OPTIONAL,
	NOT_SUPPORTED
} SctsDMTestState;

/* Test case summary info */
typedef struct _sctsTestInfo
{
	int id;
	SctsDMTestState state;
	long timeStamp;
	SctsTransportType transport;
	SctsSyncMLProto proto;
	struct _sctsTestInfo *next;
} SctsDMTestInfo;


/******************************************************************/
class SctsDMTestCase
{
friend class SctsDMTestGroup;
protected:
	SctsDMTestGroup *testGroup;
	SctsDMTestState state;
	SctsDMCommand *cmdRef;
	bool doneSIPreB;
	bool doneSIPostB;
	bool doneSIPreP;
	bool doneSIPostP;
	bool doneSMPreB;
	bool doneSMPostB;
	bool doneSMPreP;
	bool doneSMPostP;
	
public:
	virtual int GetID()=0;
	virtual bool StatePreReq() {return true;}
	virtual void StateInitiatePreBuild() {doneSIPreB=true;}
	virtual void StateInitiatePostBuild() {doneSIPostB=true;}
	virtual void StateInitiatePreProcess() {doneSIPreP=true;}
	virtual void StateInitiatePostProcess() {doneSIPostP=true;}
	virtual void StateManagePreBuild() {doneSMPreB=true;}
	virtual void StateManagePostBuild() {doneSMPostB=true;}
	virtual void StateManagePreProcess() {doneSMPreP=true;}
	virtual void StateManagePostProcess() {doneSMPostP=true;}
	virtual void StateTerminate() {}
	SctsDMTestState GetState() {return state;}
	SctsDMTestCase() {sctsMemset(this,0,sizeof(SctsDMTestCase));}
	virtual ~SctsDMTestCase() {};
    virtual bool ContinueNextSession() {return false;};
};

/******************************************************************/
class SctsDMTestGroup
{
public:	
	static SctsDMTestGroup *GetTestGroup(SctsDMDevice *device,int id);
	SctsDMSession *session;
	SctsDMDevice *device;
	std::list <SctsDMTestCase *> testCases;
	std::list <SctsDMCommand *> commandRefs;
	void StateInitiatePreBuild();
	void StateInitiatePostBuild();
	void StateInitiatePreProcess();
	void StateInitiatePostProcess();
	void StateManagePreBuild();
	void StateManagePostBuild();
	void StateManagePreProcess();
	void StateManagePostProcess();
	void StateTerminate();
	void AddTestCase(SctsDMTestCase *);
	SctsDMTestGroup(SctsDMDevice *_device) {session=0;device=_device;}
	~SctsDMTestGroup();
    bool HasPendingCases() {return false;};
};

/***************************************************************************
SctsDMTester Class
***************************************************************************/

class SctsDMTester:public SctsMutex
{
friend class SctsDMTestGroup;
private:
	int lastTestGroupID;
	int nextTestGroupID;
	SctsDMTestPreReq preReq;
	void *uiCallbackData;
	long sequenceTimestamp;
	SctsMutex stateLock;
	SctsDMTestEngineState state;
	void (*uiCallback)(void *,SctsDMSession *);	
public:
	
	void *SetUICallback(void *_uiCallbackData,void (*_uiCallback)(void *,SctsDMSession *),bool alreadyLocked=false);
	SctsDMDevice *device;				
	SctsDMTestInfo *testInfo;
	SctsDMTestGroup *nextTestGroup;
	bool sctsIsServer;
	char *testNode;	
	char *leaftestNode;
	SctsDMTestEngineState GetState();
	void SetState(SctsDMTestEngineState _state);
	
	void ExecuteTestGroup();
	/* Stage 1 : Brings the Test Objects's Tree to the required state */
	void ExecuteStageCheck();
	/* Stage 2 : Starts the Test Session */
	void ExecuteStageTest(SctsDMSession *);
	/* Stage 3 : Checks the test session to see if all test cases have passed */
	void ExecuteStageTerminate(SctsDMSession *);
	
	void SetNextTestGroupID(int);
	int GetNextTestGroupID();
	void ResetTests();
	
	void GenerateReport(char *fname);
	void Save(FILE *fp);
	void Load(FILE *fp);
	SctsDMTester(FILE *);
	SctsDMTester(SctsDMDevice *device,char *testNode=".");
	~SctsDMTester();
};

/* Callback functions used to route the call to the test account object */
void sctsTestDeviceExecuteStageTest(SctsDMSession *);
void sctsTestDeviceExecuteStageTerminate(SctsDMSession *);

#endif
#endif
