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 + -
显示快捷键?