ecostest.cpp
来自「基于ecos的redboot」· C++ 代码 · 共 1,792 行 · 第 1/4 页
CPP
1,792 行
// If we can there is a GDB instruction to send to gdb, do it
String str;
if(GetDirective(_T("GDB:"),str,m_nLastGdbInst)){
strCmd=str;
m_nCmdIndex--; // undo increment above
}
if(0==_tcscmp(_T("load"),strCmd)){
// load command issued - we are now "downloading"
m_bDownloading=true;
} else if(0==_tcscmp(_T("run"),strCmd) || 0==_tcscmp(_T("cont"),strCmd)){
SetStatus(NoResult);
}
strCmd+=_TCHAR('\n');
LogString(strCmd);
m_psp->Send(strCmd);
}
}
// If there is a EXEC instruction to process, obey it
String strCmd;
while(GetDirective(_T("EXEC:"),strCmd,m_nLastExecInst)){
CSubprocess *pExecsp=new CSubprocess;
pExecsp->SetPath(m_strPath);
if(!pExecsp->Run(AppendFunc,this,(LPCTSTR)strCmd,false)){
Log(_T("%%%% Failed to create process '%s'\n"),(LPCTSTR)strCmd);
delete pExecsp;
} else {
m_arpExecsp.push_back(pExecsp);
}
}
// If there is a PIPE instruction to process, obey it
while(GetDirective(_T("PIPE:"),strCmd,m_nLastPipeInst)){
if(m_pspPipe){
Log(_T("%%%% Two PIPE commands are a no-no\n"));
} else {
m_pspPipe=new CSubprocess;
m_pspPipe->SetPath(m_strPath);
if(!m_pspPipe->Run(AppendFunc,this,(LPCTSTR)strCmd,false)){
Log(_T("%%%% Failed to create process '%s'\n"),(LPCTSTR)strCmd);
delete m_pspPipe;
m_pspPipe=0;
} else {
// Send what we read have so far
m_pspPipe->Send(m_strOutput);
}
}
}
while(GetDirective(_T("TIMEOUT:"),strCmd,m_nLastTimeoutInst)){
int n=_ttoi(strCmd);
if(n){
SetTimeouts(n); // second parameter is download timeout, which is now irrelevant
} else {
Log(_T("%%%% Illegal timeout specified: %s\n"),(LPCTSTR)strCmd);
}
}
}
void CeCosTest::RunInferior(LPCTSTR pszCmdline)
{
m_psp=new CSubprocess;
m_psp->SetContinuationFunc(SCheckForTimeout,this);
try {
m_nMaxInactiveTime=0;
m_nTotalTime=0;
m_nDownloadTime=0;
m_nOutputLen=0;
m_bDownloading=false;
// Decide on the baseline status - NotStarted if there is a download element, NoResult otherwise.
m_Status=NoResult;
for(unsigned int i=0;i<m_arstrInferiorCmds.size();i++){
if(0==_tcscmp(_T("run"),m_arstrInferiorCmds[i]) || 0==_tcscmp(_T("cont"),m_arstrInferiorCmds[i])){
m_Status=NotStarted;
break;
}
}
TRACE(_T("Status <- %s\n"),(LPCTSTR)Image(m_Status));
m_tPrevSample=0; // force an initial reading
m_tInferiorCpuTime=0;
m_tBase=m_tBase0=InferiorTime(); // Returns either Now() or nothing
m_tWallClock0=Now();
m_nCmdIndex=0;
TRACE(_T("RunGDB()\n"));
m_nLastGdbInst=m_nLastExecInst=m_nLastTimeoutInst=m_nLastPipeInst=0;
m_psp->SetPath(m_strPath);
if(m_psp->Run(SInferiorOutputFunc,this,pszCmdline,true)){
if(m_pspPipe){
m_pspPipe->Send(_T("\n"));
m_pspPipe->CloseInput();
if(m_pspPipe->Wait(5000)){
// OK the pipe process terminated.
int rc=m_pspPipe->GetExitCode();
if(0!=rc){
Log(_T("%%%% Pipe process returned rc=%d\n"),rc);
SetStatus(Fail);
}
} else {
LogString(_T("%%%% Pipe process would not complete\n"));
}
}
AnalyzeOutput();
} else {
Log(_T("Failed to run \"%s\" - %s\n"),pszCmdline,(LPCTSTR)m_psp->ErrorString());
}
}
catch(...){
ERROR(_T("!!! Exception caught in RunInferior()\n"));
}
/*
if(CeCosTestPlatform::COYSIM==m_ep.Platform()->Type()){
FILE *f=_tfopen(_T("cpu.log"),_T("r") MODE_TEXT);
TCHAR buf[512];
if(f){
LogString(_T("$$$ Contents of cpu.log start\n"));
while(_fgetts(buf,sizeof(buf)-1,f)){
LogString(buf);
}
LogString(_T("$$$ Contents of cpu.log end\n"));
fclose(f);
}
_tunlink(_T("cpu.log"));
}
*/
delete m_psp; // will cause process to be killed as necessary and completion to be waited for
m_psp=NULL;
for(int i=0;i<(signed)m_arpExecsp.size();i++){
delete (CSubprocess *)m_arpExecsp[i]; // ditto
}
m_arpExecsp.clear();
TRACE(_T("Exiting RunInferior()\n"));
}
void CeCosTest::AnalyzeOutput()
{
// This test is pulled out to allow ser_filter to simulate a test failure
if(OutputContains(_T("FAIL:"))){
SetStatus(Fail);
}
if(OutputContains(_T("EXIT:"))||OutputContains(_T("NOTAPPLICABLE:"))){
static LPCTSTR arpszKeepAlive[]={_T("FAIL:"),_T("NOTAPPLICABLE:"), _T("PASS:")};
static const StatusType arStatus[] ={Fail, Inapplicable, Pass};
for(unsigned int i=0;i<sizeof arpszKeepAlive/sizeof arpszKeepAlive[0];i++){
if(OutputContains(arpszKeepAlive[i])){
TRACE(_T("DriveInferior: saw '%s'\n"),arpszKeepAlive[i]);
SetStatus(arStatus[i]); // Do not break!
}
}
}
// Certain output spells failure...
if(OutputContains(_T("cyg_assert_fail ("))){
SetStatus(AssertFail);
} else {
static LPCTSTR arpszSignals[]={_T("SIGBUS"), _T("SIGSEGV"), _T("SIGILL"), _T("SIGFPE"), _T("SIGSYS"), _T("SIGTRAP")};
for(unsigned int i=0;i<sizeof arpszSignals/sizeof arpszSignals[0];i++){
String str1,str2;
str1.Format(_T("signal %s"),arpszSignals[i]);
str2.Format(_T("handle %s nostop"),arpszSignals[i]);
if(OutputContains(str1)&&!OutputContains(str2)){
SetStatus(Fail);
break;
}
}
}
int nIndex=0;
String str;
while(GetDirective(_T("EXPECT:"),str,nIndex)){
// s1 is the pointer to the text following the expect - that to be tested
LPCTSTR s1=(LPCTSTR)m_strOutput+nIndex;
while (_istspace(*s1)){
s1++;
}
// whereas s2 is the pointer to the text in the expect string (what we are expecting)
LPCTSTR s2=(LPCTSTR)str;
while(*s2){
if(*s2!=*s1){
Log(_T("EXPECT:<> failure - expected '%s' saw '%s'\n"),(LPCTSTR)str,(LPCTSTR)m_strOutput+nIndex);
SetStatus(Fail);
break;
}
s1++;
s2++;
}
}
}
bool CeCosTest::ExecutionParameters::FromStr(LPCTSTR psz)
{
String str1,str2,str3,str4,str5;
int nUseFilter,nUnused2,nUnused3;
int nLen=_tcslen(psz);
_stscanf(psz,_T("%s %s %d %d %d %d %d %d %d %d %s %s %s"),
str1.GetBuffer(1+nLen),
str2.GetBuffer(1+nLen),
&m_nActiveTimeout,
&m_nDownloadTimeout,
&m_nUnused1,
&m_nUnused2,
&m_nUnused3,
&nUseFilter,
&nUnused2,
&nUnused3,
str3.GetBuffer(1+nLen),
str4.GetBuffer(1+nLen),
str5.GetBuffer(1+nLen)
);
m_bUseFilter=(0!=nUseFilter);
m_bUnused2=(0!=nUnused2);
m_bUnused3=(0!=nUnused3);
str1.ReleaseBuffer();
str2.ReleaseBuffer();
str3.ReleaseBuffer();
str4.ReleaseBuffer();
str5.ReleaseBuffer();
m_Target=str1;
int r;
for(r=0;r<RequestTypeMax;r++){
if(0==_tcscmp(arRequestImage[r],str2)){
break;
}
}
m_Request=(RequestType)r;
return CeCosTestPlatform::IsValid(m_Target);
}
CeCosTest::ExecutionParameters::ExecutionParameters (RequestType r,
LPCTSTR Target,
Duration nActiveTimeout/*=NOTIMEOUT*/,
Duration nDownloadTimeout/*=NOTIMEOUT*/):
m_bUseFilter(true),
m_Target(Target),
m_nActiveTimeout(nActiveTimeout),
m_nDownloadTimeout(nDownloadTimeout),
m_Request(r),
m_nUnused1(0),
m_nUnused2(0),
m_nUnused3(0),
m_bUnused2(false),
m_bUnused3(false)
{
}
String CeCosTest::ExecutionParameters::Image() const
{
String str;
str.Format(_T("%s %s %d %d %d %d %d %d %d %d"),(LPCTSTR)PlatformName(),(LPCTSTR)Image(Request()),
ActiveTimeout(),DownloadTimeout(),
m_nUnused1,
m_nUnused2,
m_nUnused3,
m_bUseFilter,
m_bUnused2,
m_bUnused3);
return str;
}
bool CeCosTest::GetTargetReady(String &strHostPort)
{
bool rc=false;
int nTargetReady;
do{
if(!m_pSock->recvInteger(nTargetReady,_T("Target ready"),120*1000)){
Log(_T("Failed to read target ready indicator from server - %s\n"),(LPCTSTR)m_pSock->SocketErrString());
break;
}
switch(nTargetReady){
case 0:
LogString(_T("Failed to reset target"));
break;
case 1:
if(m_pSock->recvString(strHostPort, _T("host:port"))){
TRACE(_T("Instructed to use %s\n"),(LPCTSTR)strHostPort);
rc=true;
} else {
Log(_T("Failed to read host:port - %s\n"),(LPCTSTR)m_pSock->SocketErrString());
}
break;
case 2:
{
String strOutput;
if(m_pSock->recvString(strOutput, _T("output"))){
LogString(strOutput);
} else {
Log(_T("Failed to read output\n"),(LPCTSTR)m_pSock->SocketErrString());
return false;
}
}
break;
}
} while(2==nTargetReady);
return rc;
}
CeCosTest::ServerStatus CeCosTest::ServerStatusValue(LPCTSTR psz)
{
int s;
for(s=0;s<ServerStatusMax;s++){
if(0==_tcsicmp(psz,arServerStatusImage[s])){
break;
}
}
return (ServerStatus)s;
}
// Gets a directive from the test output (like EXEC:)
bool CeCosTest::GetDirective(LPCTSTR pszDirective, String &str, int &nIndex)
{
bool rc=false;
ENTERCRITICAL;
LPCTSTR pszOutput=(LPCTSTR)m_strOutput;
LPCTSTR pc=_tcsstr(pszOutput+nIndex,pszDirective);
if(pc){
pc+=_tcslen(pszDirective); // Now after the final character (':') of the directive
if(_TCHAR('<')==*pc){
pc++;
// Extract the argument
str=_T("");
while(*pc){
// Process escapes: FIXME more escapes?
TCHAR c=*pc;
if(_TCHAR('\\')==c){
switch(pc[1]){
case _TCHAR('t'):
c=_TCHAR('\t');
break;
case _TCHAR('n'):
c=_TCHAR('\n');
break;
case _TCHAR('\0'):
pc--; // avoid grief
break;
default:
c=pc[1];
break;
}
pc++;
} else if (_TCHAR('>')==c) {
nIndex=pc+1-pszOutput;
rc=true;
break;
} else if (_TCHAR('\n')==c) {
nIndex=pc+1-pszOutput;
Log(_T("%%%% Unterminated directive: %s"),(LPCTSTR)str);
break;
}
str+=c;
pc++;
}
}
}
LEAVECRITICAL;
return rc;
}
void CeCosTest::GetInferiorCommands(StringArray &arstrInferiorCmds)
{
arstrInferiorCmds.clear();
// Construct commands for gdb. The commands may be found (semicolon-separated) in the target info:
const String strInferiorCmds(m_ep.Platform()->GdbCmds());
StringArray ar;
int nCmds=strInferiorCmds.Chop(ar,_TCHAR(';'),false);
for(int i=0;i<nCmds;i++){
// Into each command must be substituted:
// Baud rate (%b)
// Port (%p) This will be a serial port (e.g. COM1) or a socket connection (e.g.aloo:8000) depending on circumstances.
// and escapes must be dealt with.
String strCmd;
for(const TCHAR *pc=ar[i];*pc;pc++){
switch(*pc){
// Process escapes: FIXME more escapes?
case _TCHAR('\\'):
switch(pc[1]){
case _TCHAR('t'):
strCmd+=_TCHAR('\t');
pc++;
continue;
case _TCHAR('n'):
strCmd+=_TCHAR('\n');
pc++;
continue;
case _TCHAR('\0'):
continue;
default:
break;
}
break;
case _TCHAR('%'):
switch(pc[1]){
case _TCHAR('%'):
strCmd+=_TCHAR('%');
pc++;
break;
case _TCHAR('b'):
if(0==m_pResource->Baud()){
goto NextCmd; // Suppress output of this command if there is no baud rate to output
}
strCmd+=String::SFormat(_T("%d"),m_pResource->Baud());
pc++;
continue;
case _TCHAR('p'):
if(_TCHAR('\0')==*(m_pResource->Serial())){
goto NextCmd; // Suppress output of this command if there is no serial port
}
strCmd+=m_pResource->Serial();
pc++;
continue;
case _TCHAR('\0'):
continue;
default:
break;
}
break;
default:
break;
}
strCmd+=*pc;
}
arstrInferiorCmds.push_back(strCmd);
NextCmd:
;
}
return;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?