|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * Design Overview: |
|
16 * The diagram below shows the Script Engine classes and their parent child |
|
17 * hierarchy. All classes have a CActive base, and apart from CTaskTimer, all classes |
|
18 * have their own state machine. Apart from CScriptMaster, all classes have a reference |
|
19 * to a Mixin/Interface completion call of its parent, which it calls when the object |
|
20 * needs to notify the parent of an event. |
|
21 * CScriptMaster (derived CActive) |
|
22 * CScriptControl (derived CActiveBase - Can go recursive) |
|
23 * CProgramControl (derived CTaskControlBase) CClientControl ( derived CTaskControlBase maps to n x test steps) |
|
24 * CTaskTimer CTaskTimer (derived CTimer) |
|
25 * state transition tables for CScriptMaster, CScriptControl & CClientControl |
|
26 * CActiveBase: |
|
27 * Derives CActive. |
|
28 * Contains code for priming, triggering and completing AO's |
|
29 * Implements the pure abstract MChildCompletion::ChildCompletion() method |
|
30 * CTaskControlBase: |
|
31 * Derives CActiveBase. |
|
32 * Abstract class. Base for CClientControl and CProgramControl. |
|
33 * CScriptMaster: |
|
34 * Derives CActiveBase. |
|
35 * Master control active object with simple state machine. |
|
36 * Instantiates the top level CScriptControl object and triggers its state machine. |
|
37 * CScriptContol: |
|
38 * Derives CActiveBase. |
|
39 * Main script interpreter state machine. Creates one or more CClientControl and/or |
|
40 * CProgramControl objects. |
|
41 * In CONCURRENT mode, it can create as many instances as there are RUN_TEST_STEP and/or |
|
42 * RUN_PROGRAM calls. |
|
43 * Creates root sessions with the xxxtest servers using the RTestServ::Connect() client call. |
|
44 * In the case of non-nested scripts, the parent object is CScriptMaster. |
|
45 * When scripts are nested and it goes recursive, the parent object could be another |
|
46 * CScriptControl. |
|
47 * Implements the MTaskCompletion pure abstract class for callbacks from |
|
48 * CClientControl or CProgramControl objects |
|
49 * Calls back into its parent object when the script is complete and all async commands have |
|
50 * completed. |
|
51 * CClientControl: |
|
52 * Derives CTaskControlBase. |
|
53 * Test Step Controler. Instantiated by CScriptControl when a RUN_TEST_STEP line is interpreted |
|
54 * Creates and kicks off a CTaskTimer object set to the timeout value for the test step. |
|
55 * Opens a test step using the RTestSession::Open() client call. |
|
56 * Executes a test step using the RTestSession::RunTestStep() client call. |
|
57 * This method issues the client RTestSession::AbortTestStep() call and |
|
58 * the RunL() state machine handles the completion from the test server. |
|
59 * Implements the MTaskTimerCompletion pure abstract class for callbacks from the |
|
60 * CTaskTimer class. |
|
61 * Calls back into its parent CScriptControl object when a test step completes. |
|
62 * CProgramControl |
|
63 * Derives CTaskControlBase |
|
64 * Kicks off an executable in its own process and handles process completion asynchronously |
|
65 * CTaskTimer: |
|
66 * Derives CTimer. |
|
67 * Calls back into its parent object if the timer expires. |
|
68 * EPOC include |
|
69 * |
|
70 */ |
|
71 |
|
72 |
|
73 |
|
74 /** |
|
75 @file scriptengine.cpp |
|
76 */ |
|
77 |
|
78 //#include <utf.h> |
|
79 #if !(defined TEF_LITE) |
|
80 #include <apacmdln.h> |
|
81 #include <apgtask.h> |
|
82 #endif |
|
83 |
|
84 // User include |
|
85 #include <testexecuteclient.h> |
|
86 #include "ScriptEngine.h" |
|
87 |
|
88 // Fix defect 119337, initialize the integer to zero |
|
89 GLDEF_D TInt CScriptControl::iNestedNumRunScriptInLoop=0; |
|
90 // End defect 119337 |
|
91 |
|
92 /** |
|
93 * @param aPtrC1 - Instance of TPtrC to compare |
|
94 * @param aPtrC2 - Instance of TPtrC to compare |
|
95 * Function to implement the comparison algo for RArray::Find to work with |
|
96 */ |
|
97 TBool TSelectiveTestingOptions::CompareTPtrC(const TPtrC& aPtrC1, const TPtrC& aPtrC2) |
|
98 { |
|
99 TInt ret =aPtrC1.CompareF(aPtrC2); |
|
100 return (ret==0) ? ETrue : EFalse; |
|
101 } |
|
102 |
|
103 /** |
|
104 * @param aRng1 - Instance of TRange to compare |
|
105 * @param aRng2 - Instance of TRange to compare |
|
106 * Function to implement the comparison algo for RArray::Find to work with. |
|
107 * TRange::iStartTestCase determines the match |
|
108 */ |
|
109 TBool TRange::CompareTRangeStartCase(const TRange& aRng1, const TRange& aRng2) |
|
110 { |
|
111 TInt ret =aRng2.iStartTestCase.CompareF(aRng1.iStartTestCase); |
|
112 return (ret==0) ? ETrue : EFalse; |
|
113 } |
|
114 |
|
115 /** |
|
116 * @param aRng1 - Instance of TRange to compare |
|
117 * @param aRng2 - Instance of TRange to compare |
|
118 * Function to implement the comparison algo for RArray::Find to work with. |
|
119 * TRange::iEndTestCase determines the match |
|
120 */ |
|
121 TBool TRange::CompareTRangeEnd(const TRange& aRng1, const TRange& aRng2) |
|
122 { |
|
123 TInt ret =aRng2.iEndTestCase.CompareF(aRng1.iEndTestCase); |
|
124 return (ret==0) ? ETrue : EFalse; |
|
125 } |
|
126 |
|
127 /** |
|
128 * @param aRng1 - Instance of TRange to compare |
|
129 * @param aRng2 - Instance of TRange to compare |
|
130 * Function to implement the comparison algo for RArray::Sort to work with. |
|
131 * TRange::iStartTestCase is used as the sort key |
|
132 */ |
|
133 TInt TRange::CompareTRangeStartOrder(const TRange& aRng1, const TRange& aRng2) |
|
134 { |
|
135 return aRng1.iStartTestCase.CompareF( aRng2.iStartTestCase); |
|
136 } |
|
137 |
|
138 /** |
|
139 * @param aPtrC1 - Instance of TPtrC to compare |
|
140 * @param aPtrC2 - Instance of TPtrC to compare |
|
141 * Function to implement the comparison algo for RArray::Sort to work with. |
|
142 */ |
|
143 TInt TSelectiveTestingOptions::CompareTPtrCOrder(const TPtrC& aPtrC1, const TPtrC& aPtrC2) |
|
144 { |
|
145 return aPtrC1.CompareF(aPtrC2); |
|
146 } |
|
147 |
|
148 /** |
|
149 * @param aServ - Instance of the test server handle |
|
150 * @param aStepName - Test step name |
|
151 * Wrapper around the RTestServ class. Performs counting on test step sessions |
|
152 */ |
|
153 TInt RScriptTestSession::Open(RScriptTestServ& aServ, const TBool aIsTestStep, const TDesC& aStepName ) |
|
154 { |
|
155 if(aServ.SharedData() && aServ.SessionCount()) |
|
156 return KErrInUse; |
|
157 TInt ret = KErrNone; |
|
158 |
|
159 if( aIsTestStep ) |
|
160 { |
|
161 ret = RTestSession::Open(aServ, aStepName, aServ.SharedData()); |
|
162 } |
|
163 else |
|
164 { |
|
165 ret = RTestSession::Open(aServ, aServ.SharedData()); |
|
166 } |
|
167 if(ret) |
|
168 return ret; |
|
169 aServ.AddSession(); |
|
170 iServ = &aServ; |
|
171 return KErrNone; |
|
172 } |
|
173 |
|
174 /** |
|
175 * @param aScriptFilePath - The full path and filename of a script command file. |
|
176 * @param aLogger - Reference to a logger interface object that contains HTML & XML log client sessions. |
|
177 * @param aConsole - Reference to console object for printing script line during test execution |
|
178 * @param aSysDrive - Default System drive letter |
|
179 * @param aTestSysDrive - Default System drive letter overwritten through testexecute.ini |
|
180 * Constructor |
|
181 */ |
|
182 CScriptMaster::CScriptMaster(const TDesC& aScriptFilePath, CTestExecuteLogger& aLogger, RConsoleLogger& aConsole, const TDriveName& aSysDrive, const TDriveName& aTestSysDrive, TSelectiveTestingOptions* aSelTestingOptions ) : |
|
183 iState(EInit), iScriptFilePath(aScriptFilePath), iLogger(aLogger), iConsoleLogger(aConsole), iDefaultSysDrive(aSysDrive), iTestSysDrive(aTestSysDrive), iSelTestingOptions(aSelTestingOptions) |
|
184 { |
|
185 } |
|
186 |
|
187 /** |
|
188 * Destructor |
|
189 */ |
|
190 CScriptMaster::~CScriptMaster() |
|
191 { |
|
192 } |
|
193 |
|
194 /** |
|
195 * Pure virtual implementation. |
|
196 * The Top level state machine Kick'd() into by MainL() |
|
197 * Picks up the completion from a CScriptControl instance then exits the scheduler |
|
198 */ |
|
199 void CScriptMaster::RunL() |
|
200 { |
|
201 switch (iState) |
|
202 { |
|
203 case EInit : |
|
204 { |
|
205 // Create the master CScriptControl instance. |
|
206 CScriptControl* scriptControl = new (ELeave) CScriptControl(*this,iScriptFilePath,Logger(),ConsoleLogger(),iStartLooping,iLoop,iDefaultSysDrive,iTestSysDrive,iSelTestingOptions); |
|
207 iState = ERunning; |
|
208 // Set our AO up ready for completion |
|
209 Prime(); |
|
210 // Kick the CScriptControl state machine |
|
211 scriptControl->Kick(); |
|
212 } |
|
213 break; |
|
214 case ERunning : |
|
215 { |
|
216 // All child AO's have completed and been deleted so it's safe to exit. |
|
217 CActiveScheduler::Stop(); |
|
218 } |
|
219 break; |
|
220 default: |
|
221 break; |
|
222 } |
|
223 } |
|
224 |
|
225 /** |
|
226 * @param aCompletion - Callback into the parent object. |
|
227 * @param aScriptFilePath - The full path and filename of a script file |
|
228 * @param aLogger - Reference to a logger instance |
|
229 * @param aConsole - Reference to console object for printing script line during test execution |
|
230 * @param aStartLooping - Initiate the looping |
|
231 * @param aLoop - Check for nesting of loops |
|
232 * @param aSysDrive - Default System drive letter |
|
233 * @param aTestSysDrive - System drive letter overwritten from testexecute.ini |
|
234 * Constructor |
|
235 */ |
|
236 CScriptControl::CScriptControl(MChildCompletion& aCompletion, const TDesC& aScriptFilePath, CTestExecuteLogger& aLogger, RConsoleLogger& aConsole, TBool aStartLooping, TBool aLoop, const TDriveName& aSysDrive, const TDriveName& aTestSysDrive, TSelectiveTestingOptions* aSelTestingOptions): |
|
237 iScriptFile(aScriptFilePath), |
|
238 iState(EInit), |
|
239 iParent(aCompletion), |
|
240 iConcurrent(EFalse), |
|
241 iCanComplete(ETrue), |
|
242 iBreakOnError(EFalse), |
|
243 iAsyncTasksOutstanding(0), |
|
244 iCurrentScriptLineNumber(0), |
|
245 iLogger(aLogger), |
|
246 iConsoleLogger(aConsole), |
|
247 iScriptLinePrefixSet(EFalse), |
|
248 iStartLooping(aStartLooping), |
|
249 iLoop(aLoop), |
|
250 iSharedDataNum(KTEFZeroValue), |
|
251 iIsSharedData(EFalse), |
|
252 iSyncControl(NULL), |
|
253 iTestCaseID(KTEFTestCaseDefault), |
|
254 iDefaultSysDrive(aSysDrive), |
|
255 iTestSysDrive(aTestSysDrive), |
|
256 iSelTestingOptions(aSelTestingOptions), |
|
257 iSelectOne(EFalse), |
|
258 iRangeRefCounter(0), |
|
259 iTestCaseCounter(0) |
|
260 { |
|
261 } |
|
262 |
|
263 /** |
|
264 * Destructor |
|
265 */ |
|
266 CScriptControl::~CScriptControl() |
|
267 { |
|
268 iTimer.Cancel(); |
|
269 iTimer.Close(); |
|
270 // We read the complete script into the heap for parsing so: |
|
271 delete iScriptData; |
|
272 for (TInt index = 0; index < iSharedDataNum; index++) |
|
273 { |
|
274 delete iSharedDataArray[index]; |
|
275 } |
|
276 // Instance has an array of pointers to RTestServer objects. |
|
277 // Loop through deleting and closing |
|
278 TInt i = 0; |
|
279 TInt count = iServers.Count(); |
|
280 for(i=0;i<count;i++) |
|
281 { |
|
282 iServers[0]->Close(); |
|
283 delete iServers[0]; |
|
284 iServers.Remove(0); |
|
285 } |
|
286 iServers.Close(); |
|
287 if( iSyncControl ) |
|
288 { |
|
289 delete iSyncControl; |
|
290 } |
|
291 } |
|
292 |
|
293 /** |
|
294 * @param aError - Integer error value returned by the active object while leaving |
|
295 * @return TInt - System-wide error codes |
|
296 * Error Handler for active object |
|
297 */ |
|
298 TInt CScriptControl::RunError(TInt aError) |
|
299 { |
|
300 if (aError == KErrNoMemory) |
|
301 { |
|
302 ERR_PRINTF1(_L("Insufficient memory available to perform further operation.\n\tPlease increase the maximum heap size from the testexecute.mmp and try running the test again. Exiting test script...")); |
|
303 } |
|
304 else |
|
305 { |
|
306 ERR_PRINTF2(_L("Test execution failed with error %d. Terminating tests.."), aError); |
|
307 } |
|
308 iParent.ChildCompletion(KErrNone); |
|
309 delete this; |
|
310 return KErrNone; |
|
311 } |
|
312 |
|
313 /** |
|
314 * Implementation of pure virtual |
|
315 * The main script interpreter state machine. |
|
316 * Kick'd() into by CScriptMaster or, in the case of nested scripts, another CScriptControl |
|
317 * instance. |
|
318 * Picks up the completions from CClientControls and/or, in the case of nested scripts, |
|
319 * another CScriptControl instance. |
|
320 */ |
|
321 void CScriptControl::RunL() |
|
322 { |
|
323 switch (iState) |
|
324 { |
|
325 case EInit : |
|
326 // First state after Kick() from parent |
|
327 { |
|
328 // Standard log output goes to flogger |
|
329 // Result log goes to a propietary file in c:\logs\testexecute |
|
330 User::LeaveIfError(iTimer.CreateLocal()); |
|
331 TRAPD(err,CreateScriptDataFromScriptFileL()); |
|
332 if(err) |
|
333 { |
|
334 // If we can't open the script file then log the fact and gracefully exit |
|
335 // the state machine. |
|
336 TBuf<KMaxTestExecuteCommandLength> buf(iScriptFile); |
|
337 _LIT(KScriptFileError,"Failed Script File Open %S"); |
|
338 ERR_PRINTF2(KScriptFileError,&buf); |
|
339 iState = EClosing; |
|
340 //condition used for checking failure in testexecute.cpp |
|
341 commentedCommandsCount=-1; |
|
342 iRunScriptFailCount++; |
|
343 Kick(); |
|
344 break; |
|
345 } |
|
346 |
|
347 // Script file reading state next |
|
348 iState = ERunning; |
|
349 // Kick ourselves into the next state |
|
350 Kick(); |
|
351 } |
|
352 break; |
|
353 |
|
354 case ERunning : |
|
355 // Always in this state whilst we're reading lines from script file data member |
|
356 { |
|
357 TPtrC scriptLine; |
|
358 if(!iStartLooping) |
|
359 { |
|
360 if(!GetNextScriptLine(scriptLine)) |
|
361 { |
|
362 // End of the script file |
|
363 // Check see if there are any async requests outstanding |
|
364 // In concurrent mode there are very likely to be |
|
365 if(iAsyncTasksOutstanding == 0) |
|
366 { |
|
367 // No requests outstanding so call into the parent |
|
368 iParent.ChildCompletion(KErrNone); |
|
369 delete this; |
|
370 } |
|
371 else |
|
372 { |
|
373 // Requests outstanding |
|
374 // Next time we're completed we'll be in the closing state |
|
375 iState = EClosing; |
|
376 iCanComplete =ETrue; |
|
377 // Prime ourselves for completion |
|
378 Prime(); |
|
379 } |
|
380 break; |
|
381 } |
|
382 } |
|
383 //Get the script lines which are to be looped |
|
384 else if(!GetLoopScriptLine(scriptLine)) |
|
385 { |
|
386 // End of the script file |
|
387 // Check see if there are any async requests outstanding |
|
388 // In concurrent mode there are very likely to be |
|
389 if(iAsyncTasksOutstanding == 0) |
|
390 { |
|
391 // No requests outstanding so call into the parent |
|
392 iParent.ChildCompletion(KErrNone); |
|
393 delete this; |
|
394 } |
|
395 else |
|
396 { |
|
397 // Requests outstanding |
|
398 // Next time we're completed we'll be in the closing state |
|
399 iState = EClosing; |
|
400 iCanComplete =ETrue; |
|
401 // Prime ourselves for completion |
|
402 Prime(); |
|
403 } |
|
404 break; |
|
405 } |
|
406 |
|
407 iCurrentScriptLine.Set(scriptLine); |
|
408 |
|
409 TBool commentedCommand = CheckCommentedCommands(); |
|
410 if(commentedCommand) |
|
411 { |
|
412 iCanComplete = EFalse; |
|
413 Kick(); |
|
414 break; |
|
415 } |
|
416 |
|
417 if (iScriptLinePrefixSet ) |
|
418 { |
|
419 TLex lookahead(iCurrentScriptLine); |
|
420 |
|
421 TPtrC firstCommand(lookahead.NextToken()); |
|
422 |
|
423 if (firstCommand.CompareF(KTEFRemovePrefixCommand) != 0) |
|
424 { |
|
425 // If we aren't the Remove_Prefix command, prefix the current line... |
|
426 iPrefixedCurrentScriptLine = iScriptLinePrefix; |
|
427 iPrefixedCurrentScriptLine.Append(scriptLine); |
|
428 iCurrentScriptLine.Set(iPrefixedCurrentScriptLine); |
|
429 } |
|
430 } |
|
431 |
|
432 TRAPD(err, MakeAbsoluteFilePathsL(iCurrentScriptLine)); |
|
433 PrintCurrentScriptLine(); |
|
434 |
|
435 TLex lex(iCurrentScriptLine); |
|
436 |
|
437 TPtrC token(lex.NextToken()); |
|
438 |
|
439 if (err == KTEFErrInvalidRelPath) |
|
440 { |
|
441 _LIT(KTEFErrInvalidRelPathText,"Invalid relative path provided in the script file. Skipping the script line from execution.."); |
|
442 ERR_PRINTF1(KTEFErrInvalidRelPathText); |
|
443 |
|
444 if (token.CompareF(KTEFRunTestStepCommand) == 0 || |
|
445 token.CompareF(KTEFRunPanicStepCommand) == 0 || |
|
446 token.CompareF(KTEFRunTestStepResultCommand) == 0 || |
|
447 token.CompareF(KTEFRunPanicStepResultCommand) == 0) |
|
448 { |
|
449 TExitCategoryName blankPanicString; //Not a Panic |
|
450 LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine); |
|
451 } |
|
452 iCanComplete = EFalse; |
|
453 Kick(); |
|
454 break; |
|
455 } |
|
456 |
|
457 if(err == KErrTooBig) |
|
458 { |
|
459 _LIT(KTEFErrTooBigArguments, "One or more arguments for the command exceeded allowed limit for length. Skipping test.."); |
|
460 ERR_PRINTF1(KTEFErrTooBigArguments); |
|
461 |
|
462 if (token.CompareF(KTEFRunTestStepCommand) == 0 || |
|
463 token.CompareF(KTEFRunPanicStepCommand) == 0 || |
|
464 token.CompareF(KTEFRunTestStepResultCommand) == 0 || |
|
465 token.CompareF(KTEFRunPanicStepResultCommand) == 0) |
|
466 { |
|
467 TExitCategoryName blankPanicString; //Not a Panic |
|
468 LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine); |
|
469 } |
|
470 iCanComplete = EFalse; |
|
471 Kick(); |
|
472 break; |
|
473 } |
|
474 |
|
475 // Main parser |
|
476 if(token.CompareF(KTEFLoadSuiteCommand) == 0 || token.CompareF(KTEFLoadServerCommand) == 0) |
|
477 { |
|
478 TRAPD(err,CreateServerFromScriptLineL()); |
|
479 |
|
480 // Create a TLogField structure array |
|
481 // Size of array equals to number of fields to be displayed for the command |
|
482 TExtraLogField logField[2]; |
|
483 |
|
484 // The first member of the structure stores the field name |
|
485 // The second one holds the value for the particular field |
|
486 _LIT(KSuiteName, "SUITE_NAME"); |
|
487 logField[0].iLogFieldName.Copy(KSuiteName); |
|
488 logField[0].iLogFieldValue.Copy(lex.NextToken()); |
|
489 |
|
490 logField[1].iLogFieldName.Copy(KTEFResultString); |
|
491 if(err != KErrNone) |
|
492 { |
|
493 logField[1].iLogFieldValue.Copy(KTEFResultFail); |
|
494 if( KErrNotFound == err ) |
|
495 { |
|
496 _LIT(KServerNotFound,"Failed to create server, either the server or one of its dependancies could not be found."); |
|
497 ERR_PRINTF1(KServerNotFound); |
|
498 } |
|
499 else |
|
500 { |
|
501 _LIT(KServerCreateError,"Failed to Create Server Err = %d"); |
|
502 ERR_PRINTF2(KServerCreateError,err); |
|
503 } |
|
504 } |
|
505 else |
|
506 { |
|
507 logField[1].iLogFieldValue.Copy(KTEFResultPass); |
|
508 } |
|
509 |
|
510 // Call the Logger().LogToXml routine which handles XML logging for individual commands |
|
511 // Takes in the command name, number of fields and the struture array |
|
512 Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, token, 2, logField); |
|
513 iCanComplete = EFalse; |
|
514 Kick(); |
|
515 } |
|
516 else if(token.CompareF(KTEFStartTestBlock)==0) |
|
517 { |
|
518 // Parse the START_TEST_BLOCK command line |
|
519 TInt index = 0; |
|
520 TBool taskCanComplete = ETrue; |
|
521 TBool concurrent = iConcurrent; |
|
522 // Make sure the server is loaded |
|
523 if(!GetServerIndexFromScriptLine(index)) |
|
524 { |
|
525 // Not loaded. Skip the line, but ensure its logged as a failure. |
|
526 TExitCategoryName blankPanicString; //Not a Panic |
|
527 LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine); |
|
528 |
|
529 iCanComplete = EFalse; |
|
530 Kick(); |
|
531 break; |
|
532 } |
|
533 |
|
534 TBuf<KMaxTestExecuteCommandLength> startBlockLine = iCurrentScriptLine; |
|
535 |
|
536 // Parse the test block of commands |
|
537 TTEFItemArray* itemArray = new (ELeave) TTEFItemArray(1); |
|
538 CleanupStack::PushL( itemArray ); |
|
539 TRAPD( err, ParseTestBlockL(*itemArray) ); |
|
540 |
|
541 if( KErrNone == err ) |
|
542 { |
|
543 if(!iConcurrent) |
|
544 { |
|
545 // If we're not in concurrent mode then child objects can complete us |
|
546 taskCanComplete = ETrue; |
|
547 // Prime ready for completion |
|
548 Prime(); |
|
549 } |
|
550 else |
|
551 { |
|
552 // In concurrent mode children can't complete us as we kick() ourselves. |
|
553 taskCanComplete = EFalse; |
|
554 Kick(); |
|
555 } |
|
556 // Create the test block controler object |
|
557 TInt loopIndex = -1; |
|
558 if (iLoop) |
|
559 { |
|
560 loopIndex = iLoopCounter + 1; |
|
561 } |
|
562 |
|
563 CClientControl* blockController = CClientControl::NewL( *iServers[index], |
|
564 startBlockLine, |
|
565 *this, |
|
566 iCurrentScriptLineNumber, |
|
567 Logger(), |
|
568 loopIndex, |
|
569 iTestCaseID, |
|
570 iCurrentScriptLine, |
|
571 iScriptFile, |
|
572 *itemArray, |
|
573 iDefaultSysDrive, |
|
574 iTestSysDrive); |
|
575 |
|
576 blockController->SetTaskComplete(taskCanComplete); |
|
577 iAsyncTasksOutstanding++; |
|
578 // Kick() the test step object into its state machine |
|
579 blockController->Kick(); |
|
580 } |
|
581 else |
|
582 { |
|
583 iCanComplete = EFalse; |
|
584 Kick(); |
|
585 } |
|
586 |
|
587 iConcurrent = concurrent; |
|
588 CleanupStack::PopAndDestroy( itemArray ); |
|
589 } |
|
590 else if(token.CompareF(KTEFEndTestBlock)==0) |
|
591 { |
|
592 // If this is called then there is a missing START_TEST_BLOCK command |
|
593 TExitCategoryName blankPanicString; |
|
594 LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine); |
|
595 iCanComplete = EFalse; |
|
596 Kick(); |
|
597 } |
|
598 else if(token.CompareF(KTEFStartRepeat)==0) |
|
599 { |
|
600 TPtrC iniFile(lex.NextToken()); |
|
601 TPtrC iniSection(lex.NextToken()); |
|
602 TPtrC tempRepeatParam=lex.NextToken(); |
|
603 CIniData* configData = NULL; |
|
604 TInt err = 0; |
|
605 if(iniFile.Length()) |
|
606 { |
|
607 TRAP(err,configData = CIniData::NewL(iniFile)); |
|
608 } |
|
609 if(err != KErrNone) |
|
610 { |
|
611 _LIT(KTEFIniFileNotFound,"Ini file not found.. Looping Ignored"); |
|
612 ERR_PRINTF1(KTEFIniFileNotFound); |
|
613 Kick(); |
|
614 break; |
|
615 } |
|
616 iRepeatParam=0; |
|
617 CleanupStack::PushL(configData); |
|
618 if(configData) |
|
619 { |
|
620 //For Syntax Error continue ignoring looping |
|
621 if (!configData->FindVar(iniSection, tempRepeatParam, iRepeatParam)) |
|
622 { |
|
623 _LIT(KIniFailMessage,"The input data is not found in the ini specified"); |
|
624 INFO_PRINTF1(KIniFailMessage); |
|
625 CleanupStack::PopAndDestroy(configData); |
|
626 Kick(); |
|
627 break; |
|
628 } |
|
629 } |
|
630 |
|
631 CleanupStack::PopAndDestroy(configData); |
|
632 TExtraLogField logField[1]; |
|
633 _LIT(KIterations,"ITERATIONS"); |
|
634 logField[0].iLogFieldName.Copy(KIterations); |
|
635 logField[0].iLogFieldValue.Copy(KNull); |
|
636 logField[0].iLogFieldValue.AppendNum(iRepeatParam); |
|
637 Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, token, 1, logField); |
|
638 |
|
639 if(tempRepeatParam.Compare(KNull)==0) |
|
640 { |
|
641 _LIT(KRepeatKeyNotFound,"Repeat Parameter Key Not Found"); |
|
642 INFO_PRINTF1(KRepeatKeyNotFound); |
|
643 Kick(); |
|
644 break; |
|
645 } |
|
646 //Nesting of Control Logic is Not supported |
|
647 if(iLoop) |
|
648 { |
|
649 _LIT(KNestingNotAllowed,"Nesting of START_REPEAT is not supported.. Looping Ignored"); |
|
650 WARN_PRINTF1(KNestingNotAllowed); |
|
651 iLoop=EFalse; |
|
652 Kick(); |
|
653 break; |
|
654 } |
|
655 //Looping is not to be started with Concurrent mode |
|
656 if(iConcurrent) |
|
657 { |
|
658 _LIT(KConcurrentNotAllowed,"No concurrent Execution is Allowed in Looping"); |
|
659 INFO_PRINTF1(KConcurrentNotAllowed); |
|
660 Kick(); |
|
661 break; |
|
662 } |
|
663 |
|
664 iLoopCounter=0; |
|
665 //For Invalid Parameter continue ignoring looping |
|
666 if(iRepeatParam<1) |
|
667 { |
|
668 _LIT(KInvalidRepeatParam,"The repeat Parameter is invalid"); |
|
669 INFO_PRINTF1(KInvalidRepeatParam); |
|
670 Kick(); |
|
671 break; |
|
672 } |
|
673 iLoop=ETrue; |
|
674 iCheckVar=EFalse; |
|
675 Kick(); |
|
676 } |
|
677 else if(token.CompareF(KTEFEndRepeat)==0) |
|
678 { |
|
679 if(!iLoop) |
|
680 { |
|
681 _LIT(KLoopNotInitiated,"The Looping is Not Initiated"); |
|
682 INFO_PRINTF1(KLoopNotInitiated); |
|
683 Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, token); |
|
684 Kick(); |
|
685 break; |
|
686 } |
|
687 |
|
688 iLoopCounter++; |
|
689 if(iLoopCounter==iRepeatParam) |
|
690 { |
|
691 Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, token); |
|
692 iStartLooping=EFalse; |
|
693 iLoop=EFalse; |
|
694 } |
|
695 else |
|
696 { |
|
697 iStartLooping=ETrue; |
|
698 //Looping needs to be started in CONSECUTIVE mode |
|
699 if(iConcurrent) |
|
700 { |
|
701 iConcurrent=EFalse; |
|
702 } |
|
703 } |
|
704 Kick(); |
|
705 } |
|
706 else if(token.CompareF(KTEFRunTestStepCommand) == 0 || |
|
707 token.CompareF(KTEFRunPanicStepCommand) == 0 || |
|
708 token.CompareF(KTEFRunTestStepResultCommand) == 0 || |
|
709 token.CompareF(KTEFRunPanicStepResultCommand) == 0 |
|
710 ) |
|
711 { |
|
712 if(!CheckValidScriptLine()) |
|
713 { |
|
714 // Not a Valid Script Line |
|
715 |
|
716 TExitCategoryName blankPanicString; //Not a Panic |
|
717 LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine); |
|
718 // End of defect 037066 |
|
719 |
|
720 iCanComplete = EFalse; |
|
721 Kick(); |
|
722 break; |
|
723 } |
|
724 |
|
725 TInt index; |
|
726 TBool taskCanComplete = ETrue; |
|
727 TBool concurrent = iConcurrent; |
|
728 // Make sure the server is loaded |
|
729 if(!GetServerIndexFromScriptLine(index)) |
|
730 { |
|
731 // Not loaded. Skip the line, but ensure its logged as a failure. |
|
732 |
|
733 // Start of defect 037066 |
|
734 TExitCategoryName blankPanicString; //Not a Panic |
|
735 LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine); |
|
736 // End of defect 037066 |
|
737 |
|
738 iCanComplete = EFalse; |
|
739 Kick(); |
|
740 break; |
|
741 } |
|
742 |
|
743 if(!iConcurrent) |
|
744 { |
|
745 // If we're not in concurrent mode then child objects can complete us |
|
746 taskCanComplete = ETrue; |
|
747 // Prime ready for completion |
|
748 Prime(); |
|
749 } |
|
750 else |
|
751 { |
|
752 // In concurrent mode children can't complete us as we kick() ourselves. |
|
753 taskCanComplete = EFalse; |
|
754 Kick(); |
|
755 } |
|
756 iConcurrent = concurrent; |
|
757 // Create the test step controler object |
|
758 TInt loopIndex = -1; |
|
759 if (iLoop) |
|
760 { |
|
761 loopIndex = iLoopCounter + 1; |
|
762 } |
|
763 CClientControl* stepController = new (ELeave) CClientControl(*iServers[index],iCurrentScriptLine,*this,iCurrentScriptLineNumber,Logger(), loopIndex, iTestCaseID, iScriptFile, iDefaultSysDrive, iTestSysDrive); |
|
764 stepController->SetTaskComplete(taskCanComplete); |
|
765 iAsyncTasksOutstanding++; |
|
766 // Kick() the test step object into its state machine |
|
767 stepController->Kick(); |
|
768 } |
|
769 else if(token.CompareF(KTEFRunProgramCommand) == 0) |
|
770 { |
|
771 TBool taskCanComplete = ETrue; |
|
772 if(!iConcurrent) |
|
773 { |
|
774 // If we're not in concurrent mode then child objects can complete us |
|
775 taskCanComplete = ETrue; |
|
776 // Prime ready for completion |
|
777 Prime(); |
|
778 } |
|
779 else |
|
780 { |
|
781 // In concurrent mode children can't complete us as we kick() ourselves. |
|
782 taskCanComplete = EFalse; |
|
783 Kick(); |
|
784 } |
|
785 // Create the test step controller object |
|
786 CProgramControl* programController = new (ELeave) CProgramControl(iCurrentScriptLine,*this,iCurrentScriptLineNumber,Logger()); |
|
787 programController->SetTaskComplete(taskCanComplete); |
|
788 iAsyncTasksOutstanding++; |
|
789 // Kick() the test step object into its state machine |
|
790 programController->Kick(); |
|
791 } |
|
792 else if(token.CompareF(KTEFRunWSProgramCommand) == 0) |
|
793 { |
|
794 TBool taskCanComplete = ETrue; |
|
795 if(!iConcurrent) |
|
796 { |
|
797 // If we're not in concurrent mode then child objects can complete us |
|
798 taskCanComplete = ETrue; |
|
799 // Prime ready for completion |
|
800 Prime(); |
|
801 } |
|
802 else |
|
803 { |
|
804 // In concurrent mode children can't complete us as we kick() ourselves. |
|
805 taskCanComplete = EFalse; |
|
806 Kick(); |
|
807 } |
|
808 // Create the test step controller object |
|
809 CProgramControl* programController = new (ELeave) CProgramControl(iCurrentScriptLine,*this,iCurrentScriptLineNumber,Logger(),ETrue); |
|
810 iAsyncTasksOutstanding++; |
|
811 programController->SetTaskComplete(taskCanComplete); |
|
812 // Kick() the test step object into its state machine |
|
813 programController->Kick(); |
|
814 } |
|
815 else if(token.CompareF(KTEFConcurrentCommand) == 0) |
|
816 { |
|
817 // Go into concurrent mode |
|
818 // Whilst we're in concurrent mode we always kick() ourselves |
|
819 // around the state engine |
|
820 iConcurrent = ETrue; |
|
821 // Call the Logger()'s LogToXml routine to handle XML logging |
|
822 // Takes in just the command name without any field |
|
823 Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, KTEFConcurrentCommand); |
|
824 iCanComplete = EFalse; |
|
825 Kick(); |
|
826 } |
|
827 else if(token.CompareF(KTEFConsecutiveCommand) == 0) |
|
828 { |
|
829 // If we go into consecutive mode we have to make sure there are no |
|
830 // requests outstanding.Set the state accordingly |
|
831 iConcurrent = EFalse; |
|
832 |
|
833 // Call the Logger()'s LogToXml routine to handle XML logging |
|
834 // Takes in just the command name without any field |
|
835 Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, KTEFConsecutiveCommand); |
|
836 if(iAsyncTasksOutstanding) |
|
837 { |
|
838 iCanComplete = ETrue; |
|
839 iState = EWaitCompletions; |
|
840 Prime(); |
|
841 } |
|
842 else |
|
843 { |
|
844 iCanComplete = EFalse; |
|
845 iState = ERunning; |
|
846 Kick(); |
|
847 } |
|
848 } |
|
849 else if(token.CompareF(KTEFRunUtilsCommand) == 0) |
|
850 { |
|
851 // All utils complete synchronously |
|
852 TRAPD(err,RunUtilsFromScriptLineL()); |
|
853 |
|
854 // Create a TLogField structure array |
|
855 // Size of array equals to number of fields to be displayed for the command |
|
856 TExtraLogField logField[2]; |
|
857 |
|
858 // The first member of the structure stores the field name |
|
859 // The second one holds the value for the particular field |
|
860 _LIT(KCommand,"COMMAND"); |
|
861 logField[0].iLogFieldName.Copy(KCommand); |
|
862 logField[0].iLogFieldValue.Copy(lex.NextToken()); |
|
863 |
|
864 logField[1].iLogFieldName.Copy(KTEFResultString); |
|
865 if (err == KErrNone) |
|
866 { |
|
867 logField[1].iLogFieldValue.Copy(KTEFResultPass); |
|
868 } |
|
869 else |
|
870 { |
|
871 logField[1].iLogFieldValue.Copy(KTEFResultFail); |
|
872 } |
|
873 |
|
874 // Call the Logger().LogToXml routine which handles XML logging for individual commands |
|
875 // Takes in the command name, number of fields and the struture array |
|
876 Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, KTEFRunUtilsCommand, 2, logField); |
|
877 |
|
878 if(err != KErrNone) |
|
879 { |
|
880 _LIT(KRunUtilsError,"RUN_UTILS ret = %d"); |
|
881 INFO_PRINTF2(KRunUtilsError,err); |
|
882 } |
|
883 iCanComplete = EFalse; |
|
884 Kick(); |
|
885 } |
|
886 else if(token.CompareF(KTEFPrintCommand) == 0) |
|
887 { |
|
888 PrintFromScriptLine(); |
|
889 iCanComplete = EFalse; |
|
890 Kick(); |
|
891 } |
|
892 else if (token.CompareF(KTEFPrefixCommand) == 0) |
|
893 { |
|
894 |
|
895 if(iAsyncTasksOutstanding) |
|
896 // Don't run Prefix until all outstanding requests have completed |
|
897 { |
|
898 iState = EPrefixPending; |
|
899 iCanComplete = ETrue; |
|
900 Prime(); |
|
901 } |
|
902 else |
|
903 { |
|
904 // Ok to run PREFIX - Kick the stated machine so it's run next time in the RunL() |
|
905 iState = ERunPrefix; |
|
906 iCanComplete = EFalse; |
|
907 Kick(); |
|
908 } |
|
909 |
|
910 } |
|
911 else if (token.CompareF(KTEFRemovePrefixCommand) == 0) |
|
912 { |
|
913 iScriptLinePrefixSet = EFalse; |
|
914 iCanComplete = EFalse; |
|
915 Kick(); |
|
916 } |
|
917 else if (token.CompareF(KTEFStartTestCaseCommand) == 0) |
|
918 { |
|
919 if(ProceedTestCase()) |
|
920 { |
|
921 LogTestCaseMarkerL(); |
|
922 iCanComplete = EFalse; |
|
923 Kick(); |
|
924 } |
|
925 else |
|
926 { |
|
927 iState = ETestCaseIgnore; |
|
928 iCanComplete = EFalse; |
|
929 Kick(); |
|
930 } |
|
931 } |
|
932 else if (token.CompareF(KTEFEndTestCaseCommand) == 0) |
|
933 { |
|
934 ProcessEndCase(); |
|
935 if(iAsyncTasksOutstanding) |
|
936 // Don't run END_TESTCASE until all outstanding requests have completed |
|
937 { |
|
938 iState = EEndTestCasePending; |
|
939 iCanComplete = ETrue; |
|
940 Prime(); |
|
941 } |
|
942 else |
|
943 { |
|
944 // Ok to run END_TESTCASE - Kick the stated machine so it's run next time in the RunL() |
|
945 iState = ERunEndTestCase; |
|
946 iCanComplete = EFalse; |
|
947 Kick(); |
|
948 } |
|
949 } |
|
950 else if (token.CompareF(KTEFStartSyncTestCaseCommand) == 0) |
|
951 { |
|
952 if(ProceedTestCase()) |
|
953 { |
|
954 // Start Synchronised Test Case |
|
955 // Check to see if the Sync Data has been created |
|
956 // If not then create it |
|
957 if( iSyncControl == NULL ) |
|
958 { |
|
959 iSyncControl = CSyncControl::NewL(); |
|
960 } |
|
961 LogTestCaseMarkerL(); |
|
962 iState = ERunStartSyncTestCase; |
|
963 iCanComplete = EFalse; |
|
964 Kick(); |
|
965 } |
|
966 else |
|
967 { |
|
968 //go into some sleep state until you |
|
969 //encounter an end test case for this... |
|
970 iState = ETestCaseIgnore; |
|
971 iCanComplete = EFalse; |
|
972 Kick(); |
|
973 } |
|
974 } |
|
975 else if (token.CompareF(KTEFEndSyncTestCaseCommand) == 0) |
|
976 { |
|
977 ProcessEndCase(); |
|
978 // End Synchronised Test Case |
|
979 if(iAsyncTasksOutstanding) |
|
980 // Don't run END_SYNCHRONISED_TESTCASE until all outstanding requests have completed |
|
981 { |
|
982 iState = EEndTestCasePending; |
|
983 iCanComplete = ETrue; |
|
984 Prime(); |
|
985 } |
|
986 else |
|
987 { |
|
988 // Ok to run END_SYNCHRONISED_TESTCASE - Kick the stated machine so it's run next time in the RunL() |
|
989 iState = ERunEndTestCase; |
|
990 iCanComplete = EFalse; |
|
991 Kick(); |
|
992 } |
|
993 } |
|
994 else if(token.CompareF(KTEFRunScriptCommand) == 0) |
|
995 { |
|
996 // Create a TLogField structure array |
|
997 // Size of array equals to number of fields to be displayed for the command |
|
998 TExtraLogField logField[1]; |
|
999 |
|
1000 // The first member of the structure stores the field name |
|
1001 // The second one holds the value for the particular field |
|
1002 _LIT(KScriptName,"SCRIPT_NAME"); |
|
1003 logField[0].iLogFieldName.Copy(KScriptName); |
|
1004 logField[0].iLogFieldValue.Copy(lex.NextToken()); |
|
1005 |
|
1006 // Call the Logger().LogToXml routine which handles XML logging for individual commands |
|
1007 // Takes in the command name, number of fields and the struture array |
|
1008 Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrHigh, KTEFRunScriptCommand, 1, logField); |
|
1009 if(iAsyncTasksOutstanding) |
|
1010 { |
|
1011 // Don't recursively process a new script until this one's async |
|
1012 // requests are completed |
|
1013 iState = ERunScriptPending; |
|
1014 iCanComplete = ETrue; |
|
1015 Prime(); |
|
1016 } |
|
1017 else |
|
1018 { |
|
1019 // Ok to process the script recursively |
|
1020 iState = ERunScript; |
|
1021 iCanComplete = EFalse; |
|
1022 Kick(); |
|
1023 } |
|
1024 } |
|
1025 else if(token.CompareF(KTEFCedCommand) == 0) |
|
1026 // Run the CED comms database editor |
|
1027 { |
|
1028 if(iAsyncTasksOutstanding) |
|
1029 // Don't run CED until all outstanding requests have completed |
|
1030 { |
|
1031 iState = ERunCedPending; |
|
1032 iCanComplete = ETrue; |
|
1033 Prime(); |
|
1034 } |
|
1035 else |
|
1036 { |
|
1037 // Ok to run CED - Kick the stated machine so it's run next time in the RunL() |
|
1038 iState = ERunCed; |
|
1039 iCanComplete = EFalse; |
|
1040 Kick(); |
|
1041 } |
|
1042 } |
|
1043 else if(token.CompareF(KTEFDelayCommand) == 0) |
|
1044 // Delay n milliseconds |
|
1045 { |
|
1046 if(iAsyncTasksOutstanding) |
|
1047 // Don't delay until all outstanding requests have completed |
|
1048 { |
|
1049 iState = EDelayPending; |
|
1050 iCanComplete = ETrue; |
|
1051 Prime(); |
|
1052 } |
|
1053 else |
|
1054 { |
|
1055 // Ok to delay |
|
1056 iState = EDelay; |
|
1057 iCanComplete = EFalse; |
|
1058 Kick(); |
|
1059 } |
|
1060 } |
|
1061 // Script can exit on error |
|
1062 // Flag is checked on async task completion |
|
1063 else if(token.CompareF(KTEFBreakErrorOnCommand) == 0) |
|
1064 { |
|
1065 // Set the flag and process next line |
|
1066 iCanComplete = EFalse; |
|
1067 iBreakOnError = ETrue; |
|
1068 |
|
1069 // Call the Logger()'s LogToXml routine to handle XML logging |
|
1070 // Takes in just the command name without any field |
|
1071 Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, KTEFBreakErrorOnCommand); |
|
1072 Kick(); |
|
1073 } |
|
1074 else if(token.CompareF(KTEFBreakErrorOffCommand) == 0) |
|
1075 { |
|
1076 // Reset the flag and process next line |
|
1077 iCanComplete = EFalse; |
|
1078 iBreakOnError = EFalse; |
|
1079 |
|
1080 // Call the Logger()'s LogToXml routine to handle XML logging |
|
1081 // Takes in just the command name without any field |
|
1082 Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, KTEFBreakErrorOffCommand); |
|
1083 Kick(); |
|
1084 } |
|
1085 // We only implement the pause command if JustInTime debugging is switched on |
|
1086 else if(token.CompareF(KTEFPauseCommand) == 0 && User::JustInTime()) |
|
1087 { |
|
1088 // Create a TLogField structure array |
|
1089 // Size of array equals to number of fields to be displayed for the command |
|
1090 TExtraLogField logField[1]; |
|
1091 |
|
1092 // The first member of the structure stores the field name |
|
1093 // The second one holds the value for the particular field |
|
1094 _LIT(KDelay,"DELAY"); |
|
1095 logField[0].iLogFieldName.Copy(KDelay); |
|
1096 logField[0].iLogFieldValue.Copy(lex.NextToken()); |
|
1097 |
|
1098 // Call the Logger().LogToXml routine which handles XML logging for individual commands |
|
1099 // Takes in the command name, number of fields and the struture array |
|
1100 Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrLow, KTEFPauseCommand, 1, logField); |
|
1101 |
|
1102 if(iAsyncTasksOutstanding) |
|
1103 // Don't pause until all outstanding requests have completed |
|
1104 { |
|
1105 iState = EPausePending; |
|
1106 iCanComplete = ETrue; |
|
1107 Prime(); |
|
1108 } |
|
1109 else |
|
1110 { |
|
1111 // Ok to Pause |
|
1112 iState = EPause; |
|
1113 iCanComplete = EFalse; |
|
1114 Kick(); |
|
1115 } |
|
1116 } |
|
1117 // Handles the shared comand and also creates the shared object |
|
1118 // on reading user inputs from ini file |
|
1119 else if(token.CompareF(KTEFSharedDataCommand) == 0) |
|
1120 { |
|
1121 if (iIsSharedData) |
|
1122 { |
|
1123 WARN_PRINTF1(KTEFSharedDataCommandRepeated); |
|
1124 } |
|
1125 else |
|
1126 { |
|
1127 TRAPD(err,CreateSharedObjectsFromScriptLineL()); |
|
1128 if (err != KErrNone) |
|
1129 { |
|
1130 ERR_PRINTF1(KTEFErrInCreatingSharedObjects); |
|
1131 } |
|
1132 } |
|
1133 iCanComplete = EFalse; |
|
1134 Kick(); |
|
1135 } |
|
1136 else |
|
1137 { |
|
1138 // Command not implemented or a comment line |
|
1139 // Code implemented for defect 047340 |
|
1140 TBuf<KMaxTestExecuteCommandLength> bufWarning; |
|
1141 if(token.Length()) |
|
1142 { |
|
1143 TInt firstChar = iCurrentScriptLine[0]; |
|
1144 if(firstChar != '\r' && firstChar != '\n' && firstChar != '#' && firstChar != '/' && token.CompareF(KTEFPauseCommand) != 0) |
|
1145 { |
|
1146 _LIT(KUnrecognised,"Unrecognised Command - %S"); |
|
1147 if(token.Length() < bufWarning.MaxLength()) |
|
1148 { |
|
1149 bufWarning.Copy(token); |
|
1150 WARN_PRINTF2(KUnrecognised,&bufWarning); |
|
1151 } |
|
1152 else |
|
1153 { |
|
1154 _LIT(KLineTooLong,"Command line too long"); |
|
1155 bufWarning.Copy(KLineTooLong); |
|
1156 WARN_PRINTF2(KUnrecognised,&bufWarning); |
|
1157 } |
|
1158 } |
|
1159 } |
|
1160 iCanComplete = EFalse; |
|
1161 Kick(); |
|
1162 } |
|
1163 } |
|
1164 break; |
|
1165 |
|
1166 case EClosing : |
|
1167 // Script has been processed |
|
1168 // Pick up the completions |
|
1169 { |
|
1170 if(iAsyncTasksOutstanding == 0) |
|
1171 { |
|
1172 // Script finished |
|
1173 // Call into the parent |
|
1174 iParent.ChildCompletion(KErrNone); |
|
1175 delete this; |
|
1176 } |
|
1177 else |
|
1178 { |
|
1179 // More requests to complete |
|
1180 iCanComplete = ETrue; |
|
1181 Prime(); |
|
1182 } |
|
1183 } |
|
1184 break; |
|
1185 |
|
1186 case ERunScriptPending : |
|
1187 case EWaitCompletions : |
|
1188 case ERunCedPending : |
|
1189 case EDelayPending : |
|
1190 case EPausePending : |
|
1191 case EEndTestCasePending : |
|
1192 case EPrefixPending: |
|
1193 // We go into this state if we're waiting for RUN_TEST_STEP's |
|
1194 // to complete before we execute another command |
|
1195 { |
|
1196 if(iAsyncTasksOutstanding == 0) |
|
1197 { |
|
1198 // All steps complete |
|
1199 // Set up the next state and kick() the state machine |
|
1200 if(iState == ERunScriptPending) |
|
1201 iState = ERunScript; |
|
1202 else if(iState == EWaitCompletions) |
|
1203 iState = ERunning; |
|
1204 else if(iState == ERunCedPending) |
|
1205 iState = ERunCed; |
|
1206 else if(iState == EDelayPending) |
|
1207 iState = EDelay; |
|
1208 else if(iState == EPausePending) |
|
1209 iState = EPause; |
|
1210 else if(iState == EEndTestCasePending) |
|
1211 iState = ERunEndTestCase; |
|
1212 else if(iState == EPrefixPending) |
|
1213 iState = ERunPrefix; |
|
1214 // Safe to Kick() the state machine again |
|
1215 iCanComplete = EFalse; |
|
1216 Kick(); |
|
1217 } |
|
1218 else |
|
1219 { |
|
1220 // More requests outstanding |
|
1221 iCanComplete = ETrue; |
|
1222 Prime(); |
|
1223 } |
|
1224 } |
|
1225 break; |
|
1226 |
|
1227 case ERunScript : |
|
1228 // Recursively instantiate the CScriptControl class |
|
1229 { |
|
1230 GetScriptFileFromScriptLine(); |
|
1231 CScriptControl* scriptControl = new (ELeave) CScriptControl(*this,iChildScriptFile,Logger(),ConsoleLogger(),iStartLooping,iLoop,iDefaultSysDrive,iTestSysDrive,iSelTestingOptions); |
|
1232 // Kick the nested CScriptControl state machine |
|
1233 scriptControl->Kick(); |
|
1234 // Put our instance in the idling state, Prime()'d ready for clild-parent |
|
1235 // completion by the nested one. |
|
1236 iState = EIdling; |
|
1237 iCanComplete = ETrue; |
|
1238 Prime(); |
|
1239 } |
|
1240 break; |
|
1241 |
|
1242 case ERunCed : |
|
1243 // Slightly tricky one |
|
1244 // WIN32 & Non-secure means we execute CED synchronously |
|
1245 { |
|
1246 SetActive(); |
|
1247 TRAPD(err,RunCedFromScriptLineL()); |
|
1248 if(!err) |
|
1249 // Expect completion asynchronously |
|
1250 // We're set for completion so just set the state |
|
1251 iState = EIdling; |
|
1252 else |
|
1253 { |
|
1254 _LIT(KCedError,"CED Error = %d"); |
|
1255 ERR_PRINTF2(KCedError,err); |
|
1256 // A CED error so kick the state machine |
|
1257 iState = ERunning; |
|
1258 Kick(); |
|
1259 } |
|
1260 } |
|
1261 break; |
|
1262 |
|
1263 case EDelay : |
|
1264 { |
|
1265 // Kick the timer and wait for completion |
|
1266 SetActive(); |
|
1267 StartTimerFromScriptLine(); |
|
1268 iState = EIdling; |
|
1269 } |
|
1270 break; |
|
1271 |
|
1272 case ERunEndTestCase : |
|
1273 { |
|
1274 LogTestCaseMarkerL(); |
|
1275 iState = ERunning; |
|
1276 iCanComplete = EFalse; |
|
1277 Kick(); |
|
1278 } |
|
1279 break; |
|
1280 |
|
1281 case ERunStartSyncTestCase : |
|
1282 { |
|
1283 // Check to see if the test case is ready to continue |
|
1284 SetActive(); |
|
1285 iTimer.After( iStatus, KTEFStatusDelay*1000 ); |
|
1286 TBool syncContinue = iSyncControl->TestCaseContinueL(); |
|
1287 if( syncContinue ) |
|
1288 { |
|
1289 iState = EIdling; |
|
1290 } |
|
1291 } |
|
1292 break; |
|
1293 case ERunPrefix : |
|
1294 { |
|
1295 SetPrefix(); |
|
1296 iState = ERunning; |
|
1297 iCanComplete = EFalse; |
|
1298 Kick(); |
|
1299 } |
|
1300 break; |
|
1301 |
|
1302 case EIdling : |
|
1303 { |
|
1304 // Woken up due to either: |
|
1305 // A child CScriptControl instance completing OR |
|
1306 // the delay timer has completed. |
|
1307 iState = ERunning; |
|
1308 iCanComplete = EFalse; |
|
1309 Kick(); |
|
1310 } |
|
1311 break; |
|
1312 |
|
1313 case EPause : |
|
1314 { |
|
1315 _LIT(KPaused,"PAUSED - Hit Any Key to Continue\n"); |
|
1316 ConsoleLogger().Console().Printf(KPaused); |
|
1317 ConsoleLogger().Console().Getch(); |
|
1318 iState = ERunning; |
|
1319 iCanComplete = EFalse; |
|
1320 Kick(); |
|
1321 } |
|
1322 //Start of defect 115942 |
|
1323 break; |
|
1324 //End of defect 115942 |
|
1325 |
|
1326 case ETestCaseIgnore: |
|
1327 { |
|
1328 TPtrC scriptLine; |
|
1329 //do we want to while till we come to end of test case? |
|
1330 while(GetNextScriptLine(scriptLine)) |
|
1331 { |
|
1332 TLex lex(scriptLine); |
|
1333 TPtrC token(lex.NextToken()); |
|
1334 if((token.CompareF(KTEFEndTestCaseCommand) == 0) |
|
1335 || (token.CompareF(KTEFEndSyncTestCaseCommand) == 0)) //we found an end test case one |
|
1336 { |
|
1337 TPtrC testCID(lex.NextToken()); |
|
1338 //to support nested test cases |
|
1339 if(iTestCaseIDToIgnore.CompareF(testCID) == 0) |
|
1340 { |
|
1341 //in any case...go back to running and re-evaluate our position at |
|
1342 iState = ERunning; |
|
1343 iTestCaseIDToIgnore.Set(KTEFNull); |
|
1344 iCanComplete = EFalse; |
|
1345 iCurrentScriptLine.Set(scriptLine); |
|
1346 //before going back to running re-evaluate the |
|
1347 //state of selective testing |
|
1348 ProcessEndCase() ; |
|
1349 Kick(); |
|
1350 break; |
|
1351 } |
|
1352 } |
|
1353 } |
|
1354 break; |
|
1355 } |
|
1356 |
|
1357 default: |
|
1358 break; |
|
1359 } |
|
1360 } |
|
1361 |
|
1362 /** |
|
1363 * Implement the PRINT command |
|
1364 * Print the string(s) following the PRINT command to the log file |
|
1365 */ |
|
1366 void CScriptControl::PrintFromScriptLine() const |
|
1367 { |
|
1368 TLex lex(iCurrentScriptLine); |
|
1369 lex.NextToken(); |
|
1370 TBuf<KMaxTestExecuteCommandLength> buf; |
|
1371 buf.Copy(lex.Remainder()); |
|
1372 |
|
1373 _LIT(KCommentString, " //"); |
|
1374 |
|
1375 TInt offset = buf.Find(KCommentString); |
|
1376 if (offset != KErrNotFound) |
|
1377 { |
|
1378 buf.SetLength(offset); |
|
1379 } |
|
1380 |
|
1381 _LIT(KS,"%S"); |
|
1382 INFO_PRINTF2(KS,&buf); |
|
1383 } |
|
1384 |
|
1385 /** |
|
1386 * Implement the PREFIX command |
|
1387 * Stores the prefix for command line prefixing |
|
1388 */ |
|
1389 void CScriptControl::SetPrefix() |
|
1390 { |
|
1391 TLex lex(iCurrentScriptLine); |
|
1392 // Bypass the PREFIX command |
|
1393 lex.NextToken(); |
|
1394 |
|
1395 // Get rid of any leading spaces |
|
1396 while(!lex.Eos()) |
|
1397 { |
|
1398 TChar peek = lex.Peek(); |
|
1399 if(peek == ' ') |
|
1400 { |
|
1401 lex.Inc(); |
|
1402 } |
|
1403 else |
|
1404 break; |
|
1405 } |
|
1406 |
|
1407 // Chop off the carriage return and insert a space |
|
1408 // If there is a preceding comment line, get rid of that. |
|
1409 |
|
1410 iScriptLinePrefix.Copy(lex.Remainder()); |
|
1411 |
|
1412 _LIT(KCarriageReturn, "\r\n"); |
|
1413 _LIT(KCommentString, " //"); |
|
1414 |
|
1415 TInt offset = iScriptLinePrefix.Find(KCommentString); |
|
1416 if (offset != KErrNotFound) |
|
1417 { |
|
1418 iScriptLinePrefix.SetLength(offset); |
|
1419 } |
|
1420 else |
|
1421 { |
|
1422 offset = iScriptLinePrefix.Find(KCarriageReturn); |
|
1423 |
|
1424 if (offset != KErrNotFound) |
|
1425 { |
|
1426 iScriptLinePrefix.SetLength(offset); |
|
1427 } |
|
1428 } |
|
1429 |
|
1430 _LIT(KTEFSpace, " "); |
|
1431 iScriptLinePrefix.Append(KTEFSpace); |
|
1432 |
|
1433 iScriptLinePrefixSet = ETrue; |
|
1434 |
|
1435 } |
|
1436 |
|
1437 /** |
|
1438 * Function to evaluate the situation of selective testing |
|
1439 * Returns whether the testcase on the current script line |
|
1440 * should be run. |
|
1441 */ |
|
1442 TBool CScriptControl::ProceedTestCase() |
|
1443 { |
|
1444 |
|
1445 //if selective testing is not on, dont bother |
|
1446 if(iSelTestingOptions == NULL) |
|
1447 return ETrue; |
|
1448 iTestCaseCounter++; |
|
1449 if(iTestCaseCounter > 1) //if this is nested, let it run unconditionally |
|
1450 return ETrue; |
|
1451 // the remaining continues only if selective testing is on |
|
1452 // AND we have a non-null, and hopefully valid instance of |
|
1453 // iSelTestingOptions |
|
1454 TLex lex(iCurrentScriptLine); |
|
1455 TPtrC token(lex.NextToken()); |
|
1456 TPtrC testCaseID(lex.NextToken()); |
|
1457 //evaluating class state variables... |
|
1458 //check range |
|
1459 TIdentityRelation<TPtrC> crackID(TSelectiveTestingOptions::CompareTPtrC); |
|
1460 TIdentityRelation<TRange> rangeComprtr(TRange::CompareTRangeStartCase); |
|
1461 TRange dummy(testCaseID,testCaseID); |
|
1462 for ( TInt index=0; index<iSelTestingOptions->iSelectiveCaseRange.Count(); ++index ) |
|
1463 { |
|
1464 if ( testCaseID.CompareF(iSelTestingOptions->iSelectiveCaseRange[index].iStartTestCase) == 0 ) |
|
1465 { |
|
1466 iSelTestingOptions->iSelectiveCaseRange[index].iState=TRange::EStateInUse; |
|
1467 ++iRangeRefCounter;//number of ranges now in operation |
|
1468 } |
|
1469 } |
|
1470 |
|
1471 |
|
1472 TBool runCase = ETrue ; //run everything by def |
|
1473 if( iSelTestingOptions->iSelectiveTestingType == iInclusive ) |
|
1474 { |
|
1475 //so selective testing is on and also its inclusive... |
|
1476 runCase = (iRangeRefCounter>0) || iSelectOne ; |
|
1477 } |
|
1478 else if(iSelTestingOptions->iSelectiveTestingType == iExclusive) |
|
1479 { |
|
1480 //so selective testing is on and also its exclusive... |
|
1481 runCase = (iRangeRefCounter<=0) && !iSelectOne ; |
|
1482 } |
|
1483 if(!runCase)//if the test case is to be selectively skipped, log it... |
|
1484 { |
|
1485 //use this one to log unexecuted cases... |
|
1486 Logger().LogTestCaseResult(iScriptFile, iCurrentScriptLineNumber, RFileFlogger::ESevrInfo, token, testCaseID,ESkippedSelectively); |
|
1487 } |
|
1488 if(runCase == EFalse) |
|
1489 { |
|
1490 iTestCaseIDToIgnore.Set(testCaseID) ; |
|
1491 } |
|
1492 |
|
1493 return runCase ; |
|
1494 } |
|
1495 |
|
1496 /** |
|
1497 * Function to evaluate the state variables |
|
1498 * at the end of test case |
|
1499 */ |
|
1500 void CScriptControl::ProcessEndCase() |
|
1501 { |
|
1502 if(iSelTestingOptions==NULL) //selective testing is not on |
|
1503 return; // dont bother |
|
1504 iTestCaseCounter--; |
|
1505 if(iTestCaseCounter<0) //in case we encountered unmatched end cases |
|
1506 iTestCaseCounter=0; |
|
1507 TLex lex(iCurrentScriptLine); |
|
1508 TPtrC token(lex.NextToken()); |
|
1509 TPtrC testCaseID(lex.NextToken()); |
|
1510 //check if this is ending a range |
|
1511 TRange dummy(testCaseID,testCaseID); |
|
1512 TIdentityRelation<TRange> crackIDRangeend(TRange::CompareTRangeEnd); |
|
1513 for ( TInt index=0; index<iSelTestingOptions->iSelectiveCaseRange.Count(); ++index ) |
|
1514 { |
|
1515 if ( testCaseID.CompareF(iSelTestingOptions->iSelectiveCaseRange[index].iEndTestCase) == 0 ) |
|
1516 { |
|
1517 if ( iSelTestingOptions->iSelectiveCaseRange[index].iState == TRange::EStateInUse ) |
|
1518 { |
|
1519 iSelTestingOptions->iSelectiveCaseRange[index].iState=TRange::EStateUsed; |
|
1520 --iRangeRefCounter; |
|
1521 } |
|
1522 else |
|
1523 { |
|
1524 // Error condition. An end test case has been matched to a range that has not processed the start test case |
|
1525 // Either the start test case does not exist or the start test case comes after the end test case in the script |
|
1526 //or maybe do nothing |
|
1527 |
|
1528 } |
|
1529 } |
|
1530 } |
|
1531 |
|
1532 |
|
1533 //always reset the onetime test case thing |
|
1534 iSelectOne = EFalse; |
|
1535 } |
|
1536 |
|
1537 /** |
|
1538 * Implement START_TESTCASE/ END_TESTCASE commands |
|
1539 * Write a testcase marker to the logfile |
|
1540 */ |
|
1541 void CScriptControl::LogTestCaseMarkerL() |
|
1542 { |
|
1543 TLex lex(iCurrentScriptLine); |
|
1544 TPtrC token(lex.NextToken()); |
|
1545 TVerdict TestCaseResult(EFail); |
|
1546 |
|
1547 TPtrC TestCaseMarker(lex.NextToken()); |
|
1548 |
|
1549 if (token.CompareF(KTEFStartTestCaseCommand) == 0 || token.CompareF(KTEFStartSyncTestCaseCommand) == 0) |
|
1550 { |
|
1551 // Call the interface routine for logging in HTML & XML format |
|
1552 Logger().LogTestCaseResult(iScriptFile, iCurrentScriptLineNumber, RFileFlogger::ESevrHigh, token, TestCaseMarker); |
|
1553 iTestCaseID.Copy(TestCaseMarker); |
|
1554 } |
|
1555 else |
|
1556 { |
|
1557 // Its an END_TESTCASE. |
|
1558 // Need to identify whether all preceding test steps in the file |
|
1559 // passed (back to a *matching* START_TESTCASE). |
|
1560 TestCaseResult = HasTestCasePassedL(TestCaseMarker); |
|
1561 |
|
1562 // Special case for KTEFEndSyncTestCaseCommand where the result in |
|
1563 // the shared data area needs to be updated so STAT can retrieve it later. |
|
1564 if( token.CompareF(KTEFEndSyncTestCaseCommand) == 0 ) |
|
1565 { |
|
1566 // Check to see if the Sync Data has been created |
|
1567 if( iSyncControl != NULL ) |
|
1568 { |
|
1569 // Update the TEFResult shared data value |
|
1570 iSyncControl->SetResultL( TestCaseResult ); |
|
1571 } |
|
1572 else |
|
1573 { |
|
1574 User::Leave( KErrNotReady ); |
|
1575 } |
|
1576 } |
|
1577 // Call the interface routine for logging in HTML & XML format |
|
1578 Logger().LogTestCaseResult(iScriptFile, iCurrentScriptLineNumber, RFileFlogger::ESevrHigh, token, TestCaseMarker, TestCaseResult); |
|
1579 iTestCaseID.Copy(KTEFTestCaseDefault); |
|
1580 } |
|
1581 } |
|
1582 |
|
1583 /** |
|
1584 * |
|
1585 * Implement TestCase pass checking |
|
1586 */ |
|
1587 TVerdict CScriptControl::HasTestCasePassedL(TPtrC aTestCaseMarker) |
|
1588 { |
|
1589 // Looks from the top of the file for the equivalent Start_TestCase |
|
1590 // when it finds it it checks that all the steps to the bottom of |
|
1591 // the file (the current position) |
|
1592 |
|
1593 // Create a Cinidata object to parse through the testexecute.ini |
|
1594 // To retrieve the path where the log is to be placed |
|
1595 |
|
1596 CTestExecuteIniData* parseTestExecuteIni = NULL; |
|
1597 TBuf<KMaxTestExecuteNameLength> resultFilePath; |
|
1598 |
|
1599 TRAPD(err,parseTestExecuteIni = CTestExecuteIniData::NewL(iDefaultSysDrive)); |
|
1600 if (err == KErrNone) |
|
1601 { |
|
1602 CleanupStack::PushL(parseTestExecuteIni); |
|
1603 parseTestExecuteIni->ExtractValuesFromIni(); |
|
1604 parseTestExecuteIni->GetKeyValueFromIni(KTEFHtmlKey, resultFilePath); |
|
1605 } |
|
1606 else |
|
1607 { |
|
1608 resultFilePath.Copy(KTestExecuteLogPath); |
|
1609 resultFilePath.Replace(0, 2, iDefaultSysDrive); |
|
1610 } |
|
1611 |
|
1612 TBuf<KMaxTestExecuteNameLength> resultFileName(resultFilePath); |
|
1613 // loading the simplified test result in case of out-of-memory |
|
1614 resultFileName.Append(KTEFTestExecuteResultSimplifiedSummaryFile); |
|
1615 if (parseTestExecuteIni != NULL) |
|
1616 { |
|
1617 CleanupStack::PopAndDestroy(parseTestExecuteIni); |
|
1618 } |
|
1619 |
|
1620 // Open the result summary file |
|
1621 RFs fS; |
|
1622 User::LeaveIfError(fS.Connect()); |
|
1623 CleanupClosePushL(fS); |
|
1624 |
|
1625 RFile logFile; |
|
1626 User::LeaveIfError(logFile.Open(fS,resultFileName, EFileWrite | EFileRead | EFileShareAny)); |
|
1627 CleanupClosePushL(logFile); |
|
1628 TInt fileSize; |
|
1629 // Read the complete result summary file onto the heap |
|
1630 // It wont be that large |
|
1631 User::LeaveIfError(logFile.Size(fileSize)); |
|
1632 HBufC* resultData = HBufC::NewLC(fileSize); |
|
1633 HBufC8* resultData8 = HBufC8::NewLC(fileSize); |
|
1634 TPtr8 ptrData8(resultData8->Des()); |
|
1635 User::LeaveIfError(logFile.Read(ptrData8)); |
|
1636 TPtr ptrData(resultData->Des()); |
|
1637 ptrData.Copy(ptrData8); |
|
1638 CleanupStack::PopAndDestroy(resultData8); |
|
1639 |
|
1640 TBool foundMarker(EFalse); |
|
1641 TBool foundNonPassResult(EFalse); |
|
1642 TInt duplicatesCounter(0); |
|
1643 |
|
1644 TLex lex(ptrData); |
|
1645 while (!lex.Eos()) |
|
1646 { |
|
1647 // Find the ***Result keywords |
|
1648 TPtrC commandName( lex.NextToken() ); |
|
1649 if( commandName.CompareF(KTEFStartTestCaseCommand) == 0 || |
|
1650 commandName.CompareF(KTEFStartSyncTestCaseCommand) == 0 ) |
|
1651 { |
|
1652 if (lex.NextToken() == aTestCaseMarker) |
|
1653 { |
|
1654 // Increment the counter to identify that the test case id is duplicated |
|
1655 duplicatesCounter++; |
|
1656 if (duplicatesCounter == 2) |
|
1657 { |
|
1658 // If the test case id is duplicated for more than once, |
|
1659 // issue a warning in the log file, mentioning duplicate of test case id |
|
1660 _LIT(KWarnDuplicateTCID, "Test Case ID : %S re-used"); |
|
1661 WARN_PRINTF2(KWarnDuplicateTCID, &aTestCaseMarker); |
|
1662 } |
|
1663 |
|
1664 // When a matching test case id is found, the found marker is set to ETrue |
|
1665 foundMarker = ETrue; |
|
1666 // Initialise the foundNonPassResult to EFalse, on entry into each test case result in the log |
|
1667 foundNonPassResult = EFalse; |
|
1668 continue; |
|
1669 } |
|
1670 continue; |
|
1671 } |
|
1672 else if (foundMarker && commandName == KTEFResultTag) |
|
1673 { |
|
1674 // If the START_TESTCASE is found and a RESULT tag is found in the test result file, |
|
1675 // Extract the result value set for every test step called within |
|
1676 // and check to see if there are any non-pas results |
|
1677 _LIT(KTEFEquals,"="); |
|
1678 if (lex.NextToken() != KTEFEquals) |
|
1679 continue; |
|
1680 TPtrC result(lex.NextToken()); |
|
1681 if(result != KTEFResultPass) |
|
1682 { |
|
1683 // Set the foundNonPassResult to ETrue indicating the test case to fail |
|
1684 foundNonPassResult = ETrue; |
|
1685 } |
|
1686 } |
|
1687 } |
|
1688 |
|
1689 CleanupStack::PopAndDestroy(resultData); |
|
1690 CleanupStack::Pop(&logFile); |
|
1691 logFile.Close(); |
|
1692 CleanupStack::Pop(&fS); |
|
1693 fS.Close(); |
|
1694 |
|
1695 if (foundMarker) |
|
1696 { |
|
1697 if (foundNonPassResult) |
|
1698 { |
|
1699 return EFail; |
|
1700 } |
|
1701 else |
|
1702 { |
|
1703 return EPass; |
|
1704 } |
|
1705 } |
|
1706 else |
|
1707 { |
|
1708 return EInconclusive; |
|
1709 } |
|
1710 } |
|
1711 |
|
1712 /** |
|
1713 * Implement the DELAY command |
|
1714 */ |
|
1715 void CScriptControl::StartTimerFromScriptLine() |
|
1716 { |
|
1717 TLex lex(iCurrentScriptLine); |
|
1718 lex.NextToken(); |
|
1719 TLex delayLex(lex.NextToken()); |
|
1720 TInt delay; |
|
1721 // Read the delay in milliseconds |
|
1722 TInt err = delayLex.Val(delay); |
|
1723 if(err) |
|
1724 // Set the default |
|
1725 delay = KDefaultDelayMilliseconds; |
|
1726 iTimer.After(iStatus,delay*1000); |
|
1727 } |
|
1728 |
|
1729 /** |
|
1730 * Secure - same for Target and Wins |
|
1731 */ |
|
1732 void CScriptControl::RunCedFromScriptLineL() |
|
1733 { |
|
1734 TLex lex(iCurrentScriptLine); |
|
1735 // Skip CED |
|
1736 lex.NextToken(); |
|
1737 TPtrC cedCommandLine(lex.Remainder()); |
|
1738 iCurrentScriptLine.Set(cedCommandLine); |
|
1739 RProcess process; |
|
1740 User::LeaveIfError(process.Create(_L("ced.exe"),iCurrentScriptLine)); |
|
1741 process.Rendezvous(iStatus); |
|
1742 // Run CED asynchronously |
|
1743 process.Resume(); |
|
1744 process.Close(); |
|
1745 } |
|
1746 |
|
1747 /** |
|
1748 * Set up the path of a script file for a child CScriptControl object |
|
1749 */ |
|
1750 void CScriptControl::GetScriptFileFromScriptLine() |
|
1751 { |
|
1752 TLex lex(iCurrentScriptLine); |
|
1753 lex.NextToken(); |
|
1754 iChildScriptFile.Set(lex.NextToken()); |
|
1755 } |
|
1756 |
|
1757 /** |
|
1758 * @param aUtilsCommand - Command string for the utilities command |
|
1759 * Implement basic commands: |
|
1760 * NB: Always requires the full path |
|
1761 * Logic borrowed from Scheduletest |
|
1762 * Always complete synchronously |
|
1763 * |
|
1764 * CopyFile |
|
1765 * MKDir |
|
1766 * MakeReadWrite |
|
1767 * Delete |
|
1768 * DeleteDirectory |
|
1769 */ |
|
1770 void CScriptControl::RunUtilsFromScriptLineL() const |
|
1771 { |
|
1772 _LIT(KDefault, "?:\\default"); |
|
1773 _LIT(KCDrive, "?:\\"); |
|
1774 _LIT(KTEFBackslash, "\\" ); |
|
1775 |
|
1776 TBuf<10> defaultPath(KDefault); |
|
1777 defaultPath.Replace(0, 2, iTestSysDrive); |
|
1778 |
|
1779 TBuf<3> cDrive(KCDrive); |
|
1780 cDrive.Replace(0, 2, iTestSysDrive); |
|
1781 |
|
1782 RFs fS; |
|
1783 User::LeaveIfError(fS.Connect() ); |
|
1784 CleanupClosePushL(fS); |
|
1785 |
|
1786 TLex lex(iCurrentScriptLine); |
|
1787 lex.NextToken(); |
|
1788 TPtrC token(lex.NextToken()); |
|
1789 if(token.CompareF(KTEFRunUtilsCopyFile) == 0) |
|
1790 { |
|
1791 TPtrC file1=lex.NextToken(); |
|
1792 TPtrC file2=lex.NextToken(); |
|
1793 TParse source, dest; |
|
1794 CFileMan* fMan = CFileMan::NewL(fS); |
|
1795 CleanupStack::PushL(fMan); |
|
1796 User::LeaveIfError(source.Set(file1, &defaultPath, NULL) ); |
|
1797 User::LeaveIfError(dest.Set(file2, &defaultPath, NULL) ); |
|
1798 User::LeaveIfError(fMan->Copy(source.FullName(), dest.FullName(), CFileMan::EOverWrite) ); |
|
1799 CleanupStack::PopAndDestroy(fMan); |
|
1800 } |
|
1801 else if(token.CompareF(KTEFRunUtilsMkDir) == 0) |
|
1802 { |
|
1803 token.Set(lex.NextToken()); |
|
1804 TParse fileName; |
|
1805 |
|
1806 if (!token.Length()) |
|
1807 User::Leave(KErrPathNotFound); |
|
1808 |
|
1809 TPtrC lastChar(token.Mid(token.Length() - 1)); |
|
1810 if ( lastChar.CompareF(KTEFBackslash) != 0 ) |
|
1811 { |
|
1812 TBuf<64> tempToken(token); |
|
1813 tempToken.Append(KTEFBackslash); |
|
1814 token.Set(tempToken); |
|
1815 } |
|
1816 |
|
1817 User::LeaveIfError( fileName.Set(token, &cDrive, NULL) ); |
|
1818 User::LeaveIfError( fS.MkDir( fileName.DriveAndPath() ) ); |
|
1819 } |
|
1820 else if(token.CompareF(KTEFRunUtilsDeleteFile) == 0 || |
|
1821 token.CompareF(KTEFRunUtilsDelete) == 0) |
|
1822 { |
|
1823 token.Set(lex.NextToken()); |
|
1824 // defect047128 - Code change for handling wildcard deletes |
|
1825 CFileMan* fMan = CFileMan::NewL(fS); |
|
1826 CleanupStack::PushL(fMan); |
|
1827 User::LeaveIfError(fMan->Delete(token) ); |
|
1828 CleanupStack::PopAndDestroy(fMan); |
|
1829 } |
|
1830 else if(token.CompareF(KTEFRunUtilsMakeReadWrite) == 0) |
|
1831 { |
|
1832 token.Set(lex.NextToken()); |
|
1833 TParse fileName; |
|
1834 User::LeaveIfError(fileName.Set(token, &defaultPath, NULL) ); |
|
1835 TInt err = fS.SetAtt(fileName.FullName(),0, KEntryAttReadOnly); |
|
1836 if (err != KErrNone && err != KErrNotFound) |
|
1837 User::Leave(err); |
|
1838 } |
|
1839 //It deletes the specified directory |
|
1840 else if(token.CompareF(KTEFDeleteDirectory) == 0) |
|
1841 { |
|
1842 token.Set(lex.NextToken()); |
|
1843 TParse fileName; |
|
1844 |
|
1845 if (!token.Length()) |
|
1846 User::Leave(KErrPathNotFound); |
|
1847 |
|
1848 TPtrC lastChar(token.Mid(token.Length() - 1)); |
|
1849 if ( lastChar.CompareF(KTEFBackslash) != 0 ) |
|
1850 { |
|
1851 TBuf<64> tempToken(token); |
|
1852 tempToken.Append(KTEFBackslash); |
|
1853 token.Set(tempToken); |
|
1854 } |
|
1855 |
|
1856 CFileMan* fMan = CFileMan::NewL(fS); |
|
1857 CleanupStack::PushL(fMan); |
|
1858 |
|
1859 User::LeaveIfError(fileName.Set(token, &cDrive, NULL) ); |
|
1860 User::LeaveIfError( fMan->RmDir( fileName.DriveAndPath() ) ); |
|
1861 |
|
1862 CleanupStack::PopAndDestroy(fMan); |
|
1863 } |
|
1864 |
|
1865 fS.Close(); |
|
1866 CleanupStack::Pop(&fS); |
|
1867 } |
|
1868 |
|
1869 /** |
|
1870 * Read the Script File data into a heap buffer |
|
1871 * We could read the file line by line but that would be cumbersome, and unless there |
|
1872 * is a heap size problem, this is tidier. |
|
1873 */ |
|
1874 void CScriptControl::CreateScriptDataFromScriptFileL() |
|
1875 { |
|
1876 RFs fS; |
|
1877 User::LeaveIfError(fS.Connect()); |
|
1878 CleanupClosePushL(fS); |
|
1879 RFile scriptFile; |
|
1880 User::LeaveIfError(scriptFile.Open(fS,iScriptFile,EFileRead | EFileShareAny)); |
|
1881 CleanupClosePushL(scriptFile); |
|
1882 TInt fileSize; |
|
1883 User::LeaveIfError(scriptFile.Size(fileSize)); |
|
1884 // Create a 16bit heap buffer |
|
1885 iScriptData = HBufC::NewL(fileSize); |
|
1886 HBufC8* narrowData = HBufC8::NewL(fileSize); |
|
1887 CleanupStack::PushL(narrowData); |
|
1888 TPtr8 narrowPtr=narrowData->Des(); |
|
1889 // Read the file into an 8bit heap buffer |
|
1890 User::LeaveIfError(scriptFile.Read(narrowPtr)); |
|
1891 TPtr widePtr(iScriptData->Des()); |
|
1892 // Copy it to the 16bit buffer |
|
1893 widePtr.Copy(narrowData->Des()); |
|
1894 CleanupStack::PopAndDestroy(narrowData); |
|
1895 CleanupStack::Pop(2); |
|
1896 scriptFile.Close(); |
|
1897 fS.Close(); |
|
1898 // Set up the instance token parser |
|
1899 iScriptLex = iScriptData->Des(); |
|
1900 } |
|
1901 |
|
1902 /** |
|
1903 * Extracts the human readable server name from the current script line then |
|
1904 * calls Client RTestServ Interface to make a connection to the server. |
|
1905 */ |
|
1906 void CScriptControl::CreateServerFromScriptLineL() |
|
1907 { |
|
1908 TLex lex(iCurrentScriptLine); |
|
1909 lex.NextToken(); |
|
1910 TInt i=0; |
|
1911 TInt count = iServers.Count(); |
|
1912 TPtrC serverName(lex.NextToken()); |
|
1913 |
|
1914 // We loop through to see if the server has already been created |
|
1915 for(i=0;i<count;i++) |
|
1916 { |
|
1917 if(iServers[i]->ServerName() == serverName) |
|
1918 // Server already exists in our array |
|
1919 break; |
|
1920 } |
|
1921 if(i == count) |
|
1922 { |
|
1923 // Create a new RTestServ pointer and add it to the list |
|
1924 RScriptTestServ* serv = new (ELeave) RScriptTestServ; |
|
1925 // Connect using the client API |
|
1926 TInt err; |
|
1927 if(lex.NextToken().CompareF(KTEFLoadSuiteSharedData) == 0) |
|
1928 { |
|
1929 err = serv->Connect(serverName,ETrue); |
|
1930 } |
|
1931 else |
|
1932 err = serv->Connect(serverName,EFalse); |
|
1933 if(err) |
|
1934 { |
|
1935 // Don't add the server to the array if we fail to connect. |
|
1936 delete serv; |
|
1937 // Caller TRAP's |
|
1938 User::Leave(err); |
|
1939 } |
|
1940 iServers.Append(serv); |
|
1941 } |
|
1942 } |
|
1943 |
|
1944 /** |
|
1945 * @param aIndex - Return the index of the RTestServ instance - If found |
|
1946 * @return - EFalse if server not found. ETrue if server found. |
|
1947 * |
|
1948 */ |
|
1949 TBool CScriptControl::GetServerIndexFromScriptLine(TInt& aIndex) |
|
1950 { |
|
1951 TLex lex(iCurrentScriptLine); |
|
1952 TLex lexTimeout; |
|
1953 _LIT(KErrInvalidArgumentSet,"The arguments are not provided in proper format.\ |
|
1954 Unable to retrieve the details of the server from the command line"); |
|
1955 |
|
1956 TPtrC command(lex.NextToken()); |
|
1957 if(command.CompareF(KTEFRunTestStepResultCommand) == 0) |
|
1958 { |
|
1959 lex.NextToken(); |
|
1960 lex.SkipSpace(); |
|
1961 lex.Mark(); |
|
1962 } |
|
1963 |
|
1964 else if(command.CompareF(KTEFRunPanicStepResultCommand) == 0) |
|
1965 { |
|
1966 lex.NextToken(); |
|
1967 TPtrC panicString(lex.NextToken()); |
|
1968 // Check to see if the panic string contains open quotes and close quotes |
|
1969 // If the panic string token contains open quote, it is understood that the panic string contains spaces |
|
1970 // So, look for close quote in the subsequent tokens. If not found, return boolean false as return value |
|
1971 if(panicString.Left(1).Compare(KTEFOpenQuotes) == 0 && panicString.Right(1).Compare(KTEFOpenQuotes) != 0) |
|
1972 { |
|
1973 TBool validCommandLine(EFalse); |
|
1974 while(!lex.Eos() && !validCommandLine) |
|
1975 { |
|
1976 panicString.Set(lex.NextToken()); |
|
1977 if(panicString.Right(1).Compare(KTEFOpenQuotes) == 0) |
|
1978 validCommandLine = ETrue; |
|
1979 } |
|
1980 if (!validCommandLine) |
|
1981 { |
|
1982 ERR_PRINTF1(KErrInvalidArgumentSet); |
|
1983 return EFalse; |
|
1984 } |
|
1985 } |
|
1986 lex.SkipSpace(); |
|
1987 lex.Mark(); |
|
1988 } |
|
1989 else if(command.CompareF(KTEFRunTestStepCommand) == 0 || |
|
1990 command.CompareF(KTEFStartTestBlock) == 0) |
|
1991 { |
|
1992 TInt firstChar; |
|
1993 TPtrC commandStr; |
|
1994 TBool panicStringComplete(ETrue); |
|
1995 while(!lex.Eos()) |
|
1996 { |
|
1997 lex.SkipSpace(); |
|
1998 lex.Mark(); |
|
1999 |
|
2000 TPtrC token = lex.NextToken(); |
|
2001 if( token.Length()>0 ) |
|
2002 { |
|
2003 commandStr.Set( token ); |
|
2004 firstChar = commandStr[0]; |
|
2005 // 33 is the ascii value for "!". Used here for confirming switches |
|
2006 if (firstChar != KTEFAsciiExclamation && panicStringComplete) |
|
2007 { |
|
2008 break; |
|
2009 } |
|
2010 // Check to see if !PanicString TEF parameter contains panic string with spaces |
|
2011 // If so, see if they are enclosed within a open & close braces |
|
2012 if(commandStr.Length() > 14 && |
|
2013 commandStr.Mid(0,14).Compare(_L("!PanicString=\"")) == 0) |
|
2014 panicStringComplete = EFalse; |
|
2015 if(!panicStringComplete && commandStr.Right(1).Compare(KTEFOpenQuotes) == 0) |
|
2016 panicStringComplete = ETrue; |
|
2017 } |
|
2018 } |
|
2019 if (!panicStringComplete) |
|
2020 { |
|
2021 ERR_PRINTF1(KErrInvalidArgumentSet); |
|
2022 return EFalse; |
|
2023 } |
|
2024 } |
|
2025 |
|
2026 // We need to skip the timeout if it's there. |
|
2027 if( command.CompareF(KTEFRunTestStepCommand) == 0 || |
|
2028 command.CompareF(KTEFStartTestBlock) == 0) |
|
2029 lexTimeout=lex.MarkedToken(); |
|
2030 else |
|
2031 lexTimeout=lex.NextToken(); |
|
2032 TInt timeout; |
|
2033 TPtrC serverName; |
|
2034 if(lexTimeout.Val(timeout) != KErrNone) |
|
2035 // No timeout so use the second token |
|
2036 serverName.Set(lex.MarkedToken()); |
|
2037 else |
|
2038 // Timeout value there |
|
2039 serverName.Set(lex.NextToken()); |
|
2040 TInt i=0; |
|
2041 // Loop through the installed servers |
|
2042 TInt count = iServers.Count(); |
|
2043 for(i=0;i<count;i++) |
|
2044 { |
|
2045 if(iServers[i]->ServerName() == serverName) |
|
2046 // Found server installed |
|
2047 break; |
|
2048 } |
|
2049 // Return found or not found |
|
2050 if(i == count) |
|
2051 return EFalse; |
|
2052 else |
|
2053 { |
|
2054 aIndex = i; |
|
2055 if (iServers[i]->SharedData()) |
|
2056 { |
|
2057 iConcurrent = EFalse; |
|
2058 } |
|
2059 return ETrue; |
|
2060 } |
|
2061 } |
|
2062 |
|
2063 /** |
|
2064 * * @return - ETrue if the scriptline is valid, else retuens EFalse |
|
2065 */ |
|
2066 TBool CScriptControl::CheckValidScriptLine() const |
|
2067 { |
|
2068 TLex lex(iCurrentScriptLine); |
|
2069 TPtrC command(lex.NextToken()); |
|
2070 TBool panicCodeSet(EFalse); |
|
2071 TBool panicStringSet(EFalse); |
|
2072 TBool heapValueSet(EFalse); |
|
2073 TBool validScript(ETrue); |
|
2074 TBool oomRequestSet(EFalse); |
|
2075 TBool setupOptionSet(EFalse); |
|
2076 |
|
2077 if(command.CompareF(KTEFRunTestStepCommand) == 0) |
|
2078 { |
|
2079 TInt firstChar; |
|
2080 TPtrC commandStr; |
|
2081 while(!lex.Eos()) |
|
2082 { |
|
2083 lex.SkipSpace(); |
|
2084 commandStr.Set(lex.NextToken()); |
|
2085 firstChar = commandStr[0]; |
|
2086 // 33 is the ascii value for "!". Used here for confirming switches |
|
2087 if (firstChar == KTEFAsciiExclamation) |
|
2088 { |
|
2089 if (commandStr.Length() >= KTEFMinErrorParamLength && commandStr.Mid(0,KTEFMinErrorParamLength).CompareF(KTEFError) == 0) |
|
2090 { |
|
2091 if(command.CompareF(KTEFRunTestStepCommand) == 0) |
|
2092 command.Set(KTEFRunErrorStepResultCommand); |
|
2093 else |
|
2094 validScript = EFalse; |
|
2095 } |
|
2096 else if (commandStr.Length() >= KTEFMinSetupParamLength && commandStr.Mid(0,KTEFMinSetupParamLength).CompareF(KTEFSetUpParam) == 0) |
|
2097 { |
|
2098 if(command.CompareF(KTEFRunTestStepCommand) == 0 && !setupOptionSet) |
|
2099 setupOptionSet = ETrue; |
|
2100 else |
|
2101 validScript = EFalse; |
|
2102 } |
|
2103 else if (commandStr.Length() > KTEFMinResultParamLength && commandStr.Mid(0,KTEFMinResultParamLength).CompareF(KTEFResult) == 0 && commandStr.Mid(KTEFMinResultParamLength).Length() <= KTEFMaxVerdictLength) |
|
2104 { |
|
2105 if (command.CompareF(KTEFRunTestStepCommand) == 0) |
|
2106 command.Set(KTEFRunTestStepResultCommand); |
|
2107 else |
|
2108 validScript = EFalse; |
|
2109 } |
|
2110 else if (commandStr.Length() >= KTEFMinPanicCodeParamLength && commandStr.Mid(0,KTEFMinPanicCodeParamLength).CompareF(KTEFPanicCode) == 0) |
|
2111 { |
|
2112 if ((command.CompareF(KTEFRunTestStepCommand) == 0 || command.CompareF(KTEFRunPanicStepResultCommand) == 0) && !panicCodeSet) |
|
2113 { |
|
2114 command.Set(KTEFRunPanicStepResultCommand); |
|
2115 panicCodeSet=ETrue; |
|
2116 } |
|
2117 else |
|
2118 validScript = EFalse; |
|
2119 } |
|
2120 else if (commandStr.Length() >= KTEFMinPanicStringParamLength && commandStr.Mid(0,KTEFMinPanicStringParamLength).CompareF(KTEFPanicString) == 0) |
|
2121 { |
|
2122 if ((command.CompareF(KTEFRunTestStepCommand) == 0 || command.CompareF(KTEFRunPanicStepResultCommand) == 0) && !panicStringSet) |
|
2123 { |
|
2124 command.Set(KTEFRunPanicStepResultCommand); |
|
2125 panicStringSet = ETrue; |
|
2126 } |
|
2127 else |
|
2128 validScript = EFalse; |
|
2129 } |
|
2130 else |
|
2131 { |
|
2132 if (commandStr.Length() >= KTEFMinHeapParamLength && commandStr.Mid(0,KTEFMinHeapParamLength).CompareF(KTEFHeap) == 0 && !heapValueSet) |
|
2133 heapValueSet = ETrue; |
|
2134 else if (commandStr.Length() >= KTEFMinOomParamLength && commandStr.Mid(0,KTEFMinOomParamLength).CompareF(KTEFOom) == 0 && !oomRequestSet) |
|
2135 oomRequestSet = ETrue; |
|
2136 else |
|
2137 validScript = EFalse; |
|
2138 } |
|
2139 } |
|
2140 else |
|
2141 break; |
|
2142 } |
|
2143 } |
|
2144 return validScript; |
|
2145 } |
|
2146 |
|
2147 /** |
|
2148 * Return the next line in the script file |
|
2149 * @param aScriptLine - return line in the script file minus CRLF |
|
2150 * @return - True if line found, false for end of file. |
|
2151 */ |
|
2152 TBool CScriptControl::GetNextScriptLine(TPtrC& aScriptLine) |
|
2153 { |
|
2154 if(iScriptLex.Eos()) |
|
2155 { |
|
2156 // Fix defect 1193337, check the value is zero or not. If zero, this should be no nested run script |
|
2157 if((0 == iNestedNumRunScriptInLoop) && iLoop) |
|
2158 // End defect 119337 |
|
2159 { |
|
2160 _LIT(KEndRepeatNotFound,"The END_REPEAT command is not found"); |
|
2161 INFO_PRINTF1(KEndRepeatNotFound); |
|
2162 } |
|
2163 |
|
2164 // Fix defect 119337, check if this is still in loop and this run script command is nested |
|
2165 // decrease one shows that the nested number is decreased |
|
2166 else if (iNestedNumRunScriptInLoop > 0 && iLoop) |
|
2167 { |
|
2168 --iNestedNumRunScriptInLoop; |
|
2169 } |
|
2170 // End defect 119337 |
|
2171 |
|
2172 return EFalse; |
|
2173 } |
|
2174 // Mark the current script line to return |
|
2175 iScriptLex.Mark(); |
|
2176 if(iLoop && !iCheckVar) |
|
2177 { |
|
2178 iStoreLoop.Assign(iScriptLex.RemainderFromMark()); |
|
2179 iTempStoreLoop.Assign(iScriptLex.RemainderFromMark()); |
|
2180 iCheckVar=ETrue; |
|
2181 } |
|
2182 // Place the lex marker for the next read |
|
2183 while(!iScriptLex.Eos()) |
|
2184 { |
|
2185 TChar peek = iScriptLex.Peek(); |
|
2186 if(peek == '\n') |
|
2187 { |
|
2188 iScriptLex.Inc(); |
|
2189 iCurrentScriptLineNumber++; |
|
2190 break; |
|
2191 } |
|
2192 else |
|
2193 iScriptLex.Inc(); |
|
2194 } |
|
2195 aScriptLine.Set(iScriptLex.MarkedToken()); |
|
2196 if(aScriptLine.FindF(KTEFRunScriptCommand)!=KErrNotFound && iLoop) |
|
2197 { |
|
2198 // Fix defect 119337, add this integer shows a nested run script added. |
|
2199 ++iNestedNumRunScriptInLoop; |
|
2200 // End Fix defect 119337 |
|
2201 } |
|
2202 if(aScriptLine.Length() || !iScriptLex.Eos()) |
|
2203 return ETrue; |
|
2204 else |
|
2205 return EFalse; |
|
2206 } |
|
2207 |
|
2208 /** |
|
2209 * Return the next line from script file which is to be looped |
|
2210 * @param aScriptLine - return line in the script file which is under loop minus CRLF |
|
2211 * @return -True if line is found else return false |
|
2212 * |
|
2213 * If RUN_SCRIPT command has been encountered return the line from GetNextScriptLine Function |
|
2214 */ |
|
2215 TBool CScriptControl::GetLoopScriptLine(TPtrC& aScriptLine) |
|
2216 { |
|
2217 // Fix defect 119337, check if the run script is nested |
|
2218 if (0 != iNestedNumRunScriptInLoop) |
|
2219 // End defect 119337 |
|
2220 return(GetNextScriptLine(aScriptLine)); |
|
2221 if(iStoreLoop.Eos()) |
|
2222 return EFalse; |
|
2223 iStoreLoop.Mark(); |
|
2224 while(!iStoreLoop.Eos()) |
|
2225 { |
|
2226 TChar peek = iStoreLoop.Peek(); |
|
2227 if(peek == '\n') |
|
2228 { |
|
2229 iStoreLoop.Inc(); |
|
2230 break; |
|
2231 } |
|
2232 else |
|
2233 iStoreLoop.Inc(); |
|
2234 } |
|
2235 aScriptLine.Set(iStoreLoop.MarkedToken()); |
|
2236 if(aScriptLine.Find(KTEFEndRepeat)!=KErrNotFound) |
|
2237 { |
|
2238 iStoreLoop.Assign(iTempStoreLoop); |
|
2239 } |
|
2240 if(aScriptLine.FindF(KTEFRunScriptCommand)!=KErrNotFound) |
|
2241 { |
|
2242 // Fix defect 119337, add this integer shows a nested run script added. |
|
2243 ++iNestedNumRunScriptInLoop; |
|
2244 // End defect 119337 |
|
2245 } |
|
2246 if(aScriptLine.Length() || !iStoreLoop.Eos()) |
|
2247 return ETrue; |
|
2248 else |
|
2249 return EFalse; |
|
2250 } |
|
2251 |
|
2252 /** |
|
2253 * @param aErr - The completion code |
|
2254 * @param aPanicString - Descriptor reference containing the panic string if a test were to panic |
|
2255 * @param aScriptLineNumber - Script line number used for printing result into log file |
|
2256 * @param aCommand - Command name also used for printing result into log file |
|
2257 * Called by a CClientControl or CProgramControl child object |
|
2258 */ |
|
2259 void CScriptControl::TaskCompletion(TInt aErr, const TDesC& aPanicString, TInt aScriptLineNumber,const TDesC& aCommand,TBool aTaskCanComplete,TTEFItemArray* aItemArray) |
|
2260 { |
|
2261 if(aItemArray) |
|
2262 { |
|
2263 TVerdict err = Logger().LogBlock( aItemArray, aScriptLineNumber ); |
|
2264 |
|
2265 // If no error was set on the server side (ie. a panic) then set |
|
2266 // it here with the post processing result |
|
2267 if( EPass == aErr && aPanicString.Length() == 0 ) |
|
2268 { |
|
2269 aErr = err; |
|
2270 } |
|
2271 } |
|
2272 // Log the test step result to the output file |
|
2273 LogResult((TVerdict)aErr, aPanicString, aScriptLineNumber, aCommand); |
|
2274 |
|
2275 if(aErr != KErrNone && aErr != KErrNotSupported && iBreakOnError) |
|
2276 // Put this instance of the script engine into the closing state as we've |
|
2277 // encountered the BREAK_ERROR_ON command. |
|
2278 // KErrNotSupported is considered a benign error |
|
2279 { |
|
2280 iState = EClosing; |
|
2281 } |
|
2282 iAsyncTasksOutstanding--; |
|
2283 // Check the flag first then trigger our own RunL() |
|
2284 if(aTaskCanComplete || iCanComplete) |
|
2285 Complete(aErr); |
|
2286 } |
|
2287 |
|
2288 /** |
|
2289 * Print the current script line to the console |
|
2290 */ |
|
2291 void CScriptControl::PrintCurrentScriptLine() const |
|
2292 { |
|
2293 // Check we don't overflow |
|
2294 TBuf<KMaxTestExecuteLogLineLength> output; |
|
2295 if((iCurrentScriptLine.Length() + iScriptFile.Length() + 4 ) > output.MaxLength()) |
|
2296 { |
|
2297 output.Copy(iAlteredScriptLine); |
|
2298 Logger().PrintCurrentScriptLine(output); |
|
2299 return; |
|
2300 } |
|
2301 // Copy the script filename. Handy for recursion |
|
2302 output.Copy(iScriptFile); |
|
2303 output.Append(KTEFSpace); |
|
2304 // Append the script file line |
|
2305 output.Append(iCurrentScriptLine); |
|
2306 // Write to console |
|
2307 ConsoleLogger().Console().Printf(KTEFStringFormat,&output); |
|
2308 |
|
2309 Logger().PrintCurrentScriptLine(output); |
|
2310 } |
|
2311 |
|
2312 /** |
|
2313 * Checks for commented commands and increments a counter for logging |
|
2314 */ |
|
2315 TBool CScriptControl::CheckCommentedCommands() const |
|
2316 { |
|
2317 if(!iCurrentScriptLine.Length()) |
|
2318 return ETrue; |
|
2319 |
|
2320 TLex lex(iCurrentScriptLine); |
|
2321 TPtrC token(lex.NextToken()); |
|
2322 if (!token.Length()) |
|
2323 return ETrue; |
|
2324 |
|
2325 TInt firstChar = iCurrentScriptLine[0]; |
|
2326 if(firstChar == '/') |
|
2327 { |
|
2328 TInt findRunTestStep; |
|
2329 TInt findRunPanicStep; |
|
2330 TInt findRunScript; |
|
2331 TInt findRunProgram; |
|
2332 TInt findRunWSProgram; |
|
2333 TInt findStartTestBlock; |
|
2334 findRunTestStep=iCurrentScriptLine.Find(KTEFRunTestStepCommand); |
|
2335 findRunScript=iCurrentScriptLine.Find(KTEFRunScriptCommand); |
|
2336 findRunPanicStep=iCurrentScriptLine.Find(KTEFRunPanicStepCommand); |
|
2337 findRunProgram=iCurrentScriptLine.Find(KTEFRunProgramCommand); |
|
2338 findRunWSProgram=iCurrentScriptLine.Find(KTEFRunWSProgramCommand); |
|
2339 findStartTestBlock=iCurrentScriptLine.Find(KTEFStartTestBlock); |
|
2340 if(findRunTestStep>0 || findRunScript>0 || findRunPanicStep>0 || findRunProgram>0 || findRunWSProgram>0 || findStartTestBlock>0 && !iStartLooping) |
|
2341 { |
|
2342 commentedCommandsCount++; |
|
2343 } |
|
2344 } |
|
2345 if(firstChar == '\r' || firstChar == '\n' || firstChar == '#' || firstChar == '/') |
|
2346 return ETrue; |
|
2347 return EFalse; |
|
2348 } |
|
2349 |
|
2350 /** |
|
2351 * @param aResult - Test Step result |
|
2352 * @param aPanicString - Descriptor containing the panic string if test were to panic |
|
2353 * @param aScriptLineNumber - The line in the script file |
|
2354 * @param aCommand - Command name whose result is set for logging |
|
2355 * Log a RUN_TEST_STEP, RUN_PANIC_STEP or RUN_PROGRAM result to file |
|
2356 */ |
|
2357 void CScriptControl::LogResult(TVerdict aResult, const TDesC& aPanicString, TInt aScriptLineNumber,const TDesC& aCommand) |
|
2358 { |
|
2359 // Call the Logger()'s LogResult() routine to manipulate results of RUN_TEST_STEP command/variants |
|
2360 // Also controls the fields for logging both HTML & XML logging |
|
2361 Logger().LogResult(aResult, aPanicString, aScriptLineNumber, aCommand, iScriptFile, RFileFlogger::ESevrHigh); |
|
2362 } |
|
2363 |
|
2364 /** |
|
2365 * Constructor |
|
2366 * @param RTestServ - Reference to a root RTestServer instance |
|
2367 * @param aCommand - Reference to a RUN_TEST_STEP script line |
|
2368 * @param MTaskCompletion - Reference to the parent completion interface |
|
2369 * @param aScriptLineNumber - The line in script file |
|
2370 * @param aLogger - Reference to the Logger class |
|
2371 * @param aLoopIndex - TInt reference that provides the loop index for the test. The value is 0 if not in loop. |
|
2372 * @param aTestCaseID - Descriptor containing the test case id, if test run is within a test case |
|
2373 * @param aScriptFilePath - The path of the script file being executed |
|
2374 * @param aSysDrive - Default system drive letter |
|
2375 * @param aTestSysDrive - System drive letter overwritten from testexecute.ini |
|
2376 */ |
|
2377 CClientControl::CClientControl(RScriptTestServ& aServ,const TDesC& aCommand, MTaskCompletion& aCompletion, TInt aScriptLineNumber, CTestExecuteLogger& aLogger, TInt aLoopIndex, const TDesC& aTestCaseID, TPtrC& aScriptFilePath, const TDriveName& aSysDrive, const TDriveName& aTestSysDrive) |
|
2378 : CTaskControlBase(aCommand,aCompletion,aScriptLineNumber,aLogger) |
|
2379 , iServ(aServ) |
|
2380 , iRetryCount(0) |
|
2381 , iLoopIndex(aLoopIndex) |
|
2382 , iTestCaseID(aTestCaseID) |
|
2383 , iBlockArrayPkg(NULL) |
|
2384 , iBlockArrayPtr(STATIC_CAST(TUint8*,NULL), 0) |
|
2385 , iScriptFilePath(aScriptFilePath) |
|
2386 , iDefaultSysDrive(aSysDrive) |
|
2387 , iTestSysDrive(aTestSysDrive) |
|
2388 { |
|
2389 // Extract the parameters to the test step and store them in the class |
|
2390 GetStepParamsFromStepCommand(); |
|
2391 } |
|
2392 |
|
2393 CClientControl* CClientControl::NewL( RScriptTestServ& aTestServ, |
|
2394 const TDesC& aCommand, |
|
2395 MTaskCompletion& aCompletion, |
|
2396 TInt aScriptLineNumber, |
|
2397 CTestExecuteLogger& aLogger, |
|
2398 TInt aLoopIndex, |
|
2399 const TDesC& aTestCaseID, |
|
2400 const TDesC& aEndBlockCommand, |
|
2401 TPtrC& aScriptFilePath, |
|
2402 const TTEFItemArray& aBlockArray, |
|
2403 const TDriveName& aSysDrive, |
|
2404 const TDriveName& aTestSysDrive) |
|
2405 { |
|
2406 CClientControl* self = new (ELeave) CClientControl( aTestServ, |
|
2407 aCommand, |
|
2408 aCompletion, |
|
2409 aScriptLineNumber, |
|
2410 aLogger, |
|
2411 aLoopIndex, |
|
2412 aTestCaseID, |
|
2413 aScriptFilePath, |
|
2414 aSysDrive, |
|
2415 aTestSysDrive); |
|
2416 CleanupStack::PushL(self); |
|
2417 self->ConstructL(aEndBlockCommand, aBlockArray); |
|
2418 CleanupStack::Pop(); |
|
2419 return self; |
|
2420 } |
|
2421 |
|
2422 void CClientControl::ConstructL( const TDesC& aEndBlockCommand, const TTEFItemArray& aBlockArray ) |
|
2423 { |
|
2424 iEndBlockCommand.Set( aEndBlockCommand ); |
|
2425 TTEFItemPkgBuf itemPckgBuf; |
|
2426 TInt count = aBlockArray.Count(); |
|
2427 iBlockArrayPkg = HBufC8::NewL( count * itemPckgBuf.Size() ); |
|
2428 iBlockArrayPtr.Set( iBlockArrayPkg->Des() ); |
|
2429 for( TInt i=0; i<count; i++ ) |
|
2430 { |
|
2431 itemPckgBuf = aBlockArray.At(i); |
|
2432 iBlockArrayPtr.Append( itemPckgBuf ); |
|
2433 } |
|
2434 } |
|
2435 |
|
2436 TTEFItemArray* CClientControl::CreateBlockArrayLC() |
|
2437 { |
|
2438 TTEFItemPkgBuf itemPckgBuf; |
|
2439 TPtr8 blockArrayPtr(iBlockArrayPkg->Des()); |
|
2440 TInt count = blockArrayPtr.Size()/itemPckgBuf.Size(); |
|
2441 TTEFItemArray* itemArray = new (ELeave) TTEFItemArray( count ); |
|
2442 CleanupStack::PushL( itemArray ); |
|
2443 |
|
2444 TInt pos = 0; |
|
2445 for( TInt i=0; i<count; i++ ) |
|
2446 { |
|
2447 itemPckgBuf.Copy(blockArrayPtr.Mid(pos, itemPckgBuf.Size())); |
|
2448 pos += itemPckgBuf.Size(); |
|
2449 itemArray->AppendL( itemPckgBuf() ); |
|
2450 } |
|
2451 |
|
2452 return itemArray; |
|
2453 } |
|
2454 |
|
2455 /** |
|
2456 * Destructor |
|
2457 */ |
|
2458 CClientControl::~CClientControl() |
|
2459 { |
|
2460 iTimer.Cancel(); |
|
2461 iTimer.Close(); |
|
2462 |
|
2463 if( iBlockArrayPkg ) |
|
2464 { |
|
2465 delete iBlockArrayPkg; |
|
2466 iBlockArrayPkg = NULL; |
|
2467 } |
|
2468 } |
|
2469 const TInt KDisableTimer = -1; |
|
2470 |
|
2471 /** |
|
2472 * Test step has done. log the test result. |
|
2473 */ |
|
2474 void CClientControl::TestStepComplete() |
|
2475 { |
|
2476 iSession.Close(); |
|
2477 if(iBlockArrayPkg) |
|
2478 { |
|
2479 TTEFItemArray *itemArray = CreateBlockArrayLC(); |
|
2480 iParent.TaskCompletion(iStatus.Int(), iTaskExitCategory, iScriptLineNumber, iEndBlockCommand, iTaskCanComplete, itemArray); |
|
2481 CleanupStack::PopAndDestroy(itemArray); |
|
2482 } |
|
2483 else |
|
2484 { |
|
2485 iParent.TaskCompletion(iStatus.Int(), iTaskExitCategory, iScriptLineNumber, iCommandLine, iTaskCanComplete); |
|
2486 } |
|
2487 } |
|
2488 |
|
2489 /** |
|
2490 * Pure virtual |
|
2491 * Test step handling state machine |
|
2492 * Kick'd() into by the parent CScriptControl object. Constructed in the EInit state |
|
2493 */ |
|
2494 void CClientControl::RunL() |
|
2495 { |
|
2496 switch(iState) |
|
2497 { |
|
2498 case EInit : |
|
2499 User::LeaveIfError(iTimer.CreateLocal()); |
|
2500 if(iBlockArrayPkg) |
|
2501 { |
|
2502 User::LeaveIfError(iSession.Open(iServ, EFalse)); |
|
2503 } |
|
2504 else |
|
2505 { |
|
2506 User::LeaveIfError(iSession.Open(iServ, ETrue, iStepName)); |
|
2507 } |
|
2508 // Whilst testing concurrent mode, the OS occasionally completes with |
|
2509 // KErrServerBusy or KErrInUse. |
|
2510 |
|
2511 // clean up retry counter. case ERetry will using. |
|
2512 iRetryCount = 0; |
|
2513 case EServerRetry : |
|
2514 { |
|
2515 SetActive(); |
|
2516 |
|
2517 // Set the heap size for creating the thread heap size |
|
2518 iTaskExitCategory.Copy(iTaskHeapSize); |
|
2519 |
|
2520 TBuf<5> checkOOMArgsBuf; |
|
2521 |
|
2522 // Check if the step args has the OOM arguments already |
|
2523 // A minimum 5 chars expected to check this : "OOM=0" or "OOM=1" |
|
2524 if (iStepArgs.Length() >=5) |
|
2525 { |
|
2526 // Extract the first 5 chars from the start of step args string |
|
2527 checkOOMArgsBuf.Copy(iStepArgs.Mid(0,5)); |
|
2528 } |
|
2529 |
|
2530 _LIT(KOOMOne,"OOM=1"); |
|
2531 _LIT(KOOMZero,"OOM=0"); |
|
2532 |
|
2533 // Set the OOM argument after checking for existence of OOM param already |
|
2534 if ((checkOOMArgsBuf.CompareF(KOOMOne) != KErrNone) && (checkOOMArgsBuf.CompareF(KOOMZero) != KErrNone)) |
|
2535 { |
|
2536 // Insert the OOM arguments to the start of iStepArgs string |
|
2537 if (iOOMRequestSet) // Set OOM=1 if !OOM is used in the RUN_TEST_STEP command |
|
2538 iStepArgs.Insert(0,_L("OOM=1 ")); |
|
2539 else |
|
2540 iStepArgs.Insert(0,_L("OOM=0 ")); |
|
2541 } |
|
2542 |
|
2543 TBuf<KMaxTestExecuteCommandLength> checkSetUpArgsBuf; |
|
2544 |
|
2545 // Check if the step args has the Setup arguments already |
|
2546 // A min of 13 chars expected to check this : "OOM=0 !Setup=" or "OOM=1 !Setup=" |
|
2547 if (iStepArgs.Length() >=13) |
|
2548 { |
|
2549 // Extract 7 chars after skipping the OOM arguments "OOM=0 " or "OOM=1 " |
|
2550 checkSetUpArgsBuf.Copy(iStepArgs.Mid(6,7)); |
|
2551 } |
|
2552 |
|
2553 // Set the !Setup argument after checking for existence !Setup param already |
|
2554 if (checkSetUpArgsBuf.CompareF(KTEFSetUpParam) != KErrNone) |
|
2555 { |
|
2556 // Retain the !Setup value from RUN_TEST_STEP command, if available |
|
2557 if (iSetUpParamValue.Length() == KTEFZeroValue) |
|
2558 { |
|
2559 // If !Setup is not used in RUN_TEST_STEP, set the !Setup to TTestSetupState::ESetupNone (0) |
|
2560 iSetUpParamValue.Copy(KTEFSetUpParam); |
|
2561 iSetUpParamValue.AppendNum(TTestSetupState(ESetupNone)); |
|
2562 } |
|
2563 |
|
2564 // Append a space and also include the loop index |
|
2565 iSetUpParamValue.Append(KTEFSpace); |
|
2566 // The loop index is 0 if the test is not in loop; loop index, otherwise |
|
2567 iSetUpParamValue.AppendNum(iLoopIndex); |
|
2568 iSetUpParamValue.Append(KTEFSpace); |
|
2569 |
|
2570 // Append the TestCaseID along with the Setup params |
|
2571 iSetUpParamValue.Append(iTestCaseID); |
|
2572 iSetUpParamValue.Append(KTEFSpace); |
|
2573 |
|
2574 // Insert the !Setup arguments after the OOM arguments within the iStepArgs |
|
2575 iStepArgs.Insert(6, iSetUpParamValue); |
|
2576 } |
|
2577 |
|
2578 // Call the async client API to run the test step |
|
2579 if(iBlockArrayPkg) |
|
2580 { |
|
2581 iSession.RunTestBlock(iStepArgs,iTaskExitCategory,iBlockArrayPtr,iStatus); |
|
2582 } |
|
2583 else |
|
2584 { |
|
2585 iSession.RunTestStep(iStepArgs,iTaskExitCategory,iStatus); |
|
2586 } |
|
2587 // Start a timer and provide it with our callback MTaskCompletion |
|
2588 iState = ERunning; |
|
2589 // Only start the timer if the disable value is not set |
|
2590 if(iTaskTimeout != KDisableTimer) |
|
2591 { |
|
2592 iTaskTimer = CTaskTimer::NewL(*this); |
|
2593 iTaskTimer->Timeout(iTaskTimeout); |
|
2594 } |
|
2595 } |
|
2596 break; |
|
2597 |
|
2598 case ERunning : |
|
2599 { |
|
2600 // We have been completed but we need to find out the source |
|
2601 // If the timer expires it Aborts the server test step which results in |
|
2602 // the RunTestStep call completing with KErrAbort. |
|
2603 // When the timer expires it calls us back and we delete it then NULL it. |
|
2604 if(iTaskTimer) |
|
2605 { |
|
2606 // The timer did not expire |
|
2607 iTaskTimer->Cancel(); |
|
2608 delete iTaskTimer; |
|
2609 iTaskTimer = NULL; |
|
2610 } |
|
2611 const TInt KRetry10Microseconds = 100000; |
|
2612 const TInt KMaxRetryCount = 20; |
|
2613 if(iStatus.Int() == KErrInUse && iRetryCount < KMaxRetryCount) |
|
2614 { |
|
2615 // OS (not the server) has rejected the call. |
|
2616 // Timed retry |
|
2617 // Noticed this one after panic's in shared data mode |
|
2618 iState = EServerRetry; |
|
2619 // Keep increasing the timeout |
|
2620 iRetryCount++; |
|
2621 SetActive(); |
|
2622 iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrInfo, |
|
2623 _L("Error Message :: The Task Is Retrying ")); |
|
2624 iTimer.After(iStatus,KRetry10Microseconds * iRetryCount); |
|
2625 } |
|
2626 else if(iStatus.Int() == KErrServerBusy) |
|
2627 { |
|
2628 // tempt to do test again when test server return busy. |
|
2629 iState = EServerRetry; |
|
2630 iRetryCount++; |
|
2631 if(iRetryCount < KMaxRetryCount) |
|
2632 { |
|
2633 iState = EServerRetry; |
|
2634 SetActive(); |
|
2635 iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrInfo, |
|
2636 _L("Error Message : Server return -16 = KErrServerBusy : Retrying %d"),iRetryCount); |
|
2637 iTimer.After(iStatus,KRetry10Microseconds ); |
|
2638 } |
|
2639 else//server alwayse busy. stop test. |
|
2640 { |
|
2641 iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrErr, |
|
2642 _L("Error Message : Server Busy Retrying %d times. Test Teminated!"),iRetryCount); |
|
2643 iParent.TaskCompletion(iStatus.Int(),iTaskExitCategory,iScriptLineNumber,iCommandLine,iTaskCanComplete); |
|
2644 |
|
2645 iSession.Close(); |
|
2646 delete this; |
|
2647 } |
|
2648 } |
|
2649 else |
|
2650 { |
|
2651 // see testserverbase.cpp::void SytemWideErrToTefErr(TInt &aErr). converting thi value. |
|
2652 //Check the status, if the status is KErrTestExecuteInUse |
|
2653 //then log the information and change it back to |
|
2654 if(iStatus.Int() == KErrTestExecuteInUse) |
|
2655 { |
|
2656 //Convert the status back to KErrInUse |
|
2657 iStatus=KErrInUse; |
|
2658 } |
|
2659 else if(iStatus.Int() == KErrTestExecuteServerBusy) |
|
2660 { |
|
2661 //this is not server really busy! we should change the server side iStatus back to -16 |
|
2662 //Convert the status back to KErrServerBusy |
|
2663 iStatus = KErrServerBusy; |
|
2664 } |
|
2665 // Step completion |
|
2666 TestStepComplete(); |
|
2667 delete this; |
|
2668 } |
|
2669 } |
|
2670 break; |
|
2671 |
|
2672 default: |
|
2673 break; |
|
2674 } |
|
2675 } |
|
2676 |
|
2677 /** |
|
2678 * @param aError - TInt value representing error returned due to processing request from RunL() |
|
2679 * Handles the leave from RunL() and cleans up the allocated objects |
|
2680 * Also returns KErrNone upon sucessful handling of leave |
|
2681 */ |
|
2682 TInt CClientControl::RunError(TInt aError) |
|
2683 { |
|
2684 if(iBlockArrayPkg) |
|
2685 { |
|
2686 TTEFItemArray* itemArray = CreateBlockArrayLC(); |
|
2687 iParent.TaskCompletion(aError,iTaskExitCategory,iScriptLineNumber,iEndBlockCommand,iTaskCanComplete,itemArray); |
|
2688 CleanupStack::PopAndDestroy( itemArray ); |
|
2689 } |
|
2690 else |
|
2691 { |
|
2692 iParent.TaskCompletion(aError,iTaskExitCategory,iScriptLineNumber,iCommandLine,iTaskCanComplete); |
|
2693 } |
|
2694 delete this; |
|
2695 return KErrNone; |
|
2696 } |
|
2697 |
|
2698 /** |
|
2699 * Extract and save the timeout, step name and test step arguments |
|
2700 */ |
|
2701 void CClientControl::GetStepParamsFromStepCommand() |
|
2702 { |
|
2703 TLex scriptLineLex(iCommandLine); |
|
2704 TPtrC command(scriptLineLex.NextToken()); |
|
2705 if(command.CompareF(KTEFRunTestStepResultCommand) == 0) |
|
2706 scriptLineLex.NextToken(); |
|
2707 else if(command.CompareF(KTEFRunPanicStepResultCommand) == 0) |
|
2708 { |
|
2709 scriptLineLex.NextToken(); |
|
2710 TPtrC panicString(scriptLineLex.NextToken()); |
|
2711 if(panicString.Left(1).Compare(KTEFOpenQuotes) == 0 && panicString.Right(1).Compare(KTEFOpenQuotes) != 0) |
|
2712 { |
|
2713 TBool validCommandLine(EFalse); |
|
2714 while(!scriptLineLex.Eos() && !validCommandLine) |
|
2715 { |
|
2716 panicString.Set(scriptLineLex.NextToken()); |
|
2717 if(panicString.Right(1).Compare(KTEFOpenQuotes) == 0) |
|
2718 validCommandLine = ETrue; |
|
2719 } |
|
2720 } |
|
2721 } |
|
2722 else if(command.CompareF(KTEFRunTestStepCommand) == 0 || |
|
2723 command.CompareF(KTEFStartTestBlock) == 0 ) |
|
2724 { |
|
2725 TInt firstChar; |
|
2726 TPtrC commandStr; |
|
2727 TBool panicStringComplete(ETrue); |
|
2728 while(!scriptLineLex.Eos()) |
|
2729 { |
|
2730 scriptLineLex.SkipSpace(); |
|
2731 scriptLineLex.Mark(); |
|
2732 |
|
2733 TPtrC token = scriptLineLex.NextToken(); |
|
2734 if( token.Length()>0 ) |
|
2735 { |
|
2736 commandStr.Set( token ); |
|
2737 firstChar = commandStr[0]; |
|
2738 // 33 is the ascii value for "!". Used here for confirming switches |
|
2739 if (firstChar != KTEFAsciiExclamation && panicStringComplete) |
|
2740 { |
|
2741 break; |
|
2742 } |
|
2743 if(commandStr.Length() > 14 && |
|
2744 commandStr.Mid(0,14).Compare(_L("!PanicString=\"")) == 0) |
|
2745 panicStringComplete = EFalse; |
|
2746 if(!panicStringComplete && commandStr.Right(1).Compare(KTEFOpenQuotes) == 0) |
|
2747 panicStringComplete = ETrue; |
|
2748 if (commandStr.Length() >= KTEFMinHeapParamLength && commandStr.Mid(0,KTEFMinHeapParamLength).CompareF(KTEFHeap) == 0) |
|
2749 iTaskHeapSize.Set(commandStr.Mid(KTEFMinHeapParamLength)); |
|
2750 else if (commandStr.Length() >= KTEFMinSetupParamLength && commandStr.Mid(0,KTEFMinSetupParamLength).CompareF(KTEFSetUpParam) == 0) |
|
2751 iSetUpParamValue.Copy(commandStr); |
|
2752 else if (commandStr.Length() >= KTEFMinOomParamLength && commandStr.Mid(0,KTEFMinOomParamLength).CompareF(KTEFOom) == 0) |
|
2753 { |
|
2754 // Out of memory cannot be supported for UREL builds due to UHEAP macros |
|
2755 // not being supported in UREL builds |
|
2756 #if defined(_DEBUG) |
|
2757 iOOMRequestSet = ETrue; |
|
2758 #else |
|
2759 iOOMRequestSet = EFalse; |
|
2760 iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrWarn, |
|
2761 _L("Out of Memory Testing is not supported for UREL builds")); |
|
2762 #endif |
|
2763 } |
|
2764 } |
|
2765 } |
|
2766 } |
|
2767 |
|
2768 TLex timeoutLex; |
|
2769 if( command.CompareF(KTEFRunTestStepCommand) == 0 || |
|
2770 command.CompareF(KTEFStartTestBlock) == 0) |
|
2771 timeoutLex = scriptLineLex.MarkedToken(); |
|
2772 else |
|
2773 timeoutLex = scriptLineLex.NextToken(); |
|
2774 TInt err = timeoutLex.Val(iTaskTimeout); |
|
2775 if(err) |
|
2776 { |
|
2777 // No timeout specified |
|
2778 iTaskTimeout = KDefaultTimeoutSeconds; |
|
2779 iStepName.Set(scriptLineLex.NextToken()); |
|
2780 } |
|
2781 else |
|
2782 { |
|
2783 scriptLineLex.NextToken(); |
|
2784 if( command.CompareF(KTEFRunTestStepCommand) == 0 || |
|
2785 command.CompareF(KTEFRunTestStepResultCommand) == 0 || |
|
2786 command.CompareF(KTEFRunPanicStepResultCommand) == 0 || |
|
2787 command.CompareF(KTEFRunPanicStepCommand) == 0|| |
|
2788 command.CompareF(KTEFRunErrorStepResultCommand) == 0) |
|
2789 { |
|
2790 // Save the step name |
|
2791 iStepName.Set(scriptLineLex.NextToken()); |
|
2792 } |
|
2793 } |
|
2794 // The rest is sent to the server |
|
2795 scriptLineLex.SkipSpace(); |
|
2796 iStepArgs.Copy(iScriptFilePath.Mid(0,2)); |
|
2797 iStepArgs.Append(KTEFSpace); |
|
2798 iStepArgs.Append(iDefaultSysDrive); |
|
2799 iStepArgs.Append(KTEFSpace); |
|
2800 iStepArgs.Append(iTestSysDrive); |
|
2801 iStepArgs.Append(KTEFSpace); |
|
2802 iStepArgs.Append(scriptLineLex.Remainder()); |
|
2803 } |
|
2804 |
|
2805 /** |
|
2806 * Callback from a CTaskTimer object |
|
2807 * Abort the test step, NULL the timer so we know that a timeout has caused test step completion |
|
2808 */ |
|
2809 void CClientControl::TaskTimerCompletion() |
|
2810 { |
|
2811 delete iTaskTimer; |
|
2812 iTaskTimer = NULL; |
|
2813 iSession.AbortTestStep(); |
|
2814 } |
|
2815 |
|
2816 /** |
|
2817 * Constructor |
|
2818 * @param aCompletion - Reference to a callback method in the CClientControl parent object |
|
2819 */ |
|
2820 CTaskTimer::CTaskTimer(MTaskTimerCompletion& aCompletion) : CTimer(EPriorityUserInput), iParent(aCompletion) |
|
2821 { |
|
2822 CActiveScheduler::Add(this); |
|
2823 } |
|
2824 |
|
2825 /** |
|
2826 * Iterate till the timer has expired and callback into the parent |
|
2827 */ |
|
2828 void CTaskTimer::RunL() |
|
2829 { |
|
2830 if (iTimesAfter > 0 || iSecondsRemaining > 0) |
|
2831 { |
|
2832 RunTimeout(); // Function call implementing the After() routines |
|
2833 } |
|
2834 else |
|
2835 { |
|
2836 iParent.TaskTimerCompletion(); // Call the completion routine for the timeout |
|
2837 } |
|
2838 } |
|
2839 |
|
2840 /** |
|
2841 * Implements a timeout based using CTimer::After() |
|
2842 * Modified for handling huge timeout values |
|
2843 * @param aSeconds - Timeout value in seconds |
|
2844 */ |
|
2845 void CTaskTimer::Timeout(TInt aSeconds) |
|
2846 { |
|
2847 iTimesAfter = aSeconds/60; // Convert the aSeconds to equivalent minutes |
|
2848 iSecondsRemaining = (aSeconds - (iTimesAfter*60)); // Remainder of seconds after converting to equivalent minutes |
|
2849 RunTimeout(); |
|
2850 } |
|
2851 |
|
2852 /** |
|
2853 * Implements the After() routines for the timeout value specified |
|
2854 * The call is initiated from Timeout() & is iterated from the RunL() |
|
2855 */ |
|
2856 void CTaskTimer::RunTimeout() |
|
2857 { |
|
2858 if (iTimesAfter > 0) |
|
2859 { |
|
2860 After(60*1000000); // Call After() for every minute until iTimesAfter is >0 |
|
2861 iTimesAfter--; |
|
2862 } |
|
2863 else if (iSecondsRemaining > 0) |
|
2864 { |
|
2865 After(iSecondsRemaining*1000000); // Call After() for remainder of microsec |
|
2866 iSecondsRemaining = 0; |
|
2867 } |
|
2868 } |
|
2869 |
|
2870 /** |
|
2871 * Destructor |
|
2872 */ |
|
2873 CTaskTimer::~CTaskTimer() |
|
2874 { |
|
2875 } |
|
2876 |
|
2877 /* |
|
2878 * @param aCompletion - Reference to a callback method in a CTaskControlBase parent object |
|
2879 * Two phase contruction |
|
2880 */ |
|
2881 CTaskTimer* CTaskTimer::NewL(MTaskTimerCompletion& aCompletion) |
|
2882 { |
|
2883 CTaskTimer* taskTimer = new(ELeave) CTaskTimer(aCompletion); |
|
2884 CleanupStack::PushL(taskTimer); |
|
2885 // We have to call the base class second phase constructor |
|
2886 taskTimer->ConstructL(); |
|
2887 CleanupStack::Pop(taskTimer); |
|
2888 return taskTimer; |
|
2889 } |
|
2890 |
|
2891 /** |
|
2892 * @param aCommand - Command for the derived class |
|
2893 * @param aCompletion - Reference to the parent class callback method |
|
2894 * @param aScriptLineNumber - The script file line number of this command |
|
2895 * @param aLogger - Reference to a Flogger derived session |
|
2896 * Constructor - Just initialise the abstract class data |
|
2897 */ |
|
2898 CTaskControlBase::CTaskControlBase(const TDesC& aCommand, MTaskCompletion& aCompletion,TInt aScriptLineNumber, CTestExecuteLogger& aLogger) : |
|
2899 iCommandLine(aCommand), |
|
2900 iParent(aCompletion), |
|
2901 iScriptLineNumber(aScriptLineNumber), |
|
2902 iLogger(aLogger), |
|
2903 iTaskTimer(NULL) |
|
2904 { |
|
2905 } |
|
2906 |
|
2907 /** |
|
2908 * Destructor |
|
2909 */ |
|
2910 CTaskControlBase::~CTaskControlBase() |
|
2911 { |
|
2912 } |
|
2913 |
|
2914 /** |
|
2915 * @param aCommand - Command line for the program (Store in base class) |
|
2916 * @param aCompletion - Reference to the parent class callback method (Store in base class) |
|
2917 * @param aScriptLineNumber - The script file line number of this command (Store in base class) |
|
2918 * @param aLogger - Reference to a Flogger derived session (Store in base class) |
|
2919 * @param aWSProgRun - Boolean value used for identifying window server programs |
|
2920 */ |
|
2921 CProgramControl::CProgramControl(const TDesC& aCommand,MTaskCompletion& aCompletion,TInt aScriptLineNumber, CTestExecuteLogger& aLogger, TBool aWSProgRun) : CTaskControlBase(aCommand,aCompletion,aScriptLineNumber,aLogger), |
|
2922 iState(EInit) |
|
2923 { |
|
2924 // Extract the program arguments from the command line |
|
2925 GetProgramArgsFromCommand(); |
|
2926 |
|
2927 // Try to connect to the window server (if available) |
|
2928 iWSProgRun = aWSProgRun; |
|
2929 #if !defined TEF_LITE |
|
2930 if( iWSProgRun ) |
|
2931 { |
|
2932 iWs.Connect(); |
|
2933 } |
|
2934 #else |
|
2935 // Always set to false if TEF_LITE is set |
|
2936 //iWSProgRun = EFalse; |
|
2937 #endif |
|
2938 } |
|
2939 |
|
2940 /** |
|
2941 * Destructor |
|
2942 */ |
|
2943 CProgramControl::~CProgramControl() |
|
2944 { |
|
2945 #if !defined TEF_LITE |
|
2946 if( iWSProgRun ) |
|
2947 { |
|
2948 iWs.Close(); |
|
2949 } |
|
2950 #endif |
|
2951 } |
|
2952 |
|
2953 /** |
|
2954 * Simple State machine. |
|
2955 * Kick()'d into by parent object. |
|
2956 * Runs an executable in its own process. |
|
2957 */ |
|
2958 void CProgramControl::RunL() |
|
2959 { |
|
2960 switch(iState) |
|
2961 { |
|
2962 case EInit : |
|
2963 { |
|
2964 TRAPD(err,RunProgramL()); |
|
2965 if(err != KErrNone) |
|
2966 { |
|
2967 // Special case where the executable has already completed |
|
2968 if( err == KErrCompletion ) |
|
2969 { |
|
2970 // Reset the error code |
|
2971 err = KErrNone; |
|
2972 } |
|
2973 // Failed so complete immediately |
|
2974 iParent.TaskCompletion(err,iTaskExitCategory,iScriptLineNumber,iCommandLine,iTaskCanComplete); |
|
2975 delete this; |
|
2976 } |
|
2977 else |
|
2978 { |
|
2979 SetActive(); |
|
2980 iState = ERunning; |
|
2981 // Only start the timer if the disable value is not set |
|
2982 if(iTaskTimeout != KDisableTimer) |
|
2983 { |
|
2984 iTaskTimer = CTaskTimer::NewL(*this); |
|
2985 iTaskTimer->Timeout(iTaskTimeout); |
|
2986 } |
|
2987 if (iProgRenamed == 1) |
|
2988 { |
|
2989 iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrInfo, |
|
2990 _L(".EXE not found - .APP run instead")); |
|
2991 } |
|
2992 |
|
2993 } |
|
2994 } |
|
2995 break; |
|
2996 |
|
2997 case ERunning : |
|
2998 { |
|
2999 if(iTaskTimer) |
|
3000 { |
|
3001 // The timer did not expire |
|
3002 iTaskTimer->Cancel(); |
|
3003 delete iTaskTimer; |
|
3004 iTaskTimer = NULL; |
|
3005 } |
|
3006 // Set up the panic string if the program panicked |
|
3007 if( !iWSProgRun ) |
|
3008 { |
|
3009 if(iProgram.ExitType() == EExitPanic) |
|
3010 { |
|
3011 iTaskExitCategory.Copy(KPanicEquals); |
|
3012 iTaskExitCategory.Append(iProgram.ExitCategory()); |
|
3013 } |
|
3014 else if (iProgram.ExitType() == EExitPending) |
|
3015 { |
|
3016 iProgram.Kill(KErrAbort); |
|
3017 iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrWarn, |
|
3018 _L("Program has been killed as the timeout is achieved.")); |
|
3019 } |
|
3020 iProgram.Close(); |
|
3021 } |
|
3022 #if !defined TEF_LITE |
|
3023 else |
|
3024 { |
|
3025 if(iProgramWS.ExitType() == EExitPanic) |
|
3026 { |
|
3027 iTaskExitCategory.Copy(KPanicEquals); |
|
3028 iTaskExitCategory.Append(iProgramWS.ExitCategory()); |
|
3029 } |
|
3030 |
|
3031 // Close the application |
|
3032 TInt prev = 0; |
|
3033 TInt winGid = iWs.FindWindowGroupIdentifier(prev, iProgramWS.Id()); |
|
3034 TApaTask task(iWs); |
|
3035 task.SetWgId(winGid); |
|
3036 if( task.Exists() ) |
|
3037 { |
|
3038 task.KillTask(); |
|
3039 } |
|
3040 iProgramWS.Close(); |
|
3041 } |
|
3042 #endif |
|
3043 |
|
3044 // Complete to the parent object. |
|
3045 iParent.TaskCompletion(iStatus.Int(),iTaskExitCategory,iScriptLineNumber,iCommandLine,iTaskCanComplete); |
|
3046 delete this; |
|
3047 } |
|
3048 break; |
|
3049 |
|
3050 default: |
|
3051 break; |
|
3052 } |
|
3053 } |
|
3054 |
|
3055 /** |
|
3056 * Retrieve the program arguments from the script line. |
|
3057 */ |
|
3058 void CProgramControl::GetProgramArgsFromCommand() |
|
3059 { |
|
3060 TLex scriptLineLex(iCommandLine); |
|
3061 // Skip the RUN_PROGRAM command |
|
3062 scriptLineLex.NextToken(); |
|
3063 TLex lex(scriptLineLex); |
|
3064 // Get the timer if it's been included |
|
3065 TLex timeoutLex(lex.NextToken()); |
|
3066 TInt err = timeoutLex.Val(iTaskTimeout); |
|
3067 if(err) |
|
3068 // No timeout specified |
|
3069 iTaskTimeout = KDefaultTimeoutSeconds; |
|
3070 else |
|
3071 // Skip the timeout value |
|
3072 scriptLineLex.NextToken(); |
|
3073 scriptLineLex.SkipSpace(); |
|
3074 // Use the rest |
|
3075 iProgramArgs.Set(scriptLineLex.Remainder()); |
|
3076 } |
|
3077 |
|
3078 /** |
|
3079 * Task timer expired |
|
3080 */ |
|
3081 void CProgramControl::TaskTimerCompletion() |
|
3082 { |
|
3083 delete iTaskTimer; |
|
3084 iTaskTimer = NULL; |
|
3085 if( !iWSProgRun ) |
|
3086 { |
|
3087 iProgram.RendezvousCancel(iStatus); |
|
3088 } |
|
3089 #if !defined TEF_LITE |
|
3090 else |
|
3091 { |
|
3092 iProgramWS.RendezvousCancel(iStatus); |
|
3093 } |
|
3094 #endif |
|
3095 // We ORPHAN the process |
|
3096 // Our RunL() gets called immediately |
|
3097 // Kill requires KillAnyProcess capability |
|
3098 // ups the stakes as regards CAPABILITY |
|
3099 } |
|
3100 |
|
3101 /** |
|
3102 * Processes RUN_PROGRAM command arguments and starts the program |
|
3103 */ |
|
3104 void CProgramControl::RunProgramL() |
|
3105 { |
|
3106 TLex lex(iProgramArgs); |
|
3107 // Get program name. |
|
3108 lex.Mark(); |
|
3109 lex.NextToken(); |
|
3110 #if !defined TEF_LITE |
|
3111 // Set up the program arguments |
|
3112 TBuf<KMaxTestExecuteCommandLength> programArgs(lex.Remainder()); |
|
3113 programArgs.Trim(); |
|
3114 iProgramArgs.Set(programArgs); |
|
3115 |
|
3116 if( !iWSProgRun ) |
|
3117 { |
|
3118 // Create the Process |
|
3119 User::LeaveIfError(iProgram.Create(lex.MarkedToken(),iProgramArgs)); |
|
3120 } |
|
3121 else |
|
3122 { |
|
3123 if( !IsWindowServerAvailable() ) |
|
3124 { |
|
3125 User::Leave(KErrNotSupported); |
|
3126 } |
|
3127 |
|
3128 // Launch the application using RApaLsSession |
|
3129 // This will only work if there is a window server available. |
|
3130 // It allows TechView apps to be launched |
|
3131 CApaCommandLine *cmd=CApaCommandLine::NewLC(); |
|
3132 cmd->SetExecutableNameL(lex.MarkedToken()); |
|
3133 |
|
3134 // Set the program arguments |
|
3135 cmd->SetDocumentNameL( iProgramArgs ); |
|
3136 cmd->SetCommandL(EApaCommandRun); |
|
3137 |
|
3138 User::LeaveIfError( iApaLsSess.Connect() ); |
|
3139 // startup |
|
3140 TThreadId thread; |
|
3141 User::LeaveIfError( iApaLsSess.StartApp(*cmd, thread) ); |
|
3142 TInt ret = iProgramWS.Open(thread); |
|
3143 if( ret != KErrNone ) |
|
3144 { |
|
3145 if( ret == KErrNotFound ) |
|
3146 { |
|
3147 // If the thread can not be found then it has already completed |
|
3148 // Leave with a relavent error |
|
3149 User::Leave(KErrCompletion); |
|
3150 } |
|
3151 User::Leave(ret); |
|
3152 } |
|
3153 |
|
3154 //cleanup |
|
3155 iApaLsSess.Close(); |
|
3156 CleanupStack::PopAndDestroy(); |
|
3157 } |
|
3158 #else |
|
3159 /** |
|
3160 * Kick off an exe in its own pocess |
|
3161 * completes asynchronously |
|
3162 */ |
|
3163 |
|
3164 if (iWSProgRun) //TEF lite doesn't support RUN_WS_PROGRAM. |
|
3165 { |
|
3166 iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrErr, |
|
3167 _L("Error Message :: TEF lite doesn't support RUN_WS_PROGRAM.")); |
|
3168 User::Leave(EFail); |
|
3169 } |
|
3170 |
|
3171 // Set up the program arguments |
|
3172 TPtrC commandLine(lex.Remainder()); |
|
3173 iProgramArgs.Set(commandLine); |
|
3174 // Create the Process |
|
3175 User::LeaveIfError(iProgram.Create(lex.MarkedToken(),iProgramArgs)); |
|
3176 |
|
3177 #endif |
|
3178 if( !iWSProgRun ) |
|
3179 { |
|
3180 iProgram.Rendezvous(iStatus); |
|
3181 iProgram.Resume(); |
|
3182 } |
|
3183 #if !defined TEF_LITE |
|
3184 else |
|
3185 { |
|
3186 iProgramWS.Rendezvous(iStatus); |
|
3187 } |
|
3188 #endif |
|
3189 } |
|
3190 |
|
3191 /** |
|
3192 * @param aServerName - Test server to connect to |
|
3193 * @param aSharedData - Flag for shared data mode session with test server |
|
3194 * Connect to the test server |
|
3195 * EKA2 version requires a just in time debug flag for the test server process |
|
3196 * This is read from the command line. |
|
3197 * Base class connect acts on this. |
|
3198 */ |
|
3199 TInt RScriptTestServ::Connect(const TDesC& aServerName,TBool aSharedData) |
|
3200 { |
|
3201 iSharedData = aSharedData; |
|
3202 // Parse the command line for -d |
|
3203 TBuf<KMaxTestExecuteCommandLength> commandLine; |
|
3204 if(User::CommandLineLength() > commandLine.MaxLength()) |
|
3205 User::Leave(KErrTooBig); |
|
3206 User::CommandLine(commandLine); |
|
3207 TLex flagLex(commandLine); |
|
3208 // Default to false |
|
3209 TBool aJustInTime(EFalse); |
|
3210 while(!flagLex.Eos()) |
|
3211 { |
|
3212 TPtrC token(flagLex.NextToken()); |
|
3213 if(token == KTestExecuteCommandLineFlagDebugMode) |
|
3214 { |
|
3215 aJustInTime = ETrue; |
|
3216 break; |
|
3217 } |
|
3218 } |
|
3219 return RTestServ::Connect(aServerName,aJustInTime); |
|
3220 |
|
3221 } |
|
3222 |
|
3223 /** |
|
3224 * Copies the integer value read from ini file to the reference integer passed to the function |
|
3225 * @param aConfigData - Pointer to CIniData object used for reading data from ini file |
|
3226 * @param aConfigSection - Descriptor value describing the section name within an ini file for reading |
|
3227 * @param aSharedData - KeyName within a section where the input data is available in ini file |
|
3228 * @param aSharedDataNum - Reference integer variable for collecting the value at the keyname specified |
|
3229 * @Leave system wide errors |
|
3230 */ |
|
3231 void CScriptControl::FindValueL(CIniData* aConfigData, TPtrC aConfigSection, TPtrC aSharedData, TInt& aSharedDataNum) |
|
3232 { |
|
3233 aConfigData->FindVar(aConfigSection, aSharedData, aSharedDataNum); |
|
3234 if (aSharedDataNum == 0) |
|
3235 { |
|
3236 User::Leave(KErrGeneral); |
|
3237 } |
|
3238 } |
|
3239 |
|
3240 /** |
|
3241 * Copies the descriptor value read from ini file to the reference descriptor passed to the function |
|
3242 * @param aConfigData - Pointer to CIniData object used for reading data from ini file |
|
3243 * @param aConfigSection - Descriptor value describing the section name within an ini file for reading |
|
3244 * @param aSharedData - KeyName within a section where the input data is available in ini file |
|
3245 * @param aSharedDataName - Reference descriptor variable for collecting the value at the keyname specified |
|
3246 * @Leave system wide errors |
|
3247 */ |
|
3248 void CScriptControl::FindValueL(CIniData* aConfigData, TPtrC aConfigSection, TPtrC aSharedData, TPtrC& aSharedDataName) |
|
3249 { |
|
3250 User::LeaveIfError(aConfigData->FindVar(aConfigSection, aSharedData, aSharedDataName)); |
|
3251 TPtrC blankString(KNull); |
|
3252 if (aSharedDataName.CompareF(blankString) == 0) |
|
3253 { |
|
3254 User::Leave(KErrGeneral); |
|
3255 } |
|
3256 } |
|
3257 |
|
3258 /** |
|
3259 * Creates one or more shared objects based on the inputs provided in ini file |
|
3260 * @Leave system wide errors |
|
3261 */ |
|
3262 void CScriptControl::CreateSharedObjectsFromScriptLineL() |
|
3263 { |
|
3264 CIniData* configData = NULL; |
|
3265 TInt err = 0; |
|
3266 TInt sharedDataCount = 0; |
|
3267 TPtrC sharedDataName; |
|
3268 |
|
3269 // Sets the boolean to ETrue |
|
3270 // Avoids SHARED_DATA command being called more than once |
|
3271 iIsSharedData = ETrue; |
|
3272 |
|
3273 //It copies the current line from the script to TLex object |
|
3274 TLex shareLex(iCurrentScriptLine); |
|
3275 |
|
3276 //reads the next word |
|
3277 shareLex.NextToken(); |
|
3278 |
|
3279 TPtrC configFile(shareLex.NextToken()); |
|
3280 |
|
3281 TPtrC configSection(shareLex.NextToken()); |
|
3282 |
|
3283 if(configFile.Length()) |
|
3284 { |
|
3285 // Create instance of CIniData for reading ini input |
|
3286 TRAP(err,configData = CIniData::NewL(configFile)); |
|
3287 } |
|
3288 if(err != KErrNone) |
|
3289 { |
|
3290 ERR_PRINTF1(KTEFErrorReadingIni); |
|
3291 User::Leave(err); |
|
3292 } |
|
3293 if(configData) |
|
3294 { |
|
3295 CleanupStack::PushL(configData); |
|
3296 TPtrC sharedDataNumberKey(KTEFSharedDataNum); |
|
3297 // Read the ini file for number of shared objects to be created |
|
3298 // Store the value into variable sharedDataCount |
|
3299 TRAP(err,FindValueL(configData,configSection,sharedDataNumberKey,sharedDataCount)); |
|
3300 if (err != KErrNone) |
|
3301 { |
|
3302 ERR_PRINTF1(KTEFErrNumberOfShareNotInIni); |
|
3303 } |
|
3304 else |
|
3305 { |
|
3306 // If ini input is available for number of shared data |
|
3307 // Run a loop to read individual shared objects name |
|
3308 for (TInt i=1; i<=sharedDataCount; i++) |
|
3309 { |
|
3310 TBuf<20> keyName(KTEFSharedName); |
|
3311 |
|
3312 keyName.AppendNum(i); |
|
3313 |
|
3314 keyName.ZeroTerminate(); |
|
3315 |
|
3316 TPtrC sharedDataNameKey(keyName); |
|
3317 |
|
3318 sharedDataName.Set(KNull); |
|
3319 |
|
3320 // Read ini file for i th object name |
|
3321 TRAP(err,FindValueL(configData,configSection,sharedDataNameKey,sharedDataName)); |
|
3322 if (err != KErrNone) |
|
3323 { |
|
3324 ERR_PRINTF2(KTEFErrShareNameNotInIni,i); |
|
3325 } |
|
3326 else |
|
3327 { |
|
3328 // Number of shared data is limited to the value set in the constant KTEFMaxSharedArraySize |
|
3329 // The constant is defined in ScriptEngine.h which can be extended from there |
|
3330 if (iSharedDataNum < KTEFMaxSharedArraySize) |
|
3331 { |
|
3332 // If ini input is available for i th object name |
|
3333 // Creating template class object for sharing the object |
|
3334 CTestSharedData* sharedObject = NULL; |
|
3335 |
|
3336 CTEFSharedData<CTestSharedData>* sharedData1 = NULL; |
|
3337 TRAP(err,sharedData1 = CTEFSharedData<CTestSharedData>::NewL(sharedObject, KTEFSharedDataSize, sharedDataName)); |
|
3338 if (err != KErrNone) |
|
3339 { |
|
3340 User::Leave(err); |
|
3341 } |
|
3342 else |
|
3343 { |
|
3344 sharedData1->EnterCriticalSection(); |
|
3345 sharedObject->Construct(); |
|
3346 sharedData1->ExitCriticalSection(); |
|
3347 // Adding the template object to an array |
|
3348 iSharedDataArray[iSharedDataNum] = sharedData1; |
|
3349 // Counting the number of objects created |
|
3350 // destructor can destroy the objects based on this count |
|
3351 iSharedDataNum++; |
|
3352 } |
|
3353 } |
|
3354 else |
|
3355 { |
|
3356 WARN_PRINTF1(KTEFMaxNumberOfSharedObjectsReached); |
|
3357 } |
|
3358 } |
|
3359 } |
|
3360 } |
|
3361 // Cleanup CInidata object |
|
3362 CleanupStack::PopAndDestroy(configData); |
|
3363 } |
|
3364 } |
|
3365 |
|
3366 /** |
|
3367 * Parses the test block header |
|
3368 * @Return ETrue if pass ok else EFalse |
|
3369 */ |
|
3370 // Fix defect 118337, check the configuration file exists or not, and set the flag. |
|
3371 TBool CScriptControl::ParseTestBlockHeader() |
|
3372 { |
|
3373 TLex lex(iCurrentScriptLine); |
|
3374 TPtrC token = lex.NextToken(); |
|
3375 TInt paraCount = 1; |
|
3376 const TInt KLeastBlockHeaderParaCount = 4; |
|
3377 _LIT(KLegacySysDrive, "C:"); |
|
3378 _LIT(KDefaultIniFilePath, "\\System\\Data\\"); |
|
3379 |
|
3380 while (!lex.Eos()) |
|
3381 { |
|
3382 token.Set(lex.NextToken()); |
|
3383 lex.SkipSpace(); |
|
3384 ++paraCount; |
|
3385 } |
|
3386 |
|
3387 if (paraCount < KLeastBlockHeaderParaCount) |
|
3388 { |
|
3389 _LIT(KBadError, "Bad error syntax!"); |
|
3390 ERR_PRINTF1(KBadError); |
|
3391 return EFalse; |
|
3392 } |
|
3393 |
|
3394 TFileName defaultIniFilePath(KLegacySysDrive); |
|
3395 defaultIniFilePath.Append(KDefaultIniFilePath); |
|
3396 |
|
3397 iFS.Connect(); |
|
3398 TFindFile fileFind(iFS); |
|
3399 TInt ret = fileFind.FindByDir(token, defaultIniFilePath); |
|
3400 iFS.Close(); |
|
3401 if (KErrNotFound == ret) |
|
3402 { |
|
3403 _LIT(KFileNotFound, "Configuration File %S Not Found!"); |
|
3404 ERR_PRINTF2(KFileNotFound, &token); |
|
3405 return EFalse; |
|
3406 } |
|
3407 return ETrue; |
|
3408 } |
|
3409 // End defect 118337 |
|
3410 |
|
3411 /** |
|
3412 * Parses the test block and populates the iBlockArray |
|
3413 * @Leave system wide errors |
|
3414 */ |
|
3415 void CScriptControl::ParseTestBlockL( TTEFItemArray& aItemArray ) |
|
3416 { |
|
3417 // Iterate through the commands contained within the test block |
|
3418 // and append them to the itemArray. |
|
3419 TPtrC startBlockScriptLine = iCurrentScriptLine; |
|
3420 TInt startBlockLineNumber = iCurrentScriptLineNumber; |
|
3421 |
|
3422 TBool parseResult = ParseTestBlockHeader(); |
|
3423 |
|
3424 FOREVER |
|
3425 { |
|
3426 TTEFBlockItem blockItem; |
|
3427 |
|
3428 // Read in the next script line |
|
3429 TBool scriptLineRes = EFalse; |
|
3430 if( !iStartLooping ) |
|
3431 { |
|
3432 scriptLineRes = GetNextScriptLine(iCurrentScriptLine); |
|
3433 } |
|
3434 else |
|
3435 { |
|
3436 scriptLineRes = GetLoopScriptLine(iCurrentScriptLine); |
|
3437 } |
|
3438 |
|
3439 if( !scriptLineRes ) |
|
3440 { |
|
3441 _LIT( KTEFEoF, "Unexpectedly hit the end of the file" ); |
|
3442 ERR_PRINTF1( KTEFEoF ); |
|
3443 TExitCategoryName blankPanicString; |
|
3444 LogResult(EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine); |
|
3445 User::Leave( KErrEof ); |
|
3446 } |
|
3447 |
|
3448 // Strip off any trailling comment |
|
3449 TInt offset = iCurrentScriptLine.Find(KTEFComment); |
|
3450 if( offset != KErrNotFound ) |
|
3451 { |
|
3452 iCurrentScriptLine.Set( iCurrentScriptLine.Mid(0, offset) ); |
|
3453 } |
|
3454 |
|
3455 TLex lex(iCurrentScriptLine); |
|
3456 TPtrC token(lex.NextToken()); |
|
3457 |
|
3458 // Populate the blockItem with the data required for each command |
|
3459 |
|
3460 // CREATE_OBJECT <object type> <object name section> |
|
3461 if( 0 == token.CompareF(KTEFCreateObject) ) |
|
3462 { |
|
3463 blockItem.iItemType = ETEFCreateObject; |
|
3464 blockItem.iObjectType = lex.NextToken().Left(KTEFMaxNameLength); |
|
3465 blockItem.iSection = lex.NextToken().Left(KTEFMaxNameLength); |
|
3466 } |
|
3467 // RESTORE_OBJECT <object type> <object name section> |
|
3468 else if( 0 == token.CompareF(KTEFRestoreObject) ) |
|
3469 { |
|
3470 blockItem.iItemType = ETEFRestoreObject; |
|
3471 blockItem.iObjectType = lex.NextToken().Left(KTEFMaxNameLength); |
|
3472 blockItem.iSection = lex.NextToken().Left(KTEFMaxNameLength); |
|
3473 } |
|
3474 // COMMAND [Error TEFParameter] <object name section> <function name> [section] |
|
3475 else if( 0 == token.CompareF(KTEFCommand) ) |
|
3476 { |
|
3477 blockItem.iItemType = ETEFCommand; |
|
3478 TPtrC param = lex.NextToken().Left(KTEFMaxNameLength); |
|
3479 |
|
3480 if( param.Length() > 0 ) |
|
3481 { |
|
3482 while( param[0] == KTEFAsciiExclamation ) |
|
3483 { |
|
3484 // This is a TEF Error Parameter |
|
3485 // Extract the type of TEF parameter being read in |
|
3486 if( param.Length() >= KTEFError().Length() && |
|
3487 0 == param.Mid(0,KTEFError().Length()).CompareF(KTEFError) ) |
|
3488 { |
|
3489 TInt start = KTEFError().Length(); |
|
3490 TInt length = param.Length()-start; |
|
3491 TLex errorCodeLex( param.Mid(start, |
|
3492 length )); |
|
3493 |
|
3494 TInt errorCode = 0; |
|
3495 if( errorCodeLex.Val(errorCode) == KErrNone ) |
|
3496 { |
|
3497 blockItem.iExpectedError = errorCode; |
|
3498 } |
|
3499 else |
|
3500 { |
|
3501 _LIT(KBadError,"Bad error syntax."); |
|
3502 ERR_PRINTF1(KBadError); |
|
3503 blockItem.iError = KErrNotSupported; |
|
3504 } |
|
3505 } |
|
3506 else if( param.Length() >= KTEFAsyncError().Length() && |
|
3507 0 == param.Mid(0,KTEFAsyncError().Length()).CompareF(KTEFAsyncError)) |
|
3508 { |
|
3509 TInt start = KTEFAsyncError().Length(); |
|
3510 TInt length = param.Length()-start; |
|
3511 TLex errorCodeLex( param.Mid(start, |
|
3512 length )); |
|
3513 |
|
3514 TInt errorCode = 0; |
|
3515 if( errorCodeLex.Val(errorCode) == KErrNone ) |
|
3516 { |
|
3517 blockItem.iExpectedAsyncError = errorCode; |
|
3518 } |
|
3519 else |
|
3520 { |
|
3521 _LIT(KBadError,"Bad error syntax."); |
|
3522 ERR_PRINTF1(KBadError); |
|
3523 blockItem.iAsyncError = KErrNotSupported; |
|
3524 } |
|
3525 } |
|
3526 else |
|
3527 { |
|
3528 // Unknown TEFParameter |
|
3529 _LIT(KUnknownTEFParam,"Unknown Test Block TEFParameter."); |
|
3530 ERR_PRINTF1(KUnknownTEFParam); |
|
3531 TExitCategoryName blankPanicString; |
|
3532 LogResult(EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine); |
|
3533 User::Leave(KErrNotSupported); |
|
3534 } |
|
3535 |
|
3536 // Read the next token |
|
3537 param.Set( lex.NextToken().Left(KTEFMaxNameLength) ); |
|
3538 } |
|
3539 } |
|
3540 |
|
3541 // Read in the object section name, function name and optional data section |
|
3542 blockItem.iCommand.iObject = param; |
|
3543 blockItem.iCommand.iFunction = lex.NextToken().Left(KTEFMaxNameLength); |
|
3544 blockItem.iSection = lex.NextToken().Left(KTEFMaxNameLength); |
|
3545 } |
|
3546 // STORE <section> |
|
3547 else if( 0 == token.CompareF(KTEFStore) ) |
|
3548 { |
|
3549 blockItem.iItemType = ETEFStore; |
|
3550 blockItem.iSection = lex.NextToken().Left(KTEFMaxNameLength); |
|
3551 } |
|
3552 // OUTSTANDING <poll interval in ms> |
|
3553 else if( 0 == token.CompareF(KTEFOutstanding) ) |
|
3554 { |
|
3555 blockItem.iItemType = ETEFOutstanding; |
|
3556 TLex pollLex( lex.NextToken().Left(KTEFMaxNameLength) ); |
|
3557 TInt poll = 0; |
|
3558 blockItem.iTime = (KErrNone==pollLex.Val(poll)?poll:0); |
|
3559 blockItem.iSection = lex.NextToken().Left(KTEFMaxNameLength); |
|
3560 } |
|
3561 // DELAY <time in ms> |
|
3562 else if( 0 == token.CompareF(KTEFDelay) ) |
|
3563 { |
|
3564 blockItem.iItemType = ETEFDelay; |
|
3565 TLex delayLex( lex.NextToken().Left(KTEFMaxNameLength) ); |
|
3566 TInt delay = 0; |
|
3567 blockItem.iTime = (KErrNone==delayLex.Val(delay)?delay:0); |
|
3568 } |
|
3569 // ASYNC_DELAY <time in ms> |
|
3570 else if( 0 == token.CompareF(KTEFAsyncDelay) ) |
|
3571 { |
|
3572 blockItem.iItemType = ETEFAsyncDelay; |
|
3573 TLex delayLex( lex.NextToken().Left(KTEFMaxNameLength) ); |
|
3574 TInt delay = 0; |
|
3575 blockItem.iTime = (KErrNone==delayLex.Val(delay)?delay:0); |
|
3576 } |
|
3577 // SHARED_ACTIVE_SCHEDULER |
|
3578 else if( 0 == token.CompareF(KTEFSharedActiveScheduler) ) |
|
3579 { |
|
3580 blockItem.iItemType = ETEFSharedActiveScheduler; |
|
3581 } |
|
3582 // STORE_ACTIVE_SCHEDULER |
|
3583 else if( 0 == token.CompareF(KTEFStoreActiveScheduler) ) |
|
3584 { |
|
3585 blockItem.iItemType = ETEFStoreActiveScheduler; |
|
3586 } |
|
3587 // END_TEST_BLOCK [Scheduler Cleanup] |
|
3588 else if( 0 == token.CompareF(KTEFEndTestBlock) ) |
|
3589 { |
|
3590 TExitCategoryName blankPanicString; |
|
3591 if( 0 == aItemArray.Count() ) |
|
3592 { |
|
3593 _LIT( KTEFEmptyBlock, "The Test Block is empty." ); |
|
3594 ERR_PRINTF1( KTEFEmptyBlock ); |
|
3595 LogResult(EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine); |
|
3596 User::Leave(KErrNotFound); |
|
3597 } |
|
3598 else |
|
3599 { |
|
3600 // Hit the end of the test block and the package is ready |
|
3601 // Fix defect 118337, check parse result, and print corresponding message. |
|
3602 LogResult(parseResult?EPass:EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine); |
|
3603 //End defect 118337 |
|
3604 break; |
|
3605 } |
|
3606 } |
|
3607 else if( 0 == token.CompareF(KTEFStartTestBlock) ) |
|
3608 { |
|
3609 // Error - there was no end test block command |
|
3610 _LIT(KMissingEnd,"Missing END_TEST_BLOCK command."); |
|
3611 ERR_PRINTF1(KMissingEnd); |
|
3612 TExitCategoryName blankPanicString; |
|
3613 LogResult(EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine); |
|
3614 User::Leave(KErrNotFound); |
|
3615 } |
|
3616 else |
|
3617 { |
|
3618 if( token.Length() > 0 ) |
|
3619 { |
|
3620 if( 0 != token.Left(2).Compare(KTEFComment) ) |
|
3621 { |
|
3622 // The SART_TEST_BLOCK command failed |
|
3623 _LIT(KUnknownCmd,"Unknown Test Block command."); |
|
3624 ERR_PRINTF1(KUnknownCmd); |
|
3625 TExitCategoryName blankPanicString; |
|
3626 LogResult(EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine); |
|
3627 |
|
3628 // Special case for END_TESTCASE commands |
|
3629 // If one has been hit here because an END_TEST_BLOCK command was missing |
|
3630 // the we must log its completion. |
|
3631 if( token.CompareF(KTEFEndTestCaseCommand) == 0 || token.CompareF(KTEFEndSyncTestCaseCommand) == 0 ) |
|
3632 { |
|
3633 LogTestCaseMarkerL(); |
|
3634 } |
|
3635 User::Leave(KErrNotSupported); |
|
3636 } |
|
3637 } |
|
3638 } |
|
3639 |
|
3640 // Append the blockItem to the package |
|
3641 if( ETEFNull != blockItem.iItemType ) |
|
3642 { |
|
3643 aItemArray.AppendL( blockItem ); |
|
3644 } |
|
3645 } |
|
3646 } |
|
3647 |
|
3648 |
|
3649 _LIT( KTEFSyncStatus, "TEFStatus" ); |
|
3650 _LIT( KTEFSyncResult, "TEFResult" ); |
|
3651 const TInt KDelay = 3000000; |
|
3652 const TInt KRetryCount = 10; |
|
3653 |
|
3654 enum TSyncStatus |
|
3655 { |
|
3656 ETEFSyncUnknown = 0, |
|
3657 ETEFSyncRunning = 1, |
|
3658 ETEFSyncComplete = 2, |
|
3659 ETEFSyncWaiting = 3, |
|
3660 ETEFSyncContinue = 4, |
|
3661 ETEFRetrieveResult = 5 |
|
3662 }; |
|
3663 |
|
3664 /** |
|
3665 * Constructor |
|
3666 */ |
|
3667 CSyncControl::CSyncControl() |
|
3668 : iSharedTEFStatus(NULL), iSharedTEFResult(NULL) |
|
3669 { |
|
3670 } |
|
3671 /** |
|
3672 * Destructor |
|
3673 */ |
|
3674 CSyncControl::~CSyncControl() |
|
3675 { |
|
3676 if( iSharedTEFResult && iSharedTEFStatus ) |
|
3677 { |
|
3678 // Don't cleanup until the status is correct |
|
3679 // This will allow time for any retrieve result calls to get through before TEF exits |
|
3680 // Will retry for 30 seconds |
|
3681 CTestSharedData* tefStatus = iSharedTEFStatus->Ptr(); |
|
3682 if( tefStatus != NULL ) |
|
3683 { |
|
3684 TInt64 status = ETEFRetrieveResult; |
|
3685 TInt count = 0; |
|
3686 while( status == ETEFRetrieveResult && count < KRetryCount ) |
|
3687 { |
|
3688 iSharedTEFStatus->EnterCriticalSection(); |
|
3689 HBufC* statusBuffer = NULL; |
|
3690 TRAPD( err, statusBuffer = HBufC::NewL(tefStatus->TextLength()) ); |
|
3691 if( err == KErrNone ) |
|
3692 { |
|
3693 TPtr statusPtr( statusBuffer->Des() ); |
|
3694 tefStatus->GetText( statusPtr ); |
|
3695 TLex lex(statusPtr); |
|
3696 lex.Val(status); |
|
3697 delete statusBuffer; |
|
3698 } |
|
3699 iSharedTEFStatus->ExitCriticalSection(); |
|
3700 |
|
3701 // Don't deley for the first i |
|
3702 if( count > 0 ) |
|
3703 { |
|
3704 User::After( KDelay ); |
|
3705 } |
|
3706 count++; |
|
3707 } |
|
3708 } |
|
3709 delete iSharedTEFResult; |
|
3710 delete iSharedTEFStatus; |
|
3711 } |
|
3712 } |
|
3713 |
|
3714 /** |
|
3715 * Two phase construction |
|
3716 */ |
|
3717 CSyncControl* CSyncControl::NewL() |
|
3718 { |
|
3719 CSyncControl* self = CSyncControl::NewLC(); |
|
3720 CleanupStack::Pop(); |
|
3721 return self; |
|
3722 } |
|
3723 |
|
3724 /** |
|
3725 * Two phase construction |
|
3726 */ |
|
3727 CSyncControl* CSyncControl::NewLC() |
|
3728 { |
|
3729 CSyncControl* self = new (ELeave) CSyncControl(); |
|
3730 CleanupStack::PushL(self); |
|
3731 self->ConstructL(); |
|
3732 return self; |
|
3733 } |
|
3734 |
|
3735 /** |
|
3736 * ConstructL |
|
3737 */ |
|
3738 void CSyncControl::ConstructL() |
|
3739 { |
|
3740 // Initialise the sync status shared data |
|
3741 CTestSharedData* tefStatus = NULL; |
|
3742 iSharedTEFStatus = CTEFSharedData<CTestSharedData>::NewL( tefStatus, |
|
3743 KMaxSharedDataLength, |
|
3744 KTEFSyncStatus ); |
|
3745 iSharedTEFStatus->EnterCriticalSection(); |
|
3746 tefStatus->Construct(); |
|
3747 HBufC* statusBuffer = NULL; |
|
3748 TRAPD( err, statusBuffer = HBufC::NewL(sizeof(TInt64)) ); |
|
3749 if( err != KErrNone ) |
|
3750 { |
|
3751 iSharedTEFStatus->ExitCriticalSection(); |
|
3752 User::Leave( err ); |
|
3753 } |
|
3754 TPtr statusPtr( statusBuffer->Des() ); |
|
3755 statusPtr.Num( ETEFSyncWaiting ); |
|
3756 tefStatus->SetText( statusPtr ); |
|
3757 delete statusBuffer; |
|
3758 iSharedTEFStatus->ExitCriticalSection(); |
|
3759 |
|
3760 // Initialise the sync result shared data |
|
3761 CTestSharedData* tefResult = NULL; |
|
3762 iSharedTEFResult = CTEFSharedData<CTestSharedData>::NewL( tefResult, |
|
3763 KMaxSharedDataLength, |
|
3764 KTEFSyncResult ); |
|
3765 iSharedTEFResult->EnterCriticalSection(); |
|
3766 tefResult->Construct(); |
|
3767 HBufC* resBuffer = NULL; |
|
3768 TRAP( err, resBuffer = HBufC::NewL(sizeof(TInt64)) ); |
|
3769 if( err != KErrNone ) |
|
3770 { |
|
3771 iSharedTEFResult->ExitCriticalSection(); |
|
3772 User::Leave( err ); |
|
3773 } |
|
3774 TPtr resPtr( resBuffer->Des() ); |
|
3775 resPtr.Num( EInconclusive ); |
|
3776 tefResult->SetText( resPtr ); |
|
3777 delete resBuffer; |
|
3778 iSharedTEFResult->ExitCriticalSection(); |
|
3779 } |
|
3780 |
|
3781 /** |
|
3782 * @param aError - Error value resulting from synchronised testcase for logging |
|
3783 * Sets the result obtained from synchronised testcase for logging |
|
3784 */ |
|
3785 void CSyncControl::SetResultL( TVerdict aError ) |
|
3786 { |
|
3787 // Retrieve the status and result shared data pointers |
|
3788 CTestSharedData* tefResult = iSharedTEFResult->Ptr(); |
|
3789 CTestSharedData* tefStatus = iSharedTEFStatus->Ptr(); |
|
3790 |
|
3791 if( tefResult != NULL && tefStatus != NULL ) |
|
3792 { |
|
3793 // Update the shared sync test case result code |
|
3794 iSharedTEFResult->EnterCriticalSection(); |
|
3795 HBufC* resBuffer = NULL; |
|
3796 TRAPD( err, resBuffer = HBufC::NewL(sizeof(TInt64)) ); |
|
3797 if( err != KErrNone ) |
|
3798 { |
|
3799 iSharedTEFResult->ExitCriticalSection(); |
|
3800 User::Leave( err ); |
|
3801 } |
|
3802 TPtr resPtr( resBuffer->Des() ); |
|
3803 resPtr.Num( (TInt64)aError ); |
|
3804 tefResult->SetText( resPtr ); |
|
3805 delete resBuffer; |
|
3806 |
|
3807 iSharedTEFResult->ExitCriticalSection(); |
|
3808 |
|
3809 // So now the test has complete and the result has been updated |
|
3810 // we need to update the status to reflect this |
|
3811 iSharedTEFStatus->EnterCriticalSection(); |
|
3812 HBufC* statusBuffer = NULL; |
|
3813 TRAP( err, statusBuffer = HBufC::NewL(sizeof(TInt64)) ); |
|
3814 if( err != KErrNone ) |
|
3815 { |
|
3816 iSharedTEFStatus->ExitCriticalSection(); |
|
3817 User::Leave( err ); |
|
3818 } |
|
3819 TPtr statusPtr( statusBuffer->Des() ); |
|
3820 statusPtr.Num( ETEFRetrieveResult ); |
|
3821 tefStatus->SetText( statusPtr ); |
|
3822 delete statusBuffer; |
|
3823 |
|
3824 iSharedTEFStatus->ExitCriticalSection(); |
|
3825 } |
|
3826 else |
|
3827 { |
|
3828 User::Leave( KErrNotFound ); |
|
3829 } |
|
3830 } |
|
3831 |
|
3832 /** |
|
3833 * Identifies state of synchronised testcases and continues with the test or completes the tests |
|
3834 */ |
|
3835 TBool CSyncControl::TestCaseContinueL() |
|
3836 { |
|
3837 TBool tefContinue = EFalse; |
|
3838 |
|
3839 // Retrieve the status and result shared data pointers |
|
3840 CTestSharedData* tefStatus = iSharedTEFStatus->Ptr(); |
|
3841 CTestSharedData* tefResult = iSharedTEFResult->Ptr(); |
|
3842 |
|
3843 if( tefStatus != NULL && tefResult != NULL ) |
|
3844 { |
|
3845 iSharedTEFStatus->EnterCriticalSection(); |
|
3846 |
|
3847 // Retrieve the current status |
|
3848 HBufC* statusBuffer = NULL; |
|
3849 TRAPD( err, statusBuffer = HBufC::NewL(tefStatus->TextLength()) ); |
|
3850 if( err != KErrNone ) |
|
3851 { |
|
3852 iSharedTEFStatus->ExitCriticalSection(); |
|
3853 User::Leave( err ); |
|
3854 } |
|
3855 |
|
3856 TPtr statusPtr( statusBuffer->Des() ); |
|
3857 tefStatus->GetText( statusPtr ); |
|
3858 TLex lex(statusPtr); |
|
3859 TInt64 status = ETEFSyncUnknown; |
|
3860 User::LeaveIfError( lex.Val(status) ); |
|
3861 |
|
3862 if( status == ETEFSyncContinue ) |
|
3863 { |
|
3864 tefContinue = ETrue; |
|
3865 // Update the status to running |
|
3866 HBufC* buffer = NULL; |
|
3867 TRAP( err, buffer = HBufC::NewL(sizeof(TInt64)) ); |
|
3868 if( err != KErrNone ) |
|
3869 { |
|
3870 delete statusBuffer; |
|
3871 iSharedTEFStatus->ExitCriticalSection(); |
|
3872 User::Leave( err ); |
|
3873 } |
|
3874 |
|
3875 TPtr ptr( buffer->Des() ); |
|
3876 ptr.Num( ETEFSyncRunning ); |
|
3877 tefStatus->SetText( ptr ); |
|
3878 delete buffer; |
|
3879 } |
|
3880 else if( status == ETEFSyncComplete ) |
|
3881 { |
|
3882 // Previous test has completed and a new sync block has been hit |
|
3883 // Update the status to waiting |
|
3884 HBufC* buffer = NULL; |
|
3885 TRAP( err, buffer = HBufC::NewL(sizeof(TInt64)) ); |
|
3886 if( err != KErrNone ) |
|
3887 { |
|
3888 delete statusBuffer; |
|
3889 iSharedTEFStatus->ExitCriticalSection(); |
|
3890 User::Leave( err ); |
|
3891 } |
|
3892 |
|
3893 TPtr ptr( buffer->Des() ); |
|
3894 ptr.Num( ETEFSyncWaiting ); |
|
3895 tefStatus->SetText( ptr ); |
|
3896 delete buffer; |
|
3897 } |
|
3898 delete statusBuffer; |
|
3899 iSharedTEFStatus->ExitCriticalSection(); |
|
3900 } |
|
3901 else |
|
3902 { |
|
3903 User::Leave( KErrNotFound ); |
|
3904 } |
|
3905 return tefContinue; |
|
3906 } |
|
3907 |
|
3908 /** |
|
3909 * Takes in a script line updates any relative file paths into corresponding absolute path based on the current script file path |
|
3910 * @param aScriptLineString - Pointer descriptor containing a particular script line for updation |
|
3911 */ |
|
3912 void CScriptControl::MakeAbsoluteFilePathsL(TPtrC16& aScriptLineString) |
|
3913 { |
|
3914 TLex lex(aScriptLineString); |
|
3915 iAlteredScriptLine.Zero(); // Initialise the altered script line to zero b4 we start processing |
|
3916 TBuf<KMaxTestExecuteCommandLength> commandName; // To store the command name, basically first token of each script line |
|
3917 TBuf<KMaxTestExecuteCommandLength> commandString; // To store individual tokens of script line for processing |
|
3918 TBuf<KMaxTestExecuteCommandLength> prevCommandString; |
|
3919 const TInt KTEFMinFileExtnSizeIni = 4; |
|
3920 const TInt KTEFMinFileExtnSizeScript = 7; |
|
3921 |
|
3922 while(!lex.Eos()) // start a loop for each token until end of the script line |
|
3923 { |
|
3924 lex.NextToken(); |
|
3925 lex.SkipSpace(); |
|
3926 if (lex.MarkedToken().Length() > KMaxTestExecuteCommandLength) |
|
3927 { |
|
3928 User::Leave(KErrTooBig); |
|
3929 } |
|
3930 |
|
3931 commandString.Copy(lex.MarkedToken()); |
|
3932 lex.Mark(); |
|
3933 |
|
3934 if (commandName.CompareF(KTEFRunScriptCommand) == 0 && |
|
3935 commandString.CompareF(KTEFNull) != 0) |
|
3936 { |
|
3937 // if the command name is RUN_SCRIPT, then check the parameter is not not null and has valid .script extn |
|
3938 // We append .script extn if the length of the token is less than 7 (.script -> Length) |
|
3939 // Or when the token does not end with .script enxtn |
|
3940 if(commandString.Length() < KTEFMinFileExtnSizeScript || |
|
3941 commandString.Right(KTEFMinFileExtnSizeScript).CompareF(KTEFScriptExtension) != 0) |
|
3942 { |
|
3943 commandString.Append(KTEFScriptExtension); |
|
3944 } |
|
3945 } |
|
3946 |
|
3947 // Expand recognised variables into their values |
|
3948 // At the moment just ${SYSDRIVE} -> GetSystemDrive() |
|
3949 ExpandVariables(commandString); |
|
3950 |
|
3951 // we consider eligible path if the token is an argument for RUN_SCRIPT |
|
3952 // or any INI file or an argument for RUN_UTILS command |
|
3953 // Check to see if the token contains a ":" as second character represeting a drive letter |
|
3954 if (commandString.Length() >= KTEFMinFileExtnSizeIni && |
|
3955 commandString.Mid(1,1).CompareF(KTEFColon) != 0) |
|
3956 { |
|
3957 // if the ":" is not found, we process converting relative -> absolute path |
|
3958 // Provided the token ends with .script or .ini extns |
|
3959 if ((commandString.Length() >= KTEFMinFileExtnSizeScript && |
|
3960 commandString.Right(KTEFMinFileExtnSizeScript).CompareF(KTEFScriptExtension) == 0) || |
|
3961 (commandString.Length() >= KTEFMinFileExtnSizeIni && |
|
3962 commandString.Right(KTEFMinFileExtnSizeIni).CompareF(KTEFIniExtension) == 0)) |
|
3963 { |
|
3964 // token does not does not have a ':' but is a eligible path, |
|
3965 // so, convert relative path to absolute path |
|
3966 TRAPD(err, ConvertRelativeToAbsoluteL(commandString)); |
|
3967 if(err != KErrNone) |
|
3968 { |
|
3969 // Leave here since we have got an invalid path |
|
3970 User::Leave(err); |
|
3971 } |
|
3972 } |
|
3973 else if(commandName.CompareF(KTEFRunUtilsCommand) == 0 && |
|
3974 (prevCommandString.CompareF(KTEFRunUtilsCopyFile) == 0 || |
|
3975 prevCommandString.CompareF(KTEFRunUtilsMkDir) == 0 || |
|
3976 prevCommandString.CompareF(KTEFRunUtilsDeleteFile) == 0 || |
|
3977 prevCommandString.CompareF(KTEFRunUtilsDelete) == 0 || |
|
3978 prevCommandString.CompareF(KTEFRunUtilsMakeReadWrite) == 0 || |
|
3979 prevCommandString.CompareF(KTEFDeleteDirectory) == 0)) |
|
3980 { |
|
3981 // token does not does not have a ':' but is a eligible path, |
|
3982 // so, convert relative path to absolute path |
|
3983 TRAPD(err, ConvertRelativeToAbsoluteL(commandString)); |
|
3984 if(err != KErrNone) |
|
3985 { |
|
3986 // Leave here since we have got an invalid path |
|
3987 User::Leave(err); |
|
3988 } |
|
3989 } |
|
3990 } |
|
3991 //start defect 120600 |
|
3992 //remove the code which append an extra space. |
|
3993 // if (iAlteredScriptLine.Length()) |
|
3994 //end defect 120600 |
|
3995 if (iAlteredScriptLine.Length() == 0) |
|
3996 { |
|
3997 // While completng the processing for the first token in the script line, |
|
3998 // we record the token as command name, so that we can use it to identify |
|
3999 // eligible paths in the following loop cycles for the script line |
|
4000 commandName.Copy(commandString); |
|
4001 } |
|
4002 prevCommandString.Copy(commandString); |
|
4003 // Construct the altered script line with individual verified tokens of script line |
|
4004 if(iAlteredScriptLine.Length() + commandString.Length() <= iAlteredScriptLine.MaxLength() ) |
|
4005 { |
|
4006 iAlteredScriptLine.Append(commandString); |
|
4007 } |
|
4008 else// this scipte too long buffer not long enought |
|
4009 { |
|
4010 User::Leave(KErrTooBig); |
|
4011 } |
|
4012 } |
|
4013 // At the end of the while loop, we are ready with new processed script line |
|
4014 // which we shall update it with the original reference taken in |
|
4015 aScriptLineString.Set(iAlteredScriptLine); |
|
4016 } |
|
4017 |
|
4018 /** |
|
4019 * Takes in lex token and updates any relative file paths into corresponding absolute path based on the current script file path |
|
4020 * @param aCommandString - Pointer descriptor containing a particular token within a script line for updation |
|
4021 */ |
|
4022 void CScriptControl::ConvertRelativeToAbsoluteL(TDes& aCommandString) |
|
4023 { |
|
4024 TInt offset = 0; |
|
4025 TInt posOfLastSlash=iScriptFile.LocateReverse('\\') ; |
|
4026 TBuf<KMaxTestExecuteCommandLength> tempStore(iScriptFile.Mid(0,posOfLastSlash)); // Initial script file path |
|
4027 |
|
4028 if(aCommandString.FindC(KTEFOneUp) >= 0) |
|
4029 { |
|
4030 while(aCommandString.FindC(KTEFOneUp) >= 0) |
|
4031 { |
|
4032 offset = aCommandString.FindC(KTEFOneUp); |
|
4033 posOfLastSlash=tempStore.LocateReverse('\\') ; |
|
4034 if (posOfLastSlash <= 0) |
|
4035 { |
|
4036 User::Leave(KTEFErrInvalidRelPath); |
|
4037 } |
|
4038 tempStore.Copy(iScriptFile.Mid(0,posOfLastSlash));// script file path |
|
4039 aCommandString.Copy(aCommandString.Mid(offset + 3)); // 3 for ..'\\' |
|
4040 } |
|
4041 |
|
4042 tempStore.Append('\\'); |
|
4043 } |
|
4044 else if (aCommandString.FindC(KTEFDotSlash) >= 0) |
|
4045 { |
|
4046 offset = aCommandString.FindC(KTEFDotSlash); |
|
4047 aCommandString.Copy(aCommandString.Mid(offset + 1)); |
|
4048 } |
|
4049 else if(aCommandString.Locate('\\') == 0) |
|
4050 { |
|
4051 tempStore.Copy(iScriptFile.Mid(0,2)); // Example: c: |
|
4052 } |
|
4053 else |
|
4054 { |
|
4055 tempStore.Append('\\'); |
|
4056 } |
|
4057 |
|
4058 tempStore.Append(aCommandString); |
|
4059 aCommandString.Copy(tempStore); |
|
4060 } |
|
4061 |
|
4062 /** |
|
4063 * Expand recognised variables in script file into their corresponding value |
|
4064 * Currently supported variable is ${SYSDRIVE} -> GetSystemDrive() / Drive letter set from testexecute.ini |
|
4065 * @param aCommandString - Descriptor containing a particular token within a script line for updation |
|
4066 */ |
|
4067 void CScriptControl::ExpandVariables(TDes& aCommandString) |
|
4068 { |
|
4069 TInt offset = 0; |
|
4070 if (aCommandString.FindC(KTEFSysDrive) >= 0) |
|
4071 { |
|
4072 // If we find ${SYSDRIVE} in the token, replace it with the drive letter to be substitued |
|
4073 offset = aCommandString.FindC(KTEFSysDrive); |
|
4074 aCommandString.Replace(offset, 11, iTestSysDrive); |
|
4075 } |
|
4076 } |