#include "StdAfx.h"
#include "SATExecutor.h"
#include "ScriptExecutor.h"
#include "CharEncoding.h"

CSATExecutor::CSATExecutor(void)
{
	m_bLogin = FALSE;
	m_hEventHearbeat = NULL;
	m_hThreadHearbeat = NULL;
	m_hEventExcuteScript = NULL;
	m_hThreadExcuteScript = NULL;
}

CSATExecutor::~CSATExecutor(void)
{
}

bool CSATExecutor::IsTaskExist(SATHTTP::STTask &task)
{
	bool found = false;
	std::list<SATHTTP::STTask>::iterator it = m_vtTask.begin();
	for ( ; it != m_vtTask.end(); it++ ) {
		// 不要使用nTaskId,这个值没啥用;
		if ( it->Id == task.Id ) {
			found = true;
			break;
		}
	}

	return found;
}

SATHTTP::STTask* CSATExecutor::IsThereATaskInProcess()
{
	std::list<SATHTTP::STTask>::iterator it = m_vtTask.begin();
	for ( ; it != m_vtTask.end(); it++ ) {
		if ( it->_nExecutionState == 1 ) {
			return &(*it);
		}
	}

	return NULL;
}

SATHTTP::STTask* CSATExecutor::GetFreeTask()
{
	std::list<SATHTTP::STTask>::iterator it = m_vtTask.begin();
	for ( ; it != m_vtTask.end(); it++ ) {
		if ( it->_nExecutionState == 0 ) {
			return &(*it);
		}
	}

	return NULL;
}

void CSATExecutor::DelFinishedTask()
{
	AutoThreadSection ats(&m_csTask);
	std::list<SATHTTP::STTask>::iterator it = m_vtTask.begin();
	for ( ; it != m_vtTask.end(); it++ ) {
		// 状态为2的完成任务;
		if ( it->_nExecutionState == 2 ) {
			// 删除所有执行器对象;
			for (std::vector<SATHTTP::STCase>::iterator _case = it->Job.vtCases.begin(); _case != it->Job.vtCases.end(); _case++ ) {
				if ( _case->_pExcutor )
					delete _case->_pExcutor;
				_case->_pExcutor = NULL;
			}
			m_vtTask.erase(it);
			break;
		}
	}
}

SATHTTP::STCase* CSATExecutor::IsCaseScriptProcess(std::vector<SATHTTP::STCase> &vtCases)
{
	std::vector<SATHTTP::STCase>::iterator it = vtCases.begin();
	for ( ; it != vtCases.end(); it++) {
		if ( it->_nExecutionState == 1 ) {
			return &(*it);
		}
	}

	return NULL;
}

SATHTTP::STCase* CSATExecutor::GetFreeCaseScript(std::vector<SATHTTP::STCase> &vtCases)
{
	std::vector<SATHTTP::STCase>::iterator it = vtCases.begin();
	for ( ; it != vtCases.end(); it++) {
		if ( it->_nExecutionState == 0 ) {
			return &(*it);
		}
	}

	return NULL;
}

SATHTTP::STCase* CSATExecutor::ExecuteFreeCaseScript(SATHTTP::STTask* pTask)
{
	SATHTTP::STCase* pCase = GetFreeCaseScript(pTask->Job.vtCases);
	if (pCase) {		
		if ( !pCase->_pExcutor ) {
			CScriptExecutor *pExcutor = new CScriptExecutor(); 
			if ( pExcutor ) {
				pCase->_pExcutor = pExcutor;
				// 用例的日志文件路径;
				pCase->_strCaseLog = pCase->_strFileDir + "\\" + pCase->_strFileName + ".txt";
				if ( pExcutor->InitScript(pCase->_strScriptPath, pCase->_strCaseLog, "", SUBPROCESS) ) {
					// 设置用例对象;
					pExcutor->SetCaseObje(pCase);
					pExcutor->StartScript();
					// 标记用例执行中;
					pCase->_nExecutionState = 1;
				}
				else { // 初始化失败;
					pCase->_nExecutionState = 4;
				}

				// 标记任务为执行中;
				pTask->_nExecutionState = 1;
				// 记录开始时间;
				pCase->_ulStartTickCount = GetTickCount64();
				pCase->_strStartTime = CTime::GetCurrentTime().Format(_T("%Y-%m-%d %H:%M:%S"));
			}	
		}
		else {
			//CScriptExecutor *pExcutor = (CScriptExecutor *)pCase->_pExcutor;
		}
	}

	return pCase;
}

void CSATExecutor::AddDevices(const SATDEV::STDevice &stDevice)
{
	if ( IsDeviceExist(stDevice.strName) )
		return;

	SATHTTP::STDevice http_dev;
	// 设备使用状态;
	if ( stDevice.nStatus == SATDEV::Idle )
		http_dev.strStatus = "0";
	else if ( stDevice.nStatus == SATDEV::InUse )
		http_dev.strStatus = "1";
	// 设备序列号;
	http_dev.strDeviceSerial = stDevice.strName;
	// 余下变量固定值;
	http_dev.strComments = "";
	http_dev.strCPU = "";
	http_dev.strDeviceMac = "";
	http_dev.strElectric = "";
	http_dev.strHardwareVersion = "SAT-HV";
	http_dev.strLastJob = "";
	http_dev.strLastJobFinishTime = "";
	http_dev.strLastJobStartTime = "";
	http_dev.strLastTimeBreak = "";
	http_dev.strLastTimeConnected = "";
	http_dev.strManu = "";
	http_dev.strMemory = "";
	http_dev.strModel = "SATModel";
	http_dev.strPhoneNumber = "";
	http_dev.strSoftwareVersion = "0123456789";

	m_vtDevice.push_back(http_dev);
}

void CSATExecutor::DelDevices(const SATDEV::STDevice &stDevice)
{
	std::vector<SATHTTP::STDevice>::iterator it = m_vtDevice.begin();
	for ( ; it != m_vtDevice.end(); it++ ) {
		if ( _tcsicmp(it->strDeviceSerial.c_str(), stDevice.strName.c_str()) == 0 ) {
			m_vtDevice.erase(it);
			break;
		}
	}
}

void CSATExecutor::SynchDeviceStatus(std::string strDevName, SATDEV::DEVICE_USAGE_STATUS status)
{
	std::vector<SATHTTP::STDevice>::iterator it = m_vtDevice.begin();
	for ( ; it != m_vtDevice.end(); it++ ) {
		if ( _tcsicmp(it->strDeviceSerial.c_str(), strDevName.c_str()) == 0 ) {
			if ( status == SATDEV::Idle )
				it->strStatus = "0";
			else if ( status == SATDEV::InUse )
				it->strStatus = "1";
			break;
		}
	}

	CSATDevices::SetDeviceUsageStatus(strDevName, status);
}

bool CSATExecutor::IsDeviceExist(std::string strDevName)
{
	bool bExist = false;
	std::vector<SATHTTP::STDevice>::iterator it = m_vtDevice.begin();
	for ( ; it != m_vtDevice.end(); it++ ) {
		if ( _tcsicmp(it->strDeviceSerial.c_str(), strDevName.c_str()) == 0 ) {
			bExist = true;
			break;
		}
	}

	return bExist;
}

bool CSATExecutor::Login(std::string user, std::string password, std::string actuator, bool bLogin /*= true*/)
{
	std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
	url.append("/ajaxInteractiveManage!executeLogin.action");
	// 填充数据;
	m_stLoginReq.strUserName = user;
	m_stLoginReq.strPassword = password;
	m_stLoginReq.strStatus = bLogin ? "0" : "1";   // 0表示登录;
	m_stLoginReq.strDeleteStatus = "";
	m_stLoginReq.strIP = GLOBAL::g_strIPAddress;
	m_stLoginReq.strStorage = "";
	if ( bLogin ) {
		m_stLoginReq.strDisconnectTime = "";
		m_stLoginReq.strConnectTime = CTime::GetCurrentTime().Format(_T("%Y-%m-%d %H:%M:%S"));		
	} else { 
		m_stLoginReq.strConnectTime = "";
		m_stLoginReq.strDisconnectTime = CTime::GetCurrentTime().Format(_T("%Y-%m-%d %H:%M:%S"));
	}
	// 执行器名称;
	m_stLoginReq.strExecuteName = m_strActuatorName = actuator;
	// 执行器PC物理地址;
	m_stLoginReq.strMAC = GLOBAL::g_strMacs;	
	m_stLoginReq.strCPU = "";

	if ( ::Login(url, m_stLoginReq, m_stLoginResp) ) {
#ifdef _DEBUG
	OutputDebugString("登录成功\n");
#endif
		GLOBAL::WriteTextLog("登录成功");
		m_bLogin = TRUE;
		return true;
	}

#ifdef _DEBUG
	OutputDebugString("登录失败\n");
#endif
	GLOBAL::WriteTextLog("登录失败");

	return false;
}

bool CSATExecutor::Logout(std::string user, std::string password)
{
	return Login(user, password, false);
}

bool CSATExecutor::UpdateDevice()
{
	SATHTTP::STUpdateDeviceReq stUpdateDeviceReq;
	SATHTTP::STUpdateDeviceResp stUpdateDeviceResp;
	std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
	url.append("/ajaxInteractiveManage!updateDeviceMessage.action");
	// 这个状态值要怎么设置?// 此处统一为0;
	stUpdateDeviceReq.strStatus = "0";
	stUpdateDeviceReq.strUserName = m_stLoginReq.strUserName;		
	stUpdateDeviceReq.strIP = GLOBAL::g_strIPAddress;
	stUpdateDeviceReq.strStorage = "";
	stUpdateDeviceReq.strRunnerName = m_strActuatorName;
	// 这里使用PC物理地址;
	stUpdateDeviceReq.strMAC = GLOBAL::g_strMacs;
	// 这个reportType具体意义不明;
	stUpdateDeviceReq.strReportType = "1";
	stUpdateDeviceReq.strStartTime = CTime::GetCurrentTime().Format(_T("%Y-%m-%d %H:%M:%S"));
	stUpdateDeviceReq.strMemory = "";
	stUpdateDeviceReq.strEndTime = "";
	stUpdateDeviceReq.strCPU = "";
	stUpdateDeviceReq.devicelist.assign(m_vtDevice.begin(), m_vtDevice.end());
	if ( !::UpdateDeviceMessage(url, stUpdateDeviceReq, stUpdateDeviceResp) )
	{
		return false;
	}
	
	return true;
}

bool CSATExecutor::NotifyTaskStart(SATHTTP::STTask* pTask)
{
	if ( !pTask )
		return false;

	SATHTTP::STNotifyJobStartReq stNotifyJobStartReq;
	SATHTTP::STNotifyJobStartResp stNotifyJobStartResp;
	std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
	url.append("/ajaxInteractiveManage!setResult.action");

	TCHAR szValue[36] = {0};
	_itoa_s(pTask->nDeviceId, szValue, 10);
	stNotifyJobStartReq.strDeviceId = szValue;

	_itoa_s(pTask->nExecuteId, szValue, 10);
	stNotifyJobStartReq.strExecuteId = szValue;

	// _itoa_s(stTask.nInstanceId, szValue, 10); // 误导：应该使用id而不是nInstanceId
	_itoa_s(pTask->Id, szValue, 10);
	stNotifyJobStartReq.strInstanceId = szValue;					

	//_itoa_s(pTask->nTaskId, szValue, 10);
	stNotifyJobStartReq.strTaskId = pTask->Job.strTaskId;

	// 这个映像路径有何用?
	stNotifyJobStartReq.strSignalImageUrl = GLOBAL::g_stSATConfig.szScriptDir;
	stNotifyJobStartReq.strSignalImageUrl.append(pTask->strTaskName+"\\\\");
	stNotifyJobStartReq.strSignalImageUrl.append(pTask->Job.strUniqueId+"\\\\");
	stNotifyJobStartReq.strSignalImageUrl.append(pTask->Job.strDeviceId);

	if ( SetResult(url, stNotifyJobStartReq, stNotifyJobStartResp) )
	{
		// 此处可能需要设置设备为忙碌状态;
		// SetDeviceStatus(BUSY);
		return true;
	}

#ifdef _DEBUG
	OutputDebugString("通知SAT失败\n");
#endif

	return false;
}

bool CSATExecutor::UploadCaseImg(SATHTTP::STTask* pTask, SATHTTP::STCase *pCase, std::string img)
{
	TCHAR szValue[MAX_PATH] = {0};
	std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
	url.append("/ajaxInteractiveManage!saveResultImg.action");

	SATHTTP::STSaveImgReq stSaveImgReq;
	SATHTTP::STSaveImgResp stSaveImgResp;

	stSaveImgReq.strCaseId = pCase->strId;
	stSaveImgReq.strCaseRepeat = "0";
	_itoa_s(pCase->_nCaseStep, szValue, 10);
	stSaveImgReq.strCaseStep = szValue;
	// 实例Id;
	_itoa_s(pTask->nDeviceId, szValue, 10);
	stSaveImgReq.strDeviceId = szValue;//pTask->Job.strDeviceId;
	// 就是Task中的ExecuteId
	_itoa_s(pTask->nExecuteId, szValue, 10);
	stSaveImgReq.strExecuteId = szValue;
	// 实例Id;
	_itoa_s(pTask->nInstanceId, szValue, 10);
	stSaveImgReq.strInstanceId = szValue;
	stSaveImgReq.strJobRepeat = "0";
	// 注意避坑：roundnum必须赋值0或1;
	stSaveImgReq.strRoundNum = "0";
	stSaveImgReq.strTaskType = pTask->strTaskType;
	stSaveImgReq.strUploads = img;

	// 上传用例图片;
	if ( SaveResultImg(url, stSaveImgReq, stSaveImgResp) )
	{
		return true;
	}

	return false;
}

bool CSATExecutor::UploadCaseLog(SATHTTP::STTask* pTask, SATHTTP::STCase *pCase)
{
	TCHAR szValue[MAX_PATH] = {0};
	std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
	url.append("/ajaxInteractiveManage!saveCaseOrTaskLog.action");

	SATHTTP::STSaveLogReq stSaveLogReq;
	SATHTTP::STSaveLogResp stSaveLogResp;

	stSaveLogReq.strCaseId = pCase->strId;
	// 执行ID;
	_itoa_s(pTask->nExecuteId, szValue, 10);
	stSaveLogReq.strExecuteId = szValue;
	stSaveLogReq.strFileType = "caseLogFile";
	// 任务Id;
	//_itoa_s(pTask->nTaskId, szValue, 10);
	stSaveLogReq.strTaskId = pTask->Job.strTaskInstanceId;
	stSaveLogReq.strUserId = pTask->Job.strUserId;
	// 要上传的日志文件;
	stSaveLogReq.strUploads = pCase->_strCaseLog;
	if ( SaveCaseOrTaskLog(url, stSaveLogReq, stSaveLogResp) )
	{
		return true;
	}

	return false;
}

bool CSATExecutor::ReportCaseItemFinish(SATHTTP::STTask* pTask, SATHTTP::STCase *pCase, STCaseItem &caseItem)
{
	TCHAR szValue[MAX_PATH] = {0};
	std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
	url.append("/ajaxInteractiveManage!setResultList.action");

	SATHTTP::STJobProcessReq stJobProcessReq;
	SATHTTP::STJobProcessResp stJobProcessResp;

	stJobProcessReq.strResultState = caseItem.result ? "1" : "0";
	stJobProcessReq.strCaseScene = "";
	// 索引;
	_itoa_s(pCase->_nCaseStep, szValue, 10);
	stJobProcessReq.strCaseStep = szValue;
	stJobProcessReq.strApkMD5 = "";
	stJobProcessReq.strCrashTime = "";
	// 就是Task中的ExecuteId
	_itoa_s(pTask->nExecuteId, szValue, 10);
	stJobProcessReq.strRunnerId = szValue;
	stJobProcessReq.strCPUInfo = "0";
	stJobProcessReq.strRunnedActionNameList = "";
	stJobProcessReq.strArtificialResult = "";
	stJobProcessReq.strArtificialModify = "";
	stJobProcessReq.strRunnerName = "";
	stJobProcessReq.strTaskType = "FUNCTIONALITY";
	stJobProcessReq.strCaseRepeat = "0";
	stJobProcessReq.strApplicationGroup = "";
	// 实例Id;
	_itoa_s(pTask->Id, szValue, 10);
	stJobProcessReq.strInstanceId = szValue;
	stJobProcessReq.strCaseId = pCase->strId;
	// 进度;
	_itoa_s(100*(atoi(pCase->strIndex.c_str()))/pTask->Job.vtCases.size(), szValue, 10);
	stJobProcessReq.strProgress = szValue;
	// 需要将utf-8转gbk;
	stJobProcessReq.strReusltMessage = caseItem.name;//CharEncoding::UTF82ASCII(caseItem.name.c_str());
	stJobProcessReq.strJobRepeat = "0";
	stJobProcessReq.strScreenShot = "";
	stJobProcessReq.strStartTime = pCase->_strStartTime;
	stJobProcessReq.strCrashNumber = "";
	stJobProcessReq.strCaseName = pCase->strCaseName;
	//stJobProcessReq.strFailedReason = CharEncoding::UTF82ASCII(caseItem.remark.c_str());
	//stJobProcessReq.strFailedReason = (char*)CharEncoding::UTF82UNICODE(caseItem.remark.c_str());
	stJobProcessReq.strFailedReason = caseItem.remark;
	for (std::vector<std::string>::iterator it = caseItem.imgs.begin(); it != caseItem.imgs.end(); it++ )
	{
		int npos = it->find_last_of('/');
		if ( std::string::npos != npos )
		{
			stJobProcessReq.strImgName.append(it->substr(npos+1));
			stJobProcessReq.strImgName.append("&");
		}
	}
	if ( stJobProcessReq.strImgName.size() && stJobProcessReq.strImgName.at(stJobProcessReq.strImgName.size()-1) == '&')
		stJobProcessReq.strImgName.erase(stJobProcessReq.strImgName.size()-1);
	stJobProcessReq.strCaseIndex = pCase->strIndex;
	// 实例Id;
	_itoa_s(pTask->nDeviceId, szValue, 10);
	stJobProcessReq.strDeviceId = szValue;
	stJobProcessReq.strSceneIndex = "0";
	// 实例Id;
	//_itoa_s(pTask->nTaskId, szValue, 10);
	stJobProcessReq.strTaskId = pTask->Job.strTaskId;
	//stJobProcessReq.strAnalysis = CharEncoding::UTF82ASCII(caseItem.data.c_str());
	stJobProcessReq.strAnalysis = caseItem.data.c_str(); 
	// 设备名称：即DeviceSerial;
	stJobProcessReq.strDevnceName = pTask->Job.strDeviceId;	// 命名及其不范围,一会deviceid是deviceserial,一会是id;
	// 固定为：TOTAL
	stJobProcessReq.strInfoType = "";
	// 如果是Android设备,需要通过adb获取;
	//stJobProcessReq.strMemoryInfo = stDevice.strMemory;
	stJobProcessReq.strEndTime = CTime::GetCurrentTime().Format(_T("%Y-%m-%d %H:%M:%S"));//"2019-12-16 10:18:20";
	stJobProcessReq.strRoundNumber = "1";
	stJobProcessReq.strResultType = "4";		// reportActionFinish;
	stJobProcessReq.strOperationStep = "";

	if ( SetResultList(url, stJobProcessReq, stJobProcessResp) )
	{
		// 再上传图片;
		std::string img;
		for (std::vector<std::string>::iterator it = caseItem.imgs.begin(); it != caseItem.imgs.end(); it++ )
		{
			img = "D:/SAT/results/";
			img.append(it->substr(3));
			UploadCaseImg(pTask, pCase, img);
		}

		return true;
	}

	return false;
}

bool CSATExecutor::ReportCaseFinish(SATHTTP::STTask* pTask, SATHTTP::STCase *pCase)
{
	TCHAR szValue[MAX_PATH] = {0};
	std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
	url.append("/ajaxInteractiveManage!setResultList.action");

	SATHTTP::STJobProcessReq stJobProcessReq;
	SATHTTP::STJobProcessResp stJobProcessResp;

	// 上报用例结果：0表示脚本成功执行,	1表示脚本出错或超时;
	if ( pCase->_nExecutionState == 2 )
		stJobProcessReq.strResultState = "0";	// 脚本未执行完成;
	else if ( pCase->_nExecutionState == 1 )	
		stJobProcessReq.strResultState = "1";	// 脚本执行中,认为fail;
	
	stJobProcessReq.strCaseScene = "";
	// 索引;
	_itoa_s(pCase->_nCaseStep, szValue, 10);
	stJobProcessReq.strCaseStep = szValue;
	stJobProcessReq.strApkMD5 = "";
	stJobProcessReq.strCrashTime = "";
	// 就是Task中的ExecuteId
	_itoa_s(pTask->nExecuteId, szValue, 10);
	stJobProcessReq.strRunnerId = szValue;
	stJobProcessReq.strCPUInfo = "0";
	stJobProcessReq.strRunnedActionNameList = "";
	stJobProcessReq.strArtificialResult = "";
	stJobProcessReq.strArtificialModify = "";
	stJobProcessReq.strRunnerName = "";
	stJobProcessReq.strTaskType = "FUNCTIONALITY";
	stJobProcessReq.strCaseRepeat = "";
	stJobProcessReq.strApplicationGroup = "";
	// 实例Id;注意避坑;
	_itoa_s(pTask->Id, szValue, 10);
	stJobProcessReq.strInstanceId = szValue;
	stJobProcessReq.strCaseId = pCase->strId;
	// 进度(###需要修改此处###);
	_itoa_s(100*(atoi(pCase->strIndex.c_str()))/pTask->Job.vtCases.size(), szValue, 10);
	stJobProcessReq.strProgress = szValue;
	// 需要将utf-8转gbk;
	stJobProcessReq.strReusltMessage = CharEncoding::ASCII2UTF8("测试用例结果：");
	stJobProcessReq.strJobRepeat = "";
	stJobProcessReq.strScreenShot = "";
	stJobProcessReq.strStartTime = pCase->_strStartTime;
	stJobProcessReq.strCrashNumber = "";
	stJobProcessReq.strCaseName = pCase->strCaseName;
	stJobProcessReq.strFailedReason = "";

	stJobProcessReq.strImgName = "";
	stJobProcessReq.strCaseIndex = pCase->strIndex;
	// 实例Id;
	_itoa_s(pTask->nDeviceId, szValue, 10);
	stJobProcessReq.strDeviceId = szValue;
	stJobProcessReq.strSceneIndex = "0";
	// 实例Id;
	//_itoa_s(pTask->nTaskId, szValue, 10);
	stJobProcessReq.strTaskId = pTask->Job.strTaskId;
	stJobProcessReq.strAnalysis = "";
	// 设备名称：即DeviceSerial;
	stJobProcessReq.strDevnceName = pTask->Job.strDeviceId;	// 命名及其不范围,一会deviceid是deviceserial,一会是id;
	// 固定为：TOTAL
	stJobProcessReq.strInfoType = "TOTAL";
	// 如果是Android设备,需要通过adb获取;
	//stJobProcessReq.strMemoryInfo = stDevice.strMemory;
	stJobProcessReq.strEndTime = pCase->_strEndTime;//CTime::GetCurrentTime().Format(_T("%Y-%m-%d %H:%M:%S"));//"2019-12-16 10:18:20";
	stJobProcessReq.strRoundNumber = "1";
	stJobProcessReq.strResultType = "5";		// reportCaseFinish;
	stJobProcessReq.strOperationStep = "";

	if ( SetResultList(url, stJobProcessReq, stJobProcessResp) )
	{
		return true;
	}

	return false;
}

bool CSATExecutor::ReportCaseResult(SATHTTP::STTask* pTask, SATHTTP::STCase *pCase)
{
	// 获取xml文件内容;
	std::string xmlpath = "D:\\SAT\\results\\detail\\";
	xmlpath.append(pCase->_strFileName);
	xmlpath.append("_result.xml");
	std::vector<STCaseItem> vtCaseItem;
	GetCaseXMLResult(xmlpath, vtCaseItem);
	//if ( vtCaseItem.size() == 0 )
	//	return false;
	
	int nIndex = 1;
	TCHAR szValue[MAX_PATH] = {0};
	std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
	url.append("/ajaxInteractiveManage!setResultList.action");
	SATHTTP::STJobProcessReq stJobProcessReq;
	SATHTTP::STJobProcessResp stJobProcessResp;
	// 遍历所有用例测试项;
	std::vector<STCaseItem>::iterator it = vtCaseItem.begin();
	for (; it != vtCaseItem.end(); it++ )
	{
		// 上报测试项结果(包含相片);
		ReportCaseItemFinish(pTask, pCase, *it);		
	}

	// 上报用例完成;
	ReportCaseFinish(pTask, pCase);

	// 上传用例日志;
	UploadCaseLog(pTask, pCase);

	// 删除执行对象;
	if ( pCase->_pExcutor )
		delete pCase->_pExcutor;
	pCase->_pExcutor = NULL;
	GLOBAL::WriteTextLog(_T("执行器对象删除成功，脚本用例名为=%s"), pCase->strCaseName.c_str());

	return true;
}

bool CSATExecutor::UploadTaskLog(SATHTTP::STTask* pTask)
{
	TCHAR szValue[MAX_PATH] = {0};
	std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
	url.append("/ajaxInteractiveManage!saveCaseOrTaskLog.action");

	SATHTTP::STSaveLogReq stSaveLogReq;
	SATHTTP::STSaveLogResp stSaveLogResp;

	stSaveLogReq.strCaseId = "";
	// 执行ID;
	_itoa_s(pTask->nExecuteId, szValue, 10);
	stSaveLogReq.strExecuteId = szValue;
	stSaveLogReq.strFileType = "taskLogFile";
	// 任务Id;
	//_itoa_s(pTask->nTaskId, szValue, 10);
	stSaveLogReq.strTaskId = pTask->Job.strTaskInstanceId;
	stSaveLogReq.strUserId = pTask->Job.strUserId;
	// 要上传的日志文件;
	stSaveLogReq.strUploads = "D:\\sat\\log.txt";//pTask->_strTaskLog;
	if ( SaveCaseOrTaskLog(url, stSaveLogReq, stSaveLogResp) )
	{
		return true;
	}

	return false;
}

bool CSATExecutor::ReportTaskStart(SATHTTP::STTask* pTask)
{
	TCHAR szValue[MAX_PATH] = {0};
	std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
	url.append("/ajaxInteractiveManage!setResultList.action");

	SATHTTP::STJobProcessReq stJobProcessReq;
	SATHTTP::STJobProcessResp stJobProcessResp;

	// 需要处理###
	stJobProcessReq.strResultState = "";	// 脚本执行中,认为fail;

	stJobProcessReq.strCaseScene = "";
	// 索引;
	stJobProcessReq.strCaseStep = "0";
	stJobProcessReq.strApkMD5 = "";
	stJobProcessReq.strCrashTime = "";
	// 就是Task中的ExecuteId
	_itoa_s(pTask->nExecuteId, szValue, 10);
	stJobProcessReq.strRunnerId = szValue;
	stJobProcessReq.strCPUInfo = "0";
	stJobProcessReq.strRunnedActionNameList = "";
	stJobProcessReq.strArtificialResult = "";
	stJobProcessReq.strArtificialModify = "";
	stJobProcessReq.strRunnerName = "";
	stJobProcessReq.strTaskType = "FUNCTIONALITY";
	stJobProcessReq.strCaseRepeat = "";
	stJobProcessReq.strApplicationGroup = "";
	// 实例Id;注意避坑;
	_itoa_s(pTask->Id, szValue, 10);
	stJobProcessReq.strInstanceId = szValue;
	stJobProcessReq.strCaseId = "";
	// 进度(###需要修改此处###);
	stJobProcessReq.strProgress = "0";
	// 需要将utf-8转gbk;
	stJobProcessReq.strReusltMessage = "任务开始";
	stJobProcessReq.strJobRepeat = "";
	stJobProcessReq.strScreenShot = "";
	stJobProcessReq.strStartTime = pTask->strStartTime;
	stJobProcessReq.strCrashNumber = "";
	stJobProcessReq.strCaseName = "";
	stJobProcessReq.strFailedReason = "";

	stJobProcessReq.strImgName = "";
	stJobProcessReq.strCaseIndex = "";
	// 实例Id;
	_itoa_s(pTask->nDeviceId, szValue, 10);
	stJobProcessReq.strDeviceId = szValue;
	stJobProcessReq.strSceneIndex = "";
	// 实例Id;
	//_itoa_s(pTask->nTaskId, szValue, 10);
	stJobProcessReq.strTaskId = pTask->Job.strTaskId;
	stJobProcessReq.strAnalysis = "";
	// 设备名称：即DeviceSerial;
	stJobProcessReq.strDevnceName = pTask->Job.strDeviceId;	// 命名及其不范围,一会deviceid是deviceserial,一会是id;
	// 固定为：TOTAL
	stJobProcessReq.strInfoType = "TOTAL";
	// 如果是Android设备,需要通过adb获取;
	//stJobProcessReq.strMemoryInfo = stDevice.strMemory;
	stJobProcessReq.strEndTime = "";// CTime::GetCurrentTime().Format(_T("%Y-%m-%d %H:%M:%S"));//"2019-12-16 10:18:20";
	stJobProcessReq.strRoundNumber = "1";
	stJobProcessReq.strResultType = "0";		// reportJobStart;
	stJobProcessReq.strOperationStep = "";

	if ( SetResultList(url, stJobProcessReq, stJobProcessResp) )
	{
		return true;
	}

	return false;
}

bool CSATExecutor::ReportTaskFinish(SATHTTP::STTask* pTask)
{
	TCHAR szValue[MAX_PATH] = {0};
	std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
	url.append("/ajaxInteractiveManage!setResultList.action");

	SATHTTP::STJobProcessReq stJobProcessReq;
	SATHTTP::STJobProcessResp stJobProcessResp;

	// 需要处理###
	stJobProcessReq.strResultState = "0";	// 脚本执行中,认为fail;

	stJobProcessReq.strCaseScene = "";
	// 索引;
	stJobProcessReq.strCaseStep = "0";
	stJobProcessReq.strApkMD5 = "";
	stJobProcessReq.strCrashTime = "";
	// 就是Task中的ExecuteId
	_itoa_s(pTask->nExecuteId, szValue, 10);
	stJobProcessReq.strRunnerId = szValue;
	stJobProcessReq.strCPUInfo = "0";
	stJobProcessReq.strRunnedActionNameList = "";
	stJobProcessReq.strArtificialResult = "";
	stJobProcessReq.strArtificialModify = "";
	stJobProcessReq.strRunnerName = "";
	stJobProcessReq.strTaskType = "FUNCTIONALITY";
	stJobProcessReq.strCaseRepeat = "0";
	stJobProcessReq.strApplicationGroup = "";
	// 实例Id;注意避坑;
	_itoa_s(pTask->Id, szValue, 10);
	stJobProcessReq.strInstanceId = szValue;
	stJobProcessReq.strCaseId = "";
	// 进度(###需要修改此处###);
	stJobProcessReq.strProgress = "100";
	// 需要将utf-8转gbk;
	stJobProcessReq.strReusltMessage = "任务结束";
	stJobProcessReq.strJobRepeat = "0";
	stJobProcessReq.strScreenShot = "";
	stJobProcessReq.strStartTime = pTask->strStartTime;
	stJobProcessReq.strCrashNumber = "";
	stJobProcessReq.strCaseName = "";
	stJobProcessReq.strFailedReason = "";

	stJobProcessReq.strImgName = "";
	stJobProcessReq.strCaseIndex = "";
	// 实例Id;
	_itoa_s(pTask->nDeviceId, szValue, 10);
	stJobProcessReq.strDeviceId = szValue;
	stJobProcessReq.strSceneIndex = "0";
	// 实例Id;
	//_itoa_s(pTask->nTaskId, szValue, 10);
	stJobProcessReq.strTaskId = pTask->Job.strTaskId;
	stJobProcessReq.strAnalysis = "";
	// 设备名称：即DeviceSerial;
	stJobProcessReq.strDevnceName = pTask->Job.strDeviceId;	// 命名及其不范围,一会deviceid是deviceserial,一会是id;
	// 固定为：TOTAL
	stJobProcessReq.strInfoType = "";
	// 如果是Android设备,需要通过adb获取;
	//stJobProcessReq.strMemoryInfo = stDevice.strMemory;
	stJobProcessReq.strEndTime = CTime::GetCurrentTime().Format(_T("%Y-%m-%d %H:%M:%S"));//"2019-12-16 10:18:20";
	stJobProcessReq.strRoundNumber = "1";
	stJobProcessReq.strResultType = "1";		// reportJobFinish;
	stJobProcessReq.strOperationStep = "";

	if ( SetResultList(url, stJobProcessReq, stJobProcessResp) )
	{
		return true;
	}

	return false;
}

bool CSATExecutor::GetCaseXMLResult(std::string xmlpath, std::vector<STCaseItem> &vtCaseItem)
{
	// 解析xml;
	tinyxml2::XMLDocument doc;
	if (tinyxml2::XML_SUCCESS != doc.LoadFile(xmlpath.c_str()) ) {
		return false;
	}

	tinyxml2::XMLElement *pXmlRoot = NULL;
	if ((pXmlRoot = doc.RootElement()) == NULL)
		return false;
	
	if (_tcsicmp(pXmlRoot->Value(), "results") != 0)
		return false;
	
	tinyxml2::XMLElement *pXmlElent = pXmlRoot->FirstChildElement();
	while (pXmlElent) {
		if (_tcsicmp(pXmlElent->Value(), _T("item")) == 0) {
			STCaseItem cItem;
			tinyxml2::XMLElement *pItem = pXmlElent->FirstChildElement();
			while (pItem) {
				if (_tcsicmp(pItem->Value(), _T("name")) == 0)
				{
					cItem.name = pItem->GetText();
				}
				else if (_tcsicmp(pItem->Value(), _T("result")) == 0)
				{
					cItem.result = pItem->BoolText();
				}
				else if (_tcsicmp(pItem->Value(), _T("data")) == 0)
				{
					cItem.data = pItem->GetText();
				}
				else if (_tcsicmp(pItem->Value(), _T("log")) == 0)
				{
					cItem.log = pItem->GetText();
				}
				else if (_tcsicmp(pItem->Value(), _T("remark")) == 0)
				{
					cItem.remark = pItem->GetText();
				}
				else if (_tcsicmp(pItem->Value(), _T("screen")) == 0)
				{
					cItem.imgs.push_back(pItem->GetText());
				}

				pItem = pItem->NextSiblingElement();
			}

			// 压入容器;
			if ( cItem.name.size() )
				vtCaseItem.push_back(cItem);
		}

		pXmlElent = pXmlElent->NextSiblingElement();
	}
	
	return true;
}

void CSATExecutor::StartWork()
{
	m_hEventHearbeat = CreateEvent(NULL, TRUE, FALSE, NULL);
	if ( m_hEventHearbeat == NULL ) {
		_tprintf_s(_T("创建事件失败\n"));
		return;
	}

	m_hEventExcuteScript = CreateEvent(NULL, TRUE, FALSE, NULL);
	if ( m_hEventExcuteScript == NULL ) {
		_tprintf_s(_T("创建事件失败2\n"));
		return;
	}

	m_hThreadHearbeat = CreateThread(NULL, 0, HearbeatThread, this, 0, NULL);
	if ( m_hThreadHearbeat == NULL) {
		SetEvent(m_hEventHearbeat);
		SetEvent(m_hEventExcuteScript);
		CloseHandle(m_hEventHearbeat);
		CloseHandle(m_hEventExcuteScript);
		m_hEventHearbeat = NULL;
		m_hEventExcuteScript = NULL;
		_tprintf_s(_T("创建线程失败\n"));
		return;
	}

	m_hThreadExcuteScript = CreateThread(NULL, 0, ExecuteScriptThread, this, 0, NULL);
	if ( m_hThreadExcuteScript == NULL ) {
		SetEvent(m_hEventHearbeat);
		SetEvent(m_hEventExcuteScript);
		CloseHandle(m_hEventHearbeat);
		CloseHandle(m_hEventExcuteScript);
		m_hEventHearbeat = NULL;
		m_hEventExcuteScript = NULL;
		WaitForSingleObject(m_hThreadHearbeat,INFINITE);
		if (m_hThreadHearbeat)
			CloseHandle(m_hThreadHearbeat);
		m_hThreadHearbeat = NULL;
		_tprintf_s(_T("创建线程失败2\n"));
		return;
	}
}

void CSATExecutor::EndofWork()
{
	//////////////////////////////////////////////////////////////////////////
	// 设置事件有信号;
	if ( m_hEventHearbeat )
		SetEvent(m_hEventHearbeat);

	// 等待线程结束;
	if ( m_hThreadHearbeat ) {
		WaitForSingleObject(m_hThreadHearbeat, INFINITE);
		CloseHandle(m_hThreadHearbeat);
		m_hThreadHearbeat = NULL;
	}

	// 关闭事件句柄;
	if ( m_hEventHearbeat ) {
		CloseHandle(m_hEventHearbeat);
		m_hEventHearbeat = NULL;
	}

	//////////////////////////////////////////////////////////////////////////
	// 设置事件有信号;
	if ( m_hEventExcuteScript )
		SetEvent(m_hEventExcuteScript);

	// 等待线程结束;
	if ( m_hThreadExcuteScript ) {
		WaitForSingleObject(m_hThreadExcuteScript, INFINITE);
		CloseHandle(m_hThreadExcuteScript);
		m_hThreadExcuteScript = NULL;
	}

	// 关闭事件句柄;
	if ( m_hEventExcuteScript ) {
		CloseHandle(m_hEventExcuteScript);
		m_hEventExcuteScript = NULL;
	}
}

DWORD CSATExecutor::HearbeatThread(LPVOID lpVoid)
{
	CSATExecutor *that = (CSATExecutor*)lpVoid;
	if ( !that ) return 0;
	
	do {
		// 没有登录成功,不查询;
		if ( !that->m_bLogin ) continue;
		// 更新设备;
		that->UpdateDevice();
		// 脚本保存目录;
		std::string strScriptSaveDir;
		SATHTTP::STHeartbeatReq stHeartbeatReq;
		SATHTTP::STHeartbeatResp stHeartbeatResp;
		std::string url = GLOBAL::g_stSATConfig.szExecuteServer;
		url.append("/ajaxInteractiveManage!executeHeartbeat.action");

		stHeartbeatReq.strUserName = that->m_stLoginReq.strUserName;
		stHeartbeatReq.strRunnerMac = that->m_stLoginReq.strMAC;
		stHeartbeatReq.devicelist.assign(that->m_vtDevice.begin(), that->m_vtDevice.end());
		if ( Heartbeat(url, stHeartbeatReq, stHeartbeatResp) ) {
			std::vector<SATHTTP::STTask>::iterator it = stHeartbeatResp.vtTask.begin();
			for ( ; it != stHeartbeatResp.vtTask.end(); it++ ) {
				if (!that->IsTaskExist(*it)) {
					// 将任务压入队列中;
					AutoThreadSection ats(&that->m_csTask);
					// 同时下载任务;
					std::string host = GLOBAL::g_stSATConfig.szCaseServer;
					std::string url = host + "/ajaxInteractiveManage!getCaseFileListUrl.action";
					std::vector<SATHTTP::STCase>::iterator _case = it->Job.vtCases.begin();
					for ( int i = 1; _case != it->Job.vtCases.end(); _case++) {
						// 下载脚本;
						_case->_nCaseStep = i++;
						SATHTTP::STScriptUrlResp stScriptUrlResp;
						// 脚本保存路径;
						strScriptSaveDir = GLOBAL::g_stSATConfig.szScriptDir;
						strScriptSaveDir.append(it->Job.strProjectName+"\\");
						strScriptSaveDir.append(it->Job.strUniqueId+"\\");
						// 把冒号改成下划线;
						strScriptSaveDir.append(GLOBAL::Replace(it->Job.strDeviceId, "_", ":")+"\\");
						if ( DownloadScript(url, _case->strId, strScriptSaveDir, stScriptUrlResp) ) {
							_case->_strFileDir = stScriptUrlResp._strFileDir;
							_case->_strFileName = stScriptUrlResp._strFileName;
							_case->_strScriptPath = stScriptUrlResp._strScripFile;
						}
					}

					that->m_vtTask.push_back(*it);

					// 通知SAT服务器,脚本开始执行;
					// 待开发：同时将任务存储到数据库中;
					/*
					db process
					*/
				}
			}
		}

	} while ( WaitForSingleObject(that->m_hEventHearbeat, 5000) == WAIT_TIMEOUT );

	return 0;
}

DWORD CSATExecutor::ExecuteScriptThread(LPVOID lpVoid)
{
	CSATExecutor *that = (CSATExecutor*)lpVoid;
	if ( !that ) return 0;

	do {
		// 删除已完成的任务;
		that->DelFinishedTask();
		// 是否有任务在执行;
		SATHTTP::STTask *pTask = that->IsThereATaskInProcess();
		if ( pTask ) {// 有任务在执行中;
			if ( pTask->_bConcurrent ) {// 并发;

			}
			else {// 串行;
				// 是否有脚本用例在执行;
				SATHTTP::STCase* pCase = that->IsCaseScriptProcess(pTask->Job.vtCases);
				if ( pCase ) {
					CScriptExecutor *pExcutor = (CScriptExecutor*)pCase->_pExcutor;
					if ( pExcutor ) {
						if ( pExcutor->IsScriptOver() ) {
							pCase->_nExecutionState = 2;
							// 上报服务器,完成脚本用例,并上传用例结果;
							that->ReportCaseResult(pTask, pCase);
						}
						else {
							// 判断是否超时;
							ULONGLONG ulCurTickCount = GetTickCount64();
							if ( ulCurTickCount - pExcutor->GetActiveTickCount() > GLOBAL::g_stSATConfig.dwScriptTimeout ) {	
								// 结束进程;
								pExcutor->EndSubprocess();
								// 超时中断;
								pCase->_nExecutionState = 3;
								// 上报用例结果;
								that->ReportCaseResult(pTask, pCase);
							}
						}
					}
				}
				else {
					// 没有在执行的用例,开始执行新的用例;
					pCase = that->ExecuteFreeCaseScript(pTask);
					if ( NULL == pCase ) {
						// 没有空闲的用例可执行,说明所有用例已执行完成;
						pTask->_nExecutionState = 2;
						// 上报任务完成;
						that->ReportTaskFinish(pTask);
						// 上报任务结果;
						that->UploadTaskLog(pTask);
					}
				}
			}
		}
		else {
			// 获取空闲的任务;
			pTask = that->GetFreeTask();
			if ( pTask ) {
				// 是否支持并发;
				if ( pTask->_bConcurrent ) {
					// 暂时全部一起并发;
					std::vector<SATHTTP::STCase>::iterator _case = pTask->Job.vtCases.begin();
					for ( ; _case != pTask->Job.vtCases.end(); _case++) {
						if (!_case->_pExcutor) {					
							CScriptExecutor *pExcutor = new CScriptExecutor();
							if ( pExcutor ) {
								_case->_pExcutor = pExcutor;
								pExcutor->InitScript(_case->_strScriptPath, _case->_strFileDir + "\\" + _case->_strFileName + ".txt", "", SUBPROCESS);
								pExcutor->StartScript();
								// 标记用例执行中;
								_case->_nExecutionState = 1;
							}
						}
					}

					// 标记任务为执行中;
					pTask->_nExecutionState = 1;
				}
				else {
					// 是否有用例脚本在执行;
					SATHTTP::STCase* pCase = that->IsCaseScriptProcess(pTask->Job.vtCases);
					if ( !pCase ) {
						// 执行空闲用例脚本;
						that->ExecuteFreeCaseScript(pTask);
					}				
				}

				// 通知SAT服务器,脚本开始执行;
				that->NotifyTaskStart(pTask);

				// 通知SAT服务器,脚本开始;
				that->ReportTaskStart(pTask);
			}	
		}
	} while ( WaitForSingleObject(that->m_hEventExcuteScript, 10000) == WAIT_TIMEOUT );

	return 0;
}