1 //####COPYRIGHTBEGIN####
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
6 // This program is part of the eCos host tools.
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)
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
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.
22 // ----------------------------------------------------------------------------
24 //####COPYRIGHTEND####
25 //=================================================================
31 //=================================================================
32 //=================================================================
33 //#####DESCRIPTIONBEGIN####
38 // Description: Run one or more tests
41 //####DESCRIPTIONEND####
46 //=================================================================
47 // This class represents a single eCos test [executable].
48 // It includes member functions to run the test and to manage related system resources.
49 //=================================================================
51 #include "Collections.h"
53 #include "eCosTestPlatform.h"
54 #include "eCosTestUtils.h"
55 #include "ResetAttributes.h"
64 static LPCTSTR pszFormat;
66 ///////////////////////////////////////////////////////////////////////////
67 // Representation of an elapsed time (units of milliseconds)
68 enum {NOTIMEOUT=0x7fffffff}; // No timeout specified
70 ///////////////////////////////////////////////////////////////////////////
71 // ctors, dtors and their friends
72 class ExecutionParameters;
73 CeCosTest(const ExecutionParameters &e, LPCTSTR const pszExecutable, LPCTSTR const pszTitle=0);
75 // Count of number of instances of this class:
76 static int InstanceCount;
77 // Delete all heap instances of this class (*must* be allocated on heap)
78 static void DeleteAllInstances ();
79 // Simply wait for instances to die a natural death
80 static bool WaitForAllInstances (int nPoll=1000,Duration nTimeout=NOTIMEOUT);
81 // Tap them on the shoulder (does not wait)
82 static void CancelAllInstances ();
83 ///////////////////////////////////////////////////////////////////////////
85 ///////////////////////////////////////////////////////////////////////////
86 // Class used to represent execution parameters (to be passed with request to execute a test)
87 ///////////////////////////////////////////////////////////////////////////
88 class ExecutionParameters {
91 enum RequestType { RUN, QUERY, LOCK, UNLOCK, STOP, RequestTypeMax};
92 static RequestType RequestTypeValue(LPCTSTR );
93 static const String Image(RequestType r) { return (r>=0 && r<=RequestTypeMax)?String(arRequestImage[r]):String::SFormat(_T("Unknown(%d)"),r); }
95 Duration ActiveTimeout() const { return m_nActiveTimeout; }
96 Duration DownloadTimeout() const { return m_nDownloadTimeout; }
98 const CeCosTestPlatform *Platform() const { return CeCosTestPlatform::Get(m_Target); }
99 LPCTSTR PlatformName() const { return Platform()?Platform()->Name():_T("UNKNOWN"); }
101 RequestType Request() const { return m_Request;}
102 void SetActiveTimeout (Duration t){m_nActiveTimeout=t;}
103 void SetDownloadTimeout (Duration t){m_nDownloadTimeout=t;}
105 ExecutionParameters (
106 RequestType r=CeCosTest::ExecutionParameters::RUN,
107 LPCTSTR Target=_T(""),
108 Duration nActiveTimeout=NOTIMEOUT,
109 Duration nDownloadTimeout=NOTIMEOUT);
110 bool FromStr(LPCTSTR psz);
112 String Image() const;
113 virtual ~ExecutionParameters(){}
116 static LPCTSTR arRequestImage [1+RequestTypeMax];
118 Duration m_nActiveTimeout,m_nDownloadTimeout;
119 RequestType m_Request;
126 ///////////////////////////////////////////////////////////////////////////
128 ///////////////////////////////////////////////////////////////////////////
129 // Result status stuff.
130 // Order is important - SetStatus can only change status in left-to-right direction
131 void AnalyzeOutput();
132 enum StatusType {NotStarted, NoResult, Inapplicable, Pass, DownloadTimeOut, TimeOut, Cancelled, Fail,
133 AssertFail, StatusTypeMax};
134 static StatusType StatusTypeValue (LPCTSTR const pszStr);
135 static const String Image(StatusType s) { return (s>=0 && s<StatusTypeMax)?String(arResultImage[s]):String::SFormat(_T("Unknown(%d)"),s); }
136 ///////////////////////////////////////////////////////////////////////////
138 ///////////////////////////////////////////////////////////////////////////
140 LPCTSTR const Executable() const { return m_strExecutable;} // Executable name
142 StatusType Status() const { return m_Status; } // Test status
144 Duration Download() const { return m_nDownloadTime; } // Download time
145 Duration Total() const { return m_nTotalTime; } // Total
146 Duration MaxInactive() const { return m_nMaxInactiveTime; } // Max. inactive
148 LPCTSTR const Output() const { return m_strOutput; } // Output generated by a test run [for report purposes]
149 //const CTestResource * const Port() const { return m_pResource; } // Resource used for a test run [for report purposes]
151 const String ResultString (bool bIncludeOutput=true) const;
152 ///////////////////////////////////////////////////////////////////////////
154 ///////////////////////////////////////////////////////////////////////////
157 // Run a test locally:
160 // Run a test remotely:
161 // If pszRemoteHostPort is given, it sends the test for execution on the given host:post.
162 // Otherwise, a suitable host:port is determined from the test resource information.
163 bool RunRemote (LPCTSTR const pszRemoteHostPort);
164 ///////////////////////////////////////////////////////////////////////////
166 ///////////////////////////////////////////////////////////////////////////
167 // Resource functions
169 // Run as a server on given TCP/IP port
170 static bool RunAgent(int nTcpPort);
172 bool InteractiveInferior(LPCTSTR pszHostPort,TCHAR **argv);
173 void SetTimeouts (Duration dActive=NOTIMEOUT,Duration dDownload=NOTIMEOUT/*,Duration dElapsed=15*60*1000*/);
174 void SetExecutable (LPCTSTR pszExecutable);
180 String &strExecutionHostPort,
181 String &strExecutableTail,
184 Duration &nTotalTime,
185 Duration &nMaxInactiveTime,
186 Duration &nDownloadTime,
187 Duration &nDownloadTimeout,
188 Duration &nActiveTimeout,
189 int &nDownloadedSize);
191 enum ServerStatus {SERVER_BUSY, SERVER_READY, SERVER_CANT_RUN, CONNECTION_FAILED, SERVER_LOCKED, ServerStatusMax};
192 static LPCTSTR const Image(ServerStatus s) { return arServerStatusImage[MIN(s,ServerStatusMax)]; }
193 static ServerStatus ServerStatusValue(LPCTSTR psz);
195 // Force the result to change. Generally you can only set the result left-to-right in the order of the enumeration literals
196 void ForceResult(StatusType s) { m_Status=s; }
198 // Get size information (generally by running *gdb-size)
201 // Connect to a test server
202 static ServerStatus CeCosTest::Connect (LPCTSTR pszHostPort, CeCosSocket *&pSock, const ExecutionParameters &e,String &strInfo,Duration dTimeout=10*1000);
204 // Log some output. The accumulated output can be retrieved using Output()
205 void Log (LPCTSTR const pszFormat,...);
206 void LogString (LPCTSTR psz);
211 void Cancel (); // Stop the run
213 // Connect to m_strExecutionHostPort
214 void ConnectForExecution ();
216 // Callback used when EXEC output is used to create host-side processes
217 static void CALLBACK AppendFunc(void *pParam,LPCTSTR psz) { ((CeCosTest*)pParam)->Log(_T("%%%% %s"),psz);}
219 void GetInferiorCommands (StringArray &arstrInferiorCmds);
220 CSubprocess *m_pspPipe;
221 PtrArray m_arpExecsp;
223 // Extract a directive (such as "EXEC:") from the test output. The index passed keeps track of the last such
224 // directive extracted such that successive calls march through the output, returning a different one each time.
225 bool GetDirective (LPCTSTR pszDirective, String &str,int &nIndex);
227 // Keep track of directives in the gdb output
228 int m_nLastGdbInst; // GDB
229 int m_nLastExecInst; // EXEC
230 int m_nLastTimeoutInst; // TIMEOUT
231 int m_nLastPipeInst; // PIPE
233 // Commands to be sent to gdb, or other inferior process
234 StringArray m_arstrInferiorCmds;
236 unsigned int m_nCmdIndex;
238 // Inferior process output comes through here
239 static void CALLBACK SInferiorOutputFunc(void *pParam,LPCTSTR psz) { ((CeCosTest *)pParam)->InferiorOutputFunc(psz); }
240 void InferiorOutputFunc(LPCTSTR psz);
242 // Has a timeout occurred? Returns false if so.
243 static bool CALLBACK SCheckForTimeout(void *pParam) { return ((CeCosTest *)pParam)->CheckForTimeout(); }
245 // Read target ready indicator from server
246 bool GetTargetReady(String &strHostPort);
248 // This may be set to force the socket-to-serial connection to terminate
249 bool m_bStopConnectSocketToSerial;
251 // Convert a path to one understandable by Cygwin
252 static String CygPath (LPCTSTR pszPath);
254 // Are we at a prompt?
257 // To limit calls to ps, under UNIX. This prevents the acquisition of cpu time consuming the whole machine :-).
258 mutable Time m_tInferiorCpuTime;
259 mutable Time m_tPrevSample;
260 Time InferiorTime() const;
262 unsigned int m_nStrippedSize;
264 // Path to use to execute subprocesses
267 // Size of executable
268 unsigned int m_nFileSize;
270 // host:port we are connecting to
271 String m_strExecutionHostPort;
273 ///////////////////////////////////////////////////////////////////////////
274 // Stuff to manage running gdb (or some other inferior process)
275 bool CheckForTimeout(); // Check for a timeout - set status and return false if it happens
276 bool m_bDownloading; // Are we currently downloading executable?
277 bool InferiorProcessAlive (); // Is gdb still alive and kicking?
278 Time m_tBase; // Base used for measurement of timeouts
279 Time m_tBase0; // Base used for measurement of timeouts
280 Time m_tWallClock0; // When the test was actually started
282 ///////////////////////////////////////////////////////////////////////////
283 // Close the socket used by the current class instance
286 bool send(const void * const pData,unsigned int nLength,LPCTSTR const pszMsg=_T(""),Duration dTimeout=10*1000);
287 bool recv(const void *pData,unsigned int nLength,LPCTSTR const pszMsg=_T(""),Duration dTimeout=10*1000);
289 bool sendResult(Duration dTimeout=10*1000);
290 bool recvResult(Duration dTimeout=10*1000);
292 ///////////////////////////////////////////////////////////////////////////
294 ///////////////////////////////////////////////////////////////////////////
295 CeCosSocket *m_pSock;
297 ExecutionParameters m_ep;
299 // Chaining to allow *AllInstances functions to work:
300 static CeCosTest * pFirstInstance;
301 CeCosTest * m_pPrevInstance;
302 CeCosTest * m_pNextInstance;
304 void RunInferior (LPCTSTR pszCmdline);
306 bool OutputContains(LPCTSTR psz) const { return 0!=_tcsstr(m_strOutput,psz); }
308 static void CALLBACK SAcceptThreadFunc (void *pParam) {((CeCosTest *)pParam)->AcceptThreadFunc(); }
309 void AcceptThreadFunc();
311 static void CALLBACK SConnectSocketToSerialThreadFunc(void *pParam) { ((CeCosTest *)pParam)->ConnectSocketToSerialThreadFunc(); }
312 void ConnectSocketToSerialThreadFunc();
314 String m_strExecutable;
317 void SetStatus (StatusType status);
320 Duration m_nDownloadTime;
321 Duration m_nTotalTime;
322 Duration m_nMaxInactiveTime;
324 CTestResource *m_pResource;
327 String m_strOutput; // the output of the test run goes here
329 static LPCTSTR const arResultImage[1+StatusTypeMax];
330 static LPCTSTR const arServerStatusImage[1+ServerStatusMax];
331 bool m_bConnectSocketToSerialThreadDone;
332 static void CALLBACK ResetLogFunc(void *pParam, LPCTSTR psz);
334 // These are used by RunAgent and its friends for setting up the RDI connection
336 int m_nAuxListenSock;
339 }; // class CeCosTest