|
1 // Copyright (c) 2000-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 // Framework for Automated Test code. |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file autotest.cpp |
|
20 */ |
|
21 |
|
22 #include "autotest.h" |
|
23 |
|
24 #include <flogger.h> // for RFileLogger |
|
25 |
|
26 |
|
27 _LIT(KTestKeywordSuccess, "SUCCESS"); |
|
28 _LIT(KTestKeywordFailed, "FAILED"); |
|
29 _LIT(KTestKeywordNotSupported, "NOT SUPPORTED"); |
|
30 |
|
31 // |
|
32 // implementation of CAutoTest |
|
33 // |
|
34 |
|
35 EXPORT_C CAutoTest* CAutoTest::NewL(const struct TAutoTestCase* aTestcases, TInt aNumberOfTestcases, const TDesC& aName, RTest& aTest) |
|
36 /** |
|
37 * 2 phase constructor |
|
38 * |
|
39 * @param aTestcases Pointer to the table with test cases |
|
40 * @param aNumberOfTestcases Number of automated test cases |
|
41 * @param aName Name of the test report file |
|
42 * @param aTest The RTest object owned by the client |
|
43 * @return CAutoTest* A newly created CAutoTest object |
|
44 */ |
|
45 { |
|
46 CAutoTest* p = new (ELeave) CAutoTest(aTestcases, aNumberOfTestcases, aName, aTest); |
|
47 CleanupStack::PushL(p); |
|
48 p->ConstructL(); |
|
49 CleanupStack::Pop(); |
|
50 return p; |
|
51 } |
|
52 |
|
53 |
|
54 CAutoTest::~CAutoTest() |
|
55 /** |
|
56 * D'tor |
|
57 */ |
|
58 { |
|
59 // close file handles |
|
60 iTestReport.Close(); |
|
61 iFileServer.Close(); |
|
62 |
|
63 delete iCommandLine; |
|
64 delete iTestResults; |
|
65 delete iSkipList; |
|
66 iTestCases = NULL; |
|
67 } |
|
68 |
|
69 |
|
70 EXPORT_C TInt CAutoTest::ExecuteL() |
|
71 /** |
|
72 * Execute the test suite. |
|
73 * |
|
74 * @return test result, KErrNone if all tests passed |
|
75 */ |
|
76 { |
|
77 (void)User::LeaveIfError(iTestReport.Write(_L8("--- test report start---\r\n"))); |
|
78 |
|
79 // |
|
80 // machine info |
|
81 // |
|
82 MachineInfoL(); |
|
83 |
|
84 // |
|
85 // date & time info |
|
86 // |
|
87 (void)User::LeaveIfError(iTestReport.Write(_L8("Time started: "))); |
|
88 LogTimeL(); |
|
89 |
|
90 // |
|
91 // component under test info (optional) |
|
92 // |
|
93 if(iCompInfo.Length()) |
|
94 { |
|
95 (void)User::LeaveIfError(iTestReport.Write(_L8("Component info: "))); |
|
96 (void)User::LeaveIfError(iTestReport.Write(iCompInfo)); |
|
97 (void)User::LeaveIfError(iTestReport.Write(_L8("\r\n"))); |
|
98 } |
|
99 |
|
100 |
|
101 // decide to run the menu or the complete test |
|
102 if(iKeepGoing) |
|
103 RunAllTestsL(); |
|
104 else |
|
105 StartMenuL(); |
|
106 |
|
107 // date & time info |
|
108 (void)User::LeaveIfError(iTestReport.Write(_L8("Time finished: "))); |
|
109 LogTimeL(); |
|
110 |
|
111 (void)User::LeaveIfError(iTestReport.Write(_L8("--- test report end---\r\n"))); |
|
112 |
|
113 return iTestSuiteFailed ? 84 : KErrNone; |
|
114 |
|
115 } |
|
116 |
|
117 EXPORT_C void CAutoTest::TestCheckPointCompareL(TInt aVal,TInt aExpectedVal, const TDesC& aText, char* aFile,TInt aLine) |
|
118 { |
|
119 if(aVal == aExpectedVal) |
|
120 return; |
|
121 |
|
122 TBuf<200> temp; |
|
123 temp.Copy(TPtrC8((TText8*)aFile)); |
|
124 |
|
125 iRTest.Printf(_L("FAILED test %d : Val = %d Exp Val = %d file %S, line %d\n") |
|
126 , iTestCase+1, aVal, aExpectedVal, &temp, aLine); |
|
127 |
|
128 // |
|
129 // Log failure to log file, even if iKeepGoing is EFalse. |
|
130 // The code used to only log the failure to the file if iKeepGoing was ETrue. |
|
131 // If a filaure occurs it needs to be written to log regardless of iKeepGoing. |
|
132 TBuf8<256> stringBuf; |
|
133 stringBuf.AppendFormat(_L8("FAILED test %d : Val = %d Exp Val = %d file %s, line %d : "),iTestCase+1,aVal,aExpectedVal, aFile, aLine); |
|
134 stringBuf.Append(aText); |
|
135 stringBuf.AppendFormat(_L8("\r\n")); |
|
136 (void)User::LeaveIfError(iTestReport.Write(stringBuf)); |
|
137 iTestSuiteFailed = ETrue; |
|
138 |
|
139 User::Leave(aVal); |
|
140 } |
|
141 |
|
142 |
|
143 EXPORT_C void CAutoTest::TestCheckPointCodeL(TInt aCase, char* aFile, TInt aLine) |
|
144 /** |
|
145 * hidden by the macro GLOBAL_CHECKPOINT_CODE. Used to validate return values etc. |
|
146 * If the 'keepgoing' command line option is specified, the test program * will not stop, but just print a warning in the test report, including |
|
147 * which file and line where the test failed. Then it will leave the test |
|
148 * case and do the next one. |
|
149 * |
|
150 * @param aCase 0 no error or the error code |
|
151 * @param aFile name of the file involved here |
|
152 * @param aLine the line of the file involved here |
|
153 */ |
|
154 { |
|
155 if(!aCase) |
|
156 return; |
|
157 |
|
158 // Convert to unicode for log to console |
|
159 TBuf<200> temp; |
|
160 temp.Copy(TPtrC8((TText8*)aFile)); |
|
161 |
|
162 iRTest.Printf(_L("FAILED test %d : Code = %d file %S, line %d\n"), iTestCase+1, aCase, &temp, aLine); |
|
163 |
|
164 // |
|
165 // Log failure to log file, even if iKeepGoing is EFalse. |
|
166 // The code used to only log the failure to the file if iKeepGoing was ETrue. |
|
167 // If a filaure occurs it needs to be written to log regardless of iKeepGoing. |
|
168 TBuf8<256> stringBuf; |
|
169 stringBuf.AppendFormat(_L8("FAILED test %d : Code = %d file %s, line %d\r\n"),iTestCase+1, aCase, aFile, aLine); |
|
170 (void)User::LeaveIfError(iTestReport.Write(stringBuf)); |
|
171 iTestSuiteFailed = ETrue; |
|
172 |
|
173 User::Leave(aCase); |
|
174 } |
|
175 |
|
176 EXPORT_C void CAutoTest::TestCheckPointL(TBool aCase, char* aFile, TInt aLine) |
|
177 /** |
|
178 * hidden by the macro GLOBAL_CHECKPOINT. Used to validate return values etc. |
|
179 * If the 'keepgoing' option is specified, the test program |
|
180 * will not stop, but just print a warning in the test report, including |
|
181 * which file and line where the test failed. Then it will leave the test |
|
182 * case and do the next one. |
|
183 * |
|
184 * @param aCase if true success, false means failed |
|
185 * @param aFile name of the file involved here |
|
186 * @param aLine the line of the file involved here |
|
187 */ |
|
188 { |
|
189 if(aCase) |
|
190 return; |
|
191 |
|
192 // Convert to unicode for log to console |
|
193 TBuf<200> temp; |
|
194 temp.Copy(TPtrC8((TText8*)aFile)); |
|
195 |
|
196 iRTest.Printf(_L("FAILED test %d : file %S, line %d\n"),iTestCase+1, &temp, aLine); |
|
197 |
|
198 // Log failure to log file, even if iKeepGoing is EFalse. |
|
199 // The code used to only log the failure to the file if iKeepGoing was ETrue. |
|
200 // If a filaure occurs it needs to be written to log regardless of iKeepGoing. |
|
201 TBuf8<256> stringBuf; |
|
202 stringBuf.AppendFormat(_L8("FAILED test %d : file %s, line %d\r\n"),iTestCase+1, aFile, aLine); |
|
203 (void)User::LeaveIfError(iTestReport.Write(stringBuf)); |
|
204 iTestSuiteFailed = ETrue; |
|
205 User::Leave(84); |
|
206 } |
|
207 |
|
208 EXPORT_C void CAutoTest::SetCompInfo(const TDesC8& aCompInfo) |
|
209 /** |
|
210 * store information about the Component under test in the autotest object |
|
211 * |
|
212 * @param aCompInfo descriptor containin the component info |
|
213 */ |
|
214 { |
|
215 iCompInfo = aCompInfo; |
|
216 } |
|
217 |
|
218 // |
|
219 // protected |
|
220 // |
|
221 |
|
222 CAutoTest::CAutoTest(const struct TAutoTestCase* aTestcases, TInt aNumberOfTestcases, const TDesC& aName, RTest& aTest) |
|
223 /** |
|
224 * C'tor |
|
225 * |
|
226 * @param aTestcases Pointer to the table with test cases |
|
227 * @param aNumberOfTestcases Number of automated test cases |
|
228 * @param aName Name of the test report file |
|
229 * @param aTest The RTest object owned by the client |
|
230 */ |
|
231 :iTestCases(aTestcases) |
|
232 ,iNumberOfTestcases(aNumberOfTestcases) |
|
233 ,iTestReportName(aName) |
|
234 ,iKeepGoing(EFalse) |
|
235 ,iTestSuiteFailed(ETrue) |
|
236 ,iRTest(aTest) |
|
237 ,iSkipList(NULL) |
|
238 ,iCommandLine(NULL) |
|
239 { |
|
240 } |
|
241 |
|
242 |
|
243 void CAutoTest::ConstructL() |
|
244 /** |
|
245 * 2nd phase of 2 phased constructor. |
|
246 * |
|
247 * create a new table for test results storing, depending on the |
|
248 * number of test cases. Connect to the file server and open |
|
249 * and replace the test report file. |
|
250 */ |
|
251 { |
|
252 // No serial port logging |
|
253 iRTest.SetLogged(EFalse); |
|
254 // Array of test result codes |
|
255 iTestResults = new (ELeave) TInt[iNumberOfTestcases]; |
|
256 // Array of bools to determine whether a test should be skipped |
|
257 // Set to ETrue if a test is not supported |
|
258 iSkipList = new (ELeave) TBool[iNumberOfTestcases]; |
|
259 Mem::FillZ(iSkipList,iNumberOfTestcases * sizeof(TBool)); |
|
260 (void)User::LeaveIfError(iFileServer.Connect()); |
|
261 |
|
262 // Read the command line or contents of config file specified on the command line, |
|
263 // into private storage |
|
264 GetCommandLineL(); |
|
265 // Get the name of the output log file |
|
266 SetLogFileL(); |
|
267 // Set up the test skip options |
|
268 GetSkipOptions(); |
|
269 // Set the keepgoing flag |
|
270 GetKeepGoingOption(); |
|
271 } |
|
272 |
|
273 |
|
274 // |
|
275 // private |
|
276 // |
|
277 |
|
278 void CAutoTest::PrintMenu() const |
|
279 /** |
|
280 * print a menu to the console |
|
281 */ |
|
282 { |
|
283 |
|
284 iRTest.Printf(_L("menu:\n") ); |
|
285 iRTest.Printf(_L(" ! - Run all tests\n") ); |
|
286 iRTest.Printf(_L(" ^C - Quit\n") ); |
|
287 |
|
288 for(TInt i=0;i<iNumberOfTestcases;i++) |
|
289 { |
|
290 iRTest.Printf(_L("%d %s \n"), i+1, iTestCases[i].iText ); |
|
291 } |
|
292 |
|
293 } |
|
294 |
|
295 EXPORT_C void CAutoTest::Printf(TRefByValue<const TDesC> aFmt,...) |
|
296 /** |
|
297 * print to console and logfile |
|
298 */ |
|
299 { |
|
300 VA_LIST list; |
|
301 VA_START(list, aFmt); |
|
302 TBuf<0x100> aBuf; |
|
303 aBuf.AppendFormatList(aFmt, list); |
|
304 |
|
305 // console |
|
306 iRTest.Printf(aBuf); |
|
307 |
|
308 // logfile |
|
309 LogExtra((TText8*)__FILE__, __LINE__, aFmt); |
|
310 } |
|
311 |
|
312 |
|
313 void CAutoTest::StartMenuL() |
|
314 /** |
|
315 * run the menu forever, until press Ctrl-C |
|
316 * |
|
317 * @leave this function may leave |
|
318 */ |
|
319 { |
|
320 TInt ret; |
|
321 |
|
322 |
|
323 FOREVER |
|
324 { |
|
325 TBuf<256> inputBuf; |
|
326 |
|
327 PrintMenu(); |
|
328 |
|
329 TInt key = iRTest.Getch(); |
|
330 iRTest.Printf(_L("%c"), key); |
|
331 |
|
332 switch(key) |
|
333 { |
|
334 case '!': |
|
335 // for the time, that there is a request in the menu to run all the |
|
336 // test cases, the iKeepGoing flag shoulg should be set and deleted |
|
337 // afterwards; because test cases behave different in automated and |
|
338 // manual mode; and here we are definitely in the automated mode |
|
339 iKeepGoing = ETrue; |
|
340 RunAllTestsL(); |
|
341 iKeepGoing = EFalse; |
|
342 break; |
|
343 |
|
344 case 0x03: // Ctrl-C |
|
345 return; |
|
346 |
|
347 default: |
|
348 |
|
349 inputBuf.Append(key); |
|
350 GetString(*iRTest.Console(), inputBuf); |
|
351 TLex lexer(inputBuf); |
|
352 TInt value; |
|
353 ret = lexer.Val(value); |
|
354 value-=1; |
|
355 if(ret == KErrNone) |
|
356 { |
|
357 iRTest.Printf(_L("Testcase: %d\n"), value+1); |
|
358 if((value >= 0) && (value < (TInt)iNumberOfTestcases)) |
|
359 { |
|
360 iTestCase = value; |
|
361 ret = RunATestL(); |
|
362 } |
|
363 else |
|
364 break; |
|
365 |
|
366 // |
|
367 // Display the success or failure to the console |
|
368 if(ret == KErrNone) |
|
369 iRTest.Printf(_L("SUCCESS! \n")); |
|
370 else if(ret == KErrNotSupported) |
|
371 iRTest.Printf(_L("NOT SUPPORTED\n"), ret); |
|
372 else |
|
373 iRTest.Printf(_L("FAILED! (ret=%d)\n"), ret); |
|
374 |
|
375 // |
|
376 // Log our success/failure in the log file |
|
377 TBuf8<256> stringBuf8; |
|
378 stringBuf8.AppendFormat(_L8("test %d: "), value +1 ); |
|
379 |
|
380 if(ret == KErrNone) |
|
381 stringBuf8.Append(KTestKeywordSuccess); |
|
382 else if(ret == KErrNotSupported) |
|
383 stringBuf8.Append(KTestKeywordNotSupported); |
|
384 else |
|
385 stringBuf8.Append(KTestKeywordFailed); |
|
386 |
|
387 stringBuf8.AppendFormat(_L8(" (return=%d) "), ret ); |
|
388 TBuf<256> buf; |
|
389 buf.AppendFormat(_L("[%s]\r\n"), iTestCases[value].iText); |
|
390 stringBuf8.Append(buf); |
|
391 (void)User::LeaveIfError(iTestReport.Write(stringBuf8)); |
|
392 } |
|
393 |
|
394 break; |
|
395 |
|
396 } // end, switch(key) |
|
397 |
|
398 } // end, FOREVER |
|
399 |
|
400 } |
|
401 |
|
402 void CAutoTest::RunAllTestsL() |
|
403 /** |
|
404 * run all the tests for this test program |
|
405 */ |
|
406 { |
|
407 TInt ret; |
|
408 iRTest.Printf(_L("Now running all the testcases...\n") ); |
|
409 |
|
410 for(TInt i=0;i<iNumberOfTestcases;i++) |
|
411 { |
|
412 iTestCase = i; |
|
413 ret = RunATestL(); |
|
414 iTestResults[i] = ret; |
|
415 PrintTestReportL(i); |
|
416 } |
|
417 } |
|
418 |
|
419 void CAutoTest::PrintThreadsToLogFile() |
|
420 // Print all the current running thread names to the log file |
|
421 { |
|
422 TBuf<0x1> asterisk=_L("*"); |
|
423 TName search=asterisk; |
|
424 |
|
425 TFindThread findHb; |
|
426 findHb.Find(search); |
|
427 TFullName name; |
|
428 |
|
429 while (findHb.Next(name)==KErrNone) |
|
430 { |
|
431 TBuf8<300> stringBuf8(_L8("\tThread Name = ")); |
|
432 stringBuf8.Append(name); |
|
433 stringBuf8.Append(_L8("\r\n")); |
|
434 iTestReport.Write(stringBuf8); |
|
435 } |
|
436 } |
|
437 |
|
438 |
|
439 TInt CAutoTest::RunATestL()// const |
|
440 /** |
|
441 * run a test and return the error code. |
|
442 * the testcase is gived in iTestCase |
|
443 * |
|
444 * @return error code for that test case |
|
445 */ |
|
446 { |
|
447 TInt ret; |
|
448 |
|
449 if(iSkipList[iTestCase]) |
|
450 return KErrNotSupported; |
|
451 |
|
452 // check the index first |
|
453 if(iTestCase < 0 || iTestCase >= (TInt)iNumberOfTestcases) |
|
454 User::Leave(KErrNotFound); |
|
455 |
|
456 iRTest.Printf(_L("%d %s \n"), iTestCase+1, iTestCases[iTestCase].iText ); |
|
457 |
|
458 // get number of outstanding requetsts on thread before we run the test |
|
459 TInt reqsAtStart = RThread().RequestCount(); |
|
460 if(reqsAtStart!=0) |
|
461 { |
|
462 TBuf8<256> stringBuf8; |
|
463 stringBuf8.AppendFormat(_L8("Warning: thread had %d oustanding requests before starting test %d!\r\n"),reqsAtStart,iTestCase+1); |
|
464 iTestReport.Write(stringBuf8); |
|
465 } |
|
466 |
|
467 // get number of Handles *before* we start the program |
|
468 TInt processHandleCountBefore; |
|
469 TInt threadHandleCountBefore; |
|
470 RThread().HandleCount(processHandleCountBefore, threadHandleCountBefore); |
|
471 |
|
472 // ------------------------------------------ |
|
473 void (*fn)(void) = iTestCases[iTestCase].iFunc; |
|
474 TRAP(ret, fn() ); |
|
475 // ------------------------------------------ |
|
476 |
|
477 // |
|
478 // if the test case failed then we dont bother |
|
479 // with checking the outstanding requests etc. |
|
480 // |
|
481 if(ret == KErrNone) |
|
482 { |
|
483 // get number of Handles *after* the program is finished |
|
484 TInt processHandleCountAfter; |
|
485 TInt threadHandleCountAfter; |
|
486 RThread().HandleCount(processHandleCountAfter, threadHandleCountAfter); |
|
487 |
|
488 // check that we are closing all the handles |
|
489 if(threadHandleCountBefore<threadHandleCountAfter) |
|
490 { |
|
491 |
|
492 |
|
493 TBuf8<256> stringBuf8; |
|
494 stringBuf8.AppendFormat(_L8("%d handles left open after test %d returned!\r\n"),threadHandleCountAfter-threadHandleCountBefore,iTestCase+1); |
|
495 iTestReport.Write(stringBuf8); |
|
496 |
|
497 PrintThreadsToLogFile(); |
|
498 |
|
499 return KErrGeneral; |
|
500 } |
|
501 |
|
502 // check that number of oustanding requests on thread has not increased |
|
503 const TInt reqsNow=RThread().RequestCount(); |
|
504 if(reqsNow>reqsAtStart) |
|
505 { |
|
506 TBuf8<256> stringBuf8; |
|
507 stringBuf8.AppendFormat(_L8("%d requests were left outstanding after test %d returned!\r\n"),reqsNow,iTestCase+1); |
|
508 iTestReport.Write(stringBuf8); |
|
509 return KErrGeneral; |
|
510 } |
|
511 } |
|
512 return ret; |
|
513 } |
|
514 |
|
515 void CAutoTest::SetLogFileL() |
|
516 /** |
|
517 * Parse the command line buffer to see if a logfile has been specified |
|
518 * If a logfile is specified create it |
|
519 */ |
|
520 { |
|
521 TPtr ptr = iCommandLine->Des(); |
|
522 TLex lex(ptr); |
|
523 |
|
524 // Parse the command line for the "-log" |
|
525 while(!lex.Eos()) |
|
526 { |
|
527 TPtrC ptr = lex.NextToken(); |
|
528 _LIT(KLogCommand,"-log"); |
|
529 if(ptr == KLogCommand) |
|
530 break; |
|
531 } |
|
532 // Read the log filename |
|
533 if(!lex.Eos()) |
|
534 { |
|
535 TPtrC file = lex.NextToken(); |
|
536 iTestReportName.Copy(file); |
|
537 } |
|
538 // Replace if it exists and if not, create the folder then create the file |
|
539 if(iTestReport.Replace(iFileServer, iTestReportName, EFileWrite) != KErrNone) |
|
540 { |
|
541 if(iTestReport.Create(iFileServer, iTestReportName, EFileWrite) == KErrPathNotFound) |
|
542 (void)User::LeaveIfError(iFileServer.MkDirAll(iTestReportName)); |
|
543 (void)User::LeaveIfError(iTestReport.Create(iFileServer, iTestReportName, EFileWrite)); |
|
544 } |
|
545 } |
|
546 |
|
547 void CAutoTest::GetCommandLineL() |
|
548 /** |
|
549 * Parse the command line to see if a config file has been specified: "-config afile.txt" |
|
550 * If it has, then read the contents of the file into the private command line buffer. Otherwise |
|
551 * copy the real command line into the private command line buffer |
|
552 */ |
|
553 { |
|
554 TBuf<KMaxCmdLength> cmdLine; |
|
555 TBuf<KMaxFileName> fileName; |
|
556 |
|
557 #ifndef EKA2 |
|
558 RProcess().CommandLine(cmdLine); |
|
559 #else |
|
560 User::CommandLine(cmdLine); |
|
561 #endif |
|
562 |
|
563 TLex lex(cmdLine); |
|
564 // Parse the real command line for the -config option |
|
565 while(!lex.Eos()) |
|
566 { |
|
567 TPtrC ptr = lex.NextToken(); |
|
568 _LIT(KConfigCommand,"-config"); |
|
569 if(ptr == KConfigCommand) |
|
570 break; |
|
571 } |
|
572 // Read the config filename if it's there |
|
573 if(!lex.Eos()) |
|
574 { |
|
575 TPtrC file = lex.NextToken(); |
|
576 fileName.Copy(file); |
|
577 } |
|
578 // If the filename has not been specified, set up the default |
|
579 // This may not exist either, by the way. |
|
580 if(!fileName.Length()) |
|
581 { |
|
582 _LIT(KDefaultConfigFile,"c:\\autotestconfig.txt"); |
|
583 fileName = KDefaultConfigFile; |
|
584 } |
|
585 RFile file; |
|
586 CleanupClosePushL(file); |
|
587 // Try to open the config file |
|
588 if(file.Open(iFileServer,fileName, EFileRead) == KErrNone) |
|
589 // Config file exists |
|
590 // read it into a local 8 bit buffer |
|
591 { |
|
592 TInt size; |
|
593 // Get the size of the file |
|
594 (void)User::LeaveIfError(file.Size(size)); |
|
595 HBufC8* buf8 = HBufC8::NewL(size); |
|
596 CleanupStack::PushL(buf8); |
|
597 TPtr8 ptr8 = buf8->Des(); |
|
598 // Read the file contents into the heap buffer |
|
599 (void)User::LeaveIfError(file.Read(ptr8,size)); |
|
600 // Copy to private class unicode buffer |
|
601 iCommandLine = HBufC::NewL(size); |
|
602 TPtr ptr16 = iCommandLine->Des(); |
|
603 ptr16.Copy(ptr8); |
|
604 CleanupStack::PopAndDestroy(buf8); |
|
605 } |
|
606 else |
|
607 // Config file does not exist so copy the real command line buffer to the private class copy |
|
608 { |
|
609 iCommandLine = HBufC::NewL(cmdLine.Length()); |
|
610 TPtr ptr16 = iCommandLine->Des(); |
|
611 ptr16.Copy(cmdLine); |
|
612 } |
|
613 CleanupStack::PopAndDestroy(&file); |
|
614 } |
|
615 |
|
616 void CAutoTest::GetKeepGoingOption() |
|
617 /** |
|
618 * Read the keepgoing flag from the command line bufffer |
|
619 */ |
|
620 { |
|
621 _LIT(KKeepGoingString, "keepgoing"); |
|
622 TInt ret = iCommandLine->Find(KKeepGoingString); |
|
623 if(ret >= KErrNone) |
|
624 iKeepGoing = ETrue; |
|
625 } |
|
626 |
|
627 void CAutoTest::GetSkipOptions() |
|
628 /** |
|
629 * Read the test skip options, if any, from the command line buffer |
|
630 * Usage: "-skip 1 4 5" to skip tests 1, 4 & 5 and log as NOT SUPPORTED |
|
631 */ |
|
632 { |
|
633 TPtr ptr = iCommandLine->Des(); |
|
634 TLex lex(ptr); |
|
635 // Parse for -skip |
|
636 while(!lex.Eos()) |
|
637 { |
|
638 TPtrC token = lex.NextToken(); |
|
639 _LIT(KSkipCommand,"-skip"); |
|
640 if(token == KSkipCommand) |
|
641 break; |
|
642 } |
|
643 // Loop through reading the test numbers to skip |
|
644 while(!lex.Eos()) |
|
645 { |
|
646 TInt testNum; |
|
647 TPtrC ptr = lex.NextToken(); |
|
648 TLex lex(ptr); |
|
649 // Read the test number as an integer |
|
650 if(lex.Val(testNum) != KErrNone) |
|
651 // Exit at the first token that's not a valid number |
|
652 break; |
|
653 if(testNum <= 0 || testNum > iNumberOfTestcases) |
|
654 // Out of range |
|
655 continue; |
|
656 // Skip this test |
|
657 iSkipList[testNum-1] = ETrue; |
|
658 } |
|
659 } |
|
660 |
|
661 |
|
662 void CAutoTest::PrintTestReportL(TInt aTestIndex) |
|
663 /** |
|
664 * print a test report to file and console |
|
665 */ |
|
666 { |
|
667 // print status |
|
668 TBuf8<256> stringBuf8; |
|
669 stringBuf8.AppendFormat(_L8("test %d: "), aTestIndex+1 ); |
|
670 if(iTestResults[aTestIndex] == KErrNone) |
|
671 stringBuf8.Append(KTestKeywordSuccess); |
|
672 else if(iTestResults[aTestIndex] == KErrNotSupported) |
|
673 stringBuf8.Append(KTestKeywordNotSupported); |
|
674 else |
|
675 stringBuf8.Append(KTestKeywordFailed); |
|
676 stringBuf8.AppendFormat(_L8(" (return=%d) "), iTestResults[aTestIndex] ); |
|
677 TBuf<256> buf; |
|
678 buf.AppendFormat(_L("[%s]\r\n"), iTestCases[aTestIndex].iText); |
|
679 stringBuf8.Append(buf); |
|
680 (void)User::LeaveIfError(iTestReport.Write(stringBuf8)); |
|
681 TBuf<256> stringBuf; |
|
682 stringBuf.Copy(stringBuf8); |
|
683 iRTest.Printf(stringBuf); |
|
684 } |
|
685 |
|
686 |
|
687 EXPORT_C void CAutoTest::GetString(CConsoleBase& aConsole, TDes& aString) const |
|
688 /** |
|
689 * This function re-invents the wheel (once again...) |
|
690 * It reads a string from the keyboard. Uses Getch() to get keys and does not |
|
691 * return until ENTER is pressed. |
|
692 * |
|
693 * @param aConsole const reference to the console |
|
694 * @param aString reference to the string to be read into |
|
695 */ |
|
696 { |
|
697 TKeyCode code; |
|
698 TBuf<1> kjar; |
|
699 |
|
700 FOREVER |
|
701 { |
|
702 code = aConsole.Getch(); |
|
703 kjar.SetLength(0); |
|
704 kjar.Append(code); |
|
705 |
|
706 aConsole.Printf(_L("%S"),&kjar); |
|
707 |
|
708 // If <CR> finish editing string |
|
709 if (code == '\r') |
|
710 break; |
|
711 |
|
712 // if <BS> remove last character |
|
713 if ((code == 0x08) && (aString.Length() != 0)) |
|
714 aString.SetLength((aString.Length()-1)); |
|
715 else |
|
716 aString.Append(code); |
|
717 } |
|
718 aConsole.Printf(_L("\n")); |
|
719 } |
|
720 |
|
721 |
|
722 void CAutoTest::LogTimeL() |
|
723 /* |
|
724 * write date&time info to log file |
|
725 */ |
|
726 { |
|
727 TBuf8<64> buf8; |
|
728 TTime now; |
|
729 now.HomeTime(); |
|
730 TDateTime dateTime; |
|
731 dateTime = now.DateTime(); |
|
732 buf8.Format(_L8("%02d/%02d/%04d %02d:%02d.%02d \r\n"), dateTime.Day()+1, dateTime.Month()+1, dateTime.Year(), |
|
733 dateTime.Hour(), dateTime.Minute(), dateTime.Second() ); |
|
734 (void)User::LeaveIfError(iTestReport.Write(buf8)); |
|
735 } |
|
736 |
|
737 EXPORT_C TBool CAutoTest::KeepGoing(void) |
|
738 // For external visibility |
|
739 // Handy if someone wants to use defaults instead of taking keyboard input |
|
740 { |
|
741 return iKeepGoing; |
|
742 } |
|
743 |
|
744 |
|
745 EXPORT_C void CAutoTest::LogExtra(const TText8* aFile, TInt aLine, TRefByValue<const TDesC> aFmt,...) |
|
746 /** |
|
747 * Write a free formatted string to a second log file and to the console. |
|
748 * The second log files name is the same as the main log file plus '.EXTRA'. |
|
749 */ |
|
750 { |
|
751 VA_LIST list; |
|
752 VA_START(list,aFmt); |
|
753 // |
|
754 // Assemble file name for second log file |
|
755 _LIT(KExtra,".EXTRA"); |
|
756 TBuf<KMaxCmdLength+6> logFileName; // +6 to hold the text ".EXTRA" |
|
757 logFileName.Copy(iTestReportName); |
|
758 logFileName.Append(KExtra); |
|
759 |
|
760 // |
|
761 // Assemble string to be written to second log |
|
762 TBuf<256> buf; |
|
763 { // Braces used to scope lifetime of TBuf objects |
|
764 TPtrC8 fileName8(aFile); |
|
765 TBuf<128> fileName; |
|
766 fileName.Copy(fileName8); |
|
767 buf.Format(_L("\t%S\t%d\t"), &fileName, aLine); |
|
768 |
|
769 buf.AppendFormatList(aFmt,list); |
|
770 } |
|
771 |
|
772 // |
|
773 // (1) Open/create log file. |
|
774 // (2) Write text to log file (RFileLogger adds a time stamp for us) |
|
775 // (3) Close log |
|
776 _LIT(KLogFolder,"autotest"); |
|
777 RFileLogger log; |
|
778 if(log.Connect()==KErrNone) |
|
779 { |
|
780 log.CreateLog(KLogFolder,logFileName,EFileLoggingModeAppend); |
|
781 log.Write(buf); |
|
782 log.CloseLog(); |
|
783 log.Close(); |
|
784 } |
|
785 |
|
786 // |
|
787 // Also write the text to the console (with a new line after) |
|
788 buf.Zero(); |
|
789 buf.AppendFormatList(aFmt,list); |
|
790 iRTest.Printf(_L("%S\n"),&buf); |
|
791 } |
|
792 |
|
793 |
|
794 void CAutoTest::MachineInfoL() |
|
795 /* |
|
796 * write machine info to log file |
|
797 */ |
|
798 { |
|
799 TBuf8<256> buf8; |
|
800 buf8.AppendFormat(_L8("Machine info: \r\n")); |
|
801 // |
|
802 // platform |
|
803 // |
|
804 #if defined(__WINS__) |
|
805 _LIT8(KPlatform, "WINS"); |
|
806 #elif defined(__MARM_ARMI__) |
|
807 _LIT8(KPlatform, "ARMI"); |
|
808 #elif defined(__MARM_ARM4__) |
|
809 _LIT8(KPlatform, "ARM4"); |
|
810 #elif defined(__MARM_THUMB__) |
|
811 _LIT8(KPlatform, "THUMB"); |
|
812 #else |
|
813 _LIT8(KPlatform, "unknown"); |
|
814 #endif |
|
815 |
|
816 #if defined (_DEBUG) |
|
817 _LIT8(KDebugRelease, "Debug"); |
|
818 #else |
|
819 _LIT8(KDebugRelease, "Release"); |
|
820 #endif |
|
821 |
|
822 buf8.AppendFormat(_L8(" Platform: %S %S\r\n"), &KPlatform, &KDebugRelease ); |
|
823 |
|
824 // |
|
825 // machine info from Hal9000 |
|
826 // |
|
827 TMachineInfoV1Buf machine; |
|
828 UserHal::MachineInfo(machine); |
|
829 |
|
830 TVersion romver = machine().iRomVersion; |
|
831 TInt64 uid = machine().iMachineUniqueId; |
|
832 TInt khz = machine().iProcessorClockInKHz; |
|
833 |
|
834 buf8.AppendFormat(_L8(" Rom version: %d.%d.%d\r\n"), romver.iMajor, romver.iMinor, romver.iBuild ); |
|
835 buf8.AppendFormat(_L8(" Unique ID: 0x%016x\r\n"), uid ); |
|
836 buf8.AppendFormat(_L8(" CPU Speed: %d kHz\r\n"), khz ); |
|
837 |
|
838 User::LeaveIfError(iTestReport.Write(buf8)); |
|
839 } |
|
840 |
|
841 #ifndef EKA2 |
|
842 GLDEF_C TInt E32Dll(TDllReason /*aReason*/) |
|
843 // |
|
844 // DLL entry point |
|
845 // |
|
846 { |
|
847 return(KErrNone); |
|
848 } |
|
849 #endif |
|
850 // EOF - AUTOTEST.CPP |