📄 ecostestutils.cpp
字号:
//=================================================================//// eCosTestUtils.cpp//// Utility functions////=================================================================//####COPYRIGHTBEGIN####//// -------------------------------------------// The contents of this file are subject to the Cygnus eCos Public License// Version 1.0 (the "License"); you may not use this file except in// compliance with the License. You may obtain a copy of the License at// http://sourceware.cygnus.com/ecos// // Software distributed under the License is distributed on an "AS IS"// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the// License for the specific language governing rights and limitations under// the License.// // The Original Code is eCos - Embedded Cygnus Operating System, released// September 30, 1998.// // The Initial Developer of the Original Code is Cygnus. Portions created// by Cygnus are Copyright (C) 1998, 1999 Cygnus Solutions.// All Rights Reserved.// -------------------------------------------////####COPYRIGHTEND####//=================================================================//#####DESCRIPTIONBEGIN####//// Author(s): sdf// Contributors: sdf// Date: 1999-04-01// Description: This class contains utility functions for use in the testing infrastructure// Usage:////####DESCRIPTIONEND#####include "stdafx.h"#include "eCosTestUtils.h"#include "eCosTest.h"int nCSOwner=-1;int CeCosTestUtils::m_nCriticalSectionLock=0;bool CeCosTestUtils::bVerbose=false;FILE *CeCosTestUtils::fTrace=stderr;#ifdef _WIN32int CALLBACK CeCosTestUtils::FilterFunction(LPEXCEPTION_POINTERS p){ PEXCEPTION_RECORD pRec=p->ExceptionRecord; PCONTEXT pContext=p->ContextRecord; TRACE("!!!Exception!!! address=%08x code=%08x stack:\n",pRec->ExceptionAddress,pRec->ExceptionCode); const unsigned char *ESP=(const unsigned char *)pContext->Esp; for(int i=0;i<16;i++){ char s[49]; static const char hexchar[]="0123456789ABCDEF"; char *c=s; for(int j=0;j<16;j++){ *c++=hexchar[(*ESP)/16]; *c++=hexchar[(*ESP)%16]; *c++=' '; ESP++; } *c='\0'; TRACE("%08x %s\n",ESP,s); ESP+=16; } return EXCEPTION_EXECUTE_HANDLER;}#endifbool CeCosTestUtils::ParseHostPort (const char * const pszHostPort, CeCosTestUtils::String &strHost, int &nPort){ nPort=0; bool rc=false; const char *c=strchr(pszHostPort,':'); if(c){ nPort=atoi(c+1); if(nPort && nPort>0 && nPort<=0xffff){ int nLength=c-pszHostPort; strncpy(strHost.GetBuffer(nLength),pszHostPort,nLength); strHost.ReleaseBuffer(); while(*++c && isdigit(*c)); rc=('\0'==*c); } } return rc;}bool CeCosTestUtils::IsLegalHostPort (const char * const pszHostPort){ int nPort=0; CeCosTestUtils::String strHost; return ParseHostPort(pszHostPort,strHost,nPort);}void CeCosTestUtils::Trace(const char * pszFormat, ...){ if(bVerbose){ va_list marker; va_start (marker, pszFormat); CeCosTestUtils::String str; str.vFormat(pszFormat,marker); va_end (marker); time_t ltime; time(<ime); struct tm *now=localtime( <ime ); String s; void *id=GetThreadId(); s.Format("[%x %02d:%02d:%02d%s] %s",id,now->tm_hour,now->tm_min,now->tm_sec,nCSOwner==(int)id?"*":"",(const char *)str); #ifdef _WIN32 OutputDebugString(s); #endif fputs(s,fTrace); fflush(fTrace); }}void CeCosTestUtils::Error(const char * pszFormat, ...){ va_list marker; va_start (marker, pszFormat); CeCosTestUtils::String str; str.vFormat(pszFormat,marker); va_end (marker); time_t ltime; time(<ime); struct tm *now=localtime( <ime ); String s; if(bVerbose){ void *id=GetThreadId(); s.Format("[%x %02d:%02d:%02d%s] %s",id,now->tm_hour,now->tm_min,now->tm_sec,nCSOwner==(int)id?"*":"",(const char *)str); } else { s=str; } #ifdef _WIN32 OutputDebugString(s); #endif fputs(s,fTrace); fflush(fTrace);}#ifdef _WIN32static CRITICAL_SECTION cs;static bCSInitialized=false;#else// Static mutex for unix critical sectionstatic pthread_mutex_t cs = PTHREAD_MUTEX_INITIALIZER;#endifvoid CeCosTestUtils::EnterCriticalSection(const char *pszFile,int nLine){ #ifdef VERBOSE fprintf(stderr,"%x try CS %s:%d\n",GetThreadId(),pszFile,nLine);//sdf #else nLine;pszFile; //prevent compiler warning #endif #ifdef _WIN32 if(!bCSInitialized){ InitializeCriticalSection(&cs); bCSInitialized=true; } ::EnterCriticalSection(&cs); #else // Get mutex lock; block until available unless current // thread already owns the mutex. if ((int)GetThreadId() != nCSOwner) pthread_mutex_lock(&cs); #endif nCSOwner=(int)GetThreadId(); m_nCriticalSectionLock++; #ifdef VERBOSE fprintf(stderr,"%x has CS count=%d\n",GetThreadId(),m_nCriticalSectionLock);//sdf #endif}void CeCosTestUtils::LeaveCriticalSection(const char *pszFile,int nLine){ m_nCriticalSectionLock--; nCSOwner=-1; #ifdef VERBOSE fprintf(stderr,"%x leaves CS count=%d %s:%d\n",GetThreadId(),m_nCriticalSectionLock,pszFile,nLine);//sdf #else pszFile;nLine; // prevent compiler warnings #endif assert(m_nCriticalSectionLock>=0); #ifdef _WIN32 ::LeaveCriticalSection(&cs); #else // Release mutex lock. if (0 == m_nCriticalSectionLock) pthread_mutex_unlock(&cs); else nCSOwner=(int)GetThreadId(); #endif}CeCosTestUtils::GarbageCollector::GarbageCollector(){ #ifdef _WIN32 WSADATA wsaData; WORD wVersionRequested = MAKEWORD( 2, 0 ); WSAStartup( wVersionRequested, &wsaData ); #else sigset_t mask; // Clean out all the signals sigemptyset(&mask); // Add our sigpipe sigaddset(&mask, SIGPIPE); sigprocmask(SIG_SETMASK, &mask, NULL); #endif};CeCosTestUtils::GarbageCollector::~GarbageCollector(){ CeCosTest::DeleteAllInstances(); #ifdef _WIN32 WSACleanup(); if(bCSInitialized){ DeleteCriticalSection(&cs); bCSInitialized=false; } #endif};const char * const CeCosTestUtils::Tail(const char * const pszFile){ const char *pszTail=strrchr(pszFile,'/'); if(0==pszTail){ pszTail=strrchr(pszFile,'\\'); } return (0==pszTail)?pszFile:pszTail+1;}CeCosTestUtils::GarbageCollector CeCosTestUtils::GarbageCollector::gc;int CeCosTestUtils::AtomicIncrement (int &n){ ENTERCRITICAL; int rc=n++; LEAVECRITICAL; return rc;}int CeCosTestUtils::AtomicDecrement (int &n){ ENTERCRITICAL; int rc=n--; LEAVECRITICAL; return rc;}CeCosTestUtils::String::String () : m_pszData(0), m_nSize(0){ AllocCopy("");}CeCosTestUtils::String::String (const char *pszStr) : m_pszData(0), m_nSize(0){ AllocCopy(pszStr);}CeCosTestUtils::String::String (const CeCosTestUtils::String &o) : m_pszData(0), m_nSize(0){ AllocCopy(o.m_pszData);}CeCosTestUtils::String::~String(){ delete [] m_pszData; m_pszData=0;}const CeCosTestUtils::String& CeCosTestUtils::String::operator+=(const char *pszStr){ if(0!=pszStr){ unsigned int nLen=strlen(m_pszData); SetLength(nLen+strlen(pszStr)); strcpy(m_pszData+nLen,pszStr); } return *this;}const CeCosTestUtils::String& CeCosTestUtils::String::operator=(const char *lpsz){ AllocCopy(lpsz); return *this;}const CeCosTestUtils::String& CeCosTestUtils::String::operator=(const String &o){ AllocCopy(o.m_pszData); return *this;}const CeCosTestUtils::String& CeCosTestUtils::String::operator+=(char ch){ int nLen=GetLength(); SetLength(1+nLen); m_pszData[nLen]=ch; m_pszData[nLen+1]='\0'; return *this;}void CeCosTestUtils::String::Format (const char * const pszFormat,...){ va_list args; va_start(args, pszFormat); vFormat(pszFormat,args); va_end(args);}void CeCosTestUtils::String::vFormat(const char * pszFormat, va_list marker){#ifdef _WIN32 int nLength=1000; int n; do { SetLength(nLength); n=vsnprintf( m_pszData, nLength, pszFormat, marker ); nLength+=100; } while (n==-1); SetLength(n); return;#else const char *pszF=pszFormat; m_pszData[0]='\0'; while(*pszFormat){ //CHECKHEAP; if('%'==*pszFormat){ pszFormat++; if('%'==*pszFormat){ // Simply escaping a '%' operator+=('%'); //CHECKHEAP; } else { // Pick an arg and format it // Calculate a length good enough for this item. // The initial value is ok for integers sans override unsigned int nItemLen=12; char szFormatItem[20]={'%'}; // We reckon a format item will fit in this unsigned int nFormatLen=1; // length of the format item (e.g. the "%08x") // We ought to be supporting // %[flags] [width] [.precision] [{h | l | I64 | L}]type // We'll suck everything up to a 'flags' character into szFormatItem bool bReadWidth=false; while(0==strchr("cCdiouxXeEfgGnpsS",*pszFormat)){ if(!bReadWidth && isdigit(*pszFormat)){ nItemLen+=(unsigned)atoi(pszFormat); // User is overriding length [probably] bReadWidth=true; } if(2+nFormatLen>=sizeof szFormatItem){ return; } szFormatItem[nFormatLen++]=*pszFormat++; } szFormatItem[nFormatLen++]=*pszFormat; szFormatItem[nFormatLen]='\0'; // Now szFormatItem holds the format string // Extract the argument according to type union { const void *pArg; int nArg; double dArg; const char *pszArg; } u; bool bDouble=true; switch(*pszFormat){ case 'c': case 'C': case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': u.nArg=va_arg(marker,int); break; case 'e': case 'E': case 'f': case 'g': case 'G': u.dArg=va_arg(marker,double); bDouble=true; break; case 'n': case 'p': u.pArg=va_arg(marker,const void *); break; case 's': case 'S': u.pszArg=va_arg(marker,const char *); if(0==u.pszArg){ u.pszArg="(null)"; } nItemLen=max(nItemLen,1+strlen(u.pszArg)); // It's a string - make sure we can accommodate it break; default: fprintf(stderr, "Don't know how to print this format code : %c\n", *pszFormat); fprintf(stderr, "Full string is '%s'\n", pszFormat); assert(false); } unsigned int nLen=GetLength(); SetLength(nLen+nItemLen+100); int n=sprintf(m_pszData+nLen,szFormatItem,bDouble?u.dArg:u.nArg); if((unsigned)n>nItemLen){ if('s'==*pszFormat){ fprintf(stderr,"arg=%s\n",u.pszArg); } fprintf(stderr,"offs=%d n=%d\nnItemlen=%d\npszFormat=%s\n",pszFormat-pszF,n,nItemLen,pszF); } assert((unsigned)n<=nItemLen); //CHECKHEAP; } } else { // pick a single character out of the format string operator+=(*pszFormat); //CHECKHEAP; } pszFormat++; }#endif}char CeCosTestUtils::String::operator[](unsigned int nIndex) const{ assert(nIndex<GetLength()); return m_pszData[nIndex];}void CeCosTestUtils::String::AllocCopy(const char *pszContents){ if(0==pszContents){ pszContents=""; } unsigned int nSize=1+strlen(pszContents); if(nSize>m_nSize){ delete [] m_pszData; m_nSize=nSize|255; // 256-byte chunks m_pszData=new char[m_nSize]; } strcpy(m_pszData,pszContents);}void CeCosTestUtils::String::SetLength(unsigned int nLength){ if(1+nLength>m_nSize){ int nOldsize=m_nSize; m_nSize=1+(nLength|255); // 256-byte chunks char *pszNew=new char[m_nSize]; memcpy(pszNew,m_pszData,nOldsize); delete [] m_pszData; m_pszData=pszNew; } m_pszData[nLength]='\0';}void CeCosTestUtils::String::MakeLower(){ for(char *c=m_pszData;*c;c++){ if(isalpha(*c)){ *c=(char)tolower(*c); } }}void CeCosTestUtils::String::MakeUpper(){ for(char *c=m_pszData;*c;c++){ if(isalpha(*c)){ *c=(char)toupper(*c); } }}char * CeCosTestUtils::String::GetBuffer(unsigned int nLength){ SetLength(nLength); return m_pszData;}char * CeCosTestUtils::String::GetBuffer(){ return m_pszData;}void CeCosTestUtils::String::ReleaseBuffer(){}bool CeCosTestUtils::SetTraceFile(const char *pszFile){ FILE *f=fopen(pszFile,"at"); if(f){ if(fTrace!=stderr){ fclose(fTrace); } fTrace=f; } return 0!=f;}void * CeCosTestUtils::GetThreadId(){ return (void *) #ifdef _WIN32 GetCurrentThreadId(); #else pthread_self(); #endif}// Wait for the specified Boolean to turn true or the timeout to occur// The value of the Boolean is returned as resultbool CeCosTestUtils::WaitFor (bool &b, CeCosTestUtils::Duration dTimeout){ CeCosTestUtils::Time t=CeCosTestUtils::Time::Now(); do { if(b){ break; } Sleep(250); } while (CeCosTestUtils::Time::Now()-t<dTimeout); return b;}void CeCosTestUtils::Sleep(Duration nMsec){ if(nMsec>0){#ifdef _WIN32 ::Sleep(nMsec);#else usleep((int)nMsec * 1000);#endif } if(nMsec>0){ }}CeCosTestUtils::Time CeCosTestUtils::Time::Now(){#ifdef _WIN32 __int64 ft; SYSTEMTIME st; GetSystemTime (&st); SystemTimeToFileTime(&st,(FILETIME *)&ft); return Time((int)(ft/=10000));#else struct timeval tv; gettimeofday(&tv,0); Time t; return Time(tv.tv_sec*1000+tv.tv_usec/1000);#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -