Mercurial > ecos-v2_0-branch
diff host/tools/ecostest/common/TestResource.cpp @ 76:435cced73e2f ecos-v1_3_1-release
eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
| author | jlarmour |
|---|---|
| date | Tue, 28 Mar 2000 14:10:45 +0000 |
| parents | |
| children | 6736c52df507 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/host/tools/ecostest/common/TestResource.cpp @@ -0,0 +1,552 @@ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This program is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +//================================================================= +// +// TestResource.cpp +// +// Resource test class +// +//================================================================= +//================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): sdf +// Contributors: sdf +// Date: 1999-04-01 +// Description: This class abstracts a test resource for use in the testing infrastructure +// Usage: +// +//####DESCRIPTIONEND#### +#include "eCosStd.h" +#include "eCosTestUtils.h" +#include "eCosTrace.h" +#ifdef _WIN32 + #include "Subprocess.h" +#endif +#include "TestResource.h" + +CTestResource *CTestResource::pFirstInstance=0; +unsigned int CTestResource::nCount=0; + +String CTestResource::strResourceHost; +int CTestResource::nResourcePort; + +CTestResource::CTestResource(LPCTSTR target, LPCTSTR pszDownloadPort, int nBaud, LPCTSTR pszResetString): + m_strReset(pszResetString), + m_bInUse(false), + m_nBaud(nBaud), + m_strPort(pszDownloadPort), + m_bLocked(false), + m_Target(target), + m_strHost(CeCosTestUtils::HostName()), + m_nPort(0) +{ + VTRACE(_T("@@@ Created resource %08x %s\n"),(unsigned int)this,(LPCTSTR)Output()); + Chain(); +} + +CTestResource::~CTestResource() +{ + ENTERCRITICAL; + VTRACE(_T("@@@ Destroy resource %08x %s\n"),this,(LPCTSTR)Output()); + if(m_pPrevInstance || m_pNextInstance){ + nCount--; + } + if(pFirstInstance==this){ + pFirstInstance=m_pNextInstance; + } + if(m_pPrevInstance){ + m_pPrevInstance->m_pNextInstance=m_pNextInstance; + } + if(m_pNextInstance){ + m_pNextInstance->m_pPrevInstance=m_pPrevInstance; + } + LEAVECRITICAL; +} + +// Find the resource matching the given host:port specification +// Returns 0 if no such host:port found +CTestResource * CTestResource::Lookup(LPCTSTR pszHost, int nPort) +{ + CTestResource *pResource; + ENTERCRITICAL; + for(pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ + if(nPort==pResource->TcpipPort() && 0==_tcsicmp(pszHost,pResource->Host())){ + break; + } + } + LEAVECRITICAL; + return pResource; +} + +unsigned int CTestResource::GetMatchCount (const CeCosTest::ExecutionParameters &e,bool bIgnoreLocking) +{ + unsigned int i=0; + ENTERCRITICAL; + for(const CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ + if(pResource->Matches(e,bIgnoreLocking)){ + i++; + } + } + LEAVECRITICAL; + return i; +} + +bool CTestResource::GetMatches (const CeCosTest::ExecutionParameters &e, StringArray &arstr, bool bIgnoreLocking) +{ + bool rc=false; + arstr.clear(); + if(LoadSocket()){ + ENTERCRITICAL; + for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ + if(pResource->Matches(e,bIgnoreLocking)){ + arstr.push_back(CeCosTestSocket::HostPort(pResource->Host(),pResource->TcpipPort())); + } + } + LEAVECRITICAL; + rc=true; + } + return rc; +} + +void CTestResource::DeleteAllInstances() +{ + ENTERCRITICAL; + while(pFirstInstance){ + delete pFirstInstance; + } + LEAVECRITICAL; +} + +bool CTestResource::LoadFile (LPCTSTR psz,void *key) +{ + bool rc=true; + ENTERCRITICAL; + DeleteAllInstances(); +#ifdef _WIN32 + if(key){ + // Find all the keys under "psz" and load from each of them + HKEY hKey; + if(ERROR_SUCCESS==RegOpenKeyEx ((HKEY)key, psz, 0L, KEY_ENUMERATE_SUB_KEYS, &hKey)){ + TCHAR szName[256]; + DWORD dwSizeName=sizeof szName; + FILETIME ftLastWriteTime; + for(DWORD dwIndex=0;ERROR_SUCCESS==RegEnumKeyEx(hKey, dwIndex, szName, &dwSizeName, NULL, NULL, NULL, &ftLastWriteTime); dwIndex++){ + CTestResource *pResource=new CTestResource(_T("")); + String strKey; + strKey.Format(_T("%s\\%s"),psz,szName); + CTestResourceProperties prop1(pResource,strKey,key); + prop1.SetDefaults(); + prop1.Load(); + dwSizeName=sizeof szName; + } + RegCloseKey(hKey); + } + } else +#endif + { + // Find all the files in directory "psz" and load from each of them + void *pHandle; + TCHAR szOrigDir[256]; + _tgetcwd(szOrigDir,sizeof szOrigDir-1); + if(0==_tchdir(psz)){ + String strFile; + for(bool b=CeCosTestUtils::StartSearch(pHandle,strFile);b;b=CeCosTestUtils::NextFile(pHandle,strFile)){ + struct _stat buf; + if(0==_tstat(strFile,&buf) && 0==(S_IFDIR&buf.st_mode)){ + CTestResource *pResource=new CTestResource(_T("")); + CTestResourceProperties prop1(pResource,strFile); + prop1.SetDefaults(); + prop1.Load(); + } + } + CeCosTestUtils::EndSearch(pHandle); + } else { + TRACE(_T("Failed to change to %s from %s\n"),psz,szOrigDir); + } + _tchdir(szOrigDir); + } + LEAVECRITICAL; + + return rc; +} + +bool CTestResource::SaveFile (LPCTSTR psz,void *key) +{ + bool rc=false; + ENTERCRITICAL; +#ifdef _WIN32 + if(key){ + // Delete all the keys under "psz" + HKEY hKey; + if(ERROR_SUCCESS==RegOpenKeyEx ((HKEY)key, psz, 0L, KEY_ENUMERATE_SUB_KEYS, &hKey)){ + TCHAR szName[256]; + DWORD dwSizeName=sizeof szName; + FILETIME ftLastWriteTime; + DWORD dwIndex; + if(ERROR_SUCCESS==RegQueryInfoKey(hKey,0,0,0,&dwIndex,0,0,0,0,0,0,0)){ + while((signed)--dwIndex>=0){ + if(ERROR_SUCCESS!=RegEnumKeyEx(hKey, dwIndex, szName, &dwSizeName, NULL, NULL, NULL, &ftLastWriteTime) || + ERROR_SUCCESS!=RegDeleteKey(hKey,szName)){ + rc=false; + } + dwSizeName=sizeof szName; + } + } + RegCloseKey(hKey); + } + } else +#endif + { + // Delete all the files under directory "psz" + void *pHandle; + TCHAR szOrigDir[256]; + _tgetcwd(szOrigDir,sizeof szOrigDir-1); + if(0==_tchdir(psz)){ + String strFile; + for(bool b=CeCosTestUtils::StartSearch(pHandle,strFile);b;b=CeCosTestUtils::NextFile(pHandle,strFile)){ + struct _stat buf; + if(0==_tstat(strFile,&buf) && 0==(S_IFDIR&buf.st_mode)){ + _tunlink(strFile); + } + } + CeCosTestUtils::EndSearch(pHandle); + } else { + fprintf(stderr,"Failed to change to %s from %s\n",psz,szOrigDir); + } + _tchdir(szOrigDir); + } + + rc=true; + for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ + String strName; + if(key){ + strName.Format(_T("%s\\%s-%d"),psz,(LPCTSTR)pResource->m_strHost,pResource->m_nPort); + CTestResourceProperties prop1(pResource,strName,key); + rc&=prop1.Save(); + } else { + strName.Format(_T("%s%c%s-%d"),psz,cPathsep,(LPCTSTR)pResource->m_strHost,pResource->m_nPort); + CTestResourceProperties prop1(pResource,strName,key); + rc&=prop1.Save(); + } + + } + LEAVECRITICAL; + + return rc; +} + +CTestResource::CTestResourceProperties::CTestResourceProperties(CTestResource *pResource,LPCTSTR psz,void *key): + CProperties(psz,key) +{ + CProperties::Add(_T("Baud"), pResource->m_nBaud,0); + Add(_T("BoardId"), pResource->m_strBoardID); + Add(_T("Date"), pResource->m_strDate); + Add(_T("Email"), pResource->m_strEmail); + Add(_T("Host"), pResource->m_strHost); + CProperties::Add(_T("Locked"), pResource->m_bLocked,0); + Add(_T("Originator"), pResource->m_strUser); + CProperties::Add(_T("Port"), pResource->m_nPort); + Add(_T("Reason"), pResource->m_strReason); + Add(_T("Reset"), pResource->m_strReset); + Add(_T("Serial"), pResource->m_strPort); + Add(_T("Target"), pResource->m_Target); + Add(_T("User"), pResource->m_strUser); +} + +bool CTestResource::Lock() +{ + if(!m_bLocked){ + m_bLocked=true; + return true; + } else { + return false; + } +} + +bool CTestResource::Unlock() +{ + if(m_bLocked){ + m_bLocked=false; + return true; + } else { + return false; + } +} + +bool CTestResource::LoadSocket(LPCTSTR pszResourceHost,int nResourcePort,Duration dTimeout/*=10*1000*/) +{ + bool rc=false; + ENTERCRITICAL; + CTestResource *pResource; + // If the resource is in use, we don't dare delete it! + for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){ + pResource->m_bFlag=false; + } + CeCosTestSocket sock; + if(sock.Connect(pszResourceHost,nResourcePort,dTimeout)){ + // Write the message to the socket + int nRequest=0; // read + if(!sock.sendInteger(nRequest)){ + ERROR(_T("Failed to write to socket\n")); + } else { + int nResources; + if(sock.recvInteger(nResources,_T(""),dTimeout)){ + rc=true; + while(nResources--){ + String strImage; + if(sock.recvString(strImage,_T(""),dTimeout)){ + VTRACE(_T("Recv \"%s\"\n"),(LPCTSTR)strImage); + CTestResource tmp; + tmp.FromStr(strImage); + CTestResource *pResource=Lookup(tmp.Host(),tmp.TcpipPort()); + if(0==pResource){ + pResource=new CTestResource(_T("")); + } + pResource->FromStr(strImage); + pResource->m_bFlag=true; + } else { + rc=false; + break; + } + } + } + } + } + // If the resource is in use, we don't dare delete it! + CTestResource *pNext; + for(pResource=CTestResource::First();pResource;pResource=pNext){ + pNext=pResource->Next(); + if(!pResource->m_bFlag && !pResource->m_bInUse){ + delete pResource; + } + } + + LEAVECRITICAL; + return rc; +} + +void CTestResource::Image(String &str) +{ + CTestResourceProperties prop(this); + str=prop.MakeCommandString(); + VTRACE(_T("Make command string %s\n"),(LPCTSTR)str); +} + +bool CTestResource::FromStr(LPCTSTR pszImage) +{ + CTestResourceProperties prop(this); + prop.LoadFromCommandString(pszImage); + VTRACE(_T("From command string %s\n"),pszImage); + return true; +} + +void CTestResource::Chain() +{ + ENTERCRITICAL; + nCount++; + m_pNextInstance=pFirstInstance; + if(m_pNextInstance){ + m_pNextInstance->m_pPrevInstance=this; + } + m_pPrevInstance=0; + pFirstInstance=this; + LEAVECRITICAL; +} + +bool CTestResource::Matches (const CeCosTest::ExecutionParameters &e,bool bIgnoreLocking) const +{ + return (bIgnoreLocking||(!m_bLocked)) && (0==_tcsicmp(e.Target(),m_Target)); +}; + +bool CTestResource::SaveSocket(LPCTSTR pszResourceServer,int nResourcePort,Duration dTimeout) +{ + bool rc=true; + ENTERCRITICAL; + CeCosTestSocket sock(pszResourceServer,nResourcePort, dTimeout); + if(sock.Ok()){ + // Write the message to the socket + int nRequest=1; //write + if(!sock.sendInteger(nRequest, _T(""),dTimeout)){ + ERROR(_T("Failed to write to socket\n")); + rc=false; + } else { + int nResources=0; + CTestResource *pResource; + for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){ + nResources++; + } + if(sock.sendInteger(nResources,_T("resource count"),dTimeout)){ + for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){ + String strImage; + pResource->Image(strImage); + TRACE(_T("Send \"%s\"\n"),(LPCTSTR)strImage); + if(!sock.sendString (strImage, _T("reply"),dTimeout)){ + rc=false; + break; + } + } + } else { + rc=false; + } + } + } else { + rc=false; + } + LEAVECRITICAL; + return rc; +} + +CeCosTest::ServerStatus CTestResource::Query() +{ + CeCosTest::ExecutionParameters e(CeCosTest::ExecutionParameters::QUERY,m_Target); + CeCosTestSocket *pSock=0; + CeCosTest::ServerStatus s=CeCosTest::Connect(m_strHost,m_nPort,pSock,e,m_strInfo); + delete pSock; + return s; +} + +int CTestResource::Count(const CeCosTest::ExecutionParameters &e) +{ + int nCount=0; + for(const CTestResource *p=pFirstInstance;p;p=p->m_pNextInstance){ + if(p->Matches(e)){ + nCount++; + } + } + return nCount; +} + +bool CTestResource::Use() +{ + bool rc; + ENTERCRITICAL; + if(m_bInUse){ + rc=false; + } else { + m_bInUse=true; + rc=true; + } + LEAVECRITICAL; + return rc; +} + +CTestResource *CTestResource::GetResource (const CeCosTest::ExecutionParameters &e) +{ + CTestResource *p=0; + if(0==Count(e)){ + ERROR(_T("GetResource: no candidates available\n")); + } else { + ENTERCRITICAL; + for(p=pFirstInstance;p;p=p->m_pNextInstance){ + if(p->Matches(e) && !p->m_bInUse){ + TRACE(_T("Acquired %s\n"),p->Serial()); + p->Use(); + break; + } + } + LEAVECRITICAL; + } + return p; +} + +String CTestResource::Output() const +{ + String str; + str.Format( + _T("%10s:%d %20s %8s"), + Host(), + TcpipPort(), + Target(), + Serial()); + if(HasReset()){ + str+=_T(" Reset:"); + str+=m_strReset; + } + if(IsLocked()){ + str+=_T(" [RL]"); + } + return str; +} + +bool CTestResource::Matches(LPCTSTR pszHost, int nPort, const CeCosTest::ExecutionParameters &e) +{ + bool rc=false; + ENTERCRITICAL; + if(LoadSocket()){ + CTestResource *pResource=Lookup(pszHost,nPort); + if(pResource){ + rc=pResource->Matches(e); + } + } + LEAVECRITICAL; + return rc; +} + +CResetAttributes::ResetResult CTestResource::Reset(LogFunc *pfnLog, void *pfnLogparam) +{ + String strReset; + strReset.Format(_T("port(%s,%d) %s"),Serial(),Baud(),ResetString()); + return CResetAttributes(strReset).Reset(pfnLog,pfnLogparam); +} + +CResetAttributes::ResetResult CTestResource::Reset(String &str) +{ + return Reset(StringLogFunc,&str); +} + +void CALLBACK CTestResource::StringLogFunc (void *pParam,LPCTSTR psz) +{ + *((String *)pParam)+=psz; +} + + +CResetAttributes::ResetResult CTestResource::RemoteReset(LogFunc *pfnLog, void *pfnLogparam) +{ + String strCmd; + strCmd.Format(_T("rsh %s x10reset %s\n"),Host(),ResetString()); + pfnLog(pfnLogparam,strCmd); + +#ifdef _WIN32 + // because this can be used from GUI tools + CSubprocess sp; + sp.Run(pfnLog,pfnLogparam,strCmd); +#else // UNIX + FILE *f=POPEN(strCmd,"rt"); + if(f){ + char buf[80]; + while(fgets(buf,sizeof buf,f)){ + pfnLog(pfnLogparam,buf); + } + PCLOSE(f); + } else { + String strMsg; + strMsg.Format(_T("Failed to execute '%s'\n"),(LPCTSTR)strCmd); + pfnLog(pfnLogparam,strMsg); + } +#endif + return CResetAttributes::RESET_OK; // FIXME +} +
