]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - tools/src/tools/ecostest/common/TestResource.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / ecostest / common / TestResource.cpp
1 //####COPYRIGHTBEGIN####
2 //                                                                          
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
8 // This program is free software; you can redistribute it and/or modify it 
9 // under the terms of the GNU General Public License as published by the Free 
10 // Software Foundation; either version 2 of the License, or (at your option) 
11 // any later version.
12 // 
13 // This program is distributed in the hope that it will be useful, but WITHOUT 
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
15 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
16 // more details.
17 // 
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc., 
20 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 //
22 // ----------------------------------------------------------------------------
23 //                                                                          
24 //####COPYRIGHTEND####
25 //=================================================================
26 //
27 //        TestResource.cpp
28 //
29 //        Resource test class
30 //
31 //=================================================================
32 //=================================================================
33 //#####DESCRIPTIONBEGIN####
34 //
35 // Author(s):     sdf
36 // Contributors:  sdf
37 // Date:          1999-04-01
38 // Description:   This class abstracts a test resource for use in the testing infrastructure
39 // Usage:
40 //
41 //####DESCRIPTIONEND####
42 #include "eCosStd.h"
43 #include "eCosTestUtils.h"
44 #include "eCosTrace.h"
45 #include "Subprocess.h"
46
47 #include "TestResource.h"
48
49 CTestResource *CTestResource::pFirstInstance=0;
50 unsigned int CTestResource::nCount=0;
51
52 String CTestResource::strResourceHostPort;
53
54 CTestResource::CTestResource(LPCTSTR pszHostPort, LPCTSTR target, LPCTSTR  pszDownloadPort, int nBaud, LPCTSTR pszResetString):
55   m_strReset(pszResetString),
56   m_bInUse(false),
57   m_nBaud(nBaud),
58   m_strPort(pszDownloadPort),
59   m_bLocked(false),
60   m_Target(target)
61 {
62   CeCosSocket::ParseHostPort(pszHostPort,m_strHost,m_nPort);
63   VTRACE(_T("@@@ Created resource %08x %s\n"),(unsigned int)this,(LPCTSTR)Image());
64   Chain();
65 }
66
67 CTestResource::~CTestResource()
68 {
69   ENTERCRITICAL;
70   VTRACE(_T("@@@ Destroy resource %08x %s\n"),this,(LPCTSTR)Image());
71   if(m_pPrevInstance || m_pNextInstance){
72     nCount--;
73   }
74   if(pFirstInstance==this){
75     pFirstInstance=m_pNextInstance;
76   }
77   if(m_pPrevInstance){
78     m_pPrevInstance->m_pNextInstance=m_pNextInstance;
79   }
80   if(m_pNextInstance){
81     m_pNextInstance->m_pPrevInstance=m_pPrevInstance;
82   }
83   LEAVECRITICAL;
84 }
85
86 // Find the resource matching the given host:port specification
87 // Returns 0 if no such host:port found
88 CTestResource * CTestResource::Lookup(LPCTSTR pszHostPort)
89 {
90   CTestResource *pResource=NULL;
91   ENTERCRITICAL;
92   String strHost;
93   int nPort;
94   if(CeCosSocket::ParseHostPort(pszHostPort,strHost,nPort)){
95     for(pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){
96       if(nPort==pResource->TcpIPPort() && CeCosSocket::SameHost(strHost,pResource->Host())){
97         break;
98       }
99     }
100   }
101   LEAVECRITICAL;
102   return pResource;
103 }
104
105 unsigned int CTestResource::GetMatchCount (const CeCosTest::ExecutionParameters &e,bool bIgnoreLocking)
106 {
107   unsigned int i=0;
108   ENTERCRITICAL;
109   for(const CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){
110     if(pResource->Matches(e,bIgnoreLocking)){
111       i++;
112     }
113   }
114   LEAVECRITICAL;
115   return i;
116 }
117
118 bool CTestResource::GetMatches (const CeCosTest::ExecutionParameters &e, StringArray &arstr, bool bIgnoreLocking)
119 {
120   bool rc=false;
121   arstr.clear();
122   if(Load()){
123     ENTERCRITICAL;
124     for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){
125                   if(pResource->Matches(e,bIgnoreLocking)){
126         arstr.push_back(pResource->HostPort());
127       }
128     }
129     LEAVECRITICAL;
130     rc=true;
131   }
132   return rc;
133 }
134
135 void CTestResource::DeleteAllInstances()
136 {
137   ENTERCRITICAL;
138   while(pFirstInstance){
139     delete pFirstInstance;
140   }
141   LEAVECRITICAL;
142 }
143
144 bool CTestResource::LoadFromDirectory (LPCTSTR psz)
145 {
146   bool rc=true;
147   ENTERCRITICAL;
148   DeleteAllInstances();
149   // Find all the files in directory "psz" and load from each of them
150   TCHAR szOrigDir[256];
151   _tgetcwd(szOrigDir,sizeof szOrigDir-1);
152   if(0==_tchdir(psz)){
153     String strFile;
154     void *pHandle;
155     for(bool b=CeCosTestUtils::StartSearch(pHandle,strFile);b;b=CeCosTestUtils::NextFile(pHandle,strFile)){
156       if(CeCosTestUtils::IsFile(strFile)){
157         CTestResource *pResource=new CTestResource(_T(""),_T(""));
158         CTestResourceProperties prop(pResource);
159         prop.LoadFromFile(strFile);
160       }
161     }
162     CeCosTestUtils::EndSearch(pHandle);
163   } else {
164     TRACE(_T("Failed to change to %s from %s\n"),psz,szOrigDir);
165   }
166   _tchdir(szOrigDir);
167   LEAVECRITICAL;
168   
169   return rc;
170 }
171
172 bool CTestResource::SaveToDirectory (LPCTSTR pszDir)
173 {
174   bool rc=false;    
175   ENTERCRITICAL;
176   {
177     // Delete all the files under directory "pszDir"
178     void *pHandle;
179     TCHAR szOrigDir[256];
180     _tgetcwd(szOrigDir,sizeof szOrigDir-1);
181     if(0==_tchdir(pszDir)){
182       String strFile;
183       for(bool b=CeCosTestUtils::StartSearch(pHandle,strFile);b;b=CeCosTestUtils::NextFile(pHandle,strFile)){
184         if(CeCosTestUtils::IsFile(strFile)){
185           _tunlink(strFile);
186         }
187       }
188       CeCosTestUtils::EndSearch(pHandle);
189       rc=true;
190       for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){
191         CTestResourceProperties prop(pResource);
192         rc&=prop.SaveToFile(pResource->FileName());
193       }
194     } else {
195       fprintf(stderr,"Failed to change to %s from %s\n",pszDir,szOrigDir);
196     }
197     _tchdir(szOrigDir);
198   }
199   
200   LEAVECRITICAL;
201   
202   return rc;
203 }
204
205 #ifdef _WIN32
206 bool CTestResource::LoadFromRegistry(HKEY key,LPCTSTR psz)
207 {
208   // Find all the keys under "psz" and load from each of them
209   bool rc=false;    
210   ENTERCRITICAL;
211   HKEY hKey;
212   if(ERROR_SUCCESS==RegOpenKeyEx ((HKEY)key, psz, 0L, KEY_ENUMERATE_SUB_KEYS, &hKey)){
213                 TCHAR szName[256];
214     DWORD dwSizeName=sizeof szName;
215     FILETIME ftLastWriteTime;
216     for(DWORD dwIndex=0;ERROR_SUCCESS==RegEnumKeyEx(hKey, dwIndex, szName, &dwSizeName, NULL, NULL, NULL, &ftLastWriteTime); dwIndex++){
217       CTestResource *pResource=new CTestResource(_T(""),_T(""));
218       String strKey;
219       strKey.Format(_T("%s\\%s"),psz,szName);
220       CTestResourceProperties prop1(pResource);
221       prop1.LoadFromRegistry(key,strKey);
222       dwSizeName=sizeof szName;
223     }
224     RegCloseKey(hKey);
225   }
226   LEAVECRITICAL;
227   return rc;
228 }
229
230 bool CTestResource::SaveToRegistry(HKEY key,LPCTSTR psz)
231 {
232   bool rc=false;    
233   ENTERCRITICAL;
234   // Delete all the keys under "psz"
235   HKEY hKey;
236   if(ERROR_SUCCESS==RegOpenKeyEx ((HKEY)key, psz, 0L, KEY_ENUMERATE_SUB_KEYS, &hKey)){
237     TCHAR szName[256];
238     DWORD dwSizeName=sizeof szName;
239     FILETIME ftLastWriteTime;
240     DWORD dwIndex;
241     if(ERROR_SUCCESS==RegQueryInfoKey(hKey,0,0,0,&dwIndex,0,0,0,0,0,0,0)){
242       while((signed)--dwIndex>=0){
243         if(ERROR_SUCCESS!=RegEnumKeyEx(hKey, dwIndex, szName, &dwSizeName, NULL, NULL, NULL, &ftLastWriteTime) ||
244           ERROR_SUCCESS!=RegDeleteKey(hKey,szName)){
245           rc=false;
246         }
247         dwSizeName=sizeof szName;
248       }
249     }
250     RegCloseKey(hKey);
251   }
252   rc=true;
253   for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){
254     CTestResourceProperties prop1(pResource);
255     rc&=prop1.SaveToRegistry(key,pResource->FileName());
256   }
257
258   LEAVECRITICAL;
259   return rc;
260 }
261
262 #endif
263
264 CTestResource::CTestResourceProperties::CTestResourceProperties(CTestResource *pResource)
265 {
266   Add(_T("Baud"),       pResource->m_nBaud);
267   Add(_T("BoardId"),    pResource->m_strBoardID);
268   Add(_T("Date"),       pResource->m_strDate);
269   Add(_T("Email"),      pResource->m_strEmail);
270   Add(_T("Host"),       pResource->m_strHost);
271   Add(_T("Port"),       pResource->m_nPort);
272   Add(_T("Locked"),     pResource->m_bLocked);
273   Add(_T("Originator"), pResource->m_strUser);
274   Add(_T("Reason"),     pResource->m_strReason);
275   Add(_T("Reset"),      pResource->m_strReset);
276   Add(_T("Serial"),     pResource->m_strPort);
277   Add(_T("Target"),     pResource->m_Target);
278   Add(_T("User"),       pResource->m_strUser);
279 }
280
281 bool CTestResource::Lock()
282 {
283   if(!m_bLocked){
284     m_bLocked=true;
285     return true;
286   } else {
287     return false;
288   }
289 }
290
291 bool CTestResource::Unlock()
292 {
293   if(m_bLocked){
294     m_bLocked=false;
295     return true;
296   } else {
297     return false;
298   }
299 }
300
301 bool CTestResource::LoadSocket(LPCTSTR pszResourceHostPort,Duration dTimeout/*=10*1000*/)
302 {
303   bool rc=false;
304   ENTERCRITICAL;
305   CTestResource *pResource;
306   // If the resource is in use, we don't dare delete it!
307   for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){
308     pResource->m_bFlag=false;
309   }
310   CeCosSocket sock;
311   if(sock.Connect(pszResourceHostPort,dTimeout)){
312     // Write the message to the socket
313     int nRequest=0; // read
314     if(!sock.sendInteger(nRequest)){
315       ERROR(_T("Failed to write to socket\n"));
316     } else {
317       int nResources;
318       if(sock.recvInteger(nResources,_T(""),dTimeout)){
319         rc=true;
320         while(nResources--){
321           String strImage;
322           if(sock.recvString(strImage,_T(""),dTimeout)){
323             VTRACE(_T("Recv \"%s\"\n"),(LPCTSTR)strImage);
324             CTestResource tmp;
325             tmp.FromStr(strImage);
326             CTestResource *pResource=Lookup(tmp.HostPort());
327             if(0==pResource){
328               pResource=new CTestResource(_T(""),_T(""));
329             }
330             pResource->FromStr(strImage);
331             pResource->m_bFlag=true;
332           } else {
333             rc=false;
334             break;
335           }
336         }
337       }
338     }
339   }
340   // If the resource is in use, we don't dare delete it!
341   CTestResource *pNext;
342   for(pResource=CTestResource::First();pResource;pResource=pNext){
343     pNext=pResource->Next();
344     if(!pResource->m_bFlag && !pResource->m_bInUse){
345       delete pResource;
346     }
347   }
348   
349   LEAVECRITICAL;
350   return rc;
351 }
352
353 bool CTestResource::SaveSocket(LPCTSTR pszResourceHostPort,Duration dTimeout)
354 {
355   bool rc=true;
356   ENTERCRITICAL;
357   CeCosSocket sock(pszResourceHostPort, dTimeout);
358   if(sock.Ok()){
359     // Write the message to the socket
360     int nRequest=1; //write
361     if(!sock.sendInteger(nRequest, _T(""),dTimeout)){
362       ERROR(_T("Failed to write to socket\n"));
363       rc=false;
364     } else {
365       int nResources=0;
366       CTestResource *pResource;
367       for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){
368         nResources++;
369       }
370       if(sock.sendInteger(nResources,_T("resource count"),dTimeout)){
371         for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){
372           String strImage;
373           CTestResourceProperties prop(pResource);
374           strImage=prop.MakeCommandString();
375           TRACE(_T("Send \"%s\"\n"),(LPCTSTR)strImage);
376           if(!sock.sendString (strImage, _T("reply"),dTimeout)){
377             rc=false;
378             break;
379           }
380         }
381       } else {
382         rc=false;
383       }
384     }
385   } else {
386     rc=false;
387   }
388   LEAVECRITICAL;
389   return rc;
390 }
391
392 /*
393 void CTestResource::Image(String &str)
394 {
395   CTestResourceProperties prop(this);
396   str=prop.MakeCommandString();
397   VTRACE(_T("Make command string %s\n"),(LPCTSTR)str);
398 }
399 */
400
401 bool CTestResource::FromStr(LPCTSTR pszImage)
402 {
403   CTestResourceProperties prop(this);
404   prop.LoadFromCommandString(pszImage);
405   VTRACE(_T("From command string %s\n"),pszImage);
406   return true;
407 }
408
409 void CTestResource::Chain()
410 {
411   ENTERCRITICAL;
412   nCount++;
413   m_pNextInstance=pFirstInstance;
414   if(m_pNextInstance){
415     m_pNextInstance->m_pPrevInstance=this;
416   }
417   m_pPrevInstance=0;
418   pFirstInstance=this;
419   LEAVECRITICAL;
420 }
421
422 bool CTestResource::Matches  (const CeCosTest::ExecutionParameters &e,bool bIgnoreLocking) const
423 {
424   return (bIgnoreLocking||(!m_bLocked)) && (0==_tcsicmp(e.PlatformName(),m_Target)); 
425 };
426
427 CeCosTest::ServerStatus CTestResource::Query() 
428 {
429   CeCosTest::ExecutionParameters e(CeCosTest::ExecutionParameters::QUERY,m_Target);
430   CeCosSocket *pSock=0;
431   CeCosTest::ServerStatus s=CeCosTest::Connect(HostPort(),pSock,e,m_strInfo);
432   delete pSock;
433   return s;
434 }
435
436 int CTestResource::Count(const CeCosTest::ExecutionParameters &e)
437 {
438   int nCount=0;
439   for(const CTestResource *p=pFirstInstance;p;p=p->m_pNextInstance){
440     if(p->Matches(e)){
441       nCount++;
442     }
443   }
444   return nCount;
445 }
446
447 bool CTestResource::Use()
448 {
449   bool rc;
450   ENTERCRITICAL;
451   if(m_bInUse){
452     rc=false;
453   } else {
454     m_bInUse=true;
455     rc=true;
456   }
457   LEAVECRITICAL;
458   return rc;
459 }
460
461 CTestResource *CTestResource::GetResource (const CeCosTest::ExecutionParameters &e)
462 {
463   CTestResource *p=0;
464   if(0==Count(e)){
465     ERROR(_T("GetResource: no candidates available\n"));
466   } else {
467     ENTERCRITICAL;
468     for(p=pFirstInstance;p;p=p->m_pNextInstance){
469       if(p->Matches(e) && !p->m_bInUse){
470         TRACE(_T("Acquired %s\n"),p->Serial());
471                                     p->Use();
472             break;
473       }
474     }
475     LEAVECRITICAL;
476   }
477   return p;
478 }
479
480 const String CTestResource::Image() const
481 {
482   String str;
483   str.Format(_T("%10s %20s %8s"),(LPCTSTR)HostPort(),(LPCTSTR)Target(),(LPCTSTR)Serial());
484   if(IsLocked()){
485     str+=_T(" [RL]");
486   }
487   return str;
488 }
489
490 bool CTestResource::Matches(LPCTSTR pszHostPort, const CeCosTest::ExecutionParameters &e)
491 {
492   bool rc=false;
493   ENTERCRITICAL;
494   if(Load()){
495     CTestResource *pResource=Lookup(pszHostPort);
496     if(pResource){
497       rc=pResource->Matches(e);
498     }
499   }
500   LEAVECRITICAL;
501   return rc;
502 }
503
504 CResetAttributes::ResetResult CTestResource::Reset(LogFunc *pfnLog, void *pfnLogparam)
505 {
506   String strReset;
507   strReset.Format(_T("port(%s,%d) %s"),Serial(),Baud(),ResetString());
508   return CResetAttributes(strReset).Reset(pfnLog,pfnLogparam);
509 }
510
511 CResetAttributes::ResetResult CTestResource::Reset(String &str)
512 {
513   return Reset(StringLogFunc,&str);
514 }
515
516 void CALLBACK CTestResource::StringLogFunc (void *pParam,LPCTSTR psz)
517 {
518   *((String *)pParam)+=psz;
519 }
520
521
522 CResetAttributes::ResetResult CTestResource::RemoteReset(LogFunc *pfnLog, void *pfnLogparam)
523 {
524   String strHost;
525   int nPort;
526   CeCosSocket::ParseHostPort(HostPort(),strHost,nPort);
527   String strCmd;
528   strCmd.Format(_T("rsh %s x10reset %s\n"),(LPCTSTR)strHost,ResetString());
529   pfnLog(pfnLogparam,strCmd);
530
531   CSubprocess sp;
532   sp.Run(pfnLog,pfnLogparam,strCmd);
533   return CResetAttributes::RESET_OK; // FIXME
534 }
535
536 String CTestResource::FileName() const
537 {
538   String strHost;
539   int nPort;
540   CeCosSocket::ParseHostPort(HostPort(),strHost,nPort);
541   return String::SFormat(_T("%s-%d"),(LPCTSTR)strHost,nPort);
542 }
543