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