comparison 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
comparison
equal deleted inserted replaced
75:41bf073c0c32 76:435cced73e2f
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 #ifdef _WIN32
46 #include "Subprocess.h"
47 #endif
48 #include "TestResource.h"
49
50 CTestResource *CTestResource::pFirstInstance=0;
51 unsigned int CTestResource::nCount=0;
52
53 String CTestResource::strResourceHost;
54 int CTestResource::nResourcePort;
55
56 CTestResource::CTestResource(LPCTSTR target, LPCTSTR pszDownloadPort, int nBaud, LPCTSTR pszResetString):
57 m_strReset(pszResetString),
58 m_bInUse(false),
59 m_nBaud(nBaud),
60 m_strPort(pszDownloadPort),
61 m_bLocked(false),
62 m_Target(target),
63 m_strHost(CeCosTestUtils::HostName()),
64 m_nPort(0)
65 {
66 VTRACE(_T("@@@ Created resource %08x %s\n"),(unsigned int)this,(LPCTSTR)Output());
67 Chain();
68 }
69
70 CTestResource::~CTestResource()
71 {
72 ENTERCRITICAL;
73 VTRACE(_T("@@@ Destroy resource %08x %s\n"),this,(LPCTSTR)Output());
74 if(m_pPrevInstance || m_pNextInstance){
75 nCount--;
76 }
77 if(pFirstInstance==this){
78 pFirstInstance=m_pNextInstance;
79 }
80 if(m_pPrevInstance){
81 m_pPrevInstance->m_pNextInstance=m_pNextInstance;
82 }
83 if(m_pNextInstance){
84 m_pNextInstance->m_pPrevInstance=m_pPrevInstance;
85 }
86 LEAVECRITICAL;
87 }
88
89 // Find the resource matching the given host:port specification
90 // Returns 0 if no such host:port found
91 CTestResource * CTestResource::Lookup(LPCTSTR pszHost, int nPort)
92 {
93 CTestResource *pResource;
94 ENTERCRITICAL;
95 for(pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){
96 if(nPort==pResource->TcpipPort() && 0==_tcsicmp(pszHost,pResource->Host())){
97 break;
98 }
99 }
100 LEAVECRITICAL;
101 return pResource;
102 }
103
104 unsigned int CTestResource::GetMatchCount (const CeCosTest::ExecutionParameters &e,bool bIgnoreLocking)
105 {
106 unsigned int i=0;
107 ENTERCRITICAL;
108 for(const CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){
109 if(pResource->Matches(e,bIgnoreLocking)){
110 i++;
111 }
112 }
113 LEAVECRITICAL;
114 return i;
115 }
116
117 bool CTestResource::GetMatches (const CeCosTest::ExecutionParameters &e, StringArray &arstr, bool bIgnoreLocking)
118 {
119 bool rc=false;
120 arstr.clear();
121 if(LoadSocket()){
122 ENTERCRITICAL;
123 for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){
124 if(pResource->Matches(e,bIgnoreLocking)){
125 arstr.push_back(CeCosTestSocket::HostPort(pResource->Host(),pResource->TcpipPort()));
126 }
127 }
128 LEAVECRITICAL;
129 rc=true;
130 }
131 return rc;
132 }
133
134 void CTestResource::DeleteAllInstances()
135 {
136 ENTERCRITICAL;
137 while(pFirstInstance){
138 delete pFirstInstance;
139 }
140 LEAVECRITICAL;
141 }
142
143 bool CTestResource::LoadFile (LPCTSTR psz,void *key)
144 {
145 bool rc=true;
146 ENTERCRITICAL;
147 DeleteAllInstances();
148 #ifdef _WIN32
149 if(key){
150 // Find all the keys under "psz" and load from each of them
151 HKEY hKey;
152 if(ERROR_SUCCESS==RegOpenKeyEx ((HKEY)key, psz, 0L, KEY_ENUMERATE_SUB_KEYS, &hKey)){
153 TCHAR szName[256];
154 DWORD dwSizeName=sizeof szName;
155 FILETIME ftLastWriteTime;
156 for(DWORD dwIndex=0;ERROR_SUCCESS==RegEnumKeyEx(hKey, dwIndex, szName, &dwSizeName, NULL, NULL, NULL, &ftLastWriteTime); dwIndex++){
157 CTestResource *pResource=new CTestResource(_T(""));
158 String strKey;
159 strKey.Format(_T("%s\\%s"),psz,szName);
160 CTestResourceProperties prop1(pResource,strKey,key);
161 prop1.SetDefaults();
162 prop1.Load();
163 dwSizeName=sizeof szName;
164 }
165 RegCloseKey(hKey);
166 }
167 } else
168 #endif
169 {
170 // Find all the files in directory "psz" and load from each of them
171 void *pHandle;
172 TCHAR szOrigDir[256];
173 _tgetcwd(szOrigDir,sizeof szOrigDir-1);
174 if(0==_tchdir(psz)){
175 String strFile;
176 for(bool b=CeCosTestUtils::StartSearch(pHandle,strFile);b;b=CeCosTestUtils::NextFile(pHandle,strFile)){
177 struct _stat buf;
178 if(0==_tstat(strFile,&buf) && 0==(S_IFDIR&buf.st_mode)){
179 CTestResource *pResource=new CTestResource(_T(""));
180 CTestResourceProperties prop1(pResource,strFile);
181 prop1.SetDefaults();
182 prop1.Load();
183 }
184 }
185 CeCosTestUtils::EndSearch(pHandle);
186 } else {
187 TRACE(_T("Failed to change to %s from %s\n"),psz,szOrigDir);
188 }
189 _tchdir(szOrigDir);
190 }
191 LEAVECRITICAL;
192
193 return rc;
194 }
195
196 bool CTestResource::SaveFile (LPCTSTR psz,void *key)
197 {
198 bool rc=false;
199 ENTERCRITICAL;
200 #ifdef _WIN32
201 if(key){
202 // Delete all the keys under "psz"
203 HKEY hKey;
204 if(ERROR_SUCCESS==RegOpenKeyEx ((HKEY)key, psz, 0L, KEY_ENUMERATE_SUB_KEYS, &hKey)){
205 TCHAR szName[256];
206 DWORD dwSizeName=sizeof szName;
207 FILETIME ftLastWriteTime;
208 DWORD dwIndex;
209 if(ERROR_SUCCESS==RegQueryInfoKey(hKey,0,0,0,&dwIndex,0,0,0,0,0,0,0)){
210 while((signed)--dwIndex>=0){
211 if(ERROR_SUCCESS!=RegEnumKeyEx(hKey, dwIndex, szName, &dwSizeName, NULL, NULL, NULL, &ftLastWriteTime) ||
212 ERROR_SUCCESS!=RegDeleteKey(hKey,szName)){
213 rc=false;
214 }
215 dwSizeName=sizeof szName;
216 }
217 }
218 RegCloseKey(hKey);
219 }
220 } else
221 #endif
222 {
223 // Delete all the files under directory "psz"
224 void *pHandle;
225 TCHAR szOrigDir[256];
226 _tgetcwd(szOrigDir,sizeof szOrigDir-1);
227 if(0==_tchdir(psz)){
228 String strFile;
229 for(bool b=CeCosTestUtils::StartSearch(pHandle,strFile);b;b=CeCosTestUtils::NextFile(pHandle,strFile)){
230 struct _stat buf;
231 if(0==_tstat(strFile,&buf) && 0==(S_IFDIR&buf.st_mode)){
232 _tunlink(strFile);
233 }
234 }
235 CeCosTestUtils::EndSearch(pHandle);
236 } else {
237 fprintf(stderr,"Failed to change to %s from %s\n",psz,szOrigDir);
238 }
239 _tchdir(szOrigDir);
240 }
241
242 rc=true;
243 for(CTestResource *pResource=pFirstInstance;pResource;pResource=pResource->m_pNextInstance){
244 String strName;
245 if(key){
246 strName.Format(_T("%s\\%s-%d"),psz,(LPCTSTR)pResource->m_strHost,pResource->m_nPort);
247 CTestResourceProperties prop1(pResource,strName,key);
248 rc&=prop1.Save();
249 } else {
250 strName.Format(_T("%s%c%s-%d"),psz,cPathsep,(LPCTSTR)pResource->m_strHost,pResource->m_nPort);
251 CTestResourceProperties prop1(pResource,strName,key);
252 rc&=prop1.Save();
253 }
254
255 }
256 LEAVECRITICAL;
257
258 return rc;
259 }
260
261 CTestResource::CTestResourceProperties::CTestResourceProperties(CTestResource *pResource,LPCTSTR psz,void *key):
262 CProperties(psz,key)
263 {
264 CProperties::Add(_T("Baud"), pResource->m_nBaud,0);
265 Add(_T("BoardId"), pResource->m_strBoardID);
266 Add(_T("Date"), pResource->m_strDate);
267 Add(_T("Email"), pResource->m_strEmail);
268 Add(_T("Host"), pResource->m_strHost);
269 CProperties::Add(_T("Locked"), pResource->m_bLocked,0);
270 Add(_T("Originator"), pResource->m_strUser);
271 CProperties::Add(_T("Port"), pResource->m_nPort);
272 Add(_T("Reason"), pResource->m_strReason);
273 Add(_T("Reset"), pResource->m_strReset);
274 Add(_T("Serial"), pResource->m_strPort);
275 Add(_T("Target"), pResource->m_Target);
276 Add(_T("User"), pResource->m_strUser);
277 }
278
279 bool CTestResource::Lock()
280 {
281 if(!m_bLocked){
282 m_bLocked=true;
283 return true;
284 } else {
285 return false;
286 }
287 }
288
289 bool CTestResource::Unlock()
290 {
291 if(m_bLocked){
292 m_bLocked=false;
293 return true;
294 } else {
295 return false;
296 }
297 }
298
299 bool CTestResource::LoadSocket(LPCTSTR pszResourceHost,int nResourcePort,Duration dTimeout/*=10*1000*/)
300 {
301 bool rc=false;
302 ENTERCRITICAL;
303 CTestResource *pResource;
304 // If the resource is in use, we don't dare delete it!
305 for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){
306 pResource->m_bFlag=false;
307 }
308 CeCosTestSocket sock;
309 if(sock.Connect(pszResourceHost,nResourcePort,dTimeout)){
310 // Write the message to the socket
311 int nRequest=0; // read
312 if(!sock.sendInteger(nRequest)){
313 ERROR(_T("Failed to write to socket\n"));
314 } else {
315 int nResources;
316 if(sock.recvInteger(nResources,_T(""),dTimeout)){
317 rc=true;
318 while(nResources--){
319 String strImage;
320 if(sock.recvString(strImage,_T(""),dTimeout)){
321 VTRACE(_T("Recv \"%s\"\n"),(LPCTSTR)strImage);
322 CTestResource tmp;
323 tmp.FromStr(strImage);
324 CTestResource *pResource=Lookup(tmp.Host(),tmp.TcpipPort());
325 if(0==pResource){
326 pResource=new CTestResource(_T(""));
327 }
328 pResource->FromStr(strImage);
329 pResource->m_bFlag=true;
330 } else {
331 rc=false;
332 break;
333 }
334 }
335 }
336 }
337 }
338 // If the resource is in use, we don't dare delete it!
339 CTestResource *pNext;
340 for(pResource=CTestResource::First();pResource;pResource=pNext){
341 pNext=pResource->Next();
342 if(!pResource->m_bFlag && !pResource->m_bInUse){
343 delete pResource;
344 }
345 }
346
347 LEAVECRITICAL;
348 return rc;
349 }
350
351 void CTestResource::Image(String &str)
352 {
353 CTestResourceProperties prop(this);
354 str=prop.MakeCommandString();
355 VTRACE(_T("Make command string %s\n"),(LPCTSTR)str);
356 }
357
358 bool CTestResource::FromStr(LPCTSTR pszImage)
359 {
360 CTestResourceProperties prop(this);
361 prop.LoadFromCommandString(pszImage);
362 VTRACE(_T("From command string %s\n"),pszImage);
363 return true;
364 }
365
366 void CTestResource::Chain()
367 {
368 ENTERCRITICAL;
369 nCount++;
370 m_pNextInstance=pFirstInstance;
371 if(m_pNextInstance){
372 m_pNextInstance->m_pPrevInstance=this;
373 }
374 m_pPrevInstance=0;
375 pFirstInstance=this;
376 LEAVECRITICAL;
377 }
378
379 bool CTestResource::Matches (const CeCosTest::ExecutionParameters &e,bool bIgnoreLocking) const
380 {
381 return (bIgnoreLocking||(!m_bLocked)) && (0==_tcsicmp(e.Target(),m_Target));
382 };
383
384 bool CTestResource::SaveSocket(LPCTSTR pszResourceServer,int nResourcePort,Duration dTimeout)
385 {
386 bool rc=true;
387 ENTERCRITICAL;
388 CeCosTestSocket sock(pszResourceServer,nResourcePort, dTimeout);
389 if(sock.Ok()){
390 // Write the message to the socket
391 int nRequest=1; //write
392 if(!sock.sendInteger(nRequest, _T(""),dTimeout)){
393 ERROR(_T("Failed to write to socket\n"));
394 rc=false;
395 } else {
396 int nResources=0;
397 CTestResource *pResource;
398 for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){
399 nResources++;
400 }
401 if(sock.sendInteger(nResources,_T("resource count"),dTimeout)){
402 for(pResource=CTestResource::First();pResource;pResource=pResource->Next()){
403 String strImage;
404 pResource->Image(strImage);
405 TRACE(_T("Send \"%s\"\n"),(LPCTSTR)strImage);
406 if(!sock.sendString (strImage, _T("reply"),dTimeout)){
407 rc=false;
408 break;
409 }
410 }
411 } else {
412 rc=false;
413 }
414 }
415 } else {
416 rc=false;
417 }
418 LEAVECRITICAL;
419 return rc;
420 }
421
422 CeCosTest::ServerStatus CTestResource::Query()
423 {
424 CeCosTest::ExecutionParameters e(CeCosTest::ExecutionParameters::QUERY,m_Target);
425 CeCosTestSocket *pSock=0;
426 CeCosTest::ServerStatus s=CeCosTest::Connect(m_strHost,m_nPort,pSock,e,m_strInfo);
427 delete pSock;
428 return s;
429 }
430
431 int CTestResource::Count(const CeCosTest::ExecutionParameters &e)
432 {
433 int nCount=0;
434 for(const CTestResource *p=pFirstInstance;p;p=p->m_pNextInstance){
435 if(p->Matches(e)){
436 nCount++;
437 }
438 }
439 return nCount;
440 }
441
442 bool CTestResource::Use()
443 {
444 bool rc;
445 ENTERCRITICAL;
446 if(m_bInUse){
447 rc=false;
448 } else {
449 m_bInUse=true;
450 rc=true;
451 }
452 LEAVECRITICAL;
453 return rc;
454 }
455
456 CTestResource *CTestResource::GetResource (const CeCosTest::ExecutionParameters &e)
457 {
458 CTestResource *p=0;
459 if(0==Count(e)){
460 ERROR(_T("GetResource: no candidates available\n"));
461 } else {
462 ENTERCRITICAL;
463 for(p=pFirstInstance;p;p=p->m_pNextInstance){
464 if(p->Matches(e) && !p->m_bInUse){
465 TRACE(_T("Acquired %s\n"),p->Serial());
466 p->Use();
467 break;
468 }
469 }
470 LEAVECRITICAL;
471 }
472 return p;
473 }
474
475 String CTestResource::Output() const
476 {
477 String str;
478 str.Format(
479 _T("%10s:%d %20s %8s"),
480 Host(),
481 TcpipPort(),
482 Target(),
483 Serial());
484 if(HasReset()){
485 str+=_T(" Reset:");
486 str+=m_strReset;
487 }
488 if(IsLocked()){
489 str+=_T(" [RL]");
490 }
491 return str;
492 }
493
494 bool CTestResource::Matches(LPCTSTR pszHost, int nPort, const CeCosTest::ExecutionParameters &e)
495 {
496 bool rc=false;
497 ENTERCRITICAL;
498 if(LoadSocket()){
499 CTestResource *pResource=Lookup(pszHost,nPort);
500 if(pResource){
501 rc=pResource->Matches(e);
502 }
503 }
504 LEAVECRITICAL;
505 return rc;
506 }
507
508 CResetAttributes::ResetResult CTestResource::Reset(LogFunc *pfnLog, void *pfnLogparam)
509 {
510 String strReset;
511 strReset.Format(_T("port(%s,%d) %s"),Serial(),Baud(),ResetString());
512 return CResetAttributes(strReset).Reset(pfnLog,pfnLogparam);
513 }
514
515 CResetAttributes::ResetResult CTestResource::Reset(String &str)
516 {
517 return Reset(StringLogFunc,&str);
518 }
519
520 void CALLBACK CTestResource::StringLogFunc (void *pParam,LPCTSTR psz)
521 {
522 *((String *)pParam)+=psz;
523 }
524
525
526 CResetAttributes::ResetResult CTestResource::RemoteReset(LogFunc *pfnLog, void *pfnLogparam)
527 {
528 String strCmd;
529 strCmd.Format(_T("rsh %s x10reset %s\n"),Host(),ResetString());
530 pfnLog(pfnLogparam,strCmd);
531
532 #ifdef _WIN32
533 // because this can be used from GUI tools
534 CSubprocess sp;
535 sp.Run(pfnLog,pfnLogparam,strCmd);
536 #else // UNIX
537 FILE *f=POPEN(strCmd,"rt");
538 if(f){
539 char buf[80];
540 while(fgets(buf,sizeof buf,f)){
541 pfnLog(pfnLogparam,buf);
542 }
543 PCLOSE(f);
544 } else {
545 String strMsg;
546 strMsg.Format(_T("Failed to execute '%s'\n"),(LPCTSTR)strCmd);
547 pfnLog(pfnLogparam,strMsg);
548 }
549 #endif
550 return CResetAttributes::RESET_OK; // FIXME
551 }
552