?? stressman.cpp
字號:
////////////////////////////////////////////////////////////////////////////
//
// StressMan.cpp - StressMark 管理所有測試用例(線程)的類
//
// created by Wang Yong Gang, 2001-08-07 ( version 1.0 )
// modified by Wang Yong Gang, 2002-02-16 ( version 1.1 )
//
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "StressCase.h"
#include "StressMan.h"
extern struct StressCaseDefination g_arrTestSuite[];
StressMan::StressMan(CListCtrl& list)
: m_list(list), m_event(FALSE, TRUE)
{
m_arrThreadInfo = NULL;
m_nTestSuiteArraySize = 0;
}
StressMan::~StressMan()
{
for(int i = 0; i < m_arrCaseObjects.GetSize(); i++)
{
StressCase* p = (StressCase*)m_arrCaseObjects.GetAt(i);
delete p;
}
m_arrCaseObjects.RemoveAll();
m_arrThreads.RemoveAll();
if (m_arrThreadInfo)
delete[] m_arrThreadInfo;
}
bool StressMan::InitializeCaseList()
{
m_arrCaseObjects.RemoveAll();
// 統計測試用例有多少種,并根據設置的線程數為
// 每種測試用例創建若干對象實例
int nIndex = 0; StressCase* p;
m_nTestSuiteArraySize = 0;
while(g_arrTestSuite[m_nTestSuiteArraySize].m_pCaseClass != NULL)
{
g_arrTestSuite[m_nTestSuiteArraySize].m_nClients =
min(100, max(1, g_arrTestSuite[m_nTestSuiteArraySize].m_nClients));
g_arrTestSuite[m_nTestSuiteArraySize].m_nTimes =
min(10000, max(1, g_arrTestSuite[m_nTestSuiteArraySize].m_nTimes));
for(int i = 0; i < g_arrTestSuite[m_nTestSuiteArraySize].m_nClients; i++)
{
p = (StressCase*)(g_arrTestSuite[m_nTestSuiteArraySize]
.m_pCaseClass->CreateObject());
p->m_strName = g_arrTestSuite[m_nTestSuiteArraySize].m_strName;
p->m_nID = nIndex + 1;
p->m_nClientID = i + 1;
m_arrCaseObjects.Add(p);
nIndex++;
}
m_nTestSuiteArraySize++;
}
if (!m_nTestSuiteArraySize)
{
AfxMessageBox(_T("未定義任何測試用例"));
return false;
}
m_arrThreadInfo = new ThreadInfo[m_arrCaseObjects.GetSize()];
if (m_arrThreadInfo == NULL)
{
AfxMessageBox(_T("內存不足"));
return false;
}
// 顯示所有線程信息
m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
m_list.InsertColumn(0, _T("序號"), LVCFMT_LEFT, 40);
m_list.InsertColumn(1, _T("測試用例名"), LVCFMT_LEFT, 130);
m_list.InsertColumn(2, _T("線程"), LVCFMT_LEFT, 40);
m_list.InsertColumn(3, _T("計劃執行次數"), LVCFMT_RIGHT, 90);
m_list.InsertColumn(4, _T("已執行次數"), LVCFMT_RIGHT, 80);
m_list.InsertColumn(5, _T("平均每次耗時(秒)"), LVCFMT_RIGHT, 120);
m_list.InsertColumn(6, _T("當前狀態"), LVCFMT_LEFT, 300);
nIndex = 0; TCHAR temp[20];
for(int i = 0; i < m_nTestSuiteArraySize; i++)
{
for(int j = 0; j < g_arrTestSuite[i].m_nClients; j++)
{
StressCase* p = (StressCase*)m_arrCaseObjects.GetAt(nIndex);
_stprintf(temp, _T("%03d"), nIndex + 1);
m_list.InsertItem(nIndex, temp);
m_list.SetItem(nIndex, 1, LVIF_TEXT,
g_arrTestSuite[i].m_strName, 0, 0, 0, 0);
_stprintf(temp, _T("%03d"), j + 1);
m_list.SetItem(nIndex, 2, LVIF_TEXT, temp, 0, 0, 0, 0);
_stprintf(temp, _T("%d"), g_arrTestSuite[i].m_nTimes);
m_list.SetItem(nIndex, 3, LVIF_TEXT, temp, 0, 0, 0, 0);
_stprintf(temp, _T("%d"), p->m_nFinishedTimes);
m_list.SetItem(nIndex, 4, LVIF_TEXT, temp, 0, 0, 0, 0);
_stprintf(temp, _T("%.3f"),
(p->m_nFinishedTimes != 0) ? p->m_dTime /
(double)p->m_nFinishedTimes : 0.0);
m_list.SetItem(nIndex, 5, LVIF_TEXT, temp, 0, 0, 0, 0);
m_list.SetItem(nIndex, 6, LVIF_TEXT, p->m_strState, 0, 0, 0, 0);
nIndex++;
}
}
return true;
}
bool StressMan::CanSetState(int oldState, int newState)
{
// 當原狀態是 ready 或 error 時,
// 不能設置新狀態為 ready 或 stopping
if ((oldState == StressCase::error || oldState == StressCase::ready)
&& ( newState == StressCase::ready || newState == StressCase::stopping))
return false;
else
return true;
}
void StressMan::SetThreadState(int nIndex, int nState, LPCTSTR strMessage)
{
int nCount = 0;
if (nIndex < 0)
{
for(int i = 0; i < m_nTestSuiteArraySize; i++)
{
for(int j = 0; j < g_arrTestSuite[i].m_nClients; j++)
{
StressCase* p = (StressCase*)m_arrCaseObjects.GetAt(nCount);
if (CanSetState(p->m_nState, nState))
{
p->SetClientState(nState, strMessage);
m_list.SetItem(nCount, 6, LVIF_TEXT, p->m_strState, 0, 0, 0, 0);
}
nCount++;
}
}
}
else
{
StressCase* p = (StressCase*)m_arrCaseObjects.GetAt(nIndex);
if (CanSetState(p->m_nState, nState))
{
p->SetClientState(nState, strMessage);
m_list.SetItem(nIndex, 6, LVIF_TEXT, p->m_strState, 0, 0, 0, 0);
}
}
}
void StressMan::SetThreadFinishedTimes(int nIndex, int nTimes)
{
int nCount = 0; TCHAR temp[20];
if (nIndex < 0)
{
for(int i = 0; i < m_nTestSuiteArraySize; i++)
{
for(int j = 0; j < g_arrTestSuite[i].m_nClients; j++)
{
StressCase* p = (StressCase*)m_arrCaseObjects.GetAt(nCount);
p->m_nFinishedTimes = nTimes;
_stprintf(temp, _T("%d"), p->m_nFinishedTimes);
m_list.SetItem(nCount, 4, LVIF_TEXT, temp, 0, 0, 0, 0);
nCount++;
}
}
}
else
{
StressCase* p = (StressCase*)m_arrCaseObjects.GetAt(nIndex);
p->m_nFinishedTimes = nTimes;
_stprintf(temp, _T("%d"), p->m_nFinishedTimes);
m_list.SetItem(nIndex, 4, LVIF_TEXT, temp, 0, 0, 0, 0);
}
}
void StressMan::SetThreadTime(int nIndex, double dTime)
{
int nCount = 0; TCHAR temp[20];
if (nIndex < 0)
{
for(int i = 0; i < m_nTestSuiteArraySize; i++)
{
for(int j = 0; j < g_arrTestSuite[i].m_nClients; j++)
{
StressCase* p = (StressCase*)m_arrCaseObjects.GetAt(nCount);
p->m_dTime = dTime;
_stprintf(temp, _T("%.3f"),
(p->m_nFinishedTimes != 0) ? p->m_dTime /
(double)p->m_nFinishedTimes : 0.0);
m_list.SetItem(nCount, 5, LVIF_TEXT, temp, 0, 0, 0, 0);
nCount++;
}
}
}
else
{
StressCase* p = (StressCase*)m_arrCaseObjects.GetAt(nIndex);
p->m_dTime = dTime;
_stprintf(temp, _T("%.3f"),
(p->m_nFinishedTimes != 0) ? p->m_dTime /
(double)p->m_nFinishedTimes : 0.0);
m_list.SetItem(nIndex, 5, LVIF_TEXT, temp, 0, 0, 0, 0);
}
}
bool StressMan::StartSuite()
{
SetThreadState(-1, StressCase::starting);
SetThreadFinishedTimes(-1, 0);
SetThreadTime(-1, 0.0);
AfxGetMainWnd()->InvalidateRect(NULL);
AfxGetMainWnd()->UpdateWindow();
CWinThread* pThread;
// 設置同步事件
m_event.ResetEvent();
// 線程活動數
m_lives = 0;
// 創建所有測試用例線程
m_arrThreads.RemoveAll();
for(int i = 0; i < m_nTestSuiteArraySize; i++)
{
for(int j = 0; j < g_arrTestSuite[i].m_nClients; j++)
{
m_arrThreadInfo[m_lives].pStressMan = this;
m_arrThreadInfo[m_lives].nIndex = m_lives;
m_arrThreadInfo[m_lives].nTimes = g_arrTestSuite[i].m_nTimes;
m_arrThreadInfo[m_lives].nInterval = g_arrTestSuite[i].m_nInterval;
pThread = AfxBeginThread(StressMan::ThreadBody, &(m_arrThreadInfo[m_lives]));
m_arrThreads.Add(pThread);
m_lives++;
}
}
// 創建監視線程
m_MonitorThreadInfo.pStressMan = this;
m_MonitorThreadInfo.nIndex = 0;
m_MonitorThreadInfo.nTimes = 0;
m_pMonitorThread = AfxBeginThread(StressMan::MonitorThreadBody, &m_MonitorThreadInfo);
// 設置同步事件,同時啟動所有用例線程
m_event.SetEvent();
return true;
}
bool StressMan::StopSuite()
{
SetThreadState(-1, StressCase::stopping);
return true;
}
bool StressMan::KillSuite()
{
if (WaitForSingleObject(m_pMonitorThread->m_hThread, 0) != WAIT_OBJECT_0)
TerminateThread(m_pMonitorThread->m_hThread, 0);
int nCount = m_arrThreads.GetSize();
CWinThread* p;
for(int i = 0; i < nCount; i++)
{
p = (CWinThread*)m_arrThreads.GetAt(i);
if (WaitForSingleObject(p->m_hThread, 0) != WAIT_OBJECT_0)
TerminateThread(p->m_hThread, 0);
}
SetThreadState(-1, StressCase::ready);
return true;
}
UINT StressMan::ThreadBody( LPVOID pParam )
{
ThreadInfo* pti = (ThreadInfo*)pParam;
StressCase* pCase = (StressCase*)pti->pStressMan->m_arrCaseObjects.GetAt(pti->nIndex);
CString strErrorMessage = _T("");
LARGE_INTEGER freq, c1, c2;
QueryPerformanceFrequency(&freq);
double dTime; int i;
// 初始化
if (!pCase->OnInitialize(strErrorMessage))
{
pti->pStressMan->SetThreadState(pti->nIndex, StressCase::error, strErrorMessage);
goto exit_pos;
}
// 設置正運行標記
pti->pStressMan->SetThreadState(pti->nIndex, StressCase::running);
// 等待同步事件
WaitForSingleObject(pti->pStressMan->m_event.m_hObject, 60 * 1000l);
// 測試
for(i = 0; i < pti->nTimes; i++)
{
if (pCase->m_nState == StressCase::stopping)
break;
QueryPerformanceCounter(&c1);
if (!pCase->OneStep(strErrorMessage))
{
pti->pStressMan->SetThreadState(pti->nIndex, StressCase::error, strErrorMessage);
break;
}
QueryPerformanceCounter(&c2);
// 刷新已執行次數和執行總時間
pti->pStressMan->SetThreadFinishedTimes(pti->nIndex, i+1);
dTime = pCase->m_dTime +
((double)c2.QuadPart - (double)c1.QuadPart) / (double)freq.QuadPart;
pti->pStressMan->SetThreadTime(pti->nIndex, dTime);
// 根據設置,休息一個時間間隔
if (pti->nInterval) Sleep(pti->nInterval);
}
// 清理
if (!pCase->OnUninitialize(strErrorMessage))
pti->pStressMan->SetThreadState(pti->nIndex, StressCase::error, strErrorMessage);
else
pti->pStressMan->SetThreadState(pti->nIndex, StressCase::ready);
exit_pos:
InterlockedDecrement(&pti->pStressMan->m_lives);
return 0;
}
#define WM_USER_ALL_FINISHED (WM_USER+1)
UINT StressMan::MonitorThreadBody( LPVOID pParam )
{
ThreadInfo* pti = (ThreadInfo*)pParam;
for(;;)
{
// 如果所有的用例線程都已結束,就通知主窗口做相應的處理
if (pti->pStressMan->m_lives <= 0)
{
CWnd* pWnd = AfxGetMainWnd();
pWnd->PostMessage(WM_USER_ALL_FINISHED);
break;
}
Sleep(100);
}
return 0;
}
bool StressMan::ReportSuite(LPCTSTR strPath)
{
TRY
{
SYSTEMTIME st; TCHAR buf[100]; DWORD dw = 100;
GetLocalTime(&st);
GetComputerName(buf, &dw);
CString cs;
CStdioFile file(strPath,
CFile::typeText | CFile::modeWrite | CFile::modeCreate );
file.WriteString(_T("\n=======================\n"));
file.WriteString(_T(" StressMark 測試報告\n"));
file.WriteString(_T("=======================\n"));
cs.Format(_T("\n測試機: %s\n"), buf);
file.WriteString(cs);
cs.Format(_T("報告時間: %04d-%02d-%02d %02d:%02d\n"),
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute);
file.WriteString(cs);
file.WriteString(_T("\n"));
file.WriteString(_T("序號\t用例名稱\t線程\t計劃重復次數"
"\t已執行次數\t平均每次耗時(秒)\t當前狀態\n"));
file.WriteString(_T("----------------------------------"
"----------------------------------"
"------------------------------------------\n"));
int nIndex = 0;
for(int i = 0; i < m_nTestSuiteArraySize; i++)
{
for(int j = 0; j < g_arrTestSuite[i].m_nClients; j++)
{
StressCase* p = (StressCase*)m_arrCaseObjects.GetAt(nIndex);
cs.Format(_T("%03d\t%s\t%03d\t%d\t%d\t%.3f\t%s\n"),
nIndex + 1,
g_arrTestSuite[i].m_strName,
j + 1,
g_arrTestSuite[i].m_nTimes,
p->m_nFinishedTimes,
(p->m_nFinishedTimes != 0) ? p->m_dTime /
(double)p->m_nFinishedTimes : 0.0,
p->m_strState);
file.WriteString(cs);
nIndex++;
}
}
file.WriteString(_T(""));
file.Close();
cs.Format(_T("notepad %s"), strPath);
WinExec(cs, SW_SHOW);
}
CATCH_ALL(e)
{
e->ReportError();
return false;
}
END_CATCH_ALL
return true;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -