|
1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <windows.h> |
|
17 |
|
18 #ifdef __MSVCDOTNET__ |
|
19 #include <iostream> |
|
20 #include <fstream> |
|
21 using namespace std; |
|
22 #else //!__MSVCDOTNET__ |
|
23 #include <iostream.h> |
|
24 #include <fstream.h> |
|
25 #endif //__MSVCDOTNET__ |
|
26 |
|
27 #include <stdio.h> |
|
28 #include <errno.h> |
|
29 |
|
30 #if defined(__VC32__) && !defined(__MSVCDOTNET__) |
|
31 #pragma warning( disable : 4710 ) // 'fn': function not inlined |
|
32 #endif // old MSVC |
|
33 |
|
34 const unsigned int KMaxLineLen=256; |
|
35 const unsigned int KTimeout=600000; // 10 minutes |
|
36 |
|
37 |
|
38 void NumFileLines(ifstream& inStream, unsigned int &aNumLines) |
|
39 { |
|
40 // finds out how many lines are in the file specified |
|
41 |
|
42 aNumLines=0; |
|
43 inStream.clear(); |
|
44 inStream.seekg(0); |
|
45 |
|
46 char str[KMaxLineLen]; |
|
47 while (!inStream.eof()) |
|
48 { |
|
49 inStream.getline(str, KMaxLineLen); |
|
50 aNumLines++; |
|
51 } |
|
52 } |
|
53 |
|
54 void GetTestData(ifstream& inStream, char (*aDataArray)[KMaxLineLen], unsigned int &aNumTests) |
|
55 { |
|
56 // fill the test data structure from the file stream |
|
57 |
|
58 aNumTests=0; |
|
59 inStream.clear(); |
|
60 inStream.seekg(0); |
|
61 |
|
62 char str[KMaxLineLen]=""; |
|
63 while (!inStream.eof()) |
|
64 { |
|
65 bool charsPresent=0; |
|
66 inStream.getline(str, KMaxLineLen); |
|
67 if (strlen(str)) |
|
68 { |
|
69 unsigned int len=strlen(str); |
|
70 for (unsigned int i=0; i<len; i++) |
|
71 { |
|
72 if (!isspace(str[i])) |
|
73 { |
|
74 charsPresent=1; |
|
75 break; |
|
76 } |
|
77 } |
|
78 if (charsPresent) |
|
79 { |
|
80 strcpy(aDataArray[aNumTests], str); |
|
81 aNumTests++; |
|
82 } |
|
83 } |
|
84 } |
|
85 } |
|
86 |
|
87 int GetTestOutFileName(char* aOutFile) |
|
88 { |
|
89 // Gets the temporary file in which RTest puts its output |
|
90 |
|
91 const char KTestOutFileName[16]="epocwind.out"; |
|
92 char tmpDir[KMaxLineLen]=""; |
|
93 int r=0; |
|
94 |
|
95 aOutFile[0]='\0'; |
|
96 int len=GetTempPath(KMaxLineLen, tmpDir); |
|
97 if (len==0||len>KMaxLineLen) |
|
98 r=1; |
|
99 |
|
100 if (!r) |
|
101 if (KMaxLineLen > (strlen(KTestOutFileName)+strlen(tmpDir))) |
|
102 { |
|
103 strcpy(aOutFile, tmpDir); |
|
104 strcat(aOutFile, KTestOutFileName); |
|
105 } |
|
106 else |
|
107 r=1; |
|
108 return(r); |
|
109 } |
|
110 |
|
111 void RemoveLeadingSpaces(char* aStr) |
|
112 { |
|
113 // removes leading whitespace from a string |
|
114 |
|
115 int spaces=0; |
|
116 while (isspace(aStr[spaces])) |
|
117 spaces++; |
|
118 int newLen=strlen(aStr)-spaces; |
|
119 for (int j=0;j<=newLen;j++) |
|
120 aStr[j]=aStr[j+spaces]; |
|
121 } |
|
122 |
|
123 int TestSucceeded(char* aLastLineBut1) |
|
124 { |
|
125 // checks whether an EPOC RTest has succeeded by comparing the |
|
126 // last line but 1 in the EPOCWIND.OUT file with a template success |
|
127 // string |
|
128 |
|
129 int r=0; |
|
130 const char KSuccessResult[20]="RTEST: SUCCESS :"; |
|
131 |
|
132 char testStr[KMaxLineLen]; |
|
133 strcpy(testStr,aLastLineBut1); |
|
134 RemoveLeadingSpaces(testStr); |
|
135 testStr[strlen(KSuccessResult)]='\0'; |
|
136 if (strcmp(testStr, KSuccessResult)==0) |
|
137 r=1; |
|
138 return(r); |
|
139 } |
|
140 |
|
141 int GetPenultimateLines(char* aFile, char* aLastLineBut1, char* aLastLineBut2) |
|
142 { |
|
143 // Gets the two penultimate lines in a file. |
|
144 // Returns 0 if successful, 1 otherwise. |
|
145 |
|
146 int r=0; |
|
147 |
|
148 aLastLineBut1[0]='\0'; |
|
149 aLastLineBut2[0]='\0'; |
|
150 |
|
151 ifstream fileStream(aFile); |
|
152 if (!fileStream) |
|
153 r=1; |
|
154 |
|
155 if (!r) |
|
156 { |
|
157 char lastLine[KMaxLineLen]=""; |
|
158 while (!fileStream.eof()) |
|
159 { |
|
160 strcpy(aLastLineBut2, aLastLineBut1); |
|
161 strcpy(aLastLineBut1, lastLine); |
|
162 fileStream.getline(lastLine, KMaxLineLen); |
|
163 } |
|
164 } |
|
165 return(r); |
|
166 } |
|
167 |
|
168 int main(int argc, char *argv[]) |
|
169 { |
|
170 FILE *stream = NULL; |
|
171 if (argc != 2) |
|
172 { |
|
173 cerr << "Syntax: eruntest <batch_file>" << endl; |
|
174 return(1); |
|
175 } |
|
176 // Check if input file exists |
|
177 if( (stream = fopen(argv[1], "r" )) == NULL) |
|
178 { |
|
179 cerr << "ERROR: Cannot open input file " << argv[1] << endl; |
|
180 return(1); |
|
181 } |
|
182 else |
|
183 fclose(stream); |
|
184 // stream the input file |
|
185 ifstream inFile(argv[1]); |
|
186 |
|
187 // get the number of lines in the input file |
|
188 unsigned int numLines=0; |
|
189 NumFileLines(inFile, numLines); |
|
190 |
|
191 // allocate space for the tests names |
|
192 char (*pTests)[KMaxLineLen]; |
|
193 pTests = new char[numLines][KMaxLineLen]; |
|
194 if (!pTests) |
|
195 { |
|
196 cerr << "ERROR: Out of memory" << endl; |
|
197 return(1); |
|
198 } |
|
199 |
|
200 // populate the data structure for the tests |
|
201 unsigned int numTests=0; |
|
202 GetTestData(inFile, pTests, numTests); |
|
203 |
|
204 // Get the test output file name |
|
205 char testOutFile[KMaxLineLen]; |
|
206 if (GetTestOutFileName(testOutFile)!=0) |
|
207 { |
|
208 cerr << "Error getting temporary path" << endl; |
|
209 return(1); |
|
210 } |
|
211 |
|
212 // Get the current directory |
|
213 char currentDir[KMaxLineLen]=""; |
|
214 GetCurrentDirectory(KMaxLineLen, currentDir); |
|
215 strcat(currentDir, "\\"); |
|
216 |
|
217 // Retrieve the STARTUPINFO structure for the current process |
|
218 STARTUPINFO startUpInfo; |
|
219 PROCESS_INFORMATION procInfo; |
|
220 GetStartupInfo(&startUpInfo); |
|
221 |
|
222 unsigned failCount=0; |
|
223 unsigned timeoutCount=0; |
|
224 unsigned cantStartCount=0; |
|
225 unsigned unknownCount=0; |
|
226 |
|
227 // run each test in turn |
|
228 for (unsigned int i=0; i<numTests; i++) |
|
229 { |
|
230 |
|
231 // remove epocwind.out |
|
232 remove(testOutFile); |
|
233 if (errno==EACCES) |
|
234 { |
|
235 cerr << "Cannot remove " << testOutFile << endl; |
|
236 return(1); |
|
237 } |
|
238 |
|
239 // Create the child process |
|
240 if (!CreateProcess(0, pTests[i], 0, 0, FALSE, 0,0, 0, &startUpInfo, &procInfo)) |
|
241 { |
|
242 // int error=GetLastError(); |
|
243 cout << "CAN'T START: " << currentDir << pTests[i] << endl; |
|
244 cantStartCount++; |
|
245 continue; |
|
246 } |
|
247 |
|
248 // Wait for the child process to complete |
|
249 int ret=WaitForSingleObject(procInfo.hProcess, KTimeout); |
|
250 ifstream testOutFileStream(testOutFile); |
|
251 |
|
252 char lastLineBut1[KMaxLineLen]=""; |
|
253 char lastLineBut2[KMaxLineLen]=""; |
|
254 switch (ret) |
|
255 { |
|
256 case WAIT_OBJECT_0: |
|
257 // find out if the test terminated successfully |
|
258 if (GetPenultimateLines(testOutFile, lastLineBut1, lastLineBut2)!=0) |
|
259 { |
|
260 cout << "UNKNOWN: " << currentDir << pTests[i] << endl; |
|
261 cout << " <no test output file>" << endl; |
|
262 unknownCount++; |
|
263 } |
|
264 else |
|
265 { |
|
266 // make the comparison |
|
267 if (TestSucceeded(lastLineBut1)) |
|
268 cout << "PASSED: " << currentDir << pTests[i] << endl; |
|
269 else |
|
270 { |
|
271 cout << "FAILED(RTest): " << currentDir << pTests[i] << endl; |
|
272 cout << " " << lastLineBut2 << endl; |
|
273 cout << " " << lastLineBut1 << endl; |
|
274 cout << endl; |
|
275 failCount++; |
|
276 } |
|
277 } |
|
278 break; |
|
279 case WAIT_FAILED: |
|
280 cout << "FAILED: " << currentDir << pTests[i] << endl; |
|
281 if (GetPenultimateLines(testOutFile, lastLineBut1, lastLineBut2)!=0) |
|
282 { |
|
283 cout << " <no test output file>" << endl; |
|
284 } |
|
285 else |
|
286 { |
|
287 cout << " " << lastLineBut2 << endl; |
|
288 cout << " " << lastLineBut1 << endl; |
|
289 cout << endl; |
|
290 } |
|
291 failCount++; |
|
292 break; |
|
293 case WAIT_TIMEOUT: |
|
294 cout << "TIMED OUT: " << currentDir << pTests[i] << endl; |
|
295 if (GetPenultimateLines(testOutFile, lastLineBut1, lastLineBut2)!=0) |
|
296 { |
|
297 cout << " <no test output file>" << endl; |
|
298 } |
|
299 else |
|
300 { |
|
301 cout << " " << lastLineBut2 << endl; |
|
302 cout << " " << lastLineBut1 << endl; |
|
303 cout << endl; |
|
304 } |
|
305 timeoutCount++; |
|
306 if (!TerminateProcess(procInfo.hProcess, 1)) |
|
307 { |
|
308 cout << "FROZEN: " << currentDir << endl; |
|
309 cout << " Cannot terminate - kill via Task Manager" << endl; |
|
310 cout << endl; |
|
311 } |
|
312 break; |
|
313 } |
|
314 } |
|
315 |
|
316 delete [] pTests; |
|
317 |
|
318 cout << endl; |
|
319 cout << "TotalErrors " << dec << (failCount+timeoutCount+unknownCount+cantStartCount) << endl; |
|
320 cout << " Failures " << dec << failCount << endl; |
|
321 cout << " Timeouts " << dec << timeoutCount << endl; |
|
322 cout << " Unknown " << dec << unknownCount << endl; |
|
323 cout << " Can't start " << dec << cantStartCount << endl; |
|
324 cout << endl; |
|
325 |
|
326 return(0); |
|
327 } |