X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-redboot.git;a=blobdiff_plain;f=tools%2Fsrc%2Ftools%2Fecostest%2Fcommon%2FTestResource.cpp;fp=tools%2Fsrc%2Ftools%2Fecostest%2Fcommon%2FTestResource.cpp;h=4e350f4e0d344c1dc228f52445011a80f7ab1431;hp=0000000000000000000000000000000000000000;hb=2b5bec7716c03d42cfb16d8c98c9cea573bf6722;hpb=47412fc4bd1aefc0d5498bcb3860a9d727196f16 diff --git a/tools/src/tools/ecostest/common/TestResource.cpp b/tools/src/tools/ecostest/common/TestResource.cpp new file mode 100644 index 00000000..4e350f4e --- /dev/null +++ b/tools/src/tools/ecostest/common/TestResource.cpp @@ -0,0 +1,543 @@ +//####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" +#include "Subprocess.h" + +#include "TestResource.h" + +CTestResource *CTestResource::pFirstInstance=0; +unsigned int CTestResource::nCount=0; + +String CTestResource::strResourceHostPort; + +CTestResource::CTestResource(LPCTSTR pszHostPort, 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) +{ + CeCosSocket::ParseHostPort(pszHostPort,m_strHost,m_nPort); + VTRACE(_T("@@@ Created resource %08x %s\n"),(unsigned int)this,(LPCTSTR)Image()); + Chain(); +} + +CTestResource::~CTestResource() +{ + ENTERCRITICAL; + VTRACE(_T("@@@ Destroy resource %08x %s\n"),this,(LPCTSTR)Image()); + 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 pszHostPort) +{ + CTestResource *pResource=NULL; + ENTERCRITICAL; + String strHost; + int nPort; + if(CeCosSocket::ParseHostPort(pszHostPort,strHost,nPort)){ + for(pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ + if(nPort==pResource->TcpIPPort() && CeCosSocket::SameHost(strHost,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(Load()){ + ENTERCRITICAL; + for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ + if(pResource->Matches(e,bIgnoreLocking)){ + arstr.push_back(pResource->HostPort()); + } + } + LEAVECRITICAL; + rc=true; + } + return rc; +} + +void CTestResource::DeleteAllInstances() +{ + ENTERCRITICAL; + while(pFirstInstance){ + delete pFirstInstance; + } + LEAVECRITICAL; +} + +bool CTestResource::LoadFromDirectory (LPCTSTR psz) +{ + bool rc=true; + ENTERCRITICAL; + DeleteAllInstances(); + // Find all the files in directory "psz" and load from each of them + TCHAR szOrigDir[256]; + _tgetcwd(szOrigDir,sizeof szOrigDir-1); + if(0==_tchdir(psz)){ + String strFile; + void *pHandle; + for(bool b=CeCosTestUtils::StartSearch(pHandle,strFile);b;b=CeCosTestUtils::NextFile(pHandle,strFile)){ + if(CeCosTestUtils::IsFile(strFile)){ + CTestResource *pResource=new CTestResource(_T(""),_T("")); + CTestResourceProperties prop(pResource); + prop.LoadFromFile(strFile); + } + } + CeCosTestUtils::EndSearch(pHandle); + } else { + TRACE(_T("Failed to change to %s from %s\n"),psz,szOrigDir); + } + _tchdir(szOrigDir); + LEAVECRITICAL; + + return rc; +} + +bool CTestResource::SaveToDirectory (LPCTSTR pszDir) +{ + bool rc=false; + ENTERCRITICAL; + { + // Delete all the files under directory "pszDir" + void *pHandle; + TCHAR szOrigDir[256]; + _tgetcwd(szOrigDir,sizeof szOrigDir-1); + if(0==_tchdir(pszDir)){ + String strFile; + for(bool b=CeCosTestUtils::StartSearch(pHandle,strFile);b;b=CeCosTestUtils::NextFile(pHandle,strFile)){ + if(CeCosTestUtils::IsFile(strFile)){ + _tunlink(strFile); + } + } + CeCosTestUtils::EndSearch(pHandle); + rc=true; + for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ + CTestResourceProperties prop(pResource); + rc&=prop.SaveToFile(pResource->FileName()); + } + } else { + fprintf(stderr,"Failed to change to %s from %s\n",pszDir,szOrigDir); + } + _tchdir(szOrigDir); + } + + LEAVECRITICAL; + + return rc; +} + +#ifdef _WIN32 +bool CTestResource::LoadFromRegistry(HKEY key,LPCTSTR psz) +{ + // Find all the keys under "psz" and load from each of them + bool rc=false; + ENTERCRITICAL; + 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(""),_T("")); + String strKey; + strKey.Format(_T("%s\\%s"),psz,szName); + CTestResourceProperties prop1(pResource); + prop1.LoadFromRegistry(key,strKey); + dwSizeName=sizeof szName; + } + RegCloseKey(hKey); + } + LEAVECRITICAL; + return rc; +} + +bool CTestResource::SaveToRegistry(HKEY key,LPCTSTR psz) +{ + bool rc=false; + ENTERCRITICAL; + // 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); + } + rc=true; + for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){ + CTestResourceProperties prop1(pResource); + rc&=prop1.SaveToRegistry(key,pResource->FileName()); + } + + LEAVECRITICAL; + return rc; +} + +#endif + +CTestResource::CTestResourceProperties::CTestResourceProperties(CTestResource *pResource) +{ + Add(_T("Baud"), pResource->m_nBaud); + Add(_T("BoardId"), pResource->m_strBoardID); + Add(_T("Date"), pResource->m_strDate); + Add(_T("Email"), pResource->m_strEmail); + Add(_T("Host"), pResource->m_strHost); + Add(_T("Port"), pResource->m_nPort); + Add(_T("Locked"), pResource->m_bLocked); + Add(_T("Originator"), pResource->m_strUser); + 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 pszResourceHostPort,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; + } + CeCosSocket sock; + if(sock.Connect(pszResourceHostPort,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.HostPort()); + if(0==pResource){ + pResource=new CTestResource(_T(""),_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; +} + +bool CTestResource::SaveSocket(LPCTSTR pszResourceHostPort,Duration dTimeout) +{ + bool rc=true; + ENTERCRITICAL; + CeCosSocket sock(pszResourceHostPort, 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; + CTestResourceProperties prop(pResource); + strImage=prop.MakeCommandString(); + 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; +} + +/* +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.PlatformName(),m_Target)); +}; + +CeCosTest::ServerStatus CTestResource::Query() +{ + CeCosTest::ExecutionParameters e(CeCosTest::ExecutionParameters::QUERY,m_Target); + CeCosSocket *pSock=0; + CeCosTest::ServerStatus s=CeCosTest::Connect(HostPort(),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; +} + +const String CTestResource::Image() const +{ + String str; + str.Format(_T("%10s %20s %8s"),(LPCTSTR)HostPort(),(LPCTSTR)Target(),(LPCTSTR)Serial()); + if(IsLocked()){ + str+=_T(" [RL]"); + } + return str; +} + +bool CTestResource::Matches(LPCTSTR pszHostPort, const CeCosTest::ExecutionParameters &e) +{ + bool rc=false; + ENTERCRITICAL; + if(Load()){ + CTestResource *pResource=Lookup(pszHostPort); + 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 strHost; + int nPort; + CeCosSocket::ParseHostPort(HostPort(),strHost,nPort); + String strCmd; + strCmd.Format(_T("rsh %s x10reset %s\n"),(LPCTSTR)strHost,ResetString()); + pfnLog(pfnLogparam,strCmd); + + CSubprocess sp; + sp.Run(pfnLog,pfnLogparam,strCmd); + return CResetAttributes::RESET_OK; // FIXME +} + +String CTestResource::FileName() const +{ + String strHost; + int nPort; + CeCosSocket::ParseHostPort(HostPort(),strHost,nPort); + return String::SFormat(_T("%s-%d"),(LPCTSTR)strHost,nPort); +} +